import { spawnSync } from "node:child_process"; import { readdir } from "node:fs/promises"; import { extname, resolve } from "node:path"; const recipeRoot = resolve("recipes"); const pnpmCli = requireEnvironment("npm_execpath"); if (!(await containsTypeScriptSource(recipeRoot))) { process.stdout.write( "Optional recipe typecheck: SKIP (no recipe TypeScript sources installed)\n", ); } else { const result = spawnSync( process.execPath, [pnpmCli, "exec", "tsc", "--project", "tsconfig.recipes.json"], { stdio: "inherit" }, ); if (result.error) { throw result.error; } process.exitCode = result.status ?? 1; } function requireEnvironment(name: string): string { const value = process.env[name]; if (!value) { throw new Error(`${name} is required to typecheck optional recipes`); } return value; } async function containsTypeScriptSource(directory: string): Promise { let entries; try { entries = await readdir(directory, { withFileTypes: true }); } catch (error) { if (hasErrorCode(error, "ENOENT")) { return false; } throw error; } for (const entry of entries) { const target = resolve(directory, entry.name); if (entry.isDirectory() && (await containsTypeScriptSource(target))) { return true; } if (entry.isFile() && [".ts", ".tsx", ".mts", ".cts"].includes(extname(entry.name))) { return true; } } return false; } function hasErrorCode(error: unknown, code: string): boolean { return ( typeof error === "object" && error !== null && "code" in error && error.code === code ); }