rnxsim 0.1.369 → 0.1.371
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/cli/auth.ts +2 -1
- package/cli/bin.ts +283 -273
- package/cli/commands/app-fonts.ts +3 -2
- package/cli/commands/assert.ts +8 -7
- package/cli/commands/auth.ts +2 -1
- package/cli/commands/box/checkout-plane.ts +109 -29
- package/cli/commands/box/cloud-box.ts +294 -0
- package/cli/commands/box/plane-share.ts +208 -0
- package/cli/commands/box/rnx-command.ts +2 -2
- package/cli/commands/box/search-command.ts +157 -0
- package/cli/commands/box.ts +269 -13
- package/cli/commands/config.ts +2 -1
- package/cli/commands/control.ts +43 -34
- package/cli/commands/daemon.ts +22 -21
- package/cli/commands/debug.ts +17 -15
- package/cli/commands/detox.ts +5 -4
- package/cli/commands/device.ts +6 -5
- package/cli/commands/electron.ts +6 -5
- package/cli/commands/flow.ts +12 -11
- package/cli/commands/inspect/find.ts +2 -1
- package/cli/commands/inspect/keyboard.ts +2 -1
- package/cli/commands/inspect/sleep.ts +2 -1
- package/cli/commands/inspect/wait-event.ts +4 -3
- package/cli/commands/inspect/wait-idle.ts +2 -1
- package/cli/commands/inspect/wait-ready.ts +3 -2
- package/cli/commands/inspect/wait-selector.ts +4 -3
- package/cli/commands/inspect/wait.ts +2 -1
- package/cli/commands/inspect.ts +82 -80
- package/cli/commands/install-desktop.ts +5 -4
- package/cli/commands/login.ts +3 -2
- package/cli/commands/mode.ts +2 -1
- package/cli/commands/record.ts +38 -37
- package/cli/commands/runtime.ts +9 -8
- package/cli/commands/screenshot-layers.ts +4 -3
- package/cli/commands/screenshot-mode.ts +2 -1
- package/cli/commands/screenshot.ts +8 -7
- package/cli/commands/screenshots-capture.ts +2 -1
- package/cli/commands/serve.ts +5 -4
- package/cli/commands/shell-boolean-mode.ts +2 -1
- package/cli/commands/skills.ts +11 -10
- package/cli/commands/telemetry.ts +2 -1
- package/cli/commands/three-mode.ts +2 -1
- package/cli/commands/timeline.ts +4 -3
- package/cli/commands/upload.ts +14 -13
- package/cli/commands/what-happened.ts +2 -1
- package/cli/outbound-endpoints.ts +37 -1
- package/cli/recording-access.ts +6 -5
- package/cli/run-rnx.ts +140 -0
- package/dist-cli/bin.js +6 -6
- package/dist-cli/chunks/{agent-OUUFWDLF.js → agent-W2D2V7WF.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-7BE7DR4R.js → agent-wrapper-GVNM2Z4S.js} +2 -2
- package/dist-cli/chunks/app-fonts-J6R4TTXD.js +4 -0
- package/dist-cli/chunks/{assert-I3CMRNS7.js → assert-YN6U4ZTB.js} +11 -11
- package/dist-cli/chunks/auth-XGYZAK2P.js +12 -0
- package/dist-cli/chunks/{beta-BHSKY4K4.js → beta-WRDMHHWJ.js} +2 -2
- package/dist-cli/chunks/{box-3CVWXVTT.js → box-ML5TFUQW.js} +617 -596
- package/dist-cli/chunks/{camera-MNK73TYV.js → camera-OBEI4FZA.js} +2 -2
- package/dist-cli/chunks/{chunk-JXARZBWS.js → chunk-2FIT64GR.js} +1 -1
- package/dist-cli/chunks/{chunk-RYGQ6LZN.js → chunk-2LH4DYPM.js} +2 -2
- package/dist-cli/chunks/chunk-2QW3JH6T.js +99 -0
- package/dist-cli/chunks/{chunk-2APXX4RN.js → chunk-2W4YBCPX.js} +2 -2
- package/dist-cli/chunks/{chunk-X3PEDNLV.js → chunk-42YOIDLR.js} +2 -2
- package/dist-cli/chunks/{chunk-6BMM6OCW.js → chunk-47MSXLWK.js} +2 -2
- package/dist-cli/chunks/chunk-4OLUFHEZ.js +74 -0
- package/dist-cli/chunks/{chunk-WUR4FXWT.js → chunk-5PPVVGLH.js} +25 -25
- package/dist-cli/chunks/{chunk-AKJYEX54.js → chunk-6AZKZ5AJ.js} +2 -2
- package/dist-cli/chunks/{chunk-2PVVIPQS.js → chunk-6FPXLSBJ.js} +1 -1
- package/dist-cli/chunks/{chunk-CCI3DZKE.js → chunk-763GBI7G.js} +2 -2
- package/dist-cli/chunks/{chunk-CZ2HCNRK.js → chunk-7ASCDKA3.js} +1 -1
- package/dist-cli/chunks/{chunk-ZNNE5MAV.js → chunk-7Q4WHJDH.js} +1 -1
- package/dist-cli/chunks/{chunk-IYPMULI7.js → chunk-7TWD4P6J.js} +2 -2
- package/dist-cli/chunks/{chunk-45X3D6CI.js → chunk-7YB46LGI.js} +1 -1
- package/dist-cli/chunks/{chunk-3454VMHD.js → chunk-ADJSGO55.js} +2 -2
- package/dist-cli/chunks/{chunk-F4OTMARL.js → chunk-AGZZWLEL.js} +2 -2
- package/dist-cli/chunks/{chunk-UDXQCEJU.js → chunk-AVIH3TAZ.js} +11 -11
- package/dist-cli/chunks/{chunk-DCPDMF27.js → chunk-B26ZJUQA.js} +2 -2
- package/dist-cli/chunks/{chunk-D6MGELKZ.js → chunk-BNS5LNEU.js} +1 -1
- package/dist-cli/chunks/{chunk-FHRG772G.js → chunk-CJQXP4XM.js} +1 -1
- package/dist-cli/chunks/{chunk-OROUEG22.js → chunk-DP6RGTNN.js} +2 -2
- package/dist-cli/chunks/{chunk-V7I4CTAX.js → chunk-DYFOLOYL.js} +2 -2
- package/dist-cli/chunks/chunk-ERBGQEJ5.js +4 -0
- package/dist-cli/chunks/{chunk-H2GB2PLY.js → chunk-ESWSXF55.js} +2 -2
- package/dist-cli/chunks/{chunk-FGGESBWD.js → chunk-FLNGSIBL.js} +2 -2
- package/dist-cli/chunks/{chunk-4SCVGBOX.js → chunk-GQGS7TRK.js} +1 -1
- package/dist-cli/chunks/{chunk-WGE2P25F.js → chunk-H4DU457S.js} +1 -1
- package/dist-cli/chunks/{chunk-TBK5UXW2.js → chunk-HFY35VAG.js} +2 -2
- package/dist-cli/chunks/{chunk-JLOOLA47.js → chunk-HV3WOWQM.js} +1 -1
- package/dist-cli/chunks/{chunk-RV76U3EI.js → chunk-HZ365EMS.js} +10 -10
- package/dist-cli/chunks/chunk-IPNDXGVA.js +11 -0
- package/dist-cli/chunks/{chunk-TAC4CEIX.js → chunk-IX7Z6ZVJ.js} +2 -2
- package/dist-cli/chunks/{chunk-UQJY6O72.js → chunk-IYU2EOIU.js} +1 -1
- package/dist-cli/chunks/chunk-J6A5W2DI.js +30 -0
- package/dist-cli/chunks/chunk-JKRMBNPO.js +28 -0
- package/dist-cli/chunks/{chunk-VGJLCFSC.js → chunk-JUTLQ3GX.js} +1 -1
- package/dist-cli/chunks/{chunk-5QFJFASW.js → chunk-KHGXEU4L.js} +1 -1
- package/dist-cli/chunks/{chunk-A56GQVNF.js → chunk-KL34TRNW.js} +1 -1
- package/dist-cli/chunks/chunk-LFANRLWK.js +7 -0
- package/dist-cli/chunks/{chunk-NPVEBXU3.js → chunk-MOIQZVRU.js} +2 -2
- package/dist-cli/chunks/chunk-MW4E5EED.js +497 -0
- package/dist-cli/chunks/{chunk-AJJCYLBC.js → chunk-N3LAMTGS.js} +2 -2
- package/dist-cli/chunks/{chunk-QE5MC4V3.js → chunk-NQ4CI2VI.js} +1 -1
- package/dist-cli/chunks/{chunk-6F3WOWFC.js → chunk-OF3U4SZO.js} +2 -2
- package/dist-cli/chunks/{chunk-DKSZZABN.js → chunk-OF5OBB67.js} +1 -1
- package/dist-cli/chunks/{chunk-MXWME7ET.js → chunk-OQPZOEEP.js} +1 -1
- package/dist-cli/chunks/{chunk-SSBZA5VZ.js → chunk-OWDJQWJ7.js} +1 -1
- package/dist-cli/chunks/{chunk-YLNSLMQM.js → chunk-PTWMX4AA.js} +2 -2
- package/dist-cli/chunks/{chunk-TTUZ5MCK.js → chunk-RYJTPZCX.js} +1 -1
- package/dist-cli/chunks/{chunk-A72MIIJI.js → chunk-S3AH2O67.js} +1 -1
- package/dist-cli/chunks/{chunk-ZW6JXEVX.js → chunk-SH2HXHR2.js} +2 -2
- package/dist-cli/chunks/{chunk-EKAEEWC2.js → chunk-SHLJYXIN.js} +1 -1
- package/dist-cli/chunks/{chunk-4G4VCT2M.js → chunk-TL22EBF5.js} +2 -2
- package/dist-cli/chunks/{chunk-LU3AHE6T.js → chunk-TWNLRDIH.js} +2 -2
- package/dist-cli/chunks/{chunk-B5NW4TT3.js → chunk-UHYAY3RU.js} +2 -2
- package/dist-cli/chunks/{chunk-N5KDDGV6.js → chunk-UPMR6Y5P.js} +2 -2
- package/dist-cli/chunks/chunk-VEFSHPSU.js +24 -0
- package/dist-cli/chunks/{chunk-YPBDPVLR.js → chunk-WCB5XPCH.js} +2 -2
- package/dist-cli/chunks/{chunk-USHV3QFZ.js → chunk-WHZE63R2.js} +2 -2
- package/dist-cli/chunks/{chunk-ZEF57HQO.js → chunk-WLRIPAGJ.js} +1 -1
- package/dist-cli/chunks/{chunk-FBMNYSSW.js → chunk-Y7SKGRAV.js} +1 -1
- package/dist-cli/chunks/chunk-Z6CQDU74.js +4 -0
- package/dist-cli/chunks/{cleanup-H4XFRMZV.js → cleanup-PTJBMC34.js} +2 -2
- package/dist-cli/chunks/cli-version-6ZBD6GKP.js +4 -0
- package/dist-cli/chunks/{compat-NKGYERLN.js → compat-FJ2HWRAG.js} +2 -2
- package/dist-cli/chunks/config-PYGH7JPN.js +13 -0
- package/dist-cli/chunks/{connect-WWWAVVCF.js → connect-AJV4PZA4.js} +2 -2
- package/dist-cli/chunks/control-667PAYX4.js +4 -0
- package/dist-cli/chunks/daemon-EIBOHZYQ.js +4 -0
- package/dist-cli/chunks/{debug-RO6GLDIM.js → debug-XF2XUDHN.js} +20 -20
- package/dist-cli/chunks/desktop-HEZYNFYW.js +31 -0
- package/dist-cli/chunks/detox-JCFZJRNE.js +52 -0
- package/dist-cli/chunks/device-KGUVZHFW.js +18 -0
- package/dist-cli/chunks/{diagnose-HDRTUPDO.js → diagnose-KVJQ3TOI.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-QP2NYN43.js → disk-cleanup-7HQXJFUX.js} +2 -2
- package/dist-cli/chunks/{do-chain-6LP6SV5J.js → do-chain-3FYJNA2N.js} +2 -2
- package/dist-cli/chunks/drivers-5S6M5TJB.js +4 -0
- package/dist-cli/chunks/{env-4XD5D2G6.js → env-BX6S2SOM.js} +2 -2
- package/dist-cli/chunks/{film-I5SIXLS5.js → film-2WZUVYFA.js} +3 -3
- package/dist-cli/chunks/flow-6BZSWNHG.js +4 -0
- package/dist-cli/chunks/help-OGJBD4NP.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-LJV2S4M2.js → hidden-runtime-alias-PGF55OFH.js} +2 -2
- package/dist-cli/chunks/{home-paths-RFI2QRC3.js → home-paths-EGRMTSGE.js} +2 -2
- package/dist-cli/chunks/inspect-MZVDGAN4.js +4 -0
- package/dist-cli/chunks/install-desktop-QB76DNZF.js +4 -0
- package/dist-cli/chunks/login-HRFPYPZ3.js +26 -0
- package/dist-cli/chunks/{logout-DKXZZ6HU.js → logout-LRH5HZGP.js} +2 -2
- package/dist-cli/chunks/{maestro-WKGVVWRA.js → maestro-S53T4PPE.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-KCK6RK2C.js → maestro-generate-YKIVKOB3.js} +3 -3
- package/dist-cli/chunks/mode-47JKNUNS.js +26 -0
- package/dist-cli/chunks/{optional-demo-registry-EUSKBIPP.js → optional-demo-registry-ARZSPS5Y.js} +2 -2
- package/dist-cli/chunks/{perf-IMZMA5MT.js → perf-J73OKB4T.js} +2 -2
- package/dist-cli/chunks/{permissions-SLWXTLH6.js → permissions-L3FPI56H.js} +2 -2
- package/dist-cli/chunks/{platform-HQ735LAE.js → platform-YAROAHRM.js} +3 -3
- package/dist-cli/chunks/privacy-JZQCXHKN.js +4 -0
- package/dist-cli/chunks/record-QAQMGYOO.js +72 -0
- package/dist-cli/chunks/report-issue-4FVZCAFQ.js +29 -0
- package/dist-cli/chunks/reset-NYFUFZCG.js +4 -0
- package/dist-cli/chunks/resolve-target-SP22ZGFZ.js +4 -0
- package/dist-cli/chunks/runtime-WTS2QMXZ.js +4 -0
- package/dist-cli/chunks/{screenshot-command-HAJB5FHK.js → screenshot-command-Q5MGGEWY.js} +11 -11
- package/dist-cli/chunks/screenshot-layers-4JW7DRL7.js +20 -0
- package/dist-cli/chunks/screenshots-capture-X5PMO44E.js +42 -0
- package/dist-cli/chunks/{serve-TM46TKFW.js → serve-3JWJ45J3.js} +20 -20
- package/dist-cli/chunks/setup-USPDJESI.js +4 -0
- package/dist-cli/chunks/{sim-client-LQUZSO45.js → sim-client-RL6DGOJE.js} +2 -2
- package/dist-cli/chunks/skills-QNO6GDJB.js +50 -0
- package/dist-cli/chunks/{state-RUVM4Z4S.js → state-OGUCSUC3.js} +2 -2
- package/dist-cli/chunks/{storage-GQ33UTYN.js → storage-TG7KFQZ3.js} +2 -2
- package/dist-cli/chunks/store-ZYMQW2LN.js +4 -0
- package/dist-cli/chunks/telemetry-7CSLUUIW.js +4 -0
- package/dist-cli/chunks/timeline-R4G5P335.js +24 -0
- package/dist-cli/chunks/{upgrade-AZDZLUIT.js → upgrade-RDTXJ6O3.js} +2 -2
- package/dist-cli/chunks/upload-PLF2DPMS.js +4 -0
- package/dist-cli/chunks/{version-N3ALB75G.js → version-GU2NUZDS.js} +2 -2
- package/dist-cli/chunks/{web-XPHFZATA.js → web-7PUVG3GE.js} +2 -2
- package/dist-cli/chunks/welcome-4GGUV7FY.js +5 -0
- package/dist-cli/chunks/what-happened-OHAAX6F6.js +25 -0
- package/dist-cli/chunks/{ws-bridge-RUXOYOU6.js → ws-bridge-Z3O35MNF.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-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/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 +69 -34
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +430 -106
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +2 -1
- package/dist-lib/react-native-host-modules.mjs +2 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +149 -93
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +757 -353
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +275 -92
- package/src/dev-bundle-resolution.ts +123 -40
- package/src/host/bridge-host.ts +11 -0
- package/src/host/plane-host.ts +203 -0
- package/src/react-native-host-modules.ts +1 -0
- package/dist-cli/chunks/app-fonts-66V7TL26.js +0 -4
- package/dist-cli/chunks/auth-3FMWUVJH.js +0 -12
- package/dist-cli/chunks/chunk-3NLB5LCN.js +0 -28
- package/dist-cli/chunks/chunk-5RWUFIZW.js +0 -24
- package/dist-cli/chunks/chunk-COXCR6UU.js +0 -7
- package/dist-cli/chunks/chunk-JH5KE2OI.js +0 -4
- package/dist-cli/chunks/chunk-ROISJKH3.js +0 -99
- package/dist-cli/chunks/chunk-SUHAD6N2.js +0 -30
- package/dist-cli/chunks/chunk-TIB3CTRX.js +0 -497
- package/dist-cli/chunks/chunk-YFZLDFZK.js +0 -74
- package/dist-cli/chunks/cli-version-MJWLDXBW.js +0 -4
- package/dist-cli/chunks/config-WK7467KI.js +0 -13
- package/dist-cli/chunks/control-ESI7IZNN.js +0 -4
- package/dist-cli/chunks/daemon-UCLO27YP.js +0 -4
- package/dist-cli/chunks/desktop-FF34Z5X4.js +0 -31
- package/dist-cli/chunks/detox-Q3CWY5UX.js +0 -52
- package/dist-cli/chunks/device-WN4ZWLES.js +0 -18
- package/dist-cli/chunks/drivers-OR2JPAXD.js +0 -4
- package/dist-cli/chunks/flow-4GWW5DYT.js +0 -4
- package/dist-cli/chunks/help-MIIWOT3C.js +0 -4
- package/dist-cli/chunks/inspect-3ZGNJENJ.js +0 -4
- package/dist-cli/chunks/install-desktop-BYOJVTLS.js +0 -4
- package/dist-cli/chunks/login-GNIFSAFE.js +0 -26
- package/dist-cli/chunks/mode-YVMX7OJY.js +0 -26
- package/dist-cli/chunks/privacy-EDC7PF7G.js +0 -4
- package/dist-cli/chunks/record-N4KTTVDI.js +0 -72
- package/dist-cli/chunks/report-issue-PP752HAD.js +0 -29
- package/dist-cli/chunks/reset-DRMKGVP4.js +0 -4
- package/dist-cli/chunks/resolve-target-7WWI32R3.js +0 -4
- package/dist-cli/chunks/runtime-EKJV2ZVI.js +0 -4
- package/dist-cli/chunks/screenshot-layers-GOCJVM2G.js +0 -20
- package/dist-cli/chunks/screenshots-capture-YYJLYA3V.js +0 -42
- package/dist-cli/chunks/setup-FVPVIYE4.js +0 -4
- package/dist-cli/chunks/skills-V5TE57FN.js +0 -50
- package/dist-cli/chunks/store-IKNBDDKM.js +0 -4
- package/dist-cli/chunks/telemetry-2ZVU6WLK.js +0 -4
- package/dist-cli/chunks/timeline-LP7DMJYT.js +0 -24
- package/dist-cli/chunks/upload-DFQK2Q7X.js +0 -4
- package/dist-cli/chunks/welcome-2NFYLWLJ.js +0 -5
- package/dist-cli/chunks/what-happened-EJ5PHKT7.js +0 -25
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.371 | (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;
|
|
@@ -14659,9 +14659,9 @@ function safeChildPlistName(value) {
|
|
|
14659
14659
|
name: file.toLowerCase().endsWith(".plist") ? file : `${file}.plist`
|
|
14660
14660
|
};
|
|
14661
14661
|
}
|
|
14662
|
-
async function readableSettingsBundle(
|
|
14662
|
+
async function readableSettingsBundle(path20) {
|
|
14663
14663
|
try {
|
|
14664
|
-
const root = await (0, import_promises.stat)((0, import_node_path.join)(
|
|
14664
|
+
const root = await (0, import_promises.stat)((0, import_node_path.join)(path20, "Root.plist"));
|
|
14665
14665
|
return root.isFile() && root.size <= MAX_PLIST_BYTES;
|
|
14666
14666
|
} catch {
|
|
14667
14667
|
return false;
|
|
@@ -14706,11 +14706,11 @@ async function settingsBundleFingerprint(bundlePath) {
|
|
|
14706
14706
|
return null;
|
|
14707
14707
|
}
|
|
14708
14708
|
}
|
|
14709
|
-
async function parsePlistRecord(
|
|
14709
|
+
async function parsePlistRecord(path20) {
|
|
14710
14710
|
try {
|
|
14711
|
-
const metadata = await (0, import_promises.stat)(
|
|
14711
|
+
const metadata = await (0, import_promises.stat)(path20);
|
|
14712
14712
|
if (!metadata.isFile() || metadata.size > MAX_PLIST_BYTES) return null;
|
|
14713
|
-
const source = await (0, import_promises.readFile)(
|
|
14713
|
+
const source = await (0, import_promises.readFile)(path20, "utf8");
|
|
14714
14714
|
const parsed = parsePlistSource(source);
|
|
14715
14715
|
return isRecord2(parsed) ? parsed : null;
|
|
14716
14716
|
} catch {
|
|
@@ -14972,6 +14972,25 @@ var init_optional_demo_registry = __esm({
|
|
|
14972
14972
|
});
|
|
14973
14973
|
|
|
14974
14974
|
// scripts/dev-server-scanner.ts
|
|
14975
|
+
function execGuarded(command, timeout, extra = {}) {
|
|
14976
|
+
let child;
|
|
14977
|
+
const ran = new Promise((resolve7, reject) => {
|
|
14978
|
+
child = (0, import_child_process.exec)(command, { encoding: "utf8", timeout, ...extra }, (err, stdout) => {
|
|
14979
|
+
if (err) reject(err);
|
|
14980
|
+
else resolve7({ stdout });
|
|
14981
|
+
});
|
|
14982
|
+
});
|
|
14983
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
14984
|
+
const timer = setTimeout(() => {
|
|
14985
|
+
child?.kill("SIGKILL");
|
|
14986
|
+
const err = new Error(`\`${command}\` did not exit within ${timeout}ms`);
|
|
14987
|
+
Object.assign(err, { killed: true });
|
|
14988
|
+
reject(err);
|
|
14989
|
+
}, timeout + EXEC_EXIT_GRACE_MS);
|
|
14990
|
+
timer.unref?.();
|
|
14991
|
+
});
|
|
14992
|
+
return Promise.race([ran, deadline]);
|
|
14993
|
+
}
|
|
14975
14994
|
async function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
14976
14995
|
try {
|
|
14977
14996
|
return await Promise.any(
|
|
@@ -14998,93 +15017,116 @@ async function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
14998
15017
|
return null;
|
|
14999
15018
|
}
|
|
15000
15019
|
}
|
|
15001
|
-
function httpGet(hostname, port,
|
|
15020
|
+
function httpGet(hostname, port, path20, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
15002
15021
|
return new Promise((resolve7) => {
|
|
15003
|
-
|
|
15004
|
-
|
|
15005
|
-
(
|
|
15006
|
-
|
|
15007
|
-
|
|
15008
|
-
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
|
|
15018
|
-
|
|
15019
|
-
|
|
15020
|
-
|
|
15021
|
-
|
|
15022
|
-
|
|
15023
|
-
|
|
15024
|
-
|
|
15025
|
-
|
|
15026
|
-
|
|
15027
|
-
req.destroy();
|
|
15028
|
-
resolve7(null);
|
|
15022
|
+
let settled = false;
|
|
15023
|
+
const settle = (value) => {
|
|
15024
|
+
if (settled) return;
|
|
15025
|
+
settled = true;
|
|
15026
|
+
resolve7(value);
|
|
15027
|
+
};
|
|
15028
|
+
const req = import_http.default.request({ hostname, port, path: path20, method, headers }, (res) => {
|
|
15029
|
+
let body = "";
|
|
15030
|
+
res.on("data", (c) => body += c.toString());
|
|
15031
|
+
const contentType = (() => {
|
|
15032
|
+
const raw = res.headers["content-type"];
|
|
15033
|
+
if (typeof raw === "string") return raw;
|
|
15034
|
+
if (Array.isArray(raw)) return raw[0];
|
|
15035
|
+
return void 0;
|
|
15036
|
+
})();
|
|
15037
|
+
res.on(
|
|
15038
|
+
"end",
|
|
15039
|
+
() => settle({
|
|
15040
|
+
statusCode: res.statusCode || 0,
|
|
15041
|
+
body,
|
|
15042
|
+
contentType,
|
|
15043
|
+
hostname
|
|
15044
|
+
})
|
|
15045
|
+
);
|
|
15029
15046
|
});
|
|
15047
|
+
req.on("error", () => settle(null));
|
|
15030
15048
|
req.end();
|
|
15049
|
+
const giveUp = setTimeout(() => {
|
|
15050
|
+
settle(null);
|
|
15051
|
+
req.socket?.unref();
|
|
15052
|
+
}, timeout);
|
|
15053
|
+
const abandon = setTimeout(() => req.destroy(), BODY_TIMEOUT_MS);
|
|
15054
|
+
abandon.unref?.();
|
|
15055
|
+
req.on("close", () => {
|
|
15056
|
+
clearTimeout(giveUp);
|
|
15057
|
+
clearTimeout(abandon);
|
|
15058
|
+
setImmediate(() => settle(null));
|
|
15059
|
+
});
|
|
15031
15060
|
});
|
|
15032
15061
|
}
|
|
15062
|
+
function isOwnShellPort(port) {
|
|
15063
|
+
const offset = Number(process.env.PORT_OFFSET) || 0;
|
|
15064
|
+
if (port >= SELF_PORT_RANGE_START && port <= SELF_PORT_RANGE_END) return true;
|
|
15065
|
+
return offset > 0 && port >= SELF_PORT_RANGE_START + offset && port <= SELF_PORT_RANGE_END + offset;
|
|
15066
|
+
}
|
|
15033
15067
|
function acceptPort(port, excluded) {
|
|
15034
15068
|
if (port <= 0 || port >= 2e4) return false;
|
|
15035
15069
|
if (excluded.has(port)) return false;
|
|
15036
|
-
if (port
|
|
15070
|
+
if (isOwnShellPort(port)) return false;
|
|
15037
15071
|
return true;
|
|
15038
15072
|
}
|
|
15039
|
-
|
|
15073
|
+
function wasKilledByTimeout(err) {
|
|
15074
|
+
return !!(err && typeof err === "object" && err.killed);
|
|
15075
|
+
}
|
|
15076
|
+
async function scanListeningProcesses(excludePorts = []) {
|
|
15040
15077
|
const excluded = new Set(excludePorts);
|
|
15078
|
+
let timedOut = false;
|
|
15041
15079
|
try {
|
|
15042
|
-
const { stdout } = await
|
|
15080
|
+
const { stdout } = await execGuarded(
|
|
15043
15081
|
`lsof -iTCP -sTCP:LISTEN -P -n 2>/dev/null | grep -E '^(node|bun)'`,
|
|
15044
|
-
|
|
15082
|
+
LISTING_TIMEOUT_MS
|
|
15045
15083
|
);
|
|
15046
|
-
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
if (!seen.has(port)) seen.set(port, pid);
|
|
15058
|
-
}
|
|
15059
|
-
if (seen.size > 0) {
|
|
15060
|
-
return [...seen.entries()].map(([port, pid]) => ({ port, pid }));
|
|
15061
|
-
}
|
|
15084
|
+
const seen = /* @__PURE__ */ new Map();
|
|
15085
|
+
for (const line of stdout.trim() ? stdout.trim().split("\n") : []) {
|
|
15086
|
+
const parts = line.trim().split(/\s+/);
|
|
15087
|
+
if (parts.length < 9) continue;
|
|
15088
|
+
const pid = Number(parts[1]);
|
|
15089
|
+
const addr = parts[8];
|
|
15090
|
+
const m = addr.match(/:(\d+)$/);
|
|
15091
|
+
if (!m) continue;
|
|
15092
|
+
const port = Number(m[1]);
|
|
15093
|
+
if (!acceptPort(port, excluded)) continue;
|
|
15094
|
+
if (!seen.has(port)) seen.set(port, pid);
|
|
15062
15095
|
}
|
|
15063
|
-
|
|
15096
|
+
return {
|
|
15097
|
+
state: "looked",
|
|
15098
|
+
processes: [...seen.entries()].map(([port, pid]) => ({ port, pid }))
|
|
15099
|
+
};
|
|
15100
|
+
} catch (err) {
|
|
15101
|
+
if (wasKilledByTimeout(err)) timedOut = true;
|
|
15064
15102
|
}
|
|
15065
15103
|
try {
|
|
15066
|
-
const { stdout } = await
|
|
15067
|
-
|
|
15068
|
-
|
|
15069
|
-
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
if (!seen.has(port)) seen.set(port, pid);
|
|
15080
|
-
}
|
|
15081
|
-
if (seen.size > 0) {
|
|
15082
|
-
return [...seen.entries()].map(([port, pid]) => ({ port, pid }));
|
|
15083
|
-
}
|
|
15104
|
+
const { stdout } = await execGuarded(
|
|
15105
|
+
`ss -tlnp 2>/dev/null | grep -E '"(node|bun)"'`,
|
|
15106
|
+
LISTING_TIMEOUT_MS
|
|
15107
|
+
);
|
|
15108
|
+
const seen = /* @__PURE__ */ new Map();
|
|
15109
|
+
for (const line of stdout.trim() ? stdout.trim().split("\n") : []) {
|
|
15110
|
+
const portMatch = line.match(/:(\d+)\s/);
|
|
15111
|
+
const pidMatch = line.match(/pid=(\d+)/);
|
|
15112
|
+
if (!portMatch) continue;
|
|
15113
|
+
const port = Number(portMatch[1]);
|
|
15114
|
+
const pid = pidMatch ? Number(pidMatch[1]) : 0;
|
|
15115
|
+
if (!acceptPort(port, excluded)) continue;
|
|
15116
|
+
if (!seen.has(port)) seen.set(port, pid);
|
|
15084
15117
|
}
|
|
15085
|
-
|
|
15118
|
+
return {
|
|
15119
|
+
state: "looked",
|
|
15120
|
+
processes: [...seen.entries()].map(([port, pid]) => ({ port, pid }))
|
|
15121
|
+
};
|
|
15122
|
+
} catch (err) {
|
|
15123
|
+
if (wasKilledByTimeout(err)) timedOut = true;
|
|
15086
15124
|
}
|
|
15087
|
-
|
|
15125
|
+
if (timedOut) return { state: "could-not-look" };
|
|
15126
|
+
return {
|
|
15127
|
+
state: "looked",
|
|
15128
|
+
processes: FALLBACK_PORTS.filter((p) => acceptPort(p.port, excluded))
|
|
15129
|
+
};
|
|
15088
15130
|
}
|
|
15089
15131
|
function pidFromNetstat(stdout, port) {
|
|
15090
15132
|
for (const line of stdout.split("\n")) {
|
|
@@ -15104,9 +15146,7 @@ function pidFromNetstat(stdout, port) {
|
|
|
15104
15146
|
async function resolveListeningPid(port) {
|
|
15105
15147
|
if (!Number.isInteger(port) || port <= 0) return null;
|
|
15106
15148
|
try {
|
|
15107
|
-
const { stdout } = await
|
|
15108
|
-
encoding: "utf8",
|
|
15109
|
-
timeout: 8e3,
|
|
15149
|
+
const { stdout } = await execGuarded("netstat -anv -p tcp 2>/dev/null", 8e3, {
|
|
15110
15150
|
maxBuffer: 16 * 1024 * 1024
|
|
15111
15151
|
});
|
|
15112
15152
|
const pid = pidFromNetstat(stdout, port);
|
|
@@ -15114,9 +15154,7 @@ async function resolveListeningPid(port) {
|
|
|
15114
15154
|
} catch {
|
|
15115
15155
|
}
|
|
15116
15156
|
try {
|
|
15117
|
-
const { stdout } = await
|
|
15118
|
-
encoding: "utf8",
|
|
15119
|
-
timeout: 8e3,
|
|
15157
|
+
const { stdout } = await execGuarded(`ss -tlnp 2>/dev/null`, 8e3, {
|
|
15120
15158
|
maxBuffer: 16 * 1024 * 1024
|
|
15121
15159
|
});
|
|
15122
15160
|
for (const line of stdout.split("\n")) {
|
|
@@ -15141,10 +15179,10 @@ async function resolveProcessCwd(pid) {
|
|
|
15141
15179
|
} catch {
|
|
15142
15180
|
}
|
|
15143
15181
|
try {
|
|
15144
|
-
const { stdout } = await
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15182
|
+
const { stdout } = await execGuarded(
|
|
15183
|
+
`lsof -b -w -p ${pid} -a -d cwd -Fn 2>/dev/null`,
|
|
15184
|
+
8e3
|
|
15185
|
+
);
|
|
15148
15186
|
for (const line of stdout.split("\n")) {
|
|
15149
15187
|
if (line.startsWith("n") && line.length > 1) {
|
|
15150
15188
|
const cwd = line.slice(1).trim();
|
|
@@ -15306,7 +15344,8 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
15306
15344
|
const manifestParsed = manifestRes ? safeParseManifest(manifestRes.body) : null;
|
|
15307
15345
|
const manifestLaunchUrl = typeof manifestParsed?.launchAsset?.url === "string" ? manifestParsed.launchAsset.url : null;
|
|
15308
15346
|
const manifestClient = manifestParsed?.extra?.expoClient || manifestParsed?.extra || {};
|
|
15309
|
-
|
|
15347
|
+
const manifestState = !manifestRes ? "no-answer" : manifestParsed && (manifestLaunchUrl || typeof manifestClient.name === "string") ? "resolved" : "no-manifest";
|
|
15348
|
+
if (manifestState === "resolved") {
|
|
15310
15349
|
knownNonPatched.add(port);
|
|
15311
15350
|
const launchUrl2 = manifestLaunchUrl || `${buildLoopbackProbeBaseUrl("http:", probeHostname, port)}/index.bundle?platform=ios&dev=true&hot=true&minify=false`;
|
|
15312
15351
|
const framework = launchUrl2.includes(
|
|
@@ -15327,17 +15366,15 @@ async function probePort(port, buildIconProxyUrl, listeningProcess) {
|
|
|
15327
15366
|
}
|
|
15328
15367
|
if (statusRes && statusRes.body.includes("packager-status:running")) {
|
|
15329
15368
|
knownNonPatched.add(port);
|
|
15369
|
+
const result = makeResult(
|
|
15370
|
+
probeHostname,
|
|
15371
|
+
port,
|
|
15372
|
+
expoRes && expoRes.statusCode === 200 ? "expo" : "metro",
|
|
15373
|
+
owner
|
|
15374
|
+
);
|
|
15375
|
+
if (manifestState === "no-answer") result.bundleUrlProvisional = true;
|
|
15330
15376
|
return enrichWithManifest(
|
|
15331
|
-
applyManifest(
|
|
15332
|
-
makeResult(
|
|
15333
|
-
probeHostname,
|
|
15334
|
-
port,
|
|
15335
|
-
expoRes && expoRes.statusCode === 200 ? "expo" : "metro",
|
|
15336
|
-
owner
|
|
15337
|
-
),
|
|
15338
|
-
manifestRes,
|
|
15339
|
-
buildIconProxyUrl
|
|
15340
|
-
),
|
|
15377
|
+
applyManifest(result, manifestRes, buildIconProxyUrl),
|
|
15341
15378
|
buildIconProxyUrl
|
|
15342
15379
|
);
|
|
15343
15380
|
}
|
|
@@ -15430,7 +15467,9 @@ async function attachAppSettingsBundle(result, projectRoot) {
|
|
|
15430
15467
|
}
|
|
15431
15468
|
async function scanDevServers(opts = {}) {
|
|
15432
15469
|
await loadOptionalDemoApps();
|
|
15433
|
-
const
|
|
15470
|
+
const scan = await scanListeningProcesses(opts.excludePorts);
|
|
15471
|
+
if (scan.state === "could-not-look") throw new DevServerScanUnavailableError();
|
|
15472
|
+
const processes = scan.processes;
|
|
15434
15473
|
const currentPorts = new Set(processes.map((p) => p.port));
|
|
15435
15474
|
for (const p of [...portCache.keys()]) {
|
|
15436
15475
|
if (!currentPorts.has(p)) portCache.delete(p);
|
|
@@ -15494,7 +15533,7 @@ async function scanDevServers(opts = {}) {
|
|
|
15494
15533
|
}
|
|
15495
15534
|
return results.filter((r) => !isSootSimSelfServer(r));
|
|
15496
15535
|
}
|
|
15497
|
-
var import_child_process, import_promises2, import_http, import_net, import_node_path3,
|
|
15536
|
+
var import_child_process, import_promises2, import_http, import_net, import_node_path3, EXEC_EXIT_GRACE_MS, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, BODY_TIMEOUT_MS, FALLBACK_PORTS, SELF_PORT_RANGE_START, SELF_PORT_RANGE_END, DevServerScanUnavailableError, LISTING_TIMEOUT_MS, cwdByPid, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
|
|
15498
15537
|
var init_dev_server_scanner = __esm({
|
|
15499
15538
|
"scripts/dev-server-scanner.ts"() {
|
|
15500
15539
|
"use strict";
|
|
@@ -15503,16 +15542,16 @@ var init_dev_server_scanner = __esm({
|
|
|
15503
15542
|
import_http = __toESM(require("http"), 1);
|
|
15504
15543
|
import_net = __toESM(require("net"), 1);
|
|
15505
15544
|
import_node_path3 = require("node:path");
|
|
15506
|
-
import_util = require("util");
|
|
15507
15545
|
init_backend_origin();
|
|
15508
15546
|
init_config();
|
|
15509
15547
|
init_native_dev_bundle_url();
|
|
15510
15548
|
init_settings_bundle();
|
|
15511
15549
|
init_optional_demo_registry();
|
|
15512
|
-
|
|
15550
|
+
EXEC_EXIT_GRACE_MS = 2e3;
|
|
15513
15551
|
TIMEOUT_MS = 250;
|
|
15514
15552
|
MANIFEST_TIMEOUT_MS = 1500;
|
|
15515
15553
|
TCP_GATE_MS = 120;
|
|
15554
|
+
BODY_TIMEOUT_MS = 3e4;
|
|
15516
15555
|
FALLBACK_PORTS = [
|
|
15517
15556
|
8081,
|
|
15518
15557
|
8082,
|
|
@@ -15524,6 +15563,15 @@ var init_dev_server_scanner = __esm({
|
|
|
15524
15563
|
3001,
|
|
15525
15564
|
19e3
|
|
15526
15565
|
].map((port) => ({ port, pid: 0 }));
|
|
15566
|
+
SELF_PORT_RANGE_START = 5170;
|
|
15567
|
+
SELF_PORT_RANGE_END = 5200;
|
|
15568
|
+
DevServerScanUnavailableError = class extends Error {
|
|
15569
|
+
constructor() {
|
|
15570
|
+
super("could not enumerate listening processes (lsof/ss unavailable or timed out)");
|
|
15571
|
+
this.name = "DevServerScanUnavailableError";
|
|
15572
|
+
}
|
|
15573
|
+
};
|
|
15574
|
+
LISTING_TIMEOUT_MS = 1e4;
|
|
15527
15575
|
cwdByPid = /* @__PURE__ */ new Map();
|
|
15528
15576
|
ENRICH_TIMEOUT_MS = 2e4;
|
|
15529
15577
|
enrichmentCache = /* @__PURE__ */ new Map();
|
|
@@ -18451,9 +18499,290 @@ var init_open_url = __esm({
|
|
|
18451
18499
|
}
|
|
18452
18500
|
});
|
|
18453
18501
|
|
|
18502
|
+
// cli/commands/box/checkout-plane.ts
|
|
18503
|
+
function looksBinary(filePath, size) {
|
|
18504
|
+
if (size === 0) return false;
|
|
18505
|
+
let fd;
|
|
18506
|
+
try {
|
|
18507
|
+
fd = import_node_fs9.default.openSync(filePath, "r");
|
|
18508
|
+
const buffer = Buffer.alloc(Math.min(BINARY_SNIFF_BYTES, size));
|
|
18509
|
+
const read = import_node_fs9.default.readSync(fd, buffer, 0, buffer.length, 0);
|
|
18510
|
+
return buffer.subarray(0, read).includes(0);
|
|
18511
|
+
} catch {
|
|
18512
|
+
return false;
|
|
18513
|
+
} finally {
|
|
18514
|
+
if (fd !== void 0) import_node_fs9.default.closeSync(fd);
|
|
18515
|
+
}
|
|
18516
|
+
}
|
|
18517
|
+
var import_node_child_process5, import_node_fs9, import_node_path10, CheckoutRequiresGitError, BINARY_SNIFF_BYTES, LIST_FILES_TIMEOUT_MS, CheckoutFilePlane;
|
|
18518
|
+
var init_checkout_plane = __esm({
|
|
18519
|
+
"cli/commands/box/checkout-plane.ts"() {
|
|
18520
|
+
"use strict";
|
|
18521
|
+
import_node_child_process5 = require("node:child_process");
|
|
18522
|
+
import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
18523
|
+
import_node_path10 = __toESM(require("node:path"), 1);
|
|
18524
|
+
CheckoutRequiresGitError = class extends Error {
|
|
18525
|
+
};
|
|
18526
|
+
BINARY_SNIFF_BYTES = 8192;
|
|
18527
|
+
LIST_FILES_TIMEOUT_MS = 1e4;
|
|
18528
|
+
CheckoutFilePlane = class {
|
|
18529
|
+
root;
|
|
18530
|
+
entries = /* @__PURE__ */ new Map();
|
|
18531
|
+
sniffed = /* @__PURE__ */ new Map();
|
|
18532
|
+
// the deadline above, as a number a caller can set. what it changes is how
|
|
18533
|
+
// long a wedged git is waited on, never whether it is waited on, so proving
|
|
18534
|
+
// the kill does not have to cost the production deadline.
|
|
18535
|
+
listTimeoutMs;
|
|
18536
|
+
constructor(root, options = {}) {
|
|
18537
|
+
this.root = import_node_path10.default.resolve(root);
|
|
18538
|
+
this.listTimeoutMs = options.listTimeoutMs ?? LIST_FILES_TIMEOUT_MS;
|
|
18539
|
+
}
|
|
18540
|
+
index() {
|
|
18541
|
+
return this.entries;
|
|
18542
|
+
}
|
|
18543
|
+
async refresh() {
|
|
18544
|
+
let stdout;
|
|
18545
|
+
try {
|
|
18546
|
+
stdout = (0, import_node_child_process5.execFileSync)("git", ["ls-files", "-co", "--exclude-standard", "-z"], {
|
|
18547
|
+
cwd: this.root,
|
|
18548
|
+
encoding: "utf8",
|
|
18549
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
18550
|
+
timeout: this.listTimeoutMs,
|
|
18551
|
+
// stating the environment is not redundant here. bun 1.3.14 resolves
|
|
18552
|
+
// the binary for the synchronous form against the PATH it captured at
|
|
18553
|
+
// startup and ignores a later change to `process.env.PATH`, so without
|
|
18554
|
+
// this it runs a different git than every other call in the process.
|
|
18555
|
+
env: process.env
|
|
18556
|
+
});
|
|
18557
|
+
} catch (error) {
|
|
18558
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
18559
|
+
const killed = error instanceof Error && "signal" in error && error.signal === "SIGTERM";
|
|
18560
|
+
throw new CheckoutRequiresGitError(
|
|
18561
|
+
killed ? `git did not list the project's files in ${this.root} within ${this.listTimeoutMs / 1e3}s, so the box has no file set to serve. the checkout may be on a stalled filesystem, or this machine may be too loaded to start a subprocess.` : `could not list the project's files with git in ${this.root}: ${message}`
|
|
18562
|
+
);
|
|
18563
|
+
}
|
|
18564
|
+
if (stdout.length === 0) {
|
|
18565
|
+
throw new CheckoutRequiresGitError(
|
|
18566
|
+
`git listed no files in ${this.root}. either git tracks nothing there and nothing untracked is visible to it, or this machine could not read the child process's output.`
|
|
18567
|
+
);
|
|
18568
|
+
}
|
|
18569
|
+
const next = /* @__PURE__ */ new Map();
|
|
18570
|
+
const nextSniffed = /* @__PURE__ */ new Map();
|
|
18571
|
+
for (const relative of stdout.split("\0")) {
|
|
18572
|
+
if (!relative) continue;
|
|
18573
|
+
let stat2;
|
|
18574
|
+
try {
|
|
18575
|
+
stat2 = import_node_fs9.default.statSync(import_node_path10.default.join(this.root, relative));
|
|
18576
|
+
} catch {
|
|
18577
|
+
continue;
|
|
18578
|
+
}
|
|
18579
|
+
if (!stat2.isFile()) continue;
|
|
18580
|
+
const seen = this.sniffed.get(relative);
|
|
18581
|
+
const binary = seen && seen.size === stat2.size && seen.mtimeMs === stat2.mtimeMs ? seen.binary : looksBinary(import_node_path10.default.join(this.root, relative), stat2.size);
|
|
18582
|
+
nextSniffed.set(relative, { size: stat2.size, mtimeMs: stat2.mtimeMs, binary });
|
|
18583
|
+
next.set(relative, {
|
|
18584
|
+
size: stat2.size,
|
|
18585
|
+
// a checkout carries no write policy of its own; if the user can write
|
|
18586
|
+
// the file, so can the shell
|
|
18587
|
+
readOnly: false,
|
|
18588
|
+
binary
|
|
18589
|
+
});
|
|
18590
|
+
}
|
|
18591
|
+
this.entries = next;
|
|
18592
|
+
this.sniffed = nextSniffed;
|
|
18593
|
+
}
|
|
18594
|
+
absolute(planePath) {
|
|
18595
|
+
const resolved = import_node_path10.default.resolve(this.root, planePath);
|
|
18596
|
+
if (resolved !== this.root && !resolved.startsWith(`${this.root}${import_node_path10.default.sep}`)) {
|
|
18597
|
+
throw new Error(`path escapes the project: ${planePath}`);
|
|
18598
|
+
}
|
|
18599
|
+
return resolved;
|
|
18600
|
+
}
|
|
18601
|
+
async read(planePath) {
|
|
18602
|
+
return import_node_fs9.default.promises.readFile(this.absolute(planePath), "utf8");
|
|
18603
|
+
}
|
|
18604
|
+
async readBytes(planePath) {
|
|
18605
|
+
return import_node_fs9.default.promises.readFile(this.absolute(planePath));
|
|
18606
|
+
}
|
|
18607
|
+
async write(planePath, content) {
|
|
18608
|
+
const absolute = this.absolute(planePath);
|
|
18609
|
+
await import_node_fs9.default.promises.mkdir(import_node_path10.default.dirname(absolute), { recursive: true });
|
|
18610
|
+
await import_node_fs9.default.promises.writeFile(absolute, content);
|
|
18611
|
+
this.entries.set(planePath, {
|
|
18612
|
+
size: content.byteLength,
|
|
18613
|
+
readOnly: false,
|
|
18614
|
+
// the bytes are in hand, so the same NUL test costs nothing here
|
|
18615
|
+
binary: content.subarray(0, BINARY_SNIFF_BYTES).includes(0)
|
|
18616
|
+
});
|
|
18617
|
+
}
|
|
18618
|
+
async delete(planePath) {
|
|
18619
|
+
await import_node_fs9.default.promises.rm(this.absolute(planePath), { force: true });
|
|
18620
|
+
this.entries.delete(planePath);
|
|
18621
|
+
}
|
|
18622
|
+
};
|
|
18623
|
+
}
|
|
18624
|
+
});
|
|
18625
|
+
|
|
18626
|
+
// src/host/plane-host.ts
|
|
18627
|
+
var import_node_fs10, import_node_path11, import_plane, WS_OPEN2, PlaneNotRegisteredError, PlaneHost;
|
|
18628
|
+
var init_plane_host = __esm({
|
|
18629
|
+
"src/host/plane-host.ts"() {
|
|
18630
|
+
"use strict";
|
|
18631
|
+
import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
18632
|
+
import_node_path11 = __toESM(require("node:path"), 1);
|
|
18633
|
+
import_plane = require("@contrast/harness/plane");
|
|
18634
|
+
init_checkout_plane();
|
|
18635
|
+
WS_OPEN2 = 1;
|
|
18636
|
+
PlaneNotRegisteredError = class extends Error {
|
|
18637
|
+
};
|
|
18638
|
+
PlaneHost = class {
|
|
18639
|
+
// roots a box authorized, each tied to the socket that authorized it
|
|
18640
|
+
registered = /* @__PURE__ */ new Map();
|
|
18641
|
+
open = /* @__PURE__ */ new Map();
|
|
18642
|
+
byRoot = /* @__PURE__ */ new Map();
|
|
18643
|
+
nextPlaneId = 1;
|
|
18644
|
+
/** handle a plane:* message. returns true iff it was one. */
|
|
18645
|
+
async handleMessage(ws, msg) {
|
|
18646
|
+
if (typeof msg !== "object" || msg === null) return false;
|
|
18647
|
+
const record = { ...msg };
|
|
18648
|
+
const type = record.type;
|
|
18649
|
+
if (typeof type !== "string" || !type.startsWith("plane:")) return false;
|
|
18650
|
+
const id = record.id;
|
|
18651
|
+
try {
|
|
18652
|
+
this.respond(ws, id, await this.dispatch(ws, type, record));
|
|
18653
|
+
} catch (err) {
|
|
18654
|
+
const code = err instanceof PlaneNotRegisteredError ? "plane-not-registered" : void 0;
|
|
18655
|
+
this.respondError(ws, id, err instanceof Error ? err.message : String(err), code);
|
|
18656
|
+
}
|
|
18657
|
+
return true;
|
|
18658
|
+
}
|
|
18659
|
+
unregisterSocket(ws) {
|
|
18660
|
+
for (const [root, sockets] of [...this.registered]) {
|
|
18661
|
+
if (!sockets.delete(ws)) continue;
|
|
18662
|
+
if (sockets.size > 0) continue;
|
|
18663
|
+
this.registered.delete(root);
|
|
18664
|
+
const planeId = this.byRoot.get(root);
|
|
18665
|
+
if (planeId) {
|
|
18666
|
+
this.open.delete(planeId);
|
|
18667
|
+
this.byRoot.delete(root);
|
|
18668
|
+
}
|
|
18669
|
+
}
|
|
18670
|
+
for (const [planeId, entry] of [...this.open]) {
|
|
18671
|
+
entry.sockets.delete(ws);
|
|
18672
|
+
if (entry.sockets.size === 0 && !this.registered.has(entry.root)) {
|
|
18673
|
+
this.open.delete(planeId);
|
|
18674
|
+
this.byRoot.delete(entry.root);
|
|
18675
|
+
}
|
|
18676
|
+
}
|
|
18677
|
+
}
|
|
18678
|
+
/** roots currently reachable, for the daemon's status output. */
|
|
18679
|
+
registeredRoots() {
|
|
18680
|
+
return [...this.registered.keys()];
|
|
18681
|
+
}
|
|
18682
|
+
async dispatch(ws, type, msg) {
|
|
18683
|
+
switch (type) {
|
|
18684
|
+
case "plane:register": {
|
|
18685
|
+
const root = this.realRoot(String(msg.root ?? ""));
|
|
18686
|
+
const sockets = this.registered.get(root) ?? /* @__PURE__ */ new Set();
|
|
18687
|
+
sockets.add(ws);
|
|
18688
|
+
this.registered.set(root, sockets);
|
|
18689
|
+
return { root, holders: sockets.size };
|
|
18690
|
+
}
|
|
18691
|
+
// READ ONLY, and that is the whole point of it existing beside the
|
|
18692
|
+
// `holders` field on plane:register.
|
|
18693
|
+
//
|
|
18694
|
+
// registration is the AUTHORIZATION step: it is what permits any page on
|
|
18695
|
+
// this machine to open that root over a loopback socket that CORS does
|
|
18696
|
+
// not protect. so a caller asking "is anyone else in this checkout"
|
|
18697
|
+
// cannot be made to authorize the root in order to find out, even
|
|
18698
|
+
// briefly. it also means the count is the honest one: no box reads 0 and
|
|
18699
|
+
// a single box reads 1, where asking through register would have made
|
|
18700
|
+
// every answer one higher and forced a threshold that counts the asker.
|
|
18701
|
+
case "plane:status": {
|
|
18702
|
+
const root = this.realRoot(String(msg.root ?? ""));
|
|
18703
|
+
const sockets = this.registered.get(root);
|
|
18704
|
+
return { root, holders: sockets?.size ?? 0, registered: Boolean(sockets) };
|
|
18705
|
+
}
|
|
18706
|
+
case "plane:open": {
|
|
18707
|
+
const root = this.realRoot(String(msg.root ?? ""));
|
|
18708
|
+
if (!this.registered.has(root)) {
|
|
18709
|
+
throw new PlaneNotRegisteredError(
|
|
18710
|
+
`no box has registered ${root}; start one with \`rnx box\` there`
|
|
18711
|
+
);
|
|
18712
|
+
}
|
|
18713
|
+
const existingId = this.byRoot.get(root);
|
|
18714
|
+
const existing = existingId ? this.open.get(existingId) : void 0;
|
|
18715
|
+
if (existingId && existing) {
|
|
18716
|
+
existing.sockets.add(ws);
|
|
18717
|
+
return { planeId: existingId, version: existing.version };
|
|
18718
|
+
}
|
|
18719
|
+
const plane = new CheckoutFilePlane(root);
|
|
18720
|
+
await plane.refresh();
|
|
18721
|
+
const planeId = `plane-${this.nextPlaneId++}`;
|
|
18722
|
+
const entry = {
|
|
18723
|
+
root,
|
|
18724
|
+
plane,
|
|
18725
|
+
version: (0, import_plane.indexVersion)(plane.index()),
|
|
18726
|
+
sockets: /* @__PURE__ */ new Set([ws])
|
|
18727
|
+
};
|
|
18728
|
+
this.open.set(planeId, entry);
|
|
18729
|
+
this.byRoot.set(root, planeId);
|
|
18730
|
+
return { planeId, version: entry.version };
|
|
18731
|
+
}
|
|
18732
|
+
case "plane:close": {
|
|
18733
|
+
const entry = this.open.get(String(msg.planeId ?? ""));
|
|
18734
|
+
if (entry) entry.sockets.delete(ws);
|
|
18735
|
+
return { ok: true };
|
|
18736
|
+
}
|
|
18737
|
+
default: {
|
|
18738
|
+
const entry = this.entry(msg);
|
|
18739
|
+
const handled = await (0, import_plane.dispatchPlaneCommand)(entry.plane, type, msg);
|
|
18740
|
+
if (!handled) throw new Error(`unknown plane command: ${type}`);
|
|
18741
|
+
if (handled.version) entry.version = handled.version;
|
|
18742
|
+
return handled.result;
|
|
18743
|
+
}
|
|
18744
|
+
}
|
|
18745
|
+
}
|
|
18746
|
+
entry(msg) {
|
|
18747
|
+
const entry = this.open.get(String(msg.planeId ?? ""));
|
|
18748
|
+
if (!entry) throw new Error(`unknown planeId: ${String(msg.planeId)}`);
|
|
18749
|
+
return entry;
|
|
18750
|
+
}
|
|
18751
|
+
// resolve symlinks and relative segments before comparing, so a registered
|
|
18752
|
+
// root and an opened one cannot disagree about the same directory.
|
|
18753
|
+
realRoot(root) {
|
|
18754
|
+
if (!root) throw new Error("root is required");
|
|
18755
|
+
const resolved = import_node_path11.default.resolve(root);
|
|
18756
|
+
let real;
|
|
18757
|
+
try {
|
|
18758
|
+
real = import_node_fs10.default.realpathSync(resolved);
|
|
18759
|
+
} catch {
|
|
18760
|
+
throw new Error(`no such directory: ${resolved}`);
|
|
18761
|
+
}
|
|
18762
|
+
if (!import_node_fs10.default.statSync(real).isDirectory()) throw new Error(`not a directory: ${real}`);
|
|
18763
|
+
return real;
|
|
18764
|
+
}
|
|
18765
|
+
respond(ws, id, result) {
|
|
18766
|
+
if (ws.readyState !== WS_OPEN2) return;
|
|
18767
|
+
try {
|
|
18768
|
+
ws.send(JSON.stringify({ id, result }));
|
|
18769
|
+
} catch {
|
|
18770
|
+
}
|
|
18771
|
+
}
|
|
18772
|
+
respondError(ws, id, error, code) {
|
|
18773
|
+
if (ws.readyState !== WS_OPEN2) return;
|
|
18774
|
+
try {
|
|
18775
|
+
ws.send(JSON.stringify({ id, error, ...code ? { code } : {} }));
|
|
18776
|
+
} catch {
|
|
18777
|
+
}
|
|
18778
|
+
}
|
|
18779
|
+
};
|
|
18780
|
+
}
|
|
18781
|
+
});
|
|
18782
|
+
|
|
18454
18783
|
// src/host/replacement-module-handler.ts
|
|
18455
18784
|
function getReplacementLoader(filePath) {
|
|
18456
|
-
const ext =
|
|
18785
|
+
const ext = import_node_path12.default.extname(filePath).toLowerCase();
|
|
18457
18786
|
switch (ext) {
|
|
18458
18787
|
case ".js":
|
|
18459
18788
|
return "js";
|
|
@@ -18535,7 +18864,7 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
18535
18864
|
res.end("replacement files must be .js, .jsx, .ts, or .tsx");
|
|
18536
18865
|
return true;
|
|
18537
18866
|
}
|
|
18538
|
-
if (!
|
|
18867
|
+
if (!import_node_path12.default.isAbsolute(targetPath)) {
|
|
18539
18868
|
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
|
|
18540
18869
|
res.end("replacement file path must be absolute");
|
|
18541
18870
|
return true;
|
|
@@ -18543,10 +18872,10 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
18543
18872
|
const runtimePackages = new Set(url.searchParams.getAll("runtimePackage"));
|
|
18544
18873
|
let resolvedProjectRoot;
|
|
18545
18874
|
if (options.projectRoot) {
|
|
18546
|
-
const lexicalProjectRoot =
|
|
18875
|
+
const lexicalProjectRoot = import_node_path12.default.resolve(options.projectRoot);
|
|
18547
18876
|
resolvedProjectRoot = await import_promises5.default.realpath(options.projectRoot);
|
|
18548
|
-
const lexicalTarget =
|
|
18549
|
-
if (lexicalTarget.startsWith("..") ||
|
|
18877
|
+
const lexicalTarget = import_node_path12.default.relative(lexicalProjectRoot, targetPath);
|
|
18878
|
+
if (lexicalTarget.startsWith("..") || import_node_path12.default.isAbsolute(lexicalTarget)) {
|
|
18550
18879
|
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
18551
18880
|
res.end("replacement file must be inside the project root");
|
|
18552
18881
|
return true;
|
|
@@ -18562,8 +18891,8 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
|
|
|
18562
18891
|
return true;
|
|
18563
18892
|
}
|
|
18564
18893
|
if (resolvedProjectRoot) {
|
|
18565
|
-
const relativeTarget =
|
|
18566
|
-
if (relativeTarget.startsWith("..") ||
|
|
18894
|
+
const relativeTarget = import_node_path12.default.relative(resolvedProjectRoot, resolvedTargetPath);
|
|
18895
|
+
if (relativeTarget.startsWith("..") || import_node_path12.default.isAbsolute(relativeTarget)) {
|
|
18567
18896
|
res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
|
|
18568
18897
|
res.end("replacement file must be inside the project root");
|
|
18569
18898
|
return true;
|
|
@@ -18648,12 +18977,12 @@ exports.jsxDEV = exports.jsx`,
|
|
|
18648
18977
|
}
|
|
18649
18978
|
return true;
|
|
18650
18979
|
}
|
|
18651
|
-
var import_promises5,
|
|
18980
|
+
var import_promises5, import_node_path12, import_esbuild, REPLACEMENT_MODULE_ROUTE;
|
|
18652
18981
|
var init_replacement_module_handler = __esm({
|
|
18653
18982
|
"src/host/replacement-module-handler.ts"() {
|
|
18654
18983
|
"use strict";
|
|
18655
18984
|
import_promises5 = __toESM(require("node:fs/promises"), 1);
|
|
18656
|
-
|
|
18985
|
+
import_node_path12 = __toESM(require("node:path"), 1);
|
|
18657
18986
|
import_esbuild = require("esbuild");
|
|
18658
18987
|
init_backend_origin();
|
|
18659
18988
|
REPLACEMENT_MODULE_ROUTE = "/__sootsim-replacement-module";
|
|
@@ -18900,6 +19229,7 @@ var init_bridge_host = __esm({
|
|
|
18900
19229
|
init_agent_host();
|
|
18901
19230
|
init_fetch_proxy_handler();
|
|
18902
19231
|
init_open_url();
|
|
19232
|
+
init_plane_host();
|
|
18903
19233
|
init_replacement_module_handler();
|
|
18904
19234
|
init_websocket_proxy();
|
|
18905
19235
|
SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY = "require-corp";
|
|
@@ -18964,6 +19294,7 @@ var init_bridge_host = __esm({
|
|
|
18964
19294
|
nextCliFallbackId = 1;
|
|
18965
19295
|
cliIdleTimer = null;
|
|
18966
19296
|
agentHost;
|
|
19297
|
+
planeHost = new PlaneHost();
|
|
18967
19298
|
static CLI_IDLE_TIMEOUT_MS = 6e4;
|
|
18968
19299
|
static CLI_LEASE_TTL_MS = 6e5;
|
|
18969
19300
|
static USER_ACTIVE_LEASE_TTL_MS = 8e3;
|
|
@@ -19195,6 +19526,10 @@ var init_bridge_host = __esm({
|
|
|
19195
19526
|
void this.agentHost.handleMessage(ws, msg);
|
|
19196
19527
|
return;
|
|
19197
19528
|
}
|
|
19529
|
+
if (typeof msg.type === "string" && msg.type.startsWith("plane:")) {
|
|
19530
|
+
void this.planeHost.handleMessage(ws, msg);
|
|
19531
|
+
return;
|
|
19532
|
+
}
|
|
19198
19533
|
if (msg.type === "runtime:list") {
|
|
19199
19534
|
const versions = sootsimRuntime.listInstalled();
|
|
19200
19535
|
const active = this.getActiveRuntime();
|
|
@@ -19517,6 +19852,7 @@ var init_bridge_host = __esm({
|
|
|
19517
19852
|
});
|
|
19518
19853
|
ws.on("close", () => {
|
|
19519
19854
|
this.agentHost.unregisterSocket(ws);
|
|
19855
|
+
this.planeHost.unregisterSocket(ws);
|
|
19520
19856
|
if (role === "sim" && sim) {
|
|
19521
19857
|
this.rememberDisconnectedSim(sim);
|
|
19522
19858
|
if (this.primarySimId === sim.id) {
|
|
@@ -21214,17 +21550,17 @@ function liveDevBridgeLockfiles() {
|
|
|
21214
21550
|
return readDevBridgeLockfiles().filter((lockfile) => isDevBridgeLockfileFresh(lockfile));
|
|
21215
21551
|
}
|
|
21216
21552
|
function checkoutRoot(cwd) {
|
|
21217
|
-
let current =
|
|
21553
|
+
let current = import_node_path13.default.resolve(cwd);
|
|
21218
21554
|
while (true) {
|
|
21219
|
-
if (
|
|
21220
|
-
const parent =
|
|
21555
|
+
if (import_node_fs11.default.existsSync(import_node_path13.default.join(current, ".git"))) return current;
|
|
21556
|
+
const parent = import_node_path13.default.dirname(current);
|
|
21221
21557
|
if (parent === current) return null;
|
|
21222
21558
|
current = parent;
|
|
21223
21559
|
}
|
|
21224
21560
|
}
|
|
21225
21561
|
function pathContains(parent, child) {
|
|
21226
|
-
const relative =
|
|
21227
|
-
return relative === "" || relative !== ".." && !relative.startsWith(`..${
|
|
21562
|
+
const relative = import_node_path13.default.relative(parent, child);
|
|
21563
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${import_node_path13.default.sep}`) && !import_node_path13.default.isAbsolute(relative);
|
|
21228
21564
|
}
|
|
21229
21565
|
function resolveDefaultDevBridgeLockfile() {
|
|
21230
21566
|
const lockfiles = liveDevBridgeLockfiles();
|
|
@@ -21647,18 +21983,18 @@ async function evalInBridge(bridge, code, opts = {}) {
|
|
|
21647
21983
|
if (opts.acquireLock) payload.acquireLock = true;
|
|
21648
21984
|
return bridge.send(payload);
|
|
21649
21985
|
}
|
|
21650
|
-
async function callInBridge(bridge,
|
|
21651
|
-
return bridge.send({ type: "call", path:
|
|
21986
|
+
async function callInBridge(bridge, path20, ...args) {
|
|
21987
|
+
return bridge.send({ type: "call", path: path20, args });
|
|
21652
21988
|
}
|
|
21653
|
-
async function callInBridgeWrite(bridge,
|
|
21654
|
-
return bridge.send({ type: "call", path:
|
|
21989
|
+
async function callInBridgeWrite(bridge, path20, ...args) {
|
|
21990
|
+
return bridge.send({ type: "call", path: path20, args, acquireLock: true });
|
|
21655
21991
|
}
|
|
21656
|
-
var
|
|
21992
|
+
var import_node_fs11, import_node_path13, import_ws3, RNX_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError;
|
|
21657
21993
|
var init_ws_bridge = __esm({
|
|
21658
21994
|
"cli/ws-bridge.ts"() {
|
|
21659
21995
|
"use strict";
|
|
21660
|
-
|
|
21661
|
-
|
|
21996
|
+
import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
21997
|
+
import_node_path13 = __toESM(require("node:path"), 1);
|
|
21662
21998
|
import_ws3 = require("ws");
|
|
21663
21999
|
init_bridge_constants();
|
|
21664
22000
|
init_cli_constants();
|
|
@@ -21753,8 +22089,8 @@ function getDefaultPortForProtocol(protocol) {
|
|
|
21753
22089
|
return protocol === "https:" ? 443 : 80;
|
|
21754
22090
|
}
|
|
21755
22091
|
function isBaseServerUrl(url) {
|
|
21756
|
-
const
|
|
21757
|
-
return (
|
|
22092
|
+
const path20 = url.pathname || "/";
|
|
22093
|
+
return (path20 === "/" || path20 === "") && !url.search && !url.hash;
|
|
21758
22094
|
}
|
|
21759
22095
|
async function resolvePortViaServerScan(port) {
|
|
21760
22096
|
try {
|
|
@@ -21768,6 +22104,7 @@ async function resolvePortViaServerScan(port) {
|
|
|
21768
22104
|
(s) => !!s && typeof s === "object" && s.port === port && typeof s.bundleUrl === "string"
|
|
21769
22105
|
);
|
|
21770
22106
|
if (!match) return null;
|
|
22107
|
+
if (match.bundleUrlProvisional) return null;
|
|
21771
22108
|
return {
|
|
21772
22109
|
// normalize exactly like the manifest-probe branch below — the scan
|
|
21773
22110
|
// returns metro's manifest launchAsset url (lazy=true for code-split
|
|
@@ -21783,45 +22120,76 @@ async function resolvePortViaServerScan(port) {
|
|
|
21783
22120
|
return null;
|
|
21784
22121
|
}
|
|
21785
22122
|
}
|
|
21786
|
-
async function
|
|
21787
|
-
|
|
22123
|
+
async function probeExpoManifest(normalizedBaseUrl, port) {
|
|
22124
|
+
let body;
|
|
22125
|
+
const pending = fetchDevProbe(`${normalizedBaseUrl}/`, {
|
|
22126
|
+
headers: { "expo-platform": "ios" }
|
|
22127
|
+
}).then(
|
|
22128
|
+
async (res) => res.ok ? { ok: true, body: await res.text() } : null,
|
|
22129
|
+
() => void 0
|
|
22130
|
+
);
|
|
22131
|
+
const answered = await Promise.race([
|
|
22132
|
+
pending,
|
|
22133
|
+
new Promise(
|
|
22134
|
+
(resolve7) => setTimeout(() => resolve7("timeout"), MANIFEST_PROBE_TIMEOUT_MS).unref?.()
|
|
22135
|
+
)
|
|
22136
|
+
]);
|
|
22137
|
+
if (answered === "timeout" || answered === void 0) return { state: "no-answer" };
|
|
22138
|
+
if (answered === null) return { state: "no-manifest" };
|
|
22139
|
+
body = answered.body;
|
|
22140
|
+
if (!body.trim()) return { state: "no-answer" };
|
|
22141
|
+
let manifest;
|
|
21788
22142
|
try {
|
|
21789
|
-
|
|
21790
|
-
headers: { "expo-platform": "ios" }
|
|
21791
|
-
});
|
|
21792
|
-
if (manifestRes.ok) {
|
|
21793
|
-
const manifest = await manifestRes.json();
|
|
21794
|
-
const client = manifest?.extra?.expoClient || manifest?.extra || {};
|
|
21795
|
-
const rawLaunchUrl = typeof manifest?.launchAsset?.url === "string" ? manifest.launchAsset.url : void 0;
|
|
21796
|
-
const launchUrl2 = rawLaunchUrl ? alignLoopbackBundleUrlWithProbe(rawLaunchUrl, normalizedBaseUrl) : void 0;
|
|
21797
|
-
if (launchUrl2 || client.name) {
|
|
21798
|
-
return {
|
|
21799
|
-
bundleUrl: normalizeNativeDevBundleUrl(
|
|
21800
|
-
launchUrl2 || `${normalizedBaseUrl}${METRO_BUNDLE_PATH}`
|
|
21801
|
-
),
|
|
21802
|
-
port,
|
|
21803
|
-
framework: inferManifestFramework(launchUrl2, client.sdkVersion),
|
|
21804
|
-
projectName: client.name
|
|
21805
|
-
};
|
|
21806
|
-
}
|
|
21807
|
-
}
|
|
22143
|
+
manifest = JSON.parse(body);
|
|
21808
22144
|
} catch {
|
|
22145
|
+
return { state: "no-manifest" };
|
|
21809
22146
|
}
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
21813
|
-
|
|
21814
|
-
|
|
21815
|
-
|
|
21816
|
-
|
|
21817
|
-
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
22147
|
+
const client = manifest?.extra?.expoClient || manifest?.extra || {};
|
|
22148
|
+
const rawLaunchUrl = typeof manifest?.launchAsset?.url === "string" ? manifest.launchAsset.url : void 0;
|
|
22149
|
+
const launchUrl2 = rawLaunchUrl ? alignLoopbackBundleUrlWithProbe(rawLaunchUrl, normalizedBaseUrl) : void 0;
|
|
22150
|
+
if (!launchUrl2 && !client.name) return { state: "no-manifest" };
|
|
22151
|
+
return {
|
|
22152
|
+
state: "resolved",
|
|
22153
|
+
bundle: {
|
|
22154
|
+
bundleUrl: normalizeNativeDevBundleUrl(
|
|
22155
|
+
launchUrl2 || `${normalizedBaseUrl}${METRO_BUNDLE_PATH}`
|
|
22156
|
+
),
|
|
22157
|
+
port,
|
|
22158
|
+
framework: inferManifestFramework(launchUrl2, client.sdkVersion),
|
|
22159
|
+
projectName: client.name
|
|
21821
22160
|
}
|
|
22161
|
+
};
|
|
22162
|
+
}
|
|
22163
|
+
async function isPackagerRunning(normalizedBaseUrl) {
|
|
22164
|
+
try {
|
|
22165
|
+
const res = await fetchDevProbe(`${normalizedBaseUrl}/status`);
|
|
22166
|
+
if (!res.ok) return false;
|
|
22167
|
+
return (await res.text()).includes("packager-status:running");
|
|
21822
22168
|
} catch {
|
|
22169
|
+
return false;
|
|
21823
22170
|
}
|
|
21824
|
-
|
|
22171
|
+
}
|
|
22172
|
+
async function probeBaseUrlBundleDirect(baseUrl, port) {
|
|
22173
|
+
const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
|
|
22174
|
+
let manifest = await probeExpoManifest(normalizedBaseUrl, port);
|
|
22175
|
+
let packagerConfirmed = false;
|
|
22176
|
+
if (manifest.state === "no-answer") {
|
|
22177
|
+
packagerConfirmed = await isPackagerRunning(normalizedBaseUrl);
|
|
22178
|
+
if (!packagerConfirmed) return null;
|
|
22179
|
+
const deadline = Date.now() + MANIFEST_BOOT_BUDGET_MS;
|
|
22180
|
+
while (manifest.state === "no-answer" && Date.now() < deadline) {
|
|
22181
|
+
await new Promise((resolve7) => setTimeout(resolve7, MANIFEST_BOOT_RETRY_MS));
|
|
22182
|
+
manifest = await probeExpoManifest(normalizedBaseUrl, port);
|
|
22183
|
+
}
|
|
22184
|
+
}
|
|
22185
|
+
if (manifest.state === "resolved") return manifest.bundle;
|
|
22186
|
+
if (manifest.state === "no-answer") return null;
|
|
22187
|
+
if (!packagerConfirmed && !await isPackagerRunning(normalizedBaseUrl)) return null;
|
|
22188
|
+
return {
|
|
22189
|
+
bundleUrl: `${normalizedBaseUrl}${METRO_BUNDLE_PATH}`,
|
|
22190
|
+
port,
|
|
22191
|
+
framework: "metro"
|
|
22192
|
+
};
|
|
21825
22193
|
}
|
|
21826
22194
|
async function probeBaseUrlBundle(baseUrl, port) {
|
|
21827
22195
|
try {
|
|
@@ -21870,11 +22238,15 @@ async function resolveConnectionInput(input) {
|
|
|
21870
22238
|
}
|
|
21871
22239
|
return { bundleUrl: parsed.toString(), port, framework: "unknown" };
|
|
21872
22240
|
}
|
|
22241
|
+
var MANIFEST_PROBE_TIMEOUT_MS, MANIFEST_BOOT_BUDGET_MS, MANIFEST_BOOT_RETRY_MS;
|
|
21873
22242
|
var init_dev_bundle_resolution = __esm({
|
|
21874
22243
|
"src/dev-bundle-resolution.ts"() {
|
|
21875
22244
|
"use strict";
|
|
21876
22245
|
init_backend_origin();
|
|
21877
22246
|
init_native_dev_bundle_url();
|
|
22247
|
+
MANIFEST_PROBE_TIMEOUT_MS = 5e3;
|
|
22248
|
+
MANIFEST_BOOT_BUDGET_MS = 3e4;
|
|
22249
|
+
MANIFEST_BOOT_RETRY_MS = 1e3;
|
|
21878
22250
|
}
|
|
21879
22251
|
});
|
|
21880
22252
|
|
|
@@ -21985,9 +22357,9 @@ var init_profiles = __esm({
|
|
|
21985
22357
|
// cli/app-project.ts
|
|
21986
22358
|
function firstNamedFile(dir, names) {
|
|
21987
22359
|
for (const name2 of names) {
|
|
21988
|
-
const candidate =
|
|
22360
|
+
const candidate = import_node_path14.default.join(dir, name2);
|
|
21989
22361
|
try {
|
|
21990
|
-
if (
|
|
22362
|
+
if (import_node_fs12.default.statSync(candidate).isFile()) return candidate;
|
|
21991
22363
|
} catch {
|
|
21992
22364
|
}
|
|
21993
22365
|
}
|
|
@@ -22000,24 +22372,24 @@ function findSootSimAppConfig(dir) {
|
|
|
22000
22372
|
return firstNamedFile(dir, SOOTSIM_APP_CONFIG_NAMES);
|
|
22001
22373
|
}
|
|
22002
22374
|
function resolveAppProject(projectRoot) {
|
|
22003
|
-
const appDir =
|
|
22375
|
+
const appDir = import_node_path14.default.resolve(projectRoot);
|
|
22004
22376
|
try {
|
|
22005
|
-
if (!
|
|
22377
|
+
if (!import_node_fs12.default.statSync(appDir).isDirectory()) return null;
|
|
22006
22378
|
} catch {
|
|
22007
22379
|
return null;
|
|
22008
22380
|
}
|
|
22009
22381
|
const configPath = findSootSimAppConfig(appDir);
|
|
22010
|
-
if (!configPath && !findExpoAppConfig(appDir) && !
|
|
22382
|
+
if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs12.default.existsSync(import_node_path14.default.join(appDir, "package.json"))) {
|
|
22011
22383
|
return null;
|
|
22012
22384
|
}
|
|
22013
22385
|
return { appDir, configPath };
|
|
22014
22386
|
}
|
|
22015
|
-
var
|
|
22387
|
+
var import_node_fs12, import_node_path14, EXPO_APP_CONFIG_NAMES, SOOTSIM_APP_CONFIG_NAMES;
|
|
22016
22388
|
var init_app_project = __esm({
|
|
22017
22389
|
"cli/app-project.ts"() {
|
|
22018
22390
|
"use strict";
|
|
22019
|
-
|
|
22020
|
-
|
|
22391
|
+
import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
22392
|
+
import_node_path14 = __toESM(require("node:path"), 1);
|
|
22021
22393
|
EXPO_APP_CONFIG_NAMES = [
|
|
22022
22394
|
"app.config.js",
|
|
22023
22395
|
"app.config.ts",
|
|
@@ -22046,13 +22418,13 @@ function isSootSimConfig(value) {
|
|
|
22046
22418
|
}
|
|
22047
22419
|
function resolveConfigReplacementFiles(config, configPath) {
|
|
22048
22420
|
if (!config.modules) return config;
|
|
22049
|
-
const configDir =
|
|
22421
|
+
const configDir = import_node_path15.default.dirname(configPath);
|
|
22050
22422
|
return {
|
|
22051
22423
|
...config,
|
|
22052
22424
|
modules: Object.fromEntries(
|
|
22053
22425
|
Object.entries(config.modules).map(([name2, resolution]) => [
|
|
22054
22426
|
name2,
|
|
22055
|
-
resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file:
|
|
22427
|
+
resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file: import_node_path15.default.resolve(configDir, resolution.file) } : resolution
|
|
22056
22428
|
])
|
|
22057
22429
|
)
|
|
22058
22430
|
};
|
|
@@ -22082,12 +22454,12 @@ async function resolveSootSimAppConfig(startDir = process.cwd()) {
|
|
|
22082
22454
|
const project = resolveAppProject(startDir);
|
|
22083
22455
|
return { project, config: await loadSootSimAppConfig(project) };
|
|
22084
22456
|
}
|
|
22085
|
-
var import_node_module,
|
|
22457
|
+
var import_node_module, import_node_path15, import_jiti, require2;
|
|
22086
22458
|
var init_app_config = __esm({
|
|
22087
22459
|
"cli/app-config.ts"() {
|
|
22088
22460
|
"use strict";
|
|
22089
22461
|
import_node_module = require("node:module");
|
|
22090
|
-
|
|
22462
|
+
import_node_path15 = __toESM(require("node:path"), 1);
|
|
22091
22463
|
init_src();
|
|
22092
22464
|
import_jiti = require("jiti");
|
|
22093
22465
|
init_public_brand();
|
|
@@ -22155,13 +22527,13 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
22155
22527
|
scannedFontDirectories++;
|
|
22156
22528
|
let entries;
|
|
22157
22529
|
try {
|
|
22158
|
-
entries =
|
|
22530
|
+
entries = import_node_fs13.default.readdirSync(current.dir, { withFileTypes: true });
|
|
22159
22531
|
} catch {
|
|
22160
22532
|
continue;
|
|
22161
22533
|
}
|
|
22162
22534
|
for (const entry of entries) {
|
|
22163
22535
|
if (entry.isSymbolicLink()) continue;
|
|
22164
|
-
const fullPath =
|
|
22536
|
+
const fullPath = import_node_path16.default.join(current.dir, entry.name);
|
|
22165
22537
|
if (entry.isDirectory()) {
|
|
22166
22538
|
if (current.depth < 4 && pending.length < 64 && !entry.name.startsWith(".")) {
|
|
22167
22539
|
pending.push({ dir: fullPath, depth: current.depth + 1 });
|
|
@@ -22169,15 +22541,15 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
22169
22541
|
continue;
|
|
22170
22542
|
}
|
|
22171
22543
|
if (!entry.isFile() || !/\.(ttf|otf|woff|woff2)$/i.test(entry.name)) continue;
|
|
22172
|
-
const relative =
|
|
22173
|
-
fontPaths.push(
|
|
22544
|
+
const relative = import_node_path16.default.relative(root, fullPath).split(import_node_path16.default.sep).join("/");
|
|
22545
|
+
fontPaths.push(import_node_path16.default.posix.join(metroPathPrefix, relative));
|
|
22174
22546
|
if (fontPaths.length >= 256) break;
|
|
22175
22547
|
}
|
|
22176
22548
|
}
|
|
22177
22549
|
};
|
|
22178
22550
|
try {
|
|
22179
22551
|
const packageJson = JSON.parse(
|
|
22180
|
-
|
|
22552
|
+
import_node_fs13.default.readFileSync(import_node_path16.default.join(selectedAppDir, "package.json"), "utf8")
|
|
22181
22553
|
);
|
|
22182
22554
|
const dependencyNames = /* @__PURE__ */ new Set();
|
|
22183
22555
|
for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
|
|
@@ -22192,24 +22564,24 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
22192
22564
|
const config = Reflect.get(packageJson, "reactNativeVectorIcons");
|
|
22193
22565
|
const configuredFontDir = config && typeof config === "object" ? Reflect.get(config, "fontDir") : null;
|
|
22194
22566
|
const configuredDir = typeof configuredFontDir === "string" ? configuredFontDir : "rnvi-fonts";
|
|
22195
|
-
const root =
|
|
22196
|
-
const relativeRoot =
|
|
22197
|
-
if (!relativeRoot.startsWith("..") && !
|
|
22198
|
-
collectFontFiles(root, relativeRoot.split(
|
|
22567
|
+
const root = import_node_path16.default.resolve(selectedAppDir, configuredDir);
|
|
22568
|
+
const relativeRoot = import_node_path16.default.relative(selectedAppDir, root);
|
|
22569
|
+
if (!relativeRoot.startsWith("..") && !import_node_path16.default.isAbsolute(relativeRoot)) {
|
|
22570
|
+
collectFontFiles(root, relativeRoot.split(import_node_path16.default.sep).join("/"));
|
|
22199
22571
|
}
|
|
22200
|
-
const vectorIconRequire = (0, import_node_module2.createRequire)(
|
|
22572
|
+
const vectorIconRequire = (0, import_node_module2.createRequire)(import_node_path16.default.join(selectedAppDir, "package.json"));
|
|
22201
22573
|
for (const dependencyName of vectorIconDependencies) {
|
|
22202
22574
|
try {
|
|
22203
22575
|
const entryPath = vectorIconRequire.resolve(dependencyName);
|
|
22204
|
-
const dependencyPath = dependencyName.split("/").join(
|
|
22205
|
-
const marker = `${
|
|
22576
|
+
const dependencyPath = dependencyName.split("/").join(import_node_path16.default.sep);
|
|
22577
|
+
const marker = `${import_node_path16.default.sep}node_modules${import_node_path16.default.sep}${dependencyPath}${import_node_path16.default.sep}`;
|
|
22206
22578
|
const markerIndex = entryPath.lastIndexOf(marker);
|
|
22207
22579
|
if (markerIndex === -1) continue;
|
|
22208
22580
|
const packageRoot = entryPath.slice(0, markerIndex + marker.length - 1);
|
|
22209
22581
|
const fontsDir = dependencyName === "react-native-vector-icons" ? "Fonts" : "fonts";
|
|
22210
22582
|
collectFontFiles(
|
|
22211
|
-
|
|
22212
|
-
|
|
22583
|
+
import_node_path16.default.join(packageRoot, fontsDir),
|
|
22584
|
+
import_node_path16.default.posix.join("node_modules", dependencyName, fontsDir)
|
|
22213
22585
|
);
|
|
22214
22586
|
} catch {
|
|
22215
22587
|
}
|
|
@@ -22218,37 +22590,37 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
22218
22590
|
} catch {
|
|
22219
22591
|
}
|
|
22220
22592
|
try {
|
|
22221
|
-
const configPath =
|
|
22222
|
-
if (
|
|
22223
|
-
const appConfigRequire = (0, import_node_module2.createRequire)(
|
|
22593
|
+
const configPath = import_node_path16.default.join(selectedAppDir, "react-native.config.js");
|
|
22594
|
+
if (import_node_fs13.default.statSync(configPath).isFile()) {
|
|
22595
|
+
const appConfigRequire = (0, import_node_module2.createRequire)(import_node_path16.default.join(selectedAppDir, "package.json"));
|
|
22224
22596
|
const rnConfig = appConfigRequire(configPath);
|
|
22225
22597
|
const assets = rnConfig && typeof rnConfig === "object" ? Reflect.get(rnConfig, "assets") : null;
|
|
22226
22598
|
if (Array.isArray(assets)) {
|
|
22227
22599
|
for (const assetDir of assets) {
|
|
22228
22600
|
if (typeof assetDir !== "string") continue;
|
|
22229
|
-
const root =
|
|
22230
|
-
const relativeRoot =
|
|
22231
|
-
if (relativeRoot.startsWith("..") ||
|
|
22232
|
-
collectFontFiles(root, relativeRoot.split(
|
|
22601
|
+
const root = import_node_path16.default.resolve(selectedAppDir, assetDir);
|
|
22602
|
+
const relativeRoot = import_node_path16.default.relative(selectedAppDir, root);
|
|
22603
|
+
if (relativeRoot.startsWith("..") || import_node_path16.default.isAbsolute(relativeRoot)) continue;
|
|
22604
|
+
collectFontFiles(root, relativeRoot.split(import_node_path16.default.sep).join("/"));
|
|
22233
22605
|
}
|
|
22234
22606
|
}
|
|
22235
22607
|
}
|
|
22236
22608
|
} catch {
|
|
22237
22609
|
}
|
|
22238
22610
|
if (platform === "ios") {
|
|
22239
|
-
const iosDir =
|
|
22611
|
+
const iosDir = import_node_path16.default.join(selectedAppDir, "ios");
|
|
22240
22612
|
try {
|
|
22241
|
-
const targetDirs =
|
|
22613
|
+
const targetDirs = import_node_fs13.default.readdirSync(iosDir, { withFileTypes: true }).filter(
|
|
22242
22614
|
(entry) => entry.isDirectory() && !entry.isSymbolicLink() && entry.name !== "Pods" && entry.name !== "build" && !entry.name.startsWith(".")
|
|
22243
22615
|
).slice(0, 64);
|
|
22244
|
-
const plistPaths = [
|
|
22616
|
+
const plistPaths = [import_node_path16.default.join(iosDir, "Info.plist")];
|
|
22245
22617
|
for (const entry of targetDirs) {
|
|
22246
|
-
plistPaths.push(
|
|
22618
|
+
plistPaths.push(import_node_path16.default.join(iosDir, entry.name, "Info.plist"));
|
|
22247
22619
|
}
|
|
22248
22620
|
for (const plistPath of plistPaths) {
|
|
22249
22621
|
let parsed;
|
|
22250
22622
|
try {
|
|
22251
|
-
parsed = parsePlistSource(
|
|
22623
|
+
parsed = parsePlistSource(import_node_fs13.default.readFileSync(plistPath, "utf8"));
|
|
22252
22624
|
} catch {
|
|
22253
22625
|
continue;
|
|
22254
22626
|
}
|
|
@@ -22258,21 +22630,21 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
22258
22630
|
for (const declaredFont of declaredFonts) {
|
|
22259
22631
|
if (typeof declaredFont !== "string") continue;
|
|
22260
22632
|
const candidates = [
|
|
22261
|
-
|
|
22262
|
-
|
|
22633
|
+
import_node_path16.default.resolve(import_node_path16.default.dirname(plistPath), declaredFont),
|
|
22634
|
+
import_node_path16.default.resolve(iosDir, declaredFont)
|
|
22263
22635
|
];
|
|
22264
22636
|
const fontPath = candidates.find((candidate) => {
|
|
22265
|
-
const relative =
|
|
22266
|
-
if (relative.startsWith("..") ||
|
|
22637
|
+
const relative = import_node_path16.default.relative(selectedAppDir, candidate);
|
|
22638
|
+
if (relative.startsWith("..") || import_node_path16.default.isAbsolute(relative)) return false;
|
|
22267
22639
|
try {
|
|
22268
|
-
return
|
|
22640
|
+
return import_node_fs13.default.statSync(candidate).isFile();
|
|
22269
22641
|
} catch {
|
|
22270
22642
|
return false;
|
|
22271
22643
|
}
|
|
22272
22644
|
});
|
|
22273
22645
|
if (!fontPath) continue;
|
|
22274
22646
|
fontPaths.push(
|
|
22275
|
-
|
|
22647
|
+
import_node_path16.default.relative(selectedAppDir, fontPath).split(import_node_path16.default.sep).join("/")
|
|
22276
22648
|
);
|
|
22277
22649
|
}
|
|
22278
22650
|
}
|
|
@@ -22311,13 +22683,13 @@ async function resolveMetroProjectRoot(bundleUrl, opts) {
|
|
|
22311
22683
|
function encodeAppFontsWire(specs) {
|
|
22312
22684
|
return specs.map((spec) => `${encodeURIComponent(spec.url)}::${encodeURIComponent(spec.family)}`).join(",");
|
|
22313
22685
|
}
|
|
22314
|
-
var
|
|
22686
|
+
var import_node_fs13, import_node_module2, import_node_path16, import_config_plugin_fonts, require3;
|
|
22315
22687
|
var init_app_fonts = __esm({
|
|
22316
22688
|
"cli/app-fonts.ts"() {
|
|
22317
22689
|
"use strict";
|
|
22318
|
-
|
|
22690
|
+
import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
22319
22691
|
import_node_module2 = require("node:module");
|
|
22320
|
-
|
|
22692
|
+
import_node_path16 = __toESM(require("node:path"), 1);
|
|
22321
22693
|
import_config_plugin_fonts = require("sootsim-engine/engine/config-plugin-fonts");
|
|
22322
22694
|
init_dev_server_scanner();
|
|
22323
22695
|
init_plist();
|
|
@@ -23408,7 +23780,7 @@ function resolvePlaywright() {
|
|
|
23408
23780
|
try {
|
|
23409
23781
|
const modulePath = requireFromRoot.resolve(spec);
|
|
23410
23782
|
const packageJsonPath = requireFromRoot.resolve(`${spec}/package.json`);
|
|
23411
|
-
const parsed = JSON.parse((0,
|
|
23783
|
+
const parsed = JSON.parse((0, import_node_fs14.readFileSync)(packageJsonPath, "utf8"));
|
|
23412
23784
|
if (!isRecord3(parsed) || typeof parsed.version !== "string") continue;
|
|
23413
23785
|
const bin = parsed.bin;
|
|
23414
23786
|
let binPath = null;
|
|
@@ -23420,8 +23792,8 @@ function resolvePlaywright() {
|
|
|
23420
23792
|
binPath = typeof named === "string" ? named : typeof first === "string" ? first : null;
|
|
23421
23793
|
}
|
|
23422
23794
|
if (!binPath) continue;
|
|
23423
|
-
const cliPath = (0,
|
|
23424
|
-
if (!(0,
|
|
23795
|
+
const cliPath = (0, import_node_path17.join)((0, import_node_path17.dirname)(packageJsonPath), binPath);
|
|
23796
|
+
if (!(0, import_node_fs14.existsSync)(cliPath)) continue;
|
|
23425
23797
|
return {
|
|
23426
23798
|
spec,
|
|
23427
23799
|
modulePath,
|
|
@@ -23437,7 +23809,7 @@ function resolvePlaywright() {
|
|
|
23437
23809
|
return null;
|
|
23438
23810
|
}
|
|
23439
23811
|
function probeBrowser(resolved, env) {
|
|
23440
|
-
const probe3 = (0,
|
|
23812
|
+
const probe3 = (0, import_node_child_process6.spawnSync)(process.execPath, ["-e", PLAYWRIGHT_BROWSER_PROBE], {
|
|
23441
23813
|
env: {
|
|
23442
23814
|
...env,
|
|
23443
23815
|
SOOTSIM_PW_MODULE: resolved.modulePath
|
|
@@ -23460,7 +23832,7 @@ function probeBrowser(resolved, env) {
|
|
|
23460
23832
|
return {
|
|
23461
23833
|
ok: true,
|
|
23462
23834
|
executablePath: parsed.executablePath,
|
|
23463
|
-
exists: parsed.exists && (0,
|
|
23835
|
+
exists: parsed.exists && (0, import_node_fs14.existsSync)(parsed.executablePath)
|
|
23464
23836
|
};
|
|
23465
23837
|
} catch (error) {
|
|
23466
23838
|
return {
|
|
@@ -23475,7 +23847,7 @@ function ensurePlaywrightBrowser(resolved, env = process.env) {
|
|
|
23475
23847
|
if (before.exists) {
|
|
23476
23848
|
return { ok: true, executablePath: before.executablePath, installed: false };
|
|
23477
23849
|
}
|
|
23478
|
-
const install = (0,
|
|
23850
|
+
const install = (0, import_node_child_process6.spawnSync)(process.execPath, [resolved.cliPath, "install", "chromium"], {
|
|
23479
23851
|
env,
|
|
23480
23852
|
encoding: "utf8",
|
|
23481
23853
|
timeout: 10 * 6e4
|
|
@@ -23499,14 +23871,14 @@ ${detail}` : ""}`
|
|
|
23499
23871
|
}
|
|
23500
23872
|
return { ok: true, executablePath: after.executablePath, installed: true };
|
|
23501
23873
|
}
|
|
23502
|
-
var
|
|
23874
|
+
var import_node_child_process6, import_node_fs14, import_node_module4, import_node_path17, PLAYWRIGHT_BROWSER_PROBE;
|
|
23503
23875
|
var init_playwright_provisioning = __esm({
|
|
23504
23876
|
"cli/drivers/playwright-provisioning.ts"() {
|
|
23505
23877
|
"use strict";
|
|
23506
|
-
|
|
23507
|
-
|
|
23878
|
+
import_node_child_process6 = require("node:child_process");
|
|
23879
|
+
import_node_fs14 = require("node:fs");
|
|
23508
23880
|
import_node_module4 = require("node:module");
|
|
23509
|
-
|
|
23881
|
+
import_node_path17 = require("node:path");
|
|
23510
23882
|
PLAYWRIGHT_BROWSER_PROBE = `
|
|
23511
23883
|
const { existsSync } = require('node:fs');
|
|
23512
23884
|
const modulePath = process.env.SOOTSIM_PW_MODULE;
|
|
@@ -24182,6 +24554,30 @@ var init_open_url2 = __esm({
|
|
|
24182
24554
|
}
|
|
24183
24555
|
});
|
|
24184
24556
|
|
|
24557
|
+
// cli/run-rnx.ts
|
|
24558
|
+
function rethrowIfExit(error) {
|
|
24559
|
+
if (error instanceof RnxExit) throw error;
|
|
24560
|
+
}
|
|
24561
|
+
function rnxExit(code) {
|
|
24562
|
+
throw new RnxExit(code);
|
|
24563
|
+
}
|
|
24564
|
+
var import_node_async_hooks, RnxExit, sinks;
|
|
24565
|
+
var init_run_rnx = __esm({
|
|
24566
|
+
"cli/run-rnx.ts"() {
|
|
24567
|
+
"use strict";
|
|
24568
|
+
import_node_async_hooks = require("node:async_hooks");
|
|
24569
|
+
RnxExit = class extends Error {
|
|
24570
|
+
code;
|
|
24571
|
+
constructor(code) {
|
|
24572
|
+
super(`rnx exited with code ${code}`);
|
|
24573
|
+
this.name = "RnxExit";
|
|
24574
|
+
this.code = code;
|
|
24575
|
+
}
|
|
24576
|
+
};
|
|
24577
|
+
sinks = new import_node_async_hooks.AsyncLocalStorage();
|
|
24578
|
+
}
|
|
24579
|
+
});
|
|
24580
|
+
|
|
24185
24581
|
// cli/commands/inspect/env.ts
|
|
24186
24582
|
function isAgentEnv() {
|
|
24187
24583
|
if (process.env.SOOTSIM_AGENT === "0") return false;
|
|
@@ -24285,7 +24681,7 @@ async function runRuntime(args, opts = {}) {
|
|
|
24285
24681
|
default:
|
|
24286
24682
|
console.error(` unknown runtime subcommand: ${sub}`);
|
|
24287
24683
|
printHelp();
|
|
24288
|
-
|
|
24684
|
+
rnxExit(1);
|
|
24289
24685
|
}
|
|
24290
24686
|
}
|
|
24291
24687
|
function printHelp() {
|
|
@@ -24342,7 +24738,7 @@ async function runtimeInstall(args, opts) {
|
|
|
24342
24738
|
return result;
|
|
24343
24739
|
} catch (err) {
|
|
24344
24740
|
console.error(` ${describeError(err)}`);
|
|
24345
|
-
|
|
24741
|
+
rnxExit(1);
|
|
24346
24742
|
}
|
|
24347
24743
|
}
|
|
24348
24744
|
async function activateVersion(version) {
|
|
@@ -24433,14 +24829,14 @@ async function runtimeUse(args) {
|
|
|
24433
24829
|
const version = args[0];
|
|
24434
24830
|
if (!version) {
|
|
24435
24831
|
console.error(` usage: rnx runtime use <version>`);
|
|
24436
|
-
|
|
24832
|
+
rnxExit(1);
|
|
24437
24833
|
}
|
|
24438
24834
|
const installed2 = sootsimRuntime.listInstalled();
|
|
24439
24835
|
if (!installed2.includes(version)) {
|
|
24440
24836
|
console.error(` version ${version} is not installed`);
|
|
24441
24837
|
console.error(` installed: ${installed2.join(", ") || "(none)"}`);
|
|
24442
24838
|
console.error(` run \`rnx runtime install ${version}\` first`);
|
|
24443
|
-
|
|
24839
|
+
rnxExit(1);
|
|
24444
24840
|
}
|
|
24445
24841
|
await activateVersion(version);
|
|
24446
24842
|
}
|
|
@@ -24448,7 +24844,7 @@ async function runtimeRemove(args) {
|
|
|
24448
24844
|
const version = args[0];
|
|
24449
24845
|
if (!version) {
|
|
24450
24846
|
console.error(` usage: rnx runtime remove <version>`);
|
|
24451
|
-
|
|
24847
|
+
rnxExit(1);
|
|
24452
24848
|
}
|
|
24453
24849
|
const active = readActiveRuntime();
|
|
24454
24850
|
if (active === version) {
|
|
@@ -24456,11 +24852,11 @@ async function runtimeRemove(args) {
|
|
|
24456
24852
|
console.error(
|
|
24457
24853
|
` switch with \`rnx runtime use <other>\` first, or install another version`
|
|
24458
24854
|
);
|
|
24459
|
-
|
|
24855
|
+
rnxExit(1);
|
|
24460
24856
|
}
|
|
24461
24857
|
if (readLiveRuntimeVersions().includes(version)) {
|
|
24462
24858
|
console.error(` cannot remove runtime ${version} while a project is using it`);
|
|
24463
|
-
|
|
24859
|
+
rnxExit(1);
|
|
24464
24860
|
}
|
|
24465
24861
|
const dir = runtimeDir(version);
|
|
24466
24862
|
if (!import_fs8.default.existsSync(dir)) {
|
|
@@ -24481,7 +24877,7 @@ async function runtimeWhich() {
|
|
|
24481
24877
|
async function runtimeNotes(args) {
|
|
24482
24878
|
if (args.length > 0) {
|
|
24483
24879
|
console.error(` usage: rnx runtime notes`);
|
|
24484
|
-
|
|
24880
|
+
rnxExit(1);
|
|
24485
24881
|
}
|
|
24486
24882
|
const { config } = await resolveSootSimAppConfig();
|
|
24487
24883
|
const version = config?.runtimeVersion ?? readActiveRuntime();
|
|
@@ -24532,6 +24928,7 @@ var init_runtime = __esm({
|
|
|
24532
24928
|
init_home_paths();
|
|
24533
24929
|
init_runtime_delivery();
|
|
24534
24930
|
init_app_config();
|
|
24931
|
+
init_run_rnx();
|
|
24535
24932
|
init_runtime_notes();
|
|
24536
24933
|
init_ws_bridge();
|
|
24537
24934
|
}
|
|
@@ -24656,21 +25053,21 @@ function assertExplicitBridgeLock(preferredPort, explicitPort, lock) {
|
|
|
24656
25053
|
}
|
|
24657
25054
|
async function ensureRuntimeForOpen() {
|
|
24658
25055
|
const active = readActiveRuntime();
|
|
24659
|
-
if (active &&
|
|
25056
|
+
if (active && import_node_fs15.default.existsSync(runtimeDir(active))) return;
|
|
24660
25057
|
console.error(" installing rnx engine runtime...");
|
|
24661
25058
|
const { runRuntime: runRuntime2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
|
|
24662
25059
|
await runRuntime2(["install"], {});
|
|
24663
25060
|
}
|
|
24664
25061
|
function spawnSootsim(args) {
|
|
24665
25062
|
const entry = process.argv[1];
|
|
24666
|
-
if (entry &&
|
|
24667
|
-
return (0,
|
|
25063
|
+
if (entry && import_node_fs15.default.existsSync(entry)) {
|
|
25064
|
+
return (0, import_node_child_process7.spawn)(process.execPath, [entry, ...args], {
|
|
24668
25065
|
detached: true,
|
|
24669
25066
|
stdio: "ignore",
|
|
24670
25067
|
env: process.env
|
|
24671
25068
|
});
|
|
24672
25069
|
}
|
|
24673
|
-
return (0,
|
|
25070
|
+
return (0, import_node_child_process7.spawn)(rnxPublicBrand.commandName, args, {
|
|
24674
25071
|
detached: true,
|
|
24675
25072
|
stdio: "ignore",
|
|
24676
25073
|
env: process.env
|
|
@@ -24751,7 +25148,7 @@ async function resolveConnectionInputForCli(target) {
|
|
|
24751
25148
|
const registeredPort = /^\d+$/.test(normalized) ? Number(normalized) : localBasePort(normalized);
|
|
24752
25149
|
if (registeredPort && registeredPort > 0) {
|
|
24753
25150
|
const discovered = await probePort(registeredPort);
|
|
24754
|
-
if (discovered) {
|
|
25151
|
+
if (discovered && !discovered.bundleUrlProvisional) {
|
|
24755
25152
|
return {
|
|
24756
25153
|
bundleUrl: discovered.bundleUrl,
|
|
24757
25154
|
port: discovered.port,
|
|
@@ -24810,10 +25207,10 @@ async function buildResolvedBundleOpenUrl(target, baseUrl, opts = {}) {
|
|
|
24810
25207
|
}
|
|
24811
25208
|
function normalizeReplacementPath(filePath) {
|
|
24812
25209
|
if (filePath.startsWith("~/")) {
|
|
24813
|
-
return
|
|
25210
|
+
return import_node_path18.default.join(import_node_os3.default.homedir(), filePath.slice(2));
|
|
24814
25211
|
}
|
|
24815
|
-
if (
|
|
24816
|
-
return
|
|
25212
|
+
if (import_node_path18.default.isAbsolute(filePath)) return filePath;
|
|
25213
|
+
return import_node_path18.default.resolve(process.cwd(), filePath);
|
|
24817
25214
|
}
|
|
24818
25215
|
function parseOpenRuntimeConfig(args) {
|
|
24819
25216
|
const modules = {};
|
|
@@ -24823,18 +25220,18 @@ function parseOpenRuntimeConfig(args) {
|
|
|
24823
25220
|
const raw = args[i + 1];
|
|
24824
25221
|
if (!raw) {
|
|
24825
25222
|
console.error(" rnx open: --replace expects <module>=<file>");
|
|
24826
|
-
|
|
25223
|
+
rnxExit(1);
|
|
24827
25224
|
}
|
|
24828
25225
|
const eqIndex = raw.indexOf("=");
|
|
24829
25226
|
if (eqIndex <= 0 || eqIndex === raw.length - 1) {
|
|
24830
25227
|
console.error(" rnx open: --replace expects <module>=<file>");
|
|
24831
|
-
|
|
25228
|
+
rnxExit(1);
|
|
24832
25229
|
}
|
|
24833
25230
|
const moduleName = raw.slice(0, eqIndex).trim();
|
|
24834
25231
|
const filePath = normalizeReplacementPath(raw.slice(eqIndex + 1).trim());
|
|
24835
|
-
if (!
|
|
25232
|
+
if (!import_node_fs15.default.existsSync(filePath)) {
|
|
24836
25233
|
console.error(` rnx open: replacement file not found: ${filePath}`);
|
|
24837
|
-
|
|
25234
|
+
rnxExit(1);
|
|
24838
25235
|
}
|
|
24839
25236
|
modules[moduleName] = { file: filePath };
|
|
24840
25237
|
i++;
|
|
@@ -24845,7 +25242,7 @@ function parseOpenRuntimeConfig(args) {
|
|
|
24845
25242
|
const eqIndex = raw ? raw.indexOf("=") : -1;
|
|
24846
25243
|
if (!raw || eqIndex <= 0 || eqIndex === raw.length - 1) {
|
|
24847
25244
|
console.error(" rnx open: --remap expects <host:port>=<host:port>");
|
|
24848
|
-
|
|
25245
|
+
rnxExit(1);
|
|
24849
25246
|
}
|
|
24850
25247
|
remap[raw.slice(0, eqIndex).trim()] = raw.slice(eqIndex + 1).trim();
|
|
24851
25248
|
i++;
|
|
@@ -24863,7 +25260,7 @@ async function resolveOpenAppProject(resolvedBundle) {
|
|
|
24863
25260
|
return advertisedRoot ? resolveAppProject(advertisedRoot) : null;
|
|
24864
25261
|
}
|
|
24865
25262
|
async function ensureConfiguredRuntime(version) {
|
|
24866
|
-
if (
|
|
25263
|
+
if (import_node_fs15.default.existsSync(import_node_path18.default.join(runtimeDir(version), "index.html"))) return;
|
|
24867
25264
|
console.error(` installing configured engine runtime ${version}...`);
|
|
24868
25265
|
const result = await sootsimRuntime.install({
|
|
24869
25266
|
version,
|
|
@@ -25223,7 +25620,7 @@ function playwrightHostPidForSim(sim) {
|
|
|
25223
25620
|
function signalDriverLaunchConnected(result) {
|
|
25224
25621
|
if (!result.connectAckFile) return false;
|
|
25225
25622
|
try {
|
|
25226
|
-
|
|
25623
|
+
import_node_fs15.default.writeFileSync(
|
|
25227
25624
|
result.connectAckFile,
|
|
25228
25625
|
`${JSON.stringify({ connectedAt: Date.now(), pid: result.pid ?? null })}
|
|
25229
25626
|
`,
|
|
@@ -25237,19 +25634,19 @@ function signalDriverLaunchConnected(result) {
|
|
|
25237
25634
|
function printDriverDiagnosticLogTail(result) {
|
|
25238
25635
|
if (!result.diagnosticLogPath) return;
|
|
25239
25636
|
try {
|
|
25240
|
-
const detail =
|
|
25637
|
+
const detail = import_node_fs15.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
|
|
25241
25638
|
if (!detail) {
|
|
25242
|
-
console.error(` ${
|
|
25639
|
+
console.error(` ${import_node_path18.default.basename(result.diagnosticLogPath)} was empty`);
|
|
25243
25640
|
return;
|
|
25244
25641
|
}
|
|
25245
25642
|
const shown = detail.length > 4e3 ? `\u2026
|
|
25246
25643
|
${detail.slice(-4e3)}` : detail;
|
|
25247
|
-
console.error(` ${
|
|
25644
|
+
console.error(` ${import_node_path18.default.basename(result.diagnosticLogPath)}:`);
|
|
25248
25645
|
console.error(shown);
|
|
25249
25646
|
} catch (err) {
|
|
25250
25647
|
const message = err instanceof Error ? err.message : String(err);
|
|
25251
25648
|
console.error(
|
|
25252
|
-
` failed to read ${
|
|
25649
|
+
` failed to read ${import_node_path18.default.basename(result.diagnosticLogPath)}: ${message}`
|
|
25253
25650
|
);
|
|
25254
25651
|
}
|
|
25255
25652
|
}
|
|
@@ -25270,11 +25667,11 @@ async function waitForProcessExit(pid, timeoutMs = 2500) {
|
|
|
25270
25667
|
return !isProcessAlive2(pid);
|
|
25271
25668
|
}
|
|
25272
25669
|
function isPlaywrightHostProcess(pid) {
|
|
25273
|
-
const plain = (0,
|
|
25670
|
+
const plain = (0, import_node_child_process7.spawnSync)("ps", ["-o", "command=", "-p", String(pid)], {
|
|
25274
25671
|
encoding: "utf8",
|
|
25275
25672
|
stdio: ["ignore", "pipe", "pipe"]
|
|
25276
25673
|
});
|
|
25277
|
-
const withEnv = (0,
|
|
25674
|
+
const withEnv = (0, import_node_child_process7.spawnSync)("ps", ["eww", "-o", "command=", "-p", String(pid)], {
|
|
25278
25675
|
encoding: "utf8",
|
|
25279
25676
|
stdio: ["ignore", "pipe", "pipe"]
|
|
25280
25677
|
});
|
|
@@ -25438,7 +25835,7 @@ async function runLinkCommand(args, opts = {}) {
|
|
|
25438
25835
|
if (parsed.positional.length !== 1) {
|
|
25439
25836
|
console.error(" rnx open: expected exactly one <url-or-route>");
|
|
25440
25837
|
console.error(" examples: rnx open /settings | rnx open myapp://settings");
|
|
25441
|
-
|
|
25838
|
+
rnxExit(1);
|
|
25442
25839
|
}
|
|
25443
25840
|
const bridge = createBridgeFromParsed(parsed);
|
|
25444
25841
|
const simHint = parsed.simId ? ` --sim ${parsed.simId}` : "";
|
|
@@ -25452,7 +25849,7 @@ async function runLinkCommand(args, opts = {}) {
|
|
|
25452
25849
|
warningsCommand: `rnx get warnings 5${simHint}`,
|
|
25453
25850
|
requestsCommand: `rnx get requests 5${simHint}`
|
|
25454
25851
|
});
|
|
25455
|
-
|
|
25852
|
+
rnxExit(1);
|
|
25456
25853
|
} finally {
|
|
25457
25854
|
bridge.close();
|
|
25458
25855
|
}
|
|
@@ -25490,11 +25887,11 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25490
25887
|
console.error(
|
|
25491
25888
|
` rnx open: --cdp-port must be a positive port number, got "${cdpPortArg}"`
|
|
25492
25889
|
);
|
|
25493
|
-
|
|
25890
|
+
rnxExit(1);
|
|
25494
25891
|
}
|
|
25495
25892
|
if (requestedProfileId && ephemeralProfile) {
|
|
25496
25893
|
console.error(" rnx open: --profile cannot be combined with --ephemeral");
|
|
25497
|
-
|
|
25894
|
+
rnxExit(1);
|
|
25498
25895
|
}
|
|
25499
25896
|
const profileId = requestedProfileId ? ensureProfile(requestedProfileId).id : void 0;
|
|
25500
25897
|
const openInNewSim = args.includes("--new") || !!profileId || ephemeralProfile;
|
|
@@ -25503,7 +25900,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25503
25900
|
console.error(
|
|
25504
25901
|
" rnx open: --new, --profile, and --ephemeral cannot be combined with --sim"
|
|
25505
25902
|
);
|
|
25506
|
-
|
|
25903
|
+
rnxExit(1);
|
|
25507
25904
|
}
|
|
25508
25905
|
const target = parsed.positional[0] || "";
|
|
25509
25906
|
if (isAppDeepLinkTarget(target)) {
|
|
@@ -25511,7 +25908,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25511
25908
|
console.error(
|
|
25512
25909
|
" rnx open: deep links target the current app; remove --new, --profile, or --ephemeral"
|
|
25513
25910
|
);
|
|
25514
|
-
|
|
25911
|
+
rnxExit(1);
|
|
25515
25912
|
}
|
|
25516
25913
|
await runLinkCommand(args, opts);
|
|
25517
25914
|
return;
|
|
@@ -25535,7 +25932,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25535
25932
|
` could not launch a browser: ${err instanceof Error ? err.message : String(err)}`
|
|
25536
25933
|
);
|
|
25537
25934
|
console.error(` open it yourself: ${target}`);
|
|
25538
|
-
|
|
25935
|
+
rnxExit(1);
|
|
25539
25936
|
}
|
|
25540
25937
|
console.log(
|
|
25541
25938
|
isLocal ? " to drive it under the CLI, point `rnx open` at the app\u2019s dev port instead (e.g. `rnx open 8081`)." : " the CLI can\u2019t drive a remote preview (the engine only attaches to the local bridge from localhost). to drive the app, run it locally and `rnx open <port>`."
|
|
@@ -25565,33 +25962,33 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25565
25962
|
const requestedDriverId = args.find((_, i) => args[i - 1] === "--driver") || "";
|
|
25566
25963
|
if (requestedDriverId && !isDriverId(requestedDriverId)) {
|
|
25567
25964
|
console.error(` unknown driver "${requestedDriverId}" \u2014 run \`rnx list --drivers\``);
|
|
25568
|
-
|
|
25965
|
+
rnxExit(1);
|
|
25569
25966
|
}
|
|
25570
25967
|
const driverId = isDriverId(requestedDriverId) ? requestedDriverId : process.env.CI === "1" || process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true" || isAgentEnv() || !process.stdin.isTTY ? "playwright" : readSimulatorDriverPreference() || "playwright";
|
|
25571
25968
|
const driverHeadless = resolveDriverHeadless(args, driverId);
|
|
25572
25969
|
if (cdpPort && driverId !== "playwright") {
|
|
25573
25970
|
console.error(" rnx open: --cdp-port is only honored by the playwright driver");
|
|
25574
|
-
|
|
25971
|
+
rnxExit(1);
|
|
25575
25972
|
}
|
|
25576
25973
|
const hotFlag = args.includes("--hot");
|
|
25577
25974
|
const noHmrFlag = args.includes("--no-hmr");
|
|
25578
25975
|
if (hotFlag && noHmrFlag) {
|
|
25579
25976
|
console.error(" rnx open: --hot and --no-hmr cannot be combined");
|
|
25580
|
-
|
|
25977
|
+
rnxExit(1);
|
|
25581
25978
|
}
|
|
25582
25979
|
const hotMode = hotFlag ? true : noHmrFlag ? false : driverId !== "playwright";
|
|
25583
25980
|
const deviceArg = args.find((_, i) => args[i - 1] === "--device");
|
|
25584
25981
|
if (deviceArg && !(deviceArg in import_settings.devices)) {
|
|
25585
25982
|
console.error(` rnx open: unknown device "${deviceArg}"`);
|
|
25586
25983
|
console.error(` known devices: ${(0, import_settings.listSelectableDeviceModels)().join(", ")}`);
|
|
25587
|
-
|
|
25984
|
+
rnxExit(1);
|
|
25588
25985
|
}
|
|
25589
25986
|
const deviceSpec = deviceArg ? import_settings.devices[deviceArg] : void 0;
|
|
25590
25987
|
const viewportArg = args.find((_, i) => args[i - 1] === "--viewport");
|
|
25591
25988
|
const viewportMatch = viewportArg ? /^(\d+)x(\d+)$/.exec(viewportArg) : null;
|
|
25592
25989
|
if (viewportArg && !viewportMatch) {
|
|
25593
25990
|
console.error(` rnx open: --viewport must be <width>x<height>, got "${viewportArg}"`);
|
|
25594
|
-
|
|
25991
|
+
rnxExit(1);
|
|
25595
25992
|
}
|
|
25596
25993
|
const explicitViewport = viewportMatch ? { width: Number(viewportMatch[1]), height: Number(viewportMatch[2]) } : void 0;
|
|
25597
25994
|
const buildShellUrlOpts = {
|
|
@@ -25684,7 +26081,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25684
26081
|
warningsCommand: `rnx get warnings 5${simHint}`,
|
|
25685
26082
|
requestsCommand: `rnx get requests 5${simHint}`
|
|
25686
26083
|
});
|
|
25687
|
-
|
|
26084
|
+
rnxExit(1);
|
|
25688
26085
|
}
|
|
25689
26086
|
if (!fallBackToNewSim && targetSim) {
|
|
25690
26087
|
await sleep2(1500);
|
|
@@ -25695,7 +26092,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25695
26092
|
);
|
|
25696
26093
|
if (!ready) {
|
|
25697
26094
|
console.error(" timed out waiting for current sim to load target");
|
|
25698
|
-
|
|
26095
|
+
rnxExit(1);
|
|
25699
26096
|
}
|
|
25700
26097
|
ready.bridge.close();
|
|
25701
26098
|
saveCurrentSimId(targetSim.id);
|
|
@@ -25721,13 +26118,13 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25721
26118
|
console.error(
|
|
25722
26119
|
" could not resolve a stable owning process; refusing unsupervised sim host"
|
|
25723
26120
|
);
|
|
25724
|
-
|
|
26121
|
+
rnxExit(1);
|
|
25725
26122
|
}
|
|
25726
26123
|
const simMatchesToken = (sim) => sim.url?.includes(`inspectOpen=${token}`) ?? false;
|
|
25727
26124
|
const driver = getDriver(driverId);
|
|
25728
26125
|
if (!driver) {
|
|
25729
26126
|
console.error(` unknown driver "${driverId}" \u2014 run \`rnx list --drivers\``);
|
|
25730
|
-
|
|
26127
|
+
rnxExit(1);
|
|
25731
26128
|
}
|
|
25732
26129
|
const connectWait = resolveDriverConnectWaitOptions();
|
|
25733
26130
|
const result = await driver.launch({
|
|
@@ -25747,7 +26144,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25747
26144
|
});
|
|
25748
26145
|
if (!result.launched) {
|
|
25749
26146
|
console.error(` ${driver.name} driver: ${result.message}`);
|
|
25750
|
-
|
|
26147
|
+
rnxExit(1);
|
|
25751
26148
|
}
|
|
25752
26149
|
const outcome = await waitForSimMatchOrHostExit(
|
|
25753
26150
|
parsed.wsPort,
|
|
@@ -25759,7 +26156,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25759
26156
|
if (outcome.kind === "host-exit") {
|
|
25760
26157
|
printDriverDiagnosticLogTail(result);
|
|
25761
26158
|
console.error(` ${driver.name} host crashed \u2014 sim is no longer attached`);
|
|
25762
|
-
|
|
26159
|
+
rnxExit(1);
|
|
25763
26160
|
}
|
|
25764
26161
|
if (outcome.kind === "timeout") {
|
|
25765
26162
|
if (result.pid) {
|
|
@@ -25773,7 +26170,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25773
26170
|
console.error(
|
|
25774
26171
|
` timed out after ${connectWait.timeoutMs}ms waiting for opened sim to connect`
|
|
25775
26172
|
);
|
|
25776
|
-
|
|
26173
|
+
rnxExit(1);
|
|
25777
26174
|
}
|
|
25778
26175
|
const match = outcome.sim;
|
|
25779
26176
|
saveCurrentSimId(match.id);
|
|
@@ -25802,7 +26199,7 @@ async function runUseLikeCommand(args, opts = {}) {
|
|
|
25802
26199
|
` refused: ${target.id} is locked by the active user (${secs}s) \u2014 that's a live human tab`
|
|
25803
26200
|
);
|
|
25804
26201
|
console.error(` run \`rnx open --new\` for a fresh investigation sim`);
|
|
25805
|
-
|
|
26202
|
+
rnxExit(1);
|
|
25806
26203
|
}
|
|
25807
26204
|
if (!force) {
|
|
25808
26205
|
console.error(
|
|
@@ -25811,20 +26208,21 @@ async function runUseLikeCommand(args, opts = {}) {
|
|
|
25811
26208
|
console.error(
|
|
25812
26209
|
` \`sootsim use ${target.id} --force\` to take it, or \`rnx open --new\` for a fresh sim`
|
|
25813
26210
|
);
|
|
25814
|
-
|
|
26211
|
+
rnxExit(1);
|
|
25815
26212
|
}
|
|
25816
26213
|
}
|
|
25817
26214
|
await bridge.focusSim(target.id);
|
|
25818
26215
|
saveCurrentSimId(target.id);
|
|
25819
26216
|
console.log(` using: ${target.id}`);
|
|
25820
26217
|
} catch (err) {
|
|
26218
|
+
rethrowIfExit(err);
|
|
25821
26219
|
console.error(` use failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25822
26220
|
await printBridgeFailureDiagnostics(bridge, {
|
|
25823
26221
|
errorsCommand: `rnx get errors 5${simHint}`,
|
|
25824
26222
|
warningsCommand: `rnx get warnings 5${simHint}`,
|
|
25825
26223
|
requestsCommand: `rnx get requests 5${simHint}`
|
|
25826
26224
|
});
|
|
25827
|
-
|
|
26225
|
+
rnxExit(1);
|
|
25828
26226
|
}
|
|
25829
26227
|
} finally {
|
|
25830
26228
|
bridge.close();
|
|
@@ -25862,10 +26260,10 @@ async function runClaimCommand(args, opts = {}) {
|
|
|
25862
26260
|
const secs = Math.max(0, Math.round(err.lock.expiresInMs / 1e3));
|
|
25863
26261
|
console.error(` claim failed: locked by ${err.lock.by} for ${secs}s more`);
|
|
25864
26262
|
console.error(` use --force to take it, or \`rnx open --new\` for a fresh sim`);
|
|
25865
|
-
|
|
26263
|
+
rnxExit(1);
|
|
25866
26264
|
}
|
|
25867
26265
|
console.error(` claim failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25868
|
-
|
|
26266
|
+
rnxExit(1);
|
|
25869
26267
|
}
|
|
25870
26268
|
} finally {
|
|
25871
26269
|
bridge.close();
|
|
@@ -25972,7 +26370,7 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
25972
26370
|
console.error(
|
|
25973
26371
|
` close failed: keep sim ${plan.missingExplicitKeepId} is not connected; not closing other sims`
|
|
25974
26372
|
);
|
|
25975
|
-
|
|
26373
|
+
rnxExit(1);
|
|
25976
26374
|
}
|
|
25977
26375
|
if (plan.targets.length === 0) {
|
|
25978
26376
|
console.log(
|
|
@@ -25996,11 +26394,12 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
25996
26394
|
console.log(summary);
|
|
25997
26395
|
if (result.remaining.length > 0) {
|
|
25998
26396
|
console.error(` close failed: still connected: ${result.remaining.join(", ")}`);
|
|
25999
|
-
|
|
26397
|
+
rnxExit(1);
|
|
26000
26398
|
}
|
|
26001
26399
|
} catch (err) {
|
|
26400
|
+
rethrowIfExit(err);
|
|
26002
26401
|
console.error(` close failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
26003
|
-
|
|
26402
|
+
rnxExit(1);
|
|
26004
26403
|
} finally {
|
|
26005
26404
|
bridge.close();
|
|
26006
26405
|
}
|
|
@@ -26022,7 +26421,7 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
26022
26421
|
if (!closed) {
|
|
26023
26422
|
await terminatePlaywrightHostsForSims(sims, [target.id]);
|
|
26024
26423
|
console.error(` close failed: ${target.id} is still connected`);
|
|
26025
|
-
|
|
26424
|
+
rnxExit(1);
|
|
26026
26425
|
}
|
|
26027
26426
|
await terminatePlaywrightHostsForSims(sims, [target.id]);
|
|
26028
26427
|
if (readCurrentSimId() === target.id) {
|
|
@@ -26031,26 +26430,27 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
26031
26430
|
}
|
|
26032
26431
|
console.log(` closed: ${target.id}`);
|
|
26033
26432
|
} catch (err) {
|
|
26433
|
+
rethrowIfExit(err);
|
|
26034
26434
|
console.error(` close failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
26035
26435
|
await printBridgeFailureDiagnostics(bridge, {
|
|
26036
26436
|
errorsCommand: `rnx get errors 5${simHint}`,
|
|
26037
26437
|
warningsCommand: `rnx get warnings 5${simHint}`,
|
|
26038
26438
|
requestsCommand: `rnx get requests 5${simHint}`
|
|
26039
26439
|
});
|
|
26040
|
-
|
|
26440
|
+
rnxExit(1);
|
|
26041
26441
|
}
|
|
26042
26442
|
} finally {
|
|
26043
26443
|
bridge.close();
|
|
26044
26444
|
}
|
|
26045
26445
|
}
|
|
26046
|
-
var
|
|
26446
|
+
var import_node_child_process7, import_node_fs15, import_node_os3, import_node_path18, 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;
|
|
26047
26447
|
var init_control = __esm({
|
|
26048
26448
|
"cli/commands/control.ts"() {
|
|
26049
26449
|
"use strict";
|
|
26050
|
-
|
|
26051
|
-
|
|
26450
|
+
import_node_child_process7 = require("node:child_process");
|
|
26451
|
+
import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
26052
26452
|
import_node_os3 = __toESM(require("node:os"), 1);
|
|
26053
|
-
|
|
26453
|
+
import_node_path18 = __toESM(require("node:path"), 1);
|
|
26054
26454
|
import_settings = require("sootsim-engine/settings");
|
|
26055
26455
|
import_ws5 = require("ws");
|
|
26056
26456
|
init_dev_server_scanner();
|
|
@@ -26073,6 +26473,7 @@ var init_control = __esm({
|
|
|
26073
26473
|
init_current_sim();
|
|
26074
26474
|
init_registry2();
|
|
26075
26475
|
init_open_url2();
|
|
26476
|
+
init_run_rnx();
|
|
26076
26477
|
init_ws_bridge();
|
|
26077
26478
|
init_core();
|
|
26078
26479
|
init_env();
|
|
@@ -26913,14 +27314,14 @@ process.stdin.on('end', async () => {
|
|
|
26913
27314
|
function getBaseDir() {
|
|
26914
27315
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
26915
27316
|
if (explicit?.trim()) {
|
|
26916
|
-
return (0,
|
|
27317
|
+
return (0, import_node_path19.dirname)((0, import_node_path19.resolve)(explicit));
|
|
26917
27318
|
}
|
|
26918
27319
|
return electronUserDataDir();
|
|
26919
27320
|
}
|
|
26920
27321
|
function getSharedDesktopAuthFilePath() {
|
|
26921
27322
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
26922
|
-
if (explicit?.trim()) return (0,
|
|
26923
|
-
return (0,
|
|
27323
|
+
if (explicit?.trim()) return (0, import_node_path19.resolve)(explicit);
|
|
27324
|
+
return (0, import_node_path19.join)(getBaseDir(), "desktop-auth.json");
|
|
26924
27325
|
}
|
|
26925
27326
|
function normalizeUser(input) {
|
|
26926
27327
|
if (!input || typeof input !== "object") return null;
|
|
@@ -26967,26 +27368,26 @@ function normalizeSession(input) {
|
|
|
26967
27368
|
}
|
|
26968
27369
|
function readSharedDesktopAuthSession() {
|
|
26969
27370
|
const filepath = getSharedDesktopAuthFilePath();
|
|
26970
|
-
if (!(0,
|
|
27371
|
+
if (!(0, import_node_fs16.existsSync)(filepath)) return null;
|
|
26971
27372
|
try {
|
|
26972
|
-
const parsed = JSON.parse((0,
|
|
27373
|
+
const parsed = JSON.parse((0, import_node_fs16.readFileSync)(filepath, "utf8"));
|
|
26973
27374
|
const normalized = normalizeSession(parsed);
|
|
26974
27375
|
if (!normalized) {
|
|
26975
|
-
(0,
|
|
27376
|
+
(0, import_node_fs16.rmSync)(filepath, { force: true });
|
|
26976
27377
|
return null;
|
|
26977
27378
|
}
|
|
26978
27379
|
return normalized;
|
|
26979
27380
|
} catch {
|
|
26980
|
-
(0,
|
|
27381
|
+
(0, import_node_fs16.rmSync)(filepath, { force: true });
|
|
26981
27382
|
return null;
|
|
26982
27383
|
}
|
|
26983
27384
|
}
|
|
26984
|
-
var
|
|
27385
|
+
var import_node_fs16, import_node_path19, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
|
|
26985
27386
|
var init_shared_session = __esm({
|
|
26986
27387
|
"src/auth/shared-session.ts"() {
|
|
26987
27388
|
"use strict";
|
|
26988
|
-
|
|
26989
|
-
|
|
27389
|
+
import_node_fs16 = require("node:fs");
|
|
27390
|
+
import_node_path19 = require("node:path");
|
|
26990
27391
|
init_home_paths();
|
|
26991
27392
|
SESSION_VERSION = 1;
|
|
26992
27393
|
SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
@@ -27057,6 +27458,7 @@ var init_auth = __esm({
|
|
|
27057
27458
|
"cli/auth.ts"() {
|
|
27058
27459
|
"use strict";
|
|
27059
27460
|
init_shared_session();
|
|
27461
|
+
init_run_rnx();
|
|
27060
27462
|
GITHUB_TOKEN_PREFIXES = ["ghs_", "ghp_", "gho_", "ghu_", "github_pat_"];
|
|
27061
27463
|
}
|
|
27062
27464
|
});
|
|
@@ -27089,6 +27491,7 @@ var init_upload = __esm({
|
|
|
27089
27491
|
init_auth();
|
|
27090
27492
|
init_open_url2();
|
|
27091
27493
|
init_run_registry();
|
|
27494
|
+
init_run_rnx();
|
|
27092
27495
|
init_ws_bridge();
|
|
27093
27496
|
REMOTE_DEFAULT_ORIGIN = process.env.SOOTSIM_UPLOAD_ORIGIN || "https://contrast.dev";
|
|
27094
27497
|
REMOTE_DEFAULT_PUBLIC_PREVIEW_ORIGIN = process.env.SOOTSIM_PREVIEW_ORIGIN || rnxPublicBrand.origin;
|
|
@@ -27120,7 +27523,7 @@ async function ensureCliRecordingEntitlement(commandLabel, opts = {}) {
|
|
|
27120
27523
|
|
|
27121
27524
|
`
|
|
27122
27525
|
);
|
|
27123
|
-
|
|
27526
|
+
rnxExit(1);
|
|
27124
27527
|
}
|
|
27125
27528
|
if (auth.kind === "github" && opts.allowGitHubAuth) return;
|
|
27126
27529
|
const billingOrigin = await billingOriginFor(auth, opts.originOverride);
|
|
@@ -27137,7 +27540,7 @@ async function ensureCliRecordingEntitlement(commandLabel, opts = {}) {
|
|
|
27137
27540
|
|
|
27138
27541
|
`
|
|
27139
27542
|
);
|
|
27140
|
-
|
|
27543
|
+
rnxExit(1);
|
|
27141
27544
|
}
|
|
27142
27545
|
if (res.status === 401) {
|
|
27143
27546
|
process.stderr.write(
|
|
@@ -27147,7 +27550,7 @@ async function ensureCliRecordingEntitlement(commandLabel, opts = {}) {
|
|
|
27147
27550
|
|
|
27148
27551
|
`
|
|
27149
27552
|
);
|
|
27150
|
-
|
|
27553
|
+
rnxExit(1);
|
|
27151
27554
|
}
|
|
27152
27555
|
if (!res.ok) {
|
|
27153
27556
|
const text = await res.text().catch(() => "");
|
|
@@ -27158,7 +27561,7 @@ async function ensureCliRecordingEntitlement(commandLabel, opts = {}) {
|
|
|
27158
27561
|
|
|
27159
27562
|
`
|
|
27160
27563
|
);
|
|
27161
|
-
|
|
27564
|
+
rnxExit(1);
|
|
27162
27565
|
}
|
|
27163
27566
|
const data = await res.json();
|
|
27164
27567
|
if (data.entitlements?.desktopRecording === true) return;
|
|
@@ -27171,7 +27574,7 @@ async function ensureCliRecordingEntitlement(commandLabel, opts = {}) {
|
|
|
27171
27574
|
|
|
27172
27575
|
`
|
|
27173
27576
|
);
|
|
27174
|
-
|
|
27577
|
+
rnxExit(1);
|
|
27175
27578
|
}
|
|
27176
27579
|
var init_recording_access = __esm({
|
|
27177
27580
|
"cli/recording-access.ts"() {
|
|
@@ -27179,6 +27582,7 @@ var init_recording_access = __esm({
|
|
|
27179
27582
|
init_shared_session();
|
|
27180
27583
|
init_auth();
|
|
27181
27584
|
init_upload();
|
|
27585
|
+
init_run_rnx();
|
|
27182
27586
|
}
|
|
27183
27587
|
});
|
|
27184
27588
|
|
|
@@ -27225,16 +27629,16 @@ function resolveFlowScreenshotPath(screenshotDir, name2) {
|
|
|
27225
27629
|
}
|
|
27226
27630
|
function resolveProjectRelativeFlowBase(flowDir) {
|
|
27227
27631
|
if (!flowDir) return process.cwd();
|
|
27228
|
-
return
|
|
27632
|
+
return path18.basename(flowDir) === ".maestro" ? path18.dirname(flowDir) : flowDir;
|
|
27229
27633
|
}
|
|
27230
27634
|
function resolveFlowScreenshotPathWithMode(screenshotDir, name2, opts) {
|
|
27231
27635
|
const normalizedName = name2.endsWith(".png") ? name2 : `${name2}.png`;
|
|
27232
|
-
if (
|
|
27636
|
+
if (path18.isAbsolute(normalizedName)) return normalizedName;
|
|
27233
27637
|
if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
|
|
27234
27638
|
const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
|
|
27235
|
-
return
|
|
27639
|
+
return path18.resolve(baseDir, normalizedName);
|
|
27236
27640
|
}
|
|
27237
|
-
return
|
|
27641
|
+
return path18.join(screenshotDir, normalizedName);
|
|
27238
27642
|
}
|
|
27239
27643
|
function normalizeFlowScreenshotSpec(step) {
|
|
27240
27644
|
if (typeof step === "string") {
|
|
@@ -27291,12 +27695,12 @@ function parseFlowSteps(content) {
|
|
|
27291
27695
|
const parsed = import_yaml.default.parse(candidate);
|
|
27292
27696
|
return Array.isArray(parsed) ? parsed : [];
|
|
27293
27697
|
}
|
|
27294
|
-
var
|
|
27698
|
+
var fs18, path18, import_settings3, import_yaml, import_proof_frame, DEFAULT_TIMEOUT, FLOW_TIMEOUT_SCALE, scaledTimeout, SCREEN_W, SCREEN_H, SootSimBridgeFlowRunner;
|
|
27295
27699
|
var init_bridge_flow_runner = __esm({
|
|
27296
27700
|
"cli/bridge-flow-runner.ts"() {
|
|
27297
27701
|
"use strict";
|
|
27298
|
-
|
|
27299
|
-
|
|
27702
|
+
fs18 = __toESM(require("fs"), 1);
|
|
27703
|
+
path18 = __toESM(require("path"), 1);
|
|
27300
27704
|
import_settings3 = require("sootsim-engine/settings");
|
|
27301
27705
|
import_yaml = __toESM(require("yaml"), 1);
|
|
27302
27706
|
import_proof_frame = __toESM(require_proof_frame(), 1);
|
|
@@ -27503,14 +27907,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
27503
27907
|
if (chunks.length === 0) {
|
|
27504
27908
|
throw new Error("recording requested but no video buffer was produced");
|
|
27505
27909
|
}
|
|
27506
|
-
|
|
27910
|
+
fs18.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
|
|
27507
27911
|
const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
|
|
27508
27912
|
const extension = videoMime.includes("mp4") ? "mp4" : "webm";
|
|
27509
|
-
const outputPath =
|
|
27913
|
+
const outputPath = path18.join(
|
|
27510
27914
|
this.opts.recordingOutputDir,
|
|
27511
27915
|
`sootsim-${Date.now()}.${extension}`
|
|
27512
27916
|
);
|
|
27513
|
-
|
|
27917
|
+
fs18.writeFileSync(outputPath, Buffer.concat(chunks));
|
|
27514
27918
|
return outputPath;
|
|
27515
27919
|
}
|
|
27516
27920
|
async waitForRecordingTail(opts) {
|
|
@@ -28006,7 +28410,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
28006
28410
|
flowDir: this.opts.flowDir
|
|
28007
28411
|
}
|
|
28008
28412
|
);
|
|
28009
|
-
|
|
28413
|
+
fs18.mkdirSync(path18.dirname(outputPath), { recursive: true });
|
|
28010
28414
|
const layers = spec.layers ?? this.opts.screenshotLayers;
|
|
28011
28415
|
const screenshotRequest = {
|
|
28012
28416
|
type: "screenshot",
|
|
@@ -28045,11 +28449,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
28045
28449
|
throw new Error("could not read current device model for framed screenshot");
|
|
28046
28450
|
}
|
|
28047
28451
|
const framed = await composeFramedScreenshot(rawBuffer, model);
|
|
28048
|
-
|
|
28452
|
+
fs18.writeFileSync(outputPath, framed);
|
|
28049
28453
|
console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
|
|
28050
28454
|
return outputPath;
|
|
28051
28455
|
}
|
|
28052
|
-
|
|
28456
|
+
fs18.writeFileSync(outputPath, rawBuffer);
|
|
28053
28457
|
console.log(`[flow] screenshot: ${outputPath}`);
|
|
28054
28458
|
return outputPath;
|
|
28055
28459
|
}
|
|
@@ -28071,10 +28475,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
28071
28475
|
// + a11y tree + console errors/warnings + failed network requests +
|
|
28072
28476
|
// shell state, all under one directory so post-mortem is one grep away.
|
|
28073
28477
|
async captureFailureBundle(outputDir, context) {
|
|
28074
|
-
|
|
28478
|
+
fs18.mkdirSync(outputDir, { recursive: true });
|
|
28075
28479
|
const write = (name2, content) => {
|
|
28076
28480
|
try {
|
|
28077
|
-
|
|
28481
|
+
fs18.writeFileSync(path18.join(outputDir, name2), content);
|
|
28078
28482
|
} catch {
|
|
28079
28483
|
}
|
|
28080
28484
|
};
|
|
@@ -28612,8 +29016,8 @@ var init_bridge_flow_runner = __esm({
|
|
|
28612
29016
|
runScript(target) {
|
|
28613
29017
|
const spec = typeof target === "string" ? { file: target } : target;
|
|
28614
29018
|
if (!spec.file) throw new Error("runScript requires a file");
|
|
28615
|
-
const scriptPath =
|
|
28616
|
-
const source =
|
|
29019
|
+
const scriptPath = path18.resolve(this.opts.flowDir, spec.file);
|
|
29020
|
+
const source = fs18.readFileSync(scriptPath, "utf8");
|
|
28617
29021
|
this.js.evaluate(source, { env: spec.env });
|
|
28618
29022
|
console.log(`[flow] runScript: ${spec.file} done`);
|
|
28619
29023
|
}
|
|
@@ -28910,10 +29314,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
28910
29314
|
for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
|
|
28911
29315
|
}
|
|
28912
29316
|
if (file) {
|
|
28913
|
-
const flowPath =
|
|
28914
|
-
const flowContent =
|
|
29317
|
+
const flowPath = path18.resolve(this.opts.flowDir, file);
|
|
29318
|
+
const flowContent = fs18.readFileSync(flowPath, "utf8");
|
|
28915
29319
|
const previousDir = this.opts.flowDir;
|
|
28916
|
-
this.opts.flowDir =
|
|
29320
|
+
this.opts.flowDir = path18.dirname(flowPath);
|
|
28917
29321
|
try {
|
|
28918
29322
|
await this.runFlow(parseFlowSteps(flowContent));
|
|
28919
29323
|
} finally {
|
|
@@ -29068,8 +29472,8 @@ __export(registry_exports, {
|
|
|
29068
29472
|
skillRegistry: () => skillRegistry
|
|
29069
29473
|
});
|
|
29070
29474
|
module.exports = __toCommonJS(registry_exports);
|
|
29071
|
-
var
|
|
29072
|
-
var
|
|
29475
|
+
var fs19 = __toESM(require("fs"), 1);
|
|
29476
|
+
var path19 = __toESM(require("path"), 1);
|
|
29073
29477
|
|
|
29074
29478
|
// src/skills/builtin/a11y-review.ts
|
|
29075
29479
|
init_reap_browser();
|
|
@@ -29088,8 +29492,8 @@ var skill = {
|
|
|
29088
29492
|
},
|
|
29089
29493
|
async execute(params, context) {
|
|
29090
29494
|
const { chromium } = await import("playwright");
|
|
29091
|
-
const
|
|
29092
|
-
const
|
|
29495
|
+
const path20 = await import("path");
|
|
29496
|
+
const fs20 = await import("fs");
|
|
29093
29497
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
29094
29498
|
headless: true
|
|
29095
29499
|
});
|
|
@@ -29144,9 +29548,9 @@ var skill = {
|
|
|
29144
29548
|
warnings: issues.filter((i) => i.severity === "warning").length,
|
|
29145
29549
|
tree: typeof tree === "string" ? tree : JSON.stringify(tree)
|
|
29146
29550
|
};
|
|
29147
|
-
const reportPath =
|
|
29148
|
-
|
|
29149
|
-
|
|
29551
|
+
const reportPath = path20.join(context.outputDir, "a11y-report.json");
|
|
29552
|
+
fs20.mkdirSync(path20.dirname(reportPath), { recursive: true });
|
|
29553
|
+
fs20.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
29150
29554
|
return {
|
|
29151
29555
|
success: issues.filter((i) => i.severity === "error").length === 0,
|
|
29152
29556
|
message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
|
|
@@ -29179,14 +29583,14 @@ var skill2 = {
|
|
|
29179
29583
|
}
|
|
29180
29584
|
},
|
|
29181
29585
|
async execute(params, context) {
|
|
29182
|
-
const
|
|
29183
|
-
const
|
|
29586
|
+
const fs20 = await import("node:fs");
|
|
29587
|
+
const path20 = await import("node:path");
|
|
29184
29588
|
const { COMPAT_RESULT_CAVEAT: COMPAT_RESULT_CAVEAT2, formatPackageStatus: formatPackageStatus2, formatScanCounts: formatScanCounts2, scanDeps: scanDeps2 } = await Promise.resolve().then(() => (init_web(), web_exports));
|
|
29185
|
-
const packagePath =
|
|
29186
|
-
if (!
|
|
29589
|
+
const packagePath = path20.join(context.projectDir, "package.json");
|
|
29590
|
+
if (!fs20.existsSync(packagePath)) {
|
|
29187
29591
|
return { success: false, message: "No package.json found" };
|
|
29188
29592
|
}
|
|
29189
|
-
const parsed = JSON.parse(
|
|
29593
|
+
const parsed = JSON.parse(fs20.readFileSync(packagePath, "utf8"));
|
|
29190
29594
|
if (!parsed || typeof parsed !== "object") {
|
|
29191
29595
|
return { success: false, message: "package.json is not an object" };
|
|
29192
29596
|
}
|
|
@@ -29198,9 +29602,9 @@ var skill2 = {
|
|
|
29198
29602
|
}) : scanDeps2(parsed);
|
|
29199
29603
|
const packageResult = params.packageName ? scan.packages[0] : void 0;
|
|
29200
29604
|
const message = packageResult ? `${params.packageName}: ${formatPackageStatus2(packageResult)}. ${COMPAT_RESULT_CAVEAT2}` : `${formatScanCounts2(scan)}. ${COMPAT_RESULT_CAVEAT2}`;
|
|
29201
|
-
const reportPath =
|
|
29202
|
-
|
|
29203
|
-
|
|
29605
|
+
const reportPath = path20.join(context.outputDir, "compat-report.json");
|
|
29606
|
+
fs20.mkdirSync(path20.dirname(reportPath), { recursive: true });
|
|
29607
|
+
fs20.writeFileSync(reportPath, `${JSON.stringify(scan, null, 2)}
|
|
29204
29608
|
`);
|
|
29205
29609
|
return {
|
|
29206
29610
|
success: true,
|
|
@@ -29244,8 +29648,8 @@ var skill3 = {
|
|
|
29244
29648
|
record: { type: "boolean", description: "Record video of the flow" }
|
|
29245
29649
|
},
|
|
29246
29650
|
async execute(params, context) {
|
|
29247
|
-
const
|
|
29248
|
-
const
|
|
29651
|
+
const fs20 = await import("fs");
|
|
29652
|
+
const path20 = await import("path");
|
|
29249
29653
|
const yaml2 = await import("yaml");
|
|
29250
29654
|
const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
|
|
29251
29655
|
const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
|
|
@@ -29255,7 +29659,7 @@ var skill3 = {
|
|
|
29255
29659
|
const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
|
|
29256
29660
|
host.start({ silent: true });
|
|
29257
29661
|
try {
|
|
29258
|
-
const flowContent =
|
|
29662
|
+
const flowContent = fs20.readFileSync(params.flowPath, "utf8");
|
|
29259
29663
|
const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
29260
29664
|
const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
|
|
29261
29665
|
const steps = yaml2.parse(stepsBody);
|
|
@@ -29282,7 +29686,7 @@ var skill3 = {
|
|
|
29282
29686
|
});
|
|
29283
29687
|
const driver = new SootSimBridgeFlowRunner2(bridge, {
|
|
29284
29688
|
screenshotDir: context.outputDir,
|
|
29285
|
-
flowDir:
|
|
29689
|
+
flowDir: path20.dirname(path20.resolve(params.flowPath)),
|
|
29286
29690
|
simId,
|
|
29287
29691
|
recordingOutputDir: params.record ? context.outputDir : void 0
|
|
29288
29692
|
});
|
|
@@ -29304,7 +29708,7 @@ var skill3 = {
|
|
|
29304
29708
|
simId,
|
|
29305
29709
|
videoPath: videoPath || void 0
|
|
29306
29710
|
},
|
|
29307
|
-
artifacts: videoPath ? [{ type: "video", name:
|
|
29711
|
+
artifacts: videoPath ? [{ type: "video", name: path20.basename(videoPath), path: videoPath }] : void 0
|
|
29308
29712
|
};
|
|
29309
29713
|
} finally {
|
|
29310
29714
|
try {
|
|
@@ -29351,8 +29755,8 @@ var skill4 = {
|
|
|
29351
29755
|
},
|
|
29352
29756
|
async execute(params, context) {
|
|
29353
29757
|
const { chromium } = await import("playwright");
|
|
29354
|
-
const
|
|
29355
|
-
const
|
|
29758
|
+
const path20 = await import("path");
|
|
29759
|
+
const fs20 = await import("fs");
|
|
29356
29760
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
29357
29761
|
headless: true
|
|
29358
29762
|
});
|
|
@@ -29378,9 +29782,9 @@ var skill4 = {
|
|
|
29378
29782
|
...profile,
|
|
29379
29783
|
fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
|
|
29380
29784
|
};
|
|
29381
|
-
const reportPath =
|
|
29382
|
-
|
|
29383
|
-
|
|
29785
|
+
const reportPath = path20.join(context.outputDir, "perf-report.json");
|
|
29786
|
+
fs20.mkdirSync(path20.dirname(reportPath), { recursive: true });
|
|
29787
|
+
fs20.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
29384
29788
|
return {
|
|
29385
29789
|
success: true,
|
|
29386
29790
|
message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
|
|
@@ -29413,8 +29817,8 @@ var skill5 = {
|
|
|
29413
29817
|
},
|
|
29414
29818
|
async execute(params, context) {
|
|
29415
29819
|
const { chromium } = await import("playwright");
|
|
29416
|
-
const
|
|
29417
|
-
const
|
|
29820
|
+
const path20 = await import("path");
|
|
29821
|
+
const fs20 = await import("fs");
|
|
29418
29822
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
29419
29823
|
headless: true
|
|
29420
29824
|
});
|
|
@@ -29422,8 +29826,8 @@ var skill5 = {
|
|
|
29422
29826
|
try {
|
|
29423
29827
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
29424
29828
|
await page.waitForTimeout(2e3);
|
|
29425
|
-
const outputPath =
|
|
29426
|
-
|
|
29829
|
+
const outputPath = path20.join(context.outputDir, `${params.name}.png`);
|
|
29830
|
+
fs20.mkdirSync(path20.dirname(outputPath), { recursive: true });
|
|
29427
29831
|
await page.screenshot({ path: outputPath });
|
|
29428
29832
|
return {
|
|
29429
29833
|
success: true,
|
|
@@ -29464,8 +29868,8 @@ var skill6 = {
|
|
|
29464
29868
|
},
|
|
29465
29869
|
async execute(params, context) {
|
|
29466
29870
|
const { chromium } = await import("playwright");
|
|
29467
|
-
const
|
|
29468
|
-
const
|
|
29871
|
+
const path20 = await import("path");
|
|
29872
|
+
const fs20 = await import("fs");
|
|
29469
29873
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
29470
29874
|
headless: true
|
|
29471
29875
|
});
|
|
@@ -29473,14 +29877,14 @@ var skill6 = {
|
|
|
29473
29877
|
try {
|
|
29474
29878
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
29475
29879
|
await page.waitForTimeout(2e3);
|
|
29476
|
-
const currentPath =
|
|
29477
|
-
|
|
29880
|
+
const currentPath = path20.join(context.outputDir, `${params.name}-current.png`);
|
|
29881
|
+
fs20.mkdirSync(path20.dirname(currentPath), { recursive: true });
|
|
29478
29882
|
await page.screenshot({ path: currentPath });
|
|
29479
29883
|
try {
|
|
29480
29884
|
const { PNG } = await import("pngjs");
|
|
29481
29885
|
const pixelmatch = (await import("pixelmatch")).default;
|
|
29482
|
-
const baseline = PNG.sync.read(
|
|
29483
|
-
const current = PNG.sync.read(
|
|
29886
|
+
const baseline = PNG.sync.read(fs20.readFileSync(params.baseline));
|
|
29887
|
+
const current = PNG.sync.read(fs20.readFileSync(currentPath));
|
|
29484
29888
|
const { width, height } = baseline;
|
|
29485
29889
|
const diff = new PNG({ width, height });
|
|
29486
29890
|
const numDiffPixels = pixelmatch(
|
|
@@ -29491,8 +29895,8 @@ var skill6 = {
|
|
|
29491
29895
|
height,
|
|
29492
29896
|
{ threshold: params.threshold || 0.1 }
|
|
29493
29897
|
);
|
|
29494
|
-
const diffPath =
|
|
29495
|
-
|
|
29898
|
+
const diffPath = path20.join(context.outputDir, `${params.name}-diff.png`);
|
|
29899
|
+
fs20.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
29496
29900
|
const totalPixels = width * height;
|
|
29497
29901
|
const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
|
|
29498
29902
|
return {
|
|
@@ -29556,10 +29960,10 @@ var skillRegistry = {
|
|
|
29556
29960
|
},
|
|
29557
29961
|
// load skills from a project manifest (sootsim-skills.json)
|
|
29558
29962
|
async loadFromManifest(projectDir) {
|
|
29559
|
-
const manifestPath =
|
|
29560
|
-
if (!
|
|
29963
|
+
const manifestPath = path19.join(projectDir, "sootsim-skills.json");
|
|
29964
|
+
if (!fs19.existsSync(manifestPath)) return;
|
|
29561
29965
|
try {
|
|
29562
|
-
const manifest = JSON.parse(
|
|
29966
|
+
const manifest = JSON.parse(fs19.readFileSync(manifestPath, "utf8"));
|
|
29563
29967
|
if (Array.isArray(manifest.skills)) {
|
|
29564
29968
|
for (const entry of manifest.skills) {
|
|
29565
29969
|
if (typeof entry === "string") {
|
|
@@ -29570,7 +29974,7 @@ var skillRegistry = {
|
|
|
29570
29974
|
}
|
|
29571
29975
|
} else if (entry.file) {
|
|
29572
29976
|
try {
|
|
29573
|
-
const mod = await import(
|
|
29977
|
+
const mod = await import(path19.resolve(projectDir, entry.file));
|
|
29574
29978
|
if (mod.skill) this.register(mod.skill);
|
|
29575
29979
|
} catch {
|
|
29576
29980
|
}
|
|
@@ -29583,10 +29987,10 @@ var skillRegistry = {
|
|
|
29583
29987
|
// auto-discover skills based on project dependencies
|
|
29584
29988
|
suggestSkills(projectDir) {
|
|
29585
29989
|
const suggestions = [];
|
|
29586
|
-
const pkgPath =
|
|
29587
|
-
if (!
|
|
29990
|
+
const pkgPath = path19.join(projectDir, "package.json");
|
|
29991
|
+
if (!fs19.existsSync(pkgPath)) return suggestions;
|
|
29588
29992
|
try {
|
|
29589
|
-
const pkg = JSON.parse(
|
|
29993
|
+
const pkg = JSON.parse(fs19.readFileSync(pkgPath, "utf8"));
|
|
29590
29994
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
29591
29995
|
if (deps["detox"] || deps["maestro"]) {
|
|
29592
29996
|
suggestions.push("maestro-test");
|