Files
vercel/utils/build.mjs
Chris Barber 222710f612 Add type-check and unify tsconfig (#10667)
This adds a new `pnpm type-check` that leverages `turbo` to validate the TypeScript code. This can be run at the top-level or for an individual package.

The `test-lint` workflow will run it after linting and doing the prettier check.

As apart of this effort, each package's `tsconfig.json` has been simplified. There's a new top-level `tsconfig.base.json` file that extends the Vercel Style Guide for TypeScript. Each package's `tsconfig.json` has been audited and previously suppressed rules that no longer apply have been removed. The result is each package's `tsconfig.json` is greatly simplified and we can control common settings in the base config while keeping the flexibility of package-level overrides.

Lastly, in `package/cli`, `pnpm build` calls `scripts/build.mjs` which calls `scripts/compile-templates.mjs`. The `compile-templates.mjs` file was generating invalid TypeScript code. I've fixed it and now it's happier than ever.

Note: In order to run `pnpm type-check`, you must first `pnpm build` because we need the `.d.ts` definition files.
2023-10-09 11:58:23 +00:00

76 lines
2.0 KiB
JavaScript
Vendored

import execa from 'execa';
import ts from 'typescript';
import path from 'node:path';
import { build } from 'esbuild';
import { fileURLToPath } from 'node:url';
function parseTsConfig(tsconfigPath) {
const parsedConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
if (parsedConfig.error) {
console.error(
'Error parsing tsconfig:',
ts.flattenDiagnosticMessageText(parsedConfig.error.messageText, '\n')
);
return;
}
const result = ts.parseJsonConfigFileContent(
parsedConfig.config,
ts.sys,
path.dirname(tsconfigPath)
);
if (result.errors && result.errors.length > 0) {
for (const error of result.errors) {
console.error(ts.flattenDiagnosticMessageText(error.messageText, '\n'));
}
return;
}
return result;
}
export async function esbuild(opts = {}, cwd = process.cwd()) {
const configPath = path.join(cwd, 'tsconfig.json');
const tsconfig = parseTsConfig(configPath);
if (!tsconfig) {
throw new Error(`Failed to load "${configPath}`);
}
const entryPoints = opts.bundle
? // When bundling, assume `src/index.ts` is the entrypoint file
[path.join(cwd, 'src/index.ts')]
: // When not bundling, compile all files referenced by the `tsconfig.json` file
tsconfig.fileNames;
let outdir = opts.outfile ? undefined : tsconfig.options.outDir;
await build({
entryPoints,
format: 'cjs',
outdir,
platform: 'node',
target: ts.ScriptTarget[tsconfig.options.target],
sourcemap: tsconfig.options.sourceMap,
...opts,
});
}
export async function tsc() {
const rootNodeModulesBin = fileURLToPath(
new URL('../node_modules/.bin', import.meta.url)
);
await execa('tsc', ['--declaration', '--emitDeclarationOnly'], {
stdio: 'inherit',
env: {
...process.env,
PATH: `${rootNodeModulesBin}${path.delimiter}${process.env.PATH}`,
},
});
}
// If the script is invoked directly, do the
// common case of esbuild + tsc for types
if (fileURLToPath(import.meta.url) === process.argv[1]) {
await Promise.all([tsc(), esbuild()]);
}