rnxsim 0.1.313 → 0.1.315
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/LICENSE +11 -10
- package/README.md +5 -0
- package/cli/app-config.ts +65 -0
- package/cli/app-fonts.ts +408 -0
- package/cli/app-project.ts +231 -0
- package/cli/app-splash.ts +185 -0
- package/cli/app-state-reset.ts +24 -0
- package/cli/auth.ts +155 -0
- package/cli/bin.ts +594 -0
- package/cli/bridge-diagnostics.ts +226 -0
- package/cli/bridge-flow-runner.ts +2830 -0
- package/cli/browser-evals.ts +96 -0
- package/cli/commands/agent-wrapper.ts +986 -0
- package/cli/commands/agent.ts +423 -0
- package/cli/commands/app-fonts.ts +98 -0
- package/cli/commands/assert.ts +541 -0
- package/cli/commands/auth.ts +59 -0
- package/cli/commands/camera.ts +266 -0
- package/cli/commands/cleanup.ts +169 -0
- package/cli/commands/compat.ts +87 -0
- package/cli/commands/config.ts +32 -0
- package/cli/commands/control.ts +2142 -0
- package/cli/commands/cpu-profile.ts +269 -0
- package/cli/commands/daemon-mac-app.ts +169 -0
- package/cli/commands/daemon.ts +874 -0
- package/cli/commands/debug.ts +719 -0
- package/cli/commands/desktop.ts +39 -0
- package/cli/commands/detect.ts +197 -0
- package/cli/commands/detox.ts +385 -0
- package/cli/commands/device.ts +133 -0
- package/cli/commands/diagnose.ts +589 -0
- package/cli/commands/electron.ts +95 -0
- package/cli/commands/film.ts +379 -0
- package/cli/commands/flow.ts +1124 -0
- package/cli/commands/inspect/actions.ts +622 -0
- package/cli/commands/inspect/core.ts +2405 -0
- package/cli/commands/inspect/count.ts +17 -0
- package/cli/commands/inspect/describe.ts +192 -0
- package/cli/commands/inspect/env.ts +23 -0
- package/cli/commands/inspect/find.ts +171 -0
- package/cli/commands/inspect/get-layout.ts +39 -0
- package/cli/commands/inspect/keyboard.ts +52 -0
- package/cli/commands/inspect/list.ts +58 -0
- package/cli/commands/inspect/memory.ts +215 -0
- package/cli/commands/inspect/redaction.ts +39 -0
- package/cli/commands/inspect/resolve-target.ts +82 -0
- package/cli/commands/inspect/screens.ts +78 -0
- package/cli/commands/inspect/settle.ts +22 -0
- package/cli/commands/inspect/settling.ts +158 -0
- package/cli/commands/inspect/shared.ts +353 -0
- package/cli/commands/inspect/sleep.ts +14 -0
- package/cli/commands/inspect/tree.ts +32 -0
- package/cli/commands/inspect/url.ts +17 -0
- package/cli/commands/inspect/wait-event.ts +210 -0
- package/cli/commands/inspect/wait-idle.ts +24 -0
- package/cli/commands/inspect/wait-ready.ts +74 -0
- package/cli/commands/inspect/wait-selector.ts +54 -0
- package/cli/commands/inspect/wait.ts +31 -0
- package/cli/commands/inspect.ts +4519 -0
- package/cli/commands/install-desktop.ts +351 -0
- package/cli/commands/login.ts +331 -0
- package/cli/commands/logout.ts +31 -0
- package/cli/commands/maestro-generate.ts +361 -0
- package/cli/commands/maestro.ts +453 -0
- package/cli/commands/mode.ts +57 -0
- package/cli/commands/no-bridge-hint.ts +80 -0
- package/cli/commands/perf.ts +66 -0
- package/cli/commands/permissions.ts +203 -0
- package/cli/commands/profile.ts +108 -0
- package/cli/commands/react.ts +353 -0
- package/cli/commands/record.ts +1434 -0
- package/cli/commands/report-issue.ts +305 -0
- package/cli/commands/reset.ts +85 -0
- package/cli/commands/runtime.ts +351 -0
- package/cli/commands/screenshot-command.ts +106 -0
- package/cli/commands/screenshot-layers.ts +143 -0
- package/cli/commands/screenshot-mode.ts +37 -0
- package/cli/commands/screenshot.ts +488 -0
- package/cli/commands/screenshots-capture.ts +607 -0
- package/cli/commands/screenshots.ts +127 -0
- package/cli/commands/serve.ts +168 -0
- package/cli/commands/setup.ts +545 -0
- package/cli/commands/shell-boolean-mode.ts +81 -0
- package/cli/commands/skills.ts +467 -0
- package/cli/commands/slides.ts +361 -0
- package/cli/commands/state.ts +87 -0
- package/cli/commands/storage.ts +58 -0
- package/cli/commands/telemetry.ts +54 -0
- package/cli/commands/three-mode.ts +763 -0
- package/cli/commands/timeline.ts +122 -0
- package/cli/commands/upgrade.ts +208 -0
- package/cli/commands/upload.ts +1225 -0
- package/cli/commands/version.ts +54 -0
- package/cli/commands/what-happened.ts +327 -0
- package/cli/current-sim.ts +204 -0
- package/cli/desktop-companion.ts +300 -0
- package/cli/drivers/electron.ts +70 -0
- package/cli/drivers/index.ts +20 -0
- package/cli/drivers/playwright-provisioning.ts +180 -0
- package/cli/drivers/playwright.ts +698 -0
- package/cli/drivers/registry.ts +65 -0
- package/cli/drivers/types.ts +102 -0
- package/cli/flow-file.ts +142 -0
- package/cli/flow-live-status.ts +120 -0
- package/cli/flow-session.ts +187 -0
- package/cli/help.ts +80 -0
- package/cli/hidden-runtime-alias.ts +19 -0
- package/cli/hints.ts +216 -0
- package/cli/inspect-notice-state.ts +114 -0
- package/cli/maestro-js.ts +334 -0
- package/cli/open-url.ts +8 -0
- package/cli/parent-pid.ts +204 -0
- package/cli/parse-args.ts +211 -0
- package/cli/prompt.ts +51 -0
- package/cli/recording-access.ts +107 -0
- package/cli/registry.ts +1 -0
- package/cli/resolve-assets.ts +63 -0
- package/cli/run-registry.ts +226 -0
- package/cli/runtime-notes.ts +66 -0
- package/cli/runtime-summary.ts +25 -0
- package/cli/setup-repository.ts +187 -0
- package/cli/telemetry.ts +187 -0
- package/cli/ws-bridge.ts +798 -0
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-XZ2KTPCU.js → agent-CBU2WDKV.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-UNB4R27L.js} +2 -2
- package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-YMLRF3JD.js} +2 -2
- package/dist-cli/chunks/{assert-54T5SK5F.js → assert-5N6HUCL5.js} +2 -2
- package/dist-cli/chunks/{auth-FI5UDI45.js → auth-BHDR3A6G.js} +2 -2
- package/dist-cli/chunks/{beta-JV6UKADW.js → beta-LWUVCPYK.js} +2 -2
- package/dist-cli/chunks/camera-CNO6B2JZ.js +33 -0
- package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-25VCR44B.js} +1 -1
- package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-26CSIR76.js} +8 -9
- package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-26WMWUH4.js} +1 -1
- package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-2JZ53D4A.js} +1 -1
- package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-2POODCTW.js} +2 -2
- package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-4LTBK3ZN.js} +2 -2
- package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-54MIRTFE.js} +4 -4
- package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-56H6EVO4.js} +2 -2
- package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-657SQG4D.js} +1 -1
- package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-6ZMRJPKI.js} +1 -1
- package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-AOGGOC4V.js} +2 -2
- package/dist-cli/chunks/chunk-BPCDO7ST.js +15 -0
- package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-C5O5CTXJ.js} +1 -1
- package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-CMM64PPR.js} +1 -1
- package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-D3M36D7O.js} +62 -87
- package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-DNCNFZ7V.js} +1 -1
- package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-FNTTIR2P.js} +2 -2
- package/dist-cli/chunks/chunk-H362IX2I.js +4 -0
- package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-J6HMTUZH.js} +2 -2
- package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-JZ6VTZ5B.js} +3 -3
- package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-KQSJVNFE.js} +4 -4
- package/dist-cli/chunks/chunk-L4JZKVCC.js +6 -0
- package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-LP2BTEJ6.js} +2 -2
- package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-LT6UC7I3.js} +2 -2
- package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-MCKQH4AM.js} +2 -2
- package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-MF7WUHQ3.js} +2 -2
- package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-MSSY4EEZ.js} +1 -1
- package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-N5ZCYP5F.js} +2 -2
- package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-NCKAD3V7.js} +2 -2
- package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-O2KRHVTU.js} +2 -2
- package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-OF2HTH25.js} +2 -2
- package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-OXS2IWO2.js} +2 -2
- package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-PVL7XSPN.js} +1 -1
- package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-PVPAP3TV.js} +1 -1
- package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-PXNAZYGV.js} +1 -1
- package/dist-cli/chunks/chunk-QR3HTFRB.js +5 -0
- package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-QR7MWAWE.js} +1 -1
- package/dist-cli/chunks/chunk-RJIEZ2NY.js +4 -0
- package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RVM4EZ4E.js} +2 -2
- package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-SZKSFMWS.js} +1 -1
- package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-TEL7G234.js} +2 -2
- package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-U2HNIHBY.js} +1 -1
- package/dist-cli/chunks/chunk-UROXJVY3.js +27 -0
- package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-WM32MGTJ.js} +2 -2
- package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-WMZ7NJAO.js} +89 -133
- package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-WUXCH6WN.js} +10 -9
- package/dist-cli/chunks/chunk-XOXGC3EH.js +9 -0
- package/dist-cli/chunks/chunk-XSSHENNY.js +4 -0
- package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-XZ6O67AR.js} +1 -1
- package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-Y2MWQKOS.js} +3 -3
- package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-YY24QI25.js} +1 -1
- package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-ZWX6DDIS.js} +2 -2
- package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-F3NUJ3SL.js} +2 -2
- package/dist-cli/chunks/cli-version-XIW6O3FG.js +4 -0
- package/dist-cli/chunks/{compat-ZD65FED3.js → compat-AX2SEPTH.js} +2 -2
- package/dist-cli/chunks/{config-XMJRNM2A.js → config-4QQO5JVU.js} +2 -2
- package/dist-cli/chunks/{control-KMIQT3QP.js → control-OCKKSOWA.js} +2 -2
- package/dist-cli/chunks/daemon-N5VLMYKQ.js +4 -0
- package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-T6MWVEVX.js} +5 -5
- package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-NCW7R7CB.js} +3 -3
- package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-G6GITO2X.js} +2 -2
- package/dist-cli/chunks/{device-XBNDSB2R.js → device-7BTEJCTH.js} +2 -2
- package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-SC5LACE3.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KK56QQZA.js} +2 -2
- package/dist-cli/chunks/drivers-NPGVBWMG.js +4 -0
- package/dist-cli/chunks/{film-BJGTBYZB.js → film-WGYEHGIA.js} +3 -3
- package/dist-cli/chunks/flow-KQBIBM3N.js +4 -0
- package/dist-cli/chunks/help-G7CAKI65.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-CWTZWH3L.js} +2 -2
- package/dist-cli/chunks/home-paths-EBT4XHAS.js +4 -0
- package/dist-cli/chunks/inspect-CCPZXVDU.js +4 -0
- package/dist-cli/chunks/install-desktop-NZ3VGTQZ.js +4 -0
- package/dist-cli/chunks/{login-FJ737MWG.js → login-GSYOTGVQ.js} +4 -4
- package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-JPRIR7YK.js} +2 -2
- package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-LXKDNO5M.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-5ZIKOU53.js} +3 -3
- package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-N3QHXCES.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-XDH6X24N.js} +2 -2
- package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-VOPL26FM.js} +2 -2
- package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-CZFKM4UD.js} +2 -2
- package/dist-cli/chunks/{record-QPPC2S4E.js → record-FODSOGMA.js} +3 -3
- package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-FBPCZKOV.js} +2 -2
- package/dist-cli/chunks/reset-3H35GFO3.js +4 -0
- package/dist-cli/chunks/runtime-4OVFRXV5.js +4 -0
- package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7S3FYVO7.js} +7 -7
- package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-CDYHPNC3.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-EBIIY2YU.js} +2 -2
- package/dist-cli/chunks/serve-NELNSCZP.js +44 -0
- package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-DF5ZDDIV.js} +2 -2
- package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-E2QZF6WZ.js} +2 -2
- package/dist-cli/chunks/state-MBZDKZ7U.js +14 -0
- package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-J5BMNVXM.js} +6 -6
- package/dist-cli/chunks/store-U3DXC7HH.js +4 -0
- package/dist-cli/chunks/telemetry-XIPJVT5E.js +4 -0
- package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-MC6N5BHY.js} +2 -2
- package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-7UTU53DH.js} +2 -2
- package/dist-cli/chunks/upload-2M2KOTYI.js +4 -0
- package/dist-cli/chunks/version-VNACNYQK.js +6 -0
- package/dist-cli/chunks/{web-DG3WBYD3.js → web-MGJ2TUKR.js} +2 -2
- package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-7DLKH3OD.js} +3 -3
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract.cjs +20 -0
- 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 +1 -1
- package/dist-lib/home-paths.cjs +67 -28
- package/dist-lib/host/bridge-host.cjs +140 -12
- 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/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2815 -40
- 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.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +2549 -2061
- package/dist-lib/sdk.mjs +2543 -2061
- package/dist-lib/skills.cjs +480 -280
- package/dist-lib/vite.cjs +1 -1
- package/package.json +8 -2
- package/src/bridge-constants.ts +3 -4
- package/src/bridge-contract.ts +251 -0
- package/src/connect.ts +83 -0
- package/src/disk-cleanup.ts +30 -0
- package/src/home-paths.ts +81 -38
- package/src/host/bridge-host.ts +134 -6
- package/src/index.ts +27 -1
- package/src/sdk.ts +8 -0
- package/src/sim-client.ts +660 -0
- package/dist-cli/chunks/camera-VL73YIKP.js +0 -22
- package/dist-cli/chunks/chunk-4NPPOV2N.js +0 -5
- package/dist-cli/chunks/chunk-FSUYIVJ6.js +0 -9
- package/dist-cli/chunks/chunk-G2WW6L2C.js +0 -23
- package/dist-cli/chunks/chunk-KTHV3RUS.js +0 -26
- package/dist-cli/chunks/chunk-LF2ZVT7O.js +0 -6
- package/dist-cli/chunks/chunk-NFK7T35W.js +0 -4
- package/dist-cli/chunks/chunk-TIVZIMMW.js +0 -4
- package/dist-cli/chunks/cli-version-WWLPBDQ7.js +0 -4
- package/dist-cli/chunks/daemon-G2ME7NLB.js +0 -4
- package/dist-cli/chunks/drivers-LDECZGP2.js +0 -4
- package/dist-cli/chunks/flow-UEQNVTU7.js +0 -4
- package/dist-cli/chunks/help-T5FYSVGB.js +0 -4
- package/dist-cli/chunks/home-paths-GT3LFNOR.js +0 -4
- package/dist-cli/chunks/inspect-ZA6XF5LD.js +0 -4
- package/dist-cli/chunks/install-desktop-TIMUDHPL.js +0 -4
- package/dist-cli/chunks/runtime-XOAXMSTU.js +0 -4
- package/dist-cli/chunks/serve-BI2NBAXG.js +0 -44
- package/dist-cli/chunks/store-JTHEJLAZ.js +0 -4
- package/dist-cli/chunks/telemetry-ZYJGD2DB.js +0 -4
- package/dist-cli/chunks/upload-GMSZPWM6.js +0 -4
- package/dist-cli/chunks/version-HOCHZ37L.js +0 -6
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.315 | (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;
|
|
@@ -9436,9 +9436,9 @@ function safeChildPlistName(value) {
|
|
|
9436
9436
|
name: file.toLowerCase().endsWith(".plist") ? file : `${file}.plist`
|
|
9437
9437
|
};
|
|
9438
9438
|
}
|
|
9439
|
-
async function readableSettingsBundle(
|
|
9439
|
+
async function readableSettingsBundle(path17) {
|
|
9440
9440
|
try {
|
|
9441
|
-
const root = await (0, import_promises.stat)((0, import_node_path.join)(
|
|
9441
|
+
const root = await (0, import_promises.stat)((0, import_node_path.join)(path17, "Root.plist"));
|
|
9442
9442
|
return root.isFile() && root.size <= MAX_PLIST_BYTES;
|
|
9443
9443
|
} catch {
|
|
9444
9444
|
return false;
|
|
@@ -9483,11 +9483,11 @@ async function settingsBundleFingerprint(bundlePath) {
|
|
|
9483
9483
|
return null;
|
|
9484
9484
|
}
|
|
9485
9485
|
}
|
|
9486
|
-
async function parsePlistRecord(
|
|
9486
|
+
async function parsePlistRecord(path17) {
|
|
9487
9487
|
try {
|
|
9488
|
-
const metadata = await (0, import_promises.stat)(
|
|
9488
|
+
const metadata = await (0, import_promises.stat)(path17);
|
|
9489
9489
|
if (!metadata.isFile() || metadata.size > MAX_PLIST_BYTES) return null;
|
|
9490
|
-
const source = await (0, import_promises.readFile)(
|
|
9490
|
+
const source = await (0, import_promises.readFile)(path17, "utf8");
|
|
9491
9491
|
const parsed = parsePlistSource(source);
|
|
9492
9492
|
return isRecord2(parsed) ? parsed : null;
|
|
9493
9493
|
} catch {
|
|
@@ -9766,10 +9766,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
9766
9766
|
sock.connect(port, "localhost");
|
|
9767
9767
|
});
|
|
9768
9768
|
}
|
|
9769
|
-
function httpGet(port,
|
|
9769
|
+
function httpGet(port, path17, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
9770
9770
|
return new Promise((resolve7) => {
|
|
9771
9771
|
const req = import_http.default.request(
|
|
9772
|
-
{ hostname: "localhost", port, path:
|
|
9772
|
+
{ hostname: "localhost", port, path: path17, method, timeout, headers },
|
|
9773
9773
|
(res) => {
|
|
9774
9774
|
let body = "";
|
|
9775
9775
|
res.on("data", (c) => body += c.toString());
|
|
@@ -10330,11 +10330,12 @@ __export(home_paths_exports, {
|
|
|
10330
10330
|
CONFIG_FILE: () => CONFIG_FILE,
|
|
10331
10331
|
DAEMON_HEARTBEAT_STALE_MS: () => DAEMON_HEARTBEAT_STALE_MS,
|
|
10332
10332
|
DAEMON_LOCKFILE: () => DAEMON_LOCKFILE,
|
|
10333
|
-
|
|
10333
|
+
DEV_BRIDGES_DIR: () => DEV_BRIDGES_DIR,
|
|
10334
10334
|
SOOTSIM_HOME_ENV: () => SOOTSIM_HOME_ENV,
|
|
10335
10335
|
activeRuntimeDir: () => activeRuntimeDir,
|
|
10336
10336
|
activeRuntimeFile: () => activeRuntimeFile,
|
|
10337
10337
|
cacheDir: () => cacheDir,
|
|
10338
|
+
cameraFixturesDir: () => cameraFixturesDir,
|
|
10338
10339
|
claimDaemonLockfile: () => claimDaemonLockfile,
|
|
10339
10340
|
configFilePath: () => configFilePath,
|
|
10340
10341
|
consumeRuntimeUpgradeNotice: () => consumeRuntimeUpgradeNotice,
|
|
@@ -10343,6 +10344,7 @@ __export(home_paths_exports, {
|
|
|
10343
10344
|
daemonAppLauncherPath: () => daemonAppLauncherPath,
|
|
10344
10345
|
daemonLockfilePath: () => daemonLockfilePath,
|
|
10345
10346
|
devBridgeLockfilePath: () => devBridgeLockfilePath,
|
|
10347
|
+
devBridgesDir: () => devBridgesDir,
|
|
10346
10348
|
electronDir: () => electronDir,
|
|
10347
10349
|
electronUserDataDir: () => electronUserDataDir,
|
|
10348
10350
|
electronVersionDir: () => electronVersionDir,
|
|
@@ -10354,7 +10356,7 @@ __export(home_paths_exports, {
|
|
|
10354
10356
|
profilesDir: () => profilesDir,
|
|
10355
10357
|
readActiveRuntime: () => readActiveRuntime,
|
|
10356
10358
|
readDaemonLockfile: () => readDaemonLockfile,
|
|
10357
|
-
|
|
10359
|
+
readDevBridgeLockfiles: () => readDevBridgeLockfiles,
|
|
10358
10360
|
readLiveRuntimeVersions: () => readLiveRuntimeVersions,
|
|
10359
10361
|
readOrCreateAnonymousId: () => readOrCreateAnonymousId,
|
|
10360
10362
|
readPrivacyPreferences: () => readPrivacyPreferences,
|
|
@@ -10420,6 +10422,9 @@ function electronVersionDir(version) {
|
|
|
10420
10422
|
function profilesDir() {
|
|
10421
10423
|
return import_node_path4.default.join(sootsimHomeDir(), "profiles");
|
|
10422
10424
|
}
|
|
10425
|
+
function cameraFixturesDir() {
|
|
10426
|
+
return import_node_path4.default.join(sootsimHomeDir(), "camera-fixtures");
|
|
10427
|
+
}
|
|
10423
10428
|
function daemonAppDir() {
|
|
10424
10429
|
return import_node_path4.default.join(sootsimHomeDir(), "daemon-app");
|
|
10425
10430
|
}
|
|
@@ -10435,8 +10440,14 @@ function cacheDir() {
|
|
|
10435
10440
|
function daemonLockfilePath() {
|
|
10436
10441
|
return import_node_path4.default.join(sootsimHomeDir(), DAEMON_LOCKFILE);
|
|
10437
10442
|
}
|
|
10438
|
-
function
|
|
10439
|
-
return import_node_path4.default.join(sootsimHomeDir(),
|
|
10443
|
+
function devBridgesDir() {
|
|
10444
|
+
return import_node_path4.default.join(sootsimHomeDir(), DEV_BRIDGES_DIR);
|
|
10445
|
+
}
|
|
10446
|
+
function devBridgeLockfilePath(bridgePort) {
|
|
10447
|
+
if (!Number.isInteger(bridgePort) || bridgePort <= 0) {
|
|
10448
|
+
throw new Error(`invalid development bridge port: ${bridgePort}`);
|
|
10449
|
+
}
|
|
10450
|
+
return import_node_path4.default.join(devBridgesDir(), `${bridgePort}.json`);
|
|
10440
10451
|
}
|
|
10441
10452
|
function configFilePath() {
|
|
10442
10453
|
return import_node_path4.default.join(sootsimHomeDir(), CONFIG_FILE);
|
|
@@ -10565,25 +10576,47 @@ function readDaemonLockfile() {
|
|
|
10565
10576
|
return null;
|
|
10566
10577
|
}
|
|
10567
10578
|
}
|
|
10568
|
-
function
|
|
10579
|
+
function parseDevBridgeLockfile(raw) {
|
|
10569
10580
|
try {
|
|
10570
|
-
const
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
const bytesRead = import_node_fs3.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
|
|
10574
|
-
const raw = buf.subarray(0, bytesRead).toString("utf8");
|
|
10575
|
-
const parsed = JSON.parse(raw);
|
|
10576
|
-
if (parsed && parsed.schema === 1 && parsed.source === "vite-dev" && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.cwd === "string" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number" && (parsed.shellPort === void 0 || typeof parsed.shellPort === "number") && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
|
|
10577
|
-
return parsed;
|
|
10578
|
-
}
|
|
10579
|
-
return null;
|
|
10580
|
-
} finally {
|
|
10581
|
-
import_node_fs3.default.closeSync(fd);
|
|
10581
|
+
const parsed = JSON.parse(raw);
|
|
10582
|
+
if (parsed && parsed.schema === 1 && parsed.source === "vite-dev" && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.cwd === "string" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number" && (parsed.shellPort === void 0 || typeof parsed.shellPort === "number") && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
|
|
10583
|
+
return parsed;
|
|
10582
10584
|
}
|
|
10585
|
+
return null;
|
|
10583
10586
|
} catch {
|
|
10584
10587
|
return null;
|
|
10585
10588
|
}
|
|
10586
10589
|
}
|
|
10590
|
+
function readDevBridgeLockfiles() {
|
|
10591
|
+
let entries;
|
|
10592
|
+
try {
|
|
10593
|
+
entries = import_node_fs3.default.readdirSync(devBridgesDir(), { withFileTypes: true });
|
|
10594
|
+
} catch {
|
|
10595
|
+
return [];
|
|
10596
|
+
}
|
|
10597
|
+
const lockfiles = [];
|
|
10598
|
+
for (const entry of entries) {
|
|
10599
|
+
if (!entry.isFile() || !/^\d+\.json$/.test(entry.name)) continue;
|
|
10600
|
+
try {
|
|
10601
|
+
const filePath = import_node_path4.default.join(devBridgesDir(), entry.name);
|
|
10602
|
+
const fd = import_node_fs3.default.openSync(filePath, "r");
|
|
10603
|
+
try {
|
|
10604
|
+
const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
|
|
10605
|
+
const bytesRead = import_node_fs3.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
|
|
10606
|
+
const lockfile = parseDevBridgeLockfile(
|
|
10607
|
+
buf.subarray(0, bytesRead).toString("utf8")
|
|
10608
|
+
);
|
|
10609
|
+
if (lockfile && entry.name === `${lockfile.bridgePort}.json`) {
|
|
10610
|
+
lockfiles.push(lockfile);
|
|
10611
|
+
}
|
|
10612
|
+
} finally {
|
|
10613
|
+
import_node_fs3.default.closeSync(fd);
|
|
10614
|
+
}
|
|
10615
|
+
} catch {
|
|
10616
|
+
}
|
|
10617
|
+
}
|
|
10618
|
+
return lockfiles.sort((left, right) => left.bridgePort - right.bridgePort);
|
|
10619
|
+
}
|
|
10587
10620
|
function isDaemonLockfileFresh(lock, now = Date.now()) {
|
|
10588
10621
|
if (!lock) return false;
|
|
10589
10622
|
if (now - lock.heartbeatAt > DAEMON_HEARTBEAT_STALE_MS) return false;
|
|
@@ -10611,8 +10644,8 @@ function readLiveRuntimeVersions() {
|
|
|
10611
10644
|
if (daemon.activeRuntime) versions.add(daemon.activeRuntime);
|
|
10612
10645
|
for (const version of daemon.servedRuntimes ?? []) versions.add(version);
|
|
10613
10646
|
}
|
|
10614
|
-
const devBridge
|
|
10615
|
-
|
|
10647
|
+
for (const devBridge of readDevBridgeLockfiles()) {
|
|
10648
|
+
if (!isDevBridgeLockfileFresh(devBridge)) continue;
|
|
10616
10649
|
for (const version of devBridge.servedRuntimes ?? []) versions.add(version);
|
|
10617
10650
|
}
|
|
10618
10651
|
return [...versions].sort();
|
|
@@ -10625,11 +10658,12 @@ function writeDaemonLockfile(data) {
|
|
|
10625
10658
|
import_node_fs3.default.renameSync(tmp, daemonLockfilePath());
|
|
10626
10659
|
}
|
|
10627
10660
|
function writeDevBridgeLockfile(data) {
|
|
10628
|
-
|
|
10629
|
-
const
|
|
10661
|
+
import_node_fs3.default.mkdirSync(devBridgesDir(), { recursive: true });
|
|
10662
|
+
const lockfilePath = devBridgeLockfilePath(data.bridgePort);
|
|
10663
|
+
const tmp = `${lockfilePath}.${data.pid}.tmp`;
|
|
10630
10664
|
import_node_fs3.default.writeFileSync(tmp, `${JSON.stringify(data, null, 2)}
|
|
10631
10665
|
`, "utf8");
|
|
10632
|
-
import_node_fs3.default.renameSync(tmp,
|
|
10666
|
+
import_node_fs3.default.renameSync(tmp, lockfilePath);
|
|
10633
10667
|
}
|
|
10634
10668
|
function claimDaemonLockfile(data) {
|
|
10635
10669
|
ensureSootsimHome();
|
|
@@ -10646,13 +10680,16 @@ function removeDaemonLockfile() {
|
|
|
10646
10680
|
} catch {
|
|
10647
10681
|
}
|
|
10648
10682
|
}
|
|
10649
|
-
function removeDevBridgeLockfile() {
|
|
10683
|
+
function removeDevBridgeLockfile(owner) {
|
|
10650
10684
|
try {
|
|
10651
|
-
|
|
10685
|
+
const lockfilePath = devBridgeLockfilePath(owner.bridgePort);
|
|
10686
|
+
const lockfile = parseDevBridgeLockfile(import_node_fs3.default.readFileSync(lockfilePath, "utf8"));
|
|
10687
|
+
if (lockfile?.pid !== owner.pid || lockfile.startedAt !== owner.startedAt) return;
|
|
10688
|
+
import_node_fs3.default.unlinkSync(lockfilePath);
|
|
10652
10689
|
} catch {
|
|
10653
10690
|
}
|
|
10654
10691
|
}
|
|
10655
|
-
var import_node_crypto, import_node_fs3, import_node_os, import_node_path4, SOOTSIM_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE,
|
|
10692
|
+
var import_node_crypto, import_node_fs3, import_node_os, import_node_path4, SOOTSIM_HOME_ENV, ACTIVE_RUNTIME_FILE, DAEMON_LOCKFILE, DEV_BRIDGES_DIR, CONFIG_FILE, DAEMON_HEARTBEAT_STALE_MS, DAEMON_LOCKFILE_MAX_BYTES;
|
|
10656
10693
|
var init_home_paths = __esm({
|
|
10657
10694
|
"src/home-paths.ts"() {
|
|
10658
10695
|
"use strict";
|
|
@@ -10663,7 +10700,7 @@ var init_home_paths = __esm({
|
|
|
10663
10700
|
SOOTSIM_HOME_ENV = "SOOTSIM_HOME";
|
|
10664
10701
|
ACTIVE_RUNTIME_FILE = "active";
|
|
10665
10702
|
DAEMON_LOCKFILE = "daemon.json";
|
|
10666
|
-
|
|
10703
|
+
DEV_BRIDGES_DIR = "dev-bridges";
|
|
10667
10704
|
CONFIG_FILE = "config.json";
|
|
10668
10705
|
DAEMON_HEARTBEAT_STALE_MS = 3e4;
|
|
10669
10706
|
DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
|
|
@@ -13211,7 +13248,7 @@ function unrefTimer(timer) {
|
|
|
13211
13248
|
timer.unref();
|
|
13212
13249
|
}
|
|
13213
13250
|
}
|
|
13214
|
-
var import_child_process3, import_fs2, import_http3, import_path2, import_ws2, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, SootSimBridgeHost;
|
|
13251
|
+
var import_child_process3, import_fs2, import_http3, import_path2, import_ws2, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, CAMERA_FIXTURE_ROUTE, CAMERA_FIXTURE_NAME_RE, SootSimBridgeHost;
|
|
13215
13252
|
var init_bridge_host = __esm({
|
|
13216
13253
|
"src/host/bridge-host.ts"() {
|
|
13217
13254
|
"use strict";
|
|
@@ -13231,7 +13268,14 @@ var init_bridge_host = __esm({
|
|
|
13231
13268
|
init_open_url();
|
|
13232
13269
|
init_websocket_proxy();
|
|
13233
13270
|
SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY = "require-corp";
|
|
13234
|
-
WRITE_COMMAND_TYPES = /* @__PURE__ */ new Set([
|
|
13271
|
+
WRITE_COMMAND_TYPES = /* @__PURE__ */ new Set([
|
|
13272
|
+
"tap",
|
|
13273
|
+
"keyboard",
|
|
13274
|
+
"longPress",
|
|
13275
|
+
"perform",
|
|
13276
|
+
"reset",
|
|
13277
|
+
"camera"
|
|
13278
|
+
]);
|
|
13235
13279
|
FORCE_CLOSE_GRACE_MS = 2e3;
|
|
13236
13280
|
FORCE_CLOSE_TERMINATE_MS = 1e3;
|
|
13237
13281
|
DAEMON_HEARTBEAT_INTERVAL_MS = 5e3;
|
|
@@ -13258,8 +13302,14 @@ var init_bridge_host = __esm({
|
|
|
13258
13302
|
".woff": "font/woff",
|
|
13259
13303
|
".woff2": "font/woff2",
|
|
13260
13304
|
".map": "application/json",
|
|
13261
|
-
".txt": "text/plain; charset=utf-8"
|
|
13305
|
+
".txt": "text/plain; charset=utf-8",
|
|
13306
|
+
".mp4": "video/mp4",
|
|
13307
|
+
".m4v": "video/mp4",
|
|
13308
|
+
".webm": "video/webm",
|
|
13309
|
+
".mov": "video/quicktime"
|
|
13262
13310
|
};
|
|
13311
|
+
CAMERA_FIXTURE_ROUTE = "/__camera-fixtures/";
|
|
13312
|
+
CAMERA_FIXTURE_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
13263
13313
|
SootSimBridgeHost = class _SootSimBridgeHost {
|
|
13264
13314
|
port;
|
|
13265
13315
|
openUrlHandler;
|
|
@@ -14019,6 +14069,89 @@ var init_bridge_host = __esm({
|
|
|
14019
14069
|
});
|
|
14020
14070
|
return this.inflightScan;
|
|
14021
14071
|
}
|
|
14072
|
+
// serves one staged camera fixture. addressed by basename inside
|
|
14073
|
+
// ~/.sootsim/camera-fixtures, never by a caller-supplied path, so there is
|
|
14074
|
+
// no traversal surface to defend: a name that is not a plain basename is
|
|
14075
|
+
// rejected outright. range support is not optional here — chrome asks for
|
|
14076
|
+
// byte ranges on media and cannot seek or loop a fixture without it.
|
|
14077
|
+
handleCameraFixture(name2, req, res) {
|
|
14078
|
+
const method = (req.method || "GET").toUpperCase();
|
|
14079
|
+
const cors = {
|
|
14080
|
+
"Access-Control-Allow-Origin": "*",
|
|
14081
|
+
"Cache-Control": "no-store"
|
|
14082
|
+
};
|
|
14083
|
+
if (method === "OPTIONS") {
|
|
14084
|
+
res.writeHead(204, {
|
|
14085
|
+
...cors,
|
|
14086
|
+
"Access-Control-Allow-Methods": "GET, HEAD, OPTIONS",
|
|
14087
|
+
"Access-Control-Allow-Headers": "range"
|
|
14088
|
+
});
|
|
14089
|
+
res.end();
|
|
14090
|
+
return;
|
|
14091
|
+
}
|
|
14092
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
14093
|
+
res.writeHead(405, cors);
|
|
14094
|
+
res.end();
|
|
14095
|
+
return;
|
|
14096
|
+
}
|
|
14097
|
+
if (!CAMERA_FIXTURE_NAME_RE.test(name2)) {
|
|
14098
|
+
res.writeHead(400, { ...cors, "Content-Type": "text/plain; charset=utf-8" });
|
|
14099
|
+
res.end("bad fixture name");
|
|
14100
|
+
return;
|
|
14101
|
+
}
|
|
14102
|
+
const root = cameraFixturesDir();
|
|
14103
|
+
const filePath = import_path2.default.join(root, name2);
|
|
14104
|
+
let stats;
|
|
14105
|
+
try {
|
|
14106
|
+
stats = import_fs2.default.lstatSync(filePath);
|
|
14107
|
+
} catch {
|
|
14108
|
+
res.writeHead(404, { ...cors, "Content-Type": "text/plain; charset=utf-8" });
|
|
14109
|
+
res.end("not found");
|
|
14110
|
+
return;
|
|
14111
|
+
}
|
|
14112
|
+
if (!stats.isFile()) {
|
|
14113
|
+
res.writeHead(403, { ...cors, "Content-Type": "text/plain; charset=utf-8" });
|
|
14114
|
+
res.end("forbidden");
|
|
14115
|
+
return;
|
|
14116
|
+
}
|
|
14117
|
+
const contentType = HTTP_MIME_TYPES[import_path2.default.extname(filePath).toLowerCase()] || "application/octet-stream";
|
|
14118
|
+
const total = stats.size;
|
|
14119
|
+
const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.range || "");
|
|
14120
|
+
if (range) {
|
|
14121
|
+
const [, startRaw, endRaw] = range;
|
|
14122
|
+
const start = startRaw ? Number(startRaw) : 0;
|
|
14123
|
+
const end = endRaw ? Math.min(Number(endRaw), total - 1) : total - 1;
|
|
14124
|
+
if (!Number.isFinite(start) || start > end || start >= total) {
|
|
14125
|
+
res.writeHead(416, { ...cors, "Content-Range": `bytes */${total}` });
|
|
14126
|
+
res.end();
|
|
14127
|
+
return;
|
|
14128
|
+
}
|
|
14129
|
+
res.writeHead(206, {
|
|
14130
|
+
...cors,
|
|
14131
|
+
"Content-Type": contentType,
|
|
14132
|
+
"Content-Range": `bytes ${start}-${end}/${total}`,
|
|
14133
|
+
"Accept-Ranges": "bytes",
|
|
14134
|
+
"Content-Length": String(end - start + 1)
|
|
14135
|
+
});
|
|
14136
|
+
if (method === "HEAD") {
|
|
14137
|
+
res.end();
|
|
14138
|
+
return;
|
|
14139
|
+
}
|
|
14140
|
+
import_fs2.default.createReadStream(filePath, { start, end }).pipe(res);
|
|
14141
|
+
return;
|
|
14142
|
+
}
|
|
14143
|
+
res.writeHead(200, {
|
|
14144
|
+
...cors,
|
|
14145
|
+
"Content-Type": contentType,
|
|
14146
|
+
"Accept-Ranges": "bytes",
|
|
14147
|
+
"Content-Length": String(total)
|
|
14148
|
+
});
|
|
14149
|
+
if (method === "HEAD") {
|
|
14150
|
+
res.end();
|
|
14151
|
+
return;
|
|
14152
|
+
}
|
|
14153
|
+
import_fs2.default.createReadStream(filePath).pipe(res);
|
|
14154
|
+
}
|
|
14022
14155
|
handleServerScan(res) {
|
|
14023
14156
|
const sendJson = (body) => {
|
|
14024
14157
|
res.writeHead(200, {
|
|
@@ -14242,6 +14375,10 @@ var init_bridge_host = __esm({
|
|
|
14242
14375
|
res.end("method not allowed");
|
|
14243
14376
|
return;
|
|
14244
14377
|
}
|
|
14378
|
+
if (url.pathname.startsWith(CAMERA_FIXTURE_ROUTE)) {
|
|
14379
|
+
this.handleCameraFixture(url.pathname.slice(CAMERA_FIXTURE_ROUTE.length), req, res);
|
|
14380
|
+
return;
|
|
14381
|
+
}
|
|
14245
14382
|
if (method !== "GET" && method !== "HEAD") {
|
|
14246
14383
|
res.writeHead(405, { Allow: "GET, HEAD" });
|
|
14247
14384
|
res.end("method not allowed");
|
|
@@ -14710,7 +14847,11 @@ var init_bridge_host = __esm({
|
|
|
14710
14847
|
}
|
|
14711
14848
|
if (this.shouldWriteDevLockfile) {
|
|
14712
14849
|
try {
|
|
14713
|
-
removeDevBridgeLockfile(
|
|
14850
|
+
removeDevBridgeLockfile({
|
|
14851
|
+
bridgePort: this.effectivePort,
|
|
14852
|
+
pid: process.pid,
|
|
14853
|
+
startedAt: this.startedAt
|
|
14854
|
+
});
|
|
14714
14855
|
} catch {
|
|
14715
14856
|
}
|
|
14716
14857
|
}
|
|
@@ -15465,6 +15606,53 @@ __export(ws_bridge_exports, {
|
|
|
15465
15606
|
resolveDefaultBridgePort: () => resolveDefaultBridgePort,
|
|
15466
15607
|
worldForBridgePort: () => worldForBridgePort
|
|
15467
15608
|
});
|
|
15609
|
+
function liveDevBridgeLockfiles() {
|
|
15610
|
+
return readDevBridgeLockfiles().filter((lockfile) => isDevBridgeLockfileFresh(lockfile));
|
|
15611
|
+
}
|
|
15612
|
+
function checkoutRoot(cwd) {
|
|
15613
|
+
let current = import_node_path10.default.resolve(cwd);
|
|
15614
|
+
while (true) {
|
|
15615
|
+
if (import_node_fs9.default.existsSync(import_node_path10.default.join(current, ".git"))) return current;
|
|
15616
|
+
const parent = import_node_path10.default.dirname(current);
|
|
15617
|
+
if (parent === current) return null;
|
|
15618
|
+
current = parent;
|
|
15619
|
+
}
|
|
15620
|
+
}
|
|
15621
|
+
function pathContains(parent, child) {
|
|
15622
|
+
const relative = import_node_path10.default.relative(parent, child);
|
|
15623
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${import_node_path10.default.sep}`) && !import_node_path10.default.isAbsolute(relative);
|
|
15624
|
+
}
|
|
15625
|
+
function resolveDefaultDevBridgeLockfile() {
|
|
15626
|
+
const lockfiles = liveDevBridgeLockfiles();
|
|
15627
|
+
if (lockfiles.length === 0) return null;
|
|
15628
|
+
if (process.env.SOOTSIM_BRIDGE_PORT !== void 0 || process.env.PORT_OFFSET !== void 0) {
|
|
15629
|
+
const requestedPort = resolveSootsimBridgePort({
|
|
15630
|
+
explicitPort: process.env.SOOTSIM_BRIDGE_PORT,
|
|
15631
|
+
portOffset: process.env.PORT_OFFSET
|
|
15632
|
+
});
|
|
15633
|
+
const requested = lockfiles.find((lockfile) => lockfile.bridgePort === requestedPort);
|
|
15634
|
+
if (requested) return requested;
|
|
15635
|
+
}
|
|
15636
|
+
let cwd = null;
|
|
15637
|
+
try {
|
|
15638
|
+
cwd = process.cwd();
|
|
15639
|
+
} catch {
|
|
15640
|
+
}
|
|
15641
|
+
if (cwd) {
|
|
15642
|
+
const currentCheckout = checkoutRoot(cwd);
|
|
15643
|
+
const sameCheckout = lockfiles.filter((lockfile) => {
|
|
15644
|
+
const bridgeCheckout = checkoutRoot(lockfile.cwd);
|
|
15645
|
+
if (currentCheckout && bridgeCheckout) return currentCheckout === bridgeCheckout;
|
|
15646
|
+
return pathContains(cwd, lockfile.cwd) || pathContains(lockfile.cwd, cwd);
|
|
15647
|
+
});
|
|
15648
|
+
if (sameCheckout.length > 0) {
|
|
15649
|
+
return sameCheckout.find(
|
|
15650
|
+
(lockfile) => lockfile.bridgePort === DEFAULT_SOOTSIM_BRIDGE_PORT
|
|
15651
|
+
) ?? sameCheckout[0];
|
|
15652
|
+
}
|
|
15653
|
+
}
|
|
15654
|
+
return lockfiles.find((lockfile) => lockfile.bridgePort === DEFAULT_SOOTSIM_BRIDGE_PORT) ?? lockfiles[0];
|
|
15655
|
+
}
|
|
15468
15656
|
function resolveBridgeWorld() {
|
|
15469
15657
|
const homeDir = sootsimHomeDir();
|
|
15470
15658
|
if (resolvedWorld?.homeDir === homeDir) return resolvedWorld.world;
|
|
@@ -15473,8 +15661,8 @@ function resolveBridgeWorld() {
|
|
|
15473
15661
|
return world;
|
|
15474
15662
|
}
|
|
15475
15663
|
function resolveBridgeWorldFresh() {
|
|
15476
|
-
const dev =
|
|
15477
|
-
if (dev
|
|
15664
|
+
const dev = resolveDefaultDevBridgeLockfile();
|
|
15665
|
+
if (dev) {
|
|
15478
15666
|
return {
|
|
15479
15667
|
source: "dev-bridge",
|
|
15480
15668
|
bridgePort: dev.bridgePort,
|
|
@@ -15498,8 +15686,8 @@ function resolveBridgeWorldFresh() {
|
|
|
15498
15686
|
};
|
|
15499
15687
|
}
|
|
15500
15688
|
function worldForBridgePort(port) {
|
|
15501
|
-
const dev =
|
|
15502
|
-
if (dev
|
|
15689
|
+
const dev = liveDevBridgeLockfiles().find((lockfile) => lockfile.bridgePort === port);
|
|
15690
|
+
if (dev) {
|
|
15503
15691
|
return {
|
|
15504
15692
|
source: "dev-bridge",
|
|
15505
15693
|
shellBaseUrl: dev.shellPort ? `http://localhost:${dev.shellPort}/` : DEFAULT_SOOTSIM_SHELL_URL
|
|
@@ -15523,8 +15711,10 @@ function bridgePortForShellBaseUrl(baseUrl) {
|
|
|
15523
15711
|
return null;
|
|
15524
15712
|
}
|
|
15525
15713
|
if (!Number.isFinite(port) || port <= 0) return null;
|
|
15526
|
-
const dev =
|
|
15527
|
-
|
|
15714
|
+
const dev = liveDevBridgeLockfiles().find(
|
|
15715
|
+
(lockfile) => lockfile.shellPort === port || lockfile.runtimePort === port || lockfile.bridgePort === port
|
|
15716
|
+
);
|
|
15717
|
+
if (dev) {
|
|
15528
15718
|
return dev.bridgePort;
|
|
15529
15719
|
}
|
|
15530
15720
|
const lock = readDaemonLockfile();
|
|
@@ -15539,7 +15729,7 @@ function resolveDefaultBridgePort() {
|
|
|
15539
15729
|
function printBridgeWorldNotice(bridgePort, shellBaseUrl) {
|
|
15540
15730
|
const world = worldForBridgePort(bridgePort);
|
|
15541
15731
|
const kind = world?.source === "dev-bridge" ? "dev bridge" : world?.source === "daemon" ? "daemon bridge" : "bridge";
|
|
15542
|
-
const origin = world ?
|
|
15732
|
+
const origin = world?.source === "dev-bridge" ? `dev-bridges/${bridgePort}.json` : world?.source === "daemon" ? "daemon.json" : "no lockfile";
|
|
15543
15733
|
const shell = shellBaseUrl ?? world?.shellBaseUrl;
|
|
15544
15734
|
process.stderr.write(
|
|
15545
15735
|
` \u2192 ${kind} :${bridgePort} (${shell ? `shell ${shell}, ` : ""}${origin})
|
|
@@ -15659,6 +15849,8 @@ function createBridge(wsPort, opts = {}) {
|
|
|
15659
15849
|
reject(new Error(`could not connect to ws://localhost:${wsPort}${cause}`));
|
|
15660
15850
|
});
|
|
15661
15851
|
});
|
|
15852
|
+
ready.catch(() => {
|
|
15853
|
+
});
|
|
15662
15854
|
let warnedAboutContention = false;
|
|
15663
15855
|
let noticedTarget = false;
|
|
15664
15856
|
function maybeNoticeTarget(cmdType, simId) {
|
|
@@ -15851,16 +16043,18 @@ async function evalInBridge(bridge, code, opts = {}) {
|
|
|
15851
16043
|
if (opts.acquireLock) payload.acquireLock = true;
|
|
15852
16044
|
return bridge.send(payload);
|
|
15853
16045
|
}
|
|
15854
|
-
async function callInBridge(bridge,
|
|
15855
|
-
return bridge.send({ type: "call", path:
|
|
16046
|
+
async function callInBridge(bridge, path17, ...args) {
|
|
16047
|
+
return bridge.send({ type: "call", path: path17, args });
|
|
15856
16048
|
}
|
|
15857
|
-
async function callInBridgeWrite(bridge,
|
|
15858
|
-
return bridge.send({ type: "call", path:
|
|
16049
|
+
async function callInBridgeWrite(bridge, path17, ...args) {
|
|
16050
|
+
return bridge.send({ type: "call", path: path17, args, acquireLock: true });
|
|
15859
16051
|
}
|
|
15860
|
-
var import_ws3, resolvedWorld, BridgeSimLockedError;
|
|
16052
|
+
var import_node_fs9, import_node_path10, import_ws3, resolvedWorld, BridgeSimLockedError;
|
|
15861
16053
|
var init_ws_bridge = __esm({
|
|
15862
16054
|
"cli/ws-bridge.ts"() {
|
|
15863
16055
|
"use strict";
|
|
16056
|
+
import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
16057
|
+
import_node_path10 = __toESM(require("node:path"), 1);
|
|
15864
16058
|
import_ws3 = require("ws");
|
|
15865
16059
|
init_bridge_constants();
|
|
15866
16060
|
init_cli_constants();
|
|
@@ -15915,8 +16109,8 @@ function getDefaultPortForProtocol(protocol) {
|
|
|
15915
16109
|
return protocol === "https:" ? 443 : 80;
|
|
15916
16110
|
}
|
|
15917
16111
|
function isBaseServerUrl(url) {
|
|
15918
|
-
const
|
|
15919
|
-
return (
|
|
16112
|
+
const path17 = url.pathname || "/";
|
|
16113
|
+
return (path17 === "/" || path17 === "") && !url.search && !url.hash;
|
|
15920
16114
|
}
|
|
15921
16115
|
async function resolvePortViaServerScan(port) {
|
|
15922
16116
|
try {
|
|
@@ -16136,9 +16330,9 @@ var init_profiles = __esm({
|
|
|
16136
16330
|
// cli/app-project.ts
|
|
16137
16331
|
function firstNamedFile(dir, names) {
|
|
16138
16332
|
for (const name2 of names) {
|
|
16139
|
-
const candidate =
|
|
16333
|
+
const candidate = import_node_path11.default.join(dir, name2);
|
|
16140
16334
|
try {
|
|
16141
|
-
if (
|
|
16335
|
+
if (import_node_fs10.default.statSync(candidate).isFile()) return candidate;
|
|
16142
16336
|
} catch {
|
|
16143
16337
|
}
|
|
16144
16338
|
}
|
|
@@ -16152,7 +16346,7 @@ function findSootSimAppConfig(dir) {
|
|
|
16152
16346
|
}
|
|
16153
16347
|
function readWorkspacePatterns(rootDir) {
|
|
16154
16348
|
try {
|
|
16155
|
-
const value = JSON.parse(
|
|
16349
|
+
const value = JSON.parse(import_node_fs10.default.readFileSync(import_node_path11.default.join(rootDir, "package.json"), "utf8"));
|
|
16156
16350
|
if (!value || typeof value !== "object") return [];
|
|
16157
16351
|
const workspaces = Reflect.get(value, "workspaces");
|
|
16158
16352
|
if (Array.isArray(workspaces)) {
|
|
@@ -16174,7 +16368,7 @@ function workspaceDirectories(rootDir) {
|
|
|
16174
16368
|
complete = false;
|
|
16175
16369
|
break;
|
|
16176
16370
|
}
|
|
16177
|
-
if (!pattern ||
|
|
16371
|
+
if (!pattern || import_node_path11.default.isAbsolute(pattern)) continue;
|
|
16178
16372
|
const segments = pattern.split(/[\\/]+/).filter(Boolean);
|
|
16179
16373
|
if (segments.length === 0 || segments.length > MAX_SCAN_DEPTH) continue;
|
|
16180
16374
|
if (segments.some((segment) => segment === ".." || segment === "**")) continue;
|
|
@@ -16190,19 +16384,19 @@ function workspaceDirectories(rootDir) {
|
|
|
16190
16384
|
if (segment === "*") {
|
|
16191
16385
|
let entries;
|
|
16192
16386
|
try {
|
|
16193
|
-
entries =
|
|
16387
|
+
entries = import_node_fs10.default.readdirSync(parent, { withFileTypes: true });
|
|
16194
16388
|
} catch {
|
|
16195
16389
|
continue;
|
|
16196
16390
|
}
|
|
16197
16391
|
for (const entry of entries) {
|
|
16198
16392
|
if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
|
|
16199
16393
|
if (entry.name.startsWith(".") || SKIP_DIR_NAMES.has(entry.name)) continue;
|
|
16200
|
-
next.push(
|
|
16394
|
+
next.push(import_node_path11.default.join(parent, entry.name));
|
|
16201
16395
|
}
|
|
16202
16396
|
} else if (!segment.includes("*")) {
|
|
16203
|
-
const candidate =
|
|
16397
|
+
const candidate = import_node_path11.default.join(parent, segment);
|
|
16204
16398
|
try {
|
|
16205
|
-
const stat2 =
|
|
16399
|
+
const stat2 = import_node_fs10.default.lstatSync(candidate);
|
|
16206
16400
|
if (stat2.isDirectory() && !stat2.isSymbolicLink()) next.push(candidate);
|
|
16207
16401
|
} catch {
|
|
16208
16402
|
}
|
|
@@ -16235,7 +16429,7 @@ function boundedConfigDirectories(rootDir) {
|
|
|
16235
16429
|
if (current.depth >= MAX_SCAN_DEPTH) continue;
|
|
16236
16430
|
let entries;
|
|
16237
16431
|
try {
|
|
16238
|
-
entries =
|
|
16432
|
+
entries = import_node_fs10.default.readdirSync(current.dir, { withFileTypes: true });
|
|
16239
16433
|
} catch {
|
|
16240
16434
|
continue;
|
|
16241
16435
|
}
|
|
@@ -16246,22 +16440,22 @@ function boundedConfigDirectories(rootDir) {
|
|
|
16246
16440
|
complete = false;
|
|
16247
16441
|
break;
|
|
16248
16442
|
}
|
|
16249
|
-
queue.push({ dir:
|
|
16443
|
+
queue.push({ dir: import_node_path11.default.join(current.dir, entry.name), depth: current.depth + 1 });
|
|
16250
16444
|
}
|
|
16251
16445
|
}
|
|
16252
16446
|
return { directories: matches, complete: complete && nextIndex === queue.length };
|
|
16253
16447
|
}
|
|
16254
16448
|
function resolveAppProject(startDir, opts = {}) {
|
|
16255
|
-
const rootDir =
|
|
16449
|
+
const rootDir = import_node_path11.default.resolve(startDir);
|
|
16256
16450
|
const rootConfigPath = findSootSimAppConfig(rootDir);
|
|
16257
|
-
if (findExpoAppConfig(rootDir) || opts.trustStart &&
|
|
16451
|
+
if (findExpoAppConfig(rootDir) || opts.trustStart && import_node_fs10.default.existsSync(rootDir)) {
|
|
16258
16452
|
let configPath = rootConfigPath;
|
|
16259
16453
|
if (!configPath && opts.trustStart) {
|
|
16260
|
-
let parent =
|
|
16261
|
-
for (let depth = 0; depth < MAX_SCAN_DEPTH && parent !==
|
|
16454
|
+
let parent = import_node_path11.default.dirname(rootDir);
|
|
16455
|
+
for (let depth = 0; depth < MAX_SCAN_DEPTH && parent !== import_node_path11.default.dirname(parent); depth++) {
|
|
16262
16456
|
configPath = findSootSimAppConfig(parent);
|
|
16263
16457
|
if (configPath) break;
|
|
16264
|
-
parent =
|
|
16458
|
+
parent = import_node_path11.default.dirname(parent);
|
|
16265
16459
|
}
|
|
16266
16460
|
}
|
|
16267
16461
|
return { appDir: rootDir, configPath };
|
|
@@ -16293,12 +16487,12 @@ function resolveAppProject(startDir, opts = {}) {
|
|
|
16293
16487
|
if (rootConfigPath) return { appDir: rootDir, configPath: rootConfigPath };
|
|
16294
16488
|
return null;
|
|
16295
16489
|
}
|
|
16296
|
-
var
|
|
16490
|
+
var import_node_fs10, import_node_path11, EXPO_APP_CONFIG_NAMES, SOOTSIM_APP_CONFIG_NAMES, SKIP_DIR_NAMES, MAX_SCANNED_DIRECTORIES, MAX_SCAN_DEPTH;
|
|
16297
16491
|
var init_app_project = __esm({
|
|
16298
16492
|
"cli/app-project.ts"() {
|
|
16299
16493
|
"use strict";
|
|
16300
|
-
|
|
16301
|
-
|
|
16494
|
+
import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
16495
|
+
import_node_path11 = __toESM(require("node:path"), 1);
|
|
16302
16496
|
EXPO_APP_CONFIG_NAMES = [
|
|
16303
16497
|
"app.config.js",
|
|
16304
16498
|
"app.config.ts",
|
|
@@ -16399,7 +16593,7 @@ function localOriginOf(value) {
|
|
|
16399
16593
|
}
|
|
16400
16594
|
function hasPackageJson(dir) {
|
|
16401
16595
|
try {
|
|
16402
|
-
return
|
|
16596
|
+
return import_node_fs11.default.statSync(import_node_path12.default.join(dir, "package.json")).isFile();
|
|
16403
16597
|
} catch {
|
|
16404
16598
|
return false;
|
|
16405
16599
|
}
|
|
@@ -16408,7 +16602,7 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
16408
16602
|
const metroOrigin = localOriginOf(opts.bundleUrl);
|
|
16409
16603
|
if (!metroOrigin) return [];
|
|
16410
16604
|
const explicit = opts.repoDir || process.env.CONTRAST_REPO_DIR;
|
|
16411
|
-
const startDir = explicit ?
|
|
16605
|
+
const startDir = explicit ? import_node_path12.default.resolve(explicit) : process.cwd();
|
|
16412
16606
|
if (!explicit && !hasPackageJson(startDir)) return [];
|
|
16413
16607
|
const project = resolveAppProject(startDir, { trustStart: opts.exactProjectDir });
|
|
16414
16608
|
const selectedAppDir = project?.appDir ?? null;
|
|
@@ -16454,13 +16648,13 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
16454
16648
|
scannedFontDirectories++;
|
|
16455
16649
|
let entries;
|
|
16456
16650
|
try {
|
|
16457
|
-
entries =
|
|
16651
|
+
entries = import_node_fs11.default.readdirSync(current.dir, { withFileTypes: true });
|
|
16458
16652
|
} catch {
|
|
16459
16653
|
continue;
|
|
16460
16654
|
}
|
|
16461
16655
|
for (const entry of entries) {
|
|
16462
16656
|
if (entry.isSymbolicLink()) continue;
|
|
16463
|
-
const fullPath =
|
|
16657
|
+
const fullPath = import_node_path12.default.join(current.dir, entry.name);
|
|
16464
16658
|
if (entry.isDirectory()) {
|
|
16465
16659
|
if (current.depth < 4 && pending.length < 64 && !entry.name.startsWith(".")) {
|
|
16466
16660
|
pending.push({ dir: fullPath, depth: current.depth + 1 });
|
|
@@ -16468,15 +16662,15 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
16468
16662
|
continue;
|
|
16469
16663
|
}
|
|
16470
16664
|
if (!entry.isFile() || !/\.(ttf|otf|woff|woff2)$/i.test(entry.name)) continue;
|
|
16471
|
-
const relative =
|
|
16472
|
-
fontPaths.push(
|
|
16665
|
+
const relative = import_node_path12.default.relative(root, fullPath).split(import_node_path12.default.sep).join("/");
|
|
16666
|
+
fontPaths.push(import_node_path12.default.posix.join(metroPathPrefix, relative));
|
|
16473
16667
|
if (fontPaths.length >= 256) break;
|
|
16474
16668
|
}
|
|
16475
16669
|
}
|
|
16476
16670
|
};
|
|
16477
16671
|
try {
|
|
16478
16672
|
const packageJson = JSON.parse(
|
|
16479
|
-
|
|
16673
|
+
import_node_fs11.default.readFileSync(import_node_path12.default.join(selectedAppDir, "package.json"), "utf8")
|
|
16480
16674
|
);
|
|
16481
16675
|
const dependencyNames = /* @__PURE__ */ new Set();
|
|
16482
16676
|
for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
|
|
@@ -16491,24 +16685,24 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
16491
16685
|
const config = Reflect.get(packageJson, "reactNativeVectorIcons");
|
|
16492
16686
|
const configuredFontDir = config && typeof config === "object" ? Reflect.get(config, "fontDir") : null;
|
|
16493
16687
|
const configuredDir = typeof configuredFontDir === "string" ? configuredFontDir : "rnvi-fonts";
|
|
16494
|
-
const root =
|
|
16495
|
-
const relativeRoot =
|
|
16496
|
-
if (!relativeRoot.startsWith("..") && !
|
|
16497
|
-
collectFontFiles(root, relativeRoot.split(
|
|
16688
|
+
const root = import_node_path12.default.resolve(selectedAppDir, configuredDir);
|
|
16689
|
+
const relativeRoot = import_node_path12.default.relative(selectedAppDir, root);
|
|
16690
|
+
if (!relativeRoot.startsWith("..") && !import_node_path12.default.isAbsolute(relativeRoot)) {
|
|
16691
|
+
collectFontFiles(root, relativeRoot.split(import_node_path12.default.sep).join("/"));
|
|
16498
16692
|
}
|
|
16499
|
-
const vectorIconRequire = (0, import_node_module2.createRequire)(
|
|
16693
|
+
const vectorIconRequire = (0, import_node_module2.createRequire)(import_node_path12.default.join(selectedAppDir, "package.json"));
|
|
16500
16694
|
for (const dependencyName of vectorIconDependencies) {
|
|
16501
16695
|
try {
|
|
16502
16696
|
const entryPath = vectorIconRequire.resolve(dependencyName);
|
|
16503
|
-
const dependencyPath = dependencyName.split("/").join(
|
|
16504
|
-
const marker = `${
|
|
16697
|
+
const dependencyPath = dependencyName.split("/").join(import_node_path12.default.sep);
|
|
16698
|
+
const marker = `${import_node_path12.default.sep}node_modules${import_node_path12.default.sep}${dependencyPath}${import_node_path12.default.sep}`;
|
|
16505
16699
|
const markerIndex = entryPath.lastIndexOf(marker);
|
|
16506
16700
|
if (markerIndex === -1) continue;
|
|
16507
16701
|
const packageRoot = entryPath.slice(0, markerIndex + marker.length - 1);
|
|
16508
16702
|
const fontsDir = dependencyName === "react-native-vector-icons" ? "Fonts" : "fonts";
|
|
16509
16703
|
collectFontFiles(
|
|
16510
|
-
|
|
16511
|
-
|
|
16704
|
+
import_node_path12.default.join(packageRoot, fontsDir),
|
|
16705
|
+
import_node_path12.default.posix.join("node_modules", dependencyName, fontsDir)
|
|
16512
16706
|
);
|
|
16513
16707
|
} catch {
|
|
16514
16708
|
}
|
|
@@ -16517,37 +16711,37 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
16517
16711
|
} catch {
|
|
16518
16712
|
}
|
|
16519
16713
|
try {
|
|
16520
|
-
const configPath =
|
|
16521
|
-
if (
|
|
16522
|
-
const appConfigRequire = (0, import_node_module2.createRequire)(
|
|
16714
|
+
const configPath = import_node_path12.default.join(selectedAppDir, "react-native.config.js");
|
|
16715
|
+
if (import_node_fs11.default.statSync(configPath).isFile()) {
|
|
16716
|
+
const appConfigRequire = (0, import_node_module2.createRequire)(import_node_path12.default.join(selectedAppDir, "package.json"));
|
|
16523
16717
|
const rnConfig = appConfigRequire(configPath);
|
|
16524
16718
|
const assets = rnConfig && typeof rnConfig === "object" ? Reflect.get(rnConfig, "assets") : null;
|
|
16525
16719
|
if (Array.isArray(assets)) {
|
|
16526
16720
|
for (const assetDir of assets) {
|
|
16527
16721
|
if (typeof assetDir !== "string") continue;
|
|
16528
|
-
const root =
|
|
16529
|
-
const relativeRoot =
|
|
16530
|
-
if (relativeRoot.startsWith("..") ||
|
|
16531
|
-
collectFontFiles(root, relativeRoot.split(
|
|
16722
|
+
const root = import_node_path12.default.resolve(selectedAppDir, assetDir);
|
|
16723
|
+
const relativeRoot = import_node_path12.default.relative(selectedAppDir, root);
|
|
16724
|
+
if (relativeRoot.startsWith("..") || import_node_path12.default.isAbsolute(relativeRoot)) continue;
|
|
16725
|
+
collectFontFiles(root, relativeRoot.split(import_node_path12.default.sep).join("/"));
|
|
16532
16726
|
}
|
|
16533
16727
|
}
|
|
16534
16728
|
}
|
|
16535
16729
|
} catch {
|
|
16536
16730
|
}
|
|
16537
16731
|
if (platform === "ios") {
|
|
16538
|
-
const iosDir =
|
|
16732
|
+
const iosDir = import_node_path12.default.join(selectedAppDir, "ios");
|
|
16539
16733
|
try {
|
|
16540
|
-
const targetDirs =
|
|
16734
|
+
const targetDirs = import_node_fs11.default.readdirSync(iosDir, { withFileTypes: true }).filter(
|
|
16541
16735
|
(entry) => entry.isDirectory() && !entry.isSymbolicLink() && entry.name !== "Pods" && entry.name !== "build" && !entry.name.startsWith(".")
|
|
16542
16736
|
).slice(0, 64);
|
|
16543
|
-
const plistPaths = [
|
|
16737
|
+
const plistPaths = [import_node_path12.default.join(iosDir, "Info.plist")];
|
|
16544
16738
|
for (const entry of targetDirs) {
|
|
16545
|
-
plistPaths.push(
|
|
16739
|
+
plistPaths.push(import_node_path12.default.join(iosDir, entry.name, "Info.plist"));
|
|
16546
16740
|
}
|
|
16547
16741
|
for (const plistPath of plistPaths) {
|
|
16548
16742
|
let parsed;
|
|
16549
16743
|
try {
|
|
16550
|
-
parsed = parsePlistSource(
|
|
16744
|
+
parsed = parsePlistSource(import_node_fs11.default.readFileSync(plistPath, "utf8"));
|
|
16551
16745
|
} catch {
|
|
16552
16746
|
continue;
|
|
16553
16747
|
}
|
|
@@ -16557,21 +16751,21 @@ function discoverNativeLinkedAppFonts(opts) {
|
|
|
16557
16751
|
for (const declaredFont of declaredFonts) {
|
|
16558
16752
|
if (typeof declaredFont !== "string") continue;
|
|
16559
16753
|
const candidates = [
|
|
16560
|
-
|
|
16561
|
-
|
|
16754
|
+
import_node_path12.default.resolve(import_node_path12.default.dirname(plistPath), declaredFont),
|
|
16755
|
+
import_node_path12.default.resolve(iosDir, declaredFont)
|
|
16562
16756
|
];
|
|
16563
16757
|
const fontPath = candidates.find((candidate) => {
|
|
16564
|
-
const relative =
|
|
16565
|
-
if (relative.startsWith("..") ||
|
|
16758
|
+
const relative = import_node_path12.default.relative(selectedAppDir, candidate);
|
|
16759
|
+
if (relative.startsWith("..") || import_node_path12.default.isAbsolute(relative)) return false;
|
|
16566
16760
|
try {
|
|
16567
|
-
return
|
|
16761
|
+
return import_node_fs11.default.statSync(candidate).isFile();
|
|
16568
16762
|
} catch {
|
|
16569
16763
|
return false;
|
|
16570
16764
|
}
|
|
16571
16765
|
});
|
|
16572
16766
|
if (!fontPath) continue;
|
|
16573
16767
|
fontPaths.push(
|
|
16574
|
-
|
|
16768
|
+
import_node_path12.default.relative(selectedAppDir, fontPath).split(import_node_path12.default.sep).join("/")
|
|
16575
16769
|
);
|
|
16576
16770
|
}
|
|
16577
16771
|
}
|
|
@@ -16610,13 +16804,13 @@ async function resolveMetroProjectRoot(bundleUrl, opts) {
|
|
|
16610
16804
|
function encodeAppFontsWire(specs) {
|
|
16611
16805
|
return specs.map((spec) => `${encodeURIComponent(spec.url)}::${encodeURIComponent(spec.family)}`).join(",");
|
|
16612
16806
|
}
|
|
16613
|
-
var
|
|
16807
|
+
var import_node_fs11, import_node_module2, import_node_path12, import_config_plugin_fonts, require3;
|
|
16614
16808
|
var init_app_fonts = __esm({
|
|
16615
16809
|
"cli/app-fonts.ts"() {
|
|
16616
16810
|
"use strict";
|
|
16617
|
-
|
|
16811
|
+
import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
16618
16812
|
import_node_module2 = require("node:module");
|
|
16619
|
-
|
|
16813
|
+
import_node_path12 = __toESM(require("node:path"), 1);
|
|
16620
16814
|
import_config_plugin_fonts = require("sootsim-engine/engine/config-plugin-fonts");
|
|
16621
16815
|
init_dev_server_scanner();
|
|
16622
16816
|
init_plist();
|
|
@@ -16639,7 +16833,7 @@ function localOriginOf2(value) {
|
|
|
16639
16833
|
}
|
|
16640
16834
|
function hasPackageJson2(dir) {
|
|
16641
16835
|
try {
|
|
16642
|
-
return
|
|
16836
|
+
return import_node_fs12.default.statSync(import_node_path13.default.join(dir, "package.json")).isFile();
|
|
16643
16837
|
} catch {
|
|
16644
16838
|
return false;
|
|
16645
16839
|
}
|
|
@@ -16648,7 +16842,7 @@ function discoverConfigPluginAppSplash(opts) {
|
|
|
16648
16842
|
const metroOrigin = localOriginOf2(opts.bundleUrl);
|
|
16649
16843
|
if (!metroOrigin) return null;
|
|
16650
16844
|
const explicit = opts.repoDir || process.env.CONTRAST_REPO_DIR;
|
|
16651
|
-
const startDir = explicit ?
|
|
16845
|
+
const startDir = explicit ? import_node_path13.default.resolve(explicit) : process.cwd();
|
|
16652
16846
|
if (!explicit && !hasPackageJson2(startDir)) return null;
|
|
16653
16847
|
const project = resolveAppProject(startDir, { trustStart: opts.exactProjectDir });
|
|
16654
16848
|
const selectedAppDir = project?.appDir ?? null;
|
|
@@ -16682,13 +16876,13 @@ function discoverConfigPluginAppSplash(opts) {
|
|
|
16682
16876
|
function encodeAppSplashWire(spec) {
|
|
16683
16877
|
return encodeURIComponent(JSON.stringify(spec));
|
|
16684
16878
|
}
|
|
16685
|
-
var
|
|
16879
|
+
var import_node_fs12, import_node_module3, import_node_path13, import_config_plugin_splash, require4;
|
|
16686
16880
|
var init_app_splash = __esm({
|
|
16687
16881
|
"cli/app-splash.ts"() {
|
|
16688
16882
|
"use strict";
|
|
16689
|
-
|
|
16883
|
+
import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
16690
16884
|
import_node_module3 = require("node:module");
|
|
16691
|
-
|
|
16885
|
+
import_node_path13 = __toESM(require("node:path"), 1);
|
|
16692
16886
|
import_config_plugin_splash = require("sootsim-engine/engine/config-plugin-splash");
|
|
16693
16887
|
init_app_project();
|
|
16694
16888
|
require4 = (0, import_node_module3.createRequire)(__sootsim_import_meta_url);
|
|
@@ -17706,7 +17900,7 @@ function resolvePlaywright() {
|
|
|
17706
17900
|
try {
|
|
17707
17901
|
const modulePath = requireFromRoot.resolve(spec);
|
|
17708
17902
|
const packageJsonPath = requireFromRoot.resolve(`${spec}/package.json`);
|
|
17709
|
-
const parsed = JSON.parse((0,
|
|
17903
|
+
const parsed = JSON.parse((0, import_node_fs13.readFileSync)(packageJsonPath, "utf8"));
|
|
17710
17904
|
if (!isRecord3(parsed) || typeof parsed.version !== "string") continue;
|
|
17711
17905
|
const bin = parsed.bin;
|
|
17712
17906
|
let binPath = null;
|
|
@@ -17718,8 +17912,8 @@ function resolvePlaywright() {
|
|
|
17718
17912
|
binPath = typeof named === "string" ? named : typeof first === "string" ? first : null;
|
|
17719
17913
|
}
|
|
17720
17914
|
if (!binPath) continue;
|
|
17721
|
-
const cliPath = (0,
|
|
17722
|
-
if (!(0,
|
|
17915
|
+
const cliPath = (0, import_node_path14.join)((0, import_node_path14.dirname)(packageJsonPath), binPath);
|
|
17916
|
+
if (!(0, import_node_fs13.existsSync)(cliPath)) continue;
|
|
17723
17917
|
return {
|
|
17724
17918
|
spec,
|
|
17725
17919
|
modulePath,
|
|
@@ -17758,7 +17952,7 @@ function probeBrowser(resolved, env) {
|
|
|
17758
17952
|
return {
|
|
17759
17953
|
ok: true,
|
|
17760
17954
|
executablePath: parsed.executablePath,
|
|
17761
|
-
exists: parsed.exists && (0,
|
|
17955
|
+
exists: parsed.exists && (0, import_node_fs13.existsSync)(parsed.executablePath)
|
|
17762
17956
|
};
|
|
17763
17957
|
} catch (error) {
|
|
17764
17958
|
return {
|
|
@@ -17797,14 +17991,14 @@ ${detail}` : ""}`
|
|
|
17797
17991
|
}
|
|
17798
17992
|
return { ok: true, executablePath: after.executablePath, installed: true };
|
|
17799
17993
|
}
|
|
17800
|
-
var import_node_child_process5,
|
|
17994
|
+
var import_node_child_process5, import_node_fs13, import_node_module4, import_node_path14, PLAYWRIGHT_BROWSER_PROBE;
|
|
17801
17995
|
var init_playwright_provisioning = __esm({
|
|
17802
17996
|
"cli/drivers/playwright-provisioning.ts"() {
|
|
17803
17997
|
"use strict";
|
|
17804
17998
|
import_node_child_process5 = require("node:child_process");
|
|
17805
|
-
|
|
17999
|
+
import_node_fs13 = require("node:fs");
|
|
17806
18000
|
import_node_module4 = require("node:module");
|
|
17807
|
-
|
|
18001
|
+
import_node_path14 = require("node:path");
|
|
17808
18002
|
PLAYWRIGHT_BROWSER_PROBE = `
|
|
17809
18003
|
const { existsSync } = require('node:fs');
|
|
17810
18004
|
const modulePath = process.env.SOOTSIM_PW_MODULE;
|
|
@@ -18956,14 +19150,14 @@ function assertExplicitBridgeLock(preferredPort, explicitPort, lock) {
|
|
|
18956
19150
|
}
|
|
18957
19151
|
async function ensureRuntimeForOpen() {
|
|
18958
19152
|
const active = readActiveRuntime();
|
|
18959
|
-
if (active &&
|
|
19153
|
+
if (active && import_node_fs14.default.existsSync(runtimeDir(active))) return;
|
|
18960
19154
|
console.error(" installing rnx engine runtime...");
|
|
18961
19155
|
const { runRuntime: runRuntime2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
|
|
18962
19156
|
await runRuntime2(["install"], {});
|
|
18963
19157
|
}
|
|
18964
19158
|
function spawnSootsim(args) {
|
|
18965
19159
|
const entry = process.argv[1];
|
|
18966
|
-
if (entry &&
|
|
19160
|
+
if (entry && import_node_fs14.default.existsSync(entry)) {
|
|
18967
19161
|
return (0, import_node_child_process6.spawn)(process.execPath, [entry, ...args], {
|
|
18968
19162
|
detached: true,
|
|
18969
19163
|
stdio: "ignore",
|
|
@@ -19110,10 +19304,10 @@ async function buildResolvedBundleOpenUrl(target, baseUrl, opts = {}) {
|
|
|
19110
19304
|
}
|
|
19111
19305
|
function normalizeReplacementPath(filePath) {
|
|
19112
19306
|
if (filePath.startsWith("~/")) {
|
|
19113
|
-
return
|
|
19307
|
+
return import_node_path15.default.join(import_node_os3.default.homedir(), filePath.slice(2));
|
|
19114
19308
|
}
|
|
19115
|
-
if (
|
|
19116
|
-
return
|
|
19309
|
+
if (import_node_path15.default.isAbsolute(filePath)) return filePath;
|
|
19310
|
+
return import_node_path15.default.resolve(process.cwd(), filePath);
|
|
19117
19311
|
}
|
|
19118
19312
|
function parseOpenRuntimeConfig(args) {
|
|
19119
19313
|
const modules = {};
|
|
@@ -19132,7 +19326,7 @@ function parseOpenRuntimeConfig(args) {
|
|
|
19132
19326
|
}
|
|
19133
19327
|
const moduleName = raw.slice(0, eqIndex).trim();
|
|
19134
19328
|
const filePath = normalizeReplacementPath(raw.slice(eqIndex + 1).trim());
|
|
19135
|
-
if (!
|
|
19329
|
+
if (!import_node_fs14.default.existsSync(filePath)) {
|
|
19136
19330
|
console.error(` rnxsim open: replacement file not found: ${filePath}`);
|
|
19137
19331
|
process.exit(1);
|
|
19138
19332
|
}
|
|
@@ -19167,7 +19361,7 @@ async function resolveOpenAppProject(resolvedBundle) {
|
|
|
19167
19361
|
return resolveAppProject(process.env.CONTRAST_REPO_DIR || process.cwd());
|
|
19168
19362
|
}
|
|
19169
19363
|
async function ensureConfiguredRuntime(version) {
|
|
19170
|
-
if (
|
|
19364
|
+
if (import_node_fs14.default.existsSync(import_node_path15.default.join(runtimeDir(version), "index.html"))) return;
|
|
19171
19365
|
console.error(` installing configured engine runtime ${version}...`);
|
|
19172
19366
|
const result = await sootsimRuntime.install({
|
|
19173
19367
|
version,
|
|
@@ -19531,7 +19725,7 @@ function playwrightHostPidForSim(sim) {
|
|
|
19531
19725
|
function signalDriverLaunchConnected(result) {
|
|
19532
19726
|
if (!result.connectAckFile) return false;
|
|
19533
19727
|
try {
|
|
19534
|
-
|
|
19728
|
+
import_node_fs14.default.writeFileSync(
|
|
19535
19729
|
result.connectAckFile,
|
|
19536
19730
|
`${JSON.stringify({ connectedAt: Date.now(), pid: result.pid ?? null })}
|
|
19537
19731
|
`,
|
|
@@ -19545,19 +19739,19 @@ function signalDriverLaunchConnected(result) {
|
|
|
19545
19739
|
function printDriverDiagnosticLogTail(result) {
|
|
19546
19740
|
if (!result.diagnosticLogPath) return;
|
|
19547
19741
|
try {
|
|
19548
|
-
const detail =
|
|
19742
|
+
const detail = import_node_fs14.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
|
|
19549
19743
|
if (!detail) {
|
|
19550
|
-
console.error(` ${
|
|
19744
|
+
console.error(` ${import_node_path15.default.basename(result.diagnosticLogPath)} was empty`);
|
|
19551
19745
|
return;
|
|
19552
19746
|
}
|
|
19553
19747
|
const shown = detail.length > 4e3 ? `\u2026
|
|
19554
19748
|
${detail.slice(-4e3)}` : detail;
|
|
19555
|
-
console.error(` ${
|
|
19749
|
+
console.error(` ${import_node_path15.default.basename(result.diagnosticLogPath)}:`);
|
|
19556
19750
|
console.error(shown);
|
|
19557
19751
|
} catch (err) {
|
|
19558
19752
|
const message = err instanceof Error ? err.message : String(err);
|
|
19559
19753
|
console.error(
|
|
19560
|
-
` failed to read ${
|
|
19754
|
+
` failed to read ${import_node_path15.default.basename(result.diagnosticLogPath)}: ${message}`
|
|
19561
19755
|
);
|
|
19562
19756
|
}
|
|
19563
19757
|
}
|
|
@@ -19907,7 +20101,9 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
19907
20101
|
const viewportArg = args.find((_, i) => args[i - 1] === "--viewport");
|
|
19908
20102
|
const viewportMatch = viewportArg ? /^(\d+)x(\d+)$/.exec(viewportArg) : null;
|
|
19909
20103
|
if (viewportArg && !viewportMatch) {
|
|
19910
|
-
console.error(
|
|
20104
|
+
console.error(
|
|
20105
|
+
` rnxsim open: --viewport must be <width>x<height>, got "${viewportArg}"`
|
|
20106
|
+
);
|
|
19911
20107
|
process.exit(1);
|
|
19912
20108
|
}
|
|
19913
20109
|
const explicitViewport = viewportMatch ? { width: Number(viewportMatch[1]), height: Number(viewportMatch[2]) } : void 0;
|
|
@@ -20361,14 +20557,14 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
20361
20557
|
bridge.close();
|
|
20362
20558
|
}
|
|
20363
20559
|
}
|
|
20364
|
-
var import_node_child_process6,
|
|
20560
|
+
var import_node_child_process6, import_node_fs14, import_node_os3, import_node_path15, import_settings, import_ws5, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEEP_LINK_SCHEME_RE;
|
|
20365
20561
|
var init_control = __esm({
|
|
20366
20562
|
"cli/commands/control.ts"() {
|
|
20367
20563
|
"use strict";
|
|
20368
20564
|
import_node_child_process6 = require("node:child_process");
|
|
20369
|
-
|
|
20565
|
+
import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
20370
20566
|
import_node_os3 = __toESM(require("node:os"), 1);
|
|
20371
|
-
|
|
20567
|
+
import_node_path15 = __toESM(require("node:path"), 1);
|
|
20372
20568
|
import_settings = require("sootsim-engine/settings");
|
|
20373
20569
|
import_ws5 = require("ws");
|
|
20374
20570
|
init_dev_server_scanner();
|
|
@@ -21150,14 +21346,14 @@ process.stdin.on('end', async () => {
|
|
|
21150
21346
|
function getBaseDir() {
|
|
21151
21347
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
21152
21348
|
if (explicit?.trim()) {
|
|
21153
|
-
return (0,
|
|
21349
|
+
return (0, import_node_path16.dirname)((0, import_node_path16.resolve)(explicit));
|
|
21154
21350
|
}
|
|
21155
21351
|
return electronUserDataDir();
|
|
21156
21352
|
}
|
|
21157
21353
|
function getSharedDesktopAuthFilePath() {
|
|
21158
21354
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
21159
|
-
if (explicit?.trim()) return (0,
|
|
21160
|
-
return (0,
|
|
21355
|
+
if (explicit?.trim()) return (0, import_node_path16.resolve)(explicit);
|
|
21356
|
+
return (0, import_node_path16.join)(getBaseDir(), "desktop-auth.json");
|
|
21161
21357
|
}
|
|
21162
21358
|
function normalizeUser(input) {
|
|
21163
21359
|
if (!input || typeof input !== "object") return null;
|
|
@@ -21204,26 +21400,26 @@ function normalizeSession(input) {
|
|
|
21204
21400
|
}
|
|
21205
21401
|
function readSharedDesktopAuthSession() {
|
|
21206
21402
|
const filepath = getSharedDesktopAuthFilePath();
|
|
21207
|
-
if (!(0,
|
|
21403
|
+
if (!(0, import_node_fs15.existsSync)(filepath)) return null;
|
|
21208
21404
|
try {
|
|
21209
|
-
const parsed = JSON.parse((0,
|
|
21405
|
+
const parsed = JSON.parse((0, import_node_fs15.readFileSync)(filepath, "utf8"));
|
|
21210
21406
|
const normalized = normalizeSession(parsed);
|
|
21211
21407
|
if (!normalized) {
|
|
21212
|
-
(0,
|
|
21408
|
+
(0, import_node_fs15.rmSync)(filepath, { force: true });
|
|
21213
21409
|
return null;
|
|
21214
21410
|
}
|
|
21215
21411
|
return normalized;
|
|
21216
21412
|
} catch {
|
|
21217
|
-
(0,
|
|
21413
|
+
(0, import_node_fs15.rmSync)(filepath, { force: true });
|
|
21218
21414
|
return null;
|
|
21219
21415
|
}
|
|
21220
21416
|
}
|
|
21221
|
-
var
|
|
21417
|
+
var import_node_fs15, import_node_path16, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
|
|
21222
21418
|
var init_shared_session = __esm({
|
|
21223
21419
|
"src/auth/shared-session.ts"() {
|
|
21224
21420
|
"use strict";
|
|
21225
|
-
|
|
21226
|
-
|
|
21421
|
+
import_node_fs15 = require("node:fs");
|
|
21422
|
+
import_node_path16 = require("node:path");
|
|
21227
21423
|
init_home_paths();
|
|
21228
21424
|
SESSION_VERSION = 1;
|
|
21229
21425
|
SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
@@ -21486,16 +21682,16 @@ function resolveFlowScreenshotPath(screenshotDir, name2) {
|
|
|
21486
21682
|
}
|
|
21487
21683
|
function resolveProjectRelativeFlowBase(flowDir) {
|
|
21488
21684
|
if (!flowDir) return process.cwd();
|
|
21489
|
-
return
|
|
21685
|
+
return path15.basename(flowDir) === ".maestro" ? path15.dirname(flowDir) : flowDir;
|
|
21490
21686
|
}
|
|
21491
21687
|
function resolveFlowScreenshotPathWithMode(screenshotDir, name2, opts) {
|
|
21492
21688
|
const normalizedName = name2.endsWith(".png") ? name2 : `${name2}.png`;
|
|
21493
|
-
if (
|
|
21689
|
+
if (path15.isAbsolute(normalizedName)) return normalizedName;
|
|
21494
21690
|
if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
|
|
21495
21691
|
const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
|
|
21496
|
-
return
|
|
21692
|
+
return path15.resolve(baseDir, normalizedName);
|
|
21497
21693
|
}
|
|
21498
|
-
return
|
|
21694
|
+
return path15.join(screenshotDir, normalizedName);
|
|
21499
21695
|
}
|
|
21500
21696
|
function normalizeFlowScreenshotSpec(step) {
|
|
21501
21697
|
if (typeof step === "string") {
|
|
@@ -21552,12 +21748,12 @@ function parseFlowSteps(content) {
|
|
|
21552
21748
|
const parsed = import_yaml.default.parse(candidate);
|
|
21553
21749
|
return Array.isArray(parsed) ? parsed : [];
|
|
21554
21750
|
}
|
|
21555
|
-
var
|
|
21751
|
+
var fs16, path15, import_settings3, import_yaml, DEFAULT_TIMEOUT, FLOW_TIMEOUT_SCALE, scaledTimeout, SCREEN_W, SCREEN_H, SootSimBridgeFlowRunner;
|
|
21556
21752
|
var init_bridge_flow_runner = __esm({
|
|
21557
21753
|
"cli/bridge-flow-runner.ts"() {
|
|
21558
21754
|
"use strict";
|
|
21559
|
-
|
|
21560
|
-
|
|
21755
|
+
fs16 = __toESM(require("fs"), 1);
|
|
21756
|
+
path15 = __toESM(require("path"), 1);
|
|
21561
21757
|
import_settings3 = require("sootsim-engine/settings");
|
|
21562
21758
|
import_yaml = __toESM(require("yaml"), 1);
|
|
21563
21759
|
init_frame_compose();
|
|
@@ -21668,6 +21864,15 @@ var init_bridge_flow_runner = __esm({
|
|
|
21668
21864
|
args
|
|
21669
21865
|
});
|
|
21670
21866
|
}
|
|
21867
|
+
// ordered input batch executed inside the page in one round-trip; the
|
|
21868
|
+
// engine emits agent-cursor actions for every step natively.
|
|
21869
|
+
async perform(steps) {
|
|
21870
|
+
return this.bridge.send({
|
|
21871
|
+
type: "perform",
|
|
21872
|
+
simId: this.opts.simId,
|
|
21873
|
+
steps
|
|
21874
|
+
});
|
|
21875
|
+
}
|
|
21671
21876
|
async waitForTree(timeout = DEFAULT_TIMEOUT) {
|
|
21672
21877
|
const deadline = Date.now() + scaledTimeout(timeout);
|
|
21673
21878
|
const startedAt = Date.now();
|
|
@@ -21845,14 +22050,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
21845
22050
|
if (chunks.length === 0) {
|
|
21846
22051
|
throw new Error("recording requested but no video buffer was produced");
|
|
21847
22052
|
}
|
|
21848
|
-
|
|
22053
|
+
fs16.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
|
|
21849
22054
|
const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
|
|
21850
22055
|
const extension = videoMime.includes("mp4") ? "mp4" : "webm";
|
|
21851
|
-
const outputPath =
|
|
22056
|
+
const outputPath = path15.join(
|
|
21852
22057
|
this.opts.recordingOutputDir,
|
|
21853
22058
|
`sootsim-${Date.now()}.${extension}`
|
|
21854
22059
|
);
|
|
21855
|
-
|
|
22060
|
+
fs16.writeFileSync(outputPath, Buffer.concat(chunks));
|
|
21856
22061
|
return outputPath;
|
|
21857
22062
|
}
|
|
21858
22063
|
async waitForRecordingTail(opts) {
|
|
@@ -22186,20 +22391,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
22186
22391
|
await sleep3(300);
|
|
22187
22392
|
}
|
|
22188
22393
|
async doubleTapAtCoords(x, y, gapMs = 80) {
|
|
22189
|
-
const
|
|
22190
|
-
|
|
22191
|
-
|
|
22192
|
-
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
|
|
22196
|
-
|
|
22197
|
-
if (!first || first.hit === false) return false
|
|
22198
|
-
await new Promise((resolve) => setTimeout(resolve, ${waitMs}))
|
|
22199
|
-
const second = await interact.tap(${x}, ${y})
|
|
22200
|
-
return !!second && second.hit !== false
|
|
22201
|
-
})()`);
|
|
22202
|
-
if (!ok) throw new Error(`doubleTapAtCoords failed at (${x}, ${y})`);
|
|
22394
|
+
const result = await this.perform([
|
|
22395
|
+
{ type: "doubleTap", x, y, gapMs: Math.max(0, Math.round(gapMs)) }
|
|
22396
|
+
]);
|
|
22397
|
+
if (!result?.ok) {
|
|
22398
|
+
throw new Error(
|
|
22399
|
+
`doubleTapAtCoords failed at (${x}, ${y}): ${result?.error ?? "double tap missed"}`
|
|
22400
|
+
);
|
|
22401
|
+
}
|
|
22203
22402
|
await sleep3(300);
|
|
22204
22403
|
}
|
|
22205
22404
|
async assertVisible(target) {
|
|
@@ -22361,7 +22560,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
22361
22560
|
flowDir: this.opts.flowDir
|
|
22362
22561
|
}
|
|
22363
22562
|
);
|
|
22364
|
-
|
|
22563
|
+
fs16.mkdirSync(path15.dirname(outputPath), { recursive: true });
|
|
22365
22564
|
const layers = spec.layers ?? this.opts.screenshotLayers;
|
|
22366
22565
|
const screenshotRequest = {
|
|
22367
22566
|
type: "screenshot",
|
|
@@ -22377,11 +22576,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
22377
22576
|
throw new Error("could not read current device model for framed screenshot");
|
|
22378
22577
|
}
|
|
22379
22578
|
const framed = await composeFramedScreenshot(rawBuffer, model);
|
|
22380
|
-
|
|
22579
|
+
fs16.writeFileSync(outputPath, framed);
|
|
22381
22580
|
console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
|
|
22382
22581
|
return outputPath;
|
|
22383
22582
|
}
|
|
22384
|
-
|
|
22583
|
+
fs16.writeFileSync(outputPath, rawBuffer);
|
|
22385
22584
|
console.log(`[flow] screenshot: ${outputPath}`);
|
|
22386
22585
|
return outputPath;
|
|
22387
22586
|
}
|
|
@@ -22397,22 +22596,22 @@ var init_bridge_flow_runner = __esm({
|
|
|
22397
22596
|
return model;
|
|
22398
22597
|
}
|
|
22399
22598
|
async captureScreenshot(outputPath) {
|
|
22400
|
-
|
|
22599
|
+
fs16.mkdirSync(path15.dirname(outputPath), { recursive: true });
|
|
22401
22600
|
const dataUrl = await this.bridge.send({
|
|
22402
22601
|
type: "screenshot",
|
|
22403
22602
|
simId: this.opts.simId
|
|
22404
22603
|
});
|
|
22405
22604
|
const base64 = dataUrl.replace(/^data:image\/png;base64,/, "");
|
|
22406
|
-
|
|
22605
|
+
fs16.writeFileSync(outputPath, Buffer.from(base64, "base64"));
|
|
22407
22606
|
}
|
|
22408
22607
|
// writes a per-failure debug bundle: screenshot + structured describe
|
|
22409
22608
|
// + a11y tree + console errors/warnings + failed network requests +
|
|
22410
22609
|
// shell state, all under one directory so post-mortem is one grep away.
|
|
22411
22610
|
async captureFailureBundle(outputDir, context) {
|
|
22412
|
-
|
|
22611
|
+
fs16.mkdirSync(outputDir, { recursive: true });
|
|
22413
22612
|
const write = (name2, content) => {
|
|
22414
22613
|
try {
|
|
22415
|
-
|
|
22614
|
+
fs16.writeFileSync(path15.join(outputDir, name2), content);
|
|
22416
22615
|
} catch {
|
|
22417
22616
|
}
|
|
22418
22617
|
};
|
|
@@ -22540,14 +22739,19 @@ var init_bridge_flow_runner = __esm({
|
|
|
22540
22739
|
await this.drag(fromX, fromY, toX, toY, steps, 16);
|
|
22541
22740
|
}
|
|
22542
22741
|
async drag(fromX, fromY, toX, toY, steps = 12, stepMs = 16) {
|
|
22543
|
-
const result = await this.
|
|
22544
|
-
|
|
22545
|
-
|
|
22546
|
-
|
|
22547
|
-
|
|
22548
|
-
|
|
22742
|
+
const result = await this.perform([
|
|
22743
|
+
{
|
|
22744
|
+
type: "drag",
|
|
22745
|
+
fromX,
|
|
22746
|
+
fromY,
|
|
22747
|
+
toX,
|
|
22748
|
+
toY,
|
|
22749
|
+
steps: Math.max(1, Math.round(steps)),
|
|
22750
|
+
stepMs: Math.max(0, Math.round(stepMs))
|
|
22751
|
+
}
|
|
22752
|
+
]);
|
|
22549
22753
|
if (!result?.ok) {
|
|
22550
|
-
throw new Error(
|
|
22754
|
+
throw new Error(`drag failed: ${result?.error ?? "drag missed"}`);
|
|
22551
22755
|
}
|
|
22552
22756
|
await sleep3(300);
|
|
22553
22757
|
}
|
|
@@ -22596,18 +22800,23 @@ var init_bridge_flow_runner = __esm({
|
|
|
22596
22800
|
await sleep3(250);
|
|
22597
22801
|
}
|
|
22598
22802
|
async pinch(opts) {
|
|
22599
|
-
const result = await this.
|
|
22600
|
-
|
|
22601
|
-
|
|
22602
|
-
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22803
|
+
const result = await this.perform([
|
|
22804
|
+
{
|
|
22805
|
+
type: "pinch",
|
|
22806
|
+
fromX1: opts.from[0],
|
|
22807
|
+
fromY1: opts.from[1],
|
|
22808
|
+
fromX2: opts.from[2],
|
|
22809
|
+
fromY2: opts.from[3],
|
|
22810
|
+
toX1: opts.to[0],
|
|
22811
|
+
toY1: opts.to[1],
|
|
22812
|
+
toX2: opts.to[2],
|
|
22813
|
+
toY2: opts.to[3],
|
|
22814
|
+
steps: opts.steps || 12,
|
|
22815
|
+
stepMs: opts.stepMs || 16
|
|
22816
|
+
}
|
|
22817
|
+
]);
|
|
22609
22818
|
if (!result?.ok) {
|
|
22610
|
-
throw new Error(`pinch failed: ${result?.
|
|
22819
|
+
throw new Error(`pinch failed: ${result?.error || "unknown error"}`);
|
|
22611
22820
|
}
|
|
22612
22821
|
await sleep3(250);
|
|
22613
22822
|
}
|
|
@@ -22684,43 +22893,31 @@ var init_bridge_flow_runner = __esm({
|
|
|
22684
22893
|
}
|
|
22685
22894
|
throw new Error("extendedWaitUntil timed out");
|
|
22686
22895
|
}
|
|
22687
|
-
|
|
22688
|
-
// 1. clear tenant-scoped storage through the engine bridge (best-effort).
|
|
22689
|
-
// 2. ALWAYS hard-reload the page to reset the tenant worker.
|
|
22690
|
-
// phase 2 is the important one for a long suite: the engine soft reload alone
|
|
22691
|
-
// keeps the same worker alive across every flow, so a saturated event loop /
|
|
22692
|
-
// accumulated state from one flow's post-PDS-reset auth-failure storm carries
|
|
22693
|
-
// into the next and degrades until the worker wedges or the tab crashes (the
|
|
22694
|
-
// failures clustered in the tail of a 21-flow run). a full page reload starts
|
|
22695
|
-
// each flow on a fresh worker — worker-independent, so it also recovers a
|
|
22696
|
-
// worker the bridge clear couldn't even ack. storage persists across a page
|
|
22697
|
-
// reload, so the clear in phase 1 is what actually logs the guest out.
|
|
22698
|
-
async reloadGuestApp(resetStorage) {
|
|
22699
|
-
if (resetStorage) {
|
|
22700
|
-
const ATTEMPTS = 3;
|
|
22701
|
-
const PER_ATTEMPT_MS = 2e4;
|
|
22702
|
-
let cleared = false;
|
|
22703
|
-
for (let attempt = 0; attempt < ATTEMPTS && !cleared; attempt++) {
|
|
22704
|
-
try {
|
|
22705
|
-
cleared = await this.evaluate(
|
|
22706
|
-
resetGuestAppStateEval(true),
|
|
22707
|
-
PER_ATTEMPT_MS
|
|
22708
|
-
);
|
|
22709
|
-
} catch {
|
|
22710
|
-
await sleep3(1e3);
|
|
22711
|
-
}
|
|
22712
|
-
}
|
|
22713
|
-
if (!cleared) {
|
|
22714
|
-
console.warn(
|
|
22715
|
-
" warn: tenant storage clear did not ack \u2014 hard-reloading anyway (worker reset follows)"
|
|
22716
|
-
);
|
|
22717
|
-
}
|
|
22718
|
-
}
|
|
22896
|
+
async reloadGuestApp() {
|
|
22719
22897
|
await this.evaluate("window.location.reload()").catch(() => {
|
|
22720
22898
|
});
|
|
22721
22899
|
await sleep3(500);
|
|
22722
22900
|
await this.refreshSimId();
|
|
22723
22901
|
}
|
|
22902
|
+
async resetGuestAppData() {
|
|
22903
|
+
const reset = await this.bridge.send(
|
|
22904
|
+
{
|
|
22905
|
+
type: "reset",
|
|
22906
|
+
simId: this.opts.simId,
|
|
22907
|
+
resetOptions: { strategy: "data" }
|
|
22908
|
+
},
|
|
22909
|
+
{ timeoutMs: 12e4 }
|
|
22910
|
+
);
|
|
22911
|
+
if (!reset.ok) {
|
|
22912
|
+
throw new Error(reset.error ?? "guest app data reset failed");
|
|
22913
|
+
}
|
|
22914
|
+
if (!reset.relaunched) {
|
|
22915
|
+
throw new Error("guest app data reset did not relaunch the app");
|
|
22916
|
+
}
|
|
22917
|
+
if (reset.workerReloaded !== true) {
|
|
22918
|
+
throw new Error("guest app data reset did not replace the tenant worker");
|
|
22919
|
+
}
|
|
22920
|
+
}
|
|
22724
22921
|
async softReloadGuestApp(resetStorage) {
|
|
22725
22922
|
const reloaded = await this.evaluate(
|
|
22726
22923
|
resetGuestAppStateEval(resetStorage),
|
|
@@ -22769,7 +22966,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
22769
22966
|
await this.waitForTree(3e4);
|
|
22770
22967
|
} else {
|
|
22771
22968
|
this.firstLaunchDone = true;
|
|
22772
|
-
|
|
22969
|
+
if (wantsClear) {
|
|
22970
|
+
await this.resetGuestAppData();
|
|
22971
|
+
} else {
|
|
22972
|
+
await this.reloadGuestApp();
|
|
22973
|
+
}
|
|
22773
22974
|
await this.waitForTree(12e4);
|
|
22774
22975
|
if (this.opts.onAfterLaunch) {
|
|
22775
22976
|
try {
|
|
@@ -22882,13 +23083,12 @@ var init_bridge_flow_runner = __esm({
|
|
|
22882
23083
|
// nearest equivalent to killing and later re-launching the tenant runtime.
|
|
22883
23084
|
// State clearing belongs to clearState / launchApp({ clearState: true }).
|
|
22884
23085
|
async stopApp() {
|
|
22885
|
-
await this.reloadGuestApp(
|
|
23086
|
+
await this.reloadGuestApp();
|
|
22886
23087
|
await this.rearmCaptureAfterRuntimeReload();
|
|
22887
23088
|
}
|
|
22888
|
-
// maestro clearState: wipe app-owned storage and relaunch fresh.
|
|
22889
|
-
// through the same engine soft-reload launchApp uses under `clearState: true`.
|
|
23089
|
+
// maestro clearState: wipe app-owned storage and relaunch fresh.
|
|
22890
23090
|
async clearState() {
|
|
22891
|
-
await this.
|
|
23091
|
+
await this.resetGuestAppData();
|
|
22892
23092
|
await this.rearmCaptureAfterRuntimeReload();
|
|
22893
23093
|
}
|
|
22894
23094
|
// maestro clearKeychain: there is no real keychain in sootsim's browser
|
|
@@ -22930,8 +23130,8 @@ var init_bridge_flow_runner = __esm({
|
|
|
22930
23130
|
runScript(target) {
|
|
22931
23131
|
const spec = typeof target === "string" ? { file: target } : target;
|
|
22932
23132
|
if (!spec.file) throw new Error("runScript requires a file");
|
|
22933
|
-
const scriptPath =
|
|
22934
|
-
const source =
|
|
23133
|
+
const scriptPath = path15.resolve(this.opts.flowDir, spec.file);
|
|
23134
|
+
const source = fs16.readFileSync(scriptPath, "utf8");
|
|
22935
23135
|
this.js.evaluate(source, { env: spec.env });
|
|
22936
23136
|
console.log(`[flow] runScript: ${spec.file} done`);
|
|
22937
23137
|
}
|
|
@@ -23225,10 +23425,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
23225
23425
|
for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
|
|
23226
23426
|
}
|
|
23227
23427
|
if (file) {
|
|
23228
|
-
const flowPath =
|
|
23229
|
-
const flowContent =
|
|
23428
|
+
const flowPath = path15.resolve(this.opts.flowDir, file);
|
|
23429
|
+
const flowContent = fs16.readFileSync(flowPath, "utf8");
|
|
23230
23430
|
const previousDir = this.opts.flowDir;
|
|
23231
|
-
this.opts.flowDir =
|
|
23431
|
+
this.opts.flowDir = path15.dirname(flowPath);
|
|
23232
23432
|
try {
|
|
23233
23433
|
await this.runFlow(parseFlowSteps(flowContent));
|
|
23234
23434
|
} finally {
|
|
@@ -23383,8 +23583,8 @@ __export(registry_exports, {
|
|
|
23383
23583
|
skillRegistry: () => skillRegistry
|
|
23384
23584
|
});
|
|
23385
23585
|
module.exports = __toCommonJS(registry_exports);
|
|
23386
|
-
var
|
|
23387
|
-
var
|
|
23586
|
+
var fs17 = __toESM(require("fs"), 1);
|
|
23587
|
+
var path16 = __toESM(require("path"), 1);
|
|
23388
23588
|
|
|
23389
23589
|
// src/skills/builtin/a11y-review.ts
|
|
23390
23590
|
init_reap_browser();
|
|
@@ -23403,8 +23603,8 @@ var skill = {
|
|
|
23403
23603
|
},
|
|
23404
23604
|
async execute(params, context) {
|
|
23405
23605
|
const { chromium } = await import("playwright");
|
|
23406
|
-
const
|
|
23407
|
-
const
|
|
23606
|
+
const path17 = await import("path");
|
|
23607
|
+
const fs18 = await import("fs");
|
|
23408
23608
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
23409
23609
|
headless: true
|
|
23410
23610
|
});
|
|
@@ -23459,9 +23659,9 @@ var skill = {
|
|
|
23459
23659
|
warnings: issues.filter((i) => i.severity === "warning").length,
|
|
23460
23660
|
tree: typeof tree === "string" ? tree : JSON.stringify(tree)
|
|
23461
23661
|
};
|
|
23462
|
-
const reportPath =
|
|
23463
|
-
|
|
23464
|
-
|
|
23662
|
+
const reportPath = path17.join(context.outputDir, "a11y-report.json");
|
|
23663
|
+
fs18.mkdirSync(path17.dirname(reportPath), { recursive: true });
|
|
23664
|
+
fs18.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
23465
23665
|
return {
|
|
23466
23666
|
success: issues.filter((i) => i.severity === "error").length === 0,
|
|
23467
23667
|
message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
|
|
@@ -23494,14 +23694,14 @@ var skill2 = {
|
|
|
23494
23694
|
}
|
|
23495
23695
|
},
|
|
23496
23696
|
async execute(params, context) {
|
|
23497
|
-
const
|
|
23498
|
-
const
|
|
23697
|
+
const fs18 = await import("node:fs");
|
|
23698
|
+
const path17 = await import("node:path");
|
|
23499
23699
|
const { COMPAT_RESULT_CAVEAT: COMPAT_RESULT_CAVEAT2, formatPackageStatus: formatPackageStatus2, formatScanCounts: formatScanCounts2, scanDeps: scanDeps2 } = await Promise.resolve().then(() => (init_web(), web_exports));
|
|
23500
|
-
const packagePath =
|
|
23501
|
-
if (!
|
|
23700
|
+
const packagePath = path17.join(context.projectDir, "package.json");
|
|
23701
|
+
if (!fs18.existsSync(packagePath)) {
|
|
23502
23702
|
return { success: false, message: "No package.json found" };
|
|
23503
23703
|
}
|
|
23504
|
-
const parsed = JSON.parse(
|
|
23704
|
+
const parsed = JSON.parse(fs18.readFileSync(packagePath, "utf8"));
|
|
23505
23705
|
if (!parsed || typeof parsed !== "object") {
|
|
23506
23706
|
return { success: false, message: "package.json is not an object" };
|
|
23507
23707
|
}
|
|
@@ -23513,9 +23713,9 @@ var skill2 = {
|
|
|
23513
23713
|
}) : scanDeps2(parsed);
|
|
23514
23714
|
const packageResult = params.packageName ? scan.packages[0] : void 0;
|
|
23515
23715
|
const message = packageResult ? `${params.packageName}: ${formatPackageStatus2(packageResult)}. ${COMPAT_RESULT_CAVEAT2}` : `${formatScanCounts2(scan)}. ${COMPAT_RESULT_CAVEAT2}`;
|
|
23516
|
-
const reportPath =
|
|
23517
|
-
|
|
23518
|
-
|
|
23716
|
+
const reportPath = path17.join(context.outputDir, "compat-report.json");
|
|
23717
|
+
fs18.mkdirSync(path17.dirname(reportPath), { recursive: true });
|
|
23718
|
+
fs18.writeFileSync(reportPath, `${JSON.stringify(scan, null, 2)}
|
|
23519
23719
|
`);
|
|
23520
23720
|
return {
|
|
23521
23721
|
success: true,
|
|
@@ -23559,8 +23759,8 @@ var skill3 = {
|
|
|
23559
23759
|
record: { type: "boolean", description: "Record video of the flow" }
|
|
23560
23760
|
},
|
|
23561
23761
|
async execute(params, context) {
|
|
23562
|
-
const
|
|
23563
|
-
const
|
|
23762
|
+
const fs18 = await import("fs");
|
|
23763
|
+
const path17 = await import("path");
|
|
23564
23764
|
const yaml2 = await import("yaml");
|
|
23565
23765
|
const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
|
|
23566
23766
|
const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
|
|
@@ -23570,7 +23770,7 @@ var skill3 = {
|
|
|
23570
23770
|
const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
|
|
23571
23771
|
host.start({ silent: true });
|
|
23572
23772
|
try {
|
|
23573
|
-
const flowContent =
|
|
23773
|
+
const flowContent = fs18.readFileSync(params.flowPath, "utf8");
|
|
23574
23774
|
const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
23575
23775
|
const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
|
|
23576
23776
|
const steps = yaml2.parse(stepsBody);
|
|
@@ -23597,7 +23797,7 @@ var skill3 = {
|
|
|
23597
23797
|
});
|
|
23598
23798
|
const driver = new SootSimBridgeFlowRunner2(bridge, {
|
|
23599
23799
|
screenshotDir: context.outputDir,
|
|
23600
|
-
flowDir:
|
|
23800
|
+
flowDir: path17.dirname(path17.resolve(params.flowPath)),
|
|
23601
23801
|
simId,
|
|
23602
23802
|
recordingOutputDir: params.record ? context.outputDir : void 0
|
|
23603
23803
|
});
|
|
@@ -23619,7 +23819,7 @@ var skill3 = {
|
|
|
23619
23819
|
simId,
|
|
23620
23820
|
videoPath: videoPath || void 0
|
|
23621
23821
|
},
|
|
23622
|
-
artifacts: videoPath ? [{ type: "video", name:
|
|
23822
|
+
artifacts: videoPath ? [{ type: "video", name: path17.basename(videoPath), path: videoPath }] : void 0
|
|
23623
23823
|
};
|
|
23624
23824
|
} finally {
|
|
23625
23825
|
try {
|
|
@@ -23666,8 +23866,8 @@ var skill4 = {
|
|
|
23666
23866
|
},
|
|
23667
23867
|
async execute(params, context) {
|
|
23668
23868
|
const { chromium } = await import("playwright");
|
|
23669
|
-
const
|
|
23670
|
-
const
|
|
23869
|
+
const path17 = await import("path");
|
|
23870
|
+
const fs18 = await import("fs");
|
|
23671
23871
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
23672
23872
|
headless: true
|
|
23673
23873
|
});
|
|
@@ -23693,9 +23893,9 @@ var skill4 = {
|
|
|
23693
23893
|
...profile,
|
|
23694
23894
|
fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
|
|
23695
23895
|
};
|
|
23696
|
-
const reportPath =
|
|
23697
|
-
|
|
23698
|
-
|
|
23896
|
+
const reportPath = path17.join(context.outputDir, "perf-report.json");
|
|
23897
|
+
fs18.mkdirSync(path17.dirname(reportPath), { recursive: true });
|
|
23898
|
+
fs18.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
23699
23899
|
return {
|
|
23700
23900
|
success: true,
|
|
23701
23901
|
message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
|
|
@@ -23728,8 +23928,8 @@ var skill5 = {
|
|
|
23728
23928
|
},
|
|
23729
23929
|
async execute(params, context) {
|
|
23730
23930
|
const { chromium } = await import("playwright");
|
|
23731
|
-
const
|
|
23732
|
-
const
|
|
23931
|
+
const path17 = await import("path");
|
|
23932
|
+
const fs18 = await import("fs");
|
|
23733
23933
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
23734
23934
|
headless: true
|
|
23735
23935
|
});
|
|
@@ -23737,8 +23937,8 @@ var skill5 = {
|
|
|
23737
23937
|
try {
|
|
23738
23938
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
23739
23939
|
await page.waitForTimeout(2e3);
|
|
23740
|
-
const outputPath =
|
|
23741
|
-
|
|
23940
|
+
const outputPath = path17.join(context.outputDir, `${params.name}.png`);
|
|
23941
|
+
fs18.mkdirSync(path17.dirname(outputPath), { recursive: true });
|
|
23742
23942
|
await page.screenshot({ path: outputPath });
|
|
23743
23943
|
return {
|
|
23744
23944
|
success: true,
|
|
@@ -23779,8 +23979,8 @@ var skill6 = {
|
|
|
23779
23979
|
},
|
|
23780
23980
|
async execute(params, context) {
|
|
23781
23981
|
const { chromium } = await import("playwright");
|
|
23782
|
-
const
|
|
23783
|
-
const
|
|
23982
|
+
const path17 = await import("path");
|
|
23983
|
+
const fs18 = await import("fs");
|
|
23784
23984
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
23785
23985
|
headless: true
|
|
23786
23986
|
});
|
|
@@ -23788,14 +23988,14 @@ var skill6 = {
|
|
|
23788
23988
|
try {
|
|
23789
23989
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
23790
23990
|
await page.waitForTimeout(2e3);
|
|
23791
|
-
const currentPath =
|
|
23792
|
-
|
|
23991
|
+
const currentPath = path17.join(context.outputDir, `${params.name}-current.png`);
|
|
23992
|
+
fs18.mkdirSync(path17.dirname(currentPath), { recursive: true });
|
|
23793
23993
|
await page.screenshot({ path: currentPath });
|
|
23794
23994
|
try {
|
|
23795
23995
|
const { PNG } = await import("pngjs");
|
|
23796
23996
|
const pixelmatch = (await import("pixelmatch")).default;
|
|
23797
|
-
const baseline = PNG.sync.read(
|
|
23798
|
-
const current = PNG.sync.read(
|
|
23997
|
+
const baseline = PNG.sync.read(fs18.readFileSync(params.baseline));
|
|
23998
|
+
const current = PNG.sync.read(fs18.readFileSync(currentPath));
|
|
23799
23999
|
const { width, height } = baseline;
|
|
23800
24000
|
const diff = new PNG({ width, height });
|
|
23801
24001
|
const numDiffPixels = pixelmatch(
|
|
@@ -23806,8 +24006,8 @@ var skill6 = {
|
|
|
23806
24006
|
height,
|
|
23807
24007
|
{ threshold: params.threshold || 0.1 }
|
|
23808
24008
|
);
|
|
23809
|
-
const diffPath =
|
|
23810
|
-
|
|
24009
|
+
const diffPath = path17.join(context.outputDir, `${params.name}-diff.png`);
|
|
24010
|
+
fs18.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
23811
24011
|
const totalPixels = width * height;
|
|
23812
24012
|
const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
|
|
23813
24013
|
return {
|
|
@@ -23871,10 +24071,10 @@ var skillRegistry = {
|
|
|
23871
24071
|
},
|
|
23872
24072
|
// load skills from a project manifest (sootsim-skills.json)
|
|
23873
24073
|
async loadFromManifest(projectDir) {
|
|
23874
|
-
const manifestPath =
|
|
23875
|
-
if (!
|
|
24074
|
+
const manifestPath = path16.join(projectDir, "sootsim-skills.json");
|
|
24075
|
+
if (!fs17.existsSync(manifestPath)) return;
|
|
23876
24076
|
try {
|
|
23877
|
-
const manifest = JSON.parse(
|
|
24077
|
+
const manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf8"));
|
|
23878
24078
|
if (Array.isArray(manifest.skills)) {
|
|
23879
24079
|
for (const entry of manifest.skills) {
|
|
23880
24080
|
if (typeof entry === "string") {
|
|
@@ -23885,7 +24085,7 @@ var skillRegistry = {
|
|
|
23885
24085
|
}
|
|
23886
24086
|
} else if (entry.file) {
|
|
23887
24087
|
try {
|
|
23888
|
-
const mod = await import(
|
|
24088
|
+
const mod = await import(path16.resolve(projectDir, entry.file));
|
|
23889
24089
|
if (mod.skill) this.register(mod.skill);
|
|
23890
24090
|
} catch {
|
|
23891
24091
|
}
|
|
@@ -23898,10 +24098,10 @@ var skillRegistry = {
|
|
|
23898
24098
|
// auto-discover skills based on project dependencies
|
|
23899
24099
|
suggestSkills(projectDir) {
|
|
23900
24100
|
const suggestions = [];
|
|
23901
|
-
const pkgPath =
|
|
23902
|
-
if (!
|
|
24101
|
+
const pkgPath = path16.join(projectDir, "package.json");
|
|
24102
|
+
if (!fs17.existsSync(pkgPath)) return suggestions;
|
|
23903
24103
|
try {
|
|
23904
|
-
const pkg = JSON.parse(
|
|
24104
|
+
const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf8"));
|
|
23905
24105
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
23906
24106
|
if (deps["detox"] || deps["maestro"]) {
|
|
23907
24107
|
suggestions.push("maestro-test");
|