Skip to content

Commit

Permalink
Allow compilerOptions with a tsconfig file
Browse files Browse the repository at this point in the history
Allow passing an optional `compilerOptions` property when using a
tsconfig file in `@ninjutsu-build/tsc` rules.  This will allow users to
have a standard tsconfig file, but selectively supply (or override)
options such as `outDir` or `declaration` that may differ per-project.
  • Loading branch information
elliotgoodrich committed Jun 15, 2024
1 parent 0d68c2b commit 82e8745
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 13 deletions.
35 changes: 30 additions & 5 deletions integration/src/tsc.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,10 @@ describe("tsc", (suiteCtx) => {
test("tsconfig", async (testCtx) => {
const dir = getTestDir(suiteCtx, testCtx);
const script = "script.mts";
writeFileSync(join(dir, script), "console.log('Hello World!');\n");
writeFileSync(
join(dir, script),
"function greet(msg): void { console.log(msg); }\ngreet('Hello World!');\n",
);

const tsConfig = join(dir, "tsconfig.json");
writeFileSync(
Expand All @@ -223,10 +226,8 @@ describe("tsc", (suiteCtx) => {
{
files: [script],
compilerOptions: {
noImplicitAny: false,
outDir: "myOutput",
declaration: true,
strict: true,
alwaysStrict: true,
skipLibCheck: true,
},
},
Expand All @@ -239,7 +240,10 @@ describe("tsc", (suiteCtx) => {
const tsc = makeTSCRule(ninja);
const typecheck = makeTypeCheckRule(ninja);

const out = await tsc({ tsConfig: "tsconfig.json" });
const out = await tsc({
tsConfig: "tsconfig.json",
compilerOptions: { declaration: true },
});
assert.deepEqual(out, ["myOutput/script.mjs", "myOutput/script.d.mts"]);

const typechecked = await typecheck({
Expand All @@ -250,6 +254,19 @@ describe("tsc", (suiteCtx) => {
{ file: "script.mts", [validations]: "typechecked.stamp" },
]);

const failed = await typecheck({
tsConfig: "tsconfig.json",
out: "failed.stamp",
compilerOptions: {
noImplicitAny: true,
},
});
assert.deepEqual(failed, [
{ file: "script.mts", [validations]: "failed.stamp" },
]);

const err = ninja.phony({ out: "err", in: failed[0][validations] });
ninja.default(...out, typechecked[0][validations]);
writeFileSync(join(dir, "build.ninja"), ninja.output);

{
Expand All @@ -269,6 +286,14 @@ describe("tsc", (suiteCtx) => {
}

assert.strictEqual(callNinja(dir).trimEnd(), "ninja: no work to do.");

{
const { stdout } = callNinjaWithFailure(dir, err);
assert.match(
stdout,
/error TS7006: Parameter 'msg' implicitly has an 'any' type/,
);
}
});

// TODO: Check the `incremental` flag works correctly
Expand Down
2 changes: 1 addition & 1 deletion packages/tsc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ninjutsu-build/tsc",
"version": "0.12.4",
"version": "0.12.5",
"description": "Create a ninjutsu-build rule for running the TypeScript compiler (tsc)",
"author": "Elliot Goodrich",
"scripts": {
Expand Down
23 changes: 16 additions & 7 deletions packages/tsc/src/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export type TypeCheckRuleFn = {

<O2 extends string>(a: {
tsConfig: string;
compilerOptions?: CompilerOptions;
out: O2;
[implicitDeps]?: string | readonly string[];
[orderOnlyDeps]?: Input<string> | readonly Input<string>[];
Expand All @@ -167,12 +168,12 @@ export type TypeCheckRuleFn = {
a: (
| {
in: readonly Input<string>[];
compilerOptions?: CompilerOptions;
}
| {
tsConfig: Input<string>;
}
) & {
compilerOptions?: CompilerOptions;
out: O3;
[implicitDeps]?: string | readonly string[];
[orderOnlyDeps]?: Input<string> | readonly Input<string>[];
Expand Down Expand Up @@ -241,12 +242,12 @@ export function makeTypeCheckRule(
a: (
| {
in: readonly Input<string>[];
compilerOptions?: CompilerOptions;
}
| {
tsConfig: Input<string>;
}
) & {
compilerOptions?: CompilerOptions;
out: O;
[implicitDeps]?: string | readonly string[];
[orderOnlyDeps]?: Input<string> | readonly Input<string>[];
Expand All @@ -270,7 +271,7 @@ export function makeTypeCheckRule(
const typechecked = typecheck({
in: [a.tsConfig],
out: a.out,
args: "-p",
args: compilerOptionsToString(a.compilerOptions ?? {}) + " -p",
});
return getFileNames(ninja, a.tsConfig).then(({ files }) =>
files.map((file) => ({
Expand All @@ -293,6 +294,7 @@ export type TSCRuleFn = {
}): string[];
(a: {
tsConfig: Input<string>;
compilerOptions?: CompilerOptions;
[implicitDeps]?: string | readonly string[];
[orderOnlyDeps]?: Input<string> | readonly Input<string>[];
[implicitOut]?: string | readonly string[];
Expand All @@ -302,12 +304,12 @@ export type TSCRuleFn = {
a: (
| {
in: readonly Input<string>[];
compilerOptions?: CompilerOptions;
}
| {
tsConfig: Input<string>;
}
) & {
compilerOptions?: CompilerOptions;
[implicitDeps]?: string | readonly string[];
[orderOnlyDeps]?: Input<string> | readonly Input<string>[];
[implicitOut]?: string | readonly string[];
Expand Down Expand Up @@ -399,12 +401,12 @@ export function makeTSCRule(ninja: NinjaBuilder, name = "tsc"): TSCRuleFn {
a: (
| {
in: readonly Input<string>[];
compilerOptions?: CompilerOptions;
}
| {
tsConfig: Input<string>;
}
) & {
compilerOptions?: CompilerOptions;
[implicitDeps]?: string | readonly string[];
[orderOnlyDeps]?: Input<string> | readonly Input<string>[];
[implicitOut]?: string | readonly string[];
Expand Down Expand Up @@ -441,14 +443,21 @@ export function makeTSCRule(ninja: NinjaBuilder, name = "tsc"): TSCRuleFn {
} else {
const {
tsConfig,
compilerOptions: overrideOptions = {},
[implicitOut]: _implicitOut = [],
[validations]: _validations,
...rest
} = a;
return getFileNames(ninja, tsConfig).then(
({ files, compilerOptions }) => {
const finalCompilerOptions = {
...compilerOptions,
...overrideOptions,
};
const commandLine = ts.parseCommandLine(
files.concat(compilerOptionsToArrayBestEffort(compilerOptions)),
files.concat(
compilerOptionsToArrayBestEffort(finalCompilerOptions),
),
);

// We need to set this to something, else we get a debug exception
Expand All @@ -462,7 +471,7 @@ export function makeTSCRule(ninja: NinjaBuilder, name = "tsc"): TSCRuleFn {
...rest,
in: [tsConfig],
out: out[0],
args: "-p",
args: compilerOptionsToString(finalCompilerOptions) + " -p",
[implicitOut]: out.slice(1).concat(_implicitOut),
[validations]:
_validations === undefined ? undefined : () => _validations(out),
Expand Down

0 comments on commit 82e8745

Please sign in to comment.