Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/tsc-pretscheck-prescript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@rrlab/cli": patch
---

Honor `pretscheck` as the primary pre-script alias for `rr tsc`.

Now that the typecheck task is canonically named `tscheck` (#240), a package's `pretscheck` script runs before the type check, taking precedence over the legacy `pretsc` and `pretypecheck` aliases (which still work as fallbacks).
4 changes: 2 additions & 2 deletions run-run/cli/src/actions/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ export type TscActionConfig = {

type Scripts = Record<string, string | undefined> | undefined;

const getPreScript = (scripts: Scripts) => scripts?.pretsc ?? scripts?.pretypecheck;
const getPreScript = (scripts: Scripts) => scripts?.pretscheck ?? scripts?.pretsc ?? scripts?.pretypecheck;

export async function tscAction({ ctx, tsc }: TscActionConfig): Promise<void> {
const { appPkg, shell } = ctx;

const isTsProject = (dir: string) => appPkg.hasFile("tsconfig.json", dir);

// A package's `pretsc`/`pretypecheck` runs captured, inside the task, so its
// A package's `pretscheck`/`pretsc`/`pretypecheck` runs captured, inside the task, so its
// output stays grouped with that package. It may use shell features, so it
// goes through `/bin/sh -c`. A failing pre-script fails the task before tsc.
const typecheckTask = (label: string, dir: string, scripts: Scripts): BoardTask =>
Expand Down
2 changes: 1 addition & 1 deletion run-run/cli/test/integration/only.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe("plugin { only } narrowing", () => {
// output: either its `N warnings and M errors` summary or the `tsgolint`
// type-checker it shells out to — both are oxlint-exclusive markers.
expect(combined).toMatch(/\d+ warnings? and \d+ errors?|tsgolint/i);
}, 15_000);
});

test("rr jsc composes biome's lint+format (biome's direct jsc was narrowed away)", () => {
const r = cli("jsc", { cwd: fixture.dir });
Expand Down
42 changes: 42 additions & 0 deletions run-run/cli/test/integration/tsc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,46 @@ describe("rr tsc", () => {
expect(r.stdout + r.stderr).toMatch(/Type 'string' is not assignable to type 'number'/);
});
});

describe("pre-script", () => {
const pkgWithScripts = (scripts: Record<string, string>) =>
`${JSON.stringify({ name: "rr-test-fixture", version: "0.0.0", private: true, scripts }, null, 2)}\n`;

test("runs `pretscheck` before tsc and fails the task when it fails", () => {
fixture = makeFixture("tsc-pretscheck", {
"package.json": pkgWithScripts({ pretscheck: "echo MARK_TSCHECK && exit 1" }),
"run-run.config.mts": fixtures.config(["ts"]),
"tsconfig.json": fixtures.tsconfig(),
"src/ok.ts": "export const ok: number = 1;\n",
});

const r = cli("tsc", { cwd: fixture.dir });
const combined = r.stdout + r.stderr;
expect(r.status).not.toBe(0);
// The task fails on the pre-script, before tsc runs; its captured output is surfaced.
expect(combined).toContain("pre-script");
expect(combined).toContain("MARK_TSCHECK");
});

test("prefers `pretscheck` over the legacy `pretsc`/`pretypecheck` aliases", () => {
fixture = makeFixture("tsc-pretscheck-precedence", {
"package.json": pkgWithScripts({
pretscheck: "echo MARK_TSCHECK && exit 1",
pretsc: "echo MARK_LEGACY_TSC && exit 0",
pretypecheck: "echo MARK_LEGACY_TYPECHECK && exit 0",
}),
"run-run.config.mts": fixtures.config(["ts"]),
"tsconfig.json": fixtures.tsconfig(),
"src/ok.ts": "export const ok: number = 1;\n",
});

const r = cli("tsc", { cwd: fixture.dir });
const combined = r.stdout + r.stderr;
// Only `pretscheck` runs: it fails the task and the legacy aliases never fire.
expect(r.status).not.toBe(0);
expect(combined).toContain("MARK_TSCHECK");
expect(combined).not.toContain("MARK_LEGACY_TSC");
expect(combined).not.toContain("MARK_LEGACY_TYPECHECK");
});
});
});
2 changes: 2 additions & 0 deletions run-run/cli/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default defineConfig({
test: {
name: "integration",
include: ["./test/integration/**/*.test.ts"],
testTimeout: 30_000,
hookTimeout: 30_000,
},
},
],
Expand Down
Loading