@bitmagic/cli 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/cli.d.ts +11 -0
  2. package/dist/cli.js +4 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/build.d.ts +1 -0
  5. package/dist/commands/build.js +16 -0
  6. package/dist/commands/build.js.map +1 -0
  7. package/dist/commands/upgrade.d.ts +21 -0
  8. package/dist/commands/upgrade.js +161 -0
  9. package/dist/commands/upgrade.js.map +1 -0
  10. package/dist/commands/verify.js +8 -9
  11. package/dist/commands/verify.js.map +1 -1
  12. package/dist/forge/apply-modifications.js +7 -13
  13. package/dist/forge/apply-modifications.js.map +1 -1
  14. package/dist/publish/bundle.d.ts +31 -0
  15. package/dist/publish/bundle.js +77 -0
  16. package/dist/publish/bundle.js.map +1 -0
  17. package/dist/publish/fingerprint.d.ts +27 -0
  18. package/dist/publish/fingerprint.js +64 -0
  19. package/dist/publish/fingerprint.js.map +1 -0
  20. package/dist/scaffold/dependency-diff.d.ts +28 -0
  21. package/dist/scaffold/dependency-diff.js +28 -0
  22. package/dist/scaffold/dependency-diff.js.map +1 -0
  23. package/dist/scaffold/project-files.d.ts +22 -0
  24. package/dist/scaffold/project-files.js +66 -5
  25. package/dist/scaffold/project-files.js.map +1 -1
  26. package/dist/scaffold/project.d.ts +17 -0
  27. package/dist/scaffold/project.js +24 -4
  28. package/dist/scaffold/project.js.map +1 -1
  29. package/dist/scaffold/upgrade-project.d.ts +35 -0
  30. package/dist/scaffold/upgrade-project.js +63 -0
  31. package/dist/scaffold/upgrade-project.js.map +1 -0
  32. package/dist/verify/result.d.ts +60 -0
  33. package/dist/verify/result.js +74 -0
  34. package/dist/verify/result.js.map +1 -0
  35. package/package.json +3 -3
package/dist/cli.d.ts CHANGED
@@ -49,6 +49,16 @@ declare const rawCommands: {
49
49
  readonly description: "Scaffold into a non-empty directory.";
50
50
  };
51
51
  }>;
52
+ upgrade: CommandDef<{
53
+ readonly engine: {
54
+ readonly type: "string";
55
+ readonly description: "Engine version to upgrade to (must be the currently published one).";
56
+ };
57
+ readonly force: {
58
+ readonly type: "boolean";
59
+ readonly description: "Upgrade even with uncommitted changes in the working tree.";
60
+ };
61
+ }>;
52
62
  check: CommandDef<ArgsDef>;
53
63
  dev: CommandDef<{
54
64
  readonly port: {
@@ -62,6 +72,7 @@ declare const rawCommands: {
62
72
  readonly description: "Settle time in ms (default 15000).";
63
73
  };
64
74
  }>;
75
+ build: CommandDef<ArgsDef>;
65
76
  generate: CommandDef<ArgsDef>;
66
77
  forge: CommandDef<{
67
78
  readonly prompt: {
package/dist/cli.js CHANGED
@@ -4,9 +4,11 @@ import { loginCommand } from './commands/login.js';
4
4
  import { logoutCommand } from './commands/logout.js';
5
5
  import { whoamiCommand } from './commands/whoami.js';
6
6
  import { initCommand } from './commands/init.js';
7
+ import { upgradeCommand } from './commands/upgrade.js';
7
8
  import { checkCommand } from './commands/check.js';
8
9
  import { devCommand } from './commands/dev.js';
9
10
  import { verifyCommand } from './commands/verify.js';
11
+ import { buildCommand } from './commands/build.js';
10
12
  import { generateCommand } from './commands/generate.js';
11
13
  import { forgeCommand } from './commands/forge.js';
12
14
  // citty's runMain() catches every error thrown from a command's `run()` internally and calls
@@ -87,9 +89,11 @@ const rawCommands = {
87
89
  logout: logoutCommand,
88
90
  whoami: whoamiCommand,
89
91
  init: initCommand,
92
+ upgrade: upgradeCommand,
90
93
  check: checkCommand,
91
94
  dev: devCommand,
92
95
  verify: verifyCommand,
96
+ build: buildCommand,
93
97
  generate: generateCommand,
94
98
  forge: forgeCommand,
95
99
  };
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const buildCommand: import("citty").CommandDef<import("citty").ArgsDef>;
@@ -0,0 +1,16 @@
1
+ import { defineCommand } from 'citty';
2
+ import { loadProjectContext } from '../project/context.js';
3
+ import { runBuild } from '../publish/bundle.js';
4
+ export const buildCommand = defineCommand({
5
+ meta: {
6
+ name: 'build',
7
+ description: 'Bundle the game for publishing into .bitmagic/build/index.html.',
8
+ },
9
+ async run() {
10
+ const context = loadProjectContext();
11
+ console.log('Building…');
12
+ const manifest = runBuild(context.root, context.metadata.engineVersion);
13
+ console.log(`Bundle ready: .bitmagic/build/index.html (${manifest.bytes} bytes)`);
14
+ },
15
+ });
16
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,iEAAiE;KAC/E;IACD,KAAK,CAAC,GAAG;QACP,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,6CAA6C,QAAQ,CAAC,KAAK,SAAS,CAAC,CAAC;IACpF,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface GitStatus {
2
+ dirty: boolean;
3
+ }
4
+ /**
5
+ * The boundary that makes `upgrade` safe to run at all: the whole value of the command is that a
6
+ * creator can read what it changed as a git diff. Overwriting vendored files on top of already
7
+ * -uncommitted work mixes the two together and makes that diff unreadable, so a dirty tree is
8
+ * refused unless the creator opts in with --force. Kept as a pure function, separate from the
9
+ * git call that produces `status`, so it is reachable from a test with no real repo involved.
10
+ */
11
+ export declare function assertCleanTree(status: GitStatus, force: boolean): void;
12
+ export declare const upgradeCommand: import("citty").CommandDef<{
13
+ readonly engine: {
14
+ readonly type: "string";
15
+ readonly description: "Engine version to upgrade to (must be the currently published one).";
16
+ };
17
+ readonly force: {
18
+ readonly type: "boolean";
19
+ readonly description: "Upgrade even with uncommitted changes in the working tree.";
20
+ };
21
+ }>;
@@ -0,0 +1,161 @@
1
+ import { defineCommand } from 'citty';
2
+ import * as fs from 'fs';
3
+ import * as os from 'os';
4
+ import * as path from 'path';
5
+ import { spawnSync } from 'child_process';
6
+ import { CliError } from '../errors.js';
7
+ import { resolveEnvironment, resolveAuth0ClientId } from '../config/environments.js';
8
+ import { readDefaultEnvironment } from '../config/credentials.js';
9
+ import { getAccessToken } from '../auth/session.js';
10
+ import { fetchEngineManifest, downloadAndVerify, extractEngine } from '../scaffold/engine-download.js';
11
+ import { upgradeProject } from '../scaffold/upgrade-project.js';
12
+ import { diffDependencies } from '../scaffold/dependency-diff.js';
13
+ import { DEPENDENCIES, DEV_DEPENDENCIES } from '../scaffold/project-files.js';
14
+ import { loadProjectContext } from '../project/context.js';
15
+ const deps = {
16
+ fetch: globalThis.fetch,
17
+ sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
18
+ };
19
+ /**
20
+ * The boundary that makes `upgrade` safe to run at all: the whole value of the command is that a
21
+ * creator can read what it changed as a git diff. Overwriting vendored files on top of already
22
+ * -uncommitted work mixes the two together and makes that diff unreadable, so a dirty tree is
23
+ * refused unless the creator opts in with --force. Kept as a pure function, separate from the
24
+ * git call that produces `status`, so it is reachable from a test with no real repo involved.
25
+ */
26
+ export function assertCleanTree(status, force) {
27
+ if (status.dirty && !force) {
28
+ throw new CliError('The working tree has uncommitted changes. Commit or stash them first so the upgrade shows ' +
29
+ 'up as its own reviewable diff, or pass --force to upgrade anyway.');
30
+ }
31
+ }
32
+ /**
33
+ * When the project isn't a git repository (or git itself isn't installed), there is no diff to
34
+ * protect in the first place — treated as clean rather than blocked, so `upgrade` still works for
35
+ * a project a creator hasn't put under version control.
36
+ *
37
+ * Scoped to `root` with `-- .`: plain `git status --porcelain` reports the whole repository from
38
+ * any subdirectory, which would block a creator keeping several games in one repo over dirt in a
39
+ * sibling project that `upgrade` never touches.
40
+ */
41
+ function getGitStatus(root) {
42
+ const result = spawnSync('git', ['status', '--porcelain', '--', '.'], { cwd: root, encoding: 'utf-8' });
43
+ if (result.error || result.status !== 0) {
44
+ return { dirty: false };
45
+ }
46
+ return { dirty: result.stdout.trim().length > 0 };
47
+ }
48
+ /**
49
+ * Reads just the two dependency maps out of package.json, tolerating anything else about the
50
+ * file being absent or malformed — this check is advisory (upgradeProject has already succeeded
51
+ * by the time it runs), so a bad package.json here must not turn into a hard failure.
52
+ */
53
+ function readPackageJsonDeps(root) {
54
+ let raw;
55
+ try {
56
+ raw = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8'));
57
+ }
58
+ catch {
59
+ return {};
60
+ }
61
+ if (typeof raw !== 'object' || raw === null)
62
+ return {};
63
+ const obj = raw;
64
+ return {
65
+ dependencies: isStringRecord(obj.dependencies) ? obj.dependencies : undefined,
66
+ devDependencies: isStringRecord(obj.devDependencies) ? obj.devDependencies : undefined,
67
+ };
68
+ }
69
+ function isStringRecord(value) {
70
+ return (typeof value === 'object' &&
71
+ value !== null &&
72
+ !Array.isArray(value) &&
73
+ Object.values(value).every((entry) => typeof entry === 'string'));
74
+ }
75
+ /**
76
+ * The other half of "package.json is never rewritten": upgradeProject leaves it untouched even
77
+ * when the vendored engine now needs a dependency it doesn't have (e.g. vite-plugin-singlefile,
78
+ * which every pre-Task-3 project's package.json predates) — silently doing nothing here would
79
+ * mean `upgrade` reports success while `bitmagic build` still fails later with an opaque
80
+ * module-resolution error. Prints the exact install command instead; never writes the file.
81
+ */
82
+ function printDependencyReport(root) {
83
+ const mismatches = diffDependencies(readPackageJsonDeps(root), {
84
+ dependencies: DEPENDENCIES,
85
+ devDependencies: DEV_DEPENDENCIES,
86
+ });
87
+ if (mismatches.length === 0)
88
+ return;
89
+ console.log('');
90
+ console.log("package.json is not touched by upgrade, and it is missing or outdated on dependencies the " +
91
+ 'vendored engine now needs. Run:');
92
+ const deps = mismatches.filter((m) => m.kind === 'dependency');
93
+ const devDeps = mismatches.filter((m) => m.kind === 'devDependency');
94
+ if (deps.length > 0) {
95
+ console.log(` npm install ${deps.map((m) => `${m.name}@${m.required}`).join(' ')}`);
96
+ }
97
+ if (devDeps.length > 0) {
98
+ console.log(` npm install --save-dev ${devDeps.map((m) => `${m.name}@${m.required}`).join(' ')}`);
99
+ }
100
+ }
101
+ export const upgradeCommand = defineCommand({
102
+ meta: {
103
+ name: 'upgrade',
104
+ description: "Refresh this project's vendored engine and platform config files without touching your game.",
105
+ },
106
+ args: {
107
+ engine: { type: 'string', description: 'Engine version to upgrade to (must be the currently published one).' },
108
+ force: { type: 'boolean', description: 'Upgrade even with uncommitted changes in the working tree.' },
109
+ },
110
+ async run({ args }) {
111
+ const context = loadProjectContext();
112
+ assertCleanTree(getGitStatus(context.root), args.force === true);
113
+ const environment = resolveEnvironment({ storedDefault: readDefaultEnvironment() });
114
+ const clientId = resolveAuth0ClientId(environment);
115
+ const token = await getAccessToken(environment, clientId, deps);
116
+ console.log('Fetching the engine manifest…');
117
+ const manifest = await fetchEngineManifest(environment, token, { fetch: globalThis.fetch });
118
+ // The manifest endpoint only ever serves the currently published engine — there is no way to
119
+ // fetch an older or specific version's tarball. An explicit --engine that names anything else
120
+ // must fail loudly rather than silently downloading the current tarball and mislabeling
121
+ // bitmagic.json with a version that doesn't match what actually landed on disk.
122
+ const targetVersion = args.engine ?? manifest.version;
123
+ if (targetVersion !== manifest.version) {
124
+ throw new CliError(`Cannot upgrade to engine ${targetVersion}: the server only serves the currently published ` +
125
+ `version, ${manifest.version}. Omit --engine to upgrade to it.`);
126
+ }
127
+ const workDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bitmagic-upgrade-'));
128
+ try {
129
+ const tarballPath = path.join(workDir, 'engine.tar.gz');
130
+ console.log(`Downloading engine ${manifest.version}…`);
131
+ await downloadAndVerify(manifest.tarballUrl, manifest.sha256, tarballPath, { fetch: globalThis.fetch });
132
+ const extracted = path.join(workDir, 'extracted');
133
+ const templatesDir = path.join(workDir, 'templates');
134
+ await extractEngine(tarballPath, extracted, templatesDir);
135
+ const result = upgradeProject({
136
+ root: context.root,
137
+ extractedEngineDir: extracted,
138
+ engineVersion: manifest.version,
139
+ });
140
+ console.log('');
141
+ if (result.previousEngineVersion === result.engineVersion) {
142
+ // A project scaffolded before `vite.publish.config.js` existed lands here: no engine
143
+ // bump, but this run is exactly how it gains the file `bitmagic build` needs. Say so
144
+ // explicitly rather than reporting "already up to date" and doing nothing.
145
+ console.log(`Already on engine ${result.engineVersion}. Refreshed the platform files anyway.`);
146
+ }
147
+ else {
148
+ console.log(`Upgraded engine ${result.previousEngineVersion} -> ${result.engineVersion}.`);
149
+ }
150
+ console.log('Replaced:');
151
+ for (const file of result.replaced) {
152
+ console.log(` ${file}`);
153
+ }
154
+ printDependencyReport(context.root);
155
+ }
156
+ finally {
157
+ fs.rmSync(workDir, { recursive: true, force: true });
158
+ }
159
+ },
160
+ });
161
+ //# sourceMappingURL=upgrade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,8 @@ import { reserveCorsAllowedPort, CORS_ALLOWED_PORT_MIN, CORS_ALLOWED_PORT_MAX }
8
8
  import { runHeadlessCheck } from '../verify/browser.js';
9
9
  import { classifyVerifyRun } from '../verify/classify.js';
10
10
  import { waitForServer } from '../verify/wait-for-server.js';
11
+ import { computeFingerprint } from '../publish/fingerprint.js';
12
+ import { writeVerifyRecord, decideVerifyOutcome, recordAndGateVerify } from '../verify/result.js';
11
13
  const DEFAULT_SETTLE_MS = 15_000;
12
14
  /**
13
15
  * A free port INSIDE the CORS-allowed window, never an OS-assigned ephemeral one.
@@ -106,15 +108,12 @@ export const verifyCommand = defineCommand({
106
108
  settleMs,
107
109
  });
108
110
  const result = classifyVerifyRun(observations);
109
- for (const warning of result.warnings)
110
- console.log(`warning: ${warning}`);
111
- if (!result.ok) {
112
- for (const failure of result.failures)
113
- console.error(`✗ ${failure}`);
114
- console.error(`\nArtifacts: ${consolePath}, ${screenshotPath}`);
115
- throw new CliError('Verification failed.');
116
- }
117
- console.log(`Verification passed. Artifacts in ${artifactDir}`);
111
+ const outcome = decideVerifyOutcome(result, computeFingerprint(context.root), new Date().toISOString());
112
+ recordAndGateVerify(artifactDir, outcome, { consolePath, screenshotPath }, {
113
+ write: writeVerifyRecord,
114
+ info: (line) => console.log(line),
115
+ error: (line) => console.error(line),
116
+ });
118
117
  }
119
118
  finally {
120
119
  server?.kill('SIGTERM');
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"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"}
@@ -21,14 +21,9 @@
21
21
  * here is the correct direction. The semantics below mirror `applyModification` in
22
22
  * game-play-agent's `utils/world-json-editor.ts` case for case — that is the reference
23
23
  * implementation both lanes' persist plans were written against, and the two must not drift.
24
- *
25
- * ── One place they DO differ today ────────────────────────────────────────────────────────
26
- *
27
- * The web lane re-validates the document against the engine's `GameData` schema AFTER applying
28
- * and refuses a write that introduces a NEW violation (`world-json-editor.ts:361,371`, baseline-
29
- * diff so legacy games still accept unrelated writes). This applier has no such gate: it checks
30
- * the document it READ and writes atomically, but does not check the result. Tracked in issue
31
- * #819 — it needs the validator lifted somewhere the CLI can reach.
24
+ * That includes the post-apply `GameData` schema gate (see `applyModificationsToWorld` below),
25
+ * which both lanes run baseline-diffed so a legacy game's existing violations still accept
26
+ * unrelated writes.
32
27
  */
33
28
  import * as fs from 'fs';
34
29
  import * as path from 'path';
@@ -181,11 +176,10 @@ export function applyModificationsToWorld(worldPath, modifications) {
181
176
  const preExisting = new Set(validateWorldData(world));
182
177
  const summary = modifications.map((modification) => applyOne(world, modification));
183
178
  // The engine statically casts world.json to Partial<GameData> (game/src/bundle/WorldDataLoader.ts),
184
- // so a non-conforming document breaks `tsc` in a file the creator cannot edit. game-play-agent's
185
- // applier has gated on this since it was written (`world-json-editor.ts`); this one did not, and
186
- // the two are meant to mirror each other case for case. It matters more here: by the time this
187
- // runs the design and geometry are already PAID FOR, so a bad batch left the creator with a
188
- // project that no longer builds and an error pointing at the engine rather than at the value.
179
+ // so a non-conforming document breaks `tsc` in a file the creator cannot edit. The gate matters
180
+ // more in this lane than in the web one: by the time it runs the design and geometry are already
181
+ // PAID FOR, so a bad batch would leave the creator with a project that no longer builds and an
182
+ // error pointing at the engine rather than at the offending value.
189
183
  //
190
184
  // Thrown BEFORE the rename, so world.json keeps whatever it had — the same guarantee every other
191
185
  // failure path in this function already makes.
@@ -1 +1 @@
1
- {"version":3,"file":"apply-modifications.js","sourceRoot":"","sources":["../../src/forge/apply-modifications.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apply-modifications.js","sourceRoot":"","sources":["../../src/forge/apply-modifications.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /** The config the scaffold vendors alongside `engine/`. */
2
+ export declare const VITE_PUBLISH_CONFIG = "vite.publish.config.js";
3
+ /**
4
+ * What was built, and from what.
5
+ *
6
+ * `fingerprint` is the same value `verify` records, which is what lets `publish` reuse an
7
+ * existing bundle instead of rebuilding: same inputs, same bundle.
8
+ */
9
+ export interface BuildManifest {
10
+ engineVersion: string;
11
+ fingerprint: string;
12
+ bytes: number;
13
+ /** Recorded for the publish audit trail. The server stores it; it cannot verify it. */
14
+ sha256: string;
15
+ builtAt: string;
16
+ }
17
+ export declare function buildBundlePaths(root: string): {
18
+ dir: string;
19
+ htmlPath: string;
20
+ manifestPath: string;
21
+ };
22
+ export declare function writeBuildManifest(root: string, manifest: BuildManifest): void;
23
+ /** The last build's manifest, or null if there is none to trust — same contract as readVerifyRecord. */
24
+ export declare function readBuildManifest(root: string): BuildManifest | null;
25
+ /**
26
+ * Compile and bundle the project into one self-contained HTML, and record what was built.
27
+ *
28
+ * Exit code 1 on failure, matching the table in the spec: a build failure is the creator's own
29
+ * code, and the compiler's output has already been printed.
30
+ */
31
+ export declare function runBuild(root: string, engineVersion: string): BuildManifest;
@@ -0,0 +1,77 @@
1
+ import { createHash } from 'crypto';
2
+ import { spawnSync } from 'child_process';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { CliError } from '../errors.js';
6
+ import { projectBin } from '../project/context.js';
7
+ import { computeFingerprint } from './fingerprint.js';
8
+ /** The config the scaffold vendors alongside `engine/`. */
9
+ export const VITE_PUBLISH_CONFIG = 'vite.publish.config.js';
10
+ export function buildBundlePaths(root) {
11
+ const dir = path.join(root, '.bitmagic', 'build');
12
+ return { dir, htmlPath: path.join(dir, 'index.html'), manifestPath: path.join(dir, 'manifest.json') };
13
+ }
14
+ export function writeBuildManifest(root, manifest) {
15
+ const { dir, manifestPath } = buildBundlePaths(root);
16
+ fs.mkdirSync(dir, { recursive: true });
17
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
18
+ }
19
+ function isManifest(value) {
20
+ if (typeof value !== 'object' || value === null)
21
+ return false;
22
+ const m = value;
23
+ return (typeof m.engineVersion === 'string'
24
+ && typeof m.fingerprint === 'string'
25
+ && typeof m.bytes === 'number'
26
+ && typeof m.sha256 === 'string'
27
+ && typeof m.builtAt === 'string');
28
+ }
29
+ /** The last build's manifest, or null if there is none to trust — same contract as readVerifyRecord. */
30
+ export function readBuildManifest(root) {
31
+ try {
32
+ const parsed = JSON.parse(fs.readFileSync(buildBundlePaths(root).manifestPath, 'utf-8'));
33
+ return isManifest(parsed) ? parsed : null;
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ /**
40
+ * Compile and bundle the project into one self-contained HTML, and record what was built.
41
+ *
42
+ * Exit code 1 on failure, matching the table in the spec: a build failure is the creator's own
43
+ * code, and the compiler's output has already been printed.
44
+ */
45
+ export function runBuild(root, engineVersion) {
46
+ const tsc = projectBin(root, 'tsc');
47
+ const compile = spawnSync(tsc, [], { cwd: root, stdio: 'inherit' });
48
+ if (compile.error)
49
+ throw new CliError(`Could not run the TypeScript compiler: ${compile.error.message}`, 1);
50
+ if (compile.status !== 0)
51
+ throw new CliError('Build failed: the project does not compile.', 1);
52
+ const { dir, htmlPath } = buildBundlePaths(root);
53
+ fs.mkdirSync(dir, { recursive: true });
54
+ const vite = projectBin(root, 'vite');
55
+ const bundle = spawnSync(vite, ['build', '--config', VITE_PUBLISH_CONFIG, '--outDir', dir, '--emptyOutDir'], {
56
+ cwd: root,
57
+ stdio: 'inherit',
58
+ });
59
+ if (bundle.error)
60
+ throw new CliError(`Could not run vite: ${bundle.error.message}`, 1);
61
+ if (bundle.status !== 0)
62
+ throw new CliError('Build failed: the bundle did not complete.', 1);
63
+ if (!fs.existsSync(htmlPath)) {
64
+ throw new CliError(`Build produced no ${path.relative(root, htmlPath)}. Check ${VITE_PUBLISH_CONFIG}.`, 1);
65
+ }
66
+ const contents = fs.readFileSync(htmlPath);
67
+ const manifest = {
68
+ engineVersion,
69
+ fingerprint: computeFingerprint(root),
70
+ bytes: contents.byteLength,
71
+ sha256: createHash('sha256').update(contents).digest('hex'),
72
+ builtAt: new Date().toISOString(),
73
+ };
74
+ writeBuildManifest(root, manifest);
75
+ return manifest;
76
+ }
77
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/publish/bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A relative path as the fingerprint hashes it: always forward-slashed.
3
+ *
4
+ * `sep` is a parameter rather than a direct `path.sep` read so this is testable on any
5
+ * platform — the Windows behaviour that makes normalization necessary cannot otherwise be
6
+ * exercised on the POSIX runners CI uses, which is exactly how a vacuous test gets written.
7
+ */
8
+ export declare function toPosixPath(relativePath: string, sep?: string): string;
9
+ /**
10
+ * A hash of everything that determines the published bundle.
11
+ *
12
+ * This is what lets `publish` decide whether a `verify` is too stale to trust, by CONTENT
13
+ * rather than by clock: a timestamp policy would accept an edit made one second after
14
+ * verifying and reject an untouched project that merely sat overnight.
15
+ *
16
+ * The path is hashed alongside the content so that moving a file — which changes what the
17
+ * bundle imports — changes the fingerprint even though no byte of any file did.
18
+ *
19
+ * Kept deliberately coarse (every tracked file, not a module graph): a false "stale" costs one
20
+ * `bitmagic verify`, while a false "fresh" ships an unverified bundle.
21
+ *
22
+ * Any filesystem error (unreadable directory, permission denied, etc.) propagates immediately
23
+ * rather than being silently omitted: the project source is the creator's own files, so an
24
+ * unreadable subtree is a real problem worth surfacing, not something to hide. An omitted
25
+ * directory would produce a fingerprint that matches a stale project — the costly failure mode.
26
+ */
27
+ export declare function computeFingerprint(root: string): string;
@@ -0,0 +1,64 @@
1
+ import { createHash } from 'crypto';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ /**
5
+ * Directories whose contents never change what the bundle contains: our own artifacts
6
+ * (`.bitmagic/`, `dist/`), the dependency tree (`node_modules/` — pinned by the lockfile the
7
+ * scaffold writes), and vite's cache. Including any of them would make the fingerprint change
8
+ * on every build, which would make the staleness gate reject every publish.
9
+ */
10
+ const EXCLUDED_DIRS = new Set(['.bitmagic', 'node_modules', 'dist', '.vite-cache']);
11
+ /**
12
+ * A relative path as the fingerprint hashes it: always forward-slashed.
13
+ *
14
+ * `sep` is a parameter rather than a direct `path.sep` read so this is testable on any
15
+ * platform — the Windows behaviour that makes normalization necessary cannot otherwise be
16
+ * exercised on the POSIX runners CI uses, which is exactly how a vacuous test gets written.
17
+ */
18
+ export function toPosixPath(relativePath, sep = path.sep) {
19
+ return relativePath.split(sep).join('/');
20
+ }
21
+ function walk(dir, root, out) {
22
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
23
+ for (const entry of entries) {
24
+ if (entry.isDirectory()) {
25
+ if (EXCLUDED_DIRS.has(entry.name))
26
+ continue;
27
+ walk(path.join(dir, entry.name), root, out);
28
+ }
29
+ else if (entry.isFile()) {
30
+ const relPath = path.relative(root, path.join(dir, entry.name));
31
+ out.push(toPosixPath(relPath));
32
+ }
33
+ }
34
+ }
35
+ /**
36
+ * A hash of everything that determines the published bundle.
37
+ *
38
+ * This is what lets `publish` decide whether a `verify` is too stale to trust, by CONTENT
39
+ * rather than by clock: a timestamp policy would accept an edit made one second after
40
+ * verifying and reject an untouched project that merely sat overnight.
41
+ *
42
+ * The path is hashed alongside the content so that moving a file — which changes what the
43
+ * bundle imports — changes the fingerprint even though no byte of any file did.
44
+ *
45
+ * Kept deliberately coarse (every tracked file, not a module graph): a false "stale" costs one
46
+ * `bitmagic verify`, while a false "fresh" ships an unverified bundle.
47
+ *
48
+ * Any filesystem error (unreadable directory, permission denied, etc.) propagates immediately
49
+ * rather than being silently omitted: the project source is the creator's own files, so an
50
+ * unreadable subtree is a real problem worth surfacing, not something to hide. An omitted
51
+ * directory would produce a fingerprint that matches a stale project — the costly failure mode.
52
+ */
53
+ export function computeFingerprint(root) {
54
+ const files = [];
55
+ walk(root, root, files);
56
+ files.sort();
57
+ const hash = createHash('sha256');
58
+ for (const rel of files) {
59
+ const content = fs.readFileSync(path.join(root, rel));
60
+ hash.update(`${rel}:${createHash('sha256').update(content).digest('hex')}\n`);
61
+ }
62
+ return hash.digest('hex');
63
+ }
64
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/publish/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;AAEpF;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB,EAAE,MAAc,IAAI,CAAC,GAAG;IACtE,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,IAAY,EAAE,GAAa;IACpD,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAChE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,KAAK,CAAC,IAAI,EAAE,CAAC;IAEb,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,28 @@
1
+ /** The subset of package.json this module reads — never the whole file. */
2
+ export interface PackageJsonDeps {
3
+ dependencies?: Record<string, string>;
4
+ devDependencies?: Record<string, string>;
5
+ }
6
+ export interface RequiredDependencies {
7
+ dependencies: Record<string, string>;
8
+ devDependencies: Record<string, string>;
9
+ }
10
+ export interface DependencyMismatch {
11
+ name: string;
12
+ kind: 'dependency' | 'devDependency';
13
+ required: string;
14
+ /** undefined when the package is missing from package.json entirely, not just outdated. */
15
+ current?: string;
16
+ }
17
+ /**
18
+ * Compares a project's declared dependencies against what the vendored engine actually needs
19
+ * (`DEPENDENCIES`/`DEV_DEPENDENCIES` in project-files.ts), and reports every mismatch — missing
20
+ * entirely, or present at a different version string.
21
+ *
22
+ * Pure and filesystem-free by design: `upgradeProject` never writes package.json (a creator's
23
+ * added dependencies must survive an upgrade untouched), so this is the other half of that
24
+ * decision — the mismatch it creates has to be *reported*, not silently left for `bitmagic build`
25
+ * to fail on later with an opaque module-resolution error. Kept separate from the command layer
26
+ * that reads package.json off disk so the comparison itself is testable without a fixture file.
27
+ */
28
+ export declare function diffDependencies(pkg: PackageJsonDeps, required: RequiredDependencies): DependencyMismatch[];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Compares a project's declared dependencies against what the vendored engine actually needs
3
+ * (`DEPENDENCIES`/`DEV_DEPENDENCIES` in project-files.ts), and reports every mismatch — missing
4
+ * entirely, or present at a different version string.
5
+ *
6
+ * Pure and filesystem-free by design: `upgradeProject` never writes package.json (a creator's
7
+ * added dependencies must survive an upgrade untouched), so this is the other half of that
8
+ * decision — the mismatch it creates has to be *reported*, not silently left for `bitmagic build`
9
+ * to fail on later with an opaque module-resolution error. Kept separate from the command layer
10
+ * that reads package.json off disk so the comparison itself is testable without a fixture file.
11
+ */
12
+ export function diffDependencies(pkg, required) {
13
+ const mismatches = [];
14
+ for (const [name, version] of Object.entries(required.dependencies)) {
15
+ const current = pkg.dependencies?.[name];
16
+ if (current !== version) {
17
+ mismatches.push({ name, kind: 'dependency', required: version, current });
18
+ }
19
+ }
20
+ for (const [name, version] of Object.entries(required.devDependencies)) {
21
+ const current = pkg.devDependencies?.[name];
22
+ if (current !== version) {
23
+ mismatches.push({ name, kind: 'devDependency', required: version, current });
24
+ }
25
+ }
26
+ return mismatches;
27
+ }
28
+ //# sourceMappingURL=dependency-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-diff.js","sourceRoot":"","sources":["../../src/scaffold/dependency-diff.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAoB,EAAE,QAA8B;IACnF,MAAM,UAAU,GAAyB,EAAE,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACvE,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -1,7 +1,29 @@
1
+ /**
2
+ * Mirrors game/package.json so the pro lane resolves exactly what CI builds against.
3
+ *
4
+ * Exported so `bitmagic upgrade` can diff a project's actual package.json against what the
5
+ * vendored engine currently needs — package.json itself is never rewritten (see
6
+ * PLATFORM_GENERATED_FILES in project.ts), so this is the only source of truth upgrade has for
7
+ * telling a creator what to add by hand.
8
+ */
9
+ export declare const DEPENDENCIES: Record<string, string>;
10
+ export declare const DEV_DEPENDENCIES: Record<string, string>;
1
11
  export declare function renderPackageJson(name: string): string;
2
12
  export declare function renderTsconfig(): string;
3
13
  export declare function renderIndexHtml(): string;
4
14
  export declare function renderViteConfig(): string;
15
+ /**
16
+ * The production bundle config, vendored into the project next to `engine/`.
17
+ *
18
+ * One self-contained HTML: `viteSingleFile` with an effectively unlimited inline limit, so the
19
+ * engine and all JS/CSS land inside index.html. Game ASSETS are deliberately NOT inlined — they
20
+ * already live on the CDN with absolute URLs, and inlining them is what produced multi-hundred-MB
21
+ * bundles and OOM-killed the web publish pod.
22
+ *
23
+ * Vendored rather than generated per-build so a creator can read exactly what ships, and so it
24
+ * versions with the engine it was written for.
25
+ */
26
+ export declare function renderVitePublishConfig(): string;
5
27
  export declare function renderGitignore(): string;
6
28
  export interface ProjectMetadata {
7
29
  gameId: string;
@@ -1,6 +1,13 @@
1
1
  import { tsconfigPaths, importMapEntries, viteAliasEntries } from './aliases.js';
2
- /** Mirrors game/package.json so the pro lane resolves exactly what CI builds against. */
3
- const DEPENDENCIES = {
2
+ /**
3
+ * Mirrors game/package.json so the pro lane resolves exactly what CI builds against.
4
+ *
5
+ * Exported so `bitmagic upgrade` can diff a project's actual package.json against what the
6
+ * vendored engine currently needs — package.json itself is never rewritten (see
7
+ * PLATFORM_GENERATED_FILES in project.ts), so this is the only source of truth upgrade has for
8
+ * telling a creator what to add by hand.
9
+ */
10
+ export const DEPENDENCIES = {
4
11
  '@dimforge/rapier2d-compat': '^0.19.3',
5
12
  '@dimforge/rapier3d-compat': '^0.19.3',
6
13
  '@msgpack/msgpack': '^3.1.3',
@@ -10,7 +17,7 @@ const DEPENDENCIES = {
10
17
  jszip: '^3.10.1',
11
18
  three: '^0.185.1',
12
19
  };
13
- const DEV_DEPENDENCIES = {
20
+ export const DEV_DEPENDENCIES = {
14
21
  '@types/node': '^24.10.0',
15
22
  '@types/three': '^0.185.4',
16
23
  // engine/types/ammo.d.ts opens with a triple-slash reference to this package's ambient types.
@@ -20,6 +27,7 @@ const DEV_DEPENDENCIES = {
20
27
  '@webgpu/types': '^0.1.69',
21
28
  typescript: '^5.9.2',
22
29
  vite: '^7.3.1',
30
+ 'vite-plugin-singlefile': '^2.3.3',
23
31
  };
24
32
  /**
25
33
  * The three.js release every `three*` import map entry below resolves to. Written once because
@@ -185,10 +193,19 @@ ${JSON.stringify({ imports }, null, 8).replace(/^/gm, ' ')}
185
193
  </html>
186
194
  `;
187
195
  }
188
- export function renderViteConfig() {
189
- const entries = Object.entries(viteAliasEntries())
196
+ /**
197
+ * The `resolve.alias` body shared by both vendored vite configs (this one and the publish
198
+ * config below): one `'key': 'target'` line per alias, comma-joined, indented to sit inside a
199
+ * template literal's `alias: { ... }` block. Kept in one place so the two configs' aliases
200
+ * cannot drift into two different renderings of the same `viteAliasEntries()` data.
201
+ */
202
+ function renderAliasEntries() {
203
+ return Object.entries(viteAliasEntries())
190
204
  .map(([key, target]) => ` '${key}': '${target}'`)
191
205
  .join(',\n');
206
+ }
207
+ export function renderViteConfig() {
208
+ const entries = renderAliasEntries();
192
209
  return `import { defineConfig } from 'vite';
193
210
 
194
211
  // Aliases mirror tsconfig paths but point at the COMPILED output: tsc emits to dist/ and the
@@ -209,6 +226,50 @@ ${entries}
209
226
  });
210
227
  `;
211
228
  }
229
+ /**
230
+ * The production bundle config, vendored into the project next to `engine/`.
231
+ *
232
+ * One self-contained HTML: `viteSingleFile` with an effectively unlimited inline limit, so the
233
+ * engine and all JS/CSS land inside index.html. Game ASSETS are deliberately NOT inlined — they
234
+ * already live on the CDN with absolute URLs, and inlining them is what produced multi-hundred-MB
235
+ * bundles and OOM-killed the web publish pod.
236
+ *
237
+ * Vendored rather than generated per-build so a creator can read exactly what ships, and so it
238
+ * versions with the engine it was written for.
239
+ */
240
+ export function renderVitePublishConfig() {
241
+ const entries = renderAliasEntries();
242
+ return `import { defineConfig } from 'vite';
243
+ import { viteSingleFile } from 'vite-plugin-singlefile';
244
+
245
+ // Aliases mirror vite.config.js's, deliberately NOT wrapped in path.resolve(): every target here
246
+ // already starts with '/', which Vite resolves as project-root-relative in both serve and build
247
+ // mode. A path.resolve(__dirname, target) wrapper looks more "correct" but is actively wrong —
248
+ // Node's path.resolve() drops the trailing slash from an already-absolute second argument, and
249
+ // Vite's directory-style alias substitution needs that slash to join the replacement with the
250
+ // rest of the specifier. Strip it and 'engine/GameTemplate.js' resolves to the nonexistent
251
+ // 'dist/engine/engineGameTemplate.js' instead of 'dist/engine/engine/GameTemplate.js' — silently,
252
+ // since Rollup then just treats the unmatched id as an unresolved bare specifier and fails the
253
+ // build. Verified against a real \`vite build\` before trusting the plain-string form.
254
+ export default defineConfig({
255
+ resolve: {
256
+ alias: {
257
+ ${entries}
258
+ }
259
+ },
260
+ build: {
261
+ // Effectively unlimited: everything the bundle references locally is inlined so the
262
+ // published artifact is a single file. CDN assets are absolute URLs and are untouched.
263
+ assetsInlineLimit: 100000000,
264
+ cssCodeSplit: false,
265
+ rollupOptions: {
266
+ output: { inlineDynamicImports: true },
267
+ },
268
+ },
269
+ plugins: [viteSingleFile()],
270
+ });
271
+ `;
272
+ }
212
273
  export function renderGitignore() {
213
274
  return ['dist/', 'node_modules/', '.bitmagic/', '.vite-cache/', ''].join('\n');
214
275
  }
@@ -1 +1 @@
1
- {"version":3,"file":"project-files.js","sourceRoot":"","sources":["../../src/scaffold/project-files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-files.js","sourceRoot":"","sources":["../../src/scaffold/project-files.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,23 @@ export interface TemplateEntry {
15
15
  * parallel copy that silently goes stale when an entry is added here.
16
16
  */
17
17
  export declare const VENDORED_DIRS: string[];
18
+ /**
19
+ * The subset of the generated files that are pure platform output: regenerated byte-for-byte
20
+ * from these renderers with no creator content ever entering them. `bitmagic upgrade` overwrites
21
+ * exactly this list (plus bitmagic.json, handled separately since only its engineVersion field is
22
+ * platform-owned, and engine/ + sw-cache-buster.js, handled separately since they are copied, not
23
+ * rendered).
24
+ *
25
+ * Deliberately excludes package.json (creators add dependencies to it), AGENTS.md/CLAUDE.md (the
26
+ * creator's own agent reads and may edit them), and .gitignore (same reasoning) — those are
27
+ * generated once by `scaffoldProject` but are creator-owned from that point on.
28
+ *
29
+ * Exported so `scaffoldProject` and `upgradeProject` share one definition instead of two lists
30
+ * that can drift — the exact failure that motivated this: `vite.publish.config.js` was added
31
+ * to init's inline list with no equivalent path for existing projects to ever receive it, because
32
+ * `upgrade` didn't exist yet.
33
+ */
34
+ export declare const PLATFORM_GENERATED_FILES: Array<[string, () => string]>;
18
35
  export declare function resolveTemplate(templatesDir: string, requestedId?: string): TemplateEntry;
19
36
  export interface ScaffoldOptions {
20
37
  targetDir: string;
@@ -2,7 +2,7 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { CliError } from '../errors.js';
4
4
  import { aliasSourceDir } from './aliases.js';
5
- import { renderPackageJson, renderTsconfig, renderIndexHtml, renderViteConfig, renderGitignore, renderBitmagicJson, renderAgentsMd, renderClaudeMd, renderSkillsReadme, renderGenerateSkill, } from './project-files.js';
5
+ import { renderPackageJson, renderTsconfig, renderIndexHtml, renderViteConfig, renderVitePublishConfig, renderGitignore, renderBitmagicJson, renderAgentsMd, renderClaudeMd, renderSkillsReadme, renderGenerateSkill, } from './project-files.js';
6
6
  /**
7
7
  * Directories moved out of the extracted tree into the project's vendored engine/.
8
8
  *
@@ -24,6 +24,28 @@ export const VENDORED_DIRS = [
24
24
  'utils',
25
25
  'core',
26
26
  ];
27
+ /**
28
+ * The subset of the generated files that are pure platform output: regenerated byte-for-byte
29
+ * from these renderers with no creator content ever entering them. `bitmagic upgrade` overwrites
30
+ * exactly this list (plus bitmagic.json, handled separately since only its engineVersion field is
31
+ * platform-owned, and engine/ + sw-cache-buster.js, handled separately since they are copied, not
32
+ * rendered).
33
+ *
34
+ * Deliberately excludes package.json (creators add dependencies to it), AGENTS.md/CLAUDE.md (the
35
+ * creator's own agent reads and may edit them), and .gitignore (same reasoning) — those are
36
+ * generated once by `scaffoldProject` but are creator-owned from that point on.
37
+ *
38
+ * Exported so `scaffoldProject` and `upgradeProject` share one definition instead of two lists
39
+ * that can drift — the exact failure that motivated this: `vite.publish.config.js` was added
40
+ * to init's inline list with no equivalent path for existing projects to ever receive it, because
41
+ * `upgrade` didn't exist yet.
42
+ */
43
+ export const PLATFORM_GENERATED_FILES = [
44
+ ['tsconfig.json', renderTsconfig],
45
+ ['vite.config.js', renderViteConfig],
46
+ ['vite.publish.config.js', renderVitePublishConfig],
47
+ ['index.html', renderIndexHtml],
48
+ ];
27
49
  export function resolveTemplate(templatesDir, requestedId) {
28
50
  const indexPath = path.join(templatesDir, 'index.json');
29
51
  let raw;
@@ -98,9 +120,7 @@ export function scaffoldProject(options) {
98
120
  }
99
121
  const files = [
100
122
  ['package.json', renderPackageJson(projectName)],
101
- ['tsconfig.json', renderTsconfig()],
102
- ['vite.config.js', renderViteConfig()],
103
- ['index.html', renderIndexHtml()],
123
+ ...PLATFORM_GENERATED_FILES.map((entry) => [entry[0], entry[1]()]),
104
124
  ['bitmagic.json', renderBitmagicJson(metadata)],
105
125
  ['AGENTS.md', renderAgentsMd()],
106
126
  ['CLAUDE.md', renderClaudeMd()],
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/scaffold/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/scaffold/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export interface UpgradeOptions {
2
+ root: string;
3
+ /** Where extractEngine unpacked the new engine tree, same shape scaffoldProject reads from. */
4
+ extractedEngineDir: string;
5
+ /** The engine version being upgraded to, written into bitmagic.json's engineVersion field. */
6
+ engineVersion: string;
7
+ }
8
+ export interface UpgradeResult {
9
+ engineVersion: string;
10
+ previousEngineVersion: string;
11
+ /** Every top-level path this run actually rewrote, in the order it rewrote them. */
12
+ replaced: string[];
13
+ }
14
+ /**
15
+ * Refreshes the platform-owned parts of a scaffolded project in place, and nothing else. This is
16
+ * the file-boundary described in the task brief: `engine/` (every VENDORED_DIRS entry) and
17
+ * sw-cache-buster.js are wholesale-replaced, the config files in PLATFORM_GENERATED_FILES are
18
+ * re-rendered, and bitmagic.json is read-modified-written so only its engineVersion field
19
+ * changes. Everything else on disk — src/, world.json, game.json, package.json, AGENTS.md,
20
+ * CLAUDE.md, .claude/, .gitignore — is never opened.
21
+ *
22
+ * Mirrors scaffoldProject's copy behaviour (same VENDORED_DIRS loop, same corrupt-tarball error
23
+ * when a directory is missing from the extracted tree), except it clears engine/ first: unlike a
24
+ * brand new project's empty target, an existing engine/ may hold files a since-removed
25
+ * VENDORED_DIRS entry left behind, or a leftover from a bad manual edit, and cpSync alone would
26
+ * merge over those rather than remove them.
27
+ *
28
+ * That "clear first" step is exactly why every VENDORED_DIRS source is validated to exist
29
+ * *before* engine/ is touched at all, in its own pass below: scaffoldProject can afford to check
30
+ * existence inside its copy loop because its target starts empty, so a missing source just leaves
31
+ * a partially-populated (but otherwise harmless) new directory. Here the target is a live
32
+ * project's engine/, already rm'd — the same ordering would demolish it and fail partway through
33
+ * repopulating it, and a project not under version control has no way to recover that.
34
+ */
35
+ export declare function upgradeProject(options: UpgradeOptions): UpgradeResult;
@@ -0,0 +1,63 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { CliError } from '../errors.js';
4
+ import { VENDORED_DIRS, PLATFORM_GENERATED_FILES } from './project.js';
5
+ /**
6
+ * Refreshes the platform-owned parts of a scaffolded project in place, and nothing else. This is
7
+ * the file-boundary described in the task brief: `engine/` (every VENDORED_DIRS entry) and
8
+ * sw-cache-buster.js are wholesale-replaced, the config files in PLATFORM_GENERATED_FILES are
9
+ * re-rendered, and bitmagic.json is read-modified-written so only its engineVersion field
10
+ * changes. Everything else on disk — src/, world.json, game.json, package.json, AGENTS.md,
11
+ * CLAUDE.md, .claude/, .gitignore — is never opened.
12
+ *
13
+ * Mirrors scaffoldProject's copy behaviour (same VENDORED_DIRS loop, same corrupt-tarball error
14
+ * when a directory is missing from the extracted tree), except it clears engine/ first: unlike a
15
+ * brand new project's empty target, an existing engine/ may hold files a since-removed
16
+ * VENDORED_DIRS entry left behind, or a leftover from a bad manual edit, and cpSync alone would
17
+ * merge over those rather than remove them.
18
+ *
19
+ * That "clear first" step is exactly why every VENDORED_DIRS source is validated to exist
20
+ * *before* engine/ is touched at all, in its own pass below: scaffoldProject can afford to check
21
+ * existence inside its copy loop because its target starts empty, so a missing source just leaves
22
+ * a partially-populated (but otherwise harmless) new directory. Here the target is a live
23
+ * project's engine/, already rm'd — the same ordering would demolish it and fail partway through
24
+ * repopulating it, and a project not under version control has no way to recover that.
25
+ */
26
+ export function upgradeProject(options) {
27
+ const { root, extractedEngineDir, engineVersion } = options;
28
+ const replaced = [];
29
+ for (const dir of VENDORED_DIRS) {
30
+ const source = path.join(extractedEngineDir, dir);
31
+ if (!fs.existsSync(source)) {
32
+ throw new CliError(`The engine bundle has no "${dir}" directory at ${source}. The tarball is incomplete or corrupt.`);
33
+ }
34
+ }
35
+ const engineDir = path.join(root, 'engine');
36
+ fs.rmSync(engineDir, { recursive: true, force: true });
37
+ fs.mkdirSync(engineDir, { recursive: true });
38
+ for (const dir of VENDORED_DIRS) {
39
+ fs.cpSync(path.join(extractedEngineDir, dir), path.join(engineDir, dir), { recursive: true });
40
+ }
41
+ replaced.push('engine/');
42
+ // Same "missing is not corrupt" allowance as scaffoldProject: a tarball published before this
43
+ // feature shipped simply won't have it, and upgrade must not fail a project onto that tarball.
44
+ const serviceWorker = path.join(extractedEngineDir, 'sw-cache-buster.js');
45
+ if (fs.existsSync(serviceWorker)) {
46
+ fs.cpSync(serviceWorker, path.join(root, 'sw-cache-buster.js'));
47
+ replaced.push('sw-cache-buster.js');
48
+ }
49
+ for (const [name, render] of PLATFORM_GENERATED_FILES) {
50
+ fs.writeFileSync(path.join(root, name), render());
51
+ replaced.push(name);
52
+ }
53
+ // Read-modify-write, not re-rendered from renderBitmagicJson: re-rendering would discard any
54
+ // field a later CLI/engine version adds to the metadata that this version doesn't know about.
55
+ const bitmagicJsonPath = path.join(root, 'bitmagic.json');
56
+ const meta = JSON.parse(fs.readFileSync(bitmagicJsonPath, 'utf-8'));
57
+ const previousEngineVersion = typeof meta.engineVersion === 'string' ? meta.engineVersion : '';
58
+ meta.engineVersion = engineVersion;
59
+ fs.writeFileSync(bitmagicJsonPath, `${JSON.stringify(meta, null, 2)}\n`);
60
+ replaced.push('bitmagic.json');
61
+ return { engineVersion, previousEngineVersion, replaced };
62
+ }
63
+ //# sourceMappingURL=upgrade-project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-project.js","sourceRoot":"","sources":["../../src/scaffold/upgrade-project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { VerifyResult } from './classify.js';
2
+ export declare const VERIFY_RESULT_FILENAME = "result.json";
3
+ /**
4
+ * What `bitmagic verify` observed, written so `bitmagic publish` can gate on it.
5
+ *
6
+ * `fingerprint` is what makes the record trustworthy later: it names the exact project state
7
+ * that was verified, so publish can tell "verified and unchanged" from "verified, then edited".
8
+ */
9
+ export interface VerifyRunRecord {
10
+ ok: boolean;
11
+ failures: string[];
12
+ warnings: string[];
13
+ fingerprint: string;
14
+ /** ISO 8601. Reported to the creator; never used to decide staleness. */
15
+ at: string;
16
+ }
17
+ export declare function writeVerifyRecord(artifactDir: string, record: VerifyRunRecord): void;
18
+ /**
19
+ * The last recorded run, or `null` if there is none to trust.
20
+ *
21
+ * Unreadable and malformed both read as null on purpose. This is not swallowing an error: the
22
+ * caller's next move is identical in all three cases — tell the creator to run `bitmagic
23
+ * verify` — and a partially-parsed record would be a worse thing to gate a publish on than no
24
+ * record at all.
25
+ */
26
+ export declare function readVerifyRecord(artifactDir: string): VerifyRunRecord | null;
27
+ /**
28
+ * What a classified verify run produces: the record to write, and whether the command then
29
+ * fails.
30
+ *
31
+ * Split out of the command so the ORDER is testable. The record must be written even when the
32
+ * run failed — publish distinguishes "verify failed" from "verify never ran", and those have
33
+ * different messages and different remedies. Inside `run()` that ordering is only observable by
34
+ * spawning vite and a browser, which is why it went unguarded.
35
+ */
36
+ export declare function decideVerifyOutcome(result: VerifyResult, fingerprint: string, at: string): {
37
+ record: VerifyRunRecord;
38
+ shouldThrow: boolean;
39
+ };
40
+ export interface VerifyReporter {
41
+ write: (artifactDir: string, record: VerifyRunRecord) => void;
42
+ info: (line: string) => void;
43
+ error: (line: string) => void;
44
+ }
45
+ /**
46
+ * Record the run, report it, and fail the command if it did not pass.
47
+ *
48
+ * The record is written BEFORE the throw and regardless of the verdict, because publish
49
+ * distinguishes "verify failed" from "verify never ran" and those have different remedies.
50
+ * That ordering lives here, behind injectable seams, precisely so a test can prove the record
51
+ * survives a failing run — inside `run()` it was observable only by spawning vite and a browser,
52
+ * which is why it went unguarded.
53
+ */
54
+ export declare function recordAndGateVerify(artifactDir: string, outcome: {
55
+ record: VerifyRunRecord;
56
+ shouldThrow: boolean;
57
+ }, paths: {
58
+ consolePath: string;
59
+ screenshotPath: string;
60
+ }, reporter: VerifyReporter): void;
@@ -0,0 +1,74 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { CliError } from '../errors.js';
4
+ export const VERIFY_RESULT_FILENAME = 'result.json';
5
+ export function writeVerifyRecord(artifactDir, record) {
6
+ fs.mkdirSync(artifactDir, { recursive: true });
7
+ fs.writeFileSync(path.join(artifactDir, VERIFY_RESULT_FILENAME), `${JSON.stringify(record, null, 2)}\n`);
8
+ }
9
+ function isRecord(value) {
10
+ if (typeof value !== 'object' || value === null)
11
+ return false;
12
+ const r = value;
13
+ return (typeof r.ok === 'boolean'
14
+ && Array.isArray(r.failures)
15
+ && r.failures.every((f) => typeof f === 'string')
16
+ && Array.isArray(r.warnings)
17
+ && r.warnings.every((w) => typeof w === 'string')
18
+ && typeof r.fingerprint === 'string'
19
+ && typeof r.at === 'string');
20
+ }
21
+ /**
22
+ * The last recorded run, or `null` if there is none to trust.
23
+ *
24
+ * Unreadable and malformed both read as null on purpose. This is not swallowing an error: the
25
+ * caller's next move is identical in all three cases — tell the creator to run `bitmagic
26
+ * verify` — and a partially-parsed record would be a worse thing to gate a publish on than no
27
+ * record at all.
28
+ */
29
+ export function readVerifyRecord(artifactDir) {
30
+ try {
31
+ const parsed = JSON.parse(fs.readFileSync(path.join(artifactDir, VERIFY_RESULT_FILENAME), 'utf-8'));
32
+ return isRecord(parsed) ? parsed : null;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /**
39
+ * What a classified verify run produces: the record to write, and whether the command then
40
+ * fails.
41
+ *
42
+ * Split out of the command so the ORDER is testable. The record must be written even when the
43
+ * run failed — publish distinguishes "verify failed" from "verify never ran", and those have
44
+ * different messages and different remedies. Inside `run()` that ordering is only observable by
45
+ * spawning vite and a browser, which is why it went unguarded.
46
+ */
47
+ export function decideVerifyOutcome(result, fingerprint, at) {
48
+ return {
49
+ record: { ok: result.ok, failures: result.failures, warnings: result.warnings, fingerprint, at },
50
+ shouldThrow: !result.ok,
51
+ };
52
+ }
53
+ /**
54
+ * Record the run, report it, and fail the command if it did not pass.
55
+ *
56
+ * The record is written BEFORE the throw and regardless of the verdict, because publish
57
+ * distinguishes "verify failed" from "verify never ran" and those have different remedies.
58
+ * That ordering lives here, behind injectable seams, precisely so a test can prove the record
59
+ * survives a failing run — inside `run()` it was observable only by spawning vite and a browser,
60
+ * which is why it went unguarded.
61
+ */
62
+ export function recordAndGateVerify(artifactDir, outcome, paths, reporter) {
63
+ reporter.write(artifactDir, outcome.record);
64
+ for (const warning of outcome.record.warnings)
65
+ reporter.info(`warning: ${warning}`);
66
+ if (outcome.shouldThrow) {
67
+ for (const failure of outcome.record.failures)
68
+ reporter.error(`✗ ${failure}`);
69
+ reporter.error(`\nArtifacts: ${paths.consolePath}, ${paths.screenshotPath}`);
70
+ throw new CliError('Verification failed.');
71
+ }
72
+ reporter.info(`Verification passed. Artifacts in ${artifactDir}`);
73
+ }
74
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/verify/result.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitmagic/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Build Bitmagic games from your own agent tool",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,8 +19,8 @@
19
19
  "citty": "^0.2.2",
20
20
  "playwright-core": "^1.59.1",
21
21
  "tar": "^7.4.3",
22
- "@bitmagic/asset-core": "0.1.0",
23
- "@bitmagic/world-forger": "0.1.3"
22
+ "@bitmagic/world-forger": "0.1.3",
23
+ "@bitmagic/asset-core": "0.1.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@eslint/js": "^9.38.0",