sootsim 0.1.303 → 0.1.304
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/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-NKFJH2RJ.js → agent-EK355OQM.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-WEA3TGWF.js → agent-wrapper-LCJJWHZE.js} +2 -2
- package/dist-cli/chunks/app-fonts-LIPU2DLT.js +4 -0
- package/dist-cli/chunks/{assert-ZG65AUNK.js → assert-OASKCPBX.js} +2 -2
- package/dist-cli/chunks/{auth-RMFBZQIW.js → auth-XYYKD33F.js} +2 -2
- package/dist-cli/chunks/{beta-RR6TCDCJ.js → beta-TOL55XPM.js} +2 -2
- package/dist-cli/chunks/{camera-JWOAFE6U.js → camera-PHKVEQHR.js} +2 -2
- package/dist-cli/chunks/{chunk-AWE4ZKR3.js → chunk-2MEUZOSD.js} +1 -1
- package/dist-cli/chunks/{chunk-HKWQLGKK.js → chunk-2RLFUM3C.js} +3 -3
- package/dist-cli/chunks/{chunk-TDM4IQS3.js → chunk-3UUHIHA6.js} +2 -2
- package/dist-cli/chunks/{chunk-U7GJF4CQ.js → chunk-5NJTX5OP.js} +2 -2
- package/dist-cli/chunks/{chunk-GVC4ZNVM.js → chunk-76OLOD2G.js} +2 -2
- package/dist-cli/chunks/{chunk-LK63GSPB.js → chunk-7RFXZXKH.js} +1 -1
- package/dist-cli/chunks/{chunk-NRPNLTJI.js → chunk-A4UYZTV7.js} +2 -2
- package/dist-cli/chunks/{chunk-YOV3CQIH.js → chunk-ABHNOM2C.js} +1 -1
- package/dist-cli/chunks/{chunk-WI5GVQ6M.js → chunk-AJYA6R3N.js} +2 -2
- package/dist-cli/chunks/{chunk-YPZDXYHV.js → chunk-BJOT2LL6.js} +2 -2
- package/dist-cli/chunks/{chunk-MLX2UIH7.js → chunk-BPRMA4IC.js} +2 -2
- package/dist-cli/chunks/{chunk-CVRPU5KX.js → chunk-CMYVGJBQ.js} +1 -1
- package/dist-cli/chunks/{chunk-BYCMWKNX.js → chunk-ENXLKDQ6.js} +3 -3
- package/dist-cli/chunks/{chunk-G4B2PTUA.js → chunk-EXW6TH3O.js} +2 -2
- package/dist-cli/chunks/{chunk-APBN2B6C.js → chunk-FNI75AD7.js} +1 -1
- package/dist-cli/chunks/{chunk-4F7VUXKY.js → chunk-G4R7CPCY.js} +2 -2
- package/dist-cli/chunks/{chunk-H3U7LAZG.js → chunk-GF3LDVWF.js} +2 -2
- package/dist-cli/chunks/{chunk-QR4A5JV3.js → chunk-GMILMS7P.js} +2 -2
- package/dist-cli/chunks/{chunk-JZZIA5BR.js → chunk-HFA5ZACE.js} +1 -1
- package/dist-cli/chunks/{chunk-3YYCMGOR.js → chunk-HFKQUS4I.js} +3 -3
- package/dist-cli/chunks/{chunk-CQEK4J75.js → chunk-INBBOCU4.js} +2 -2
- package/dist-cli/chunks/chunk-ITDTSNN2.js +4 -0
- package/dist-cli/chunks/{chunk-VGNEIUJ7.js → chunk-IWRRIQDJ.js} +2 -2
- package/dist-cli/chunks/{chunk-3I647BPF.js → chunk-JDKWIB6V.js} +1 -1
- package/dist-cli/chunks/{chunk-MLHEWBGL.js → chunk-LRXSLMX4.js} +1 -1
- package/dist-cli/chunks/{chunk-UJIGVLKD.js → chunk-M3ETYVNL.js} +1 -1
- package/dist-cli/chunks/{chunk-FLLDNYUC.js → chunk-MSYPDBFG.js} +2 -2
- package/dist-cli/chunks/{chunk-ATRV3MGB.js → chunk-NXYKNKNL.js} +2 -2
- package/dist-cli/chunks/{chunk-FQZQKJZ5.js → chunk-OSH6526H.js} +1 -1
- package/dist-cli/chunks/{chunk-VLLTUTO5.js → chunk-QWQHSUZC.js} +2 -2
- package/dist-cli/chunks/chunk-RJWQ3VAD.js +14 -0
- package/dist-cli/chunks/{chunk-XAHT6BRW.js → chunk-RQJDIDJ3.js} +1 -1
- package/dist-cli/chunks/{chunk-657GXEAT.js → chunk-RT7TUHH7.js} +2 -2
- package/dist-cli/chunks/{chunk-LIK6FJNR.js → chunk-RYQUO6LT.js} +1 -1
- package/dist-cli/chunks/{chunk-2LMSJNAH.js → chunk-SN6ARNCL.js} +2 -2
- package/dist-cli/chunks/{chunk-SSGGUPY7.js → chunk-SVFN66PF.js} +2 -2
- package/dist-cli/chunks/{chunk-ZJ6EL5FU.js → chunk-UB3OWUVK.js} +1 -1
- package/dist-cli/chunks/{chunk-5NHCBHYZ.js → chunk-V6JDDX4B.js} +2 -2
- package/dist-cli/chunks/{chunk-M4SIQQDE.js → chunk-VUR5QXVX.js} +2 -2
- package/dist-cli/chunks/{chunk-TFWWL3HI.js → chunk-W3CSYOSQ.js} +1 -1
- package/dist-cli/chunks/{chunk-6Q5PHS4F.js → chunk-WNDYTKLC.js} +1 -1
- package/dist-cli/chunks/{chunk-TL6D2L7C.js → chunk-XCVSB47R.js} +2 -2
- package/dist-cli/chunks/{chunk-BQLQCPXE.js → chunk-XHYSASAX.js} +1 -1
- package/dist-cli/chunks/{chunk-DTQ4XGJP.js → chunk-XXS4TCOO.js} +3 -3
- package/dist-cli/chunks/{chunk-OSCWNNYR.js → chunk-Y5YM7XHU.js} +1 -1
- package/dist-cli/chunks/{chunk-AXDVKOGM.js → chunk-YAV6BH3A.js} +2 -2
- package/dist-cli/chunks/{chunk-XE2DUF5Z.js → chunk-YXHO2OUL.js} +1 -1
- package/dist-cli/chunks/{chunk-ZED5FLNC.js → chunk-ZDRI2LUG.js} +1 -1
- package/dist-cli/chunks/{chunk-BDZ7GDAA.js → chunk-ZONISYZ5.js} +1 -1
- package/dist-cli/chunks/{cleanup-MTGLBGPQ.js → cleanup-GCTEGJMP.js} +2 -2
- package/dist-cli/chunks/{cli-version-KF6SJ5QC.js → cli-version-G72HUH4E.js} +2 -2
- package/dist-cli/chunks/{compat-NIROXTXH.js → compat-IC4JHGBH.js} +2 -2
- package/dist-cli/chunks/{config-GVI5ADMM.js → config-C65MZFU3.js} +2 -2
- package/dist-cli/chunks/{control-RLM3WBEH.js → control-RWLYBKQR.js} +2 -2
- package/dist-cli/chunks/daemon-D77E5G6Z.js +4 -0
- package/dist-cli/chunks/{debug-QLQ6VFDL.js → debug-LEL32PDN.js} +3 -3
- package/dist-cli/chunks/{desktop-4KAE6XGD.js → desktop-RDSISJH2.js} +3 -3
- package/dist-cli/chunks/{detox-XW4L3NAA.js → detox-SCCWUIKK.js} +2 -2
- package/dist-cli/chunks/{device-IMVFXWBB.js → device-MTDEKDUK.js} +2 -2
- package/dist-cli/chunks/{diagnose-JTFFK6SX.js → diagnose-UZJCKLPZ.js} +2 -2
- package/dist-cli/chunks/disk-cleanup-HLWRVTVW.js +4 -0
- package/dist-cli/chunks/drivers-Q7GMKTBM.js +4 -0
- package/dist-cli/chunks/{film-BTQI2ZPO.js → film-YBE544PG.js} +3 -3
- package/dist-cli/chunks/flow-5VOVAVZN.js +4 -0
- package/dist-cli/chunks/help-2PESJ7V2.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-5Y3QDZ2L.js → hidden-runtime-alias-KJYCJLSR.js} +2 -2
- package/dist-cli/chunks/{home-paths-K2P3TAAX.js → home-paths-NSHWNEGK.js} +2 -2
- package/dist-cli/chunks/inspect-OIA3Q5MD.js +4 -0
- package/dist-cli/chunks/install-desktop-7KLACQUW.js +4 -0
- package/dist-cli/chunks/{login-DIHEERZB.js → login-AEVUU72R.js} +4 -4
- package/dist-cli/chunks/{logout-HXABB5BG.js → logout-72XHF6J2.js} +2 -2
- package/dist-cli/chunks/{maestro-LF67TXN2.js → maestro-OXSKQJ6B.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-XU7IAT4W.js → maestro-generate-AKZFORVJ.js} +3 -3
- package/dist-cli/chunks/{mode-GJRNBJWL.js → mode-U6KRG2PE.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-SXOSQMWZ.js → optional-demo-registry-L3VIWBI2.js} +2 -2
- package/dist-cli/chunks/{perf-IZY2XMUE.js → perf-KF2BJZIN.js} +2 -2
- package/dist-cli/chunks/{permissions-RLZXUFQU.js → permissions-TRJG4QAI.js} +2 -2
- package/dist-cli/chunks/{record-OBWLYFSP.js → record-TICJYZOA.js} +3 -3
- package/dist-cli/chunks/{report-issue-DU7TRHJK.js → report-issue-OQPLBQMJ.js} +2 -2
- package/dist-cli/chunks/runtime-HDMLWNXW.js +4 -0
- package/dist-cli/chunks/{screenshot-command-5IF4BSJ4.js → screenshot-command-XLERKHVW.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-OFYWMTVR.js → screenshots-capture-B6OORSD4.js} +2 -2
- package/dist-cli/chunks/{serve-DUES2MUY.js → serve-5M7MIPWF.js} +2 -2
- package/dist-cli/chunks/{setup-7JBMUE6Q.js → setup-HJZDC4PK.js} +2 -2
- package/dist-cli/chunks/{skills-J5HVAM75.js → skills-RXHLMGGL.js} +2 -2
- package/dist-cli/chunks/{storage-EPTR6RW5.js → storage-MMPD2XBS.js} +2 -2
- package/dist-cli/chunks/store-APKY72ZY.js +4 -0
- package/dist-cli/chunks/telemetry-W3YRHE67.js +4 -0
- package/dist-cli/chunks/{timeline-QR2474MZ.js → timeline-6PF5BZ37.js} +2 -2
- package/dist-cli/chunks/{upgrade-MQL27HMQ.js → upgrade-QSMIK3RC.js} +2 -2
- package/dist-cli/chunks/upload-HQEOYILQ.js +4 -0
- package/dist-cli/chunks/{version-ILGJD7EH.js → version-WLTFXEDC.js} +2 -2
- package/dist-cli/chunks/{web-NEPM3SZU.js → web-DI73LQ7N.js} +2 -2
- package/dist-cli/chunks/{what-happened-KGOUXBW4.js → what-happened-4SAMGZWR.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/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 +1 -1
- package/dist-lib/host/bridge-host.cjs +17 -8
- 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 +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +58 -3
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +21 -11
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +95 -9
- package/skills/sootsim-setup/SKILL.md +23 -11
- package/dist-cli/chunks/app-fonts-L5JXOKIF.js +0 -4
- package/dist-cli/chunks/chunk-E3POCZJT.js +0 -4
- package/dist-cli/chunks/chunk-YWAV3FQJ.js +0 -12
- package/dist-cli/chunks/daemon-O2R2GEWR.js +0 -4
- package/dist-cli/chunks/disk-cleanup-3HBGT6XT.js +0 -4
- package/dist-cli/chunks/drivers-BHLLX7OX.js +0 -4
- package/dist-cli/chunks/flow-C7PWEH4C.js +0 -4
- package/dist-cli/chunks/help-LOC2M6FR.js +0 -4
- package/dist-cli/chunks/inspect-JH64MAHP.js +0 -4
- package/dist-cli/chunks/install-desktop-C6KE3OM5.js +0 -4
- package/dist-cli/chunks/runtime-E7SIB4P3.js +0 -4
- package/dist-cli/chunks/store-W3YDQEZQ.js +0 -4
- package/dist-cli/chunks/telemetry-WXVIVQ4Y.js +0 -4
- package/dist-cli/chunks/upload-6IA2EKEH.js +0 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.304 | (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;
|
|
@@ -39,12 +39,15 @@ __export(dev_server_scanner_exports, {
|
|
|
39
39
|
__shouldReuseScannerCacheEntry: () => __shouldReuseScannerCacheEntry,
|
|
40
40
|
discoverListeningPorts: () => discoverListeningPorts,
|
|
41
41
|
discoverListeningProcesses: () => discoverListeningProcesses,
|
|
42
|
+
pidFromNetstat: () => pidFromNetstat,
|
|
42
43
|
probePort: () => probePort,
|
|
44
|
+
resolveListeningPid: () => resolveListeningPid,
|
|
43
45
|
resolveProcessCwd: () => resolveProcessCwd,
|
|
44
46
|
scanDevServers: () => scanDevServers
|
|
45
47
|
});
|
|
46
48
|
module.exports = __toCommonJS(dev_server_scanner_exports);
|
|
47
49
|
var import_child_process = require("child_process");
|
|
50
|
+
var import_promises2 = require("fs/promises");
|
|
48
51
|
var import_http = __toESM(require("http"), 1);
|
|
49
52
|
var import_net = __toESM(require("net"), 1);
|
|
50
53
|
var import_util = require("util");
|
|
@@ -576,15 +579,65 @@ async function discoverListeningPorts(excludePorts = []) {
|
|
|
576
579
|
const processes = await discoverListeningProcesses(excludePorts);
|
|
577
580
|
return processes.map((p) => p.port);
|
|
578
581
|
}
|
|
582
|
+
function pidFromNetstat(stdout, port) {
|
|
583
|
+
for (const line of stdout.split("\n")) {
|
|
584
|
+
if (!line.includes("LISTEN")) continue;
|
|
585
|
+
const parts = line.trim().split(/\s+/);
|
|
586
|
+
if (!parts[3]?.endsWith(`.${port}`)) continue;
|
|
587
|
+
for (const token of parts) {
|
|
588
|
+
const owner = token.match(/^\S+:(\d+)$/);
|
|
589
|
+
if (owner) {
|
|
590
|
+
const pid = Number(owner[1]);
|
|
591
|
+
if (pid > 0) return pid;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
async function resolveListeningPid(port) {
|
|
598
|
+
if (!Number.isInteger(port) || port <= 0) return null;
|
|
599
|
+
try {
|
|
600
|
+
const { stdout } = await execP("netstat -anv -p tcp 2>/dev/null", {
|
|
601
|
+
encoding: "utf8",
|
|
602
|
+
timeout: 8e3,
|
|
603
|
+
maxBuffer: 16 * 1024 * 1024
|
|
604
|
+
});
|
|
605
|
+
const pid = pidFromNetstat(stdout, port);
|
|
606
|
+
if (pid !== null) return pid;
|
|
607
|
+
} catch {
|
|
608
|
+
}
|
|
609
|
+
try {
|
|
610
|
+
const { stdout } = await execP(`ss -tlnp 2>/dev/null`, {
|
|
611
|
+
encoding: "utf8",
|
|
612
|
+
timeout: 8e3,
|
|
613
|
+
maxBuffer: 16 * 1024 * 1024
|
|
614
|
+
});
|
|
615
|
+
for (const line of stdout.split("\n")) {
|
|
616
|
+
if (!new RegExp(`:${port}\\s`).test(line)) continue;
|
|
617
|
+
const pid = Number(line.match(/pid=(\d+)/)?.[1]);
|
|
618
|
+
if (pid > 0) return pid;
|
|
619
|
+
}
|
|
620
|
+
} catch {
|
|
621
|
+
}
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
579
624
|
var cwdByPid = /* @__PURE__ */ new Map();
|
|
580
625
|
async function resolveProcessCwd(pid) {
|
|
581
626
|
if (pid <= 0) return null;
|
|
582
627
|
const cached2 = cwdByPid.get(pid);
|
|
583
628
|
if (cached2) return cached2;
|
|
584
629
|
try {
|
|
585
|
-
const
|
|
630
|
+
const cwd = await (0, import_promises2.readlink)(`/proc/${pid}/cwd`);
|
|
631
|
+
if (cwd) {
|
|
632
|
+
cwdByPid.set(pid, cwd);
|
|
633
|
+
return cwd;
|
|
634
|
+
}
|
|
635
|
+
} catch {
|
|
636
|
+
}
|
|
637
|
+
try {
|
|
638
|
+
const { stdout } = await execP(`lsof -b -w -p ${pid} -a -d cwd -Fn 2>/dev/null`, {
|
|
586
639
|
encoding: "utf8",
|
|
587
|
-
timeout:
|
|
640
|
+
timeout: 8e3
|
|
588
641
|
});
|
|
589
642
|
for (const line of stdout.split("\n")) {
|
|
590
643
|
if (line.startsWith("n") && line.length > 1) {
|
|
@@ -923,7 +976,9 @@ async function scanDevServers(opts = {}) {
|
|
|
923
976
|
__shouldReuseScannerCacheEntry,
|
|
924
977
|
discoverListeningPorts,
|
|
925
978
|
discoverListeningProcesses,
|
|
979
|
+
pidFromNetstat,
|
|
926
980
|
probePort,
|
|
981
|
+
resolveListeningPid,
|
|
927
982
|
resolveProcessCwd,
|
|
928
983
|
scanDevServers
|
|
929
984
|
});
|
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.304 | (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 __defProp = Object.defineProperty;
|
package/dist-lib/sdk.mjs
CHANGED
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.304 | (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;
|
|
@@ -11386,9 +11386,17 @@ async function resolveProcessCwd(pid) {
|
|
|
11386
11386
|
const cached4 = cwdByPid.get(pid);
|
|
11387
11387
|
if (cached4) return cached4;
|
|
11388
11388
|
try {
|
|
11389
|
-
const
|
|
11389
|
+
const cwd = await (0, import_promises2.readlink)(`/proc/${pid}/cwd`);
|
|
11390
|
+
if (cwd) {
|
|
11391
|
+
cwdByPid.set(pid, cwd);
|
|
11392
|
+
return cwd;
|
|
11393
|
+
}
|
|
11394
|
+
} catch {
|
|
11395
|
+
}
|
|
11396
|
+
try {
|
|
11397
|
+
const { stdout } = await execP(`lsof -b -w -p ${pid} -a -d cwd -Fn 2>/dev/null`, {
|
|
11390
11398
|
encoding: "utf8",
|
|
11391
|
-
timeout:
|
|
11399
|
+
timeout: 8e3
|
|
11392
11400
|
});
|
|
11393
11401
|
for (const line of stdout.split("\n")) {
|
|
11394
11402
|
if (line.startsWith("n") && line.length > 1) {
|
|
@@ -11695,11 +11703,12 @@ async function scanDevServers(opts = {}) {
|
|
|
11695
11703
|
}
|
|
11696
11704
|
return results.filter((r) => !isSootSimSelfServer(r));
|
|
11697
11705
|
}
|
|
11698
|
-
var import_child_process, import_http, import_net, import_util, execP, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, FALLBACK_PORTS, cwdByPid, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
|
|
11706
|
+
var import_child_process, import_promises2, import_http, import_net, import_util, execP, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, TCP_GATE_MS, FALLBACK_PORTS, cwdByPid, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownNonExpo, knownOne, portCache, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
|
|
11699
11707
|
var init_dev_server_scanner = __esm({
|
|
11700
11708
|
"scripts/dev-server-scanner.ts"() {
|
|
11701
11709
|
"use strict";
|
|
11702
11710
|
import_child_process = require("child_process");
|
|
11711
|
+
import_promises2 = require("fs/promises");
|
|
11703
11712
|
import_http = __toESM(require("http"), 1);
|
|
11704
11713
|
import_net = __toESM(require("net"), 1);
|
|
11705
11714
|
import_util = require("util");
|
|
@@ -12355,7 +12364,7 @@ async function downloadToFile(url, destPath) {
|
|
|
12355
12364
|
import_node_fs4.default.mkdirSync(import_node_path4.default.dirname(destPath), { recursive: true });
|
|
12356
12365
|
const tmp = `${destPath}.partial`;
|
|
12357
12366
|
try {
|
|
12358
|
-
await (0,
|
|
12367
|
+
await (0, import_promises3.pipeline)(
|
|
12359
12368
|
import_node_stream.Readable.fromWeb(res.body),
|
|
12360
12369
|
import_node_fs4.default.createWriteStream(tmp)
|
|
12361
12370
|
);
|
|
@@ -12389,7 +12398,7 @@ function extractTarball(tarPath, destDir) {
|
|
|
12389
12398
|
});
|
|
12390
12399
|
});
|
|
12391
12400
|
}
|
|
12392
|
-
var import_node_child_process2, import_node_crypto, import_node_fs4, import_node_os2, import_node_path4, import_node_stream,
|
|
12401
|
+
var import_node_child_process2, import_node_crypto, import_node_fs4, import_node_os2, import_node_path4, import_node_stream, import_promises3, DEFAULT_LOCAL_RUNTIME_RETENTION_COUNT;
|
|
12393
12402
|
var init_src = __esm({
|
|
12394
12403
|
"../contrast-runtime-delivery/src/index.ts"() {
|
|
12395
12404
|
"use strict";
|
|
@@ -12399,7 +12408,7 @@ var init_src = __esm({
|
|
|
12399
12408
|
import_node_os2 = __toESM(require("node:os"), 1);
|
|
12400
12409
|
import_node_path4 = __toESM(require("node:path"), 1);
|
|
12401
12410
|
import_node_stream = require("node:stream");
|
|
12402
|
-
|
|
12411
|
+
import_promises3 = require("node:stream/promises");
|
|
12403
12412
|
init_product();
|
|
12404
12413
|
init_product();
|
|
12405
12414
|
DEFAULT_LOCAL_RUNTIME_RETENTION_COUNT = 2;
|
|
@@ -14069,7 +14078,7 @@ async function handleFetchProxyRequest(req, res) {
|
|
|
14069
14078
|
const switchToGet = (status === 301 || status === 302) && method === "POST" || status === 303 && method !== "GET" && method !== "HEAD";
|
|
14070
14079
|
const redirectUrl = new URL(location, targetUrl2);
|
|
14071
14080
|
proxyRes.resume();
|
|
14072
|
-
await (0,
|
|
14081
|
+
await (0, import_promises4.finished)(proxyRes);
|
|
14073
14082
|
await proxy(
|
|
14074
14083
|
redirectUrl,
|
|
14075
14084
|
switchToGet ? "GET" : method,
|
|
@@ -14094,7 +14103,7 @@ async function handleFetchProxyRequest(req, res) {
|
|
|
14094
14103
|
);
|
|
14095
14104
|
}
|
|
14096
14105
|
res.statusCode = status;
|
|
14097
|
-
await (0,
|
|
14106
|
+
await (0, import_promises4.pipeline)(proxyRes, res);
|
|
14098
14107
|
};
|
|
14099
14108
|
try {
|
|
14100
14109
|
await proxy(upstreamUrl, originalMethod, body, 0);
|
|
@@ -14177,13 +14186,13 @@ function handleAppApiRequest(req, res) {
|
|
|
14177
14186
|
req.pipe(proxyReq);
|
|
14178
14187
|
return true;
|
|
14179
14188
|
}
|
|
14180
|
-
var import_http2, import_https,
|
|
14189
|
+
var import_http2, import_https, import_promises4, STRIP_FETCH_PROXY_HEADERS, FETCH_PROXY_CORS_HEADERS, APP_API_HEADER_REWRITES;
|
|
14181
14190
|
var init_fetch_proxy_handler = __esm({
|
|
14182
14191
|
"src/host/fetch-proxy-handler.ts"() {
|
|
14183
14192
|
"use strict";
|
|
14184
14193
|
import_http2 = __toESM(require("http"), 1);
|
|
14185
14194
|
import_https = __toESM(require("https"), 1);
|
|
14186
|
-
|
|
14195
|
+
import_promises4 = require("stream/promises");
|
|
14187
14196
|
init_backend_origin();
|
|
14188
14197
|
init_fetch_proxy_overrides();
|
|
14189
14198
|
STRIP_FETCH_PROXY_HEADERS = /* @__PURE__ */ new Set([
|
|
@@ -18636,6 +18645,7 @@ var init_app_fonts = __esm({
|
|
|
18636
18645
|
"use strict";
|
|
18637
18646
|
import_node_module = require("node:module");
|
|
18638
18647
|
import_config_plugin_fonts = require("sootsim-engine/engine/config-plugin-fonts");
|
|
18648
|
+
init_dev_server_scanner();
|
|
18639
18649
|
init_app_project();
|
|
18640
18650
|
require2 = (0, import_node_module.createRequire)(__sootsim_import_meta_url);
|
|
18641
18651
|
}
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.304 | (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;
|
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// pid changes. before any HTTP, a TCP connect gate skips unreachable ports.
|
|
15
15
|
|
|
16
16
|
import { exec } from 'child_process'
|
|
17
|
+
import { readlink } from 'fs/promises'
|
|
17
18
|
import http from 'http'
|
|
18
19
|
import net from 'net'
|
|
19
20
|
import { promisify } from 'util'
|
|
@@ -222,27 +223,112 @@ export async function discoverListeningPorts(
|
|
|
222
223
|
return processes.map((p) => p.port)
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
/** parse `netstat -anv -p tcp` output for the pid listening on one port.
|
|
227
|
+
*
|
|
228
|
+
* macOS lays a LISTEN row out as
|
|
229
|
+
* tcp4 0 0 127.0.0.1.8090 *.* LISTEN 0 0 131072 131072 node:97330 ...
|
|
230
|
+
* so the local address is the 4th column with a DOT before the port (which is
|
|
231
|
+
* what keeps port 8137 from matching a row for 18137), and the owner is the
|
|
232
|
+
* only token shaped "<name>:<pid>".
|
|
233
|
+
*
|
|
234
|
+
* exported because this column layout is the fragile part and a child process
|
|
235
|
+
* cannot exercise it under bun's test runner, which hands back empty stdout. */
|
|
236
|
+
export function pidFromNetstat(stdout: string, port: number): number | null {
|
|
237
|
+
for (const line of stdout.split('\n')) {
|
|
238
|
+
if (!line.includes('LISTEN')) continue
|
|
239
|
+
const parts = line.trim().split(/\s+/)
|
|
240
|
+
if (!parts[3]?.endsWith(`.${port}`)) continue
|
|
241
|
+
for (const token of parts) {
|
|
242
|
+
const owner = token.match(/^\S+:(\d+)$/)
|
|
243
|
+
if (owner) {
|
|
244
|
+
const pid = Number(owner[1])
|
|
245
|
+
if (pid > 0) return pid
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return null
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** resolve the pid of the process listening on one local port.
|
|
253
|
+
*
|
|
254
|
+
* `lsof` walks every descriptor of every process, which measures 2-4s on a
|
|
255
|
+
* loaded machine — longer than any timeout worth giving it, so
|
|
256
|
+
* `discoverListeningProcesses` above degrades to its pid-less port list
|
|
257
|
+
* exactly when the machine is busy. netstat (macOS/BSD) and ss (linux) read
|
|
258
|
+
* the kernel socket table instead and answer in well under a second, and both
|
|
259
|
+
* carry the owning pid. use this whenever the question is "who owns this one
|
|
260
|
+
* port"; `discoverListeningProcesses` answers the different question of what
|
|
261
|
+
* is listening at all. */
|
|
262
|
+
export async function resolveListeningPid(port: number): Promise<number | null> {
|
|
263
|
+
if (!Number.isInteger(port) || port <= 0) return null
|
|
264
|
+
|
|
265
|
+
// macOS netstat: "tcp4 0 0 127.0.0.1.8090 *.* LISTEN ... node:97330 ..."
|
|
266
|
+
// the local address uses a dot before the port, and the owner column is the
|
|
267
|
+
// only token shaped "<name>:<pid>".
|
|
268
|
+
try {
|
|
269
|
+
const { stdout } = await execP('netstat -anv -p tcp 2>/dev/null', {
|
|
270
|
+
encoding: 'utf8',
|
|
271
|
+
timeout: 8000,
|
|
272
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
273
|
+
})
|
|
274
|
+
const pid = pidFromNetstat(stdout, port)
|
|
275
|
+
if (pid !== null) return pid
|
|
276
|
+
} catch {}
|
|
277
|
+
|
|
278
|
+
// linux ss: 'LISTEN 0 511 0.0.0.0:8081 0.0.0.0:* users:(("node",pid=1234,fd=5))'
|
|
279
|
+
try {
|
|
280
|
+
const { stdout } = await execP(`ss -tlnp 2>/dev/null`, {
|
|
281
|
+
encoding: 'utf8',
|
|
282
|
+
timeout: 8000,
|
|
283
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
284
|
+
})
|
|
285
|
+
for (const line of stdout.split('\n')) {
|
|
286
|
+
if (!new RegExp(`:${port}\\s`).test(line)) continue
|
|
287
|
+
const pid = Number(line.match(/pid=(\d+)/)?.[1])
|
|
288
|
+
if (pid > 0) return pid
|
|
289
|
+
}
|
|
290
|
+
} catch {}
|
|
291
|
+
|
|
292
|
+
return null
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// per-pid cwd cache. lsof is the only way to read another process's cwd on
|
|
296
|
+
// macOS and it is NOT cheap — measured at 3-8s for a single pid on a machine
|
|
297
|
+
// running a few dozen node processes — so caching the result until the pid
|
|
298
|
+
// goes away is what keeps the 5s tray scan viable.
|
|
228
299
|
const cwdByPid = new Map<number, string>()
|
|
229
300
|
|
|
230
|
-
/** resolve the current working directory of a pid
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
301
|
+
/** resolve the current working directory of a pid. returns null for pid 0
|
|
302
|
+
* (unknown owner) and whenever neither mechanism below can see the process.
|
|
303
|
+
* async — sync exec blocked CrBrowserMain at ~600ms on macOS.
|
|
304
|
+
*
|
|
305
|
+
* `-b -w` skips the blocking stat calls lsof otherwise makes against every
|
|
306
|
+
* mount, which roughly halves it. the timeout is generous because the answer
|
|
307
|
+
* is cached per pid: too tight a limit silently returns null on exactly the
|
|
308
|
+
* busy machines where auto-attaching a project matters most. */
|
|
234
309
|
export async function resolveProcessCwd(pid: number): Promise<string | null> {
|
|
235
310
|
if (pid <= 0) return null
|
|
236
311
|
const cached = cwdByPid.get(pid)
|
|
237
312
|
if (cached) return cached
|
|
313
|
+
|
|
314
|
+
// linux publishes the cwd as a symlink, which costs one readlink and no
|
|
315
|
+
// subprocess at all. macOS has no /proc and has to pay for lsof below.
|
|
316
|
+
try {
|
|
317
|
+
const cwd = await readlink(`/proc/${pid}/cwd`)
|
|
318
|
+
if (cwd) {
|
|
319
|
+
cwdByPid.set(pid, cwd)
|
|
320
|
+
return cwd
|
|
321
|
+
}
|
|
322
|
+
} catch {}
|
|
323
|
+
|
|
238
324
|
try {
|
|
239
325
|
// -Fn → machine-readable, one field per line. lines look like:
|
|
240
326
|
// p<pid>
|
|
241
327
|
// fcwd
|
|
242
328
|
// n<absolute path>
|
|
243
|
-
const { stdout } = await execP(`lsof -p ${pid} -a -d cwd -Fn 2>/dev/null`, {
|
|
329
|
+
const { stdout } = await execP(`lsof -b -w -p ${pid} -a -d cwd -Fn 2>/dev/null`, {
|
|
244
330
|
encoding: 'utf8',
|
|
245
|
-
timeout:
|
|
331
|
+
timeout: 8000,
|
|
246
332
|
})
|
|
247
333
|
for (const line of stdout.split('\n')) {
|
|
248
334
|
if (line.startsWith('n') && line.length > 1) {
|
|
@@ -23,16 +23,25 @@ debugging or `/sootsim-test` for writing tests.
|
|
|
23
23
|
- **an empty `sootsim list` is not "broken sootsim"** — it usually means the
|
|
24
24
|
daemon is down, the dev server port is wrong, or the runtime is missing.
|
|
25
25
|
walk the recovery checklist before reinstalling.
|
|
26
|
-
- **one sim
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
- **one sim for your whole session. switch APPS by navigating that sim, never by
|
|
27
|
+
opening another.** `sootsim open <port> --sim <id>` resolves that exact sim and
|
|
28
|
+
navigates it in place — no new tab, no new browser tree. that is the supported
|
|
29
|
+
way to move between apps and ports:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
sootsim open 8086 --sim <id> # one app, in your sim
|
|
33
|
+
sootsim open 8090 --sim <id> # a different app, same tab
|
|
34
|
+
sootsim reload --sim <id> # reload whatever it is showing
|
|
35
|
+
sootsim close <id> # dispose it when you are done
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
every `--new` spawns another browser tree, and each abandoned tab holds a
|
|
39
|
+
renderer process for the life of the browser. these land in somebody's actual
|
|
40
|
+
desktop Chrome. a run that opened one per app left 14 renderers against 2 live
|
|
41
|
+
sims on a shared machine and the owner noticed before we did.
|
|
33
42
|
- **sharing a machine with other agents? open ONE sim with `--new`, pin it, and
|
|
34
|
-
pass `--sim <id>` from then on.**
|
|
35
|
-
unpinned command has no sim of its own, so it falls back to whatever sim is
|
|
43
|
+
pass `--sim <id>` from then on.** that single `--new` is the only one you get.
|
|
44
|
+
an unpinned command has no sim of its own, so it falls back to whatever sim is
|
|
36
45
|
currently PRIMARY — and that can be another agent's live sim, mid-run. a plain
|
|
37
46
|
`sootsim open <port>` from an unpinned CLI will happily retarget somebody
|
|
38
47
|
else's sim to your port and take over their session; the warning it prints is
|
|
@@ -47,8 +56,11 @@ debugging or `/sootsim-test` for writing tests.
|
|
|
47
56
|
sootsim describe --sim <id> # name it on every command after that
|
|
48
57
|
```
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
`--new`, `--profile`, and `--ephemeral` are rejected outright when combined
|
|
60
|
+
with `--sim`, so if a command needs one of them you are starting a second sim
|
|
61
|
+
whether you meant to or not. if yours died, run `sootsim list --all` and adopt
|
|
62
|
+
an open unlocked sim with `sootsim use <id>` before you consider opening one.
|
|
63
|
+
always close yours when you finish.
|
|
52
64
|
- **never retry-loop `sootsim open` against a wedged or slow stack.** a
|
|
53
65
|
connect-timeout ("timed out waiting for opened sim to connect") means STOP and
|
|
54
66
|
diagnose — not retry. each retried open spawns a new browser tree (a
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.303 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{d as p}from"./chunk-E3POCZJT.js";import"./chunk-XAHT6BRW.js";import"./chunk-BQLQCPXE.js";import{existsSync as h,mkdirSync as d,readFileSync as y,writeFileSync as g}from"node:fs";import{join as m}from"node:path";import{gzipSync as w}from"node:zlib";function f(t,e){let o=t.indexOf(`--${e}`);if(o!==-1&&o+1<t.length)return t[o+1];let i=t.find(r=>r.startsWith(`--${e}=`));return i?i.slice(e.length+3):void 0}async function S(t){let e=f(t,"wire")||"",o=f(t,"out-dir"),i=f(t,"manifest");if((!o||!i)&&(console.error(" usage: sootsim app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>"),process.exit(1)),!e.trim()){console.log("no app fonts declared \u2014 nothing to stage");return}d(o,{recursive:!0});let r=await p(e,{onStaged:({url:n,byteLength:s})=>console.log(` staged app font: ${n} (${(s/1024).toFixed(1)} KiB)`),onError:(n,s)=>console.error(` warning: failed to fetch app font ${n}: ${s instanceof Error?s.message:s}`)}),a=[];for(let n of r){let s=w(n.bytes);g(m(o,n.urlhash),s),a.push({url:n.url,urlhash:n.urlhash,contentType:n.contentType,encoding:"gzip",sizeBytes:s.length,rawBytes:n.bytes.byteLength})}let c=[];if(h(i))try{let n=JSON.parse(y(i,"utf8"));Array.isArray(n)&&(c=n)}catch{}let u=new Set(c.map(n=>n.urlhash)),l=[...c,...a.filter(n=>!u.has(n.urlhash))];g(i,JSON.stringify(l)),console.log(`staged ${a.length} app font(s); manifest now has ${l.length} file(s)`)}async function E(t){let e=t[0];if(e==="stage"){await S(t.slice(1));return}console.error(` unknown app-fonts subcommand: ${e??"(none)"}`),console.error(" available: stage"),process.exit(1)}export{E as runAppFonts};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.303 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import { createRequire as __sootsimCreateRequire } from 'node:module'
|
|
3
|
-
var require = __sootsimCreateRequire(import.meta.url)
|
|
4
|
-
import{a as S}from"./chunk-XAHT6BRW.js";import{createHash as W}from"node:crypto";import w from"node:fs";import{createRequire as v}from"node:module";import c from"node:path";var D=/\.(ttf|otf|woff|woff2)$/i;function _(t,n,o){if(!t||typeof t!="object")return;let r=t.fonts;if(Array.isArray(r))for(let s of r)typeof s=="string"&&o.push(s);let i=t[n];if(!i||typeof i!="object")return;let e=i.fonts;if(Array.isArray(e))for(let s of e){if(typeof s=="string"){o.push(s);continue}if(!s||typeof s!="object")continue;let l=s.fontDefinitions;if(Array.isArray(l))for(let m of l){if(!m||typeof m!="object")continue;let h=m.path;typeof h=="string"&&o.push(h)}}}function $(t,n){if(!Array.isArray(t))return[];let o=[];for(let r of t){let i=Array.isArray(r)?r[0]:r;if(typeof i!="string"||!/(^|\/)expo-font$/.test(i))continue;let e=Array.isArray(r)?r[1]??{}:{};_(e,n,o)}return o}function N(t){return t.slice(t.lastIndexOf("/")+1).replace(D,"")}function T(t,n){let o=n.replace(/\/+$/,""),r=new Set,i=[];for(let e of t){let s=e.replace(/^\.\//,"").replace(/^\/+/,"");!s||r.has(s)||(r.add(s),D.test(s)&&i.push({family:N(s),url:`${o}/assets/${s}`}))}return i}var O=v(import.meta.url);function E(t){try{let n=new URL(t),o=n.hostname.replace(/^\[|\]$/g,"").toLowerCase();if(o==="localhost"||o.endsWith(".localhost")||o==="0.0.0.0"||o==="::1"||/^127(?:\.\d{1,3}){3}$/.test(o))return n.origin}catch{}return null}function q(t){try{return w.statSync(c.join(t,"package.json")).isFile()}catch{return!1}}function Q(t){let n=E(t.bundleUrl);if(!n)return[];let o=t.repoDir||process.env.CONTRAST_REPO_DIR,r=o?c.resolve(o):process.cwd();if(!o&&!q(r))return[];let i=S(r,{trustStart:t.exactProjectDir}),e=i?.appDir??null;if(!e)return[];let s=(t.platform||process.env.CONTRAST_PLATFORM||"ios").toLowerCase(),l=null;if(o||i)try{let f=O.resolve("@expo/config",{paths:[e,r]}),g=O(f);typeof g.getConfig=="function"&&(l=g.getConfig)}catch{}let m=[];if(l)try{let f=l(e,{skipSDKVersionRequirement:!0});if(f?.exp&&typeof f.exp=="object"){let g=f.exp.plugins;Array.isArray(g)&&(m=g)}}catch{}let h=$(m,s==="android"?"android":"ios").slice(0,256),I=Date.now(),P=0,A=(f,g)=>{let d=[{dir:f,depth:0}],p=0;for(;p<d.length&&P<64&&h.length<256&&Date.now()-I<50;){let a=d[p++];if(!a)continue;P++;let y;try{y=w.readdirSync(a.dir,{withFileTypes:!0})}catch{continue}for(let u of y){if(u.isSymbolicLink())continue;let x=c.join(a.dir,u.name);if(u.isDirectory()){a.depth<4&&d.length<64&&!u.name.startsWith(".")&&d.push({dir:x,depth:a.depth+1});continue}if(!u.isFile()||!/\.(ttf|otf|woff|woff2)$/i.test(u.name))continue;let j=c.relative(f,x).split(c.sep).join("/");if(h.push(c.posix.join(g,j)),h.length>=256)break}}};try{let f=JSON.parse(w.readFileSync(c.join(e,"package.json"),"utf8")),g=new Set;for(let p of["dependencies","devDependencies","optionalDependencies"]){let a=Reflect.get(f,p);if(!(!a||typeof a!="object"))for(let y of Object.keys(a))g.add(y)}let d=[...g].filter(p=>p==="react-native-vector-icons"||p.startsWith("@react-native-vector-icons/"));if(d.length>0){let p=Reflect.get(f,"reactNativeVectorIcons"),a=p&&typeof p=="object"?Reflect.get(p,"fontDir"):null,y=typeof a=="string"?a:"rnvi-fonts",u=c.resolve(e,y),x=c.relative(e,u);!x.startsWith("..")&&!c.isAbsolute(x)&&A(u,x.split(c.sep).join("/"));let j=v(c.join(e,"package.json"));for(let F of d)try{let b=j.resolve(F),L=F.split("/").join(c.sep),R=`${c.sep}node_modules${c.sep}${L}${c.sep}`,k=b.lastIndexOf(R);if(k===-1)continue;let U=b.slice(0,k+R.length-1),C=F==="react-native-vector-icons"?"Fonts":"fonts";A(c.join(U,C),c.posix.join("node_modules",F,C))}catch{}}}catch{}try{let f=c.join(e,"react-native.config.js");if(w.statSync(f).isFile()){let d=v(c.join(e,"package.json"))(f),p=d&&typeof d=="object"?Reflect.get(d,"assets"):null;if(Array.isArray(p))for(let a of p){if(typeof a!="string")continue;let y=c.resolve(e,a),u=c.relative(e,y);u.startsWith("..")||c.isAbsolute(u)||A(y,u.split(c.sep).join("/"))}}}catch{}return T(h,n)}async function Y(t,n){let o=E(t);if(!o)return null;let r=new AbortController,i=setTimeout(()=>r.abort(),n?.timeoutMs??1500);try{let e=await fetch(`${o}/`,{headers:{"expo-platform":"ios",Accept:"application/json"},signal:r.signal});if(!e.ok)return null;let l=(await e.json())?.extra?.expoClient?._internal?.projectRoot;return typeof l=="string"&&l.length>0?l:null}catch{return null}finally{clearTimeout(i)}}function Z(t){return t.map(n=>`${encodeURIComponent(n.url)}::${encodeURIComponent(n.family)}`).join(",")}function M(t){let n=[];for(let o of t.split(",")){let r=o.trim();if(!r)continue;let i=r.indexOf("::"),e=i===-1?r:r.slice(0,i);try{n.push(decodeURIComponent(e))}catch{n.push(e)}}return n.filter(Boolean)}function G(t){let n=(t.split("?")[0].split(".").pop()||"").toLowerCase();return n==="ttf"?"font/ttf":n==="otf"?"font/otf":n==="woff"?"font/woff":n==="woff2"?"font/woff2":"application/octet-stream"}async function tt(t,n){let o=[],r=new Set;for(let i of M(t)){let e=W("sha256").update(i).digest("hex");if(!r.has(e)){r.add(e);try{let s=await fetch(i);if(!s.ok){n?.onError?.(i,new Error(`${s.status} ${s.statusText}`));continue}let l=new Uint8Array(await s.arrayBuffer());o.push({url:i,urlhash:e,contentType:G(i),bytes:l}),n?.onStaged?.({url:i,byteLength:l.byteLength})}catch(s){n?.onError?.(i,s)}}}return o}export{Q as a,Y as b,Z as c,tt as d};
|