rnxsim 0.1.344 → 0.1.346
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 +59 -31
- package/cli/app-fonts.ts +8 -28
- package/cli/app-project.ts +12 -184
- package/cli/app-splash.ts +3 -17
- package/cli/bin.ts +15 -28
- package/cli/commands/control.ts +20 -30
- package/cli/commands/daemon.ts +19 -44
- package/cli/commands/flow.ts +0 -27
- package/cli/commands/install-desktop.ts +2 -16
- package/cli/commands/login.ts +3 -43
- package/cli/commands/logout.ts +0 -7
- package/cli/commands/serve.ts +2 -32
- package/cli/commands/setup.ts +20 -194
- package/cli/commands/telemetry.ts +7 -5
- package/cli/commands/upload.ts +1 -48
- package/cli/commands/welcome.ts +64 -0
- package/cli/outbound-endpoints.ts +586 -0
- package/cli/privacy.ts +53 -0
- package/cli/runtime-notes.ts +2 -2
- package/cli/telemetry.ts +46 -149
- package/dist-cli/bin.js +6 -6
- package/dist-cli/chunks/{agent-HTSE5FA4.js → agent-U6HZUHAQ.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-L6X2AEZL.js → agent-wrapper-IM2VL6XP.js} +2 -2
- package/dist-cli/chunks/{app-fonts-FGF3ETYH.js → app-fonts-LHVTPWCN.js} +2 -2
- package/dist-cli/chunks/{assert-HA2ZYVDN.js → assert-UMGCZXWN.js} +2 -2
- package/dist-cli/chunks/{auth-HONDAV75.js → auth-PQY57FPY.js} +2 -2
- package/dist-cli/chunks/{beta-U7EE4GMR.js → beta-3MMNRHL7.js} +2 -2
- package/dist-cli/chunks/{camera-RTKNUTIX.js → camera-UKISEHMH.js} +2 -2
- package/dist-cli/chunks/{chunk-CNLPLCO2.js → chunk-36P343FE.js} +2 -2
- package/dist-cli/chunks/{chunk-IWR4HFC4.js → chunk-3KPJVR63.js} +2 -2
- package/dist-cli/chunks/chunk-54Y5IXWQ.js +15 -0
- package/dist-cli/chunks/{chunk-EPEZZ6YS.js → chunk-5KMV7NAJ.js} +2 -2
- package/dist-cli/chunks/{chunk-NDGAF5OF.js → chunk-5WIYZI5H.js} +2 -2
- package/dist-cli/chunks/{chunk-KBSVSAAE.js → chunk-6GXUQ3DM.js} +2 -2
- package/dist-cli/chunks/{chunk-KT6WMCUS.js → chunk-6MUEKKJ4.js} +1 -1
- package/dist-cli/chunks/{chunk-TOHQI2II.js → chunk-6Q6S53R7.js} +1 -1
- package/dist-cli/chunks/{chunk-63NZGJ4A.js → chunk-6SQCDLTJ.js} +1 -1
- package/dist-cli/chunks/{chunk-Q2B6EQPB.js → chunk-6UW6O575.js} +2 -2
- package/dist-cli/chunks/chunk-6VH3UUYQ.js +4 -0
- package/dist-cli/chunks/{chunk-BGLWR43R.js → chunk-6XJGGFMD.js} +1 -1
- package/dist-cli/chunks/{chunk-TZNRKIS3.js → chunk-75LMZXF5.js} +2 -2
- package/dist-cli/chunks/{chunk-FZ5DRZJE.js → chunk-7CJNUNQA.js} +3 -3
- package/dist-cli/chunks/{chunk-UCVQOQCY.js → chunk-BQDGFR4B.js} +2 -2
- package/dist-cli/chunks/{chunk-H4J7EWZC.js → chunk-BSIVS2SQ.js} +1 -1
- package/dist-cli/chunks/{chunk-6E6SBYIO.js → chunk-CD2LITQX.js} +1 -1
- package/dist-cli/chunks/{chunk-PNMCALX5.js → chunk-DGH3D6WS.js} +2 -2
- package/dist-cli/chunks/chunk-EP6XBKPM.js +11 -0
- package/dist-cli/chunks/{chunk-OCUXAA6O.js → chunk-EVX6Y7ZM.js} +2 -2
- package/dist-cli/chunks/chunk-EYRKIWHE.js +4 -0
- package/dist-cli/chunks/{chunk-N5PFDTFL.js → chunk-FSYB2S6Q.js} +17 -17
- package/dist-cli/chunks/{chunk-6PEZSVIG.js → chunk-HPCTBEAP.js} +1 -1
- package/dist-cli/chunks/chunk-HS2BME6V.js +6 -0
- package/dist-cli/chunks/{chunk-G6IPT2PS.js → chunk-I3GUDHG2.js} +2 -2
- package/dist-cli/chunks/{chunk-MWUXQIA3.js → chunk-I4HVFKLM.js} +2 -2
- package/dist-cli/chunks/{chunk-ZPTFL5FQ.js → chunk-IBNK7SWL.js} +2 -2
- package/dist-cli/chunks/chunk-IUG4GWQC.js +25 -0
- package/dist-cli/chunks/{chunk-XQFDEY3F.js → chunk-IUIKD2YI.js} +1 -1
- package/dist-cli/chunks/{chunk-JFUVWIJT.js → chunk-JPVXLY7X.js} +1 -1
- package/dist-cli/chunks/{chunk-JLUEQPEF.js → chunk-K4PZLT2K.js} +1 -1
- package/dist-cli/chunks/{chunk-CRWYKW67.js → chunk-KNIKUJPD.js} +1 -1
- package/dist-cli/chunks/{chunk-EZLLZDYX.js → chunk-L6GWDWGZ.js} +2 -2
- package/dist-cli/chunks/chunk-LAVDDUQR.js +4 -0
- package/dist-cli/chunks/{chunk-22WJPMTQ.js → chunk-LPXKPZ4B.js} +1 -1
- package/dist-cli/chunks/{chunk-IPC45HTT.js → chunk-LYLK5VRP.js} +2 -2
- package/dist-cli/chunks/{chunk-S6LBAUWH.js → chunk-ME46FC4L.js} +1 -1
- package/dist-cli/chunks/chunk-NNXSLD76.js +99 -0
- package/dist-cli/chunks/{chunk-7V4ULF3U.js → chunk-PNH3YBZ4.js} +2 -2
- package/dist-cli/chunks/{chunk-GRX6NSBG.js → chunk-PPEJMNRO.js} +2 -2
- package/dist-cli/chunks/{chunk-K3VNCCEJ.js → chunk-SEWGXJG6.js} +3 -3
- package/dist-cli/chunks/{chunk-R3UYHE6G.js → chunk-T4JPZI32.js} +1 -1
- package/dist-cli/chunks/{chunk-NRTHFEPM.js → chunk-TAQYETRH.js} +2 -2
- package/dist-cli/chunks/{chunk-7JEEO33Y.js → chunk-TBVBWJJL.js} +2 -2
- package/dist-cli/chunks/{chunk-HRBMD2FS.js → chunk-UA54YLWR.js} +26 -26
- package/dist-cli/chunks/{chunk-G3UAFZE2.js → chunk-UV3TXNMG.js} +1 -1
- package/dist-cli/chunks/{chunk-EH35QQG4.js → chunk-VZ6YFPIN.js} +45 -45
- package/dist-cli/chunks/chunk-W54SRZ5K.js +14 -0
- package/dist-cli/chunks/chunk-WAC75WN6.js +4 -0
- package/dist-cli/chunks/{chunk-S7CSBQ6G.js → chunk-X2WIEZ7Q.js} +1 -1
- package/dist-cli/chunks/{chunk-EN32LN2B.js → chunk-XWTYFWZ3.js} +2 -2
- package/dist-cli/chunks/chunk-Y2C3CZVD.js +4 -0
- package/dist-cli/chunks/chunk-YM4L2CFB.js +4 -0
- package/dist-cli/chunks/{chunk-ZZSBCGHC.js → chunk-YXDR4CAQ.js} +1 -1
- package/dist-cli/chunks/{chunk-6NLWKL7Y.js → chunk-Z6P427WC.js} +2 -2
- package/dist-cli/chunks/{cleanup-EMYD5WZG.js → cleanup-KXPS5VSK.js} +2 -2
- package/dist-cli/chunks/cli-version-LJ6NFLBP.js +4 -0
- package/dist-cli/chunks/{compat-W2N5QTVG.js → compat-JWF7N3VO.js} +2 -2
- package/dist-cli/chunks/config-M42VJXNK.js +13 -0
- package/dist-cli/chunks/{control-4SFBROUE.js → control-HMZDIS6P.js} +2 -2
- package/dist-cli/chunks/daemon-MQ4UYKNQ.js +4 -0
- package/dist-cli/chunks/{debug-HCR2KFUA.js → debug-F44GWYMF.js} +3 -3
- package/dist-cli/chunks/{desktop-T2KS5PBJ.js → desktop-YJMWW6MW.js} +3 -3
- package/dist-cli/chunks/{detox-5S7EHINH.js → detox-5B4ASTJO.js} +2 -2
- package/dist-cli/chunks/{device-LVM3MZRJ.js → device-2544YZNY.js} +2 -2
- package/dist-cli/chunks/{diagnose-WK37XKLI.js → diagnose-LS4245JR.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-X7VJOXMS.js → disk-cleanup-XYL2HQQY.js} +2 -2
- package/dist-cli/chunks/drivers-P5CRSKH6.js +4 -0
- package/dist-cli/chunks/{film-7KLTI3ER.js → film-LS3TIZRM.js} +3 -3
- package/dist-cli/chunks/flow-7V77GXAB.js +4 -0
- package/dist-cli/chunks/help-HRESIFZX.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-4RVGUVFO.js → hidden-runtime-alias-HGN2EEQR.js} +2 -2
- package/dist-cli/chunks/{home-paths-5DHSAEGZ.js → home-paths-T3NTXE4U.js} +2 -2
- package/dist-cli/chunks/inspect-UC44UH4M.js +4 -0
- package/dist-cli/chunks/install-desktop-RDV66JHG.js +4 -0
- package/dist-cli/chunks/login-WVP5H5NQ.js +26 -0
- package/dist-cli/chunks/logout-GXX5OY6X.js +4 -0
- package/dist-cli/chunks/{maestro-HTRLQDJE.js → maestro-MQMGBNOB.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-GX2QNA3F.js → maestro-generate-CO355QV2.js} +3 -3
- package/dist-cli/chunks/{mode-GM6KZHQP.js → mode-QFB3M2AA.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-B4TD7JQP.js → optional-demo-registry-UIPVSBHV.js} +2 -2
- package/dist-cli/chunks/{perf-3PRXJQIC.js → perf-TDOSW3LD.js} +2 -2
- package/dist-cli/chunks/{permissions-TJZIRF2S.js → permissions-TEVQLCGJ.js} +2 -2
- package/dist-cli/chunks/privacy-DVHAMHR6.js +4 -0
- package/dist-cli/chunks/{record-LI55DTPE.js → record-OFEQLSWA.js} +3 -3
- package/dist-cli/chunks/{report-issue-TBGJVQIQ.js → report-issue-B2UPOERJ.js} +2 -2
- package/dist-cli/chunks/reset-XQQYM55B.js +4 -0
- package/dist-cli/chunks/runtime-GN6HITVB.js +4 -0
- package/dist-cli/chunks/{screenshot-command-BEN7YYIF.js → screenshot-command-NTLAY7QN.js} +3 -3
- package/dist-cli/chunks/{screenshot-layers-3IU4KYNO.js → screenshot-layers-BBLKNRQU.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-ZRC54ST6.js → screenshots-capture-6GHIRCTG.js} +2 -2
- package/dist-cli/chunks/serve-H6GJ4OHW.js +118 -0
- package/dist-cli/chunks/setup-6YLKSMWS.js +30 -0
- package/dist-cli/chunks/{skills-GKBR2HQB.js → skills-FUL7D6C7.js} +2 -2
- package/dist-cli/chunks/{state-LIHZJSL7.js → state-O2HE7XSR.js} +2 -2
- package/dist-cli/chunks/{storage-4TPN3NFB.js → storage-WIZTF7RN.js} +4 -4
- package/dist-cli/chunks/store-NJ2MBZC2.js +4 -0
- package/dist-cli/chunks/telemetry-BEC6W5WP.js +4 -0
- package/dist-cli/chunks/{timeline-EX63UNWU.js → timeline-MA4JT7UJ.js} +2 -2
- package/dist-cli/chunks/{upgrade-O6Y6EINE.js → upgrade-H5LSDXBH.js} +2 -2
- package/dist-cli/chunks/upload-Q4DWKIA4.js +4 -0
- package/dist-cli/chunks/{version-HLNL3NFB.js → version-4UWEEDVP.js} +2 -2
- package/dist-cli/chunks/{web-4EDPYPW7.js → web-F3LXRN3K.js} +2 -2
- package/dist-cli/chunks/welcome-AZBOSIG2.js +5 -0
- package/dist-cli/chunks/{what-happened-77VNUEPK.js → what-happened-6OSNLOAY.js} +2 -2
- 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 +13 -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.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +43 -13
- package/dist-lib/home-paths.cjs +145 -11
- package/dist-lib/host/bridge-host.cjs +326 -78
- 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 +71 -4
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +337 -37
- 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 +484 -14
- 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 +120 -50
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +493 -439
- package/dist-lib/vite.cjs +193 -37
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +112 -51
- package/skills/rnx-test/SKILL.md +4 -0
- package/src/backend-origin.ts +15 -1
- package/src/dev-bundle-resolution.ts +42 -18
- package/src/dev-server-open.ts +197 -0
- package/src/home-paths.ts +168 -15
- package/src/host/bridge-host.ts +2 -2
- package/src/host/replacement-module-handler.ts +68 -2
- package/src/metro-plugin.ts +83 -5
- package/src/native-dev-bundle-url.ts +22 -0
- package/src/vite-plugin-one.ts +42 -28
- package/dist-cli/chunks/chunk-3JC7H4PR.js +0 -25
- package/dist-cli/chunks/chunk-6DLIC7BZ.js +0 -4
- package/dist-cli/chunks/chunk-7TNPO2OJ.js +0 -9
- package/dist-cli/chunks/chunk-AMF5KTOI.js +0 -4
- package/dist-cli/chunks/chunk-BX5VXTOQ.js +0 -101
- package/dist-cli/chunks/chunk-D73H7ACZ.js +0 -4
- package/dist-cli/chunks/chunk-DY4O7KYI.js +0 -4
- package/dist-cli/chunks/chunk-GU2V4JDG.js +0 -15
- package/dist-cli/chunks/chunk-POOCKX5B.js +0 -14
- package/dist-cli/chunks/chunk-Z2HMSVSN.js +0 -4
- package/dist-cli/chunks/cli-version-CN3NTKLH.js +0 -4
- package/dist-cli/chunks/config-SELKGT4F.js +0 -13
- package/dist-cli/chunks/daemon-V2SFCU2E.js +0 -4
- package/dist-cli/chunks/drivers-3YFTJ5WA.js +0 -4
- package/dist-cli/chunks/flow-36ANTMJU.js +0 -4
- package/dist-cli/chunks/help-ZGL26SPK.js +0 -4
- package/dist-cli/chunks/inspect-R3B55RTS.js +0 -4
- package/dist-cli/chunks/install-desktop-TZ3H3VWK.js +0 -4
- package/dist-cli/chunks/login-4DFULI7S.js +0 -28
- package/dist-cli/chunks/logout-QMCVYMBB.js +0 -4
- package/dist-cli/chunks/reset-O6MW6X7X.js +0 -4
- package/dist-cli/chunks/runtime-JESXBHRQ.js +0 -4
- package/dist-cli/chunks/serve-QGKTWPNF.js +0 -118
- package/dist-cli/chunks/setup-3WPWATCX.js +0 -32
- package/dist-cli/chunks/store-VBX3L46S.js +0 -4
- package/dist-cli/chunks/telemetry-ACNNIQIG.js +0 -4
- package/dist-cli/chunks/upload-OD2UQHMM.js +0 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.346 | (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;
|
|
@@ -116,6 +116,21 @@ var import_net = __toESM(require("net"), 1);
|
|
|
116
116
|
var import_node_path3 = require("node:path");
|
|
117
117
|
var import_util = require("util");
|
|
118
118
|
|
|
119
|
+
// src/backend-origin.ts
|
|
120
|
+
var LOOPBACK_PROBE_HOSTNAMES = ["::1", "127.0.0.1"];
|
|
121
|
+
function normalizeHostname(hostname) {
|
|
122
|
+
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
123
|
+
}
|
|
124
|
+
function buildLoopbackProbeBaseUrl(protocol, hostname, port) {
|
|
125
|
+
const normalizedHostname = normalizeHostname(hostname);
|
|
126
|
+
const urlHost = normalizedHostname.includes(":") ? `[${normalizedHostname}]` : normalizedHostname;
|
|
127
|
+
return `${protocol}//${urlHost}:${port}`;
|
|
128
|
+
}
|
|
129
|
+
function isLoopbackHost(hostname) {
|
|
130
|
+
const normalized = normalizeHostname(hostname);
|
|
131
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
132
|
+
}
|
|
133
|
+
|
|
119
134
|
// src/config.ts
|
|
120
135
|
var SOOTSIM_CONFIG_QUERY_PARAM = "sootsimConfig";
|
|
121
136
|
function hasOwnKeys(value) {
|
|
@@ -142,6 +157,19 @@ function isAbsoluteHttpUrl(url) {
|
|
|
142
157
|
function isNativeDevBundlePath(pathname) {
|
|
143
158
|
return pathname.endsWith(".bundle");
|
|
144
159
|
}
|
|
160
|
+
function alignLoopbackBundleUrlWithProbe(bundleUrl, probeBaseUrl) {
|
|
161
|
+
try {
|
|
162
|
+
const bundle = new URL(bundleUrl);
|
|
163
|
+
const probe = new URL(probeBaseUrl);
|
|
164
|
+
if (!isLoopbackHost(bundle.hostname) || !isLoopbackHost(probe.hostname)) {
|
|
165
|
+
return bundleUrl;
|
|
166
|
+
}
|
|
167
|
+
bundle.hostname = probe.hostname;
|
|
168
|
+
return bundle.toString();
|
|
169
|
+
} catch {
|
|
170
|
+
return bundleUrl;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
145
173
|
function applyPreviewProdBundle(parsed) {
|
|
146
174
|
if (!process.env.SOOTSIM_PREVIEW_PROD_BUNDLE) return;
|
|
147
175
|
parsed.searchParams.set("dev", "false");
|
|
@@ -514,27 +542,36 @@ var execP = (0, import_util.promisify)(import_child_process.exec);
|
|
|
514
542
|
var TIMEOUT_MS = 250;
|
|
515
543
|
var MANIFEST_TIMEOUT_MS = 1500;
|
|
516
544
|
var TCP_GATE_MS = 120;
|
|
517
|
-
function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
545
|
+
async function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
546
|
+
try {
|
|
547
|
+
return await Promise.any(
|
|
548
|
+
LOOPBACK_PROBE_HOSTNAMES.map(
|
|
549
|
+
(hostname) => new Promise((resolve2, reject) => {
|
|
550
|
+
const sock = new import_net.default.Socket();
|
|
551
|
+
let settled = false;
|
|
552
|
+
const done = (reachable) => {
|
|
553
|
+
if (settled) return;
|
|
554
|
+
settled = true;
|
|
555
|
+
sock.destroy();
|
|
556
|
+
if (reachable) resolve2(hostname);
|
|
557
|
+
else reject(new Error(`unreachable loopback host ${hostname}`));
|
|
558
|
+
};
|
|
559
|
+
sock.setTimeout(timeout);
|
|
560
|
+
sock.once("connect", () => done(true));
|
|
561
|
+
sock.once("timeout", () => done(false));
|
|
562
|
+
sock.once("error", () => done(false));
|
|
563
|
+
sock.connect(port, hostname);
|
|
564
|
+
})
|
|
565
|
+
)
|
|
566
|
+
);
|
|
567
|
+
} catch {
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
533
570
|
}
|
|
534
|
-
function httpGet(port, path10, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
571
|
+
function httpGet(hostname, port, path10, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
535
572
|
return new Promise((resolve2) => {
|
|
536
573
|
const req = import_http.default.request(
|
|
537
|
-
{ hostname
|
|
574
|
+
{ hostname, port, path: path10, method, timeout, headers },
|
|
538
575
|
(res) => {
|
|
539
576
|
let body = "";
|
|
540
577
|
res.on("data", (c) => body += c.toString());
|
|
@@ -546,7 +583,12 @@ function httpGet(port, path10, method = "GET", timeout = TIMEOUT_MS, headers = {
|
|
|
546
583
|
})();
|
|
547
584
|
res.on(
|
|
548
585
|
"end",
|
|
549
|
-
() => resolve2({
|
|
586
|
+
() => resolve2({
|
|
587
|
+
statusCode: res.statusCode || 0,
|
|
588
|
+
body,
|
|
589
|
+
contentType,
|
|
590
|
+
hostname
|
|
591
|
+
})
|
|
550
592
|
);
|
|
551
593
|
}
|
|
552
594
|
);
|
|
@@ -698,16 +740,16 @@ async function resolveProcessCwd(pid) {
|
|
|
698
740
|
}
|
|
699
741
|
return null;
|
|
700
742
|
}
|
|
701
|
-
function makeResult(port, framework, owner) {
|
|
743
|
+
function makeResult(hostname, port, framework, owner) {
|
|
702
744
|
return {
|
|
703
745
|
port,
|
|
704
746
|
framework,
|
|
705
747
|
bundleUrl: withRuntimeConfig(
|
|
706
748
|
port,
|
|
707
|
-
|
|
749
|
+
`${buildLoopbackProbeBaseUrl("http:", hostname, port)}/index.bundle?platform=ios&dev=true&hot=true&minify=false`,
|
|
708
750
|
owner.cwd
|
|
709
751
|
),
|
|
710
|
-
hmrUrl:
|
|
752
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", hostname, port)}/hot`,
|
|
711
753
|
lastSeen: Date.now(),
|
|
712
754
|
...owner
|
|
713
755
|
};
|
|
@@ -738,7 +780,11 @@ function applyManifest(result, manifestRes, buildIconProxyUrl) {
|
|
|
738
780
|
if (client.name) result.projectName = client.name;
|
|
739
781
|
if (client.ios?.bundleIdentifier) result.bundleId = client.ios.bundleIdentifier;
|
|
740
782
|
if (result.framework === "metro" && client.sdkVersion) result.framework = "expo";
|
|
741
|
-
const
|
|
783
|
+
const rawLaunchUrl = manifest?.launchAsset?.url;
|
|
784
|
+
const launchUrl2 = typeof rawLaunchUrl === "string" ? alignLoopbackBundleUrlWithProbe(
|
|
785
|
+
rawLaunchUrl,
|
|
786
|
+
buildLoopbackProbeBaseUrl("http:", manifestRes.hostname, result.port)
|
|
787
|
+
) : rawLaunchUrl;
|
|
742
788
|
if (launchUrl2 && !result.patched && !isDirectOneBundleUrl(result.bundleUrl)) {
|
|
743
789
|
result.bundleUrl = withRuntimeConfig(result.port, launchUrl2, result.cwd);
|
|
744
790
|
}
|
|
@@ -751,11 +797,11 @@ function applyManifest(result, manifestRes, buildIconProxyUrl) {
|
|
|
751
797
|
} else {
|
|
752
798
|
const cleanPath = rawIconUrl.replace(/^\.\//, "");
|
|
753
799
|
result.iconUrl = buildIconProxyUrl(
|
|
754
|
-
|
|
800
|
+
`${buildLoopbackProbeBaseUrl("http:", manifestRes.hostname, result.port)}/assets/${cleanPath}`
|
|
755
801
|
);
|
|
756
802
|
}
|
|
757
803
|
} else {
|
|
758
|
-
result.iconUrl = rawIconUrl.startsWith("http") ? rawIconUrl :
|
|
804
|
+
result.iconUrl = rawIconUrl.startsWith("http") ? rawIconUrl : `${buildLoopbackProbeBaseUrl("http:", manifestRes.hostname, result.port)}/assets/${rawIconUrl.replace(/^\.\//, "")}`;
|
|
759
805
|
}
|
|
760
806
|
}
|
|
761
807
|
} catch {
|
|
@@ -779,38 +825,51 @@ function enrichWithManifest(result, buildIconProxyUrl) {
|
|
|
779
825
|
}
|
|
780
826
|
if (!enrichmentInFlight.has(result.port)) {
|
|
781
827
|
enrichmentInFlight.add(result.port);
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
() => enrichmentInFlight.delete(port)
|
|
828
|
+
void fetchManifestEnrichment(result, buildIconProxyUrl).finally(
|
|
829
|
+
() => enrichmentInFlight.delete(result.port)
|
|
785
830
|
);
|
|
786
831
|
}
|
|
787
832
|
return result;
|
|
788
833
|
}
|
|
789
|
-
async function fetchManifestEnrichment(
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
834
|
+
async function fetchManifestEnrichment(result, buildIconProxyUrl) {
|
|
835
|
+
const hostname = normalizeHostname(new URL(result.bundleUrl).hostname);
|
|
836
|
+
const manifestRes = await httpGet(
|
|
837
|
+
hostname,
|
|
838
|
+
result.port,
|
|
839
|
+
"/",
|
|
840
|
+
"GET",
|
|
841
|
+
ENRICH_TIMEOUT_MS,
|
|
842
|
+
{
|
|
843
|
+
"expo-platform": "ios"
|
|
844
|
+
}
|
|
845
|
+
);
|
|
793
846
|
if (!manifestRes || manifestRes.statusCode !== 200) return;
|
|
794
847
|
const parsed = applyManifest(
|
|
795
|
-
{
|
|
848
|
+
{
|
|
849
|
+
port: result.port,
|
|
850
|
+
framework: "one",
|
|
851
|
+
bundleUrl: `${buildLoopbackProbeBaseUrl("http:", hostname, result.port)}/index.bundle`,
|
|
852
|
+
lastSeen: 0
|
|
853
|
+
},
|
|
796
854
|
manifestRes,
|
|
797
855
|
buildIconProxyUrl
|
|
798
856
|
);
|
|
799
857
|
if (!parsed.projectName && !parsed.iconUrl) return;
|
|
800
|
-
enrichmentCache.set(port, {
|
|
858
|
+
enrichmentCache.set(result.port, {
|
|
801
859
|
projectName: parsed.projectName,
|
|
802
860
|
iconUrl: parsed.iconUrl,
|
|
803
861
|
iconPath: parsed.iconPath,
|
|
804
862
|
bundleId: parsed.bundleId
|
|
805
863
|
});
|
|
806
|
-
portCache.delete(port);
|
|
864
|
+
portCache.delete(result.port);
|
|
807
865
|
}
|
|
808
866
|
var knownNonPatched = /* @__PURE__ */ new Set();
|
|
809
867
|
var knownNonExpo = /* @__PURE__ */ new Set();
|
|
810
868
|
var knownOne = /* @__PURE__ */ new Set();
|
|
811
869
|
async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
812
870
|
await loadOptionalDemoApps();
|
|
813
|
-
|
|
871
|
+
const probeHostname = await tcpPing(port);
|
|
872
|
+
if (!probeHostname) return null;
|
|
814
873
|
const suppliedPid = listeningProcess?.pid;
|
|
815
874
|
const ownerPid = suppliedPid && suppliedPid > 0 ? suppliedPid : await resolveListeningPid(port);
|
|
816
875
|
const ownerCwd = ownerPid ? await resolveProcessCwd(ownerPid) : null;
|
|
@@ -820,10 +879,12 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
820
879
|
};
|
|
821
880
|
const onePath = `/node_modules/one/metro-entry.bundle?platform=ios&dev=true`;
|
|
822
881
|
const [sootsimRes, statusRes, manifestRes, expoRes] = await Promise.all([
|
|
823
|
-
knownNonPatched.has(port) ? Promise.resolve(null) : httpGet(port, "/__soot/"),
|
|
824
|
-
httpGet(port, "/status"),
|
|
825
|
-
knownOne.has(port) ? Promise.resolve(null) : httpGet(port, "/", "GET", MANIFEST_TIMEOUT_MS, {
|
|
826
|
-
|
|
882
|
+
knownNonPatched.has(port) ? Promise.resolve(null) : httpGet(probeHostname, port, "/__soot/"),
|
|
883
|
+
httpGet(probeHostname, port, "/status"),
|
|
884
|
+
knownOne.has(port) ? Promise.resolve(null) : httpGet(probeHostname, port, "/", "GET", MANIFEST_TIMEOUT_MS, {
|
|
885
|
+
"expo-platform": "ios"
|
|
886
|
+
}),
|
|
887
|
+
knownNonExpo.has(port) ? Promise.resolve(null) : httpGet(probeHostname, port, "/_expo/status")
|
|
827
888
|
]);
|
|
828
889
|
if (expoRes && expoRes.statusCode === 200) {
|
|
829
890
|
knownNonExpo.delete(port);
|
|
@@ -835,7 +896,7 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
835
896
|
const manifestClient = manifestParsed?.extra?.expoClient || manifestParsed?.extra || {};
|
|
836
897
|
if (manifestParsed && (manifestLaunchUrl || typeof manifestClient.name === "string")) {
|
|
837
898
|
knownNonPatched.add(port);
|
|
838
|
-
const launchUrl2 = manifestLaunchUrl ||
|
|
899
|
+
const launchUrl2 = manifestLaunchUrl || `${buildLoopbackProbeBaseUrl("http:", probeHostname, port)}/index.bundle?platform=ios&dev=true&hot=true&minify=false`;
|
|
839
900
|
const framework = launchUrl2.includes(
|
|
840
901
|
"/one/metro-entry.bundle"
|
|
841
902
|
) ? "one" : "expo";
|
|
@@ -844,7 +905,7 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
844
905
|
port,
|
|
845
906
|
framework,
|
|
846
907
|
bundleUrl: withRuntimeConfig(port, launchUrl2, owner.cwd),
|
|
847
|
-
hmrUrl:
|
|
908
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
|
|
848
909
|
lastSeen: Date.now(),
|
|
849
910
|
...owner
|
|
850
911
|
},
|
|
@@ -856,7 +917,12 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
856
917
|
knownNonPatched.add(port);
|
|
857
918
|
return enrichWithManifest(
|
|
858
919
|
applyManifest(
|
|
859
|
-
makeResult(
|
|
920
|
+
makeResult(
|
|
921
|
+
probeHostname,
|
|
922
|
+
port,
|
|
923
|
+
expoRes && expoRes.statusCode === 200 ? "expo" : "metro",
|
|
924
|
+
owner
|
|
925
|
+
),
|
|
860
926
|
manifestRes,
|
|
861
927
|
buildIconProxyUrl
|
|
862
928
|
),
|
|
@@ -872,10 +938,10 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
872
938
|
framework: "one",
|
|
873
939
|
bundleUrl: withRuntimeConfig(
|
|
874
940
|
port,
|
|
875
|
-
|
|
941
|
+
`${buildLoopbackProbeBaseUrl("http:", probeHostname, port)}/__soot/bundle.js`,
|
|
876
942
|
owner.cwd
|
|
877
943
|
),
|
|
878
|
-
hmrUrl:
|
|
944
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
|
|
879
945
|
lastSeen: Date.now(),
|
|
880
946
|
patched: true,
|
|
881
947
|
...owner
|
|
@@ -890,7 +956,7 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
890
956
|
if (looksLikeMetroPackager) {
|
|
891
957
|
return null;
|
|
892
958
|
}
|
|
893
|
-
const oneRes = await httpGet(port, onePath, "HEAD");
|
|
959
|
+
const oneRes = await httpGet(probeHostname, port, onePath, "HEAD");
|
|
894
960
|
if (oneRes && oneRes.statusCode > 0 && oneRes.statusCode < 400 && /application\/javascript/i.test(oneRes.contentType || "")) {
|
|
895
961
|
knownNonPatched.add(port);
|
|
896
962
|
knownOne.add(port);
|
|
@@ -901,10 +967,10 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
901
967
|
framework: "one",
|
|
902
968
|
bundleUrl: withRuntimeConfig(
|
|
903
969
|
port,
|
|
904
|
-
|
|
970
|
+
`${buildLoopbackProbeBaseUrl("http:", probeHostname, port)}${onePath}&minify=false`,
|
|
905
971
|
owner.cwd
|
|
906
972
|
),
|
|
907
|
-
hmrUrl:
|
|
973
|
+
hmrUrl: `${buildLoopbackProbeBaseUrl("ws:", probeHostname, port)}/hot`,
|
|
908
974
|
lastSeen: Date.now(),
|
|
909
975
|
...owner
|
|
910
976
|
},
|
|
@@ -1064,6 +1130,7 @@ function getCliVersion() {
|
|
|
1064
1130
|
}
|
|
1065
1131
|
|
|
1066
1132
|
// src/home-paths.ts
|
|
1133
|
+
var import_node_crypto = require("node:crypto");
|
|
1067
1134
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
1068
1135
|
var import_node_os = require("node:os");
|
|
1069
1136
|
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
@@ -1197,6 +1264,7 @@ function activeRuntimeDir() {
|
|
|
1197
1264
|
return null;
|
|
1198
1265
|
}
|
|
1199
1266
|
var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
1267
|
+
var DAEMON_CLAIM_STALE_MS = 3e4;
|
|
1200
1268
|
function readDaemonLockfile() {
|
|
1201
1269
|
try {
|
|
1202
1270
|
const fd = import_node_fs3.default.openSync(daemonLockfilePath(), "r");
|
|
@@ -1239,10 +1307,30 @@ function isDaemonLockfileFresh(lock, now = Date.now()) {
|
|
|
1239
1307
|
}
|
|
1240
1308
|
function writeDaemonLockfile(data) {
|
|
1241
1309
|
ensureSootsimHome();
|
|
1242
|
-
const
|
|
1310
|
+
const lockfilePath = daemonLockfilePath();
|
|
1311
|
+
const existing = readDaemonLockfile();
|
|
1312
|
+
if (!existing) {
|
|
1313
|
+
if (createDaemonLockfileExclusive(data)) return;
|
|
1314
|
+
throw new Error("another rnx daemon claimed the lockfile before this write");
|
|
1315
|
+
}
|
|
1316
|
+
if (!sameDaemonOwner(existing, data)) {
|
|
1317
|
+
throw new Error("refusing to overwrite another rnx daemon lockfile");
|
|
1318
|
+
}
|
|
1319
|
+
const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
1243
1320
|
import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
1244
1321
|
`, "utf8");
|
|
1245
|
-
|
|
1322
|
+
try {
|
|
1323
|
+
const current = readDaemonLockfile();
|
|
1324
|
+
if (!current || !sameDaemonOwner(current, data)) {
|
|
1325
|
+
throw new Error("rnx daemon lock ownership changed during heartbeat");
|
|
1326
|
+
}
|
|
1327
|
+
import_node_fs3.default.renameSync(tmp, lockfilePath);
|
|
1328
|
+
} finally {
|
|
1329
|
+
try {
|
|
1330
|
+
import_node_fs3.default.unlinkSync(tmp);
|
|
1331
|
+
} catch {
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1246
1334
|
}
|
|
1247
1335
|
function writeDevBridgeLockfile(data) {
|
|
1248
1336
|
import_node_fs3.default.mkdirSync(devBridgesDir(), { recursive: true });
|
|
@@ -1252,17 +1340,130 @@ function writeDevBridgeLockfile(data) {
|
|
|
1252
1340
|
`, "utf8");
|
|
1253
1341
|
import_node_fs3.default.renameSync(tmp, lockfilePath);
|
|
1254
1342
|
}
|
|
1343
|
+
function sameDaemonOwner(left, right) {
|
|
1344
|
+
return left.pid === right.pid && left.startedAt === right.startedAt;
|
|
1345
|
+
}
|
|
1346
|
+
function isAlreadyExists(error) {
|
|
1347
|
+
return error instanceof Error && "code" in error && Reflect.get(error, "code") === "EEXIST";
|
|
1348
|
+
}
|
|
1349
|
+
function createDaemonLockfileExclusive(data) {
|
|
1350
|
+
const lockfilePath = daemonLockfilePath();
|
|
1351
|
+
const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.claim`;
|
|
1352
|
+
import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
1353
|
+
`, "utf8");
|
|
1354
|
+
try {
|
|
1355
|
+
import_node_fs3.default.linkSync(tmp, lockfilePath);
|
|
1356
|
+
return true;
|
|
1357
|
+
} catch (error) {
|
|
1358
|
+
if (isAlreadyExists(error)) return false;
|
|
1359
|
+
throw error;
|
|
1360
|
+
} finally {
|
|
1361
|
+
try {
|
|
1362
|
+
import_node_fs3.default.unlinkSync(tmp);
|
|
1363
|
+
} catch {
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
function daemonClaimPath() {
|
|
1368
|
+
return `${daemonLockfilePath()}.claim`;
|
|
1369
|
+
}
|
|
1370
|
+
function parseDaemonClaim(raw) {
|
|
1371
|
+
try {
|
|
1372
|
+
const value = JSON.parse(raw);
|
|
1373
|
+
if (value !== null && typeof value === "object" && typeof Reflect.get(value, "pid") === "number" && typeof Reflect.get(value, "startedAt") === "number" && typeof Reflect.get(value, "createdAt") === "number") {
|
|
1374
|
+
return {
|
|
1375
|
+
pid: Reflect.get(value, "pid"),
|
|
1376
|
+
startedAt: Reflect.get(value, "startedAt"),
|
|
1377
|
+
createdAt: Reflect.get(value, "createdAt")
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
} catch {
|
|
1381
|
+
}
|
|
1382
|
+
return null;
|
|
1383
|
+
}
|
|
1384
|
+
function readDaemonClaim() {
|
|
1385
|
+
try {
|
|
1386
|
+
return parseDaemonClaim(import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8"));
|
|
1387
|
+
} catch {
|
|
1388
|
+
return null;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
function isDaemonClaimFresh(claim, now = Date.now()) {
|
|
1392
|
+
if (now - claim.createdAt > DAEMON_CLAIM_STALE_MS) return false;
|
|
1393
|
+
try {
|
|
1394
|
+
process.kill(claim.pid, 0);
|
|
1395
|
+
return true;
|
|
1396
|
+
} catch {
|
|
1397
|
+
return false;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function acquireDaemonClaim(data) {
|
|
1401
|
+
const claim = {
|
|
1402
|
+
pid: data.pid,
|
|
1403
|
+
startedAt: data.startedAt,
|
|
1404
|
+
createdAt: Date.now()
|
|
1405
|
+
};
|
|
1406
|
+
const serialized = `${JSON.stringify(claim)}
|
|
1407
|
+
`;
|
|
1408
|
+
for (let attempt = 0; attempt < 8; attempt++) {
|
|
1409
|
+
try {
|
|
1410
|
+
import_node_fs3.default.writeFileSync(daemonClaimPath(), serialized, { encoding: "utf8", flag: "wx" });
|
|
1411
|
+
return true;
|
|
1412
|
+
} catch (error) {
|
|
1413
|
+
if (!isAlreadyExists(error)) throw error;
|
|
1414
|
+
}
|
|
1415
|
+
const existing = readDaemonClaim();
|
|
1416
|
+
if (existing && sameDaemonOwner(existing, claim)) return true;
|
|
1417
|
+
if (existing && isDaemonClaimFresh(existing)) return false;
|
|
1418
|
+
let before;
|
|
1419
|
+
try {
|
|
1420
|
+
before = import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8");
|
|
1421
|
+
const latest = parseDaemonClaim(before);
|
|
1422
|
+
if (latest && isDaemonClaimFresh(latest)) return false;
|
|
1423
|
+
if (import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8") !== before) continue;
|
|
1424
|
+
import_node_fs3.default.unlinkSync(daemonClaimPath());
|
|
1425
|
+
} catch {
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
return false;
|
|
1429
|
+
}
|
|
1430
|
+
function releaseDaemonClaim(owner) {
|
|
1431
|
+
try {
|
|
1432
|
+
const claim = readDaemonClaim();
|
|
1433
|
+
if (!claim || !sameDaemonOwner(claim, owner)) return;
|
|
1434
|
+
import_node_fs3.default.unlinkSync(daemonClaimPath());
|
|
1435
|
+
} catch {
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1255
1438
|
function claimDaemonLockfile(data) {
|
|
1256
1439
|
ensureSootsimHome();
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1440
|
+
if (!acquireDaemonClaim(data)) return false;
|
|
1441
|
+
try {
|
|
1442
|
+
const existing = readDaemonLockfile();
|
|
1443
|
+
if (existing && sameDaemonOwner(existing, data)) {
|
|
1444
|
+
writeDaemonLockfile(data);
|
|
1445
|
+
return true;
|
|
1446
|
+
}
|
|
1447
|
+
if (existing && isDaemonLockfileFresh(existing)) return false;
|
|
1448
|
+
if (existing) {
|
|
1449
|
+
const latest = readDaemonLockfile();
|
|
1450
|
+
if (!latest || !sameDaemonOwner(latest, existing)) return false;
|
|
1451
|
+
if (isDaemonLockfileFresh(latest)) return false;
|
|
1452
|
+
try {
|
|
1453
|
+
import_node_fs3.default.unlinkSync(daemonLockfilePath());
|
|
1454
|
+
} catch {
|
|
1455
|
+
return false;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
return createDaemonLockfileExclusive(data);
|
|
1459
|
+
} finally {
|
|
1460
|
+
releaseDaemonClaim(data);
|
|
1260
1461
|
}
|
|
1261
|
-
writeDaemonLockfile(data);
|
|
1262
|
-
return true;
|
|
1263
1462
|
}
|
|
1264
|
-
function removeDaemonLockfile() {
|
|
1463
|
+
function removeDaemonLockfile(owner) {
|
|
1265
1464
|
try {
|
|
1465
|
+
const lockfile = readDaemonLockfile();
|
|
1466
|
+
if (!lockfile || !sameDaemonOwner(lockfile, owner)) return;
|
|
1266
1467
|
import_node_fs3.default.unlinkSync(daemonLockfilePath());
|
|
1267
1468
|
} catch {
|
|
1268
1469
|
}
|
|
@@ -1284,7 +1485,7 @@ var import_url = require("url");
|
|
|
1284
1485
|
|
|
1285
1486
|
// ../contrast-runtime-delivery/src/index.ts
|
|
1286
1487
|
var import_node_child_process = require("node:child_process");
|
|
1287
|
-
var
|
|
1488
|
+
var import_node_crypto2 = __toESM(require("node:crypto"), 1);
|
|
1288
1489
|
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
1289
1490
|
var import_node_os2 = __toESM(require("node:os"), 1);
|
|
1290
1491
|
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
@@ -1664,7 +1865,7 @@ async function downloadToFile(url, destPath) {
|
|
|
1664
1865
|
}
|
|
1665
1866
|
function sha256File(filePath) {
|
|
1666
1867
|
return new Promise((resolve2, reject) => {
|
|
1667
|
-
const hash =
|
|
1868
|
+
const hash = import_node_crypto2.default.createHash("sha256");
|
|
1668
1869
|
const stream = import_node_fs5.default.createReadStream(filePath);
|
|
1669
1870
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
1670
1871
|
stream.on("error", reject);
|
|
@@ -1780,7 +1981,7 @@ var import_node_path9 = __toESM(require("node:path"), 1);
|
|
|
1780
1981
|
|
|
1781
1982
|
// src/agent-sessions.ts
|
|
1782
1983
|
var import_node_child_process2 = require("node:child_process");
|
|
1783
|
-
var
|
|
1984
|
+
var import_node_crypto4 = require("node:crypto");
|
|
1784
1985
|
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
1785
1986
|
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
1786
1987
|
var import_node_readline = __toESM(require("node:readline"), 1);
|
|
@@ -1825,7 +2026,7 @@ function encodeAgentPromptEnvelope(input) {
|
|
|
1825
2026
|
}
|
|
1826
2027
|
|
|
1827
2028
|
// src/attached-projects.ts
|
|
1828
|
-
var
|
|
2029
|
+
var import_node_crypto3 = require("node:crypto");
|
|
1829
2030
|
var import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
1830
2031
|
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
1831
2032
|
var overrideDir = null;
|
|
@@ -1899,10 +2100,10 @@ function mutateStore(fn) {
|
|
|
1899
2100
|
return store;
|
|
1900
2101
|
}
|
|
1901
2102
|
function projectIdForCwd(cwd) {
|
|
1902
|
-
return (0,
|
|
2103
|
+
return (0, import_node_crypto3.createHash)("sha256").update(import_node_path7.default.resolve(cwd)).digest("hex").slice(0, 16);
|
|
1903
2104
|
}
|
|
1904
2105
|
function newSessionId() {
|
|
1905
|
-
return `s_${(0,
|
|
2106
|
+
return `s_${(0, import_node_crypto3.randomBytes)(10).toString("hex")}`;
|
|
1906
2107
|
}
|
|
1907
2108
|
function upsertProject(input) {
|
|
1908
2109
|
const cwd = import_node_path7.default.resolve(input.cwd);
|
|
@@ -2326,7 +2527,7 @@ async function startSession(opts) {
|
|
|
2326
2527
|
`session already running for project=${project.id} provider=${provider} (session ${existingLive.id}, pid ${existingLive.wrapperPid}). end it first with \`rnx agent end <sessionId>\`.`
|
|
2327
2528
|
);
|
|
2328
2529
|
}
|
|
2329
|
-
const claudeSessionUuid = provider === "claude" ? (0,
|
|
2530
|
+
const claudeSessionUuid = provider === "claude" ? (0, import_node_crypto4.randomUUID)() : void 0;
|
|
2330
2531
|
const session = upsertSession({
|
|
2331
2532
|
projectId: project.id,
|
|
2332
2533
|
provider,
|
|
@@ -3120,15 +3321,6 @@ var import_http2 = __toESM(require("http"), 1);
|
|
|
3120
3321
|
var import_https = __toESM(require("https"), 1);
|
|
3121
3322
|
var import_promises4 = require("stream/promises");
|
|
3122
3323
|
|
|
3123
|
-
// src/backend-origin.ts
|
|
3124
|
-
function normalizeHostname(hostname) {
|
|
3125
|
-
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
3126
|
-
}
|
|
3127
|
-
function isLoopbackHost(hostname) {
|
|
3128
|
-
const normalized = normalizeHostname(hostname);
|
|
3129
|
-
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
3130
|
-
}
|
|
3131
|
-
|
|
3132
3324
|
// src/host/fetch-proxy-overrides.ts
|
|
3133
3325
|
var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
|
|
3134
3326
|
var HOST_HEADER_OVERRIDES = [
|
|
@@ -3594,9 +3786,18 @@ export const Appearance = rn.Appearance
|
|
|
3594
3786
|
`;
|
|
3595
3787
|
}
|
|
3596
3788
|
function sendJavaScript(req, res, source) {
|
|
3789
|
+
const origin = req.headers.origin;
|
|
3790
|
+
let allowedOrigin;
|
|
3791
|
+
if (origin) {
|
|
3792
|
+
try {
|
|
3793
|
+
if (isLoopbackHost(new URL(origin).hostname)) allowedOrigin = origin;
|
|
3794
|
+
} catch {
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3597
3797
|
res.writeHead(200, {
|
|
3598
3798
|
"Content-Type": "application/javascript; charset=utf-8",
|
|
3599
|
-
"Cache-Control": "no-cache"
|
|
3799
|
+
"Cache-Control": "no-cache",
|
|
3800
|
+
...allowedOrigin ? { "Access-Control-Allow-Origin": allowedOrigin, Vary: "Origin" } : {}
|
|
3600
3801
|
});
|
|
3601
3802
|
res.end(req.method === "HEAD" ? void 0 : source);
|
|
3602
3803
|
}
|
|
@@ -3617,6 +3818,23 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
3617
3818
|
} catch {
|
|
3618
3819
|
return false;
|
|
3619
3820
|
}
|
|
3821
|
+
if (options.requireLoopbackOrigin) {
|
|
3822
|
+
const origin = req.headers.origin;
|
|
3823
|
+
const remoteAddress = req.socket.remoteAddress?.replace(/^::ffff:/, "");
|
|
3824
|
+
let allowed = Boolean(remoteAddress && isLoopbackHost(remoteAddress));
|
|
3825
|
+
if (allowed && origin) {
|
|
3826
|
+
try {
|
|
3827
|
+
allowed = isLoopbackHost(new URL(origin).hostname);
|
|
3828
|
+
} catch {
|
|
3829
|
+
allowed = false;
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
if (!allowed) {
|
|
3833
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3834
|
+
res.end("replacement modules are available only to loopback origins");
|
|
3835
|
+
return true;
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3620
3838
|
if (url.pathname === `${REPLACEMENT_RUNTIME_PREFIX}/react`) {
|
|
3621
3839
|
sendJavaScript(req, res, reactRuntimeSource(options.reactBridgeUrl));
|
|
3622
3840
|
return true;
|
|
@@ -3626,6 +3844,11 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
3626
3844
|
return true;
|
|
3627
3845
|
}
|
|
3628
3846
|
if (url.pathname !== REPLACEMENT_MODULE_ROUTE) return false;
|
|
3847
|
+
if (options.requestToken && url.searchParams.get("token") !== options.requestToken) {
|
|
3848
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3849
|
+
res.end("replacement module request token is invalid");
|
|
3850
|
+
return true;
|
|
3851
|
+
}
|
|
3629
3852
|
const targetPath = url.searchParams.get("path");
|
|
3630
3853
|
if (!targetPath) {
|
|
3631
3854
|
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
|
|
@@ -3638,17 +3861,42 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
3638
3861
|
res.end("replacement files must be .js, .jsx, .ts, or .tsx");
|
|
3639
3862
|
return true;
|
|
3640
3863
|
}
|
|
3864
|
+
if (!import_node_path10.default.isAbsolute(targetPath)) {
|
|
3865
|
+
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3866
|
+
res.end("replacement file path must be absolute");
|
|
3867
|
+
return true;
|
|
3868
|
+
}
|
|
3869
|
+
let resolvedProjectRoot;
|
|
3870
|
+
if (options.projectRoot) {
|
|
3871
|
+
const lexicalProjectRoot = import_node_path10.default.resolve(options.projectRoot);
|
|
3872
|
+
resolvedProjectRoot = await import_promises5.default.realpath(options.projectRoot);
|
|
3873
|
+
const lexicalTarget = import_node_path10.default.relative(lexicalProjectRoot, targetPath);
|
|
3874
|
+
if (lexicalTarget.startsWith("..") || import_node_path10.default.isAbsolute(lexicalTarget)) {
|
|
3875
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3876
|
+
res.end("replacement file must be inside the project root");
|
|
3877
|
+
return true;
|
|
3878
|
+
}
|
|
3879
|
+
}
|
|
3880
|
+
let resolvedTargetPath;
|
|
3641
3881
|
try {
|
|
3642
|
-
await import_promises5.default.
|
|
3882
|
+
resolvedTargetPath = await import_promises5.default.realpath(targetPath);
|
|
3643
3883
|
} catch (error) {
|
|
3644
3884
|
const message = error instanceof Error ? error.message : String(error);
|
|
3645
3885
|
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3646
3886
|
res.end(`replacement file not found: ${message}`);
|
|
3647
3887
|
return true;
|
|
3648
3888
|
}
|
|
3889
|
+
if (resolvedProjectRoot) {
|
|
3890
|
+
const relativeTarget = import_node_path10.default.relative(resolvedProjectRoot, resolvedTargetPath);
|
|
3891
|
+
if (relativeTarget.startsWith("..") || import_node_path10.default.isAbsolute(relativeTarget)) {
|
|
3892
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3893
|
+
res.end("replacement file must be inside the project root");
|
|
3894
|
+
return true;
|
|
3895
|
+
}
|
|
3896
|
+
}
|
|
3649
3897
|
try {
|
|
3650
3898
|
const result = await (0, import_esbuild.build)({
|
|
3651
|
-
entryPoints: [
|
|
3899
|
+
entryPoints: [resolvedTargetPath],
|
|
3652
3900
|
bundle: true,
|
|
3653
3901
|
write: false,
|
|
3654
3902
|
format: "esm",
|
|
@@ -4911,7 +5159,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4911
5159
|
removeLockfile() {
|
|
4912
5160
|
if (!this.shouldWriteLockfile) return;
|
|
4913
5161
|
try {
|
|
4914
|
-
removeDaemonLockfile();
|
|
5162
|
+
removeDaemonLockfile({ pid: process.pid, startedAt: this.startedAt });
|
|
4915
5163
|
} catch {
|
|
4916
5164
|
}
|
|
4917
5165
|
}
|
|
@@ -5470,7 +5718,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
5470
5718
|
}
|
|
5471
5719
|
if (this.shouldWriteLockfile) {
|
|
5472
5720
|
try {
|
|
5473
|
-
removeDaemonLockfile();
|
|
5721
|
+
removeDaemonLockfile({ pid: process.pid, startedAt: this.startedAt });
|
|
5474
5722
|
} catch {
|
|
5475
5723
|
}
|
|
5476
5724
|
}
|