46 lines
1.5 KiB
JavaScript
46 lines
1.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { constants } from 'node:fs';
|
|
import { access } from 'node:fs/promises';
|
|
import { fileURLToPath } from 'node:url';
|
|
import path from 'node:path';
|
|
|
|
export const MISSING_DEPS_EXIT = 42;
|
|
|
|
// The generated-state certification that used to live here (fingerprinting the
|
|
// web source tree and certifying apps/web/.next) retired with the Next.js build
|
|
// in Phase P5 (#1444): the Vite SPA has no generated tree that later gates
|
|
// consume, so there is no stale-output class left to defend against.
|
|
|
|
export async function runPreflight({ root = process.cwd() } = {}) {
|
|
const binDir = path.join(root, 'node_modules', '.bin');
|
|
const requiredBinaries = ['eslint', 'husky', 'prettier', 'tsc', 'turbo', 'vitest'];
|
|
const missingBinaries = [];
|
|
for (const binary of requiredBinaries) {
|
|
try {
|
|
await access(path.join(binDir, binary), constants.X_OK);
|
|
} catch {
|
|
missingBinaries.push(binary);
|
|
}
|
|
}
|
|
if (missingBinaries.length > 0) {
|
|
return {
|
|
code: MISSING_DEPS_EXIT,
|
|
message: `MOSAIC_PREFLIGHT_MISSING_DEPS: dependency installation is missing ${missingBinaries.join(', ')}; run pnpm install --frozen-lockfile`,
|
|
};
|
|
}
|
|
|
|
return { code: 0, message: 'checkout preflight passed' };
|
|
}
|
|
|
|
async function main() {
|
|
const result = await runPreflight();
|
|
const stream = result.code === 0 ? process.stdout : process.stderr;
|
|
stream.write(`${result.message}\n`);
|
|
process.exitCode = result.code;
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
await main();
|
|
}
|