// Compare client diagnostics against HEAD without changing the working tree. const ts = require('typescript'); const cp = require('node:child_process'); const path = require('node:path'); const root = path.resolve(__dirname, '../..'); const config = ts.readConfigFile(path.join(root, 'tsconfig.json'), ts.sys.readFile).config; config.include = ['assets/**/*.ts', 'creator.d.ts']; config.exclude = ['node_modules', 'server']; config.compilerOptions.noEmit = true; const parsed = ts.parseJsonConfigFileContent(config, ts.sys, root); const tracked = new Set(cp.execFileSync('git', ['ls-files'], { cwd: root, encoding: 'utf8' }).trim().split('\n')); const relative = file => path.relative(root, file).replaceAll('\\', '/'); function check(baseline) { const host = ts.createCompilerHost(parsed.options); if (baseline) { const read = host.readFile; host.readFile = file => { const key = relative(file); if (key.endsWith('.ts') && tracked.has(key)) return cp.execFileSync('git', ['show', 'HEAD:' + key], { cwd: root, encoding: 'utf8', maxBuffer: 8 * 1024 * 1024 }); return read(file); }; } const program = ts.createProgram(parsed.fileNames.filter(f => !baseline || tracked.has(relative(f))), parsed.options, host); return ts.getPreEmitDiagnostics(program).map(d => (d.file ? relative(d.file.fileName) : '') + ':' + d.code + ':' + ts.flattenDiagnosticMessageText(d.messageText, ' ')).sort(); } const current = check(false), baseline = check(true); const added = current.filter(d => !baseline.includes(d)); console.log(JSON.stringify({ current: current.length, baseline: baseline.length, added }, null, 2)); process.exitCode = added.length ? 1 : 0;