rnxsim 0.1.431 → 0.1.433

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 (78) hide show
  1. package/README.md +20 -50
  2. package/cli/auth.ts +33 -3
  3. package/cli/cloud-client.ts +524 -88
  4. package/cli/cloud-dispatch.ts +5 -10
  5. package/cli/cloud-session.ts +5 -5
  6. package/cli/commands/auth.ts +13 -2
  7. package/cli/commands/box.ts +189 -20
  8. package/cli/commands/control.ts +40 -13
  9. package/cli/commands/device.ts +1 -1
  10. package/cli/commands/flow.ts +189 -43
  11. package/cli/commands/inspect/get-layout.ts +1 -1
  12. package/cli/commands/inspect.ts +8 -1
  13. package/cli/commands/login.ts +79 -14
  14. package/cli/commands/maestro-generate.ts +70 -54
  15. package/cli/commands/maestro.ts +69 -20
  16. package/cli/commands/platform.ts +30 -32
  17. package/cli/commands/screenshot.ts +3 -2
  18. package/cli/commands/upload.ts +28 -10
  19. package/cli/help-core.ts +11 -1
  20. package/cli/outbound-endpoints.ts +27 -5
  21. package/cli/parse-args.ts +17 -0
  22. package/cli/shell-init.ts +4 -4
  23. package/cli/ws-bridge.ts +109 -62
  24. package/dist-lib/agent-daemon-client.cjs +1 -1
  25. package/dist-lib/agent-events.cjs +1 -1
  26. package/dist-lib/agent-identity.cjs +1 -1
  27. package/dist-lib/agent-sessions.cjs +1 -1
  28. package/dist-lib/attached-projects.cjs +1 -1
  29. package/dist-lib/auth/shared-session.cjs +17 -4
  30. package/dist-lib/backend-origin.cjs +1 -1
  31. package/dist-lib/beta.cjs +1 -1
  32. package/dist-lib/beta.mjs +1 -1
  33. package/dist-lib/bridge-constants.cjs +1 -1
  34. package/dist-lib/bridge-contract-input.cjs +1 -1
  35. package/dist-lib/bridge-contract-input.mjs +1 -1
  36. package/dist-lib/bridge-contract.cjs +1 -1
  37. package/dist-lib/bridge-contract.mjs +1 -1
  38. package/dist-lib/capture-contract.cjs +1 -1
  39. package/dist-lib/capture-contract.mjs +1 -1
  40. package/dist-lib/cli-constants.cjs +1 -1
  41. package/dist-lib/cloud-contract.cjs +1 -1
  42. package/dist-lib/cloud-contract.mjs +1 -1
  43. package/dist-lib/cloud.cjs +108 -93
  44. package/dist-lib/cloud.mjs +106 -91
  45. package/dist-lib/config.cjs +1 -1
  46. package/dist-lib/detox/index.cjs +1 -1
  47. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  48. package/dist-lib/home-paths.cjs +1 -1
  49. package/dist-lib/host/bridge-host.cjs +1 -1
  50. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  51. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  52. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  53. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  54. package/dist-lib/host/websocket-proxy.cjs +1 -1
  55. package/dist-lib/index.cjs +58 -139
  56. package/dist-lib/jump-to-source-babel.cjs +1 -1
  57. package/dist-lib/menu.cjs +1 -1
  58. package/dist-lib/menu.mjs +1 -1
  59. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  60. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  61. package/dist-lib/metro-production-bundle.cjs +1 -1
  62. package/dist-lib/metro-production-bundle.mjs +1 -1
  63. package/dist-lib/metro.cjs +33 -212
  64. package/dist-lib/profiles.cjs +1 -1
  65. package/dist-lib/public-brand.cjs +1 -1
  66. package/dist-lib/react-native-host-modules.cjs +1 -1
  67. package/dist-lib/react-native-host-modules.mjs +1 -1
  68. package/dist-lib/render-mode.cjs +1 -1
  69. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  70. package/dist-lib/sdk.cjs +1 -1
  71. package/dist-lib/sdk.mjs +1 -1
  72. package/dist-lib/skills.cjs +436 -351
  73. package/dist-lib/vite.cjs +1 -1
  74. package/package.json +2 -1
  75. package/src/auth/shared-session.ts +31 -0
  76. package/src/cloud.ts +83 -113
  77. package/src/metro-plugin.ts +30 -113
  78. package/src/vite-plugin.ts +11 -2
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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;
@@ -569,6 +569,10 @@ var rnxPublicBrand = Object.freeze({
569
569
  origin: "https://rnxsim.com"
570
570
  });
571
571
 
572
+ // cli/run-rnx.ts
573
+ var import_node_async_hooks = require("node:async_hooks");
574
+ var sinks = new import_node_async_hooks.AsyncLocalStorage();
575
+
572
576
  // src/backend-origin.ts
573
577
  function normalizeHostname(hostname) {
574
578
  return hostname.replace(/^\[|\]$/g, "").toLowerCase();
@@ -586,6 +590,8 @@ var RNX_SHELL_UPDATE_UNSET = `${RNX_SHELL_UPDATE_PREFIX}unset`;
586
590
 
587
591
  // cli/cloud-client.ts
588
592
  var DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
593
+ var MAX_RNX_CLOUD_BUNDLE_BYTES = RNX_CLOUD_MAX_ARTIFACT_BYTES;
594
+ var WARN_ARTIFACT_BYTES = Math.floor(MAX_RNX_CLOUD_BUNDLE_BYTES * 0.8);
589
595
 
590
596
  // cli/ws-bridge.ts
591
597
  function bridgeWsUrl(wsPort) {
@@ -684,6 +690,39 @@ function describeSimIdSource(source) {
684
690
  if (source === "saved") return "saved via `rnx use`";
685
691
  return "primary fallback \u2014 no sim pinned";
686
692
  }
693
+ var BRIDGE_VALUE_FLAGS_TABLE = [
694
+ {
695
+ names: ["--port", "-p"],
696
+ // naming the flag pins the world even when the value is missing or junk,
697
+ // so a later --base-url cannot quietly retarget the run to another shell.
698
+ apply: (state, value) => {
699
+ state.explicitPort = true;
700
+ if (value !== void 0) state.wsPort = Number(value);
701
+ }
702
+ },
703
+ {
704
+ names: ["--timeout"],
705
+ apply: (state, value) => {
706
+ if (value !== void 0) state.commandTimeoutMs = Number(value);
707
+ }
708
+ },
709
+ {
710
+ // `--sim` is the canonical target flag; `--session` / `--tab` are
711
+ // documented aliases (CLAUDE.md, the rnx agent skills, and engine docs all
712
+ // say `--session <id>`). without these aliases an agent following the docs
713
+ // would have `--session ef` silently ignored and get the *currently
714
+ // pinned* sim's tree instead — wrong-app data with no error.
715
+ names: ["--sim", "--session", "--tab"],
716
+ apply: (state, value) => {
717
+ if (value === void 0) return;
718
+ state.simId = value.trim() || void 0;
719
+ state.simIdSource = "flag";
720
+ }
721
+ }
722
+ ];
723
+ var BRIDGE_VALUE_FLAGS = BRIDGE_VALUE_FLAGS_TABLE.flatMap(
724
+ (flag) => [...flag.names]
725
+ );
687
726
  function createBridge(wsPort, opts = {}) {
688
727
  let nextId = 1;
689
728
  const commandTimeoutMs = opts.commandTimeoutMs ?? 15e3;
@@ -2769,10 +2808,8 @@ var import_path3 = __toESM(require("path"), 1);
2769
2808
  var import_node_child_process = require("node:child_process");
2770
2809
  var import_node_crypto2 = require("node:crypto");
2771
2810
  var import_node_fs4 = __toESM(require("node:fs"), 1);
2772
- var import_node_http = __toESM(require("node:http"), 1);
2773
2811
  var import_node_path4 = __toESM(require("node:path"), 1);
2774
2812
  var import_node_url = require("node:url");
2775
- var scheduledMetroOpens = /* @__PURE__ */ new Set();
2776
2813
  function resolveRnxDesktopAppName(open, projectRoot) {
2777
2814
  if (!open) return null;
2778
2815
  if (typeof open === "object") {
@@ -2843,82 +2880,6 @@ function launchRnxDesktop(bundleUrl, appName) {
2843
2880
  );
2844
2881
  observeRnxDesktopLaunch(child, appName);
2845
2882
  }
2846
- function openRnxDesktopWhenMetroIsReady({
2847
- port,
2848
- bundleUrl,
2849
- appName,
2850
- projectRoot,
2851
- serverId,
2852
- intervalMs = 100,
2853
- timeoutMs = 3e4,
2854
- launch = launchRnxDesktop
2855
- }) {
2856
- const key = `${projectRoot}\0${port}`;
2857
- if (scheduledMetroOpens.has(key)) return Promise.resolve(false);
2858
- scheduledMetroOpens.add(key);
2859
- const deadline = Date.now() + timeoutMs;
2860
- return new Promise((resolve2) => {
2861
- let finished = false;
2862
- let retryTimer;
2863
- const finish = (opened) => {
2864
- if (finished) return;
2865
- finished = true;
2866
- clearTimeout(retryTimer);
2867
- scheduledMetroOpens.delete(key);
2868
- resolve2(opened);
2869
- };
2870
- const retry = () => {
2871
- if (finished) return;
2872
- if (Date.now() >= deadline) {
2873
- console.error(
2874
- `[rnx] could not open ${appName}: Metro did not become ready on port ${port}`
2875
- );
2876
- finish(false);
2877
- return;
2878
- }
2879
- retryTimer = setTimeout(check, intervalMs);
2880
- };
2881
- const check = () => {
2882
- const request = import_node_http.default.get(
2883
- `http://127.0.0.1:${port}/__server-scan`,
2884
- { headers: { Accept: "application/json" } },
2885
- (response) => {
2886
- let body = "";
2887
- response.setEncoding("utf8");
2888
- response.on("data", (chunk) => {
2889
- body = `${body}${chunk}`.slice(0, 65536);
2890
- });
2891
- response.once("end", () => {
2892
- try {
2893
- const scan = JSON.parse(body);
2894
- const matches = response.statusCode === 200 && Array.isArray(scan) && scan.some((entry) => {
2895
- if (!entry || typeof entry !== "object") return false;
2896
- const scannedPort = Reflect.get(entry, "port");
2897
- const projectName = Reflect.get(entry, "projectName");
2898
- const scannedServerId = Reflect.get(entry, "rnxServerId");
2899
- const scannedBundle = Reflect.get(entry, "bundleUrl");
2900
- if (scannedPort !== port || projectName !== appName || scannedServerId !== serverId || typeof scannedBundle !== "string") {
2901
- return false;
2902
- }
2903
- return new URL(scannedBundle).searchParams.get("rnxAppName") === appName;
2904
- });
2905
- if (matches) {
2906
- launch(bundleUrl, appName);
2907
- finish(true);
2908
- return;
2909
- }
2910
- } catch {
2911
- }
2912
- retry();
2913
- });
2914
- }
2915
- );
2916
- request.setTimeout(Math.min(1e3, timeoutMs), () => request.destroy());
2917
- request.once("error", retry);
2918
- };
2919
- check();
2920
- });
2921
- }
2922
2883
 
2923
2884
  // src/host/replacement-module-handler.ts
2924
2885
  var import_promises = __toESM(require("node:fs/promises"), 1);
@@ -3443,7 +3404,7 @@ function appendRNXModulePaths(result, graph, options, projectRoot) {
3443
3404
  const dependencies = graph.dependencies;
3444
3405
  const createModuleId = options.createModuleId;
3445
3406
  if (!dependencies || !createModuleId) {
3446
- throw new Error("rnxsim: Metro did not provide the module graph and createModuleId");
3407
+ return result;
3447
3408
  }
3448
3409
  const modulePaths = {};
3449
3410
  for (const module2 of dependencies.values()) {
@@ -3477,13 +3438,9 @@ function appendRNXModulePaths(result, graph, options, projectRoot) {
3477
3438
  };
3478
3439
  return typeof result === "string" ? appendRNXMetroModuleIdentityFooter(result, identity) : { ...result, code: appendRNXMetroModuleIdentityFooter(result.code, identity) };
3479
3440
  }
3480
- function withRNX(config, options = {}) {
3481
- if (!options.devServer && !options.open && !options.productionBundles && !options.developmentBundles) {
3482
- return config;
3483
- }
3441
+ function withRNX(config) {
3484
3442
  const cfgProjectRoot = config.projectRoot || process.cwd();
3485
- const appName = resolveRnxDesktopAppName(options.open, cfgProjectRoot);
3486
- const configuredBundleUrl = options.bundleUrl || "/index.bundle?platform=ios&dev=true&hot=true&minify=false";
3443
+ const configuredBundleUrl = "/index.bundle?platform=ios&dev=true&hot=true&minify=false";
3487
3444
  const cfgServer = config.server;
3488
3445
  const port = resolveMetroPort(cfgServer);
3489
3446
  const metroServerId = (0, import_node_crypto4.randomUUID)();
@@ -3491,32 +3448,22 @@ function withRNX(config, options = {}) {
3491
3448
  configuredBundleUrl,
3492
3449
  `http://localhost:${port}`,
3493
3450
  metroServerId,
3494
- cfgProjectRoot,
3495
- appName
3451
+ cfgProjectRoot
3496
3452
  );
3497
3453
  const cfgSerializer = config.serializer;
3498
3454
  const existingEnhance = cfgServer?.enhanceMiddleware;
3499
3455
  const existingSerializer = cfgSerializer?.customSerializer;
3500
- let productionConfig = {};
3501
- if (options.productionBundles || options.developmentBundles) {
3502
- let defaultSerializer;
3503
- productionConfig = {
3504
- serializer: {
3505
- ...cfgSerializer,
3506
- customSerializer: async (entryPoint, preModules, graph, serializerOptions) => {
3507
- const serializer = existingSerializer || (defaultSerializer ||= createMetroDefaultSerializer(cfgProjectRoot));
3508
- const result = await serializer(
3509
- entryPoint,
3510
- preModules,
3511
- graph,
3512
- serializerOptions
3513
- );
3514
- const dev = serializerOptions.dev;
3515
- return dev === false && options.productionBundles === true || dev === true && options.developmentBundles === true ? appendRNXModulePaths(result, graph, serializerOptions, cfgProjectRoot) : result;
3516
- }
3456
+ let defaultSerializer;
3457
+ const serializerConfig = {
3458
+ serializer: {
3459
+ ...cfgSerializer,
3460
+ customSerializer: async (entryPoint, preModules, graph, serializerOptions) => {
3461
+ const serializer = existingSerializer || (defaultSerializer ||= createMetroDefaultSerializer(cfgProjectRoot));
3462
+ const result = await serializer(entryPoint, preModules, graph, serializerOptions);
3463
+ return appendRNXModulePaths(result, graph, serializerOptions, cfgProjectRoot);
3517
3464
  }
3518
- };
3519
- }
3465
+ }
3466
+ };
3520
3467
  const serverConfig = {
3521
3468
  ...cfgServer,
3522
3469
  enhanceMiddleware: (metroMiddleware, metroServer) => {
@@ -3545,23 +3492,6 @@ function withRNX(config, options = {}) {
3545
3492
  }
3546
3493
  const url = req.url || "";
3547
3494
  const pathname = url.split("?")[0];
3548
- if (pathname === "/__server-scan") {
3549
- const absoluteBundleUrl = bundleUrl.startsWith("http") ? bundleUrl : `http://localhost:${port}${bundleUrl}`;
3550
- res.setHeader("content-type", "application/json");
3551
- res.end(
3552
- JSON.stringify([
3553
- {
3554
- port,
3555
- framework: "metro",
3556
- rnxServerId: metroServerId,
3557
- bundleUrl: absoluteBundleUrl,
3558
- ...appName ? { projectName: appName } : {},
3559
- lastSeen: Date.now()
3560
- }
3561
- ])
3562
- );
3563
- return;
3564
- }
3565
3495
  const runtimeRoot = resolveRuntimeRootForRequestHost(req.headers?.host);
3566
3496
  if (!runtimeRoot) {
3567
3497
  if (pathname === prefix || pathname === prefix + "/") {
@@ -3594,10 +3524,8 @@ function withRNX(config, options = {}) {
3594
3524
  if (!ext) {
3595
3525
  const htmlPath = import_path4.default.join(runtimeRoot, "index.html");
3596
3526
  let html = import_fs5.default.readFileSync(htmlPath, "utf8");
3597
- html = html.replace(
3598
- "</head>",
3599
- `<script>(function(){var u=new URL(location.href);if(!u.searchParams.has('bundle'))u.searchParams.set('bundle',${JSON.stringify(bundleUrl)});history.replaceState(null,'','${prefix}/'+u.search)})()</script></head>`
3600
- );
3527
+ const script = `<script>(function(){var u=new URL(location.href);if(!u.searchParams.has('bundle'))u.searchParams.set('bundle',${JSON.stringify(bundleUrl)});history.replaceState(null,'','${prefix}/'+u.search)})()</script>`;
3528
+ html = html.includes("</head>") ? html.replace("</head>", `${script}</head>`) : `${html}${script}`;
3601
3529
  res.setHeader("content-type", "text/html");
3602
3530
  res.end(html);
3603
3531
  return;
@@ -3610,19 +3538,10 @@ function withRNX(config, options = {}) {
3610
3538
  return server;
3611
3539
  }
3612
3540
  };
3613
- if (appName && !process.env.CI && !process.env.RNX_NO_OPEN) {
3614
- void openRnxDesktopWhenMetroIsReady({
3615
- port,
3616
- bundleUrl: resolveRnxDesktopLaunchTarget(port, bundleUrl),
3617
- appName,
3618
- projectRoot: cfgProjectRoot,
3619
- serverId: metroServerId
3620
- });
3621
- }
3622
3541
  return {
3623
3542
  ...config,
3624
- ...productionConfig,
3625
- ...options.devServer || options.open ? { server: serverConfig } : {}
3543
+ ...serializerConfig,
3544
+ server: serverConfig
3626
3545
  };
3627
3546
  }
3628
3547
  function resolveMetroPort(server) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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.431 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.433 | (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=";