rnxsim 0.1.381 → 0.1.383
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 +19 -6
- package/cli/app-fonts.ts +1 -1
- package/cli/bin.ts +118 -26
- package/cli/bridge-diagnostics.ts +1 -1
- package/cli/bridge-flow-runner.ts +9 -9
- package/cli/browser-evals.ts +3 -3
- package/cli/cli-update.ts +261 -0
- package/cli/cloud-client.ts +407 -0
- package/cli/cloud-dispatch.ts +165 -0
- package/cli/cloud-session.ts +156 -0
- package/cli/command-contract.ts +2 -2
- package/cli/command-registry.ts +9 -0
- package/cli/commands/agent-wrapper.ts +4 -4
- package/cli/commands/agent.ts +3 -3
- package/cli/commands/box/checkout-plane.ts +16 -8
- package/cli/commands/box/rnx-command.ts +2 -2
- package/cli/commands/box/search-command.ts +2 -2
- package/cli/commands/box.ts +123 -70
- package/cli/commands/config.ts +3 -2
- package/cli/commands/control.ts +6 -6
- package/cli/commands/cpu-profile.ts +2 -2
- package/cli/commands/daemon.ts +7 -7
- package/cli/commands/debug.ts +2 -2
- package/cli/commands/detox.ts +7 -7
- package/cli/commands/diagnose.ts +1 -1
- package/cli/commands/electron.ts +1 -1
- package/cli/commands/film.ts +1 -1
- package/cli/commands/flow.ts +4 -4
- package/cli/commands/inspect/core.ts +58 -7
- package/cli/commands/inspect/env.ts +5 -3
- package/cli/commands/inspect/shared.ts +2 -1
- package/cli/commands/inspect/wait-event.ts +1 -1
- package/cli/commands/inspect/wait-ready.ts +15 -5
- package/cli/commands/inspect.ts +31 -9
- package/cli/commands/install-desktop.ts +2 -2
- package/cli/commands/maestro.ts +3 -3
- package/cli/commands/permissions.ts +1 -1
- package/cli/commands/platform.ts +91 -0
- package/cli/commands/record.ts +3 -3
- package/cli/commands/report-issue.ts +1 -1
- package/cli/commands/runtime.ts +1 -1
- package/cli/commands/screenshot-mode.ts +1 -1
- package/cli/commands/screenshot.ts +25 -0
- package/cli/commands/serve.ts +1 -1
- package/cli/commands/skills.ts +1 -1
- package/cli/commands/timeline.ts +1 -1
- package/cli/commands/upgrade.ts +8 -34
- package/cli/commands/upload.ts +3 -3
- package/cli/commands/version.ts +14 -3
- package/cli/commands/what-happened.ts +2 -2
- package/cli/current-sim.ts +43 -30
- package/cli/desktop-companion.ts +1 -1
- package/cli/drivers/electron.ts +1 -1
- package/cli/drivers/playwright.ts +3 -3
- package/cli/drivers/types.ts +4 -4
- package/cli/flow-file.ts +3 -3
- package/cli/help-core.ts +18 -11
- package/cli/hidden-runtime-alias.ts +1 -1
- package/cli/hints.ts +2 -2
- package/cli/maestro-js.ts +2 -2
- package/cli/outbound-endpoints.ts +40 -6
- package/cli/parse-args.ts +1 -1
- package/cli/registry.ts +1 -1
- package/cli/resolve-assets.ts +2 -2
- package/cli/secure-file.ts +31 -0
- package/cli/shell-init.ts +98 -0
- package/cli/ws-bridge.ts +18 -8
- package/detox/expectations.ts +1 -1
- package/detox/gestures.ts +3 -3
- package/detox/index.ts +3 -3
- 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 +20 -8
- package/dist-lib/bridge-contract-input.mjs +20 -8
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +217 -0
- package/dist-lib/capture-contract.mjs +187 -0
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +41 -0
- package/dist-lib/cloud-contract.mjs +13 -0
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +4 -4
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +9 -1
- package/dist-lib/host/bridge-host.cjs +15 -10
- 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 +361 -75
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.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 +44 -6
- package/dist-lib/sdk.mjs +44 -6
- package/dist-lib/skills.cjs +436 -155
- package/dist-lib/vite.cjs +1 -1
- package/package.json +20 -4
- package/scripts/dev-server-scanner.ts +3 -3
- package/skills/contrast/SKILL.md +1 -1
- package/skills/rnx-perf/SKILL.md +68 -52
- package/src/app-url.ts +2 -3
- package/src/bridge-contract-input.ts +25 -6
- package/src/bridge-contract.ts +35 -5
- package/src/capture-contract.ts +576 -0
- package/src/cloud-contract.ts +18 -0
- package/src/home-paths.ts +9 -3
- package/src/host/agent-host.ts +1 -1
- package/src/host/bridge-host.ts +13 -11
- package/src/host/plane-host.ts +2 -2
- package/src/index.ts +25 -0
- package/src/native-dev-bundle-url.ts +2 -2
- package/src/screenshots/orchestrate.ts +1 -1
- package/src/screenshots/org-deck.ts +1 -1
- package/src/settings-bundle.ts +1 -1
- package/src/sim-client.ts +4 -0
- package/src/vite-plugin-one.ts +2 -2
- package/src/vite-plugin.ts +1 -1
- package/cli/commands/box/cloud-box.ts +0 -294
package/dist-lib/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.383 | (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;
|
|
@@ -8,8 +8,8 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
8
8
|
var __getProtoOf = Object.getPrototypeOf;
|
|
9
9
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
10
|
var __export = (target, all) => {
|
|
11
|
-
for (var
|
|
12
|
-
__defProp(target,
|
|
11
|
+
for (var name2 in all)
|
|
12
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
13
13
|
};
|
|
14
14
|
var __copyProps = (to, from, except, desc) => {
|
|
15
15
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -35,6 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
DEFAULT_SOOTSIM_BRIDGE_PORT: () => DEFAULT_SOOTSIM_BRIDGE_PORT,
|
|
36
36
|
DEFAULT_SOOTSIM_BRIDGE_URL: () => DEFAULT_SOOTSIM_BRIDGE_URL,
|
|
37
37
|
DEFAULT_SOOTSIM_SHELL_URL: () => DEFAULT_SOOTSIM_SHELL_URL,
|
|
38
|
+
RNX_SCREEN_CAPTURE_VERSION: () => RNX_SCREEN_CAPTURE_VERSION,
|
|
38
39
|
SimClient: () => SimClient,
|
|
39
40
|
SimClientError: () => SimClientError,
|
|
40
41
|
SimConnectError: () => SimConnectError,
|
|
@@ -44,9 +45,14 @@ __export(src_exports, {
|
|
|
44
45
|
SimResetError: () => SimResetError,
|
|
45
46
|
SimTapError: () => SimTapError,
|
|
46
47
|
connect: () => connect,
|
|
48
|
+
isRnxCaptureRegionAtlas: () => isRnxCaptureRegionAtlas,
|
|
49
|
+
isRnxScreenCapture: () => isRnxScreenCapture,
|
|
47
50
|
jumpToSourceBabelPlugin: () => sootsimJumpToSourceBabelPlugin,
|
|
48
51
|
metroPlugin: () => metro_plugin_default,
|
|
49
|
-
|
|
52
|
+
rnxCaptureRasterRegions: () => rnxCaptureRasterRegions,
|
|
53
|
+
rnxPlugin: () => rnxPlugin,
|
|
54
|
+
rnxRasterFrames: () => rnxRasterFrames,
|
|
55
|
+
selectRnxRasterNodeIds: () => selectRnxRasterNodeIds
|
|
50
56
|
});
|
|
51
57
|
module.exports = __toCommonJS(src_exports);
|
|
52
58
|
|
|
@@ -208,8 +214,32 @@ function tryBuildDarwinCommFfi() {
|
|
|
208
214
|
}
|
|
209
215
|
}
|
|
210
216
|
|
|
217
|
+
// cli/secure-file.ts
|
|
218
|
+
var import_node_crypto = require("node:crypto");
|
|
219
|
+
var import_node_fs = require("node:fs");
|
|
220
|
+
var import_node_path = require("node:path");
|
|
221
|
+
function writeSecureJsonAtomic(filepath, value) {
|
|
222
|
+
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(filepath), { recursive: true });
|
|
223
|
+
const temporary = `${filepath}.tmp-${process.pid}-${(0, import_node_crypto.randomUUID)()}`;
|
|
224
|
+
let descriptor = null;
|
|
225
|
+
try {
|
|
226
|
+
descriptor = (0, import_node_fs.openSync)(temporary, "wx", 384);
|
|
227
|
+
(0, import_node_fs.fchmodSync)(descriptor, 384);
|
|
228
|
+
(0, import_node_fs.writeFileSync)(descriptor, `${JSON.stringify(value, null, 2)}
|
|
229
|
+
`);
|
|
230
|
+
(0, import_node_fs.fsyncSync)(descriptor);
|
|
231
|
+
(0, import_node_fs.closeSync)(descriptor);
|
|
232
|
+
descriptor = null;
|
|
233
|
+
(0, import_node_fs.renameSync)(temporary, filepath);
|
|
234
|
+
} catch (error) {
|
|
235
|
+
if (descriptor !== null) (0, import_node_fs.closeSync)(descriptor);
|
|
236
|
+
(0, import_node_fs.rmSync)(temporary, { force: true });
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
211
241
|
// cli/current-sim.ts
|
|
212
|
-
var CURRENT_SIM_VERSION =
|
|
242
|
+
var CURRENT_SIM_VERSION = 2;
|
|
213
243
|
var CURRENT_SIM_PATH_ENV = "SOOTSIM_CLI_CURRENT_SIM_PATH";
|
|
214
244
|
var IDENTITY_ENV_VARS = [
|
|
215
245
|
"RNX_CLI_IDENTITY",
|
|
@@ -260,10 +290,10 @@ function findTopAncestor(start, maxDepth = 20) {
|
|
|
260
290
|
return pid;
|
|
261
291
|
}
|
|
262
292
|
function getCliIdentity() {
|
|
263
|
-
for (const
|
|
264
|
-
const value = process.env[
|
|
293
|
+
for (const name2 of IDENTITY_ENV_VARS) {
|
|
294
|
+
const value = process.env[name2];
|
|
265
295
|
if (value && value.trim()) {
|
|
266
|
-
return { key: `${
|
|
296
|
+
return { key: `${name2}:${value.trim()}`, source: name2, stable: true };
|
|
267
297
|
}
|
|
268
298
|
}
|
|
269
299
|
const topPid = findTopAncestor(process.ppid);
|
|
@@ -282,35 +312,50 @@ function getCurrentSimPath() {
|
|
|
282
312
|
const key = getCliIdentityKey();
|
|
283
313
|
return (0, import_path.join)((0, import_os.tmpdir)(), `rnx-current-sim-${key}.json`);
|
|
284
314
|
}
|
|
285
|
-
function
|
|
315
|
+
function legacyCloudCredentialDirectory(filepath) {
|
|
316
|
+
return (0, import_path.join)((0, import_path.dirname)(filepath), `${(0, import_path.basename)(filepath)}.credentials`);
|
|
317
|
+
}
|
|
318
|
+
function readCurrentTarget() {
|
|
286
319
|
const filepath = getCurrentSimPath();
|
|
320
|
+
(0, import_fs2.rmSync)(legacyCloudCredentialDirectory(filepath), { recursive: true, force: true });
|
|
287
321
|
if (!(0, import_fs2.existsSync)(filepath)) return null;
|
|
288
322
|
try {
|
|
289
323
|
const parsed = JSON.parse((0, import_fs2.readFileSync)(filepath, "utf8"));
|
|
290
|
-
if (parsed
|
|
324
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
291
325
|
(0, import_fs2.rmSync)(filepath, { force: true });
|
|
292
326
|
return null;
|
|
293
327
|
}
|
|
294
|
-
|
|
328
|
+
const version = Reflect.get(parsed, "version");
|
|
329
|
+
const plane = Reflect.get(parsed, "plane");
|
|
330
|
+
const simId = Reflect.get(parsed, "simId");
|
|
331
|
+
const updatedAt = Reflect.get(parsed, "updatedAt");
|
|
332
|
+
if (version !== 1 && version !== CURRENT_SIM_VERSION || version === CURRENT_SIM_VERSION && plane !== "local" || typeof simId !== "string" || !simId.trim() || typeof updatedAt !== "string") {
|
|
333
|
+
(0, import_fs2.rmSync)(filepath, { force: true });
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
const target = {
|
|
295
337
|
version: CURRENT_SIM_VERSION,
|
|
296
|
-
|
|
297
|
-
|
|
338
|
+
plane: "local",
|
|
339
|
+
simId: simId.trim(),
|
|
340
|
+
updatedAt
|
|
298
341
|
};
|
|
342
|
+
if (version === 1) writeSecureJsonAtomic(filepath, target);
|
|
343
|
+
return target;
|
|
299
344
|
} catch {
|
|
300
345
|
(0, import_fs2.rmSync)(filepath, { force: true });
|
|
301
346
|
return null;
|
|
302
347
|
}
|
|
303
348
|
}
|
|
304
349
|
function readCurrentSimId() {
|
|
305
|
-
return
|
|
350
|
+
return readCurrentTarget()?.simId ?? null;
|
|
306
351
|
}
|
|
307
352
|
function clearCurrentSimId() {
|
|
308
353
|
(0, import_fs2.rmSync)(getCurrentSimPath(), { force: true });
|
|
309
354
|
}
|
|
310
355
|
|
|
311
356
|
// cli/ws-bridge.ts
|
|
312
|
-
var
|
|
313
|
-
var
|
|
357
|
+
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
358
|
+
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
314
359
|
var import_ws = require("ws");
|
|
315
360
|
|
|
316
361
|
// src/bridge-constants.ts
|
|
@@ -340,9 +385,9 @@ function resolveSootsimBridgePort(input = {}) {
|
|
|
340
385
|
var DEFAULT_SOOTSIM_SHELL_URL = "http://localhost:5173/";
|
|
341
386
|
|
|
342
387
|
// src/home-paths.ts
|
|
343
|
-
var
|
|
388
|
+
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
344
389
|
var import_node_os = require("node:os");
|
|
345
|
-
var
|
|
390
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
346
391
|
var RNX_HOME_ENV = "RNX_HOME";
|
|
347
392
|
var ACTIVE_RUNTIME_FILE = "active";
|
|
348
393
|
var DAEMON_LOCKFILE = "daemon.json";
|
|
@@ -350,27 +395,27 @@ var DEV_BRIDGES_DIR = "dev-bridges";
|
|
|
350
395
|
var DAEMON_HEARTBEAT_STALE_MS = 3e4;
|
|
351
396
|
function rnxHomeDir() {
|
|
352
397
|
const override = process.env[RNX_HOME_ENV];
|
|
353
|
-
if (override && override.length > 0) return
|
|
354
|
-
return
|
|
398
|
+
if (override && override.length > 0) return import_node_path2.default.resolve(override);
|
|
399
|
+
return import_node_path2.default.join((0, import_node_os.homedir)(), ".rnx");
|
|
355
400
|
}
|
|
356
401
|
function runtimesDir() {
|
|
357
|
-
return
|
|
402
|
+
return import_node_path2.default.join(rnxHomeDir(), "runtimes");
|
|
358
403
|
}
|
|
359
404
|
function runtimeDir(version) {
|
|
360
|
-
return
|
|
405
|
+
return import_node_path2.default.join(runtimesDir(), version);
|
|
361
406
|
}
|
|
362
407
|
function activeRuntimeFile() {
|
|
363
|
-
return
|
|
408
|
+
return import_node_path2.default.join(runtimesDir(), ACTIVE_RUNTIME_FILE);
|
|
364
409
|
}
|
|
365
410
|
function daemonLockfilePath() {
|
|
366
|
-
return
|
|
411
|
+
return import_node_path2.default.join(rnxHomeDir(), DAEMON_LOCKFILE);
|
|
367
412
|
}
|
|
368
413
|
function devBridgesDir() {
|
|
369
|
-
return
|
|
414
|
+
return import_node_path2.default.join(rnxHomeDir(), DEV_BRIDGES_DIR);
|
|
370
415
|
}
|
|
371
416
|
function readActiveRuntime() {
|
|
372
417
|
try {
|
|
373
|
-
const value =
|
|
418
|
+
const value = import_node_fs2.default.readFileSync(activeRuntimeFile(), "utf8").trim();
|
|
374
419
|
return value.length > 0 ? value : null;
|
|
375
420
|
} catch {
|
|
376
421
|
return null;
|
|
@@ -379,10 +424,10 @@ function readActiveRuntime() {
|
|
|
379
424
|
var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
380
425
|
function readDaemonLockfile() {
|
|
381
426
|
try {
|
|
382
|
-
const fd =
|
|
427
|
+
const fd = import_node_fs2.default.openSync(daemonLockfilePath(), "r");
|
|
383
428
|
try {
|
|
384
429
|
const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
|
|
385
|
-
const bytesRead =
|
|
430
|
+
const bytesRead = import_node_fs2.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
|
|
386
431
|
const raw = buf.subarray(0, bytesRead).toString("utf8");
|
|
387
432
|
const parsed = JSON.parse(raw);
|
|
388
433
|
if (parsed && parsed.schema === 1 && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number" && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
|
|
@@ -390,7 +435,7 @@ function readDaemonLockfile() {
|
|
|
390
435
|
}
|
|
391
436
|
return null;
|
|
392
437
|
} finally {
|
|
393
|
-
|
|
438
|
+
import_node_fs2.default.closeSync(fd);
|
|
394
439
|
}
|
|
395
440
|
} catch {
|
|
396
441
|
return null;
|
|
@@ -410,7 +455,7 @@ function parseDevBridgeLockfile(raw) {
|
|
|
410
455
|
function readDevBridgeLockfiles() {
|
|
411
456
|
let entries;
|
|
412
457
|
try {
|
|
413
|
-
entries =
|
|
458
|
+
entries = import_node_fs2.default.readdirSync(devBridgesDir(), { withFileTypes: true });
|
|
414
459
|
} catch {
|
|
415
460
|
return [];
|
|
416
461
|
}
|
|
@@ -418,11 +463,11 @@ function readDevBridgeLockfiles() {
|
|
|
418
463
|
for (const entry of entries) {
|
|
419
464
|
if (!entry.isFile() || !/^\d+\.json$/.test(entry.name)) continue;
|
|
420
465
|
try {
|
|
421
|
-
const filePath =
|
|
422
|
-
const fd =
|
|
466
|
+
const filePath = import_node_path2.default.join(devBridgesDir(), entry.name);
|
|
467
|
+
const fd = import_node_fs2.default.openSync(filePath, "r");
|
|
423
468
|
try {
|
|
424
469
|
const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
|
|
425
|
-
const bytesRead =
|
|
470
|
+
const bytesRead = import_node_fs2.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
|
|
426
471
|
const lockfile = parseDevBridgeLockfile(
|
|
427
472
|
buf.subarray(0, bytesRead).toString("utf8")
|
|
428
473
|
);
|
|
@@ -430,7 +475,7 @@ function readDevBridgeLockfiles() {
|
|
|
430
475
|
lockfiles.push(lockfile);
|
|
431
476
|
}
|
|
432
477
|
} finally {
|
|
433
|
-
|
|
478
|
+
import_node_fs2.default.closeSync(fd);
|
|
434
479
|
}
|
|
435
480
|
} catch {
|
|
436
481
|
}
|
|
@@ -458,6 +503,38 @@ function isDevBridgeLockfileFresh(lock, now = Date.now()) {
|
|
|
458
503
|
}
|
|
459
504
|
}
|
|
460
505
|
|
|
506
|
+
// src/cloud-contract.ts
|
|
507
|
+
var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
508
|
+
var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
|
|
509
|
+
|
|
510
|
+
// src/public-brand.ts
|
|
511
|
+
var name = "rnx";
|
|
512
|
+
var rnxPublicBrand = Object.freeze({
|
|
513
|
+
name,
|
|
514
|
+
packageName: "rnxsim",
|
|
515
|
+
commandName: "rnx",
|
|
516
|
+
domain: "rnxsim.com",
|
|
517
|
+
origin: "https://rnxsim.com"
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
// src/backend-origin.ts
|
|
521
|
+
function normalizeHostname(hostname) {
|
|
522
|
+
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
523
|
+
}
|
|
524
|
+
function isLoopbackHost(hostname) {
|
|
525
|
+
const normalized = normalizeHostname(hostname);
|
|
526
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// cli/cloud-session.ts
|
|
530
|
+
var MAX_ENCODED_SESSION_BYTES = 32 * 1024;
|
|
531
|
+
var RNX_SHELL_UPDATE_PREFIX = "__RNX_SHELL_UPDATE_V1__";
|
|
532
|
+
var RNX_SHELL_UPDATE_SET_PREFIX = `${RNX_SHELL_UPDATE_PREFIX}set:`;
|
|
533
|
+
var RNX_SHELL_UPDATE_UNSET = `${RNX_SHELL_UPDATE_PREFIX}unset`;
|
|
534
|
+
|
|
535
|
+
// cli/cloud-client.ts
|
|
536
|
+
var DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
|
|
537
|
+
|
|
461
538
|
// cli/ws-bridge.ts
|
|
462
539
|
function bridgeWsUrl(wsPort) {
|
|
463
540
|
return `ws://localhost:${wsPort}`;
|
|
@@ -467,17 +544,17 @@ function liveDevBridgeLockfiles() {
|
|
|
467
544
|
return readDevBridgeLockfiles().filter((lockfile) => isDevBridgeLockfileFresh(lockfile));
|
|
468
545
|
}
|
|
469
546
|
function checkoutRoot(cwd) {
|
|
470
|
-
let current =
|
|
547
|
+
let current = import_node_path3.default.resolve(cwd);
|
|
471
548
|
while (true) {
|
|
472
|
-
if (
|
|
473
|
-
const parent =
|
|
549
|
+
if (import_node_fs3.default.existsSync(import_node_path3.default.join(current, ".git"))) return current;
|
|
550
|
+
const parent = import_node_path3.default.dirname(current);
|
|
474
551
|
if (parent === current) return null;
|
|
475
552
|
current = parent;
|
|
476
553
|
}
|
|
477
554
|
}
|
|
478
555
|
function pathContains(parent, child) {
|
|
479
|
-
const relative =
|
|
480
|
-
return relative === "" || relative !== ".." && !relative.startsWith(`..${
|
|
556
|
+
const relative = import_node_path3.default.relative(parent, child);
|
|
557
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${import_node_path3.default.sep}`) && !import_node_path3.default.isAbsolute(relative);
|
|
481
558
|
}
|
|
482
559
|
function resolveDefaultDevBridgeLockfile() {
|
|
483
560
|
const lockfiles = liveDevBridgeLockfiles();
|
|
@@ -638,6 +715,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
638
715
|
}
|
|
639
716
|
});
|
|
640
717
|
return {
|
|
718
|
+
plane: "local",
|
|
641
719
|
async send(cmd, callOpts) {
|
|
642
720
|
const effectiveTimeoutMs = callOpts?.timeoutMs ?? commandTimeoutMs;
|
|
643
721
|
const sendOnce = async (defaultSimId) => {
|
|
@@ -1917,6 +1995,39 @@ async function inspectWarnings(bridge, limit = 20) {
|
|
|
1917
1995
|
return Array.isArray(result) ? result : [];
|
|
1918
1996
|
}
|
|
1919
1997
|
async function inspectLogs(bridge) {
|
|
1998
|
+
if (bridge.plane === "cloud") {
|
|
1999
|
+
const state = await bridge.send({
|
|
2000
|
+
type: "state",
|
|
2001
|
+
stateOptions: {
|
|
2002
|
+
screenshot: false,
|
|
2003
|
+
tree: false,
|
|
2004
|
+
route: false,
|
|
2005
|
+
errors: false,
|
|
2006
|
+
logs: true,
|
|
2007
|
+
logLimit: 100
|
|
2008
|
+
}
|
|
2009
|
+
});
|
|
2010
|
+
const recentLogs = state && typeof state === "object" && Array.isArray(Reflect.get(state, "recentLogs")) ? Reflect.get(state, "recentLogs") : [];
|
|
2011
|
+
return recentLogs.flatMap((entry, index) => {
|
|
2012
|
+
if (!entry || typeof entry !== "object") return [];
|
|
2013
|
+
const text = Reflect.get(entry, "text");
|
|
2014
|
+
const rawLevel = Reflect.get(entry, "level");
|
|
2015
|
+
if (typeof text !== "string") return [];
|
|
2016
|
+
const level = rawLevel === "log" || rawLevel === "info" || rawLevel === "warn" || rawLevel === "error" || rawLevel === "debug" ? rawLevel : "error";
|
|
2017
|
+
const at = Reflect.get(entry, "at");
|
|
2018
|
+
const ts = typeof at === "number" && Number.isFinite(at) ? at : 0;
|
|
2019
|
+
return [
|
|
2020
|
+
{
|
|
2021
|
+
id: `cloud-${ts}-${index}`,
|
|
2022
|
+
source: "rnx-cloud",
|
|
2023
|
+
level,
|
|
2024
|
+
ts,
|
|
2025
|
+
args: [text],
|
|
2026
|
+
stack: null
|
|
2027
|
+
}
|
|
2028
|
+
];
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
1920
2031
|
const res = await bridge.send({
|
|
1921
2032
|
type: "evaluate",
|
|
1922
2033
|
code: `(() => {
|
|
@@ -1951,7 +2062,7 @@ function filterLogEntries(entries, opts = {}) {
|
|
|
1951
2062
|
if (!opts.showInternal) {
|
|
1952
2063
|
out = out.filter((e) => {
|
|
1953
2064
|
const first = e.args[0];
|
|
1954
|
-
return !(typeof first === "string" &&
|
|
2065
|
+
return !(typeof first === "string" && /^\[(?:rnx|sootsim)(?:\s[^\]]*)?\]/.test(first));
|
|
1955
2066
|
});
|
|
1956
2067
|
}
|
|
1957
2068
|
if (opts.level) out = out.filter((e) => opts.level.has(e.level));
|
|
@@ -2037,9 +2148,8 @@ function normalizeAppUrlTarget(target) {
|
|
|
2037
2148
|
async function openAppUrl(bridge, target) {
|
|
2038
2149
|
const normalized = normalizeAppUrlTarget(target);
|
|
2039
2150
|
const result = await bridge.send({
|
|
2040
|
-
type: "
|
|
2041
|
-
|
|
2042
|
-
args: [normalized]
|
|
2151
|
+
type: "openUrl",
|
|
2152
|
+
url: normalized
|
|
2043
2153
|
});
|
|
2044
2154
|
if (result !== null && typeof result === "object" && Reflect.get(result, "ok") === false) {
|
|
2045
2155
|
const error = Reflect.get(result, "error");
|
|
@@ -2212,6 +2322,9 @@ var SimClient = class {
|
|
|
2212
2322
|
openUrl(target) {
|
|
2213
2323
|
return openAppUrl(this, target);
|
|
2214
2324
|
}
|
|
2325
|
+
async setAppearance(appearance) {
|
|
2326
|
+
await this.send({ type: "setAppearance", appearance });
|
|
2327
|
+
}
|
|
2215
2328
|
/**
|
|
2216
2329
|
* block until the guest app has mounted and painted real content.
|
|
2217
2330
|
* throws SimReadyTimeoutError (with the last probe status) on timeout.
|
|
@@ -2535,17 +2648,195 @@ async function connect(options = {}) {
|
|
|
2535
2648
|
return new SimClient(bridge, picked.id, { commandTimeoutMs });
|
|
2536
2649
|
}
|
|
2537
2650
|
|
|
2651
|
+
// src/capture-contract.ts
|
|
2652
|
+
var RNX_SCREEN_CAPTURE_VERSION = 1;
|
|
2653
|
+
function selectRnxRasterNodeIds(tree) {
|
|
2654
|
+
const nodesById = new Map(tree.nodes.map((node) => [node.nodeId, node]));
|
|
2655
|
+
const unsupported = /* @__PURE__ */ new Set();
|
|
2656
|
+
for (const node of tree.nodes) {
|
|
2657
|
+
const visibleFrame = node.visibleFrame ?? node.frame;
|
|
2658
|
+
if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue;
|
|
2659
|
+
if (node.type === "masked-view" || node.style._liquidGlass !== void 0 || node.style._liquidGlassEdge !== void 0) {
|
|
2660
|
+
unsupported.add(node.nodeId);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
for (const nodeId of [...unsupported]) {
|
|
2664
|
+
let parentNodeId = nodesById.get(nodeId)?.parentNodeId ?? null;
|
|
2665
|
+
while (parentNodeId !== null) {
|
|
2666
|
+
if (unsupported.has(parentNodeId)) {
|
|
2667
|
+
unsupported.delete(nodeId);
|
|
2668
|
+
break;
|
|
2669
|
+
}
|
|
2670
|
+
parentNodeId = nodesById.get(parentNodeId)?.parentNodeId ?? null;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
const screenArea = tree.width * tree.height;
|
|
2674
|
+
const maxLayerArea = screenArea * 0.25;
|
|
2675
|
+
const maxAtlasArea = screenArea * 0.5;
|
|
2676
|
+
const candidates = [...unsupported].map((nodeId) => {
|
|
2677
|
+
const node = nodesById.get(nodeId);
|
|
2678
|
+
const frame = node?.visibleFrame ?? node?.frame;
|
|
2679
|
+
return frame ? { nodeId, area: frame.width * frame.height } : null;
|
|
2680
|
+
}).filter(
|
|
2681
|
+
(candidate) => candidate !== null && candidate.area <= maxLayerArea
|
|
2682
|
+
).sort((left, right) => left.area - right.area || left.nodeId - right.nodeId);
|
|
2683
|
+
const selected = /* @__PURE__ */ new Set();
|
|
2684
|
+
let atlasArea = 0;
|
|
2685
|
+
for (const candidate of candidates) {
|
|
2686
|
+
if (atlasArea + candidate.area > maxAtlasArea) continue;
|
|
2687
|
+
selected.add(candidate.nodeId);
|
|
2688
|
+
atlasArea += candidate.area;
|
|
2689
|
+
}
|
|
2690
|
+
return selected;
|
|
2691
|
+
}
|
|
2692
|
+
function rnxRasterFrames(tree, nodeIds) {
|
|
2693
|
+
const frames = /* @__PURE__ */ new Map();
|
|
2694
|
+
for (const node of tree.nodes) {
|
|
2695
|
+
if (!nodeIds.has(node.nodeId)) continue;
|
|
2696
|
+
const frame = node.frame ?? {
|
|
2697
|
+
x: node.absolutePosition.x,
|
|
2698
|
+
y: node.absolutePosition.y,
|
|
2699
|
+
width: node.layout.width,
|
|
2700
|
+
height: node.layout.height
|
|
2701
|
+
};
|
|
2702
|
+
const liquidGlass = node.style._liquidGlass;
|
|
2703
|
+
const capturePadding = liquidGlass && typeof liquidGlass === "object" && typeof Reflect.get(liquidGlass, "capturePadding") === "number" ? Reflect.get(liquidGlass, "capturePadding") : 0;
|
|
2704
|
+
const shadowRadius = typeof node.style.shadowRadius === "number" ? node.style.shadowRadius : 0;
|
|
2705
|
+
const shadowOffset = node.style.shadowOffset;
|
|
2706
|
+
const shadowOffsetX = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "width") === "number" ? Reflect.get(shadowOffset, "width") : 0;
|
|
2707
|
+
const shadowOffsetY = shadowOffset && typeof shadowOffset === "object" && typeof Reflect.get(shadowOffset, "height") === "number" ? Reflect.get(shadowOffset, "height") : 0;
|
|
2708
|
+
const left = Math.max(
|
|
2709
|
+
0,
|
|
2710
|
+
frame.x - Math.max(capturePadding, shadowRadius - shadowOffsetX)
|
|
2711
|
+
);
|
|
2712
|
+
const top = Math.max(
|
|
2713
|
+
0,
|
|
2714
|
+
frame.y - Math.max(capturePadding, shadowRadius - shadowOffsetY)
|
|
2715
|
+
);
|
|
2716
|
+
const right = Math.min(
|
|
2717
|
+
tree.width,
|
|
2718
|
+
frame.x + frame.width + Math.max(capturePadding, shadowRadius + shadowOffsetX)
|
|
2719
|
+
);
|
|
2720
|
+
const bottom = Math.min(
|
|
2721
|
+
tree.height,
|
|
2722
|
+
frame.y + frame.height + Math.max(capturePadding, shadowRadius + shadowOffsetY)
|
|
2723
|
+
);
|
|
2724
|
+
if (right > left && bottom > top) {
|
|
2725
|
+
frames.set(node.nodeId, {
|
|
2726
|
+
x: left,
|
|
2727
|
+
y: top,
|
|
2728
|
+
width: right - left,
|
|
2729
|
+
height: bottom - top
|
|
2730
|
+
});
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
return frames;
|
|
2734
|
+
}
|
|
2735
|
+
function rnxCaptureRasterRegions(capture) {
|
|
2736
|
+
const tree = {
|
|
2737
|
+
width: capture.tree.viewport.width,
|
|
2738
|
+
height: capture.tree.viewport.height,
|
|
2739
|
+
nodes: capture.tree.nodes.map((node) => ({
|
|
2740
|
+
nodeId: node.nodeId,
|
|
2741
|
+
parentNodeId: node.parentNodeId,
|
|
2742
|
+
type: node.type,
|
|
2743
|
+
style: node.style.resolved,
|
|
2744
|
+
layout: node.layout.local,
|
|
2745
|
+
frame: node.layout.frame,
|
|
2746
|
+
absolutePosition: node.layout.absolutePosition,
|
|
2747
|
+
visibleFrame: node.layout.visibleFrame
|
|
2748
|
+
}))
|
|
2749
|
+
};
|
|
2750
|
+
const nodeIds = selectRnxRasterNodeIds(tree);
|
|
2751
|
+
const frames = rnxRasterFrames(tree, nodeIds);
|
|
2752
|
+
return [...nodeIds].flatMap((nodeId) => {
|
|
2753
|
+
const frame = frames.get(nodeId);
|
|
2754
|
+
return frame ? [{ key: String(nodeId), nodeId, frame }] : [];
|
|
2755
|
+
});
|
|
2756
|
+
}
|
|
2757
|
+
function captureRecord(value) {
|
|
2758
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2759
|
+
}
|
|
2760
|
+
function captureInteger(value) {
|
|
2761
|
+
return typeof value === "number" && Number.isSafeInteger(value);
|
|
2762
|
+
}
|
|
2763
|
+
function captureNumber(value) {
|
|
2764
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
2765
|
+
}
|
|
2766
|
+
function captureNullableString(value) {
|
|
2767
|
+
return value === null || typeof value === "string";
|
|
2768
|
+
}
|
|
2769
|
+
function captureRect(value) {
|
|
2770
|
+
return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y) && captureNumber(value.width) && captureNumber(value.height);
|
|
2771
|
+
}
|
|
2772
|
+
function captureOptionalString(value) {
|
|
2773
|
+
return value === void 0 || typeof value === "string";
|
|
2774
|
+
}
|
|
2775
|
+
function captureOptionalNullableString(value) {
|
|
2776
|
+
return value === void 0 || captureNullableString(value);
|
|
2777
|
+
}
|
|
2778
|
+
function captureFontRegistration(value) {
|
|
2779
|
+
return captureRecord(value) && typeof value.family === "string" && value.family.length > 0 && captureOptionalString(value.url) && captureOptionalString(value.sourceLabel) && captureOptionalNullableString(value.parsedFamily) && captureOptionalNullableString(value.parsedPostScript) && captureOptionalNullableString(value.fullName);
|
|
2780
|
+
}
|
|
2781
|
+
function capturePoint(value) {
|
|
2782
|
+
return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y);
|
|
2783
|
+
}
|
|
2784
|
+
function captureNode(value) {
|
|
2785
|
+
if (!captureRecord(value) || !captureInteger(value.nodeId) || !(value.parentNodeId === null || captureInteger(value.parentNodeId)) || !Array.isArray(value.childNodeIds) || !value.childNodeIds.every(captureInteger) || !captureInteger(value.paintIndex) || typeof value.type !== "string" || !captureNullableString(value.id) || !captureNullableString(value.testID) || !captureNullableString(value.text) || !captureInteger(value.childCount) || !captureRecord(value.accessibility) || !captureRecord(value.interaction) || !captureRecord(value.layout) || !captureRecord(value.style) || !captureRecord(value.source) || !captureRecord(value.props) || !captureRecord(value.inspection)) {
|
|
2786
|
+
return false;
|
|
2787
|
+
}
|
|
2788
|
+
const accessibility = value.accessibility;
|
|
2789
|
+
if (typeof accessibility.accessible !== "boolean" || !captureNullableString(accessibility.label) || !captureNullableString(accessibility.role) || !captureNullableString(accessibility.hint) || !(accessibility.liveRegion === null || accessibility.liveRegion === "none" || accessibility.liveRegion === "polite" || accessibility.liveRegion === "assertive") || !(accessibility.state === null || captureRecord(accessibility.state)) || !(accessibility.value === null || captureRecord(accessibility.value))) {
|
|
2790
|
+
return false;
|
|
2791
|
+
}
|
|
2792
|
+
const interaction = value.interaction;
|
|
2793
|
+
if (typeof interaction.pressed !== "boolean" || typeof interaction.pressable !== "boolean" || typeof interaction.textInput !== "boolean" || !(interaction.textSelection === null || captureRecord(interaction.textSelection)) || typeof interaction.secureTextEntry !== "boolean" || !captureNullableString(interaction.placeholder) || !capturePoint(interaction.scrollOffset) || !(interaction.zoomScale === null || captureNumber(interaction.zoomScale)) || typeof interaction.nativePinchEnabled !== "boolean" || !(interaction.contentOffsetProp === null || captureRecord(interaction.contentOffsetProp)) || !(interaction.strokeDashoffsetProp === null || captureNumber(interaction.strokeDashoffsetProp))) {
|
|
2794
|
+
return false;
|
|
2795
|
+
}
|
|
2796
|
+
const layout = value.layout;
|
|
2797
|
+
if (!captureRect(layout.local) || !(layout.frame === null || captureRect(layout.frame)) || !capturePoint(layout.absolutePosition) || !(layout.visibleFrame === null || captureRect(layout.visibleFrame))) {
|
|
2798
|
+
return false;
|
|
2799
|
+
}
|
|
2800
|
+
const style = value.style;
|
|
2801
|
+
return captureRecord(style.resolved) && captureRecord(style.authored) && captureRecord(style.computed) && captureRecord(style.tokenBindings) && (value.textLines === void 0 || Array.isArray(value.textLines));
|
|
2802
|
+
}
|
|
2803
|
+
function isRnxScreenCapture(value) {
|
|
2804
|
+
if (!captureRecord(value) || value.contractVersion !== RNX_SCREEN_CAPTURE_VERSION || !captureInteger(value.capturedAt) || !captureRecord(value.tree) || !(value.fonts === void 0 || Array.isArray(value.fonts) && value.fonts.length <= 200 && value.fonts.every(captureFontRegistration)) || !(value.visual === void 0 || captureRecord(value.visual))) {
|
|
2805
|
+
return false;
|
|
2806
|
+
}
|
|
2807
|
+
const tree = value.tree;
|
|
2808
|
+
const visual = value.visual;
|
|
2809
|
+
return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
|
|
2810
|
+
}
|
|
2811
|
+
function isRnxCaptureRegionAtlas(value) {
|
|
2812
|
+
if (!captureRecord(value) || value.kind !== "png-atlas" || value.producer !== "headless-cpu-app-surface" || typeof value.dataUri !== "string" || !value.dataUri.startsWith("data:image/png;base64,") || !captureNumber(value.width) || value.width <= 0 || !captureNumber(value.height) || value.height <= 0 || !captureInteger(value.pixelWidth) || value.pixelWidth <= 0 || !captureInteger(value.pixelHeight) || value.pixelHeight <= 0 || !Array.isArray(value.regions) || value.regions.length === 0 || value.regions.length > 256) {
|
|
2813
|
+
return false;
|
|
2814
|
+
}
|
|
2815
|
+
const scale = value.pixelWidth / value.width;
|
|
2816
|
+
if (!Number.isInteger(scale) || scale < 1 || scale > 4 || Math.abs(value.height * scale - value.pixelHeight) > 1e-6) {
|
|
2817
|
+
return false;
|
|
2818
|
+
}
|
|
2819
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2820
|
+
for (const region of value.regions) {
|
|
2821
|
+
if (!captureRecord(region) || typeof region.key !== "string" || region.key.length === 0 || keys.has(region.key) || !captureInteger(region.nodeId) || region.nodeId <= 0 || !captureRect(region.frame) || region.frame.width <= 0 || region.frame.height <= 0 || !captureRect(region.source) || region.source.x < 0 || region.source.y < 0 || region.source.width !== region.frame.width || region.source.height !== region.frame.height || region.source.x + region.source.width > value.width || region.source.y + region.source.height > value.height) {
|
|
2822
|
+
return false;
|
|
2823
|
+
}
|
|
2824
|
+
keys.add(region.key);
|
|
2825
|
+
}
|
|
2826
|
+
return true;
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2538
2829
|
// src/vite-plugin-one.ts
|
|
2539
2830
|
var import_fs4 = __toESM(require("fs"), 1);
|
|
2540
|
-
var
|
|
2831
|
+
var import_node_crypto3 = require("node:crypto");
|
|
2541
2832
|
var import_path3 = __toESM(require("path"), 1);
|
|
2542
2833
|
|
|
2543
2834
|
// src/dev-server-open.ts
|
|
2544
2835
|
var import_node_child_process = require("node:child_process");
|
|
2545
|
-
var
|
|
2546
|
-
var
|
|
2836
|
+
var import_node_crypto2 = require("node:crypto");
|
|
2837
|
+
var import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
2547
2838
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
2548
|
-
var
|
|
2839
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
2549
2840
|
var import_node_url = require("node:url");
|
|
2550
2841
|
var scheduledMetroOpens = /* @__PURE__ */ new Set();
|
|
2551
2842
|
function resolveRnxDesktopAppName(open, projectRoot) {
|
|
@@ -2555,8 +2846,8 @@ function resolveRnxDesktopAppName(open, projectRoot) {
|
|
|
2555
2846
|
if (!appName) throw new Error("rnx: open.appName must not be empty");
|
|
2556
2847
|
return appName;
|
|
2557
2848
|
}
|
|
2558
|
-
const packageJsonPath =
|
|
2559
|
-
const packageJson = JSON.parse(
|
|
2849
|
+
const packageJsonPath = import_node_path4.default.join(projectRoot, "package.json");
|
|
2850
|
+
const packageJson = JSON.parse(import_node_fs4.default.readFileSync(packageJsonPath, "utf8"));
|
|
2560
2851
|
const packageName = packageJson && typeof packageJson === "object" ? Reflect.get(packageJson, "name") : void 0;
|
|
2561
2852
|
if (typeof packageName !== "string" || !packageName.trim()) {
|
|
2562
2853
|
throw new Error(`rnx: ${packageJsonPath} must declare a package name`);
|
|
@@ -2570,7 +2861,7 @@ function tagRnxBundleForPlugin(bundleUrl, replacementOrigin, replacementToken, p
|
|
|
2570
2861
|
url.searchParams.set("rnxAppName", appName);
|
|
2571
2862
|
url.searchParams.set(
|
|
2572
2863
|
"rnxProjectId",
|
|
2573
|
-
(0,
|
|
2864
|
+
(0, import_node_crypto2.createHash)("sha256").update(import_node_fs4.default.realpathSync(projectRoot)).digest("hex").slice(0, 32)
|
|
2574
2865
|
);
|
|
2575
2866
|
}
|
|
2576
2867
|
url.searchParams.set("rnxReplacementOrigin", replacementOrigin);
|
|
@@ -2605,8 +2896,8 @@ function observeRnxDesktopLaunch(child, appName) {
|
|
|
2605
2896
|
});
|
|
2606
2897
|
}
|
|
2607
2898
|
function launchRnxDesktop(bundleUrl, appName) {
|
|
2608
|
-
const packageRoot =
|
|
2609
|
-
const binPath =
|
|
2899
|
+
const packageRoot = import_node_path4.default.resolve(import_node_path4.default.dirname((0, import_node_url.fileURLToPath)(__sootsim_import_meta_url)), "..");
|
|
2900
|
+
const binPath = import_node_path4.default.join(packageRoot, "dist-cli", "bin.js");
|
|
2610
2901
|
console.log(`[rnx] opening ${appName} in the desktop simulator`);
|
|
2611
2902
|
const child = (0, import_node_child_process.spawn)(
|
|
2612
2903
|
process.execPath,
|
|
@@ -2696,22 +2987,11 @@ function openRnxDesktopWhenMetroIsReady({
|
|
|
2696
2987
|
|
|
2697
2988
|
// src/host/replacement-module-handler.ts
|
|
2698
2989
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
2699
|
-
var
|
|
2990
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
2700
2991
|
var import_esbuild = require("esbuild");
|
|
2701
|
-
|
|
2702
|
-
// src/backend-origin.ts
|
|
2703
|
-
function normalizeHostname(hostname) {
|
|
2704
|
-
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
2705
|
-
}
|
|
2706
|
-
function isLoopbackHost(hostname) {
|
|
2707
|
-
const normalized = normalizeHostname(hostname);
|
|
2708
|
-
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
2709
|
-
}
|
|
2710
|
-
|
|
2711
|
-
// src/host/replacement-module-handler.ts
|
|
2712
2992
|
var REPLACEMENT_MODULE_ROUTE = "/__sootsim-replacement-module";
|
|
2713
2993
|
function getReplacementLoader(filePath) {
|
|
2714
|
-
const ext =
|
|
2994
|
+
const ext = import_node_path5.default.extname(filePath).toLowerCase();
|
|
2715
2995
|
switch (ext) {
|
|
2716
2996
|
case ".js":
|
|
2717
2997
|
return "js";
|
|
@@ -2793,7 +3073,7 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
2793
3073
|
res.end("replacement files must be .js, .jsx, .ts, or .tsx");
|
|
2794
3074
|
return true;
|
|
2795
3075
|
}
|
|
2796
|
-
if (!
|
|
3076
|
+
if (!import_node_path5.default.isAbsolute(targetPath)) {
|
|
2797
3077
|
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
|
|
2798
3078
|
res.end("replacement file path must be absolute");
|
|
2799
3079
|
return true;
|
|
@@ -2801,10 +3081,10 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
2801
3081
|
const runtimePackages = new Set(url.searchParams.getAll("runtimePackage"));
|
|
2802
3082
|
let resolvedProjectRoot;
|
|
2803
3083
|
if (options.projectRoot) {
|
|
2804
|
-
const lexicalProjectRoot =
|
|
3084
|
+
const lexicalProjectRoot = import_node_path5.default.resolve(options.projectRoot);
|
|
2805
3085
|
resolvedProjectRoot = await import_promises.default.realpath(options.projectRoot);
|
|
2806
|
-
const lexicalTarget =
|
|
2807
|
-
if (lexicalTarget.startsWith("..") ||
|
|
3086
|
+
const lexicalTarget = import_node_path5.default.relative(lexicalProjectRoot, targetPath);
|
|
3087
|
+
if (lexicalTarget.startsWith("..") || import_node_path5.default.isAbsolute(lexicalTarget)) {
|
|
2808
3088
|
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
2809
3089
|
res.end("replacement file must be inside the project root");
|
|
2810
3090
|
return true;
|
|
@@ -2820,8 +3100,8 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
2820
3100
|
return true;
|
|
2821
3101
|
}
|
|
2822
3102
|
if (resolvedProjectRoot) {
|
|
2823
|
-
const relativeTarget =
|
|
2824
|
-
if (relativeTarget.startsWith("..") ||
|
|
3103
|
+
const relativeTarget = import_node_path5.default.relative(resolvedProjectRoot, resolvedTargetPath);
|
|
3104
|
+
if (relativeTarget.startsWith("..") || import_node_path5.default.isAbsolute(relativeTarget)) {
|
|
2825
3105
|
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
2826
3106
|
res.end("replacement file must be inside the project root");
|
|
2827
3107
|
return true;
|
|
@@ -3062,7 +3342,7 @@ function rnxPlugin(options = {}) {
|
|
|
3062
3342
|
if (options.enabled === false) return;
|
|
3063
3343
|
const bundleUrl = options.bundleUrl || "/node_modules/one/metro-entry.bundle?platform=ios&dev=true&minify=false";
|
|
3064
3344
|
const appName = resolveRnxDesktopAppName(options.open, server.config.root);
|
|
3065
|
-
const replacementToken = (0,
|
|
3345
|
+
const replacementToken = (0, import_node_crypto3.randomUUID)();
|
|
3066
3346
|
const configuredPort = server.config.server.port || 8081;
|
|
3067
3347
|
const listeningPort = () => {
|
|
3068
3348
|
const address = server.httpServer?.address();
|
|
@@ -3187,7 +3467,7 @@ function rnxPlugin(options = {}) {
|
|
|
3187
3467
|
// src/metro-plugin.ts
|
|
3188
3468
|
var import_fs5 = __toESM(require("fs"), 1);
|
|
3189
3469
|
var import_module2 = require("module");
|
|
3190
|
-
var
|
|
3470
|
+
var import_node_crypto4 = require("node:crypto");
|
|
3191
3471
|
var import_path4 = __toESM(require("path"), 1);
|
|
3192
3472
|
|
|
3193
3473
|
// src/metro-production-bundle.ts
|
|
@@ -3284,7 +3564,7 @@ function withRNX(config, options = {}) {
|
|
|
3284
3564
|
const configuredBundleUrl = options.bundleUrl || "/index.bundle?platform=ios&dev=true&hot=true&minify=false";
|
|
3285
3565
|
const cfgServer = config.server;
|
|
3286
3566
|
const port = resolveMetroPort(cfgServer);
|
|
3287
|
-
const metroServerId = (0,
|
|
3567
|
+
const metroServerId = (0, import_node_crypto4.randomUUID)();
|
|
3288
3568
|
const bundleUrl = tagRnxBundleForPlugin(
|
|
3289
3569
|
configuredBundleUrl,
|
|
3290
3570
|
`http://localhost:${port}`,
|
|
@@ -3522,6 +3802,7 @@ function sootsimJumpToSourceBabelPlugin(api, options = {}) {
|
|
|
3522
3802
|
DEFAULT_SOOTSIM_BRIDGE_PORT,
|
|
3523
3803
|
DEFAULT_SOOTSIM_BRIDGE_URL,
|
|
3524
3804
|
DEFAULT_SOOTSIM_SHELL_URL,
|
|
3805
|
+
RNX_SCREEN_CAPTURE_VERSION,
|
|
3525
3806
|
SimClient,
|
|
3526
3807
|
SimClientError,
|
|
3527
3808
|
SimConnectError,
|
|
@@ -3531,7 +3812,12 @@ function sootsimJumpToSourceBabelPlugin(api, options = {}) {
|
|
|
3531
3812
|
SimResetError,
|
|
3532
3813
|
SimTapError,
|
|
3533
3814
|
connect,
|
|
3815
|
+
isRnxCaptureRegionAtlas,
|
|
3816
|
+
isRnxScreenCapture,
|
|
3534
3817
|
jumpToSourceBabelPlugin,
|
|
3535
3818
|
metroPlugin,
|
|
3536
|
-
|
|
3819
|
+
rnxCaptureRasterRegions,
|
|
3820
|
+
rnxPlugin,
|
|
3821
|
+
rnxRasterFrames,
|
|
3822
|
+
selectRnxRasterNodeIds
|
|
3537
3823
|
});
|