Skip to content

Commit

Permalink
Add @ninjutsu-build/tsc.getEntryPointsFromConfig
Browse files Browse the repository at this point in the history
Expose a function to return all TypeScript entry points as described by
a `tsconfig.json` file.  For all projects using a `tsconfig.json` file,
they will most likely have to use `getEntryPointsFromConfig` to get the
entry points in the configuration script if these entry points need to
be run later on and the users don't want to hardcode it.
  • Loading branch information
elliotgoodrich committed Jul 8, 2024
1 parent 91c8dd2 commit aaed490
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
10 changes: 9 additions & 1 deletion integration/src/tsc.test.mts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { beforeEach, test, describe } from "node:test";
import { strict as assert } from "node:assert";
import { NinjaBuilder, getInput, validations } from "@ninjutsu-build/core";
import { makeTSCRule, makeTypeCheckRule } from "@ninjutsu-build/tsc";
import {
getEntryPointsFromConfig,
makeTSCRule,
makeTypeCheckRule,
} from "@ninjutsu-build/tsc";
import { writeFileSync, mkdirSync, symlinkSync, existsSync } from "node:fs";
import { join } from "node:path/posix";
import {
Expand Down Expand Up @@ -269,6 +273,10 @@ describe("tsc", (suiteCtx) => {
"src/myOutput/script.mjs",
"src/myOutput/script.d.mts",
]);
assert.deepEqual(
await getEntryPointsFromConfig(ninja, "src/tsconfig.json"),
["src/script.mts"],
);

const typechecked = await typecheck({
tsConfig: { file: "src/tsconfig.json" },
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.13.0",
"version": "0.13.1",
"description": "Create a ninjutsu-build rule for running the TypeScript compiler (tsc)",
"author": "Elliot Goodrich",
"scripts": {
Expand Down
48 changes: 48 additions & 0 deletions packages/tsc/src/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,57 @@ async function showConfig(
join(ninja.outputDir, getInput(tsConfig)),
]);

// `--showConfig` displays valid JSON so use the built-in parser
return JSON.parse(stdout);
}

/**
* Return the list of entry points specified in the `tsconfig.json` file
* located at the specified `tsConfigPath`. This is a combination of
* the `files`, `include`, and `exclude` properties, see the
* [`tsconfig.json` documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)
* for further information.
*/
export async function getEntryPointsFromConfig(
ninja: NinjaBuilder,
tsConfigPath: Input<string>,
): Promise<string[]> {
const tsConfigPathRaw = join(ninja.outputDir, getInput(tsConfigPath));
const buffer = await readFile(tsConfigPathRaw);

// Use TypeScript's parsing to handle comments
let { config, error } = ts.parseConfigFileTextToJson(
tsConfigPathRaw,
buffer.toString(),
);
if (config === undefined) {
throw new Error(
error === undefined
? `Unknown error while parsing ${tsConfigPathRaw}`
: `${error.messageText}`,
);
}

// If we don't have any `include` property then `files` gives us
// exactly the entry points we care about
if (Array.isArray(config.include) && config.include.length > 0) {
// There is no public typescript method to get the full list of entry points
// so instead we call out to `tsc --showConfig`.
const { stdout } = await execFile(node, [
tsc,
getTSCPath(ninja),
"--showConfig",
"--project",
tsConfigPathRaw,
]);
// `--showConfig` displays valid JSON so use the built-in parser
config = JSON.parse(stdout);
}

const directory = dirname(getInput(tsConfigPath));
return config.files.map((f: string) => join(directory, f));
}

export type TypeCheckRuleFn = {
<O extends string>(a: {
in: readonly Input<string>[];
Expand Down

0 comments on commit aaed490

Please sign in to comment.