@bitmagic/cli 0.1.54-dev.0 → 0.1.54-dev.2

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.
package/README.md CHANGED
@@ -193,7 +193,7 @@ browser reloads itself on every change and the assets panel shows each generatio
193
193
  | `bitmagic whoami [--env <env>]` | Show the identity the CLI is authenticated as — the account's email address alongside its user id — and which environment answered, including where that environment was chosen from. |
194
194
  | `bitmagic init [dir] [--template <id>] [--name <name>] [--idea "<pitch>"] [--env <env>] [--force]` | Scaffold a new project: mints a game, downloads the vendored engine, writes `AGENTS.md`, `GAME-DESIGN.md` and templates. Starts from `empty-3d` unless told otherwise. `--idea` seeds the design doc's pitch **and** picks the template whose camera and controls fit it — "a doom-like corridor shooter" scaffolds `first-person`, "jump between floating islands" scaffolds `sidescroller`. `--template` overrides both; a suggestion that fails for any reason falls back to `empty-3d` rather than failing the scaffold. Dependencies are installed with **pnpm** when your machine has it and npm otherwise — the lockfile that produces is what every later command reads, so it never tells you to run the wrong one. |
195
195
  | `bitmagic check` | Typecheck (`tsc --noEmit`) against the vendored engine. Fast; does not prove the game runs. |
196
- | `bitmagic dev [--port <port>] [--editor-port <port>] [--no-open]` | Build, then serve everything and keep it running: `tsc --watch`, `vite` on 3010, and a **Game / Editor** view on 3011 that reloads itself when the project changes, and shows where the game is published (with a QR code) once it has been. Opens the view in your browser; `--no-open` (or `BITMAGIC_NO_OPEN=1`) skips that. The one command to leave open. See **The dev view** below. |
196
+ | `bitmagic dev [--port <port>] [--editor-port <port>] [--no-open] [--mobile] [--mobile-http]` | Build, then serve everything and keep it running: `tsc --watch`, `vite` on 3010, and a **Game / Editor** view on 3011 that reloads itself when the project changes, and shows where the game is published (with a QR code) once it has been. Opens the view in your browser; `--no-open` (or `BITMAGIC_NO_OPEN=1`) skips that. `--mobile` also serves the game to phones on your network, over https, and prints a QR code for that. The one command to leave open. See **The dev view** below. |
197
197
  | `bitmagic reload [--port <port>]` | Tell a running `bitmagic dev` to reload the browser now. For agents: run it when you finish a round of edits. Exits 0 and does nothing when no dev server is running. |
198
198
  | `bitmagic verify [--timeout <ms>] [--renderer webgpu\|webgl] [--platform desktop\|mobile\|both] [--fast] [--watch]` | Build, boot the game in a headless browser, press the engine's Play button like a player would, and report what broke. A game without the button passes as long as gameplay starts by itself (auto-starting genres, custom start UIs); a run where gameplay never starts fails. The settle is adaptive: the run ends as soon as the live engine proves stable gameplay (state, rendered frames, no fresh errors, player standing), with `--timeout` as the cap. The verdict includes live engine state — actual GPU backend, fps, player position, physics body count, gameplay events (see **Gameplay events** below) — recorded in `result.json`. `--renderer` pins the pipeline (default `webgpu`, what players run; a silent WebGPU→WebGL2 fallback **fails** the run, and `--renderer webgl` is the deliberate escape hatch). A run failing on a lost WebGL context retries once on software rendering automatically. `--fast` skips the screenshot pipeline (then there is no thumbnail candidate from this run). `--watch` keeps everything warm — incremental `tsc --watch`, one vite, one browser — and re-verifies on file change in seconds; `--fast` is the watch default (`--no-fast` restores the screenshot). `--platform` picks what the run emulates — see **Verifying the mobile path** below. Every run also reports the engine's mobile-parity check: a desktop action with no touch button is a warning, and a **failure** when `game.json` declares `primaryPlatform: "mobile"`. Writes the artifacts the publish gate reads (see below). |
199
199
  | `bitmagic build [--single-file]` | Bundle the game into a single `.bitmagic/build/index.html`. The engine, your game and its data are inlined; three.js, Rapier and the other third-party packages load from a CDN at the versions your import map pins — the same shape a game published from bitmagic.ai has. `--single-file` inlines those too, for a game that has to run with no network (offline, `file://`, a packaged shell); the file is several megabytes bigger. Rarely needs to be run by hand — `publish` builds automatically when the project changed. |
@@ -323,6 +323,7 @@ my-game/
323
323
  cover.json # its URL and the design hash it was generated from
324
324
  AGENTS.md.latest # the current AGENTS.md template, when upgrade kept your edited one
325
325
  dev.json # the running `bitmagic dev`'s ports, so `bitmagic reload` finds it
326
+ mobile-qr.png # the phone URL as a QR code, written when --mobile cannot draw one
326
327
  jobs/ # one file per generation in flight — what the assets panel reads
327
328
  previews/ # rendered asset thumbnails, cached so they are drawn once
328
329
  build/
@@ -452,6 +453,45 @@ clipboard write the image is saved to your downloads instead, and the status bar
452
453
 
453
454
  3010 still serves the game on its own, for a second window or a bookmark.
454
455
 
456
+ ### On a real phone
457
+
458
+ `bitmagic dev --mobile` serves the game to your own network as well, and prints a QR code to scan:
459
+
460
+ ```bash
461
+ bitmagic dev --mobile
462
+ # On your phone https://192.168.1.23:3012/
463
+ # QR code .bitmagic/mobile-qr.png — open it to scan.
464
+ ```
465
+
466
+ This is the thing no browser can fake. Emulation gets you a small viewport and synthetic touches;
467
+ a phone gets you iOS Safari's fullscreen rules, the real orientation behaviour, real multi-touch,
468
+ and a real thermal budget on a real GPU. The emulated run (**Verifying the mobile path** above)
469
+ still comes first — it is faster and it catches the obvious — but it is not a device.
470
+
471
+ Three things are worth knowing about how it works.
472
+
473
+ **The game is proxied, so its assets load.** Your levels and models live on the asset CDN, which
474
+ answers only the origins it allowlists — `http://localhost:3000`–`3199`, and no address a phone can
475
+ present. A phone asking the bucket directly gets nothing, and a level whose terrain never arrived
476
+ looks like a broken forge rather than a blocked request: you fall through the floor forever. So the
477
+ phone never asks the bucket. It asks your machine, which fetches on its behalf, where the rule does
478
+ not apply. Only `*.bitmagic.ai` and `*.bitmagic.cloud` are relayed this way; a third-party CDN in
479
+ your game has to allow the origin itself, as most do.
480
+
481
+ **It is served over https, and the certificate is self-signed.** Your phone will warn once per
482
+ address — tap *Show Details*, then *Visit Website*, and it remembers. The warning buys something
483
+ real: `navigator.gpu` exists only in a secure context, so over plain `http` the device would quietly
484
+ run the classic WebGL renderer and you would be testing a pipeline your players are not on. Pass
485
+ `--mobile-http` to skip the certificate anyway, and accept WebGL on the device. If `openssl` is not
486
+ installed, that is what happens by itself, and the banner says so.
487
+
488
+ **Reloads reach the phone.** It listens on the same channel the dev view does, so an agent edit —
489
+ or `bitmagic reload` — reloads what you are holding, without picking it up.
490
+
491
+ The editor is not exposed: the phone gets the game and the game's assets, and nothing that can write
492
+ to your project. The game, though, is genuinely visible to everything on your network for as long as
493
+ the command runs. On a café's Wi-Fi, that is worth a thought.
494
+
455
495
  **If those ports are busy it moves and tells you** — it does not refuse to start. That matters
456
496
  because agents run `bitmagic dev` as a background task, so a refusal would die into a log nobody
457
497
  reads. `.bitmagic/dev.json` records what it actually bound, so `bitmagic reload` still finds it, and
@@ -812,9 +852,12 @@ The code is extra, never a substitute — the URL is always printed as a plain l
812
852
  everything still works if neither a drawing nor a file appears. `--no-qr` and `BITMAGIC_NO_QR`
813
853
  suppress both.
814
854
 
815
- `bitmagic dev` deliberately has no equivalent. Its servers bind `127.0.0.1`, and the asset CDN
816
- only serves assets to `localhost` origins a phone pointed at your machine's LAN address would
817
- load the game with no terrain and drop the player through the floor. Publish privately instead.
855
+ `bitmagic dev --mobile` is the same loop without the publish see **On a real phone** above. It
856
+ takes a detour to get there: the asset CDN serves assets only to `localhost` origins, so a phone
857
+ pointed straight at your machine's LAN address loads the game with no terrain and drops the player
858
+ through the floor. `--mobile` fetches those assets on the phone's behalf, which is what makes the
859
+ LAN address work at all. Publishing privately is still the way onto a device that is not on your
860
+ network, or into someone else's hands.
818
861
 
819
862
  ### Which platform the game is catalogued as
820
863
 
package/dist/cli.d.ts CHANGED
@@ -205,6 +205,14 @@ declare const rawCommands: {
205
205
  readonly type: "boolean";
206
206
  readonly description: "Do not open a browser. Same as setting BITMAGIC_NO_OPEN.";
207
207
  };
208
+ readonly mobile: {
209
+ readonly type: "boolean";
210
+ readonly description: "Also serve the game to phones on this network, and print a QR code for it.";
211
+ };
212
+ readonly 'mobile-http': {
213
+ readonly type: "boolean";
214
+ readonly description: "Serve --mobile over http instead of a self-signed certificate (no WebGPU on the device).";
215
+ };
208
216
  }>;
209
217
  reload: CommandDef<{
210
218
  readonly port: {
@@ -11,4 +11,12 @@ export declare const devCommand: import("citty").CommandDef<{
11
11
  readonly type: "boolean";
12
12
  readonly description: "Do not open a browser. Same as setting BITMAGIC_NO_OPEN.";
13
13
  };
14
+ readonly mobile: {
15
+ readonly type: "boolean";
16
+ readonly description: "Also serve the game to phones on this network, and print a QR code for it.";
17
+ };
18
+ readonly 'mobile-http': {
19
+ readonly type: "boolean";
20
+ readonly description: "Serve --mobile over http instead of a self-signed certificate (no WebGPU on the device).";
21
+ };
14
22
  }>;
@@ -16,6 +16,8 @@
16
16
  */
17
17
  import { defineCommand } from 'citty';
18
18
  import { spawn, spawnSync } from 'child_process';
19
+ import * as fs from 'fs';
20
+ import * as os from 'os';
19
21
  import * as path from 'path';
20
22
  import { CliError } from '../errors.js';
21
23
  import { loadProjectContext, projectBin } from '../project/context.js';
@@ -27,6 +29,10 @@ import { ReloadBus } from '../editor/reload-bus.js';
27
29
  import { ReloadCoordinator, pipeTscWatch, watchProject } from '../editor/watch.js';
28
30
  import { CORS_ALLOWED_PORT_MAX, CORS_ALLOWED_PORT_MIN, isPortFree, parseLocalPort, resolveDevPort, } from '../local-port.js';
29
31
  import { openInBrowser, NO_OPEN_ENV } from '../open-browser.js';
32
+ import { lanAddresses } from '../mobile/lan-address.js';
33
+ import { ensureDevCert } from '../mobile/dev-cert.js';
34
+ import { startMobileBridge } from '../mobile/bridge.js';
35
+ import { devQrPath, emitQr } from '../render/qr-output.js';
30
36
  import { waitForServer } from '../verify/wait-for-server.js';
31
37
  import { engineUpdateNotice } from '../project/engine-update.js';
32
38
  import { reportCommandEvent } from '../telemetry/report.js';
@@ -62,6 +68,9 @@ async function notifyIfEngineOutdated(environment, projectEngineVersion, log) {
62
68
  }
63
69
  }
64
70
  const DEFAULT_GAME_PORT = 3010;
71
+ // The editor's own default now lives beside the handle that records it (project/dev-handle.ts);
72
+ // only the phone bridge's is still this file's to name.
73
+ const DEFAULT_MOBILE_PORT = 3012;
65
74
  /**
66
75
  * The port to bind, given what the creator asked for.
67
76
  *
@@ -109,6 +118,14 @@ export const devCommand = defineCommand({
109
118
  type: 'boolean',
110
119
  description: `Do not open a browser. Same as setting ${NO_OPEN_ENV}.`,
111
120
  },
121
+ mobile: {
122
+ type: 'boolean',
123
+ description: 'Also serve the game to phones on this network, and print a QR code for it.',
124
+ },
125
+ 'mobile-http': {
126
+ type: 'boolean',
127
+ description: 'Serve --mobile over http instead of a self-signed certificate (no WebGPU on the device).',
128
+ },
112
129
  },
113
130
  async run({ args }) {
114
131
  const context = loadProjectContext();
@@ -170,6 +187,44 @@ export const devCommand = defineCommand({
170
187
  coordinator,
171
188
  log: (message) => console.log(message),
172
189
  });
190
+ /**
191
+ * The phone-facing bridge, when asked for. Started before the children for the same reason the
192
+ * sidecar is: a machine on no network, or a taken port, should stop the command here rather
193
+ * than after vite has claimed a port and tsc has begun a watch.
194
+ */
195
+ let mobile = null;
196
+ let mobileAddresses = [];
197
+ let mobilePort = 0;
198
+ let mobileSecure = false;
199
+ if (args.mobile === true) {
200
+ mobileAddresses = lanAddresses(os.networkInterfaces());
201
+ const primary = mobileAddresses[0];
202
+ if (primary === undefined) {
203
+ throw new CliError('`--mobile` found no local network address to serve on. Connect this machine to the same '
204
+ + 'Wi-Fi as the phone, then run it again.');
205
+ }
206
+ // The certificate is what buys a secure context, and a secure context is what exposes
207
+ // `navigator.gpu` — without it the device silently tests the WebGL renderer instead of the
208
+ // one production runs. A machine with no openssl still gets a phone URL; it gets told what
209
+ // that costs rather than being refused the feature.
210
+ const cert = args['mobile-http'] === true ? null : ensureDevCert(primary.address);
211
+ if (cert === null && args['mobile-http'] !== true) {
212
+ console.log('Could not generate a certificate (is `openssl` installed?) — serving the phone over http '
213
+ + 'instead. WebGPU is only exposed to secure contexts, so the device will run WebGL.');
214
+ }
215
+ mobileSecure = cert !== null;
216
+ mobilePort = await claimPort(DEFAULT_MOBILE_PORT, false, '--mobile', new Set([gamePort, editorPort]));
217
+ mobile = await startMobileBridge({
218
+ gamePort,
219
+ port: mobilePort,
220
+ address: primary.address,
221
+ tls: cert,
222
+ log: (message) => console.log(message),
223
+ // The phone joins the same push channel the shell is on, so an agent edit reloads it too.
224
+ // Read-only, and the only thing on the sidecar the network can reach.
225
+ subscribe: (req, res) => bus.subscribe(req, res),
226
+ });
227
+ }
173
228
  const children = [
174
229
  // Piped rather than inherited — see the file header and editor/watch.ts.
175
230
  { name: 'tsc --watch', process: pipeTscWatch(tsc, context.root, coordinator) },
@@ -179,7 +234,12 @@ export const devCommand = defineCommand({
179
234
  },
180
235
  ];
181
236
  const watcher = watchProject(context.root, coordinator, (m) => console.log(m));
182
- writeDevHandle(context.root, { editorPort, gamePort, pid: process.pid });
237
+ writeDevHandle(context.root, {
238
+ editorPort,
239
+ gamePort,
240
+ pid: process.pid,
241
+ ...(mobile === null ? {} : { mobileUrl: mobile.url }),
242
+ });
183
243
  let shuttingDown = false;
184
244
  let requestedByUser = false;
185
245
  const shutdown = () => {
@@ -193,6 +253,7 @@ export const devCommand = defineCommand({
193
253
  bus.close();
194
254
  removeDevHandle(context.root);
195
255
  void editor.close();
256
+ void mobile?.close();
196
257
  };
197
258
  process.on('SIGINT', () => {
198
259
  requestedByUser = true;
@@ -230,6 +291,43 @@ export const devCommand = defineCommand({
230
291
  // being told — the journal is the only record of intentions the editor cannot carry out
231
292
  // itself, and of who changed what.
232
293
  console.log(` Editor actions ${path.relative(context.root, editor.journalPath)}`);
294
+ if (mobile !== null) {
295
+ const scheme = mobileSecure ? 'https' : 'http';
296
+ console.log(`\n On your phone ${mobile.url}`);
297
+ // Every address, not just the best guess: a laptop on Wi-Fi and Ethernet at once has two
298
+ // right answers and only the creator knows which network the phone is on.
299
+ for (const other of mobileAddresses.slice(1)) {
300
+ console.log(` or ${scheme}://${other.address}:${mobilePort}/ (${other.name})`);
301
+ }
302
+ // Written to a file when it cannot be drawn, because `dev` is usually started as a
303
+ // background task by an agent — a pipe, where the creator never sees this terminal.
304
+ const qrPath = emitQr(mobile.url, {
305
+ root: context.root, json: false, disabled: false, file: devQrPath(context.root),
306
+ });
307
+ if (qrPath !== null) {
308
+ console.log(` QR code ${path.relative(context.root, qrPath)} — open it to scan.`);
309
+ }
310
+ else {
311
+ // Drawn, so no file was written — and one left from an earlier run holds an address
312
+ // this machine may no longer have. A stale QR is worse than none: it scans, and then
313
+ // the phone sits on a URL nothing answers, with nothing on screen to say why.
314
+ try {
315
+ fs.rmSync(devQrPath(context.root));
316
+ }
317
+ catch {
318
+ // There was no file to clear, which is the normal case.
319
+ }
320
+ }
321
+ if (mobileSecure) {
322
+ console.log('\n The certificate is self-signed: the phone warns once per address —'
323
+ + ' tap Show Details, then Visit Website.');
324
+ }
325
+ else {
326
+ console.log('\n Serving over http, so the device has no secure context: it will run the'
327
+ + ' WebGL renderer, not WebGPU.');
328
+ }
329
+ console.log(' Anything on your local network can open the game while this is running.');
330
+ }
233
331
  console.log('\nThe browser reloads itself when the project changes. `bitmagic reload` forces it.\n');
234
332
  })
235
333
  .catch(() => {
@@ -261,6 +359,7 @@ export const devCommand = defineCommand({
261
359
  // Both children are gone by here — via a signal handler or via the failure path above, each of
262
360
  // which has already run shutdown(). This awaits the close that shutdown() could only start.
263
361
  await editor.close();
362
+ await mobile?.close();
264
363
  if (failure) {
265
364
  throw new CliError(`${failure.name} ${failure.detail}. \`bitmagic dev\` stopped.`);
266
365
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Which absolute URLs the mobile bridge proxies, and the path it proxies them under.
3
+ *
4
+ * A phone on the local network loads the game from a LAN origin, and the asset bucket's CORS policy
5
+ * allowlists literal `http://localhost:3000`-`3199` origins and nothing else (see `../local-port.ts`
6
+ * for what that costs when it is violated: a terrain-less world and a player falling forever). No
7
+ * origin a phone can present is ever on that list, and broadening the list to cover private IP
8
+ * ranges is not expressible in GCS CORS — it would mean `*` for everyone.
9
+ *
10
+ * So the phone never talks to the bucket. It asks the BRIDGE, same-origin, and the dev machine
11
+ * fetches the asset server-side, where CORS does not exist at all. This module is the two halves of
12
+ * that redirection: which hosts are ours to fetch on the browser's behalf, and the reversible path
13
+ * that carries one.
14
+ *
15
+ * The host suffixes are the same environment classification `rehost-imported-assets.ts` uses in
16
+ * game-play-agent: `bitmagic.ai` is prod (`mini.bitmagic.ai`, `forged-assets.bitmagic.ai`, ...) and
17
+ * `bitmagic.cloud` is dev/sandbox (`beta.portal.bitmagic.cloud`,
18
+ * `magic-mesh-gen.sandbox.dev.bitmagic.cloud`, ...). Everything else is deliberately left alone:
19
+ * `esm.sh` serves the import map's modules and already answers `*`, and an unrecognised host is
20
+ * more likely to be a creator's own endpoint than an asset we should be relaying.
21
+ */
22
+ /** The bridge route every proxied asset is fetched through. Trailing slash included. */
23
+ export declare const CDN_PROXY_PREFIX = "/__bm/cdn/";
24
+ /** Host suffixes that identify a bitmagic-controlled asset host. See the file header. */
25
+ export declare const MANAGED_HOST_SUFFIXES: readonly ["bitmagic.ai", "bitmagic.cloud"];
26
+ export declare function isManagedAssetHost(hostname: string): boolean;
27
+ /**
28
+ * The same-origin path that stands in for `url`, or null when the URL is not ours to proxy.
29
+ *
30
+ * Path-PRESERVING rather than `?u=<encoded>`, because GLTFLoader resolves a `.bin` or a texture
31
+ * sibling RELATIVE to the URL the .glb came from. Under a query-string form that resolution drops
32
+ * the query and lands on the bridge's own root; under this form it lands next to the .glb, on the
33
+ * same upstream host, which is where it actually lives.
34
+ */
35
+ export declare function toProxyPath(url: string): string | null;
36
+ /**
37
+ * The upstream URL a proxy path stands for, or null when the path is not one (or names a host we
38
+ * do not relay for).
39
+ *
40
+ * The host allowlist is re-checked HERE rather than trusted from `toProxyPath`: this half runs on
41
+ * request paths the bridge receives, which anything on the local network can compose. Traversal in
42
+ * the remainder needs no separate guard — every form of it stays on the host named in the first
43
+ * segment, which is the only thing this decides.
44
+ */
45
+ export declare function fromProxyPath(requestPath: string): string | null;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Which absolute URLs the mobile bridge proxies, and the path it proxies them under.
3
+ *
4
+ * A phone on the local network loads the game from a LAN origin, and the asset bucket's CORS policy
5
+ * allowlists literal `http://localhost:3000`-`3199` origins and nothing else (see `../local-port.ts`
6
+ * for what that costs when it is violated: a terrain-less world and a player falling forever). No
7
+ * origin a phone can present is ever on that list, and broadening the list to cover private IP
8
+ * ranges is not expressible in GCS CORS — it would mean `*` for everyone.
9
+ *
10
+ * So the phone never talks to the bucket. It asks the BRIDGE, same-origin, and the dev machine
11
+ * fetches the asset server-side, where CORS does not exist at all. This module is the two halves of
12
+ * that redirection: which hosts are ours to fetch on the browser's behalf, and the reversible path
13
+ * that carries one.
14
+ *
15
+ * The host suffixes are the same environment classification `rehost-imported-assets.ts` uses in
16
+ * game-play-agent: `bitmagic.ai` is prod (`mini.bitmagic.ai`, `forged-assets.bitmagic.ai`, ...) and
17
+ * `bitmagic.cloud` is dev/sandbox (`beta.portal.bitmagic.cloud`,
18
+ * `magic-mesh-gen.sandbox.dev.bitmagic.cloud`, ...). Everything else is deliberately left alone:
19
+ * `esm.sh` serves the import map's modules and already answers `*`, and an unrecognised host is
20
+ * more likely to be a creator's own endpoint than an asset we should be relaying.
21
+ */
22
+ /** The bridge route every proxied asset is fetched through. Trailing slash included. */
23
+ export const CDN_PROXY_PREFIX = '/__bm/cdn/';
24
+ /** Host suffixes that identify a bitmagic-controlled asset host. See the file header. */
25
+ export const MANAGED_HOST_SUFFIXES = ['bitmagic.ai', 'bitmagic.cloud'];
26
+ /** A hostname with no port and no credentials — what a proxy path's first segment may hold. */
27
+ const HOSTNAME = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/;
28
+ export function isManagedAssetHost(hostname) {
29
+ const host = hostname.toLowerCase();
30
+ if (!HOSTNAME.test(host))
31
+ return false;
32
+ return MANAGED_HOST_SUFFIXES.some((suffix) => host === suffix || host.endsWith(`.${suffix}`));
33
+ }
34
+ /**
35
+ * The same-origin path that stands in for `url`, or null when the URL is not ours to proxy.
36
+ *
37
+ * Path-PRESERVING rather than `?u=<encoded>`, because GLTFLoader resolves a `.bin` or a texture
38
+ * sibling RELATIVE to the URL the .glb came from. Under a query-string form that resolution drops
39
+ * the query and lands on the bridge's own root; under this form it lands next to the .glb, on the
40
+ * same upstream host, which is where it actually lives.
41
+ */
42
+ export function toProxyPath(url) {
43
+ let parsed;
44
+ try {
45
+ parsed = new URL(url);
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:')
51
+ return null;
52
+ if (parsed.port !== '' || parsed.username !== '' || parsed.password !== '')
53
+ return null;
54
+ if (!isManagedAssetHost(parsed.hostname))
55
+ return null;
56
+ return `${CDN_PROXY_PREFIX}${parsed.hostname}${parsed.pathname}${parsed.search}`;
57
+ }
58
+ /**
59
+ * The upstream URL a proxy path stands for, or null when the path is not one (or names a host we
60
+ * do not relay for).
61
+ *
62
+ * The host allowlist is re-checked HERE rather than trusted from `toProxyPath`: this half runs on
63
+ * request paths the bridge receives, which anything on the local network can compose. Traversal in
64
+ * the remainder needs no separate guard — every form of it stays on the host named in the first
65
+ * segment, which is the only thing this decides.
66
+ */
67
+ export function fromProxyPath(requestPath) {
68
+ if (!requestPath.startsWith(CDN_PROXY_PREFIX))
69
+ return null;
70
+ const rest = requestPath.slice(CDN_PROXY_PREFIX.length);
71
+ const slash = rest.indexOf('/');
72
+ if (slash <= 0)
73
+ return null;
74
+ const host = rest.slice(0, slash).toLowerCase();
75
+ if (!isManagedAssetHost(host))
76
+ return null;
77
+ return `https://${host}${rest.slice(slash)}`;
78
+ }
79
+ //# sourceMappingURL=asset-hosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-hosts.js","sourceRoot":"","sources":["../../src/mobile/asset-hosts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wFAAwF;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAE7C,yFAAyF;AACzF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,aAAa,EAAE,gBAAgB,CAAU,CAAC;AAEhF,+FAA+F;AAC/F,MAAM,QAAQ,GAAG,mEAAmE,CAAC;AAErF,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;AAChG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,MAAM,CAAC,IAAI,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACxF,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,OAAO,GAAG,gBAAgB,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;AACnF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAChD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,WAAW,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The mobile bridge: the one server `bitmagic dev` exposes to the local network.
3
+ *
4
+ * `dev` normally binds nothing outside loopback. vite serves the game on 127.0.0.1 and the editor
5
+ * sidecar deliberately stays there too — it writes files in the creator's project, and no phone
6
+ * needs the shell. So rather than opening either of them up, `--mobile` puts THIS in front: a
7
+ * reverse proxy that terminates the phone's connection, forwards the game, and does the two things
8
+ * a plain `--host` on vite could not.
9
+ *
10
+ * 1. It serves the CDN. A LAN origin is on no bucket's CORS allowlist, so the phone asking the
11
+ * bucket directly gets nothing (`../local-port.ts` documents what that looks like from the
12
+ * creator's side: a level with no terrain). Same-origin `/__bm/cdn/<host>/<path>` requests
13
+ * land here instead and are fetched server-side, where CORS does not apply.
14
+ * 2. It injects `rewrite-shim.ts` into every HTML page it passes through, which is what makes
15
+ * the engine ask for (1) in the first place.
16
+ *
17
+ * WebSocket upgrades are piped straight through to vite, so its HMR client connects from the phone
18
+ * and the page reloads on a rebuild exactly as the desktop shell does.
19
+ *
20
+ * What is NOT here is as deliberate: no route to the sidecar, and therefore no way for anything on
21
+ * the network to save a scene, start a generation, or read the editor journal. The phone gets the
22
+ * game and the game's assets.
23
+ */
24
+ import * as http from 'http';
25
+ export interface MobileBridgeOptions {
26
+ /** Where vite is serving the game, on loopback. */
27
+ gamePort: number;
28
+ /** The port to expose on the network. */
29
+ port: number;
30
+ /** The LAN address the printed URL names. The bridge itself listens on every interface. */
31
+ address: string;
32
+ /** A key/cert pair from `dev-cert.ts`, or null to serve plain http (no WebGPU on the device). */
33
+ tls: {
34
+ key: string;
35
+ cert: string;
36
+ } | null;
37
+ log: (message: string) => void;
38
+ /**
39
+ * Hands one request to the reload bus as an SSE stream, putting the phone on the SAME push
40
+ * channel as the desktop shell — the coordinator's, which only fires once a compile has landed.
41
+ *
42
+ * Passed as a function rather than the bus itself so this module stays unaware of the editor's
43
+ * half of `dev`. It is the one sidecar capability the network is given, and it is one-directional
44
+ * and read-only: nothing on the other end of it can save a scene or read the journal.
45
+ */
46
+ subscribe?: (req: http.IncomingMessage, res: http.ServerResponse) => void;
47
+ /** Seam for the test; production uses the runtime's own fetch. */
48
+ fetchImpl?: typeof globalThis.fetch;
49
+ }
50
+ export interface MobileBridge {
51
+ /** What to print, and what the QR encodes. */
52
+ url: string;
53
+ close(): Promise<void>;
54
+ }
55
+ /**
56
+ * Start the bridge and return the URL to hand the phone.
57
+ *
58
+ * Listens on every interface — that is the point of the command — which is why `dev` prints what
59
+ * that means alongside the URL.
60
+ */
61
+ export declare function startMobileBridge(options: MobileBridgeOptions): Promise<MobileBridge>;