rnxsim 0.1.500 → 0.1.501

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 (68) hide show
  1. package/README.md +1 -1
  2. package/cli/cloud-client.ts +90 -7
  3. package/cli/cloud-dispatch.ts +27 -27
  4. package/cli/cloud-session.ts +61 -6
  5. package/cli/commands/control.ts +33 -31
  6. package/cli/commands/detox.ts +157 -159
  7. package/cli/commands/platform.ts +170 -48
  8. package/cli/commands/preview.ts +1 -1
  9. package/cli/commands/test.ts +403 -95
  10. package/cli/main.ts +11 -0
  11. package/cli/outbound-endpoints.ts +10 -0
  12. package/detox/jest-preset.cjs +1 -6
  13. package/dist-lib/agent-daemon-client.cjs +1 -1
  14. package/dist-lib/agent-events.cjs +1 -1
  15. package/dist-lib/agent-identity.cjs +1 -1
  16. package/dist-lib/agent-sessions.cjs +1 -1
  17. package/dist-lib/attached-projects.cjs +1 -1
  18. package/dist-lib/auth/shared-session.cjs +1 -1
  19. package/dist-lib/backend-origin.cjs +1 -1
  20. package/dist-lib/beta.cjs +1 -1
  21. package/dist-lib/beta.mjs +1 -1
  22. package/dist-lib/bridge-constants.cjs +1 -1
  23. package/dist-lib/bridge-contract-input.cjs +1 -1
  24. package/dist-lib/bridge-contract-input.mjs +1 -1
  25. package/dist-lib/bridge-contract.cjs +1 -1
  26. package/dist-lib/bridge-contract.mjs +1 -1
  27. package/dist-lib/capture-contract.cjs +1 -1
  28. package/dist-lib/capture-contract.mjs +1 -1
  29. package/dist-lib/cli-constants.cjs +1 -1
  30. package/dist-lib/cloud-contract.cjs +7 -1
  31. package/dist-lib/cloud-contract.mjs +5 -1
  32. package/dist-lib/cloud.cjs +1 -1
  33. package/dist-lib/cloud.mjs +1 -1
  34. package/dist-lib/config.cjs +1 -1
  35. package/dist-lib/detox/index.cjs +1 -1
  36. package/dist-lib/detox/jest-preset.cjs +1 -6
  37. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  38. package/dist-lib/home-paths.cjs +1 -1
  39. package/dist-lib/host/bridge-host.cjs +54 -29
  40. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  41. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  42. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  43. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  44. package/dist-lib/host/websocket-proxy.cjs +1 -1
  45. package/dist-lib/index.cjs +39 -12
  46. package/dist-lib/jump-to-source-babel.cjs +1 -1
  47. package/dist-lib/jump-to-source-native.cjs +1 -1
  48. package/dist-lib/menu.cjs +1 -1
  49. package/dist-lib/menu.mjs +1 -1
  50. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  51. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  52. package/dist-lib/metro-production-bundle.cjs +1 -1
  53. package/dist-lib/metro-production-bundle.mjs +1 -1
  54. package/dist-lib/metro.cjs +1 -1
  55. package/dist-lib/profiles.cjs +1 -1
  56. package/dist-lib/public-brand.cjs +1 -1
  57. package/dist-lib/react-native-host-modules.cjs +1 -1
  58. package/dist-lib/react-native-host-modules.mjs +1 -1
  59. package/dist-lib/render-mode.cjs +1 -1
  60. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  61. package/dist-lib/sdk.cjs +6 -8
  62. package/dist-lib/sdk.mjs +6 -8
  63. package/dist-lib/skills.cjs +109 -51
  64. package/dist-lib/vite.cjs +1 -1
  65. package/package.json +1 -1
  66. package/skills/rnx-test/SKILL.md +2 -2
  67. package/src/cloud-contract.ts +2 -0
  68. package/src/sim-client.ts +8 -10
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.500 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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);
@@ -1951,21 +1951,19 @@ var SimClient = class {
1951
1951
  `sim ${this.simId} reported no URL to derive the shell from`
1952
1952
  );
1953
1953
  }
1954
- const nextUrl = buildSimOpenUrl(currentUrl, target);
1955
- const expected = new URL(nextUrl);
1954
+ const nextUrl = new URL(buildSimOpenUrl(currentUrl, target));
1955
+ const token = `sim-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
1956
+ nextUrl.searchParams.set("inspectOpen", token);
1956
1957
  await this.send({
1957
1958
  type: "evaluate",
1958
- code: `window.location.href = ${JSON.stringify(nextUrl)}`
1959
+ code: `window.location.href = ${JSON.stringify(nextUrl.toString())}`
1959
1960
  });
1960
1961
  const deadline = Date.now() + (opts.timeoutMs ?? 3e4);
1961
1962
  while (Date.now() < deadline) {
1962
1963
  await sleep(250);
1963
1964
  try {
1964
1965
  const { url } = await inspectUrl(this);
1965
- const current = new URL(url);
1966
- if (current.pathname === expected.pathname && current.searchParams.get("open") === expected.searchParams.get("open")) {
1967
- return;
1968
- }
1966
+ if (new URL(url).searchParams.get("inspectOpen") === token) return;
1969
1967
  } catch {
1970
1968
  }
1971
1969
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.500 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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;
@@ -27477,7 +27477,10 @@ function createCloudSession(input) {
27477
27477
  simId: input.simId.trim(),
27478
27478
  apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim()),
27479
27479
  claimId: input.claimId.trim(),
27480
- token: input.token
27480
+ token: input.token,
27481
+ ...input.platform ? { platform: input.platform } : {},
27482
+ ...input.device?.trim() ? { device: input.device.trim() } : {},
27483
+ ...input.artifact ? { artifact: input.artifact } : {}
27481
27484
  };
27482
27485
  if (!session.boxId || !session.boxToken || !session.simId || !session.claimId || !session.token) {
27483
27486
  throw new Error("cloud session requires box, simulator, origin, claim, and tokens");
@@ -27490,7 +27493,10 @@ function createCloudBoxSession(input) {
27490
27493
  service: "box",
27491
27494
  boxId: input.boxId.trim(),
27492
27495
  boxToken: input.boxToken,
27493
- apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim())
27496
+ apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim()),
27497
+ ...input.platform ? { platform: input.platform } : {},
27498
+ ...input.device?.trim() ? { device: input.device.trim() } : {},
27499
+ ...input.artifact ? { artifact: input.artifact } : {}
27494
27500
  };
27495
27501
  if (!session.boxId || !session.boxToken) {
27496
27502
  throw new Error("cloud box session requires a box, an origin, and a box token");
@@ -27521,9 +27527,22 @@ function parseCloudSession(encoded) {
27521
27527
  if (typeof boxId !== "string" || typeof boxToken !== "string" || typeof apiOrigin !== "string") {
27522
27528
  throw new Error(`${RNX_CLOUD_SESSION_ENV} is invalid`);
27523
27529
  }
27530
+ const platform = parsed.platform === "ios" || parsed.platform === "android" ? parsed.platform : void 0;
27531
+ const device = typeof parsed.device === "string" ? parsed.device : void 0;
27532
+ const artifact = isRecord4(parsed.artifact) && typeof parsed.artifact.sha256 === "string" ? {
27533
+ sha256: parsed.artifact.sha256,
27534
+ bytes: typeof parsed.artifact.bytes === "number" ? parsed.artifact.bytes : void 0
27535
+ } : void 0;
27524
27536
  try {
27525
27537
  if (parsed.service === "box") {
27526
- return createCloudBoxSession({ boxId, boxToken, apiOrigin });
27538
+ return createCloudBoxSession({
27539
+ boxId,
27540
+ boxToken,
27541
+ apiOrigin,
27542
+ platform,
27543
+ device,
27544
+ artifact
27545
+ });
27527
27546
  }
27528
27547
  const simId = parsed.simId;
27529
27548
  const claimId = parsed.claimId;
@@ -27531,7 +27550,17 @@ function parseCloudSession(encoded) {
27531
27550
  if (parsed.service !== "sim" || typeof simId !== "string" || typeof claimId !== "string" || typeof token !== "string") {
27532
27551
  throw new Error("unreadable cloud session");
27533
27552
  }
27534
- return createCloudSession({ boxId, boxToken, simId, apiOrigin, claimId, token });
27553
+ return createCloudSession({
27554
+ boxId,
27555
+ boxToken,
27556
+ simId,
27557
+ apiOrigin,
27558
+ claimId,
27559
+ token,
27560
+ platform,
27561
+ device,
27562
+ artifact
27563
+ });
27535
27564
  } catch {
27536
27565
  throw new Error(`${RNX_CLOUD_SESSION_ENV} is invalid`);
27537
27566
  }
@@ -27555,26 +27584,6 @@ var init_cloud_session = __esm({
27555
27584
  });
27556
27585
 
27557
27586
  // cli/commands/detect.ts
27558
- function findProjectRoot(cwd) {
27559
- let dir = cwd;
27560
- while (true) {
27561
- if ((0, import_fs2.existsSync)((0, import_path2.join)(dir, "turbo.json")) || (0, import_fs2.existsSync)((0, import_path2.join)(dir, "nx.json")) || (0, import_fs2.existsSync)((0, import_path2.join)(dir, "lerna.json")) || (0, import_fs2.existsSync)((0, import_path2.join)(dir, "pnpm-workspace.yaml"))) {
27562
- return dir;
27563
- }
27564
- const pkgPath = (0, import_path2.join)(dir, "package.json");
27565
- if ((0, import_fs2.existsSync)(pkgPath)) {
27566
- try {
27567
- const pkg = JSON.parse((0, import_fs2.readFileSync)(pkgPath, "utf8"));
27568
- if (pkg.workspaces) return dir;
27569
- } catch {
27570
- }
27571
- }
27572
- const parent = (0, import_path2.dirname)(dir);
27573
- if (parent === dir) break;
27574
- dir = parent;
27575
- }
27576
- return cwd;
27577
- }
27578
27587
  function detectFramework2(deps) {
27579
27588
  if (deps.one) return "one";
27580
27589
  if (deps.expo) return "expo";
@@ -27851,9 +27860,28 @@ function searchMetroAssetDest(bundlePath, descriptors) {
27851
27860
  (0, import_node_path15.resolve)(bundleDirectory, "..", "assets")
27852
27861
  ];
27853
27862
  const cwd = process.cwd();
27854
- if (detectProject(cwd)?.hasMetroConfig) {
27855
- const root = findProjectRoot(cwd);
27856
- candidates.push((0, import_node_path15.join)(root, "dist"), (0, import_node_path15.join)(root, "build"));
27863
+ let projectDirectory = null;
27864
+ for (const start of [bundleDirectory, cwd]) {
27865
+ let directory = (0, import_node_path15.resolve)(start);
27866
+ while (true) {
27867
+ if (detectProject(directory)?.hasMetroConfig) {
27868
+ projectDirectory = directory;
27869
+ break;
27870
+ }
27871
+ const parent = (0, import_node_path15.dirname)(directory);
27872
+ if (parent === directory) break;
27873
+ directory = parent;
27874
+ }
27875
+ if (projectDirectory) break;
27876
+ }
27877
+ if (projectDirectory) {
27878
+ candidates.push(
27879
+ (0, import_node_path15.join)(projectDirectory, "assets"),
27880
+ (0, import_node_path15.join)(projectDirectory, "dist"),
27881
+ (0, import_node_path15.join)(projectDirectory, "dist", "assets"),
27882
+ (0, import_node_path15.join)(projectDirectory, "build"),
27883
+ (0, import_node_path15.join)(projectDirectory, "build", "assets")
27884
+ );
27857
27885
  }
27858
27886
  const searched = [];
27859
27887
  const holders = [];
@@ -28050,6 +28078,10 @@ function readCreateResponse(value, expectedBytes, expectedSha256) {
28050
28078
  };
28051
28079
  }
28052
28080
  async function createCloudBox(options) {
28081
+ const platform = options.platform ?? "ios";
28082
+ if (platform === "android") {
28083
+ throw new UnsupportedRemoteHostError("android", "nano");
28084
+ }
28053
28085
  const apiOrigin = resolveCloudOrigin(options.apiOrigin);
28054
28086
  const artifact = await produceCloudArtifact(options.bundlePath);
28055
28087
  const boxName = options.boxName?.trim();
@@ -28057,7 +28089,7 @@ async function createCloudBox(options) {
28057
28089
  authorization: options.authorization,
28058
28090
  "x-rnx-box-size": "nano",
28059
28091
  "x-rnx-artifact-sha256": artifact.sha256,
28060
- "x-rnx-platform": "ios",
28092
+ "x-rnx-platform": platform,
28061
28093
  "x-rnx-device": options.device,
28062
28094
  ...options.accountId ? { "x-rnx-account-id": options.accountId } : null,
28063
28095
  ...boxName ? { "x-rnx-box-name": boxName } : null
@@ -28103,7 +28135,13 @@ async function createCloudBox(options) {
28103
28135
  simId: created.receipt.simulator.simId,
28104
28136
  apiOrigin,
28105
28137
  claimId: created.receipt.simulator.claim.id,
28106
- token: created.simulatorToken
28138
+ token: created.simulatorToken,
28139
+ platform,
28140
+ device: options.device,
28141
+ artifact: {
28142
+ sha256: artifact.sha256,
28143
+ bytes: artifact.bytes.length
28144
+ }
28107
28145
  });
28108
28146
  return {
28109
28147
  receipt: created.receipt,
@@ -28146,7 +28184,7 @@ function createCloudBridgeForParsed(parsed) {
28146
28184
  if (!session) return null;
28147
28185
  return session.service === "box" ? new CloudBoxBridge(session) : new CloudBridge(session);
28148
28186
  }
28149
- var import_node_crypto5, import_node_fs14, import_node_path15, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
28187
+ var import_node_crypto5, import_node_fs14, import_node_path15, UnsupportedRemoteHostError, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
28150
28188
  var init_cloud_client = __esm({
28151
28189
  "cli/cloud-client.ts"() {
28152
28190
  "use strict";
@@ -28164,9 +28202,22 @@ var init_cloud_client = __esm({
28164
28202
  init_auth();
28165
28203
  init_cloud_session();
28166
28204
  init_detect();
28205
+ UnsupportedRemoteHostError = class extends Error {
28206
+ code = "unsupported_host";
28207
+ platform;
28208
+ host;
28209
+ constructor(platform, host, message) {
28210
+ super(
28211
+ message ?? `rnx remote ${platform} does not support --${host}: rnxsim/cloud only creates iOS simulators`
28212
+ );
28213
+ this.name = "UnsupportedRemoteHostError";
28214
+ this.platform = platform;
28215
+ this.host = host;
28216
+ }
28217
+ };
28167
28218
  DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
28168
28219
  MAX_RNX_CLOUD_BUNDLE_BYTES = RNX_CLOUD_MAX_ARTIFACT_BYTES;
28169
- REMOTE_COMMAND = "rnx ios --remote";
28220
+ REMOTE_COMMAND = "rnx remote";
28170
28221
  MAX_ASSET_DEST_FILES = 25e3;
28171
28222
  ACCOUNT_CHOICE_REFUSALS = /* @__PURE__ */ new Set([
28172
28223
  "accountId is required",
@@ -34878,11 +34929,13 @@ async function runOpenCommand(args, opts = {}) {
34878
34929
  printBridgeWorldNotice(parsed.wsPort, baseUrl);
34879
34930
  const savedSimId = readCurrentSimId();
34880
34931
  const shouldReuseCurrentSim = !openInNewSim;
34932
+ const token = `cli-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
34933
+ const simMatchesToken = (sim) => sim.url?.includes(`inspectOpen=${token}`) ?? false;
34881
34934
  if (shouldReuseCurrentSim) {
34882
34935
  const bridge = createBridgeFromParsed(parsed);
34883
34936
  const simHint = parsed.simId ? ` --sim ${parsed.simId}` : "";
34884
34937
  let fallBackToNewSim = false;
34885
- let preNavSimIds = /* @__PURE__ */ new Set();
34938
+ let navigatedShellUrl = null;
34886
34939
  try {
34887
34940
  let targetSim = null;
34888
34941
  let targetShellUrl = null;
@@ -34932,17 +34985,18 @@ async function runOpenCommand(args, opts = {}) {
34932
34985
  }
34933
34986
  }
34934
34987
  if (!fallBackToNewSim && targetSim) {
34935
- preNavSimIds = new Set(sims.map((sim) => sim.id));
34936
34988
  const resolvedBaseUrl = hasExplicitBaseUrl || looksLikeSootsimUrl(target) ? baseUrl : deriveCurrentSimBaseUrl(targetSim, baseUrl);
34937
- const shellUrl = targetShellUrl ?? await buildShellUrl(
34989
+ navigatedShellUrl = targetShellUrl ?? await buildShellUrl(
34938
34990
  target,
34939
34991
  applyRNXConfigToUrl(resolvedBaseUrl, runtimeConfig),
34940
34992
  buildShellUrlOpts
34941
34993
  );
34994
+ const navigationUrl = new URL(navigatedShellUrl);
34995
+ navigationUrl.searchParams.set("inspectOpen", token);
34942
34996
  bridge.send({
34943
34997
  type: "evaluate",
34944
34998
  simId: targetSim.id,
34945
- code: `window.location.href = ${JSON.stringify(shellUrl)}`
34999
+ code: `window.location.href = ${JSON.stringify(navigationUrl.toString())}`
34946
35000
  }).catch(() => {
34947
35001
  });
34948
35002
  }
@@ -34957,18 +35011,25 @@ async function runOpenCommand(args, opts = {}) {
34957
35011
  });
34958
35012
  rnxExit(1);
34959
35013
  }
34960
- if (!fallBackToNewSim && targetSim) {
34961
- await sleep2(1500);
34962
- const navSim = targetSim;
34963
- const reloadedSim = await waitForSimMatch(
35014
+ if (!fallBackToNewSim && targetSim && navigatedShellUrl) {
35015
+ const navigatedSim = await waitForSimMatch(
34964
35016
  parsed.wsPort,
34965
35017
  parsed.commandTimeoutMs,
34966
- (sim) => sim.readyState === "open" && simUsesDriver(sim, driverId) && (sim.id === navSim.id || !preNavSimIds.has(sim.id) && sim.isPrimary),
35018
+ (sim) => sim.readyState === "open" && simUsesDriver(sim, driverId) && simMatchesToken(sim),
34967
35019
  { attempts: Math.round(30 * flowTimeoutScale()) }
34968
35020
  );
34969
- if (reloadedSim && reloadedSim.id !== navSim.id) {
34970
- targetSim = reloadedSim;
35021
+ if (!navigatedSim) {
35022
+ console.error(
35023
+ ` timed out waiting for sim ${targetSim.id} to load ${navigatedShellUrl}`
35024
+ );
35025
+ await printBridgeFailureDiagnostics(bridge, {
35026
+ errorsCommand: `rnx get errors 5${simHint}`,
35027
+ warningsCommand: `rnx get warnings 5${simHint}`,
35028
+ requestsCommand: `rnx get requests 5${simHint}`
35029
+ });
35030
+ rnxExit(1);
34971
35031
  }
35032
+ targetSim = navigatedSim;
34972
35033
  const ready = await waitForSimReady(
34973
35034
  parsed.wsPort,
34974
35035
  parsed.commandTimeoutMs,
@@ -34988,13 +35049,12 @@ async function runOpenCommand(args, opts = {}) {
34988
35049
  }
34989
35050
  ready.bridge.close();
34990
35051
  saveCurrentSimId(targetSim.id);
34991
- const resolvedBaseUrl = hasExplicitBaseUrl || looksLikeSootsimUrl(target) ? baseUrl : deriveCurrentSimBaseUrl(targetSim, baseUrl);
34992
- const shellUrl = targetShellUrl ?? await buildShellUrl(
34993
- target,
34994
- applyRNXConfigToUrl(resolvedBaseUrl, runtimeConfig),
34995
- buildShellUrlOpts
35052
+ printOpenedSim(
35053
+ navigatedShellUrl,
35054
+ { ...targetSim, url: navigatedShellUrl },
35055
+ "current sim",
35056
+ quiet
34996
35057
  );
34997
- printOpenedSim(shellUrl, { ...targetSim, url: shellUrl }, "current sim", quiet);
34998
35058
  await maybeDescribeAfterOpen(parsed.wsPort, targetSim.id, args);
34999
35059
  return parsed.wsPort;
35000
35060
  }
@@ -35003,7 +35063,6 @@ async function runOpenCommand(args, opts = {}) {
35003
35063
  }
35004
35064
  }
35005
35065
  const configuredBaseUrl = applyRNXConfigToUrl(baseUrl, runtimeConfig);
35006
- const token = `cli-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
35007
35066
  const openUrl2 = await buildOpenUrl(target, configuredBaseUrl, token, buildShellUrlOpts);
35008
35067
  const ownerPid = getStableOwnerPid();
35009
35068
  if (!ownerPid) {
@@ -35012,7 +35071,6 @@ async function runOpenCommand(args, opts = {}) {
35012
35071
  );
35013
35072
  rnxExit(1);
35014
35073
  }
35015
- const simMatchesToken = (sim) => sim.url?.includes(`inspectOpen=${token}`) ?? false;
35016
35074
  const driver = getDriver(driverId);
35017
35075
  if (!driver) {
35018
35076
  console.error(` unknown driver "${driverId}" \u2014 run \`rnx list --drivers\``);
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.500 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.501 | (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.500",
3
+ "version": "0.1.501",
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",
@@ -238,7 +238,7 @@ upstream detox surface.
238
238
  ```js
239
239
  // rnx-detox.config.cjs
240
240
  module.exports = {
241
- preset: 'rnxsim/detox/jest-preset',
241
+ preset: 'rnxsim/detox',
242
242
  rootDir: __dirname,
243
243
  testMatch: ['<rootDir>/e2e/**/*.test.ts'],
244
244
  }
@@ -294,7 +294,7 @@ rnx detox init # scaffold config + e2e/example.test.ts
294
294
  - **"no rnx shell reachable"** — start one yourself
295
295
  (`rnx open <port>`) or pass `--port <n>`.
296
296
  - **"jest cannot find module 'detox'"** — the preset isn't wired. confirm
297
- `preset: 'rnxsim/detox/jest-preset'` is in the jest config jest
297
+ `preset: 'rnxsim/detox'` is in the jest config jest
298
298
  actually loaded (`--config` overrides package.json).
299
299
  - **matchers fail on elements that exist** — canvas has no DOM. use
300
300
  `by.id` (testID); `rnx describe` shows what the shell sees.
@@ -3,6 +3,8 @@ import type { BridgeCommandType } from './bridge-contract.ts'
3
3
  export const RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024
4
4
  export const RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256
5
5
  export const RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024
6
+ export const RNX_CLOUD_TEST_FILES_MAX_COUNT = 256
7
+ export const RNX_CLOUD_TEST_FILES_MAX_BYTES = 500_000
6
8
 
7
9
  export const RNX_CLOUD_COMMAND_TYPES = Object.freeze([
8
10
  'state',
package/src/sim-client.ts CHANGED
@@ -310,24 +310,22 @@ export class SimClient implements WsBridge, InspectBridge {
310
310
  `sim ${this.simId} reported no URL to derive the shell from`,
311
311
  )
312
312
  }
313
- const nextUrl = buildSimOpenUrl(currentUrl, target)
314
- const expected = new URL(nextUrl)
313
+ const nextUrl = new URL(buildSimOpenUrl(currentUrl, target))
314
+ // the page being replaced keeps answering until the browser commits the
315
+ // navigation, and it may already sit on this target. only a one-off token
316
+ // in the new URL proves the reloaded page is the one answering.
317
+ const token = `sim-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`
318
+ nextUrl.searchParams.set('inspectOpen', token)
315
319
  await this.send({
316
320
  type: 'evaluate',
317
- code: `window.location.href = ${JSON.stringify(nextUrl)}`,
321
+ code: `window.location.href = ${JSON.stringify(nextUrl.toString())}`,
318
322
  })
319
323
  const deadline = Date.now() + (opts.timeoutMs ?? 30_000)
320
324
  while (Date.now() < deadline) {
321
325
  await sleep(250)
322
326
  try {
323
327
  const { url } = await inspectUrl(this)
324
- const current = new URL(url)
325
- if (
326
- current.pathname === expected.pathname &&
327
- current.searchParams.get('open') === expected.searchParams.get('open')
328
- ) {
329
- return
330
- }
328
+ if (new URL(url).searchParams.get('inspectOpen') === token) return
331
329
  } catch {
332
330
  // page is mid-reload; keep polling until the deadline.
333
331
  }