Skip to content

Commit

Permalink
Add tsconfig.json support to tsc plugin
Browse files Browse the repository at this point in the history
Although I would love if the ecosystem was as mature for
non-`tsconfig.json` projects compared to `tsconfig.json` projects, this
just isn't the case:

  * VSCode works much better with a local `tsconfig.json` file (e.g. it
    complains about `replaceAll` not being a method because we haven't
    set the correct `lib`)
  * There is a maximum line length for `cmd` (8191) that can be quite
    limiting when passing a large number of files via the command line
  * There are certain `tsconfig.json` options that cannot be passed via
    the command line (e.g. `paths`)
  * Existing users will most likely have a `tsconfig.json` file and it
    is simpler for them to migrate to `ninjutsu-build` if they can reuse
    this
  * There are other tools, such as TypeDoc, that only work with a
    `tsconfig.json` file

This commit adds support for a `tsconfig.json` file in the `makeTSCRule`
and `makeTypeCheckRule`.

Right now I am unsure whether to overload the `makeTSCRule` and
`makeTypeCheckRule` or rename the existing ones to `makeTSCRuleNoConfig`
and `makeTypeCheckRuleNoConfig` simplify the return types.

I will test this change out in building `ninjutsu` itself and
reevaluate.
  • Loading branch information
elliotgoodrich committed Jun 8, 2024
1 parent a743145 commit 0d68c2b
Show file tree
Hide file tree
Showing 10 changed files with 358 additions and 71 deletions.
3 changes: 3 additions & 0 deletions experiments/tsc_glob/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
src
entry.ts
tsconfig.show.json
25 changes: 25 additions & 0 deletions experiments/tsc_glob/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
This tests the speed of `tsconfig.json` `files` vs `include` properties.

Preferring `files` over `include` for performance is recommended in the
[TypeScript wiki page on performance](https://github.com/microsoft/TypeScript/wiki/Performance#specifying-files).

```
node create.mjs 10000
```

```
npx tsc --noEmit -p tsconfig.files.json
```

```
npx tsc --noEmit -p tsconfig.include.json
```

There starts being a difference after 10K files of ~1.5s on Windows (5s vs 6.5s).

```
npx tsc --showConfig -p tsconfig.include.json > tsconfig.show.json
```

A `tsconfig.json` file with both `files` and `include` takes about 5.2s. A little bit
slower than `tsconfig.files.json` but not as much as `tsconfig.include.json`.
19 changes: 19 additions & 0 deletions experiments/tsc_glob/create.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path/posix";

const limit = process.argv[2] ?? 100;

rmSync("src", { recursive: true, force: true });

let entry = "";
for (let i = 0; i < limit; ++i) {
const dir = join("src", ...i.toString());
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
writeFileSync(join(dir, "file.ts"), `export const var${i} = ${i};\n`);
entry += `import { var${i} } from "./${dir}/file.js";\n`;
}

writeFileSync("entry.ts", entry);

3 changes: 3 additions & 0 deletions experiments/tsc_glob/tsconfig.files.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"files": ["entry.ts"]
}
3 changes: 3 additions & 0 deletions experiments/tsc_glob/tsconfig.include.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"include": ["**/*.ts"]
}
63 changes: 63 additions & 0 deletions integration/src/tsc.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe("tsc", (suiteCtx) => {
out: "typecheck.stamp",
compilerOptions,
});

ninja.default(...output, ...output2, stamp[validations]);
const err1Target = ninja.phony({
out: "err1",
Expand Down Expand Up @@ -209,5 +210,67 @@ describe("tsc", (suiteCtx) => {
assert(stdout.split("\n").length < 10, stdout);
}
});

test("tsconfig", async (testCtx) => {
const dir = getTestDir(suiteCtx, testCtx);
const script = "script.mts";
writeFileSync(join(dir, script), "console.log('Hello World!');\n");

const tsConfig = join(dir, "tsconfig.json");
writeFileSync(
tsConfig,
JSON.stringify(
{
files: [script],
compilerOptions: {
outDir: "myOutput",
declaration: true,
strict: true,
alwaysStrict: true,
skipLibCheck: true,
},
},
undefined,
4,
),
);

const ninja = new NinjaBuilder({}, dir);
const tsc = makeTSCRule(ninja);
const typecheck = makeTypeCheckRule(ninja);

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

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

writeFileSync(join(dir, "build.ninja"), ninja.output);

{
const stdout = callNinja(dir);
assert.match(stdout, /Compiling tsconfig.json/);
assert.match(stdout, /Typechecking tsconfig.json/);
}

for (const output of out) {
const path = join(dir, getInput(output));
assert(existsSync(path), `${path} doesn't exist`);
}

{
const path = join(dir, getInput("typechecked.stamp"));
assert(existsSync(path), `${path} doesn't exist`);
}

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

// TODO: Check the `incremental` flag works correctly
test("incremental", { todo: true });
});
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/tsc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ We can build a `build.ninja` file that will compile `index.ts` and
use `@ninjutsu-build/node` to run the resulting JavaScript,

```ts
import { NinjaBuilder, [implicitDeps] } from "@ninjutsu-build/core";
import { NinjaBuilder } from "@ninjutsu-build/core";
import { makeTSCRule } from "@ninjutsu-build/tsc";
import { makeNodeRule } from "@ninjutsu-build/node";
import { writeFileSync } from "fs";
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.3",
"version": "0.12.4",
"description": "Create a ninjutsu-build rule for running the TypeScript compiler (tsc)",
"author": "Elliot Goodrich",
"scripts": {
Expand Down
Loading

0 comments on commit 0d68c2b

Please sign in to comment.