@bitmagic/cli 0.1.55-dev.0 → 0.1.55-dev.1

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 (70) hide show
  1. package/README.md +43 -2
  2. package/dist/cli.d.ts +23 -1
  3. package/dist/cli.js +4 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/cover.d.ts +13 -2
  6. package/dist/commands/cover.js +21 -7
  7. package/dist/commands/cover.js.map +1 -1
  8. package/dist/commands/forge.d.ts +14 -0
  9. package/dist/commands/forge.js +41 -3
  10. package/dist/commands/forge.js.map +1 -1
  11. package/dist/commands/generate.d.ts +12 -0
  12. package/dist/commands/generate.js +77 -24
  13. package/dist/commands/generate.js.map +1 -1
  14. package/dist/commands/init.js +4 -0
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/ios.d.ts +2 -0
  17. package/dist/commands/ios.js +333 -0
  18. package/dist/commands/ios.js.map +1 -0
  19. package/dist/commands/reference.d.ts +41 -0
  20. package/dist/commands/reference.js +398 -0
  21. package/dist/commands/reference.js.map +1 -0
  22. package/dist/generate/stream.d.ts +6 -0
  23. package/dist/generate/stream.js +2 -1
  24. package/dist/generate/stream.js.map +1 -1
  25. package/dist/ios/app-config.d.ts +54 -0
  26. package/dist/ios/app-config.js +109 -0
  27. package/dist/ios/app-config.js.map +1 -0
  28. package/dist/ios/collect-urls.d.ts +73 -0
  29. package/dist/ios/collect-urls.js +230 -0
  30. package/dist/ios/collect-urls.js.map +1 -0
  31. package/dist/ios/icon.d.ts +12 -0
  32. package/dist/ios/icon.js +70 -0
  33. package/dist/ios/icon.js.map +1 -0
  34. package/dist/ios/local-server.d.ts +11 -0
  35. package/dist/ios/local-server.js +88 -0
  36. package/dist/ios/local-server.js.map +1 -0
  37. package/dist/ios/paths.d.ts +21 -0
  38. package/dist/ios/paths.js +23 -0
  39. package/dist/ios/paths.js.map +1 -0
  40. package/dist/ios/record-validate.d.ts +25 -0
  41. package/dist/ios/record-validate.js +98 -0
  42. package/dist/ios/record-validate.js.map +1 -0
  43. package/dist/ios/transform.d.ts +47 -0
  44. package/dist/ios/transform.js +67 -0
  45. package/dist/ios/transform.js.map +1 -0
  46. package/dist/ios/vendor.d.ts +29 -0
  47. package/dist/ios/vendor.js +113 -0
  48. package/dist/ios/vendor.js.map +1 -0
  49. package/dist/ios/xcode-template.d.ts +11 -0
  50. package/dist/ios/xcode-template.js +615 -0
  51. package/dist/ios/xcode-template.js.map +1 -0
  52. package/dist/ios/xcodebuild.d.ts +71 -0
  53. package/dist/ios/xcodebuild.js +216 -0
  54. package/dist/ios/xcodebuild.js.map +1 -0
  55. package/dist/project/jobs.d.ts +1 -1
  56. package/dist/project/reference-file.d.ts +44 -0
  57. package/dist/project/reference-file.js +94 -0
  58. package/dist/project/reference-file.js.map +1 -0
  59. package/dist/project/reference.d.ts +78 -0
  60. package/dist/project/reference.js +175 -0
  61. package/dist/project/reference.js.map +1 -0
  62. package/dist/scaffold/project-files.js +19 -16
  63. package/dist/scaffold/project-files.js.map +1 -1
  64. package/dist/scaffold/reference-guidance.d.ts +20 -0
  65. package/dist/scaffold/reference-guidance.js +79 -0
  66. package/dist/scaffold/reference-guidance.js.map +1 -0
  67. package/dist/verify/browser.d.ts +8 -0
  68. package/dist/verify/browser.js +2 -0
  69. package/dist/verify/browser.js.map +1 -1
  70. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-config.js","sourceRoot":"","sources":["../../src/ios/app-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ export interface CollectedUrls {
2
+ /** Every absolute URL to vendor. */
3
+ urls: Set<string>;
4
+ /**
5
+ * Base-URL constants the engine concatenates file names onto (`${base}/${file}`). Rewriting
6
+ * these in the bundle makes runtime-constructed URLs resolve into the mirrored vendor tree,
7
+ * which no exact-URL map entry could cover.
8
+ */
9
+ bases: Set<string>;
10
+ /** Creator-facing lines about what was (or could not be) collected. */
11
+ notes: string[];
12
+ }
13
+ /** Walk any JSON value, collecting remote-URL strings outside the deny-listed fields. */
14
+ export declare function deepWalkUrls(value: unknown, out: Set<string>): void;
15
+ /** The same compiled-code .glb scan the standalone lane runs, over the pro project's dist. */
16
+ export declare function scanCompiledCodeUrls(compiledCode: string): Set<string>;
17
+ /** All compiled game JS under dist/src/work, concatenated — for reference scans. */
18
+ export declare function readCompiledGameCode(root: string): string;
19
+ interface AnimationEntry {
20
+ file: string;
21
+ motionId: string;
22
+ }
23
+ interface WeaponAnimationEntry {
24
+ url: string;
25
+ motionId: string;
26
+ }
27
+ /** The shape of `animationAssets` this collector relies on — structural, checked at runtime. */
28
+ export interface AnimationAssetsData {
29
+ activeLibrary: 'cdn' | 'generated';
30
+ animationBaseUrl: string;
31
+ generatedAnimationBaseUrl: string;
32
+ animalBaseUrl: string;
33
+ voxelAnimalBaseUrl: string;
34
+ voxelFishBaseUrl: string;
35
+ characterUrls: {
36
+ default: string;
37
+ defaultFallback: string;
38
+ };
39
+ coreAnimations: AnimationEntry[];
40
+ generatedAnimations: AnimationEntry[];
41
+ meleeWeaponAnimations: WeaponAnimationEntry[];
42
+ generatedMeleeWeaponAnimations: AnimationEntry[];
43
+ generatedRangedWeaponAnimations: AnimationEntry[];
44
+ generatedDirectionalAnimations: AnimationEntry[];
45
+ generatedPostureAnimations: AnimationEntry[];
46
+ animalSkeletons: Record<string, string>;
47
+ }
48
+ /**
49
+ * Import the vendored engine's compiled AnimationAssets — a pure data module with no imports,
50
+ * which is what makes this safe from plain node. Null (with the caller noting it) when the
51
+ * engine predates the module or the shape moved: the record pass still catches whatever the
52
+ * running game actually fetches.
53
+ */
54
+ export declare function loadAnimationAssets(root: string): Promise<AnimationAssetsData | null>;
55
+ interface WorldDataShape {
56
+ worldProfileData?: {
57
+ hasPlayerCharacter?: unknown;
58
+ animals?: unknown;
59
+ };
60
+ }
61
+ /**
62
+ * The built-in animation URLs this game can load. The ACTIVE library ships whole — its optional
63
+ * packs (melee/ranged/directional/posture) are loaded on demand by engine systems whose names
64
+ * game code never contains, so reference-scanning cannot bound them. The inactive library ships
65
+ * only clips the compiled game code names (`getBuiltinAnimationDef` resolves ids from either).
66
+ */
67
+ export declare function collectAnimationUrls(assets: AnimationAssetsData, worldData: WorldDataShape, compiledCode: string): {
68
+ urls: Set<string>;
69
+ bases: Set<string>;
70
+ };
71
+ /** The full §4b collection: deep walk + compiled-code scan + built-in animation surface. */
72
+ export declare function collectUrls(root: string): Promise<CollectedUrls>;
73
+ export {};
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Every remote URL the packaged game may load, collected up front (§4b of
3
+ * docs/ios-export-design.md).
4
+ *
5
+ * Deliberately NOT a port of game/scripts/generate-asset-manifest.mjs's field list — that list
6
+ * demonstrably misses fields the engine loads (glb/gltf assets by id, lodVariants, splat
7
+ * configs, heightmaps, HUD images, three of the four animation packs). Instead the work-copy
8
+ * JSON is deep-walked for anything URL-shaped, with a small deny-list of fields that never load
9
+ * at runtime. An unknown future URL field is vendored by default: too much beats a network
10
+ * fetch on a device in airplane mode.
11
+ *
12
+ * The record pass (record-validate.ts) is the empirical net under all of this — anything the
13
+ * running game fetches that this module missed still gets vendored.
14
+ */
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+ import { pathToFileURL } from 'url';
18
+ import { aliasSourceDir } from '../scaffold/aliases.js';
19
+ /** Fields whose URLs are editor/publish provenance, never loaded by the running game. */
20
+ const DENY_FIELDS = new Set([
21
+ 'screenshotUrl',
22
+ 'thumbnailUrl',
23
+ 'thumbnailUrlOverride',
24
+ 'faviconUrlOverride',
25
+ 'sourceGlbUrl',
26
+ 'sourceModelUrl',
27
+ 'sourceVxlMasterUrl',
28
+ 'sourceUrl',
29
+ ]);
30
+ function isRemoteUrl(value) {
31
+ return /^https?:\/\/[^\s"']+$/.test(value);
32
+ }
33
+ /** Walk any JSON value, collecting remote-URL strings outside the deny-listed fields. */
34
+ export function deepWalkUrls(value, out) {
35
+ if (typeof value === 'string') {
36
+ if (isRemoteUrl(value))
37
+ out.add(value);
38
+ return;
39
+ }
40
+ if (Array.isArray(value)) {
41
+ for (const item of value)
42
+ deepWalkUrls(item, out);
43
+ return;
44
+ }
45
+ if (typeof value === 'object' && value !== null) {
46
+ for (const [key, child] of Object.entries(value)) {
47
+ if (DENY_FIELDS.has(key))
48
+ continue;
49
+ deepWalkUrls(child, out);
50
+ }
51
+ }
52
+ }
53
+ /** The same compiled-code .glb scan the standalone lane runs, over the pro project's dist. */
54
+ export function scanCompiledCodeUrls(compiledCode) {
55
+ const urls = new Set();
56
+ for (const match of compiledCode.match(/https?:\/\/[^"'`\s)\\]+\.glb\b/g) ?? []) {
57
+ urls.add(match);
58
+ }
59
+ return urls;
60
+ }
61
+ /** All compiled game JS under dist/src/work, concatenated — for reference scans. */
62
+ export function readCompiledGameCode(root) {
63
+ const workDir = path.join(root, 'dist', aliasSourceDir('work'));
64
+ let combined = '';
65
+ const walk = (dir) => {
66
+ let entries;
67
+ try {
68
+ entries = fs.readdirSync(dir, { withFileTypes: true });
69
+ }
70
+ catch {
71
+ return;
72
+ }
73
+ for (const entry of entries) {
74
+ const full = path.join(dir, entry.name);
75
+ if (entry.isDirectory())
76
+ walk(full);
77
+ else if (entry.name.endsWith('.js'))
78
+ combined += fs.readFileSync(full, 'utf-8');
79
+ }
80
+ };
81
+ walk(workDir);
82
+ return combined;
83
+ }
84
+ function isAnimationAssets(value) {
85
+ if (typeof value !== 'object' || value === null)
86
+ return false;
87
+ const record = value;
88
+ return (typeof record.animationBaseUrl === 'string'
89
+ && typeof record.generatedAnimationBaseUrl === 'string'
90
+ && typeof record.characterUrls === 'object'
91
+ && Array.isArray(record.coreAnimations));
92
+ }
93
+ /**
94
+ * Import the vendored engine's compiled AnimationAssets — a pure data module with no imports,
95
+ * which is what makes this safe from plain node. Null (with the caller noting it) when the
96
+ * engine predates the module or the shape moved: the record pass still catches whatever the
97
+ * running game actually fetches.
98
+ */
99
+ export async function loadAnimationAssets(root) {
100
+ const compiled = path.join(root, 'dist', 'engine', 'engine', 'AnimationAssets.js');
101
+ if (!fs.existsSync(compiled))
102
+ return null;
103
+ try {
104
+ const loaded = await import(pathToFileURL(compiled).href);
105
+ const assets = loaded.animationAssets;
106
+ return isAnimationAssets(assets) ? assets : null;
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ /**
113
+ * The built-in animation URLs this game can load. The ACTIVE library ships whole — its optional
114
+ * packs (melee/ranged/directional/posture) are loaded on demand by engine systems whose names
115
+ * game code never contains, so reference-scanning cannot bound them. The inactive library ships
116
+ * only clips the compiled game code names (`getBuiltinAnimationDef` resolves ids from either).
117
+ */
118
+ export function collectAnimationUrls(assets, worldData, compiledCode) {
119
+ const urls = new Set();
120
+ const bases = new Set([
121
+ assets.animationBaseUrl,
122
+ assets.generatedAnimationBaseUrl,
123
+ assets.animalBaseUrl,
124
+ assets.voxelAnimalBaseUrl,
125
+ assets.voxelFishBaseUrl,
126
+ ]);
127
+ // The rig loads for any humanoid: player (default present), NPCs, or multiplayer avatars —
128
+ // the same test the standalone collector applies.
129
+ const needsHumanoid = worldData.worldProfileData?.hasPlayerCharacter !== false
130
+ || compiledCode.includes('registerNpc')
131
+ || compiledCode.includes('MultiplayerSetup');
132
+ if (needsHumanoid) {
133
+ urls.add(assets.characterUrls.default);
134
+ urls.add(assets.characterUrls.defaultFallback);
135
+ }
136
+ const referenced = (entry) => compiledCode.includes(entry.motionId)
137
+ || (entry.file !== undefined && compiledCode.includes(entry.file));
138
+ const generatedPacks = [
139
+ assets.generatedAnimations,
140
+ assets.generatedMeleeWeaponAnimations,
141
+ assets.generatedRangedWeaponAnimations,
142
+ assets.generatedDirectionalAnimations,
143
+ assets.generatedPostureAnimations,
144
+ ];
145
+ if (assets.activeLibrary === 'generated') {
146
+ if (needsHumanoid) {
147
+ for (const pack of generatedPacks) {
148
+ for (const entry of pack)
149
+ urls.add(`${assets.generatedAnimationBaseUrl}/${entry.file}`);
150
+ }
151
+ }
152
+ for (const entry of assets.coreAnimations) {
153
+ if (referenced(entry))
154
+ urls.add(`${assets.animationBaseUrl}/${entry.file}`);
155
+ }
156
+ for (const entry of assets.meleeWeaponAnimations) {
157
+ if (referenced(entry))
158
+ urls.add(entry.url);
159
+ }
160
+ }
161
+ else {
162
+ if (needsHumanoid) {
163
+ for (const entry of assets.coreAnimations)
164
+ urls.add(`${assets.animationBaseUrl}/${entry.file}`);
165
+ for (const entry of assets.meleeWeaponAnimations)
166
+ urls.add(entry.url);
167
+ }
168
+ for (const pack of generatedPacks) {
169
+ for (const entry of pack) {
170
+ if (referenced(entry))
171
+ urls.add(`${assets.generatedAnimationBaseUrl}/${entry.file}`);
172
+ }
173
+ }
174
+ }
175
+ // Skeleton rigs for skeleton-based animals in world data. Voxel animal/fish BODIES resolve
176
+ // through a registry inside the engine (species → file); those load at spawn during the
177
+ // record pass, which vendors them — the bases above are rewritten either way.
178
+ const animals = Array.isArray(worldData.worldProfileData?.animals)
179
+ ? worldData.worldProfileData.animals
180
+ : [];
181
+ for (const animal of animals) {
182
+ if (typeof animal !== 'object' || animal === null)
183
+ continue;
184
+ const skeleton = animal.skeleton;
185
+ if (typeof skeleton === 'string') {
186
+ const file = assets.animalSkeletons[skeleton];
187
+ if (file !== undefined)
188
+ urls.add(`${assets.animalBaseUrl}/${file}`);
189
+ }
190
+ }
191
+ return { urls, bases };
192
+ }
193
+ function readWorkJson(root, file) {
194
+ try {
195
+ return JSON.parse(fs.readFileSync(path.join(root, aliasSourceDir('work'), file), 'utf-8'));
196
+ }
197
+ catch {
198
+ return null;
199
+ }
200
+ }
201
+ /** The full §4b collection: deep walk + compiled-code scan + built-in animation surface. */
202
+ export async function collectUrls(root) {
203
+ const urls = new Set();
204
+ const bases = new Set();
205
+ const notes = [];
206
+ const worldData = readWorkJson(root, 'world.json');
207
+ const gameData = readWorkJson(root, 'game.json');
208
+ deepWalkUrls(worldData, urls);
209
+ deepWalkUrls(gameData, urls);
210
+ const compiledCode = readCompiledGameCode(root);
211
+ if (compiledCode.length === 0) {
212
+ notes.push('No compiled game code under dist/ — code-referenced assets cannot be scanned.');
213
+ }
214
+ for (const url of scanCompiledCodeUrls(compiledCode))
215
+ urls.add(url);
216
+ const animationAssets = await loadAnimationAssets(root);
217
+ if (animationAssets === null) {
218
+ notes.push('The vendored engine\'s AnimationAssets could not be read — built-in animations will be '
219
+ + 'collected by the record pass instead.');
220
+ }
221
+ else {
222
+ const collected = collectAnimationUrls(animationAssets, (worldData ?? {}), compiledCode);
223
+ for (const url of collected.urls)
224
+ urls.add(url);
225
+ for (const base of collected.bases)
226
+ bases.add(base);
227
+ }
228
+ return { urls, bases, notes };
229
+ }
230
+ //# sourceMappingURL=collect-urls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect-urls.js","sourceRoot":"","sources":["../../src/ios/collect-urls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface IconResult {
2
+ /** Which of the two the app got — named in the build output. */
3
+ source: 'cover' | 'placeholder';
4
+ }
5
+ /** Write `size`x`size` flat-colour RGB PNG — the no-cover placeholder. */
6
+ export declare function writeFlatPng(target: string, size: number, rgb: readonly [number, number, number]): void;
7
+ /**
8
+ * Produce `icon-1024.png` inside the generated asset catalog. `coverPath` is tried first; any
9
+ * sips failure (missing file, unreadable format) falls through to the placeholder rather than
10
+ * failing a build over artwork.
11
+ */
12
+ export declare function writeAppIcon(assetCatalogDir: string, coverPath: string): IconResult;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The app icon: `bitmagic cover` artwork resized to the single 1024 px slot Xcode needs, via
3
+ * `sips` — present on every Mac that can run this lane at all, which keeps the CLI free of a
4
+ * native image dependency. No cover (or a cover sips cannot read) falls back to a generated
5
+ * flat placeholder, and the caller nudges toward `bitmagic cover` exactly as publish does for
6
+ * thumbnails.
7
+ */
8
+ import { spawnSync } from 'child_process';
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import * as zlib from 'zlib';
12
+ /** Write `size`x`size` flat-colour RGB PNG — the no-cover placeholder. */
13
+ export function writeFlatPng(target, size, rgb) {
14
+ const row = Buffer.alloc(1 + size * 3);
15
+ for (let x = 0; x < size; x += 1) {
16
+ row[1 + x * 3] = rgb[0];
17
+ row[2 + x * 3] = rgb[1];
18
+ row[3 + x * 3] = rgb[2];
19
+ }
20
+ const raw = Buffer.concat(Array.from({ length: size }, () => row));
21
+ const chunk = (type, data) => {
22
+ const header = Buffer.alloc(8);
23
+ header.writeUInt32BE(data.length, 0);
24
+ header.write(type, 4, 'ascii');
25
+ const crc = Buffer.alloc(4);
26
+ crc.writeUInt32BE(crc32(Buffer.concat([header.subarray(4), data])), 0);
27
+ return Buffer.concat([header, data, crc]);
28
+ };
29
+ const ihdr = Buffer.alloc(13);
30
+ ihdr.writeUInt32BE(size, 0);
31
+ ihdr.writeUInt32BE(size, 4);
32
+ ihdr[8] = 8; // bit depth
33
+ ihdr[9] = 2; // colour type: truecolour
34
+ const png = Buffer.concat([
35
+ Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
36
+ chunk('IHDR', ihdr),
37
+ chunk('IDAT', zlib.deflateSync(raw)),
38
+ chunk('IEND', Buffer.alloc(0)),
39
+ ]);
40
+ fs.writeFileSync(target, png);
41
+ }
42
+ function crc32(data) {
43
+ let crc = 0xffffffff;
44
+ for (const byte of data) {
45
+ crc ^= byte;
46
+ for (let bit = 0; bit < 8; bit += 1) {
47
+ crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
48
+ }
49
+ }
50
+ return (crc ^ 0xffffffff) >>> 0;
51
+ }
52
+ /**
53
+ * Produce `icon-1024.png` inside the generated asset catalog. `coverPath` is tried first; any
54
+ * sips failure (missing file, unreadable format) falls through to the placeholder rather than
55
+ * failing a build over artwork.
56
+ */
57
+ export function writeAppIcon(assetCatalogDir, coverPath) {
58
+ const target = path.join(assetCatalogDir, 'AppIcon.appiconset', 'icon-1024.png');
59
+ fs.mkdirSync(path.dirname(target), { recursive: true });
60
+ if (fs.existsSync(coverPath)) {
61
+ const converted = spawnSync('sips', ['-s', 'format', 'png', '-z', '1024', '1024', coverPath, '--out', target], { stdio: 'ignore' });
62
+ if (converted.status === 0 && fs.existsSync(target)) {
63
+ return { source: 'cover' };
64
+ }
65
+ }
66
+ // The Bitmagic near-black — matches the launch screen so a missing cover still looks placed.
67
+ writeFlatPng(target, 1024, [16, 16, 24]);
68
+ return { source: 'placeholder' };
69
+ }
70
+ //# sourceMappingURL=icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.js","sourceRoot":"","sources":["../../src/ios/icon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** Extension → content type, shared by this server and the generated Swift handler. */
2
+ export declare const MIME_TYPES: ReadonlyArray<readonly [string, string]>;
3
+ export declare const FALLBACK_MIME = "application/octet-stream";
4
+ export declare function mimeTypeFor(filePath: string): string;
5
+ export interface PayloadServer {
6
+ port: number;
7
+ origin: string;
8
+ close: () => Promise<void>;
9
+ }
10
+ /** Serve `dir` on an ephemeral localhost port. */
11
+ export declare function startPayloadServer(dir: string): Promise<PayloadServer>;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * A minimal static server over the staged payload directory, for the record and offline
3
+ * validation passes. GET only, no caching, path-traversal guarded. The MIME table is exported
4
+ * because the Swift scheme handler (xcode-template.ts) is generated from the SAME table — the
5
+ * validation browser and the shipped app must answer identically or the validation proves
6
+ * nothing.
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as http from 'http';
10
+ import * as path from 'path';
11
+ /** Extension → content type, shared by this server and the generated Swift handler. */
12
+ export const MIME_TYPES = [
13
+ ['html', 'text/html; charset=utf-8'],
14
+ ['js', 'text/javascript; charset=utf-8'],
15
+ ['mjs', 'text/javascript; charset=utf-8'],
16
+ ['css', 'text/css; charset=utf-8'],
17
+ ['json', 'application/json'],
18
+ ['wasm', 'application/wasm'],
19
+ ['glb', 'model/gltf-binary'],
20
+ ['gltf', 'model/gltf+json'],
21
+ ['png', 'image/png'],
22
+ ['webp', 'image/webp'],
23
+ ['jpg', 'image/jpeg'],
24
+ ['jpeg', 'image/jpeg'],
25
+ ['gif', 'image/gif'],
26
+ ['svg', 'image/svg+xml'],
27
+ ['ico', 'image/png'],
28
+ ['opus', 'audio/ogg'],
29
+ ['ogg', 'audio/ogg'],
30
+ ['mp3', 'audio/mpeg'],
31
+ ['wav', 'audio/wav'],
32
+ ['mp4', 'video/mp4'],
33
+ ['webm', 'video/webm'],
34
+ ['txt', 'text/plain; charset=utf-8'],
35
+ ];
36
+ export const FALLBACK_MIME = 'application/octet-stream';
37
+ export function mimeTypeFor(filePath) {
38
+ const ext = filePath.split('?')[0].split('.').pop()?.toLowerCase() ?? '';
39
+ return MIME_TYPES.find(([extension]) => extension === ext)?.[1] ?? FALLBACK_MIME;
40
+ }
41
+ /** Serve `dir` on an ephemeral localhost port. */
42
+ export function startPayloadServer(dir) {
43
+ const rootDir = path.resolve(dir);
44
+ const server = http.createServer((req, res) => {
45
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
46
+ res.writeHead(405).end();
47
+ return;
48
+ }
49
+ const requestPath = decodeURIComponent((req.url ?? '/').split('?')[0]);
50
+ const resolved = path.resolve(rootDir, `.${requestPath}`);
51
+ if (resolved !== rootDir && !resolved.startsWith(rootDir + path.sep)) {
52
+ res.writeHead(403).end();
53
+ return;
54
+ }
55
+ let filePath = resolved;
56
+ try {
57
+ if (fs.statSync(filePath).isDirectory())
58
+ filePath = path.join(filePath, 'index.html');
59
+ const bytes = fs.readFileSync(filePath);
60
+ res
61
+ .writeHead(200, { 'Content-Type': mimeTypeFor(filePath), 'Cache-Control': 'no-store' })
62
+ .end(req.method === 'HEAD' ? undefined : bytes);
63
+ }
64
+ catch {
65
+ res.writeHead(404, { 'Content-Type': 'text/plain' }).end('not found');
66
+ }
67
+ });
68
+ return new Promise((resolve, reject) => {
69
+ server.once('error', reject);
70
+ server.listen(0, '127.0.0.1', () => {
71
+ const address = server.address();
72
+ if (address === null || typeof address === 'string') {
73
+ reject(new Error('The payload server did not report a port.'));
74
+ return;
75
+ }
76
+ resolve({
77
+ port: address.port,
78
+ origin: `http://127.0.0.1:${address.port}`,
79
+ close: () => new Promise((resolveClose) => {
80
+ server.close(() => resolveClose());
81
+ // Sockets Chrome keeps alive would otherwise hold close() open past the command.
82
+ server.closeAllConnections();
83
+ }),
84
+ });
85
+ });
86
+ });
87
+ }
88
+ //# sourceMappingURL=local-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/ios/local-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface IosPaths {
2
+ /** `.bitmagic/ios` — the lane's root. */
3
+ iosDir: string;
4
+ /** `.bitmagic/ios.json` — persisted app identity (bundle id, team, version). */
5
+ configPath: string;
6
+ /** Downloaded-asset cache, keyed by URL hash — survives payload regeneration. */
7
+ cacheDir: string;
8
+ /** The generated Xcode project directory (App.xcodeproj + sources + Info.plist). */
9
+ projectDir: string;
10
+ /** The xcodeproj bundle itself. */
11
+ xcodeprojDir: string;
12
+ /** The game payload the app ships: index.html + vendor tree. A folder reference in the project. */
13
+ payloadDir: string;
14
+ /** xcodebuild's DerivedData, kept local so nothing lands in ~/Library. */
15
+ derivedDataDir: string;
16
+ /** Archives and exported .ipa files. */
17
+ distDir: string;
18
+ /** Record/offline-validation artifacts (console logs, screenshots) — the debugging trail. */
19
+ checkDir: string;
20
+ }
21
+ export declare function iosPaths(root: string): IosPaths;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Where the iOS lane keeps everything: under `.bitmagic/`, which is in the fingerprint's
3
+ * EXCLUDED_DIRS — so packaging an iOS build can never flip verify/publish staleness. The whole
4
+ * tree is CLI-owned and regenerated by `bitmagic ios build`; the only file with state worth
5
+ * keeping is `ios.json` (see app-config.ts), which regeneration preserves.
6
+ */
7
+ import * as path from 'path';
8
+ export function iosPaths(root) {
9
+ const iosDir = path.join(root, '.bitmagic', 'ios');
10
+ const projectDir = path.join(iosDir, 'App');
11
+ return {
12
+ iosDir,
13
+ configPath: path.join(root, '.bitmagic', 'ios.json'),
14
+ cacheDir: path.join(iosDir, 'cache'),
15
+ projectDir,
16
+ xcodeprojDir: path.join(projectDir, 'App.xcodeproj'),
17
+ payloadDir: path.join(projectDir, 'GamePayload'),
18
+ derivedDataDir: path.join(iosDir, 'DerivedData'),
19
+ distDir: path.join(iosDir, 'dist'),
20
+ checkDir: path.join(iosDir, 'check'),
21
+ };
22
+ }
23
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/ios/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAuB7B,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO;QACL,MAAM;QACN,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC;QACpD,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;QACpC,UAAU;QACV,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC;QACpD,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC;QAChD,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC;QAChD,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;QAClC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type VerifyResult } from '../verify/classify.js';
2
+ import type { MobileOrientation } from '../project/platform-declaration.js';
3
+ /** Long enough for a forged level's worth of local loads; adaptive settle exits earlier. */
4
+ export declare const PACKAGED_CHECK_SETTLE_MS = 25000;
5
+ /**
6
+ * Online-only endpoints the packaged game may talk to when a network exists, and must live
7
+ * without when one does not. Never vendored, aborted during both passes.
8
+ */
9
+ export declare function isOnlineOnlyUrl(url: string): boolean;
10
+ export interface PackagedCheckOptions {
11
+ payloadDir: string;
12
+ /** Where console.log / screenshot.png land — one subdirectory per pass. */
13
+ artifactDir: string;
14
+ mode: 'record' | 'offline';
15
+ orientation?: MobileOrientation;
16
+ settleMs?: number;
17
+ }
18
+ export interface PackagedCheckOutcome {
19
+ result: VerifyResult;
20
+ /** Remote, non-online-only URLs the game requested — the vendoring gap. */
21
+ misses: string[];
22
+ consolePath: string;
23
+ screenshotPath: string;
24
+ }
25
+ export declare function runPackagedCheck(options: PackagedCheckOptions): Promise<PackagedCheckOutcome>;