diff --git a/tools/build-packs.mjs b/tools/build-packs.mjs index bc86d68..0549292 100644 --- a/tools/build-packs.mjs +++ b/tools/build-packs.mjs @@ -458,30 +458,41 @@ async function writePack(packName, entries) { // Refuse to build if a rule has been duplicated. The packs used to be built under // one rule and played under another; this makes that impossible to ship. +// +// fileURLToPath, not .pathname: on Windows a file URL's pathname is "/C:/Users/...", +// and node resolves that against the drive root, so every one of these spawned +// "C:\C:\Users\...\check-rules.mjs" and the build aborted on a module it could not +// find. npm run build has never worked on Windows. Same root as the packs/ CRLF bug — +// this repository has only ever been built on macOS and Linux. { const { execFileSync } = await import("node:child_process"); try { - execFileSync(process.execPath, [new URL("check-rules.mjs", import.meta.url).pathname], + execFileSync(process.execPath, [fileURLToPath(new URL("check-rules.mjs", import.meta.url))], { stdio: "inherit" }); // And refuse if a posting is issued kit the catalogue cannot supply. - execFileSync(process.execPath, [new URL("check-kits.mjs", import.meta.url).pathname], + execFileSync(process.execPath, [fileURLToPath(new URL("check-kits.mjs", import.meta.url))], { stdio: "inherit" }); // And refuse if the localisation file cannot be loaded, which un-localises // every sheet in the system and gives no error the user would connect to it. - execFileSync(process.execPath, [new URL("check-lang.mjs", import.meta.url).pathname], + execFileSync(process.execPath, [fileURLToPath(new URL("check-lang.mjs", import.meta.url))], { stdio: "inherit" }); // And refuse if a template will not compile. A parse error in a .hbs is a sheet // that never opens, and no other guard reads templates — npc-sheet.hbs shipped // broken and every NPC in the system threw on click. - execFileSync(process.execPath, [new URL("check-templates.mjs", import.meta.url).pathname], + execFileSync(process.execPath, [fileURLToPath(new URL("check-templates.mjs", import.meta.url))], { stdio: "inherit" }); // And refuse if a rule a play-through already found is broken again. The static // guards cannot tell whether a rule is READ; these tests can. - execFileSync(process.execPath, [new URL("check-behaviour.mjs", import.meta.url).pathname], + execFileSync(process.execPath, [fileURLToPath(new URL("check-behaviour.mjs", import.meta.url))], { stdio: "inherit" }); // And refuse a scenario that tells the GM to roll a skill nobody has. THROUGH TRAIN // asked for Ride through several drafts and a playtest; there is no Ride skill. - execFileSync(process.execPath, [new URL("check-scenarios.mjs", import.meta.url).pathname], + execFileSync(process.execPath, [fileURLToPath(new URL("check-scenarios.mjs", import.meta.url))], + { stdio: "inherit" }); + // And refuse an actor spec the engine cannot build. buildActor throws on an unknown + // skill or item key, but says nothing about a bad species, a misspelt field or a + // species-locked talent on the wrong species — all of which pack and play. + execFileSync(process.execPath, [fileURLToPath(new URL("check-creatures.mjs", import.meta.url))], { stdio: "inherit" }); } catch { console.error("build aborted: pre-build checks failed"); process.exit(1); } } diff --git a/tools/update-readme.mjs b/tools/update-readme.mjs index 01ac927..d2a20e0 100644 --- a/tools/update-readme.mjs +++ b/tools/update-readme.mjs @@ -9,6 +9,7 @@ */ import { readFile, writeFile } from "node:fs/promises"; import { execFileSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; import { SKILL_CATALOGUE, WEAPONS, ARMOURS, GEAR, VEHICLES, NPCS, TALENTS } from "./content.mjs"; import { ROLES, TRADES } from "../postings.mjs"; @@ -24,7 +25,7 @@ const items = WEAPONS.length + ARMOURS.length + GEAR.length + VEHICLES.length; // The guard lines are quoted from the guards themselves rather than paraphrased. const runGuard = name => { try { - return execFileSync(process.execPath, [new URL(name, import.meta.url).pathname], + return execFileSync(process.execPath, [fileURLToPath(new URL(name, import.meta.url))], { encoding: "utf8" }).split("\n").find(l => l.startsWith(name.replace(".mjs", ""))); } catch { return null; } };