Files
TREK/server/scripts/build.mjs
T
2026-09-20 21:38:32 +02:00

41 lines
1.8 KiB
JavaScript

import { execSync } from 'node:child_process';
import { existsSync, rmSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
// Resolved from this file rather than cwd, so the directory that gets removed is
// always this package's own dist no matter where the script is invoked from.
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
const distDir = join(packageRoot, 'dist');
// tsc only ever adds to dist, so a module deleted or renamed in src leaves its
// compiled twin behind. For most code that is merely stale, but the migrator
// globs dist/db/migrations at boot: an orphan there is a live migration with no
// source, and it runs. Same for dist/db/seeders. Nothing else writes into dist —
// the client bundle goes to server/public and the runtime assets the Dockerfile
// needs are copied in separately — so it is safe to drop wholesale.
rmSync(distDir, { recursive: true, force: true });
let tscExitedNonZero = false;
try {
execSync('tsc -p tsconfig.build.json', { stdio: 'inherit', cwd: packageRoot });
} catch {
tscExitedNonZero = true;
}
// `noEmitOnError` is off, so tsc exits non-zero on type errors and still writes
// dist — that case is deliberate, and gated by `npm run typecheck`. A tsc that
// never ran at all (not on PATH, crashed) is indistinguishable from here, and
// now that dist is emptied first it would leave nothing behind while still
// reporting success. Checking for the entry point tells the two apart.
if (!existsSync(join(distDir, 'index.js'))) {
console.error('[build] tsc emitted nothing — dist is empty. Run via `npm run build` so tsc is on PATH.');
process.exit(1);
}
if (tscExitedNonZero) {
console.warn('[build] tsc reported type errors — emitting anyway (gated by `npm run typecheck`).');
}
console.log('[build] dist ready.');