Files
pn-new-crm/scripts/tsc-staged.mjs

56 lines
1.5 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* Pre-commit type check for staged TS files.
*
* Writes a temp tsconfig that extends the project root and pins
* `files` to whatever lint-staged passed in. `tsc -p` then compiles
* the whole dep graph from those entrypoints catches errors in
* the staged code AND in anything it imports while still skipping
* the 22s full-project pass.
*
* Replaces `tsc-files` (npm), which silently fails under pnpm because
* its tsc-resolution path (typescript/../.bin/tsc) doesn't exist in
* pnpm's virtual store layout.
*/
import { spawnSync } from 'node:child_process';
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, relative, resolve } from 'node:path';
const cwd = process.cwd();
const args = process.argv.slice(2);
const files = args.filter((a) => /\.(ts|tsx)$/.test(a));
if (files.length === 0) {
process.exit(0);
}
const tmpDir = mkdtempSync(join(tmpdir(), 'tsc-staged-'));
const tmpConfig = join(tmpDir, 'tsconfig.json');
const relFiles = files.map((f) => relative(tmpDir, resolve(cwd, f)));
writeFileSync(
tmpConfig,
JSON.stringify(
{
extends: relative(tmpDir, join(cwd, 'tsconfig.json')),
compilerOptions: { noEmit: true, skipLibCheck: true },
files: relFiles,
include: [],
},
null,
2,
),
);
const tsc = spawnSync('pnpm', ['exec', 'tsc', '-p', tmpConfig, '--pretty'], {
cwd,
stdio: 'inherit',
});
rmSync(tmpDir, { recursive: true, force: true });
process.exit(tsc.status ?? 1);