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.
- package/README.md +1 -1
- package/cli/cloud-client.ts +90 -7
- package/cli/cloud-dispatch.ts +27 -27
- package/cli/cloud-session.ts +61 -6
- package/cli/commands/control.ts +33 -31
- package/cli/commands/detox.ts +157 -159
- package/cli/commands/platform.ts +170 -48
- package/cli/commands/preview.ts +1 -1
- package/cli/commands/test.ts +403 -95
- package/cli/main.ts +11 -0
- package/cli/outbound-endpoints.ts +10 -0
- package/detox/jest-preset.cjs +1 -6
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +7 -1
- package/dist-lib/cloud-contract.mjs +5 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/detox/jest-preset.cjs +1 -6
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +54 -29
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +39 -12
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +6 -8
- package/dist-lib/sdk.mjs +6 -8
- package/dist-lib/skills.cjs +109 -51
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/skills/rnx-test/SKILL.md +2 -2
- package/src/cloud-contract.ts +2 -0
- package/src/sim-client.ts +8 -10
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
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
|
|
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
|
-
|
|
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
|
}
|
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
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({
|
|
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({
|
|
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
|
-
|
|
27855
|
-
|
|
27856
|
-
|
|
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":
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
|
35018
|
+
(sim) => sim.readyState === "open" && simUsesDriver(sim, driverId) && simMatchesToken(sim),
|
|
34967
35019
|
{ attempts: Math.round(30 * flowTimeoutScale()) }
|
|
34968
35020
|
);
|
|
34969
|
-
if (
|
|
34970
|
-
|
|
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
|
-
|
|
34992
|
-
|
|
34993
|
-
|
|
34994
|
-
|
|
34995
|
-
|
|
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.
|
|
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
package/skills/rnx-test/SKILL.md
CHANGED
|
@@ -238,7 +238,7 @@ upstream detox surface.
|
|
|
238
238
|
```js
|
|
239
239
|
// rnx-detox.config.cjs
|
|
240
240
|
module.exports = {
|
|
241
|
-
preset: 'rnxsim/detox
|
|
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
|
|
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.
|
package/src/cloud-contract.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
}
|