rnxsim 0.1.343 → 0.1.345
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-RFD32ACU.js → agent-52G55XTO.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-2YLW2HQK.js → agent-wrapper-BOZM43ON.js} +2 -2
- package/dist-cli/chunks/{app-fonts-6OATDF3Y.js → app-fonts-A2L6V5EZ.js} +2 -2
- package/dist-cli/chunks/{assert-PSQICFOY.js → assert-CJKIP4LN.js} +2 -2
- package/dist-cli/chunks/{auth-XWLFKZT7.js → auth-VHHN3TOB.js} +2 -2
- package/dist-cli/chunks/{beta-I6WTVM6C.js → beta-EBDIGV3E.js} +2 -2
- package/dist-cli/chunks/{camera-45HKTLWG.js → camera-5F4KKCQ3.js} +2 -2
- package/dist-cli/chunks/chunk-3DBTS4MC.js +15 -0
- package/dist-cli/chunks/chunk-3N7M5HMJ.js +6 -0
- package/dist-cli/chunks/{chunk-RWYA2USN.js → chunk-4BIPA7MD.js} +1 -1
- package/dist-cli/chunks/chunk-4OKV7T5D.js +4 -0
- package/dist-cli/chunks/{chunk-T4T6DDKM.js → chunk-4ZILDTZX.js} +2 -2
- package/dist-cli/chunks/{chunk-R7X74I3I.js → chunk-5GXRRUOA.js} +26 -26
- package/dist-cli/chunks/chunk-63ASUHOV.js +4 -0
- package/dist-cli/chunks/{chunk-DASP2EKF.js → chunk-7GO2DSYQ.js} +1 -1
- package/dist-cli/chunks/{chunk-HJXIBZ35.js → chunk-7LGINKM6.js} +2 -2
- package/dist-cli/chunks/{chunk-2IPMH24A.js → chunk-7UIIAHVU.js} +2 -2
- package/dist-cli/chunks/{chunk-ES5BHPTS.js → chunk-7V4KPZ7O.js} +2 -2
- package/dist-cli/chunks/{chunk-FCHRGEHA.js → chunk-7YMQRA6L.js} +2 -2
- package/dist-cli/chunks/{chunk-DC7TS573.js → chunk-A2Q76LJV.js} +2 -2
- package/dist-cli/chunks/{chunk-SAUCA7SN.js → chunk-BCQV63BW.js} +45 -45
- package/dist-cli/chunks/{chunk-3FYJ7U3C.js → chunk-BFTDL2GX.js} +17 -17
- package/dist-cli/chunks/chunk-BHKSCNDC.js +4 -0
- package/dist-cli/chunks/{chunk-QPTJNLPT.js → chunk-DGTV3KOW.js} +1 -1
- package/dist-cli/chunks/chunk-DHM3JDCK.js +4 -0
- package/dist-cli/chunks/{chunk-TQRVLK64.js → chunk-DPP2M4AJ.js} +1 -1
- package/dist-cli/chunks/chunk-E2RGSCHT.js +4 -0
- package/dist-cli/chunks/{chunk-TQ5OPG33.js → chunk-EPLVIDPC.js} +1 -1
- package/dist-cli/chunks/{chunk-P3IDK7FR.js → chunk-GKGXULJK.js} +2 -2
- package/dist-cli/chunks/{chunk-34KDMQ6U.js → chunk-HK7YKH6N.js} +2 -2
- package/dist-cli/chunks/{chunk-BJUNXCPO.js → chunk-HXE344V3.js} +1 -1
- package/dist-cli/chunks/{chunk-HJHFC5ZZ.js → chunk-JC33TOAF.js} +1 -1
- package/dist-cli/chunks/{chunk-G3B2RZ47.js → chunk-KA4PJNTE.js} +2 -2
- package/dist-cli/chunks/{chunk-VC4TDPJQ.js → chunk-KH777UAO.js} +3 -3
- package/dist-cli/chunks/{chunk-4PFMDBLB.js → chunk-KRZPFXVN.js} +1 -1
- package/dist-cli/chunks/{chunk-6SLM6URN.js → chunk-KZFJNDH3.js} +1 -1
- package/dist-cli/chunks/{chunk-KLMWLQAO.js → chunk-LAQGSSTT.js} +1 -1
- package/dist-cli/chunks/chunk-LRM2XCEQ.js +11 -0
- package/dist-cli/chunks/{chunk-YKKVDKLE.js → chunk-NUPRHZQW.js} +2 -2
- package/dist-cli/chunks/{chunk-AKV2DGKM.js → chunk-OPHT4DUO.js} +1 -1
- package/dist-cli/chunks/{chunk-KON6XG4Y.js → chunk-P2CGGMU2.js} +2 -2
- package/dist-cli/chunks/{chunk-5FB4EA33.js → chunk-PLB6UVVX.js} +2 -2
- package/dist-cli/chunks/{chunk-FRRHCLG2.js → chunk-PLUWN2V5.js} +1 -1
- package/dist-cli/chunks/{chunk-WDA4QR6U.js → chunk-QNBBKRCA.js} +2 -2
- package/dist-cli/chunks/{chunk-G7S6T5OX.js → chunk-QNRWPAOA.js} +2 -2
- package/dist-cli/chunks/{chunk-2EVBZ37G.js → chunk-R7ZNRGQN.js} +1 -1
- package/dist-cli/chunks/{chunk-TMJGPUWJ.js → chunk-RB4VFUNM.js} +3 -3
- package/dist-cli/chunks/chunk-RT3DXTDP.js +25 -0
- package/dist-cli/chunks/{chunk-OYLIWHDB.js → chunk-RTDHX6CW.js} +2 -2
- package/dist-cli/chunks/{chunk-YLFDA4WW.js → chunk-T7SBFG5I.js} +2 -2
- package/dist-cli/chunks/{chunk-W7EXE22C.js → chunk-TEU5NGUA.js} +2 -2
- package/dist-cli/chunks/chunk-TMRD5MHL.js +99 -0
- package/dist-cli/chunks/{chunk-SU7RE3PV.js → chunk-TOF5TA5X.js} +11 -11
- package/dist-cli/chunks/{chunk-6IVEGYWV.js → chunk-U5YHXQHH.js} +2 -2
- package/dist-cli/chunks/{chunk-BA3HRFJ5.js → chunk-UVOEHIGP.js} +1 -1
- package/dist-cli/chunks/{chunk-SW4DV2TY.js → chunk-VLBN3KRC.js} +1 -1
- package/dist-cli/chunks/{chunk-7WKV6EKX.js → chunk-WPPGU5IK.js} +2 -2
- package/dist-cli/chunks/{chunk-JOE3J46E.js → chunk-WU72KL6Z.js} +2 -2
- package/dist-cli/chunks/chunk-XJBFJGNT.js +4 -0
- package/dist-cli/chunks/{chunk-3CMKNWRL.js → chunk-XXZLK4BY.js} +1 -1
- package/dist-cli/chunks/{chunk-BKMPV6N4.js → chunk-YVSUFVVB.js} +1 -1
- package/dist-cli/chunks/{chunk-RO3WVQPB.js → chunk-ZMTZ5G5H.js} +2 -2
- package/dist-cli/chunks/{cleanup-OU4VKFC3.js → cleanup-MAVZJXVW.js} +2 -2
- package/dist-cli/chunks/cli-version-2B4KRNML.js +4 -0
- package/dist-cli/chunks/{compat-GAEKP67T.js → compat-7AURLGCS.js} +2 -2
- package/dist-cli/chunks/config-TN3Y4J5N.js +13 -0
- package/dist-cli/chunks/{control-VQJURMFD.js → control-EV2ELU5R.js} +2 -2
- package/dist-cli/chunks/daemon-KKDG5MYR.js +4 -0
- package/dist-cli/chunks/{debug-F5N2LO4T.js → debug-JICITUB6.js} +3 -3
- package/dist-cli/chunks/{desktop-I4ILT4BS.js → desktop-4F5HGLLX.js} +3 -3
- package/dist-cli/chunks/{detox-2HMPYSP4.js → detox-ZC7NHLJI.js} +2 -2
- package/dist-cli/chunks/{device-5LWLOB5R.js → device-V57GHRXX.js} +2 -2
- package/dist-cli/chunks/{diagnose-5S4IQPAP.js → diagnose-FF4IWYXC.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-CJSZVJQX.js → disk-cleanup-T277L6ZO.js} +2 -2
- package/dist-cli/chunks/drivers-LCX7S76X.js +4 -0
- package/dist-cli/chunks/{film-HCPU2TDB.js → film-G7ZAPWB7.js} +3 -3
- package/dist-cli/chunks/flow-ONZGGFGD.js +4 -0
- package/dist-cli/chunks/help-DROVDXJM.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-YYUEZQPR.js → hidden-runtime-alias-VSJNNSNI.js} +2 -2
- package/dist-cli/chunks/{home-paths-3FXISM5I.js → home-paths-75HP3HKA.js} +2 -2
- package/dist-cli/chunks/inspect-MDA7ESGQ.js +4 -0
- package/dist-cli/chunks/install-desktop-EIVZHIFA.js +4 -0
- package/dist-cli/chunks/login-ZSIHGHUK.js +26 -0
- package/dist-cli/chunks/logout-Q4DXMI2C.js +4 -0
- package/dist-cli/chunks/{maestro-F5KK4RC4.js → maestro-LE5LCRBL.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-6SUU3Y5I.js → maestro-generate-D3ZIJCRL.js} +3 -3
- package/dist-cli/chunks/{mode-CSWGOJLI.js → mode-BWX6MDPJ.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-Y6VJ4SVV.js → optional-demo-registry-6CVASL3S.js} +2 -2
- package/dist-cli/chunks/{perf-NRWWAJL4.js → perf-NXQZISN6.js} +2 -2
- package/dist-cli/chunks/{permissions-OD62A3DJ.js → permissions-5PD67RRO.js} +2 -2
- package/dist-cli/chunks/privacy-H5KNRNIZ.js +4 -0
- package/dist-cli/chunks/{record-JZT2GM3G.js → record-YJF4KXMR.js} +3 -3
- package/dist-cli/chunks/{report-issue-ZWSNHOPB.js → report-issue-XOL5FQBG.js} +2 -2
- package/dist-cli/chunks/reset-5LZN5P5B.js +4 -0
- package/dist-cli/chunks/runtime-U36VWBH3.js +4 -0
- package/dist-cli/chunks/{screenshot-command-ZGJR7ICY.js → screenshot-command-VRPJXWFS.js} +3 -3
- package/dist-cli/chunks/{screenshot-layers-5AQKOJZK.js → screenshot-layers-QP4WA2F5.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-CPTWK5Y3.js → screenshots-capture-O2IBAVSP.js} +2 -2
- package/dist-cli/chunks/serve-WC6RZNJL.js +118 -0
- package/dist-cli/chunks/setup-A6BIG3KL.js +30 -0
- package/dist-cli/chunks/{skills-NVWRBMEO.js → skills-A7YC6RL5.js} +2 -2
- package/dist-cli/chunks/{state-QGLTKN6K.js → state-IJI5YROJ.js} +2 -2
- package/dist-cli/chunks/{storage-OZMEZ4AV.js → storage-Z2DBO2PQ.js} +4 -4
- package/dist-cli/chunks/store-BYTCKNIC.js +4 -0
- package/dist-cli/chunks/telemetry-JLHFMD7N.js +4 -0
- package/dist-cli/chunks/{timeline-EXLDREY3.js → timeline-N7V2M6QA.js} +2 -2
- package/dist-cli/chunks/{upgrade-4VWXQO6I.js → upgrade-P2NH3BOR.js} +2 -2
- package/dist-cli/chunks/upload-Z2WX5DCD.js +4 -0
- package/dist-cli/chunks/{version-WZM6XCD2.js → version-OUHCSCUS.js} +2 -2
- package/dist-cli/chunks/{web-ZYPEUVWL.js → web-6NRTF3UV.js} +2 -2
- package/dist-cli/chunks/welcome-6RS7PEJW.js +5 -0
- package/dist-cli/chunks/{what-happened-KF2HLWKW.js → what-happened-FUEL3BEF.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 +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.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 +18 -4
- package/dist-lib/home-paths.cjs +145 -11
- package/dist-lib/host/bridge-host.cjs +236 -31
- 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 +25 -2
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +384 -385
- package/dist-lib/vite.cjs +193 -37
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +12 -5
- package/skills/rnx-test/SKILL.md +4 -0
- package/src/dev-bundle-resolution.ts +13 -6
- 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-44LRQEU3.js +0 -4
- package/dist-cli/chunks/chunk-4RKTGL63.js +0 -9
- package/dist-cli/chunks/chunk-5SCIDXJD.js +0 -25
- package/dist-cli/chunks/chunk-CUVY4A2A.js +0 -4
- package/dist-cli/chunks/chunk-DPJGB7MP.js +0 -101
- package/dist-cli/chunks/chunk-HD6P3W5R.js +0 -4
- package/dist-cli/chunks/chunk-HFNESSHG.js +0 -15
- package/dist-cli/chunks/chunk-I7HHBFSD.js +0 -4
- package/dist-cli/chunks/chunk-LV2G34IX.js +0 -4
- package/dist-cli/chunks/cli-version-REQOM22G.js +0 -4
- package/dist-cli/chunks/config-QTFXJKD6.js +0 -13
- package/dist-cli/chunks/daemon-ETA375WE.js +0 -4
- package/dist-cli/chunks/drivers-R4YB2XAF.js +0 -4
- package/dist-cli/chunks/flow-3VQL6XZT.js +0 -4
- package/dist-cli/chunks/help-2RYCKZ2G.js +0 -4
- package/dist-cli/chunks/inspect-XDSX5D6D.js +0 -4
- package/dist-cli/chunks/install-desktop-OKVRLL35.js +0 -4
- package/dist-cli/chunks/login-4VCBPAY2.js +0 -28
- package/dist-cli/chunks/logout-WSL5JS5R.js +0 -4
- package/dist-cli/chunks/reset-3C52YQCV.js +0 -4
- package/dist-cli/chunks/runtime-4V2RBUOR.js +0 -4
- package/dist-cli/chunks/serve-ERAZQGCJ.js +0 -118
- package/dist-cli/chunks/setup-UG6PLYIL.js +0 -32
- package/dist-cli/chunks/store-VPBQKKWA.js +0 -4
- package/dist-cli/chunks/telemetry-FRW7OCYZ.js +0 -4
- package/dist-cli/chunks/upload-C6676NST.js +0 -4
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.345 | (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;
|
|
@@ -9524,6 +9524,20 @@ var init_config = __esm({
|
|
|
9524
9524
|
}
|
|
9525
9525
|
});
|
|
9526
9526
|
|
|
9527
|
+
// src/backend-origin.ts
|
|
9528
|
+
function normalizeHostname(hostname) {
|
|
9529
|
+
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
9530
|
+
}
|
|
9531
|
+
function isLoopbackHost(hostname) {
|
|
9532
|
+
const normalized = normalizeHostname(hostname);
|
|
9533
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
9534
|
+
}
|
|
9535
|
+
var init_backend_origin = __esm({
|
|
9536
|
+
"src/backend-origin.ts"() {
|
|
9537
|
+
"use strict";
|
|
9538
|
+
}
|
|
9539
|
+
});
|
|
9540
|
+
|
|
9527
9541
|
// src/native-dev-bundle-url.ts
|
|
9528
9542
|
function isAbsoluteHttpUrl(url) {
|
|
9529
9543
|
return /^https?:\/\//i.test(url);
|
|
@@ -9531,6 +9545,19 @@ function isAbsoluteHttpUrl(url) {
|
|
|
9531
9545
|
function isNativeDevBundlePath(pathname) {
|
|
9532
9546
|
return pathname.endsWith(".bundle");
|
|
9533
9547
|
}
|
|
9548
|
+
function alignLoopbackBundleUrlWithProbe(bundleUrl, probeBaseUrl) {
|
|
9549
|
+
try {
|
|
9550
|
+
const bundle = new URL(bundleUrl);
|
|
9551
|
+
const probe3 = new URL(probeBaseUrl);
|
|
9552
|
+
if (!isLoopbackHost(bundle.hostname) || !isLoopbackHost(probe3.hostname)) {
|
|
9553
|
+
return bundleUrl;
|
|
9554
|
+
}
|
|
9555
|
+
bundle.hostname = probe3.hostname;
|
|
9556
|
+
return bundle.toString();
|
|
9557
|
+
} catch {
|
|
9558
|
+
return bundleUrl;
|
|
9559
|
+
}
|
|
9560
|
+
}
|
|
9534
9561
|
function applyPreviewProdBundle(parsed) {
|
|
9535
9562
|
if (!process.env.SOOTSIM_PREVIEW_PROD_BUNDLE) return;
|
|
9536
9563
|
parsed.searchParams.set("dev", "false");
|
|
@@ -9570,6 +9597,7 @@ var METRO_BUNDLE_PATH;
|
|
|
9570
9597
|
var init_native_dev_bundle_url = __esm({
|
|
9571
9598
|
"src/native-dev-bundle-url.ts"() {
|
|
9572
9599
|
"use strict";
|
|
9600
|
+
init_backend_origin();
|
|
9573
9601
|
METRO_BUNDLE_PATH = "/index.bundle?platform=ios&dev=true&hot=true&minify=false";
|
|
9574
9602
|
}
|
|
9575
9603
|
});
|
|
@@ -9678,9 +9706,9 @@ function safeChildPlistName(value) {
|
|
|
9678
9706
|
name: file.toLowerCase().endsWith(".plist") ? file : `${file}.plist`
|
|
9679
9707
|
};
|
|
9680
9708
|
}
|
|
9681
|
-
async function readableSettingsBundle(
|
|
9709
|
+
async function readableSettingsBundle(path18) {
|
|
9682
9710
|
try {
|
|
9683
|
-
const root = await (0, import_promises.stat)((0, import_node_path.join)(
|
|
9711
|
+
const root = await (0, import_promises.stat)((0, import_node_path.join)(path18, "Root.plist"));
|
|
9684
9712
|
return root.isFile() && root.size <= MAX_PLIST_BYTES;
|
|
9685
9713
|
} catch {
|
|
9686
9714
|
return false;
|
|
@@ -9725,11 +9753,11 @@ async function settingsBundleFingerprint(bundlePath) {
|
|
|
9725
9753
|
return null;
|
|
9726
9754
|
}
|
|
9727
9755
|
}
|
|
9728
|
-
async function parsePlistRecord(
|
|
9756
|
+
async function parsePlistRecord(path18) {
|
|
9729
9757
|
try {
|
|
9730
|
-
const metadata = await (0, import_promises.stat)(
|
|
9758
|
+
const metadata = await (0, import_promises.stat)(path18);
|
|
9731
9759
|
if (!metadata.isFile() || metadata.size > MAX_PLIST_BYTES) return null;
|
|
9732
|
-
const source = await (0, import_promises.readFile)(
|
|
9760
|
+
const source = await (0, import_promises.readFile)(path18, "utf8");
|
|
9733
9761
|
const parsed = parsePlistSource(source);
|
|
9734
9762
|
return isRecord2(parsed) ? parsed : null;
|
|
9735
9763
|
} catch {
|
|
@@ -10008,10 +10036,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
10008
10036
|
sock.connect(port, "localhost");
|
|
10009
10037
|
});
|
|
10010
10038
|
}
|
|
10011
|
-
function httpGet(port,
|
|
10039
|
+
function httpGet(port, path18, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
10012
10040
|
return new Promise((resolve7) => {
|
|
10013
10041
|
const req = import_http.default.request(
|
|
10014
|
-
{ hostname: "localhost", port, path:
|
|
10042
|
+
{ hostname: "localhost", port, path: path18, method, timeout, headers },
|
|
10015
10043
|
(res) => {
|
|
10016
10044
|
let body = "";
|
|
10017
10045
|
res.on("data", (c) => body += c.toString());
|
|
@@ -10203,7 +10231,8 @@ function applyManifest(result, manifestRes, buildIconProxyUrl) {
|
|
|
10203
10231
|
if (client.name) result.projectName = client.name;
|
|
10204
10232
|
if (client.ios?.bundleIdentifier) result.bundleId = client.ios.bundleIdentifier;
|
|
10205
10233
|
if (result.framework === "metro" && client.sdkVersion) result.framework = "expo";
|
|
10206
|
-
const
|
|
10234
|
+
const rawLaunchUrl = manifest?.launchAsset?.url;
|
|
10235
|
+
const launchUrl2 = typeof rawLaunchUrl === "string" ? alignLoopbackBundleUrlWithProbe(rawLaunchUrl, `http://localhost:${result.port}`) : rawLaunchUrl;
|
|
10207
10236
|
if (launchUrl2 && !result.patched && !isDirectOneBundleUrl(result.bundleUrl)) {
|
|
10208
10237
|
result.bundleUrl = withRuntimeConfig(result.port, launchUrl2, result.cwd);
|
|
10209
10238
|
}
|
|
@@ -10724,8 +10753,8 @@ function readPrivacyPreferences() {
|
|
|
10724
10753
|
const productAnalytics = settings?.productAnalytics;
|
|
10725
10754
|
const crashReports = settings?.crashReports;
|
|
10726
10755
|
return {
|
|
10727
|
-
productAnalytics: typeof productAnalytics === "boolean" ? productAnalytics :
|
|
10728
|
-
crashReports: typeof crashReports === "boolean" ? crashReports :
|
|
10756
|
+
productAnalytics: typeof productAnalytics === "boolean" ? productAnalytics : false,
|
|
10757
|
+
crashReports: typeof crashReports === "boolean" ? crashReports : false,
|
|
10729
10758
|
configured: typeof productAnalytics === "boolean" && typeof crashReports === "boolean"
|
|
10730
10759
|
};
|
|
10731
10760
|
}
|
|
@@ -10894,10 +10923,30 @@ function readLiveRuntimeVersions() {
|
|
|
10894
10923
|
}
|
|
10895
10924
|
function writeDaemonLockfile(data) {
|
|
10896
10925
|
ensureSootsimHome();
|
|
10897
|
-
const
|
|
10926
|
+
const lockfilePath = daemonLockfilePath();
|
|
10927
|
+
const existing = readDaemonLockfile();
|
|
10928
|
+
if (!existing) {
|
|
10929
|
+
if (createDaemonLockfileExclusive(data)) return;
|
|
10930
|
+
throw new Error("another rnx daemon claimed the lockfile before this write");
|
|
10931
|
+
}
|
|
10932
|
+
if (!sameDaemonOwner(existing, data)) {
|
|
10933
|
+
throw new Error("refusing to overwrite another rnx daemon lockfile");
|
|
10934
|
+
}
|
|
10935
|
+
const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
10898
10936
|
import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
10899
10937
|
`, "utf8");
|
|
10900
|
-
|
|
10938
|
+
try {
|
|
10939
|
+
const current = readDaemonLockfile();
|
|
10940
|
+
if (!current || !sameDaemonOwner(current, data)) {
|
|
10941
|
+
throw new Error("rnx daemon lock ownership changed during heartbeat");
|
|
10942
|
+
}
|
|
10943
|
+
import_node_fs3.default.renameSync(tmp, lockfilePath);
|
|
10944
|
+
} finally {
|
|
10945
|
+
try {
|
|
10946
|
+
import_node_fs3.default.unlinkSync(tmp);
|
|
10947
|
+
} catch {
|
|
10948
|
+
}
|
|
10949
|
+
}
|
|
10901
10950
|
}
|
|
10902
10951
|
function writeDevBridgeLockfile(data) {
|
|
10903
10952
|
import_node_fs3.default.mkdirSync(devBridgesDir(), { recursive: true });
|
|
@@ -10907,17 +10956,130 @@ function writeDevBridgeLockfile(data) {
|
|
|
10907
10956
|
`, "utf8");
|
|
10908
10957
|
import_node_fs3.default.renameSync(tmp, lockfilePath);
|
|
10909
10958
|
}
|
|
10959
|
+
function sameDaemonOwner(left, right) {
|
|
10960
|
+
return left.pid === right.pid && left.startedAt === right.startedAt;
|
|
10961
|
+
}
|
|
10962
|
+
function isAlreadyExists(error) {
|
|
10963
|
+
return error instanceof Error && "code" in error && Reflect.get(error, "code") === "EEXIST";
|
|
10964
|
+
}
|
|
10965
|
+
function createDaemonLockfileExclusive(data) {
|
|
10966
|
+
const lockfilePath = daemonLockfilePath();
|
|
10967
|
+
const tmp = `${lockfilePath}.${data.pid}.${(0, import_node_crypto.randomUUID)()}.claim`;
|
|
10968
|
+
import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
10969
|
+
`, "utf8");
|
|
10970
|
+
try {
|
|
10971
|
+
import_node_fs3.default.linkSync(tmp, lockfilePath);
|
|
10972
|
+
return true;
|
|
10973
|
+
} catch (error) {
|
|
10974
|
+
if (isAlreadyExists(error)) return false;
|
|
10975
|
+
throw error;
|
|
10976
|
+
} finally {
|
|
10977
|
+
try {
|
|
10978
|
+
import_node_fs3.default.unlinkSync(tmp);
|
|
10979
|
+
} catch {
|
|
10980
|
+
}
|
|
10981
|
+
}
|
|
10982
|
+
}
|
|
10983
|
+
function daemonClaimPath() {
|
|
10984
|
+
return `${daemonLockfilePath()}.claim`;
|
|
10985
|
+
}
|
|
10986
|
+
function parseDaemonClaim(raw) {
|
|
10987
|
+
try {
|
|
10988
|
+
const value = JSON.parse(raw);
|
|
10989
|
+
if (value !== null && typeof value === "object" && typeof Reflect.get(value, "pid") === "number" && typeof Reflect.get(value, "startedAt") === "number" && typeof Reflect.get(value, "createdAt") === "number") {
|
|
10990
|
+
return {
|
|
10991
|
+
pid: Reflect.get(value, "pid"),
|
|
10992
|
+
startedAt: Reflect.get(value, "startedAt"),
|
|
10993
|
+
createdAt: Reflect.get(value, "createdAt")
|
|
10994
|
+
};
|
|
10995
|
+
}
|
|
10996
|
+
} catch {
|
|
10997
|
+
}
|
|
10998
|
+
return null;
|
|
10999
|
+
}
|
|
11000
|
+
function readDaemonClaim() {
|
|
11001
|
+
try {
|
|
11002
|
+
return parseDaemonClaim(import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8"));
|
|
11003
|
+
} catch {
|
|
11004
|
+
return null;
|
|
11005
|
+
}
|
|
11006
|
+
}
|
|
11007
|
+
function isDaemonClaimFresh(claim, now = Date.now()) {
|
|
11008
|
+
if (now - claim.createdAt > DAEMON_CLAIM_STALE_MS) return false;
|
|
11009
|
+
try {
|
|
11010
|
+
process.kill(claim.pid, 0);
|
|
11011
|
+
return true;
|
|
11012
|
+
} catch {
|
|
11013
|
+
return false;
|
|
11014
|
+
}
|
|
11015
|
+
}
|
|
11016
|
+
function acquireDaemonClaim(data) {
|
|
11017
|
+
const claim = {
|
|
11018
|
+
pid: data.pid,
|
|
11019
|
+
startedAt: data.startedAt,
|
|
11020
|
+
createdAt: Date.now()
|
|
11021
|
+
};
|
|
11022
|
+
const serialized = `${JSON.stringify(claim)}
|
|
11023
|
+
`;
|
|
11024
|
+
for (let attempt = 0; attempt < 8; attempt++) {
|
|
11025
|
+
try {
|
|
11026
|
+
import_node_fs3.default.writeFileSync(daemonClaimPath(), serialized, { encoding: "utf8", flag: "wx" });
|
|
11027
|
+
return true;
|
|
11028
|
+
} catch (error) {
|
|
11029
|
+
if (!isAlreadyExists(error)) throw error;
|
|
11030
|
+
}
|
|
11031
|
+
const existing = readDaemonClaim();
|
|
11032
|
+
if (existing && sameDaemonOwner(existing, claim)) return true;
|
|
11033
|
+
if (existing && isDaemonClaimFresh(existing)) return false;
|
|
11034
|
+
let before;
|
|
11035
|
+
try {
|
|
11036
|
+
before = import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8");
|
|
11037
|
+
const latest = parseDaemonClaim(before);
|
|
11038
|
+
if (latest && isDaemonClaimFresh(latest)) return false;
|
|
11039
|
+
if (import_node_fs3.default.readFileSync(daemonClaimPath(), "utf8") !== before) continue;
|
|
11040
|
+
import_node_fs3.default.unlinkSync(daemonClaimPath());
|
|
11041
|
+
} catch {
|
|
11042
|
+
}
|
|
11043
|
+
}
|
|
11044
|
+
return false;
|
|
11045
|
+
}
|
|
11046
|
+
function releaseDaemonClaim(owner) {
|
|
11047
|
+
try {
|
|
11048
|
+
const claim = readDaemonClaim();
|
|
11049
|
+
if (!claim || !sameDaemonOwner(claim, owner)) return;
|
|
11050
|
+
import_node_fs3.default.unlinkSync(daemonClaimPath());
|
|
11051
|
+
} catch {
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
10910
11054
|
function claimDaemonLockfile(data) {
|
|
10911
11055
|
ensureSootsimHome();
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
11056
|
+
if (!acquireDaemonClaim(data)) return false;
|
|
11057
|
+
try {
|
|
11058
|
+
const existing = readDaemonLockfile();
|
|
11059
|
+
if (existing && sameDaemonOwner(existing, data)) {
|
|
11060
|
+
writeDaemonLockfile(data);
|
|
11061
|
+
return true;
|
|
11062
|
+
}
|
|
11063
|
+
if (existing && isDaemonLockfileFresh(existing)) return false;
|
|
11064
|
+
if (existing) {
|
|
11065
|
+
const latest = readDaemonLockfile();
|
|
11066
|
+
if (!latest || !sameDaemonOwner(latest, existing)) return false;
|
|
11067
|
+
if (isDaemonLockfileFresh(latest)) return false;
|
|
11068
|
+
try {
|
|
11069
|
+
import_node_fs3.default.unlinkSync(daemonLockfilePath());
|
|
11070
|
+
} catch {
|
|
11071
|
+
return false;
|
|
11072
|
+
}
|
|
11073
|
+
}
|
|
11074
|
+
return createDaemonLockfileExclusive(data);
|
|
11075
|
+
} finally {
|
|
11076
|
+
releaseDaemonClaim(data);
|
|
10915
11077
|
}
|
|
10916
|
-
writeDaemonLockfile(data);
|
|
10917
|
-
return true;
|
|
10918
11078
|
}
|
|
10919
|
-
function removeDaemonLockfile() {
|
|
11079
|
+
function removeDaemonLockfile(owner) {
|
|
10920
11080
|
try {
|
|
11081
|
+
const lockfile = readDaemonLockfile();
|
|
11082
|
+
if (!lockfile || !sameDaemonOwner(lockfile, owner)) return;
|
|
10921
11083
|
import_node_fs3.default.unlinkSync(daemonLockfilePath());
|
|
10922
11084
|
} catch {
|
|
10923
11085
|
}
|
|
@@ -10931,7 +11093,7 @@ function removeDevBridgeLockfile(owner) {
|
|
|
10931
11093
|
} catch {
|
|
10932
11094
|
}
|
|
10933
11095
|
}
|
|
10934
|
-
var import_node_crypto, import_node_fs3, import_node_os, import_node_path4, SOOTSIM_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES;
|
|
11096
|
+
var import_node_crypto, import_node_fs3, import_node_os, import_node_path4, SOOTSIM_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES, DAEMON_CLAIM_STALE_MS;
|
|
10935
11097
|
var init_home_paths = __esm({
|
|
10936
11098
|
"src/home-paths.ts"() {
|
|
10937
11099
|
"use strict";
|
|
@@ -10946,6 +11108,7 @@ var init_home_paths = __esm({
|
|
|
10946
11108
|
CONFIG_FILE = "config.json";
|
|
10947
11109
|
DAEMON_HEARTBEAT_STALE_MS = 3e4;
|
|
10948
11110
|
DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
11111
|
+
DAEMON_CLAIM_STALE_MS = 3e4;
|
|
10949
11112
|
}
|
|
10950
11113
|
});
|
|
10951
11114
|
|
|
@@ -12870,20 +13033,6 @@ var init_agent_host = __esm({
|
|
|
12870
13033
|
}
|
|
12871
13034
|
});
|
|
12872
13035
|
|
|
12873
|
-
// src/backend-origin.ts
|
|
12874
|
-
function normalizeHostname(hostname) {
|
|
12875
|
-
return hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
12876
|
-
}
|
|
12877
|
-
function isLoopbackHost(hostname) {
|
|
12878
|
-
const normalized = normalizeHostname(hostname);
|
|
12879
|
-
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
|
|
12880
|
-
}
|
|
12881
|
-
var init_backend_origin = __esm({
|
|
12882
|
-
"src/backend-origin.ts"() {
|
|
12883
|
-
"use strict";
|
|
12884
|
-
}
|
|
12885
|
-
});
|
|
12886
|
-
|
|
12887
13036
|
// src/host/fetch-proxy-overrides.ts
|
|
12888
13037
|
function headerOverridesFor(hostname) {
|
|
12889
13038
|
const host = hostname.toLowerCase();
|
|
@@ -13367,9 +13516,18 @@ export const Appearance = rn.Appearance
|
|
|
13367
13516
|
`;
|
|
13368
13517
|
}
|
|
13369
13518
|
function sendJavaScript(req, res, source) {
|
|
13519
|
+
const origin = req.headers.origin;
|
|
13520
|
+
let allowedOrigin;
|
|
13521
|
+
if (origin) {
|
|
13522
|
+
try {
|
|
13523
|
+
if (isLoopbackHost(new URL(origin).hostname)) allowedOrigin = origin;
|
|
13524
|
+
} catch {
|
|
13525
|
+
}
|
|
13526
|
+
}
|
|
13370
13527
|
res.writeHead(200, {
|
|
13371
13528
|
"Content-Type": "application/javascript; charset=utf-8",
|
|
13372
|
-
"Cache-Control": "no-cache"
|
|
13529
|
+
"Cache-Control": "no-cache",
|
|
13530
|
+
...allowedOrigin ? { "Access-Control-Allow-Origin": allowedOrigin, Vary: "Origin" } : {}
|
|
13373
13531
|
});
|
|
13374
13532
|
res.end(req.method === "HEAD" ? void 0 : source);
|
|
13375
13533
|
}
|
|
@@ -13390,6 +13548,23 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
13390
13548
|
} catch {
|
|
13391
13549
|
return false;
|
|
13392
13550
|
}
|
|
13551
|
+
if (options.requireLoopbackOrigin) {
|
|
13552
|
+
const origin = req.headers.origin;
|
|
13553
|
+
const remoteAddress = req.socket.remoteAddress?.replace(/^::ffff:/, "");
|
|
13554
|
+
let allowed = Boolean(remoteAddress && isLoopbackHost(remoteAddress));
|
|
13555
|
+
if (allowed && origin) {
|
|
13556
|
+
try {
|
|
13557
|
+
allowed = isLoopbackHost(new URL(origin).hostname);
|
|
13558
|
+
} catch {
|
|
13559
|
+
allowed = false;
|
|
13560
|
+
}
|
|
13561
|
+
}
|
|
13562
|
+
if (!allowed) {
|
|
13563
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
13564
|
+
res.end("replacement modules are available only to loopback origins");
|
|
13565
|
+
return true;
|
|
13566
|
+
}
|
|
13567
|
+
}
|
|
13393
13568
|
if (url.pathname === `${REPLACEMENT_RUNTIME_PREFIX}/react`) {
|
|
13394
13569
|
sendJavaScript(req, res, reactRuntimeSource(options.reactBridgeUrl));
|
|
13395
13570
|
return true;
|
|
@@ -13399,6 +13574,11 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
13399
13574
|
return true;
|
|
13400
13575
|
}
|
|
13401
13576
|
if (url.pathname !== REPLACEMENT_MODULE_ROUTE) return false;
|
|
13577
|
+
if (options.requestToken && url.searchParams.get("token") !== options.requestToken) {
|
|
13578
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
13579
|
+
res.end("replacement module request token is invalid");
|
|
13580
|
+
return true;
|
|
13581
|
+
}
|
|
13402
13582
|
const targetPath = url.searchParams.get("path");
|
|
13403
13583
|
if (!targetPath) {
|
|
13404
13584
|
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
|
|
@@ -13411,17 +13591,42 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
13411
13591
|
res.end("replacement files must be .js, .jsx, .ts, or .tsx");
|
|
13412
13592
|
return true;
|
|
13413
13593
|
}
|
|
13594
|
+
if (!import_node_path10.default.isAbsolute(targetPath)) {
|
|
13595
|
+
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
|
|
13596
|
+
res.end("replacement file path must be absolute");
|
|
13597
|
+
return true;
|
|
13598
|
+
}
|
|
13599
|
+
let resolvedProjectRoot;
|
|
13600
|
+
if (options.projectRoot) {
|
|
13601
|
+
const lexicalProjectRoot = import_node_path10.default.resolve(options.projectRoot);
|
|
13602
|
+
resolvedProjectRoot = await import_promises5.default.realpath(options.projectRoot);
|
|
13603
|
+
const lexicalTarget = import_node_path10.default.relative(lexicalProjectRoot, targetPath);
|
|
13604
|
+
if (lexicalTarget.startsWith("..") || import_node_path10.default.isAbsolute(lexicalTarget)) {
|
|
13605
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
13606
|
+
res.end("replacement file must be inside the project root");
|
|
13607
|
+
return true;
|
|
13608
|
+
}
|
|
13609
|
+
}
|
|
13610
|
+
let resolvedTargetPath;
|
|
13414
13611
|
try {
|
|
13415
|
-
await import_promises5.default.
|
|
13612
|
+
resolvedTargetPath = await import_promises5.default.realpath(targetPath);
|
|
13416
13613
|
} catch (error) {
|
|
13417
13614
|
const message = error instanceof Error ? error.message : String(error);
|
|
13418
13615
|
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
13419
13616
|
res.end(`replacement file not found: ${message}`);
|
|
13420
13617
|
return true;
|
|
13421
13618
|
}
|
|
13619
|
+
if (resolvedProjectRoot) {
|
|
13620
|
+
const relativeTarget = import_node_path10.default.relative(resolvedProjectRoot, resolvedTargetPath);
|
|
13621
|
+
if (relativeTarget.startsWith("..") || import_node_path10.default.isAbsolute(relativeTarget)) {
|
|
13622
|
+
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
13623
|
+
res.end("replacement file must be inside the project root");
|
|
13624
|
+
return true;
|
|
13625
|
+
}
|
|
13626
|
+
}
|
|
13422
13627
|
try {
|
|
13423
13628
|
const result = await (0, import_esbuild.build)({
|
|
13424
|
-
entryPoints: [
|
|
13629
|
+
entryPoints: [resolvedTargetPath],
|
|
13425
13630
|
bundle: true,
|
|
13426
13631
|
write: false,
|
|
13427
13632
|
format: "esm",
|
|
@@ -13460,6 +13665,7 @@ var init_replacement_module_handler = __esm({
|
|
|
13460
13665
|
import_promises5 = __toESM(require("node:fs/promises"), 1);
|
|
13461
13666
|
import_node_path10 = __toESM(require("node:path"), 1);
|
|
13462
13667
|
import_esbuild = require("esbuild");
|
|
13668
|
+
init_backend_origin();
|
|
13463
13669
|
REPLACEMENT_MODULE_ROUTE = "/__sootsim-replacement-module";
|
|
13464
13670
|
REPLACEMENT_RUNTIME_PREFIX = "/__sootsim-replacement-runtime";
|
|
13465
13671
|
}
|
|
@@ -14726,7 +14932,7 @@ var init_bridge_host = __esm({
|
|
|
14726
14932
|
removeLockfile() {
|
|
14727
14933
|
if (!this.shouldWriteLockfile) return;
|
|
14728
14934
|
try {
|
|
14729
|
-
removeDaemonLockfile();
|
|
14935
|
+
removeDaemonLockfile({ pid: process.pid, startedAt: this.startedAt });
|
|
14730
14936
|
} catch {
|
|
14731
14937
|
}
|
|
14732
14938
|
}
|
|
@@ -15285,7 +15491,7 @@ var init_bridge_host = __esm({
|
|
|
15285
15491
|
}
|
|
15286
15492
|
if (this.shouldWriteLockfile) {
|
|
15287
15493
|
try {
|
|
15288
|
-
removeDaemonLockfile();
|
|
15494
|
+
removeDaemonLockfile({ pid: process.pid, startedAt: this.startedAt });
|
|
15289
15495
|
} catch {
|
|
15290
15496
|
}
|
|
15291
15497
|
}
|
|
@@ -16487,11 +16693,11 @@ async function evalInBridge(bridge, code, opts = {}) {
|
|
|
16487
16693
|
if (opts.acquireLock) payload.acquireLock = true;
|
|
16488
16694
|
return bridge.send(payload);
|
|
16489
16695
|
}
|
|
16490
|
-
async function callInBridge(bridge,
|
|
16491
|
-
return bridge.send({ type: "call", path:
|
|
16696
|
+
async function callInBridge(bridge, path18, ...args) {
|
|
16697
|
+
return bridge.send({ type: "call", path: path18, args });
|
|
16492
16698
|
}
|
|
16493
|
-
async function callInBridgeWrite(bridge,
|
|
16494
|
-
return bridge.send({ type: "call", path:
|
|
16699
|
+
async function callInBridgeWrite(bridge, path18, ...args) {
|
|
16700
|
+
return bridge.send({ type: "call", path: path18, args, acquireLock: true });
|
|
16495
16701
|
}
|
|
16496
16702
|
var import_node_fs9, import_node_path11, import_ws3, resolvedWorld, BridgeSimLockedError;
|
|
16497
16703
|
var init_ws_bridge = __esm({
|
|
@@ -16553,8 +16759,8 @@ function getDefaultPortForProtocol(protocol) {
|
|
|
16553
16759
|
return protocol === "https:" ? 443 : 80;
|
|
16554
16760
|
}
|
|
16555
16761
|
function isBaseServerUrl(url) {
|
|
16556
|
-
const
|
|
16557
|
-
return (
|
|
16762
|
+
const path18 = url.pathname || "/";
|
|
16763
|
+
return (path18 === "/" || path18 === "") && !url.search && !url.hash;
|
|
16558
16764
|
}
|
|
16559
16765
|
async function resolvePortViaServerScan(port) {
|
|
16560
16766
|
try {
|
|
@@ -16570,8 +16776,8 @@ async function resolvePortViaServerScan(port) {
|
|
|
16570
16776
|
if (!match) return null;
|
|
16571
16777
|
return {
|
|
16572
16778
|
// normalize exactly like the manifest-probe branch below — the scan
|
|
16573
|
-
// returns metro's
|
|
16574
|
-
// apps), but sootsim loads ONE self-contained bundle into the tenant
|
|
16779
|
+
// returns metro's manifest launchAsset url (lazy=true for code-split
|
|
16780
|
+
// one/vxrn apps), but sootsim loads ONE self-contained bundle into the tenant
|
|
16575
16781
|
// worker, so a deferred React.lazy chunk throws "Requiring unknown module
|
|
16576
16782
|
// <id>". normalizeNativeDevBundleUrl forces lazy=false + strips bytecode.
|
|
16577
16783
|
bundleUrl: normalizeNativeDevBundleUrl(match.bundleUrl),
|
|
@@ -16599,7 +16805,8 @@ async function probeBaseUrlBundle(baseUrl, port) {
|
|
|
16599
16805
|
if (manifestRes.ok) {
|
|
16600
16806
|
const manifest = await manifestRes.json();
|
|
16601
16807
|
const client = manifest?.extra?.expoClient || manifest?.extra || {};
|
|
16602
|
-
const
|
|
16808
|
+
const rawLaunchUrl = typeof manifest?.launchAsset?.url === "string" ? manifest.launchAsset.url : void 0;
|
|
16809
|
+
const launchUrl2 = rawLaunchUrl ? alignLoopbackBundleUrlWithProbe(rawLaunchUrl, normalizedBaseUrl) : void 0;
|
|
16603
16810
|
if (launchUrl2 || client.name) {
|
|
16604
16811
|
return {
|
|
16605
16812
|
bundleUrl: normalizeNativeDevBundleUrl(
|
|
@@ -16788,150 +16995,20 @@ function findExpoAppConfig(dir) {
|
|
|
16788
16995
|
function findSootSimAppConfig(dir) {
|
|
16789
16996
|
return firstNamedFile(dir, SOOTSIM_APP_CONFIG_NAMES);
|
|
16790
16997
|
}
|
|
16791
|
-
function
|
|
16998
|
+
function resolveAppProject(projectRoot) {
|
|
16999
|
+
const appDir = import_node_path12.default.resolve(projectRoot);
|
|
16792
17000
|
try {
|
|
16793
|
-
|
|
16794
|
-
if (!value || typeof value !== "object") return [];
|
|
16795
|
-
const workspaces = Reflect.get(value, "workspaces");
|
|
16796
|
-
if (Array.isArray(workspaces)) {
|
|
16797
|
-
return workspaces.filter((entry) => typeof entry === "string");
|
|
16798
|
-
}
|
|
16799
|
-
if (!workspaces || typeof workspaces !== "object") return [];
|
|
16800
|
-
const packages = Reflect.get(workspaces, "packages");
|
|
16801
|
-
return Array.isArray(packages) ? packages.filter((entry) => typeof entry === "string") : [];
|
|
17001
|
+
if (!import_node_fs10.default.statSync(appDir).isDirectory()) return null;
|
|
16802
17002
|
} catch {
|
|
16803
|
-
return
|
|
16804
|
-
}
|
|
16805
|
-
}
|
|
16806
|
-
function workspaceDirectories(rootDir) {
|
|
16807
|
-
const directories = /* @__PURE__ */ new Set();
|
|
16808
|
-
let expanded = 0;
|
|
16809
|
-
let complete = true;
|
|
16810
|
-
for (const pattern of readWorkspacePatterns(rootDir)) {
|
|
16811
|
-
if (expanded >= MAX_SCANNED_DIRECTORIES) {
|
|
16812
|
-
complete = false;
|
|
16813
|
-
break;
|
|
16814
|
-
}
|
|
16815
|
-
if (!pattern || import_node_path12.default.isAbsolute(pattern)) continue;
|
|
16816
|
-
const segments = pattern.split(/[\\/]+/).filter(Boolean);
|
|
16817
|
-
if (segments.length === 0 || segments.length > MAX_SCAN_DEPTH) continue;
|
|
16818
|
-
if (segments.some((segment) => segment === ".." || segment === "**")) continue;
|
|
16819
|
-
let current = [rootDir];
|
|
16820
|
-
for (const segment of segments) {
|
|
16821
|
-
const next = [];
|
|
16822
|
-
for (const parent of current) {
|
|
16823
|
-
if (expanded >= MAX_SCANNED_DIRECTORIES) {
|
|
16824
|
-
complete = false;
|
|
16825
|
-
break;
|
|
16826
|
-
}
|
|
16827
|
-
expanded++;
|
|
16828
|
-
if (segment === "*") {
|
|
16829
|
-
let entries;
|
|
16830
|
-
try {
|
|
16831
|
-
entries = import_node_fs10.default.readdirSync(parent, { withFileTypes: true });
|
|
16832
|
-
} catch {
|
|
16833
|
-
continue;
|
|
16834
|
-
}
|
|
16835
|
-
for (const entry of entries) {
|
|
16836
|
-
if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
|
|
16837
|
-
if (entry.name.startsWith(".") || SKIP_DIR_NAMES.has(entry.name)) continue;
|
|
16838
|
-
next.push(import_node_path12.default.join(parent, entry.name));
|
|
16839
|
-
}
|
|
16840
|
-
} else if (!segment.includes("*")) {
|
|
16841
|
-
const candidate = import_node_path12.default.join(parent, segment);
|
|
16842
|
-
try {
|
|
16843
|
-
const stat2 = import_node_fs10.default.lstatSync(candidate);
|
|
16844
|
-
if (stat2.isDirectory() && !stat2.isSymbolicLink()) next.push(candidate);
|
|
16845
|
-
} catch {
|
|
16846
|
-
}
|
|
16847
|
-
}
|
|
16848
|
-
}
|
|
16849
|
-
current = next;
|
|
16850
|
-
if (current.length > MAX_SCANNED_DIRECTORIES) {
|
|
16851
|
-
current.length = MAX_SCANNED_DIRECTORIES;
|
|
16852
|
-
complete = false;
|
|
16853
|
-
}
|
|
16854
|
-
}
|
|
16855
|
-
for (const directory of current) directories.add(directory);
|
|
16856
|
-
}
|
|
16857
|
-
return { directories: [...directories], complete };
|
|
16858
|
-
}
|
|
16859
|
-
function boundedConfigDirectories(rootDir) {
|
|
16860
|
-
const queue = [{ dir: rootDir, depth: 0 }];
|
|
16861
|
-
const matches = [];
|
|
16862
|
-
let visited = 0;
|
|
16863
|
-
let nextIndex = 0;
|
|
16864
|
-
let complete = true;
|
|
16865
|
-
while (nextIndex < queue.length && visited < MAX_SCANNED_DIRECTORIES) {
|
|
16866
|
-
const current = queue[nextIndex++];
|
|
16867
|
-
if (!current) break;
|
|
16868
|
-
visited++;
|
|
16869
|
-
if (current.depth > 0 && findExpoAppConfig(current.dir)) {
|
|
16870
|
-
matches.push(current.dir);
|
|
16871
|
-
if (matches.length > 1) return { directories: matches, complete: true };
|
|
16872
|
-
}
|
|
16873
|
-
if (current.depth >= MAX_SCAN_DEPTH) continue;
|
|
16874
|
-
let entries;
|
|
16875
|
-
try {
|
|
16876
|
-
entries = import_node_fs10.default.readdirSync(current.dir, { withFileTypes: true });
|
|
16877
|
-
} catch {
|
|
16878
|
-
continue;
|
|
16879
|
-
}
|
|
16880
|
-
for (const entry of entries) {
|
|
16881
|
-
if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
|
|
16882
|
-
if (entry.name.startsWith(".") || SKIP_DIR_NAMES.has(entry.name)) continue;
|
|
16883
|
-
if (queue.length >= MAX_SCANNED_DIRECTORIES) {
|
|
16884
|
-
complete = false;
|
|
16885
|
-
break;
|
|
16886
|
-
}
|
|
16887
|
-
queue.push({ dir: import_node_path12.default.join(current.dir, entry.name), depth: current.depth + 1 });
|
|
16888
|
-
}
|
|
16889
|
-
}
|
|
16890
|
-
return { directories: matches, complete: complete && nextIndex === queue.length };
|
|
16891
|
-
}
|
|
16892
|
-
function resolveAppProject(startDir, opts = {}) {
|
|
16893
|
-
const rootDir = import_node_path12.default.resolve(startDir);
|
|
16894
|
-
const rootConfigPath = findSootSimAppConfig(rootDir);
|
|
16895
|
-
if (findExpoAppConfig(rootDir) || opts.trustStart && import_node_fs10.default.existsSync(rootDir)) {
|
|
16896
|
-
let configPath = rootConfigPath;
|
|
16897
|
-
if (!configPath && opts.trustStart) {
|
|
16898
|
-
let parent = import_node_path12.default.dirname(rootDir);
|
|
16899
|
-
for (let depth = 0; depth < MAX_SCAN_DEPTH && parent !== import_node_path12.default.dirname(parent); depth++) {
|
|
16900
|
-
configPath = findSootSimAppConfig(parent);
|
|
16901
|
-
if (configPath) break;
|
|
16902
|
-
parent = import_node_path12.default.dirname(parent);
|
|
16903
|
-
}
|
|
16904
|
-
}
|
|
16905
|
-
return { appDir: rootDir, configPath };
|
|
16906
|
-
}
|
|
16907
|
-
const workspaceScan = workspaceDirectories(rootDir);
|
|
16908
|
-
const workspaceApps = workspaceScan.directories.filter(
|
|
16909
|
-
(directory) => findExpoAppConfig(directory)
|
|
16910
|
-
);
|
|
16911
|
-
if (workspaceApps.length > 1) return null;
|
|
16912
|
-
if (!workspaceScan.complete) return null;
|
|
16913
|
-
if (workspaceApps.length === 1) {
|
|
16914
|
-
const workspaceAppDir = workspaceApps[0];
|
|
16915
|
-
return {
|
|
16916
|
-
appDir: workspaceAppDir,
|
|
16917
|
-
configPath: rootConfigPath ?? findSootSimAppConfig(workspaceAppDir)
|
|
16918
|
-
};
|
|
17003
|
+
return null;
|
|
16919
17004
|
}
|
|
16920
|
-
const
|
|
16921
|
-
|
|
16922
|
-
|
|
16923
|
-
if (!fallbackScan.complete) return null;
|
|
16924
|
-
if (scannedApps.length === 1) {
|
|
16925
|
-
const scannedAppDir = scannedApps[0];
|
|
16926
|
-
return {
|
|
16927
|
-
appDir: scannedAppDir,
|
|
16928
|
-
configPath: rootConfigPath ?? findSootSimAppConfig(scannedAppDir)
|
|
16929
|
-
};
|
|
17005
|
+
const configPath = findSootSimAppConfig(appDir);
|
|
17006
|
+
if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs10.default.existsSync(import_node_path12.default.join(appDir, "package.json"))) {
|
|
17007
|
+
return null;
|
|
16930
17008
|
}
|
|
16931
|
-
|
|
16932
|
-
return null;
|
|
17009
|
+
return { appDir, configPath };
|
|
16933
17010
|
}
|
|
16934
|
-
var import_node_fs10, import_node_path12, EXPO_APP_CONFIG_NAMES, SOOTSIM_APP_CONFIG_NAMES
|
|
17011
|
+
var import_node_fs10, import_node_path12, EXPO_APP_CONFIG_NAMES, SOOTSIM_APP_CONFIG_NAMES;
|
|
16935
17012
|
var init_app_project = __esm({
|
|
16936
17013
|
"cli/app-project.ts"() {
|
|
16937
17014
|
"use strict";
|
|
@@ -16950,28 +17027,6 @@ var init_app_project = __esm({
|
|
|
16950
17027
|
"sootsim.config.mjs",
|
|
16951
17028
|
"sootsim.config.cjs"
|
|
16952
17029
|
];
|
|
16953
|
-
SKIP_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
16954
|
-
"node_modules",
|
|
16955
|
-
"artifacts",
|
|
16956
|
-
"dist",
|
|
16957
|
-
"build",
|
|
16958
|
-
"out",
|
|
16959
|
-
"coverage",
|
|
16960
|
-
"tmp",
|
|
16961
|
-
"public",
|
|
16962
|
-
"ios",
|
|
16963
|
-
"android",
|
|
16964
|
-
"macos",
|
|
16965
|
-
"windows",
|
|
16966
|
-
"__fixtures__",
|
|
16967
|
-
"__tests__",
|
|
16968
|
-
"fixtures",
|
|
16969
|
-
"fixture",
|
|
16970
|
-
"examples",
|
|
16971
|
-
"example"
|
|
16972
|
-
]);
|
|
16973
|
-
MAX_SCANNED_DIRECTORIES = 256;
|
|
16974
|
-
MAX_SCAN_DEPTH = 4;
|
|
16975
17030
|
}
|
|
16976
17031
|
});
|
|
16977
17032
|
|
|
@@ -17049,28 +17104,18 @@ function localOriginOf(value) {
|
|
|
17049
17104
|
}
|
|
17050
17105
|
return null;
|
|
17051
17106
|
}
|
|
17052
|
-
function hasPackageJson(dir) {
|
|
17053
|
-
try {
|
|
17054
|
-
return import_node_fs11.default.statSync(import_node_path14.default.join(dir, "package.json")).isFile();
|
|
17055
|
-
} catch {
|
|
17056
|
-
return false;
|
|
17057
|
-
}
|
|
17058
|
-
}
|
|
17059
17107
|
function discoverNativeLinkedAppFonts(opts) {
|
|
17060
17108
|
const metroOrigin = localOriginOf(opts.bundleUrl);
|
|
17061
17109
|
if (!metroOrigin) return [];
|
|
17062
|
-
const
|
|
17063
|
-
const startDir = explicit ? import_node_path14.default.resolve(explicit) : process.cwd();
|
|
17064
|
-
if (!explicit && !hasPackageJson(startDir)) return [];
|
|
17065
|
-
const project = resolveAppProject(startDir, { trustStart: opts.exactProjectDir });
|
|
17110
|
+
const project = resolveAppProject(opts.projectDir);
|
|
17066
17111
|
const selectedAppDir = project?.appDir ?? null;
|
|
17067
17112
|
if (!selectedAppDir) return [];
|
|
17068
17113
|
const platform = (opts.platform || process.env.CONTRAST_PLATFORM || "ios").toLowerCase();
|
|
17069
17114
|
let getConfig = null;
|
|
17070
|
-
if (
|
|
17115
|
+
if (project) {
|
|
17071
17116
|
try {
|
|
17072
17117
|
const modulePath = require3.resolve("@expo/config", {
|
|
17073
|
-
paths: [selectedAppDir
|
|
17118
|
+
paths: [selectedAppDir]
|
|
17074
17119
|
});
|
|
17075
17120
|
const mod = require3(modulePath);
|
|
17076
17121
|
if (typeof mod.getConfig === "function") {
|
|
@@ -17289,27 +17334,17 @@ function localOriginOf2(value) {
|
|
|
17289
17334
|
}
|
|
17290
17335
|
return null;
|
|
17291
17336
|
}
|
|
17292
|
-
function hasPackageJson2(dir) {
|
|
17293
|
-
try {
|
|
17294
|
-
return import_node_fs12.default.statSync(import_node_path15.default.join(dir, "package.json")).isFile();
|
|
17295
|
-
} catch {
|
|
17296
|
-
return false;
|
|
17297
|
-
}
|
|
17298
|
-
}
|
|
17299
17337
|
function discoverConfigPluginAppSplash(opts) {
|
|
17300
17338
|
const metroOrigin = localOriginOf2(opts.bundleUrl);
|
|
17301
17339
|
if (!metroOrigin) return null;
|
|
17302
|
-
const
|
|
17303
|
-
const startDir = explicit ? import_node_path15.default.resolve(explicit) : process.cwd();
|
|
17304
|
-
if (!explicit && !hasPackageJson2(startDir)) return null;
|
|
17305
|
-
const project = resolveAppProject(startDir, { trustStart: opts.exactProjectDir });
|
|
17340
|
+
const project = resolveAppProject(opts.projectDir);
|
|
17306
17341
|
const selectedAppDir = project?.appDir ?? null;
|
|
17307
17342
|
if (!selectedAppDir) return null;
|
|
17308
17343
|
const platform = (opts.platform || process.env.CONTRAST_PLATFORM || "ios").toLowerCase();
|
|
17309
17344
|
let getConfig = null;
|
|
17310
17345
|
try {
|
|
17311
17346
|
const modulePath = require4.resolve("@expo/config", {
|
|
17312
|
-
paths: [selectedAppDir
|
|
17347
|
+
paths: [selectedAppDir]
|
|
17313
17348
|
});
|
|
17314
17349
|
const mod = require4(modulePath);
|
|
17315
17350
|
if (typeof mod.getConfig === "function") {
|
|
@@ -17334,13 +17369,11 @@ function discoverConfigPluginAppSplash(opts) {
|
|
|
17334
17369
|
function encodeAppSplashWire(spec) {
|
|
17335
17370
|
return encodeURIComponent(JSON.stringify(spec));
|
|
17336
17371
|
}
|
|
17337
|
-
var
|
|
17372
|
+
var import_node_module3, import_config_plugin_splash, require4;
|
|
17338
17373
|
var init_app_splash = __esm({
|
|
17339
17374
|
"cli/app-splash.ts"() {
|
|
17340
17375
|
"use strict";
|
|
17341
|
-
import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
17342
17376
|
import_node_module3 = require("node:module");
|
|
17343
|
-
import_node_path15 = __toESM(require("node:path"), 1);
|
|
17344
17377
|
import_config_plugin_splash = require("sootsim-engine/engine/config-plugin-splash");
|
|
17345
17378
|
init_app_project();
|
|
17346
17379
|
require4 = (0, import_node_module3.createRequire)(__sootsim_import_meta_url);
|
|
@@ -18358,7 +18391,7 @@ function resolvePlaywright() {
|
|
|
18358
18391
|
try {
|
|
18359
18392
|
const modulePath = requireFromRoot.resolve(spec);
|
|
18360
18393
|
const packageJsonPath = requireFromRoot.resolve(`${spec}/package.json`);
|
|
18361
|
-
const parsed = JSON.parse((0,
|
|
18394
|
+
const parsed = JSON.parse((0, import_node_fs12.readFileSync)(packageJsonPath, "utf8"));
|
|
18362
18395
|
if (!isRecord3(parsed) || typeof parsed.version !== "string") continue;
|
|
18363
18396
|
const bin = parsed.bin;
|
|
18364
18397
|
let binPath = null;
|
|
@@ -18370,8 +18403,8 @@ function resolvePlaywright() {
|
|
|
18370
18403
|
binPath = typeof named === "string" ? named : typeof first === "string" ? first : null;
|
|
18371
18404
|
}
|
|
18372
18405
|
if (!binPath) continue;
|
|
18373
|
-
const cliPath = (0,
|
|
18374
|
-
if (!(0,
|
|
18406
|
+
const cliPath = (0, import_node_path15.join)((0, import_node_path15.dirname)(packageJsonPath), binPath);
|
|
18407
|
+
if (!(0, import_node_fs12.existsSync)(cliPath)) continue;
|
|
18375
18408
|
return {
|
|
18376
18409
|
spec,
|
|
18377
18410
|
modulePath,
|
|
@@ -18410,7 +18443,7 @@ function probeBrowser(resolved, env) {
|
|
|
18410
18443
|
return {
|
|
18411
18444
|
ok: true,
|
|
18412
18445
|
executablePath: parsed.executablePath,
|
|
18413
|
-
exists: parsed.exists && (0,
|
|
18446
|
+
exists: parsed.exists && (0, import_node_fs12.existsSync)(parsed.executablePath)
|
|
18414
18447
|
};
|
|
18415
18448
|
} catch (error) {
|
|
18416
18449
|
return {
|
|
@@ -18449,14 +18482,14 @@ ${detail}` : ""}`
|
|
|
18449
18482
|
}
|
|
18450
18483
|
return { ok: true, executablePath: after.executablePath, installed: true };
|
|
18451
18484
|
}
|
|
18452
|
-
var import_node_child_process5,
|
|
18485
|
+
var import_node_child_process5, import_node_fs12, import_node_module4, import_node_path15, PLAYWRIGHT_BROWSER_PROBE;
|
|
18453
18486
|
var init_playwright_provisioning = __esm({
|
|
18454
18487
|
"cli/drivers/playwright-provisioning.ts"() {
|
|
18455
18488
|
"use strict";
|
|
18456
18489
|
import_node_child_process5 = require("node:child_process");
|
|
18457
|
-
|
|
18490
|
+
import_node_fs12 = require("node:fs");
|
|
18458
18491
|
import_node_module4 = require("node:module");
|
|
18459
|
-
|
|
18492
|
+
import_node_path15 = require("node:path");
|
|
18460
18493
|
PLAYWRIGHT_BROWSER_PROBE = `
|
|
18461
18494
|
const { existsSync } = require('node:fs');
|
|
18462
18495
|
const modulePath = process.env.SOOTSIM_PW_MODULE;
|
|
@@ -19142,11 +19175,11 @@ function isChangelogEntry(value) {
|
|
|
19142
19175
|
)
|
|
19143
19176
|
);
|
|
19144
19177
|
}
|
|
19145
|
-
async function fetchRuntimeReleaseNotes(version,
|
|
19178
|
+
async function fetchRuntimeReleaseNotes(version, fetchImpl = fetch) {
|
|
19146
19179
|
try {
|
|
19147
19180
|
const url = new URL(SOOTSIM_CHANGELOG_API_URL);
|
|
19148
19181
|
url.searchParams.set("version", version);
|
|
19149
|
-
const response = await
|
|
19182
|
+
const response = await fetchImpl(url, {
|
|
19150
19183
|
headers: { accept: "application/json" },
|
|
19151
19184
|
signal: AbortSignal.timeout(5e3)
|
|
19152
19185
|
});
|
|
@@ -19551,9 +19584,12 @@ function shouldOpenAsDeepLink(target) {
|
|
|
19551
19584
|
return !/^https?:\/\//i.test(trimmed);
|
|
19552
19585
|
}
|
|
19553
19586
|
async function ensureBridgeForOpen(preferredPort, explicitPort = false) {
|
|
19554
|
-
if (await canConnectToBridge(preferredPort, 250)) return preferredPort;
|
|
19555
19587
|
const lock = readDaemonLockfile();
|
|
19556
19588
|
assertExplicitBridgeLock(preferredPort, explicitPort, lock);
|
|
19589
|
+
const preferredWorld = worldForBridgePort(preferredPort);
|
|
19590
|
+
if ((explicitPort || preferredWorld !== null) && await canConnectToBridge(preferredPort, 250)) {
|
|
19591
|
+
return preferredPort;
|
|
19592
|
+
}
|
|
19557
19593
|
if (lock && isDaemonLockfileFresh(lock) && await canConnectToBridge(lock.bridgePort, 500)) {
|
|
19558
19594
|
return lock.bridgePort;
|
|
19559
19595
|
}
|
|
@@ -19579,12 +19615,6 @@ async function ensureBridgeForOpen(preferredPort, explicitPort = false) {
|
|
|
19579
19615
|
);
|
|
19580
19616
|
return nextLock.bridgePort;
|
|
19581
19617
|
}
|
|
19582
|
-
if (await canConnectToBridge(preferredPort, 250)) {
|
|
19583
|
-
console.error(
|
|
19584
|
-
` started local bridge on port ${preferredPort}; run \`sootsim setup\` to install the background daemon`
|
|
19585
|
-
);
|
|
19586
|
-
return preferredPort;
|
|
19587
|
-
}
|
|
19588
19618
|
if (childExit) {
|
|
19589
19619
|
throw new Error(`rnx bridge exited before becoming ready (exit ${childExit})`);
|
|
19590
19620
|
}
|
|
@@ -19604,14 +19634,14 @@ function assertExplicitBridgeLock(preferredPort, explicitPort, lock) {
|
|
|
19604
19634
|
}
|
|
19605
19635
|
async function ensureRuntimeForOpen() {
|
|
19606
19636
|
const active = readActiveRuntime();
|
|
19607
|
-
if (active &&
|
|
19637
|
+
if (active && import_node_fs13.default.existsSync(runtimeDir(active))) return;
|
|
19608
19638
|
console.error(" installing rnx engine runtime...");
|
|
19609
19639
|
const { runRuntime: runRuntime2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
|
|
19610
19640
|
await runRuntime2(["install"], {});
|
|
19611
19641
|
}
|
|
19612
19642
|
function spawnSootsim(args) {
|
|
19613
19643
|
const entry = process.argv[1];
|
|
19614
|
-
if (entry &&
|
|
19644
|
+
if (entry && import_node_fs13.default.existsSync(entry)) {
|
|
19615
19645
|
return (0, import_node_child_process6.spawn)(process.execPath, [entry, ...args], {
|
|
19616
19646
|
detached: true,
|
|
19617
19647
|
stdio: "ignore",
|
|
@@ -19758,10 +19788,10 @@ async function buildResolvedBundleOpenUrl(target, baseUrl, opts = {}) {
|
|
|
19758
19788
|
}
|
|
19759
19789
|
function normalizeReplacementPath(filePath) {
|
|
19760
19790
|
if (filePath.startsWith("~/")) {
|
|
19761
|
-
return
|
|
19791
|
+
return import_node_path16.default.join(import_node_os3.default.homedir(), filePath.slice(2));
|
|
19762
19792
|
}
|
|
19763
|
-
if (
|
|
19764
|
-
return
|
|
19793
|
+
if (import_node_path16.default.isAbsolute(filePath)) return filePath;
|
|
19794
|
+
return import_node_path16.default.resolve(process.cwd(), filePath);
|
|
19765
19795
|
}
|
|
19766
19796
|
function parseOpenRuntimeConfig(args) {
|
|
19767
19797
|
const modules = {};
|
|
@@ -19780,7 +19810,7 @@ function parseOpenRuntimeConfig(args) {
|
|
|
19780
19810
|
}
|
|
19781
19811
|
const moduleName = raw.slice(0, eqIndex).trim();
|
|
19782
19812
|
const filePath = normalizeReplacementPath(raw.slice(eqIndex + 1).trim());
|
|
19783
|
-
if (!
|
|
19813
|
+
if (!import_node_fs13.default.existsSync(filePath)) {
|
|
19784
19814
|
console.error(` rnx open: replacement file not found: ${filePath}`);
|
|
19785
19815
|
process.exit(1);
|
|
19786
19816
|
}
|
|
@@ -19806,16 +19836,12 @@ function parseOpenRuntimeConfig(args) {
|
|
|
19806
19836
|
return config.modules || config.network ? config : void 0;
|
|
19807
19837
|
}
|
|
19808
19838
|
async function resolveOpenAppProject(resolvedBundle) {
|
|
19809
|
-
if (resolvedBundle)
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
return resolveAppProject(advertisedRoot, { trustStart: true });
|
|
19813
|
-
}
|
|
19814
|
-
}
|
|
19815
|
-
return resolveAppProject(process.env.CONTRAST_REPO_DIR || process.cwd());
|
|
19839
|
+
if (!resolvedBundle) return null;
|
|
19840
|
+
const advertisedRoot = await resolveMetroProjectRoot(resolvedBundle.bundleUrl);
|
|
19841
|
+
return advertisedRoot ? resolveAppProject(advertisedRoot) : null;
|
|
19816
19842
|
}
|
|
19817
19843
|
async function ensureConfiguredRuntime(version) {
|
|
19818
|
-
if (
|
|
19844
|
+
if (import_node_fs13.default.existsSync(import_node_path16.default.join(runtimeDir(version), "index.html"))) return;
|
|
19819
19845
|
console.error(` installing configured engine runtime ${version}...`);
|
|
19820
19846
|
const result = await sootsimRuntime.install({
|
|
19821
19847
|
version,
|
|
@@ -19847,12 +19873,10 @@ async function stampAppFonts(urlStr, project) {
|
|
|
19847
19873
|
try {
|
|
19848
19874
|
const url = new URL(urlStr);
|
|
19849
19875
|
const bundleUrl = url.searchParams.get("bundle") || "";
|
|
19850
|
-
if (!bundleUrl) return urlStr;
|
|
19851
|
-
const repoDir = project?.appDir ?? await resolveMetroProjectRoot(bundleUrl) ?? void 0;
|
|
19876
|
+
if (!bundleUrl || !project) return urlStr;
|
|
19852
19877
|
const specs = discoverNativeLinkedAppFonts({
|
|
19853
19878
|
bundleUrl,
|
|
19854
|
-
|
|
19855
|
-
exactProjectDir: !!project || !!repoDir
|
|
19879
|
+
projectDir: project.appDir
|
|
19856
19880
|
});
|
|
19857
19881
|
if (specs.length === 0) return urlStr;
|
|
19858
19882
|
const reachable = await filterReachableAppFonts(specs);
|
|
@@ -19914,12 +19938,10 @@ async function stampAppSplash(urlStr, project) {
|
|
|
19914
19938
|
try {
|
|
19915
19939
|
const url = new URL(urlStr);
|
|
19916
19940
|
const bundleUrl = url.searchParams.get("bundle") || "";
|
|
19917
|
-
if (!bundleUrl) return urlStr;
|
|
19918
|
-
const repoDir = project?.appDir ?? await resolveMetroProjectRoot(bundleUrl) ?? void 0;
|
|
19941
|
+
if (!bundleUrl || !project) return urlStr;
|
|
19919
19942
|
const spec = discoverConfigPluginAppSplash({
|
|
19920
19943
|
bundleUrl,
|
|
19921
|
-
|
|
19922
|
-
exactProjectDir: !!project || !!repoDir
|
|
19944
|
+
projectDir: project.appDir
|
|
19923
19945
|
});
|
|
19924
19946
|
if (!spec) return urlStr;
|
|
19925
19947
|
if (spec.imageUrl) {
|
|
@@ -20179,7 +20201,7 @@ function playwrightHostPidForSim(sim) {
|
|
|
20179
20201
|
function signalDriverLaunchConnected(result) {
|
|
20180
20202
|
if (!result.connectAckFile) return false;
|
|
20181
20203
|
try {
|
|
20182
|
-
|
|
20204
|
+
import_node_fs13.default.writeFileSync(
|
|
20183
20205
|
result.connectAckFile,
|
|
20184
20206
|
`${JSON.stringify({ connectedAt: Date.now(), pid: result.pid ?? null })}
|
|
20185
20207
|
`,
|
|
@@ -20193,19 +20215,19 @@ function signalDriverLaunchConnected(result) {
|
|
|
20193
20215
|
function printDriverDiagnosticLogTail(result) {
|
|
20194
20216
|
if (!result.diagnosticLogPath) return;
|
|
20195
20217
|
try {
|
|
20196
|
-
const detail =
|
|
20218
|
+
const detail = import_node_fs13.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
|
|
20197
20219
|
if (!detail) {
|
|
20198
|
-
console.error(` ${
|
|
20220
|
+
console.error(` ${import_node_path16.default.basename(result.diagnosticLogPath)} was empty`);
|
|
20199
20221
|
return;
|
|
20200
20222
|
}
|
|
20201
20223
|
const shown = detail.length > 4e3 ? `\u2026
|
|
20202
20224
|
${detail.slice(-4e3)}` : detail;
|
|
20203
|
-
console.error(` ${
|
|
20225
|
+
console.error(` ${import_node_path16.default.basename(result.diagnosticLogPath)}:`);
|
|
20204
20226
|
console.error(shown);
|
|
20205
20227
|
} catch (err) {
|
|
20206
20228
|
const message = err instanceof Error ? err.message : String(err);
|
|
20207
20229
|
console.error(
|
|
20208
|
-
` failed to read ${
|
|
20230
|
+
` failed to read ${import_node_path16.default.basename(result.diagnosticLogPath)}: ${message}`
|
|
20209
20231
|
);
|
|
20210
20232
|
}
|
|
20211
20233
|
}
|
|
@@ -20687,7 +20709,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
20687
20709
|
);
|
|
20688
20710
|
printOpenedSim(shellUrl, { ...targetSim, url: shellUrl }, "current sim");
|
|
20689
20711
|
await maybeDescribeAfterOpen(parsed.wsPort, targetSim.id, args);
|
|
20690
|
-
return;
|
|
20712
|
+
return parsed.wsPort;
|
|
20691
20713
|
}
|
|
20692
20714
|
} finally {
|
|
20693
20715
|
bridge.close();
|
|
@@ -20760,6 +20782,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
20760
20782
|
signalDriverLaunchConnected(result);
|
|
20761
20783
|
printOpenedSim(openUrl2, match, `${driver.name} driver`);
|
|
20762
20784
|
await maybeDescribeAfterOpen(parsed.wsPort, match.id, args);
|
|
20785
|
+
return parsed.wsPort;
|
|
20763
20786
|
}
|
|
20764
20787
|
async function runUseLikeCommand(args, opts = {}) {
|
|
20765
20788
|
const parsed = parseBridgeCliArgs(args, {
|
|
@@ -21022,14 +21045,14 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
21022
21045
|
bridge.close();
|
|
21023
21046
|
}
|
|
21024
21047
|
}
|
|
21025
|
-
var import_node_child_process6,
|
|
21048
|
+
var import_node_child_process6, import_node_fs13, import_node_os3, import_node_path16, import_settings, import_ws5, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEEP_LINK_SCHEME_RE;
|
|
21026
21049
|
var init_control = __esm({
|
|
21027
21050
|
"cli/commands/control.ts"() {
|
|
21028
21051
|
"use strict";
|
|
21029
21052
|
import_node_child_process6 = require("node:child_process");
|
|
21030
|
-
|
|
21053
|
+
import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
21031
21054
|
import_node_os3 = __toESM(require("node:os"), 1);
|
|
21032
|
-
|
|
21055
|
+
import_node_path16 = __toESM(require("node:path"), 1);
|
|
21033
21056
|
import_settings = require("sootsim-engine/settings");
|
|
21034
21057
|
import_ws5 = require("ws");
|
|
21035
21058
|
init_dev_server_scanner();
|
|
@@ -21811,14 +21834,14 @@ process.stdin.on('end', async () => {
|
|
|
21811
21834
|
function getBaseDir() {
|
|
21812
21835
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
21813
21836
|
if (explicit?.trim()) {
|
|
21814
|
-
return (0,
|
|
21837
|
+
return (0, import_node_path17.dirname)((0, import_node_path17.resolve)(explicit));
|
|
21815
21838
|
}
|
|
21816
21839
|
return electronUserDataDir();
|
|
21817
21840
|
}
|
|
21818
21841
|
function getSharedDesktopAuthFilePath() {
|
|
21819
21842
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
21820
|
-
if (explicit?.trim()) return (0,
|
|
21821
|
-
return (0,
|
|
21843
|
+
if (explicit?.trim()) return (0, import_node_path17.resolve)(explicit);
|
|
21844
|
+
return (0, import_node_path17.join)(getBaseDir(), "desktop-auth.json");
|
|
21822
21845
|
}
|
|
21823
21846
|
function normalizeUser(input) {
|
|
21824
21847
|
if (!input || typeof input !== "object") return null;
|
|
@@ -21865,26 +21888,26 @@ function normalizeSession(input) {
|
|
|
21865
21888
|
}
|
|
21866
21889
|
function readSharedDesktopAuthSession() {
|
|
21867
21890
|
const filepath = getSharedDesktopAuthFilePath();
|
|
21868
|
-
if (!(0,
|
|
21891
|
+
if (!(0, import_node_fs14.existsSync)(filepath)) return null;
|
|
21869
21892
|
try {
|
|
21870
|
-
const parsed = JSON.parse((0,
|
|
21893
|
+
const parsed = JSON.parse((0, import_node_fs14.readFileSync)(filepath, "utf8"));
|
|
21871
21894
|
const normalized = normalizeSession(parsed);
|
|
21872
21895
|
if (!normalized) {
|
|
21873
|
-
(0,
|
|
21896
|
+
(0, import_node_fs14.rmSync)(filepath, { force: true });
|
|
21874
21897
|
return null;
|
|
21875
21898
|
}
|
|
21876
21899
|
return normalized;
|
|
21877
21900
|
} catch {
|
|
21878
|
-
(0,
|
|
21901
|
+
(0, import_node_fs14.rmSync)(filepath, { force: true });
|
|
21879
21902
|
return null;
|
|
21880
21903
|
}
|
|
21881
21904
|
}
|
|
21882
|
-
var
|
|
21905
|
+
var import_node_fs14, import_node_path17, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
|
|
21883
21906
|
var init_shared_session = __esm({
|
|
21884
21907
|
"src/auth/shared-session.ts"() {
|
|
21885
21908
|
"use strict";
|
|
21886
|
-
|
|
21887
|
-
|
|
21909
|
+
import_node_fs14 = require("node:fs");
|
|
21910
|
+
import_node_path17 = require("node:path");
|
|
21888
21911
|
init_home_paths();
|
|
21889
21912
|
SESSION_VERSION = 1;
|
|
21890
21913
|
SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
@@ -21967,33 +21990,13 @@ var init_run_registry = __esm({
|
|
|
21967
21990
|
}
|
|
21968
21991
|
});
|
|
21969
21992
|
|
|
21970
|
-
// cli/telemetry.ts
|
|
21971
|
-
var init_telemetry = __esm({
|
|
21972
|
-
"cli/telemetry.ts"() {
|
|
21973
|
-
"use strict";
|
|
21974
|
-
init_agent_identity();
|
|
21975
|
-
init_shared_session();
|
|
21976
|
-
init_home_paths();
|
|
21977
|
-
}
|
|
21978
|
-
});
|
|
21979
|
-
|
|
21980
21993
|
// cli/commands/upload.ts
|
|
21981
21994
|
async function resolveDefaultUploadOrigin(explicitOrigin) {
|
|
21982
21995
|
if (explicitOrigin) return explicitOrigin;
|
|
21983
21996
|
if (process.env.SOOTSIM_UPLOAD_ORIGIN) return process.env.SOOTSIM_UPLOAD_ORIGIN;
|
|
21984
|
-
try {
|
|
21985
|
-
const res = await fetch(`${LOCAL_DEFAULT_ORIGIN}/api/preview/upload/init`, {
|
|
21986
|
-
method: "OPTIONS",
|
|
21987
|
-
signal: AbortSignal.timeout(LOCAL_UPLOAD_PROBE_TIMEOUT_MS)
|
|
21988
|
-
});
|
|
21989
|
-
if (res.ok || res.status === 204 || res.status === 405) {
|
|
21990
|
-
return LOCAL_DEFAULT_ORIGIN;
|
|
21991
|
-
}
|
|
21992
|
-
} catch {
|
|
21993
|
-
}
|
|
21994
21997
|
return REMOTE_DEFAULT_ORIGIN;
|
|
21995
21998
|
}
|
|
21996
|
-
var import_compress, import_compress_node, import_presigned_upload, import_trace, REMOTE_DEFAULT_ORIGIN, REMOTE_DEFAULT_PUBLIC_PREVIEW_ORIGIN
|
|
21999
|
+
var import_compress, import_compress_node, import_presigned_upload, import_trace, REMOTE_DEFAULT_ORIGIN, REMOTE_DEFAULT_PUBLIC_PREVIEW_ORIGIN;
|
|
21997
22000
|
var init_upload = __esm({
|
|
21998
22001
|
"cli/commands/upload.ts"() {
|
|
21999
22002
|
"use strict";
|
|
@@ -22001,19 +22004,15 @@ var init_upload = __esm({
|
|
|
22001
22004
|
import_compress_node = require("sootsim-engine/preview/compress-node");
|
|
22002
22005
|
import_presigned_upload = require("sootsim-engine/preview/presigned-upload");
|
|
22003
22006
|
import_trace = require("sootsim-engine/preview/trace");
|
|
22004
|
-
init_shared_session();
|
|
22005
22007
|
init_public_brand();
|
|
22006
22008
|
init_app_fonts();
|
|
22007
22009
|
init_app_splash();
|
|
22008
22010
|
init_auth();
|
|
22009
22011
|
init_open_url2();
|
|
22010
22012
|
init_run_registry();
|
|
22011
|
-
init_telemetry();
|
|
22012
22013
|
init_ws_bridge();
|
|
22013
22014
|
REMOTE_DEFAULT_ORIGIN = process.env.SOOTSIM_UPLOAD_ORIGIN || "https://contrast.dev";
|
|
22014
22015
|
REMOTE_DEFAULT_PUBLIC_PREVIEW_ORIGIN = process.env.SOOTSIM_PREVIEW_ORIGIN || rnxPublicBrand.origin;
|
|
22015
|
-
LOCAL_DEFAULT_ORIGIN = "https://contrast.localhost:3000";
|
|
22016
|
-
LOCAL_UPLOAD_PROBE_TIMEOUT_MS = 2e3;
|
|
22017
22016
|
}
|
|
22018
22017
|
});
|
|
22019
22018
|
|
|
@@ -22147,16 +22146,16 @@ function resolveFlowScreenshotPath(screenshotDir, name2) {
|
|
|
22147
22146
|
}
|
|
22148
22147
|
function resolveProjectRelativeFlowBase(flowDir) {
|
|
22149
22148
|
if (!flowDir) return process.cwd();
|
|
22150
|
-
return
|
|
22149
|
+
return path16.basename(flowDir) === ".maestro" ? path16.dirname(flowDir) : flowDir;
|
|
22151
22150
|
}
|
|
22152
22151
|
function resolveFlowScreenshotPathWithMode(screenshotDir, name2, opts) {
|
|
22153
22152
|
const normalizedName = name2.endsWith(".png") ? name2 : `${name2}.png`;
|
|
22154
|
-
if (
|
|
22153
|
+
if (path16.isAbsolute(normalizedName)) return normalizedName;
|
|
22155
22154
|
if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
|
|
22156
22155
|
const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
|
|
22157
|
-
return
|
|
22156
|
+
return path16.resolve(baseDir, normalizedName);
|
|
22158
22157
|
}
|
|
22159
|
-
return
|
|
22158
|
+
return path16.join(screenshotDir, normalizedName);
|
|
22160
22159
|
}
|
|
22161
22160
|
function normalizeFlowScreenshotSpec(step) {
|
|
22162
22161
|
if (typeof step === "string") {
|
|
@@ -22213,12 +22212,12 @@ function parseFlowSteps(content) {
|
|
|
22213
22212
|
const parsed = import_yaml.default.parse(candidate);
|
|
22214
22213
|
return Array.isArray(parsed) ? parsed : [];
|
|
22215
22214
|
}
|
|
22216
|
-
var
|
|
22215
|
+
var fs16, path16, import_settings3, import_yaml, DEFAULT_TIMEOUT, FLOW_TIMEOUT_SCALE, scaledTimeout, SCREEN_W, SCREEN_H, SootSimBridgeFlowRunner;
|
|
22217
22216
|
var init_bridge_flow_runner = __esm({
|
|
22218
22217
|
"cli/bridge-flow-runner.ts"() {
|
|
22219
22218
|
"use strict";
|
|
22220
|
-
|
|
22221
|
-
|
|
22219
|
+
fs16 = __toESM(require("fs"), 1);
|
|
22220
|
+
path16 = __toESM(require("path"), 1);
|
|
22222
22221
|
import_settings3 = require("sootsim-engine/settings");
|
|
22223
22222
|
import_yaml = __toESM(require("yaml"), 1);
|
|
22224
22223
|
init_frame_compose();
|
|
@@ -22515,14 +22514,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
22515
22514
|
if (chunks.length === 0) {
|
|
22516
22515
|
throw new Error("recording requested but no video buffer was produced");
|
|
22517
22516
|
}
|
|
22518
|
-
|
|
22517
|
+
fs16.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
|
|
22519
22518
|
const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
|
|
22520
22519
|
const extension = videoMime.includes("mp4") ? "mp4" : "webm";
|
|
22521
|
-
const outputPath =
|
|
22520
|
+
const outputPath = path16.join(
|
|
22522
22521
|
this.opts.recordingOutputDir,
|
|
22523
22522
|
`sootsim-${Date.now()}.${extension}`
|
|
22524
22523
|
);
|
|
22525
|
-
|
|
22524
|
+
fs16.writeFileSync(outputPath, Buffer.concat(chunks));
|
|
22526
22525
|
return outputPath;
|
|
22527
22526
|
}
|
|
22528
22527
|
async waitForRecordingTail(opts) {
|
|
@@ -23025,7 +23024,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
23025
23024
|
flowDir: this.opts.flowDir
|
|
23026
23025
|
}
|
|
23027
23026
|
);
|
|
23028
|
-
|
|
23027
|
+
fs16.mkdirSync(path16.dirname(outputPath), { recursive: true });
|
|
23029
23028
|
const layers = spec.layers ?? this.opts.screenshotLayers;
|
|
23030
23029
|
const screenshotRequest = {
|
|
23031
23030
|
type: "screenshot",
|
|
@@ -23041,11 +23040,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
23041
23040
|
throw new Error("could not read current device model for framed screenshot");
|
|
23042
23041
|
}
|
|
23043
23042
|
const framed = await composeFramedScreenshot(rawBuffer, model);
|
|
23044
|
-
|
|
23043
|
+
fs16.writeFileSync(outputPath, framed);
|
|
23045
23044
|
console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
|
|
23046
23045
|
return outputPath;
|
|
23047
23046
|
}
|
|
23048
|
-
|
|
23047
|
+
fs16.writeFileSync(outputPath, rawBuffer);
|
|
23049
23048
|
console.log(`[flow] screenshot: ${outputPath}`);
|
|
23050
23049
|
return outputPath;
|
|
23051
23050
|
}
|
|
@@ -23061,22 +23060,22 @@ var init_bridge_flow_runner = __esm({
|
|
|
23061
23060
|
return model;
|
|
23062
23061
|
}
|
|
23063
23062
|
async captureScreenshot(outputPath) {
|
|
23064
|
-
|
|
23063
|
+
fs16.mkdirSync(path16.dirname(outputPath), { recursive: true });
|
|
23065
23064
|
const dataUrl = await this.bridge.send({
|
|
23066
23065
|
type: "screenshot",
|
|
23067
23066
|
simId: this.opts.simId
|
|
23068
23067
|
});
|
|
23069
23068
|
const base64 = dataUrl.replace(/^data:image\/png;base64,/, "");
|
|
23070
|
-
|
|
23069
|
+
fs16.writeFileSync(outputPath, Buffer.from(base64, "base64"));
|
|
23071
23070
|
}
|
|
23072
23071
|
// writes a per-failure debug bundle: screenshot + structured describe
|
|
23073
23072
|
// + a11y tree + console errors/warnings + failed network requests +
|
|
23074
23073
|
// shell state, all under one directory so post-mortem is one grep away.
|
|
23075
23074
|
async captureFailureBundle(outputDir, context) {
|
|
23076
|
-
|
|
23075
|
+
fs16.mkdirSync(outputDir, { recursive: true });
|
|
23077
23076
|
const write = (name2, content) => {
|
|
23078
23077
|
try {
|
|
23079
|
-
|
|
23078
|
+
fs16.writeFileSync(path16.join(outputDir, name2), content);
|
|
23080
23079
|
} catch {
|
|
23081
23080
|
}
|
|
23082
23081
|
};
|
|
@@ -23595,8 +23594,8 @@ var init_bridge_flow_runner = __esm({
|
|
|
23595
23594
|
runScript(target) {
|
|
23596
23595
|
const spec = typeof target === "string" ? { file: target } : target;
|
|
23597
23596
|
if (!spec.file) throw new Error("runScript requires a file");
|
|
23598
|
-
const scriptPath =
|
|
23599
|
-
const source =
|
|
23597
|
+
const scriptPath = path16.resolve(this.opts.flowDir, spec.file);
|
|
23598
|
+
const source = fs16.readFileSync(scriptPath, "utf8");
|
|
23600
23599
|
this.js.evaluate(source, { env: spec.env });
|
|
23601
23600
|
console.log(`[flow] runScript: ${spec.file} done`);
|
|
23602
23601
|
}
|
|
@@ -23890,10 +23889,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
23890
23889
|
for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
|
|
23891
23890
|
}
|
|
23892
23891
|
if (file) {
|
|
23893
|
-
const flowPath =
|
|
23894
|
-
const flowContent =
|
|
23892
|
+
const flowPath = path16.resolve(this.opts.flowDir, file);
|
|
23893
|
+
const flowContent = fs16.readFileSync(flowPath, "utf8");
|
|
23895
23894
|
const previousDir = this.opts.flowDir;
|
|
23896
|
-
this.opts.flowDir =
|
|
23895
|
+
this.opts.flowDir = path16.dirname(flowPath);
|
|
23897
23896
|
try {
|
|
23898
23897
|
await this.runFlow(parseFlowSteps(flowContent));
|
|
23899
23898
|
} finally {
|
|
@@ -24048,8 +24047,8 @@ __export(registry_exports, {
|
|
|
24048
24047
|
skillRegistry: () => skillRegistry
|
|
24049
24048
|
});
|
|
24050
24049
|
module.exports = __toCommonJS(registry_exports);
|
|
24051
|
-
var
|
|
24052
|
-
var
|
|
24050
|
+
var fs17 = __toESM(require("fs"), 1);
|
|
24051
|
+
var path17 = __toESM(require("path"), 1);
|
|
24053
24052
|
|
|
24054
24053
|
// src/skills/builtin/a11y-review.ts
|
|
24055
24054
|
init_reap_browser();
|
|
@@ -24068,8 +24067,8 @@ var skill = {
|
|
|
24068
24067
|
},
|
|
24069
24068
|
async execute(params, context) {
|
|
24070
24069
|
const { chromium } = await import("playwright");
|
|
24071
|
-
const
|
|
24072
|
-
const
|
|
24070
|
+
const path18 = await import("path");
|
|
24071
|
+
const fs18 = await import("fs");
|
|
24073
24072
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
24074
24073
|
headless: true
|
|
24075
24074
|
});
|
|
@@ -24124,9 +24123,9 @@ var skill = {
|
|
|
24124
24123
|
warnings: issues.filter((i) => i.severity === "warning").length,
|
|
24125
24124
|
tree: typeof tree === "string" ? tree : JSON.stringify(tree)
|
|
24126
24125
|
};
|
|
24127
|
-
const reportPath =
|
|
24128
|
-
|
|
24129
|
-
|
|
24126
|
+
const reportPath = path18.join(context.outputDir, "a11y-report.json");
|
|
24127
|
+
fs18.mkdirSync(path18.dirname(reportPath), { recursive: true });
|
|
24128
|
+
fs18.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
24130
24129
|
return {
|
|
24131
24130
|
success: issues.filter((i) => i.severity === "error").length === 0,
|
|
24132
24131
|
message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
|
|
@@ -24159,14 +24158,14 @@ var skill2 = {
|
|
|
24159
24158
|
}
|
|
24160
24159
|
},
|
|
24161
24160
|
async execute(params, context) {
|
|
24162
|
-
const
|
|
24163
|
-
const
|
|
24161
|
+
const fs18 = await import("node:fs");
|
|
24162
|
+
const path18 = await import("node:path");
|
|
24164
24163
|
const { COMPAT_RESULT_CAVEAT: COMPAT_RESULT_CAVEAT2, formatPackageStatus: formatPackageStatus2, formatScanCounts: formatScanCounts2, scanDeps: scanDeps2 } = await Promise.resolve().then(() => (init_web(), web_exports));
|
|
24165
|
-
const packagePath =
|
|
24166
|
-
if (!
|
|
24164
|
+
const packagePath = path18.join(context.projectDir, "package.json");
|
|
24165
|
+
if (!fs18.existsSync(packagePath)) {
|
|
24167
24166
|
return { success: false, message: "No package.json found" };
|
|
24168
24167
|
}
|
|
24169
|
-
const parsed = JSON.parse(
|
|
24168
|
+
const parsed = JSON.parse(fs18.readFileSync(packagePath, "utf8"));
|
|
24170
24169
|
if (!parsed || typeof parsed !== "object") {
|
|
24171
24170
|
return { success: false, message: "package.json is not an object" };
|
|
24172
24171
|
}
|
|
@@ -24178,9 +24177,9 @@ var skill2 = {
|
|
|
24178
24177
|
}) : scanDeps2(parsed);
|
|
24179
24178
|
const packageResult = params.packageName ? scan.packages[0] : void 0;
|
|
24180
24179
|
const message = packageResult ? `${params.packageName}: ${formatPackageStatus2(packageResult)}. ${COMPAT_RESULT_CAVEAT2}` : `${formatScanCounts2(scan)}. ${COMPAT_RESULT_CAVEAT2}`;
|
|
24181
|
-
const reportPath =
|
|
24182
|
-
|
|
24183
|
-
|
|
24180
|
+
const reportPath = path18.join(context.outputDir, "compat-report.json");
|
|
24181
|
+
fs18.mkdirSync(path18.dirname(reportPath), { recursive: true });
|
|
24182
|
+
fs18.writeFileSync(reportPath, `${JSON.stringify(scan, null, 2)}
|
|
24184
24183
|
`);
|
|
24185
24184
|
return {
|
|
24186
24185
|
success: true,
|
|
@@ -24224,8 +24223,8 @@ var skill3 = {
|
|
|
24224
24223
|
record: { type: "boolean", description: "Record video of the flow" }
|
|
24225
24224
|
},
|
|
24226
24225
|
async execute(params, context) {
|
|
24227
|
-
const
|
|
24228
|
-
const
|
|
24226
|
+
const fs18 = await import("fs");
|
|
24227
|
+
const path18 = await import("path");
|
|
24229
24228
|
const yaml2 = await import("yaml");
|
|
24230
24229
|
const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
|
|
24231
24230
|
const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
|
|
@@ -24235,7 +24234,7 @@ var skill3 = {
|
|
|
24235
24234
|
const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
|
|
24236
24235
|
host.start({ silent: true });
|
|
24237
24236
|
try {
|
|
24238
|
-
const flowContent =
|
|
24237
|
+
const flowContent = fs18.readFileSync(params.flowPath, "utf8");
|
|
24239
24238
|
const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
24240
24239
|
const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
|
|
24241
24240
|
const steps = yaml2.parse(stepsBody);
|
|
@@ -24262,7 +24261,7 @@ var skill3 = {
|
|
|
24262
24261
|
});
|
|
24263
24262
|
const driver = new SootSimBridgeFlowRunner2(bridge, {
|
|
24264
24263
|
screenshotDir: context.outputDir,
|
|
24265
|
-
flowDir:
|
|
24264
|
+
flowDir: path18.dirname(path18.resolve(params.flowPath)),
|
|
24266
24265
|
simId,
|
|
24267
24266
|
recordingOutputDir: params.record ? context.outputDir : void 0
|
|
24268
24267
|
});
|
|
@@ -24284,7 +24283,7 @@ var skill3 = {
|
|
|
24284
24283
|
simId,
|
|
24285
24284
|
videoPath: videoPath || void 0
|
|
24286
24285
|
},
|
|
24287
|
-
artifacts: videoPath ? [{ type: "video", name:
|
|
24286
|
+
artifacts: videoPath ? [{ type: "video", name: path18.basename(videoPath), path: videoPath }] : void 0
|
|
24288
24287
|
};
|
|
24289
24288
|
} finally {
|
|
24290
24289
|
try {
|
|
@@ -24331,8 +24330,8 @@ var skill4 = {
|
|
|
24331
24330
|
},
|
|
24332
24331
|
async execute(params, context) {
|
|
24333
24332
|
const { chromium } = await import("playwright");
|
|
24334
|
-
const
|
|
24335
|
-
const
|
|
24333
|
+
const path18 = await import("path");
|
|
24334
|
+
const fs18 = await import("fs");
|
|
24336
24335
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
24337
24336
|
headless: true
|
|
24338
24337
|
});
|
|
@@ -24358,9 +24357,9 @@ var skill4 = {
|
|
|
24358
24357
|
...profile,
|
|
24359
24358
|
fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
|
|
24360
24359
|
};
|
|
24361
|
-
const reportPath =
|
|
24362
|
-
|
|
24363
|
-
|
|
24360
|
+
const reportPath = path18.join(context.outputDir, "perf-report.json");
|
|
24361
|
+
fs18.mkdirSync(path18.dirname(reportPath), { recursive: true });
|
|
24362
|
+
fs18.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
24364
24363
|
return {
|
|
24365
24364
|
success: true,
|
|
24366
24365
|
message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
|
|
@@ -24393,8 +24392,8 @@ var skill5 = {
|
|
|
24393
24392
|
},
|
|
24394
24393
|
async execute(params, context) {
|
|
24395
24394
|
const { chromium } = await import("playwright");
|
|
24396
|
-
const
|
|
24397
|
-
const
|
|
24395
|
+
const path18 = await import("path");
|
|
24396
|
+
const fs18 = await import("fs");
|
|
24398
24397
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
24399
24398
|
headless: true
|
|
24400
24399
|
});
|
|
@@ -24402,8 +24401,8 @@ var skill5 = {
|
|
|
24402
24401
|
try {
|
|
24403
24402
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
24404
24403
|
await page.waitForTimeout(2e3);
|
|
24405
|
-
const outputPath =
|
|
24406
|
-
|
|
24404
|
+
const outputPath = path18.join(context.outputDir, `${params.name}.png`);
|
|
24405
|
+
fs18.mkdirSync(path18.dirname(outputPath), { recursive: true });
|
|
24407
24406
|
await page.screenshot({ path: outputPath });
|
|
24408
24407
|
return {
|
|
24409
24408
|
success: true,
|
|
@@ -24444,8 +24443,8 @@ var skill6 = {
|
|
|
24444
24443
|
},
|
|
24445
24444
|
async execute(params, context) {
|
|
24446
24445
|
const { chromium } = await import("playwright");
|
|
24447
|
-
const
|
|
24448
|
-
const
|
|
24446
|
+
const path18 = await import("path");
|
|
24447
|
+
const fs18 = await import("fs");
|
|
24449
24448
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
24450
24449
|
headless: true
|
|
24451
24450
|
});
|
|
@@ -24453,14 +24452,14 @@ var skill6 = {
|
|
|
24453
24452
|
try {
|
|
24454
24453
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
24455
24454
|
await page.waitForTimeout(2e3);
|
|
24456
|
-
const currentPath =
|
|
24457
|
-
|
|
24455
|
+
const currentPath = path18.join(context.outputDir, `${params.name}-current.png`);
|
|
24456
|
+
fs18.mkdirSync(path18.dirname(currentPath), { recursive: true });
|
|
24458
24457
|
await page.screenshot({ path: currentPath });
|
|
24459
24458
|
try {
|
|
24460
24459
|
const { PNG } = await import("pngjs");
|
|
24461
24460
|
const pixelmatch = (await import("pixelmatch")).default;
|
|
24462
|
-
const baseline = PNG.sync.read(
|
|
24463
|
-
const current = PNG.sync.read(
|
|
24461
|
+
const baseline = PNG.sync.read(fs18.readFileSync(params.baseline));
|
|
24462
|
+
const current = PNG.sync.read(fs18.readFileSync(currentPath));
|
|
24464
24463
|
const { width, height } = baseline;
|
|
24465
24464
|
const diff = new PNG({ width, height });
|
|
24466
24465
|
const numDiffPixels = pixelmatch(
|
|
@@ -24471,8 +24470,8 @@ var skill6 = {
|
|
|
24471
24470
|
height,
|
|
24472
24471
|
{ threshold: params.threshold || 0.1 }
|
|
24473
24472
|
);
|
|
24474
|
-
const diffPath =
|
|
24475
|
-
|
|
24473
|
+
const diffPath = path18.join(context.outputDir, `${params.name}-diff.png`);
|
|
24474
|
+
fs18.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
24476
24475
|
const totalPixels = width * height;
|
|
24477
24476
|
const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
|
|
24478
24477
|
return {
|
|
@@ -24536,10 +24535,10 @@ var skillRegistry = {
|
|
|
24536
24535
|
},
|
|
24537
24536
|
// load skills from a project manifest (sootsim-skills.json)
|
|
24538
24537
|
async loadFromManifest(projectDir) {
|
|
24539
|
-
const manifestPath =
|
|
24540
|
-
if (!
|
|
24538
|
+
const manifestPath = path17.join(projectDir, "sootsim-skills.json");
|
|
24539
|
+
if (!fs17.existsSync(manifestPath)) return;
|
|
24541
24540
|
try {
|
|
24542
|
-
const manifest = JSON.parse(
|
|
24541
|
+
const manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf8"));
|
|
24543
24542
|
if (Array.isArray(manifest.skills)) {
|
|
24544
24543
|
for (const entry of manifest.skills) {
|
|
24545
24544
|
if (typeof entry === "string") {
|
|
@@ -24550,7 +24549,7 @@ var skillRegistry = {
|
|
|
24550
24549
|
}
|
|
24551
24550
|
} else if (entry.file) {
|
|
24552
24551
|
try {
|
|
24553
|
-
const mod = await import(
|
|
24552
|
+
const mod = await import(path17.resolve(projectDir, entry.file));
|
|
24554
24553
|
if (mod.skill) this.register(mod.skill);
|
|
24555
24554
|
} catch {
|
|
24556
24555
|
}
|
|
@@ -24563,10 +24562,10 @@ var skillRegistry = {
|
|
|
24563
24562
|
// auto-discover skills based on project dependencies
|
|
24564
24563
|
suggestSkills(projectDir) {
|
|
24565
24564
|
const suggestions = [];
|
|
24566
|
-
const pkgPath =
|
|
24567
|
-
if (!
|
|
24565
|
+
const pkgPath = path17.join(projectDir, "package.json");
|
|
24566
|
+
if (!fs17.existsSync(pkgPath)) return suggestions;
|
|
24568
24567
|
try {
|
|
24569
|
-
const pkg = JSON.parse(
|
|
24568
|
+
const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf8"));
|
|
24570
24569
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
24571
24570
|
if (deps["detox"] || deps["maestro"]) {
|
|
24572
24571
|
suggestions.push("maestro-test");
|