rnxsim 0.1.490 → 0.1.492

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 (65) hide show
  1. package/cli/app-state-reset.ts +11 -9
  2. package/cli/cloud-client.ts +43 -7
  3. package/cli/command-registry.ts +3 -0
  4. package/cli/commands/detox.ts +41 -11
  5. package/cli/commands/flow.ts +2 -1
  6. package/cli/commands/maestro.ts +30 -0
  7. package/cli/commands/platform.ts +15 -0
  8. package/cli/commands/preview.ts +104 -0
  9. package/cli/commands/test.ts +224 -0
  10. package/cli/main.ts +34 -0
  11. package/cli/outbound-endpoints.ts +5 -2
  12. package/dist-lib/agent-daemon-client.cjs +1 -1
  13. package/dist-lib/agent-events.cjs +1 -1
  14. package/dist-lib/agent-identity.cjs +1 -1
  15. package/dist-lib/agent-sessions.cjs +1 -1
  16. package/dist-lib/attached-projects.cjs +1 -1
  17. package/dist-lib/auth/shared-session.cjs +1 -1
  18. package/dist-lib/backend-origin.cjs +1 -1
  19. package/dist-lib/beta.cjs +1 -1
  20. package/dist-lib/beta.mjs +1 -1
  21. package/dist-lib/bridge-constants.cjs +1 -1
  22. package/dist-lib/bridge-contract-input.cjs +1 -1
  23. package/dist-lib/bridge-contract-input.mjs +1 -1
  24. package/dist-lib/bridge-contract.cjs +1 -1
  25. package/dist-lib/bridge-contract.mjs +1 -1
  26. package/dist-lib/capture-contract.cjs +1 -1
  27. package/dist-lib/capture-contract.mjs +1 -1
  28. package/dist-lib/cli-constants.cjs +1 -1
  29. package/dist-lib/cloud-contract.cjs +1 -1
  30. package/dist-lib/cloud-contract.mjs +1 -1
  31. package/dist-lib/cloud.cjs +1 -1
  32. package/dist-lib/cloud.mjs +1 -1
  33. package/dist-lib/config.cjs +1 -1
  34. package/dist-lib/detox/index.cjs +1 -1
  35. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  36. package/dist-lib/home-paths.cjs +1 -1
  37. package/dist-lib/host/bridge-host.cjs +22 -8
  38. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  39. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  40. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  41. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  42. package/dist-lib/host/websocket-proxy.cjs +1 -1
  43. package/dist-lib/index.cjs +1 -1
  44. package/dist-lib/jump-to-source-babel.cjs +1 -1
  45. package/dist-lib/jump-to-source-native.cjs +1 -1
  46. package/dist-lib/menu.cjs +1 -1
  47. package/dist-lib/menu.mjs +1 -1
  48. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  49. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  50. package/dist-lib/metro-production-bundle.cjs +1 -1
  51. package/dist-lib/metro-production-bundle.mjs +1 -1
  52. package/dist-lib/metro.cjs +1 -1
  53. package/dist-lib/profiles.cjs +1 -1
  54. package/dist-lib/public-brand.cjs +1 -1
  55. package/dist-lib/react-native-host-modules.cjs +1 -1
  56. package/dist-lib/react-native-host-modules.mjs +1 -1
  57. package/dist-lib/render-mode.cjs +1 -1
  58. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  59. package/dist-lib/sdk.cjs +1 -1
  60. package/dist-lib/sdk.mjs +1 -1
  61. package/dist-lib/skills.cjs +22 -8
  62. package/dist-lib/vite.cjs +1 -1
  63. package/package.json +1 -1
  64. package/skills/contrast/SKILL.md +3 -0
  65. package/src/bridge-contract.ts +4 -5
package/cli/main.ts CHANGED
@@ -364,6 +364,11 @@ try {
364
364
  await runInspect([command, ...commandArgsWithSim], { port, verbose })
365
365
  } else {
366
366
  switch (command) {
367
+ case 'test': {
368
+ const { runTest } = await import('./commands/test')
369
+ await exitWithFlush(await runTest(commandArgsWithSim, { port, verbose }))
370
+ }
371
+
367
372
  case 'assert': {
368
373
  // stays outside the usual dispatcher — it spawns self to get the
369
374
  // inner verb's --json payload, so it never needs the shared bridge
@@ -483,6 +488,35 @@ try {
483
488
  await exitWithFlush(typeof code === 'number' ? code : 0)
484
489
  }
485
490
 
491
+ case 'remote': {
492
+ if (globalSimTarget) {
493
+ console.error(
494
+ ` ${rnxPublicBrand.commandName} remote creates a new simulator and cannot target --sim`,
495
+ )
496
+ await exitWithFlush(1)
497
+ }
498
+ const platform = parsed.commandArgs[0]
499
+ if (platform === 'ios' || platform === 'android') {
500
+ const { runRemotePlatformCommand } = await import('./commands/platform')
501
+ const code = await runRemotePlatformCommand(
502
+ platform,
503
+ parsed.commandArgs.slice(1),
504
+ { port },
505
+ )
506
+ await exitWithFlush(typeof code === 'number' ? code : 0)
507
+ } else {
508
+ console.error(
509
+ ` usage: ${rnxPublicBrand.commandName} remote ios|android <bundle.js|https://bundle-url>`,
510
+ )
511
+ await exitWithFlush(1)
512
+ }
513
+ }
514
+
515
+ case 'preview': {
516
+ const { runPreview } = await import('./commands/preview')
517
+ await exitWithFlush(await runPreview(parsed.commandArgs))
518
+ }
519
+
486
520
  case 'web': {
487
521
  const { getRnxCommandAvailability } = await import('./command-registry')
488
522
  const availability = getRnxCommandAvailability('web', parsed.commandArgs, 'node')
@@ -320,9 +320,12 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
320
320
  category: 'guest_app_network',
321
321
  count: 2,
322
322
  },
323
- 'packages/sootsim-engine/src/preview/presigned-upload.ts :: fetch :: `${origin}/api/preview/upload/finalize`':
323
+ // the path is a parameter so one uploader serves both callers: recordings use
324
+ // /api/preview/upload/{init,finalize} (the default) and `rnx preview` passes
325
+ // /api/v1/previews{,/finalize}. both are first-party contrast endpoints.
326
+ 'packages/sootsim-engine/src/preview/presigned-upload.ts :: fetch :: `${origin}${endpoints.finalize}`':
324
327
  { category: 'contrast_user_action', count: 1 },
325
- 'packages/sootsim-engine/src/preview/presigned-upload.ts :: fetch :: `${origin}/api/preview/upload/init`':
328
+ 'packages/sootsim-engine/src/preview/presigned-upload.ts :: fetch :: `${origin}${endpoints.init}`':
326
329
  { category: 'contrast_user_action', count: 1 },
327
330
  'packages/sootsim-engine/src/preview/presigned-upload.ts :: fetch :: job.url': {
328
331
  category: 'presigned_upload',
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -3881,6 +3881,15 @@ async function inferCloudModuleIdentity(source) {
3881
3881
  }
3882
3882
  }
3883
3883
  async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_CLOUD_BUNDLE_BYTES) {
3884
+ return produceArtifact(
3885
+ bundlePath,
3886
+ assetsPath,
3887
+ maxBytes,
3888
+ REMOTE_COMMAND,
3889
+ "allow-placeholders"
3890
+ );
3891
+ }
3892
+ async function produceArtifact(bundlePath, assetsPath, maxBytes, command, assetPolicy) {
3884
3893
  const source = await loadBundleSource(bundlePath);
3885
3894
  const descriptors = extractAssetDescriptors(source);
3886
3895
  const search = assetsPath ? explicitMetroAssetDest((0, import_node_path15.resolve)(assetsPath), descriptors) : descriptors.length > 0 && !isRemoteBundleInput(bundlePath) ? searchMetroAssetDest(bundlePath, descriptors) : { dest: null, searched: [], truncated: false };
@@ -3896,7 +3905,7 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
3896
3905
  const placement = placements.get(label);
3897
3906
  if (placement?.mismatched && dest) {
3898
3907
  throw new Error(
3899
- `${REMOTE_COMMAND} found ${variant.descriptor.name}.${variant.descriptor.type} in ${dest.directory}, but its bytes are not the ones this bundle was built against. Rebuild with \`react-native bundle --assets-dest ${dest.directory}\` so the bundle and the images match.`
3908
+ `${command} found ${variant.descriptor.name}.${variant.descriptor.type} in ${dest.directory}, but its bytes are not the ones this bundle was built against. Rebuild with \`react-native bundle --assets-dest ${dest.directory}\` so the bundle and the images match.`
3900
3909
  );
3901
3910
  }
3902
3911
  const relative2 = placement?.files.get(variant.scale);
@@ -3904,17 +3913,22 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
3904
3913
  if (placement && placement.files.size > 0) return null;
3905
3914
  if (placement && placement.ambiguous.length > 0 && dest) {
3906
3915
  throw new Error(
3907
- `${REMOTE_COMMAND} found more than one image for ${label} in ${dest.directory} and none of them is the one Metro hashed: ${placement.ambiguous.sort().join(", ")}. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
3916
+ `${command} found more than one image for ${label} in ${dest.directory} and none of them is the one Metro hashed: ${placement.ambiguous.sort().join(", ")}. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
3908
3917
  );
3909
3918
  }
3910
3919
  if (assetsPath) {
3911
3920
  throw new Error(
3912
- `${REMOTE_COMMAND} could not find ${label} under --assets ${dest?.directory ?? (0, import_node_path15.resolve)(assetsPath)}. Point --assets at the directory \`react-native bundle --assets-dest\` wrote, or drop the flag to let ${REMOTE_COMMAND} find it.`
3921
+ `${command} could not find ${label} under --assets ${dest?.directory ?? (0, import_node_path15.resolve)(assetsPath)}. Point --assets at the directory \`react-native bundle --assets-dest\` wrote, or drop the flag to let ${command} find it.`
3913
3922
  );
3914
3923
  }
3915
3924
  if (search.truncated) {
3916
3925
  throw new Error(
3917
- `${REMOTE_COMMAND} stopped listing ${search.searched.join(", ")} after ${MAX_ASSET_DEST_FILES} files and never reached ${label}, so it cannot tell a missing asset from an unread one. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
3926
+ `${command} stopped listing ${search.searched.join(", ")} after ${MAX_ASSET_DEST_FILES} files and never reached ${label}, so it cannot tell a missing asset from an unread one. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
3927
+ );
3928
+ }
3929
+ if (assetPolicy === "require-assets") {
3930
+ throw new Error(
3931
+ `${command} could not find ${label}. Pass --assets <dir> pointing at the directory \`react-native bundle --assets-dest <dir>\` wrote, or build with \`--assets-dest\`.`
3918
3932
  );
3919
3933
  }
3920
3934
  const placeholder = metroAssetPlaceholderBytes(variant.descriptor.type);
@@ -3929,7 +3943,7 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
3929
3943
  );
3930
3944
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
3931
3945
  throw new Error(
3932
- `${REMOTE_COMMAND} could not read ${(0, import_node_path15.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Build the bundle with --assets-dest, or pass --assets <dir>.`
3946
+ `${command} could not read ${(0, import_node_path15.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Build the bundle with --assets-dest, or pass --assets <dir>.`
3933
3947
  );
3934
3948
  });
3935
3949
  const artifact = await buildRnxCloudArtifact(embedded.code, {
@@ -3945,12 +3959,12 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
3945
3959
  const warnings = [];
3946
3960
  if (substituted.length > 0) {
3947
3961
  warnings.push(
3948
- `${REMOTE_COMMAND} embedded a placeholder image for ${substituted.length} asset(s) no scale of which is in ${search.searched.join(", ") || "any asset dest directory"}: ${substituted.join(", ")}. Build the bundle with --assets-dest, or pass --assets <dir>, to ship the real images.`
3962
+ `${command} embedded a placeholder image for ${substituted.length} asset(s) no scale of which is in ${search.searched.join(", ") || "any asset dest directory"}: ${substituted.join(", ")}. Build the bundle with --assets-dest, or pass --assets <dir>, to ship the real images.`
3949
3963
  );
3950
3964
  }
3951
3965
  if (bytes.length >= Math.floor(maxBytes * 0.8)) {
3952
3966
  warnings.push(
3953
- `${REMOTE_COMMAND} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / maxBytes * 100)}% of the ${maxBytes}-byte limit.${largestEmbeddedAssets(assets.sizes, 5)}`
3967
+ `${command} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / maxBytes * 100)}% of the ${maxBytes}-byte limit.${largestEmbeddedAssets(assets.sizes, 5)}`
3954
3968
  );
3955
3969
  }
3956
3970
  return {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "rnx";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -27949,6 +27949,15 @@ async function inferCloudModuleIdentity(source) {
27949
27949
  }
27950
27950
  }
27951
27951
  async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_CLOUD_BUNDLE_BYTES) {
27952
+ return produceArtifact(
27953
+ bundlePath,
27954
+ assetsPath,
27955
+ maxBytes,
27956
+ REMOTE_COMMAND,
27957
+ "allow-placeholders"
27958
+ );
27959
+ }
27960
+ async function produceArtifact(bundlePath, assetsPath, maxBytes, command, assetPolicy) {
27952
27961
  const source = await loadBundleSource(bundlePath);
27953
27962
  const descriptors = extractAssetDescriptors(source);
27954
27963
  const search = assetsPath ? explicitMetroAssetDest((0, import_node_path15.resolve)(assetsPath), descriptors) : descriptors.length > 0 && !isRemoteBundleInput(bundlePath) ? searchMetroAssetDest(bundlePath, descriptors) : { dest: null, searched: [], truncated: false };
@@ -27964,7 +27973,7 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
27964
27973
  const placement = placements.get(label);
27965
27974
  if (placement?.mismatched && dest) {
27966
27975
  throw new Error(
27967
- `${REMOTE_COMMAND} found ${variant.descriptor.name}.${variant.descriptor.type} in ${dest.directory}, but its bytes are not the ones this bundle was built against. Rebuild with \`react-native bundle --assets-dest ${dest.directory}\` so the bundle and the images match.`
27976
+ `${command} found ${variant.descriptor.name}.${variant.descriptor.type} in ${dest.directory}, but its bytes are not the ones this bundle was built against. Rebuild with \`react-native bundle --assets-dest ${dest.directory}\` so the bundle and the images match.`
27968
27977
  );
27969
27978
  }
27970
27979
  const relative2 = placement?.files.get(variant.scale);
@@ -27972,17 +27981,22 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
27972
27981
  if (placement && placement.files.size > 0) return null;
27973
27982
  if (placement && placement.ambiguous.length > 0 && dest) {
27974
27983
  throw new Error(
27975
- `${REMOTE_COMMAND} found more than one image for ${label} in ${dest.directory} and none of them is the one Metro hashed: ${placement.ambiguous.sort().join(", ")}. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
27984
+ `${command} found more than one image for ${label} in ${dest.directory} and none of them is the one Metro hashed: ${placement.ambiguous.sort().join(", ")}. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
27976
27985
  );
27977
27986
  }
27978
27987
  if (assetsPath) {
27979
27988
  throw new Error(
27980
- `${REMOTE_COMMAND} could not find ${label} under --assets ${dest?.directory ?? (0, import_node_path15.resolve)(assetsPath)}. Point --assets at the directory \`react-native bundle --assets-dest\` wrote, or drop the flag to let ${REMOTE_COMMAND} find it.`
27989
+ `${command} could not find ${label} under --assets ${dest?.directory ?? (0, import_node_path15.resolve)(assetsPath)}. Point --assets at the directory \`react-native bundle --assets-dest\` wrote, or drop the flag to let ${command} find it.`
27981
27990
  );
27982
27991
  }
27983
27992
  if (search.truncated) {
27984
27993
  throw new Error(
27985
- `${REMOTE_COMMAND} stopped listing ${search.searched.join(", ")} after ${MAX_ASSET_DEST_FILES} files and never reached ${label}, so it cannot tell a missing asset from an unread one. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
27994
+ `${command} stopped listing ${search.searched.join(", ")} after ${MAX_ASSET_DEST_FILES} files and never reached ${label}, so it cannot tell a missing asset from an unread one. Pass --assets <dir> to name the directory \`react-native bundle --assets-dest\` wrote.`
27995
+ );
27996
+ }
27997
+ if (assetPolicy === "require-assets") {
27998
+ throw new Error(
27999
+ `${command} could not find ${label}. Pass --assets <dir> pointing at the directory \`react-native bundle --assets-dest <dir>\` wrote, or build with \`--assets-dest\`.`
27986
28000
  );
27987
28001
  }
27988
28002
  const placeholder = metroAssetPlaceholderBytes(variant.descriptor.type);
@@ -27997,7 +28011,7 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
27997
28011
  );
27998
28012
  const classic = metroIosAssetDestRelatives(variant.descriptor.httpServerLocation, filename)[0] ?? filename;
27999
28013
  throw new Error(
28000
- `${REMOTE_COMMAND} could not read ${(0, import_node_path15.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Build the bundle with --assets-dest, or pass --assets <dir>.`
28014
+ `${command} could not read ${(0, import_node_path15.join)(dest?.directory ?? ".", classic)} for ${variant.descriptor.name}.${variant.descriptor.type} at scale ${variant.scale}, and has no stand-in for a .${variant.descriptor.type} asset. Build the bundle with --assets-dest, or pass --assets <dir>.`
28001
28015
  );
28002
28016
  });
28003
28017
  const artifact = await buildRnxCloudArtifact(embedded.code, {
@@ -28013,12 +28027,12 @@ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_C
28013
28027
  const warnings = [];
28014
28028
  if (substituted.length > 0) {
28015
28029
  warnings.push(
28016
- `${REMOTE_COMMAND} embedded a placeholder image for ${substituted.length} asset(s) no scale of which is in ${search.searched.join(", ") || "any asset dest directory"}: ${substituted.join(", ")}. Build the bundle with --assets-dest, or pass --assets <dir>, to ship the real images.`
28030
+ `${command} embedded a placeholder image for ${substituted.length} asset(s) no scale of which is in ${search.searched.join(", ") || "any asset dest directory"}: ${substituted.join(", ")}. Build the bundle with --assets-dest, or pass --assets <dir>, to ship the real images.`
28017
28031
  );
28018
28032
  }
28019
28033
  if (bytes.length >= Math.floor(maxBytes * 0.8)) {
28020
28034
  warnings.push(
28021
- `${REMOTE_COMMAND} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / maxBytes * 100)}% of the ${maxBytes}-byte limit.${largestEmbeddedAssets(assets.sizes, 5)}`
28035
+ `${command} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / maxBytes * 100)}% of the ${maxBytes}-byte limit.${largestEmbeddedAssets(assets.sizes, 5)}`
28022
28036
  );
28023
28037
  }
28024
28038
  return {
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.490 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.492 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.490",
3
+ "version": "0.1.492",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",