stim 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -4
- package/dist/{activity-BxnkDZDi.mjs → activity-BrGh9EAI.mjs} +3 -3
- package/dist/{agent-device-usage-output-CZ66YA4T.mjs → agent-device-usage-output-DVyv_hWj.mjs} +7 -7
- package/dist/android-0vv-OruW.mjs +6 -0
- package/dist/android-Brx6EKvJ.mjs +1258 -0
- package/dist/{android-DC3ZLuw0.mjs → android-BsYNR81W.mjs} +103 -45
- package/dist/{android-CBwCNicO.mjs → android-CK3fpEyZ.mjs} +2 -2
- package/dist/{android-cas-BBFyr9CA.mjs → android-cas-DCAuXryb.mjs} +9 -5
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/api-run.mjs +159 -8
- package/dist/{api-D0VtFhqk.mjs → api-zuX3ynYN.mjs} +9 -7
- package/dist/api.d.mts +104 -4
- package/dist/api.mjs +1 -1
- package/dist/{app-install-D-PUENug.mjs → app-install-0LgaQRT7.mjs} +39 -18
- package/dist/artifact-CnC0mfov.mjs +807 -0
- package/dist/artifact-DClXJNWx.mjs +772 -0
- package/dist/artifact-lifecycle-DzPpBYvK.mjs +30 -0
- package/dist/{web-DTU0uiWj.mjs → browser-web-CzBmhmgs.mjs} +136 -174
- package/dist/{budget-DIhL2BKx.mjs → budget-BONq9vXY.mjs} +3096 -3244
- package/dist/build-BixRI6sB.mjs +462 -0
- package/dist/build-plan-CP0tckNU.mjs +553 -0
- package/dist/{cache-manifest-BI7ozfmH.mjs → cache-manifest-qA3dT2x2.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/ccache-CjHQ5F8g.mjs +142 -0
- package/dist/{chrome-DJnmnS5q.mjs → chrome-Dp2lMLBe.mjs} +1 -1
- package/dist/{cli-DNJMwADx.mjs → cli-B2R8wH1F.mjs} +20 -20
- package/dist/cli.mjs +1 -1
- package/dist/{client-DzhapoMB.mjs → client-BLy1Pw2V.mjs} +172 -165
- package/dist/collector-run.d.mts +10 -0
- package/dist/collector-run.mjs +7 -7
- package/dist/{command-output-CBtzyIgF.mjs → command-output-BjPN99ZB.mjs} +2 -2
- package/dist/{config-CgYMahz7.mjs → config-D0LhTY3S.mjs} +13 -13
- package/dist/{created-devices-DKbeWsiK.mjs → created-devices-HU_DAb_Q.mjs} +7 -6
- package/dist/{dependency-state-xKoOypBm.mjs → dependency-state-B2m8eqsS.mjs} +2 -2
- package/dist/{detached-entry-BLfcgc4O.mjs → detached-entry-BXq4fIl-.mjs} +1 -1
- package/dist/{dev-client-CLnIH02x.mjs → dev-client-ClATaJoH.mjs} +2 -2
- package/dist/{device-D7oCHGWi.mjs → device-B7lsC0K1.mjs} +8 -8
- package/dist/device-DVCwAFlX.mjs +727 -0
- package/dist/{device-capacity-EUOOYr8T.mjs → device-capacity-Ca_ke1LE.mjs} +25 -15
- package/dist/device-host-worker.mjs +38 -18
- package/dist/{device-ios-6MewKKnc.mjs → device-ios-CRUqPxKw.mjs} +12 -11
- package/dist/{device-lease-Co-EwifR.mjs → device-lease-DHOBXGgS.mjs} +135 -22
- package/dist/{device-lease-run-w1xhCqIW.mjs → device-lease-run-CvDeHTkG.mjs} +4 -4
- package/dist/{device-pool-F5WvRPtD.mjs → device-pool-L2-5GxMy.mjs} +3 -3
- package/dist/{device-remote-tHbd1fKy.mjs → device-remote-Bmg42063.mjs} +17 -69
- package/dist/doctor-C2MSuMMg.mjs +515 -0
- package/dist/{doctor-B9ckYUoU.mjs → doctor-DPAqhVCK.mjs} +334 -721
- package/dist/doctor-watchman-CB4NnVZm.mjs +260 -0
- package/dist/{simslim-EHBQ2R4G.mjs → eas-build-Dw_ec2Km.mjs} +6 -152
- package/dist/{stim-installations-aR_WsNOA.mjs → eas-session-ledger-DZlC-Fq3.mjs} +57 -4
- package/dist/{error-diagnostics-BRXOqDzG.mjs → error-diagnostics-Du7I_GuY.mjs} +17 -12
- package/dist/errors-DzkMYh8Q.mjs +205 -0
- package/dist/{exec-DWhCZDGm.mjs → exec-B81Qodjn.mjs} +69 -15
- package/dist/{gc-Dh6mXOKC.mjs → gc-PWp34zGb.mjs} +23 -22
- package/dist/{gradle-C6GKnunQ.mjs → gradle-C2OEKCCI.mjs} +50 -125
- package/dist/{guide-tm6igAaa.mjs → guide-Dai9lphv.mjs} +862 -538
- package/dist/{hosted-android-Bv285t_t.mjs → hosted-android-DQ-Agsd8.mjs} +5 -5
- package/dist/{hosted-client-C-rMtppF.mjs → hosted-client-Io01s5By.mjs} +9 -3
- package/dist/{hosted-ios-D5mNmtj4.mjs → hosted-ios-DIxFnYp-.mjs} +3 -3
- package/dist/{hosted-logs-DN8Iz4mJ.mjs → hosted-logs-DP-ABU_M.mjs} +8 -8
- package/dist/{hosted-macos-B-wEjlwG.mjs → hosted-macos-Aziw9T_9.mjs} +7 -6
- package/dist/{hosted-native-DeeOG8xZ.mjs → hosted-native-BdAQi21M.mjs} +23 -16
- package/dist/{idle-shutdown-jjtxAn5C.mjs → idle-shutdown-DdMqoSUB.mjs} +7 -7
- package/dist/ios-BZ9dg2Fr.mjs +9 -0
- package/dist/{ios-B3SbOWdw.mjs → ios-CXLIUxXJ.mjs} +180 -24
- package/dist/ios-CZuv6gRv.mjs +1112 -0
- package/dist/{ios-Bvbf0SGY.mjs → ios-VGvNdsv2.mjs} +1 -1
- package/dist/{ios-device-Bn7jWDB1.mjs → ios-device-B1B14xND.mjs} +1 -1
- package/dist/{ios-device-vOaByMhw.mjs → ios-device-BreZOpM0.mjs} +3 -3
- package/dist/ios-project-B9drt_aY.mjs +197 -0
- package/dist/{ios-state-B2pES6Vs.mjs → ios-state-CjrL2qv-.mjs} +1 -1
- package/dist/js-swap-C8icNYIY.mjs +432 -0
- package/dist/launch-DxH0THLP.mjs +745 -0
- package/dist/launch-YrbqaIFj.mjs +1530 -0
- package/dist/{launch-verify-hskNcWkZ.mjs → launch-verify-BzRdbuO1.mjs} +26 -7
- package/dist/{logs-1Ylc1Ri6.mjs → logs-DHaRNfg7.mjs} +11 -11
- package/dist/macos-C0iljhsN.mjs +2 -0
- package/dist/{macos-DF6C7wUU.mjs → macos-V_3Ui7g4.mjs} +125 -155
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +13 -10
- package/dist/{metro-Dh8T4Ytd.mjs → metro-D_j9sN-B.mjs} +209 -43
- package/dist/{metro-gateway-CEUw9RMH.mjs → metro-gateway-BBJldOdi.mjs} +2 -2
- package/dist/miss-reason-BPAzZS0r.mjs +238 -0
- package/dist/{named-ports-BFIz1Shz.mjs → named-ports-C2lvoPsb.mjs} +12 -5
- package/dist/native-android-lHzaew7r.mjs +226 -0
- package/dist/native-gradle-inputs-BQnIdAlL.mjs +356 -0
- package/dist/{native-runtime-D_603JiC.mjs → native-runtime-BRmWL7ru.mjs} +9 -8
- package/dist/native-xcode-inputs-eutS19jU.mjs +307 -0
- package/dist/native-xcode-ios-DP3cHLwu.mjs +434 -0
- package/dist/{ndjson-LGZAMsqa.mjs → ndjson-GOnbyvso.mjs} +6 -6
- package/dist/offload-worker.d.mts +12 -6
- package/dist/offload-worker.mjs +409 -73
- package/dist/{ownership-D6Se7gg_.mjs → ownership-DXzMMSx6.mjs} +2 -2
- package/dist/{placement-log-BcPhRwR4.mjs → placement-log-reFbjqEr.mjs} +7 -3
- package/dist/plan-BDk2AeY_.mjs +260 -0
- package/dist/plan-placement-D_YYlE6N.mjs +73 -0
- package/dist/{ports-BLTtfBq-.mjs → ports-jzvAJXXL.mjs} +3 -3
- package/dist/{prebuild-juCyreaR.mjs → prebuild-Bw44QxVh.mjs} +4 -4
- package/dist/{preview-D5V07Nrl.mjs → preview-BaBJ72Al.mjs} +51 -34
- package/dist/project-B8_duAzW.mjs +1067 -0
- package/dist/project-plan-BPwbLwQu.mjs +10 -0
- package/dist/{pull-request-u4vp7zmK.mjs → pull-request-vOhLNmIb.mjs} +1 -1
- package/dist/pull-requests.mjs +1 -1
- package/dist/react-native-android-chm1DMlA.mjs +921 -0
- package/dist/react-native-build-oAw6gQeW.mjs +239 -0
- package/dist/react-native-doctor-DYXoh-6I.mjs +78 -0
- package/dist/react-native-ios-SCTK_CT5.mjs +595 -0
- package/dist/{recordings-BAWltsVt.mjs → recordings-Bk-VivUV.mjs} +1 -1
- package/dist/{reload-DvyWzVjJ.mjs → reload-D34GkY78.mjs} +17 -14
- package/dist/remote-BU9UyhCJ.mjs +192 -0
- package/dist/{remote-cache-BGg7aGIZ.mjs → remote-cache-Bsts6f6Y.mjs} +5 -5
- package/dist/result-BDoRk1k3.mjs +186 -0
- package/dist/{run-vhtDgpHO.mjs → run-qvff78hv.mjs} +3 -3
- package/dist/{server-bare-B9E7S1aR.mjs → server-bare-dWjAarki.mjs} +6 -6
- package/dist/server-command-7XIKlWtO.mjs +69 -0
- package/dist/{server-expo-DoBHhuzK.mjs → server-expo-CsYu2aKL.mjs} +107 -82
- package/dist/server-expo-DV43vep4.mjs +2 -0
- package/dist/settings-Bbztm4oV.mjs +1503 -0
- package/dist/{settings-Byp2AQ_E.mjs → settings-CT3E71-i.mjs} +6 -7
- package/dist/{state-lKh8shBp.d.mts → settings-vk3mJGSm.d.mts} +4 -2
- package/dist/settings.schema.json +156 -6
- package/dist/simslim-ChMfe8rg.mjs +149 -0
- package/dist/{slot-launch-C1nqh4mu.mjs → slot-launch-B9hn96wd.mjs} +6 -6
- package/dist/{stage-g_WqWeaE.mjs → stage-BNKKdDNc.mjs} +6 -3
- package/dist/start-CbQCSnXQ.mjs +2 -0
- package/dist/{start-D-IeOyoK.mjs → start-CdvcTaXr.mjs} +113 -77
- package/dist/{state-xnqpx3AD.mjs → state-Boo0IMJq.mjs} +4 -2
- package/dist/{state-BG-aAk4k.mjs → state-DI84A-uu.mjs} +29 -10
- package/dist/{stats-DY6ekz8F.mjs → stats-BIIDrjA8.mjs} +6 -6
- package/dist/{status-BEeL6IKz.mjs → status-BDGHwkCs.mjs} +3 -1
- package/dist/{status-DCjZeE-K.mjs → status-DARMkc9q.mjs} +80 -294
- package/dist/status-watch-DvmI3SmN.mjs +296 -0
- package/dist/{stim-desktop-Behws_fi.mjs → stim-desktop-8GQX2OV8.mjs} +1 -1
- package/dist/{stop-DIJtD2GL.mjs → stop-CCZS-C9m.mjs} +2 -2
- package/dist/stop-WQPQHLuy.mjs +72 -0
- package/dist/{stop-BTjs3xbc.mjs → stop-iNemHsJC.mjs} +81 -33
- package/dist/supervisor-run.d.mts +7 -2
- package/dist/supervisor-run.mjs +32 -20
- package/dist/{support-Bwvbrq5-.mjs → support-CnE_SIjt.mjs} +17 -7
- package/dist/{support-BaayeYCf.mjs → support-DCco5fut.mjs} +61 -8
- package/dist/swiftpm-macos-afeNUExW.mjs +119 -0
- package/dist/{native-run-B06FkmZx.mjs → tailnet-CoJUb2tB.mjs} +113 -6
- package/dist/toolchain-BIupIro1.mjs +2 -0
- package/dist/{toolchain-Bnyd_K3A.mjs → toolchain-DqyDXs30.mjs} +225 -315
- package/dist/{trigger-CJMhwXe8.mjs → trigger-C0MWBi8O.mjs} +3 -3
- package/dist/trigger-SHLOWJ4O.mjs +2 -0
- package/dist/{warm-progress-CjB-MP6H.mjs → warm-progress-C3ASD6z5.mjs} +134 -37
- package/dist/{status-Dcr0Qexd.mjs → watchman-CQl51YZu.mjs} +75 -7
- package/dist/web-B3eldHFH.mjs +123 -0
- package/dist/web-BLXpOe6b.mjs +2 -0
- package/dist/web-run.mjs +10 -10
- package/dist/{workspace-state-C59dqG-Z.mjs → workspace-state-CSIFuuDa.mjs} +33 -33
- package/dist/{workspaces-xXItD8Dj.mjs → workspaces-D2xSHBDY.mjs} +1297 -1211
- package/dist/{worktree-BSYlofkq.mjs → worktree-BxDqaTev.mjs} +102 -63
- package/dist/worktree-q7_OZNY0.mjs +2 -0
- package/package.json +8 -6
- package/shim/bundle-response.cjs +2 -1
- package/shim/bundle-response.d.cts +1 -1
- package/shim/expo-metro-config.cjs +1 -1
- package/shim/native-android.gradle +101 -0
- package/dist/android-BKA16DTf.mjs +0 -4
- package/dist/android-BvwuMUJ9.mjs +0 -3572
- package/dist/guide-status-Bhf9SJXc.mjs +0 -125
- package/dist/ios-CPdkoKaa.mjs +0 -3953
- package/dist/ios-DNpdygiv.mjs +0 -7
- package/dist/macos-Ck7OBMNY.mjs +0 -2
- package/dist/metro-store-BAHFcJm6.mjs +0 -106
- package/dist/plan-placement-CtxkCO54.mjs +0 -1859
- package/dist/project-C3ChRLZy.mjs +0 -212
- package/dist/projects-DD7dBTCj.mjs +0 -92
- package/dist/server-expo-Db9HBUoa.mjs +0 -2
- package/dist/settings-CQyMElEP.mjs +0 -701
- package/dist/start-NTc1Ifqs.mjs +0 -2
- package/dist/stop-BGhKMOuH.mjs +0 -48
- package/dist/trigger-DWAq9hkw.mjs +0 -2
- package/dist/web-B6_bFDn7.mjs +0 -2
- package/dist/worktree-BJfnU6r5.mjs +0 -2
- package/dist/worktree-CsKYexJM.mjs +0 -753
|
@@ -1,12 +1,198 @@
|
|
|
1
1
|
import { t as process_identity_exports } from "./process-identity-Biv3arCO.mjs";
|
|
2
|
-
import { t as getExecutor } from "./exec-
|
|
3
|
-
import { M as isOnMountedVolume, N as listMountedVolumes, _ as loadConfig, n as allMetroPorts, r as claimMetroPort, x as releaseMetroPort } from "./config-
|
|
4
|
-
import { r as readWorkspaceState } from "./workspace-state-
|
|
2
|
+
import { t as getExecutor } from "./exec-B81Qodjn.mjs";
|
|
3
|
+
import { M as isOnMountedVolume, N as listMountedVolumes, _ as loadConfig, n as allMetroPorts, r as claimMetroPort, x as releaseMetroPort } from "./config-D0LhTY3S.mjs";
|
|
4
|
+
import { r as readWorkspaceState } from "./workspace-state-CSIFuuDa.mjs";
|
|
5
5
|
import { sep } from "path";
|
|
6
6
|
import { existsSync, readlinkSync, realpathSync } from "fs";
|
|
7
|
+
import { readFile } from "node:fs/promises";
|
|
7
8
|
import { request } from "http";
|
|
8
|
-
import { connect } from "net";
|
|
9
|
+
import { connect } from "node:net";
|
|
10
|
+
//#region src/listening-ports.ts
|
|
11
|
+
/**
|
|
12
|
+
* Returns occupied TCP ports across local interfaces. Rejects if listener inspection fails.
|
|
13
|
+
*/
|
|
14
|
+
async function readListeningPorts(platform = process.platform) {
|
|
15
|
+
switch (platform) {
|
|
16
|
+
case "darwin": return parseDarwinPorts(await readNetstat("/usr/sbin/netstat", [
|
|
17
|
+
"-anL",
|
|
18
|
+
"-p",
|
|
19
|
+
"tcp"
|
|
20
|
+
]));
|
|
21
|
+
case "linux": return parseLinuxPorts(await Promise.all([readFile("/proc/net/tcp", "utf8"), readFile("/proc/net/tcp6", "utf8").catch((error) => {
|
|
22
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
|
|
23
|
+
throw error;
|
|
24
|
+
})]));
|
|
25
|
+
case "win32": return parseWindowsPorts(await readNetstat("netstat", ["-an"]));
|
|
26
|
+
default: throw new Error(`TCP listener inspection is not supported on ${platform}.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const DARWIN_TITLE = "Current listen queue sizes (qlen/incqlen/maxqlen)";
|
|
30
|
+
const DARWIN_COLUMNS = /^Listen\s+Local Address$/;
|
|
31
|
+
const DARWIN_TABLE_CHANGE = /^Some tcp sockets may have been (?:created|deleted|created or deleted)\.?$/;
|
|
32
|
+
const DARWIN_LISTENER = /^\d+\/\d+\/\d+\s+\S+\.(?<port>\d+)$/;
|
|
33
|
+
function parseDarwinPorts(output) {
|
|
34
|
+
const ports = /* @__PURE__ */ new Set();
|
|
35
|
+
let title = false;
|
|
36
|
+
let columns = false;
|
|
37
|
+
for (const raw of output.split("\n")) {
|
|
38
|
+
const line = raw.trim();
|
|
39
|
+
if (line === DARWIN_TITLE) title = true;
|
|
40
|
+
else if (DARWIN_COLUMNS.test(line)) columns = true;
|
|
41
|
+
if (!line || line === DARWIN_TITLE || DARWIN_COLUMNS.test(line) || DARWIN_TABLE_CHANGE.test(line)) continue;
|
|
42
|
+
const listener = DARWIN_LISTENER.exec(line)?.groups;
|
|
43
|
+
if (!listener) throw new Error("Cannot parse the TCP listen table from netstat.");
|
|
44
|
+
addPort(ports, Number(listener.port));
|
|
45
|
+
}
|
|
46
|
+
if (!title || !columns) throw new Error("netstat printed no TCP listen table.");
|
|
47
|
+
return ports;
|
|
48
|
+
}
|
|
49
|
+
const LINUX_COLUMNS = /^\s*sl\s+local_address\s+rem(?:ote)?_address\s+st\s/;
|
|
50
|
+
const LINUX_TCP_STATE = /^[0-9A-F]{2}$/i;
|
|
51
|
+
const LINUX_LOCAL_ADDRESS = /^(?:[0-9A-F]{8}|[0-9A-F]{32}):(?<port>[0-9A-F]{4})$/i;
|
|
52
|
+
const LINUX_LISTEN_STATE = "0A";
|
|
53
|
+
function parseLinuxPorts(tables) {
|
|
54
|
+
const ports = /* @__PURE__ */ new Set();
|
|
55
|
+
for (const table of tables) {
|
|
56
|
+
if (table === null) continue;
|
|
57
|
+
const [header, ...rows] = table.trim().split("\n");
|
|
58
|
+
if (!header || !LINUX_COLUMNS.test(header)) throw new Error("Cannot parse the TCP socket table from /proc/net.");
|
|
59
|
+
for (const raw of rows) {
|
|
60
|
+
const line = raw.trim();
|
|
61
|
+
if (!line) continue;
|
|
62
|
+
const [, localAddress, , state] = line.split(/\s+/);
|
|
63
|
+
if (!state || !LINUX_TCP_STATE.test(state)) throw new Error("Invalid TCP state in /proc/net.");
|
|
64
|
+
if (state.toUpperCase() !== LINUX_LISTEN_STATE) continue;
|
|
65
|
+
const listener = localAddress && LINUX_LOCAL_ADDRESS.exec(localAddress)?.groups;
|
|
66
|
+
if (!listener) throw new Error("Invalid TCP listener in /proc/net.");
|
|
67
|
+
addPort(ports, Number(`0x${listener.port}`));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return ports;
|
|
71
|
+
}
|
|
72
|
+
const WINDOWS_COLUMNS = /^Proto\s/;
|
|
73
|
+
const WINDOWS_TCP_ROW = /^TCP\s+\S*:(?<localPort>\d+)\s+\S*:(?<remotePort>\d+)\s+\S/;
|
|
74
|
+
function parseWindowsPorts(output) {
|
|
75
|
+
const ports = /* @__PURE__ */ new Set();
|
|
76
|
+
let table = false;
|
|
77
|
+
for (const raw of output.split("\n")) {
|
|
78
|
+
const line = raw.trim();
|
|
79
|
+
if (WINDOWS_COLUMNS.test(line)) table = true;
|
|
80
|
+
const [protocol] = line.split(/\s+/, 1);
|
|
81
|
+
if (protocol !== "TCP") continue;
|
|
82
|
+
table = true;
|
|
83
|
+
const connection = WINDOWS_TCP_ROW.exec(line)?.groups;
|
|
84
|
+
if (!connection) throw new Error("Cannot parse the TCP connection table from netstat.");
|
|
85
|
+
if (Number(connection.remotePort) === 0) addPort(ports, Number(connection.localPort));
|
|
86
|
+
}
|
|
87
|
+
if (!table) throw new Error("netstat printed no TCP connection table.");
|
|
88
|
+
return ports;
|
|
89
|
+
}
|
|
90
|
+
function readNetstat(file, args) {
|
|
91
|
+
return getExecutor().runFileAsync(file, args, {
|
|
92
|
+
timeoutMs: 5e3,
|
|
93
|
+
rejectStderr: true,
|
|
94
|
+
env: { LC_ALL: "C" }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function addPort(ports, port) {
|
|
98
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid TCP listener port.");
|
|
99
|
+
ports.add(port);
|
|
100
|
+
}
|
|
101
|
+
function addressPort(address) {
|
|
102
|
+
const colon = String(address ?? "").lastIndexOf(":");
|
|
103
|
+
return colon < 0 ? NaN : Number(String(address).slice(colon + 1));
|
|
104
|
+
}
|
|
105
|
+
function parseLsofListeners(out) {
|
|
106
|
+
const byPort = /* @__PURE__ */ new Map();
|
|
107
|
+
let pid = null;
|
|
108
|
+
for (const line of String(out ?? "").split("\n")) if (line.startsWith("p")) pid = parseInt(line.slice(1), 10);
|
|
109
|
+
else if (line.startsWith("n") && pid !== null && Number.isFinite(pid)) {
|
|
110
|
+
const port = addressPort(line.slice(1));
|
|
111
|
+
const pids = byPort.get(port) ?? [];
|
|
112
|
+
if (!pids.includes(pid)) pids.push(pid);
|
|
113
|
+
byPort.set(port, pids);
|
|
114
|
+
}
|
|
115
|
+
return byPort;
|
|
116
|
+
}
|
|
117
|
+
const PORT_INSPECTION_REMEDY = "Allow Stim to run netstat or lsof, or to connect to 127.0.0.1 and ::1, then retry. A metro.port pin skips the scan for Metro.";
|
|
118
|
+
var PortInspectionError = class extends Error {
|
|
119
|
+
code = "STIM_PORT_INSPECTION_FAILED";
|
|
120
|
+
reason;
|
|
121
|
+
constructor(reason) {
|
|
122
|
+
super(`${reason} ${PORT_INSPECTION_REMEDY}`);
|
|
123
|
+
this.reason = reason;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Returns the TCP ports lsof lists as listening, or null when lsof cannot list them.
|
|
128
|
+
*/
|
|
129
|
+
async function readLsofListeningPorts() {
|
|
130
|
+
try {
|
|
131
|
+
const out = await getExecutor().runFileAsync("lsof", [
|
|
132
|
+
"-nP",
|
|
133
|
+
"-iTCP",
|
|
134
|
+
"-sTCP:LISTEN",
|
|
135
|
+
"-Fpn"
|
|
136
|
+
], { timeoutMs: 5e3 });
|
|
137
|
+
return new Set([...parseLsofListeners(out).keys()].filter(Number.isInteger));
|
|
138
|
+
} catch (error) {
|
|
139
|
+
const result = error;
|
|
140
|
+
if (result.status === 1 && !String(result.stdout ?? "").trim() && !String(result.stderr ?? "").trim()) return /* @__PURE__ */ new Set();
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const IPV6_UNAVAILABLE = /* @__PURE__ */ new Set([
|
|
145
|
+
"EADDRNOTAVAIL",
|
|
146
|
+
"EAFNOSUPPORT",
|
|
147
|
+
"ENETUNREACH"
|
|
148
|
+
]);
|
|
149
|
+
/**
|
|
150
|
+
* Connects to a loopback port: `taken` when something accepts or the connect hangs, `free` when
|
|
151
|
+
* it is refused or IPv6 is unavailable, `unknown` for any other connect error.
|
|
152
|
+
*/
|
|
153
|
+
function probeLoopback(port, host, timeoutMs = 400) {
|
|
154
|
+
return new Promise((resolve) => {
|
|
155
|
+
const socket = connect({
|
|
156
|
+
port,
|
|
157
|
+
host
|
|
158
|
+
});
|
|
159
|
+
const done = (answer) => {
|
|
160
|
+
socket.removeAllListeners();
|
|
161
|
+
socket.destroy();
|
|
162
|
+
resolve(answer);
|
|
163
|
+
};
|
|
164
|
+
socket.setTimeout(timeoutMs);
|
|
165
|
+
socket.once("connect", () => done("taken"));
|
|
166
|
+
socket.once("timeout", () => done("taken"));
|
|
167
|
+
socket.once("error", (error) => {
|
|
168
|
+
const refused = error.code === "ECONNREFUSED" || host === "::1" && IPV6_UNAVAILABLE.has(error.code ?? "");
|
|
169
|
+
done(refused ? "free" : "unknown");
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
9
174
|
//#region src/ports.ts
|
|
175
|
+
/**
|
|
176
|
+
* Creates one lazy listener snapshot for an allocation attempt; discard the probe before retrying.
|
|
177
|
+
* When the native TCP table cannot be read, each port is checked with an lsof listener scan and
|
|
178
|
+
* loopback connects instead. Rejects with `PortInspectionError` only when none of them can answer.
|
|
179
|
+
*/
|
|
180
|
+
function createPortProbe() {
|
|
181
|
+
let snapshot;
|
|
182
|
+
let lsof;
|
|
183
|
+
return async (port) => {
|
|
184
|
+
const listening = await (snapshot ??= readListeningPorts().catch((error) => error instanceof Error ? error : new Error(String(error))));
|
|
185
|
+
if (!(listening instanceof Error)) return !listening.has(port);
|
|
186
|
+
const [listed, ipv4, ipv6] = await Promise.all([
|
|
187
|
+
lsof ??= readLsofListeningPorts(),
|
|
188
|
+
probeLoopback(port, "127.0.0.1"),
|
|
189
|
+
probeLoopback(port, "::1")
|
|
190
|
+
]);
|
|
191
|
+
if (listed?.has(port) || ipv4 === "taken" || ipv6 === "taken") return false;
|
|
192
|
+
if (listed || ipv4 === "free" && ipv6 === "free") return true;
|
|
193
|
+
throw new PortInspectionError(`Cannot tell whether TCP port ${port} is free: the TCP listener table failed (${listening.message.replace(/\s+/g, " ").trim()}), lsof could not list listeners, and a loopback connect failed.`);
|
|
194
|
+
};
|
|
195
|
+
}
|
|
10
196
|
function isMetroRunning(port) {
|
|
11
197
|
return new Promise((resolve) => {
|
|
12
198
|
const req = request({
|
|
@@ -29,25 +215,8 @@ function isMetroRunning(port) {
|
|
|
29
215
|
req.end();
|
|
30
216
|
});
|
|
31
217
|
}
|
|
32
|
-
function isPortFree(port, { timeoutMs = 400 } = {}) {
|
|
33
|
-
return new Promise((resolve) => {
|
|
34
|
-
const sock = connect({
|
|
35
|
-
port,
|
|
36
|
-
host: "127.0.0.1"
|
|
37
|
-
});
|
|
38
|
-
const done = (free) => {
|
|
39
|
-
sock.removeAllListeners();
|
|
40
|
-
sock.destroy();
|
|
41
|
-
resolve(free);
|
|
42
|
-
};
|
|
43
|
-
sock.setTimeout(timeoutMs);
|
|
44
|
-
sock.once("connect", () => done(false));
|
|
45
|
-
sock.once("error", () => done(true));
|
|
46
|
-
sock.once("timeout", () => done(false));
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
218
|
const FIRST_PORT = 8082;
|
|
50
|
-
async function computeNextPort(isFree =
|
|
219
|
+
async function computeNextPort(isFree = createPortProbe()) {
|
|
51
220
|
const taken = new Set(allMetroPorts());
|
|
52
221
|
for (let port = FIRST_PORT; port < 8282; port++) {
|
|
53
222
|
if (taken.has(port)) continue;
|
|
@@ -73,7 +242,7 @@ async function findReclaimablePort(excludeProjectPath, probe = isMetroRunning, {
|
|
|
73
242
|
for (const c of candidates) if (!await probe(c.port)) return c;
|
|
74
243
|
return null;
|
|
75
244
|
}
|
|
76
|
-
async function allocatePort(projectPath, probe = isMetroRunning, isFree =
|
|
245
|
+
async function allocatePort(projectPath, probe = isMetroRunning, isFree = createPortProbe()) {
|
|
77
246
|
const reclaim = await findReclaimablePort(projectPath, probe);
|
|
78
247
|
if (reclaim && await isFree(reclaim.port)) {
|
|
79
248
|
releaseMetroPort(reclaim.ownerPath, reclaim.port);
|
|
@@ -82,7 +251,7 @@ async function allocatePort(projectPath, probe = isMetroRunning, isFree = isPort
|
|
|
82
251
|
return computeNextPort(isFree);
|
|
83
252
|
}
|
|
84
253
|
const RESERVE_ATTEMPTS = 5;
|
|
85
|
-
async function reserveMetroPort(projectPath, probe = isMetroRunning, isFree
|
|
254
|
+
async function reserveMetroPort(projectPath, probe = isMetroRunning, isFree, pinned = null) {
|
|
86
255
|
if (pinned !== null) {
|
|
87
256
|
if (claimMetroPort(projectPath, pinned) !== null) return pinned;
|
|
88
257
|
throw new Error(`metro.port ${pinned} is already reserved by another workspace's Metro or named port.`);
|
|
@@ -116,10 +285,6 @@ function parseLsofPids(out) {
|
|
|
116
285
|
if (!out) return [];
|
|
117
286
|
return String(out).split("\n").map((s) => parseInt(s.trim(), 10)).filter((n) => Number.isFinite(n));
|
|
118
287
|
}
|
|
119
|
-
function addressPort(address) {
|
|
120
|
-
const colon = String(address ?? "").lastIndexOf(":");
|
|
121
|
-
return colon < 0 ? NaN : Number(String(address).slice(colon + 1));
|
|
122
|
-
}
|
|
123
288
|
function parseNetstatPids(out, port) {
|
|
124
289
|
const pids = [];
|
|
125
290
|
for (const line of String(out ?? "").split("\n")) {
|
|
@@ -132,7 +297,12 @@ function parseNetstatPids(out, port) {
|
|
|
132
297
|
return pids;
|
|
133
298
|
}
|
|
134
299
|
function listeningPids(port, platform = process.platform) {
|
|
135
|
-
const pids = parseLsofPids(getExecutor().
|
|
300
|
+
const pids = parseLsofPids(getExecutor().runFileQuiet("lsof", [
|
|
301
|
+
"-nP",
|
|
302
|
+
`-iTCP:${port}`,
|
|
303
|
+
"-sTCP:LISTEN",
|
|
304
|
+
"-t"
|
|
305
|
+
]));
|
|
136
306
|
if (pids.length > 0 || platform !== "win32") return pids;
|
|
137
307
|
return parseNetstatPids(getExecutor().runQuiet("netstat -ano"), port);
|
|
138
308
|
}
|
|
@@ -147,18 +317,6 @@ function parseLsofCwd(out) {
|
|
|
147
317
|
function lsofOutput(args) {
|
|
148
318
|
return getExecutor().runFileAsync("lsof", args).catch((error) => typeof error?.stdout === "string" ? error.stdout : null);
|
|
149
319
|
}
|
|
150
|
-
function parseLsofListeners(out) {
|
|
151
|
-
const byPort = /* @__PURE__ */ new Map();
|
|
152
|
-
let pid = null;
|
|
153
|
-
for (const line of String(out ?? "").split("\n")) if (line.startsWith("p")) pid = parseInt(line.slice(1), 10);
|
|
154
|
-
else if (line.startsWith("n") && pid !== null && Number.isFinite(pid)) {
|
|
155
|
-
const port = addressPort(line.slice(1));
|
|
156
|
-
const pids = byPort.get(port) ?? [];
|
|
157
|
-
if (!pids.includes(pid)) pids.push(pid);
|
|
158
|
-
byPort.set(port, pids);
|
|
159
|
-
}
|
|
160
|
-
return byPort;
|
|
161
|
-
}
|
|
162
320
|
/**
|
|
163
321
|
* `listeningPids` for several ports with one lsof call. A port lsof could not be asked about is
|
|
164
322
|
* missing from the map.
|
|
@@ -218,7 +376,14 @@ function processCwd(pid) {
|
|
|
218
376
|
if (process.platform === "linux") try {
|
|
219
377
|
return readlinkSync(`/proc/${pid}/cwd`);
|
|
220
378
|
} catch {}
|
|
221
|
-
return parseLsofCwd(getExecutor().
|
|
379
|
+
return parseLsofCwd(getExecutor().runFileQuiet("lsof", [
|
|
380
|
+
"-a",
|
|
381
|
+
"-p",
|
|
382
|
+
String(pid),
|
|
383
|
+
"-d",
|
|
384
|
+
"cwd",
|
|
385
|
+
"-Fn"
|
|
386
|
+
]));
|
|
222
387
|
}
|
|
223
388
|
function canonicalPath(path) {
|
|
224
389
|
try {
|
|
@@ -286,6 +451,7 @@ async function resolveProjectMetro(port, projectPath, { probe = isMetroRunning,
|
|
|
286
451
|
* always forceful.
|
|
287
452
|
*/
|
|
288
453
|
function signalProcessTree(pid, signal = "SIGTERM", { group = false, platform = process.platform } = {}) {
|
|
454
|
+
if (!Number.isSafeInteger(pid) || pid <= 1) throw new Error(`Refusing to signal pid ${pid}.`);
|
|
289
455
|
if (platform !== "win32") return process.kill(group ? -pid : pid, signal);
|
|
290
456
|
return getExecutor().runFileQuiet("taskkill", [
|
|
291
457
|
"/PID",
|
|
@@ -306,4 +472,4 @@ function killMetroTree(leader, processToken) {
|
|
|
306
472
|
}
|
|
307
473
|
}
|
|
308
474
|
//#endregion
|
|
309
|
-
export { listeningPidsByPort as a,
|
|
475
|
+
export { listeningPidsByPort as a, processCwd as c, signalProcessTree as d, createPortProbe as f, PortInspectionError as g, PORT_INSPECTION_REMEDY as h, listeningPids as i, processCwds as l, reserveMetroPort as m, isInsideProject as n, parseNetstatPids as o, isMetroRunning as p, killMetroTree as r, pidExists as s, NOT_OURS_FOREIGN_CWD as t, resolveProjectMetro as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as process_identity_exports } from "./process-identity-Biv3arCO.mjs";
|
|
2
|
-
import { a as updateWorkspaceState, r as readWorkspaceState$1 } from "./workspace-state-
|
|
3
|
-
import {
|
|
2
|
+
import { a as updateWorkspaceState, r as readWorkspaceState$1 } from "./workspace-state-CSIFuuDa.mjs";
|
|
3
|
+
import { l as realIo } from "./tailnet-CoJUb2tB.mjs";
|
|
4
4
|
import { HOSTED_METRO_REQUESTS_KEY, findPeer, hostedMetroGateways, hostedMetroRequests, isJsonObject, parseMachine } from "@stim-cli/core/state";
|
|
5
5
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
6
6
|
import { isIP } from "node:net";
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { ht as gitCommonDirOnDisk } from "./settings-Bbztm4oV.mjs";
|
|
2
|
+
import { C as diffFingerprintSources, I as storedSources } from "./device-lease-DHOBXGgS.mjs";
|
|
3
|
+
import { m as sharedBuildCache } from "./workspace-state-CSIFuuDa.mjs";
|
|
4
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
5
|
+
import { dirname, join, relative } from "node:path";
|
|
6
|
+
import { LAST_BUILD_KEYS, loadConfig, readWorkspaceState } from "@stim-cli/core/state";
|
|
7
|
+
import * as expoFingerprint from "@expo/fingerprint";
|
|
8
|
+
//#region src/cache/miss-reason.ts
|
|
9
|
+
const MISS_CHANGE_CAP = 20;
|
|
10
|
+
function recordedBuilds(state, platform) {
|
|
11
|
+
const builds = [];
|
|
12
|
+
for (const value of [state?.[LAST_BUILD_KEYS[platform]], state?.lastBuild]) {
|
|
13
|
+
const record = value;
|
|
14
|
+
if (record?.platform !== platform) continue;
|
|
15
|
+
const startedAt = typeof record.startedAt === "string" ? record.startedAt : "";
|
|
16
|
+
if (typeof record.fingerprint === "string" && typeof record.cacheKey === "string") builds.push({
|
|
17
|
+
fingerprint: record.fingerprint,
|
|
18
|
+
cacheKey: record.cacheKey,
|
|
19
|
+
startedAt
|
|
20
|
+
});
|
|
21
|
+
const carried = record.missReason?.baseline;
|
|
22
|
+
if (typeof carried?.fingerprint === "string" && typeof carried.cacheKey === "string") builds.push({
|
|
23
|
+
fingerprint: carried.fingerprint,
|
|
24
|
+
cacheKey: carried.cacheKey,
|
|
25
|
+
startedAt
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return builds;
|
|
29
|
+
}
|
|
30
|
+
function projectIdentity(root) {
|
|
31
|
+
let real;
|
|
32
|
+
try {
|
|
33
|
+
real = realpathSync.native(root);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
for (let dir = real;; dir = dirname(dir)) {
|
|
38
|
+
if (existsSync(join(dir, ".git"))) {
|
|
39
|
+
const common = gitCommonDirOnDisk(dir);
|
|
40
|
+
return common ? `${common}\n${relative(dir, real)}` : null;
|
|
41
|
+
}
|
|
42
|
+
if (dirname(dir) === dir) return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function findMissBaseline(root, platform, { readState = readWorkspaceState, projectRoots = () => Object.keys(loadConfig()?.projects ?? {}), identity = projectIdentity, sourcesOf = (p, key) => storedSources(p, key, sharedBuildCache()) } = {}) {
|
|
46
|
+
for (const build of recordedBuilds(readState(root), platform)) {
|
|
47
|
+
const sources = sourcesOf(platform, build.cacheKey);
|
|
48
|
+
if (sources) return {
|
|
49
|
+
fingerprint: build.fingerprint,
|
|
50
|
+
cacheKey: build.cacheKey,
|
|
51
|
+
sources,
|
|
52
|
+
from: "workspace"
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const project = identity(root);
|
|
56
|
+
if (!project) return null;
|
|
57
|
+
const others = [];
|
|
58
|
+
for (const other of projectRoots()) {
|
|
59
|
+
if (other === root || identity(other) !== project) continue;
|
|
60
|
+
others.push(...recordedBuilds(readState(other), platform));
|
|
61
|
+
}
|
|
62
|
+
for (const build of others.toSorted((a, b) => (Date.parse(b.startedAt) || 0) - (Date.parse(a.startedAt) || 0))) {
|
|
63
|
+
const sources = sourcesOf(platform, build.cacheKey);
|
|
64
|
+
if (sources) return {
|
|
65
|
+
fingerprint: build.fingerprint,
|
|
66
|
+
cacheKey: build.cacheKey,
|
|
67
|
+
sources,
|
|
68
|
+
from: "project"
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const CATEGORY_RANK = {
|
|
74
|
+
"native-dependency": 0,
|
|
75
|
+
"app-config": 1,
|
|
76
|
+
"config-plugin": 2,
|
|
77
|
+
package: 3,
|
|
78
|
+
"native-dir": 4,
|
|
79
|
+
file: 5,
|
|
80
|
+
"app-asset": 6,
|
|
81
|
+
other: 7,
|
|
82
|
+
"package-scripts": 8,
|
|
83
|
+
autolinking: 9
|
|
84
|
+
};
|
|
85
|
+
function packageIn(path) {
|
|
86
|
+
return [...path.matchAll(/(?:^|\/)node_modules\/((?:@[^/]+\/)?[^/]+)/g)].at(-1)?.[1] ?? null;
|
|
87
|
+
}
|
|
88
|
+
function describeChange({ name, change, reasons }) {
|
|
89
|
+
const pkg = packageIn(name);
|
|
90
|
+
if (name === "expoConfig" || reasons.includes("expoConfig")) return {
|
|
91
|
+
category: "app-config",
|
|
92
|
+
label: "app config changed"
|
|
93
|
+
};
|
|
94
|
+
if (pkg && reasons.some((reason) => /^(expo|rncore)Autolinking(Ios|Android)?$/.test(reason))) return {
|
|
95
|
+
category: "native-dependency",
|
|
96
|
+
label: `native dependency ${change}: ${pkg}`
|
|
97
|
+
};
|
|
98
|
+
if (pkg && reasons.includes("expoConfigPlugins")) return {
|
|
99
|
+
category: "config-plugin",
|
|
100
|
+
label: `config plugin ${change}: ${pkg}`
|
|
101
|
+
};
|
|
102
|
+
if (/^(expoAutolinkingConfig|rncoreAutolinkingConfig)(:|$)/.test(name)) return {
|
|
103
|
+
category: "autolinking",
|
|
104
|
+
label: "autolinking config changed"
|
|
105
|
+
};
|
|
106
|
+
if (name.startsWith("package:")) return {
|
|
107
|
+
category: "package",
|
|
108
|
+
label: `${name.slice(8)} ${change}`
|
|
109
|
+
};
|
|
110
|
+
if (name === "packageJson:scripts") return {
|
|
111
|
+
category: "package-scripts",
|
|
112
|
+
label: "package.json scripts changed"
|
|
113
|
+
};
|
|
114
|
+
if (reasons.includes("expoConfigExternalFile")) return {
|
|
115
|
+
category: "app-asset",
|
|
116
|
+
label: `app asset ${change}: ${name}`
|
|
117
|
+
};
|
|
118
|
+
if (reasons.includes("bareNativeDir")) return {
|
|
119
|
+
category: "native-dir",
|
|
120
|
+
label: `${name}/ ${change}`
|
|
121
|
+
};
|
|
122
|
+
if (reasons.length || name.includes("/") || name.includes(".")) return {
|
|
123
|
+
category: "file",
|
|
124
|
+
label: `${name} ${change}`
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
category: "other",
|
|
128
|
+
label: `${name} ${change}`
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function rekeyPrefix(rekeyedBy) {
|
|
132
|
+
return rekeyedBy.length ? `${rekeyedBy.join(" and ")} changed native inputs; ` : "";
|
|
133
|
+
}
|
|
134
|
+
function missReasonFromChanges({ changes, baseline, rekeyedBy = [] }) {
|
|
135
|
+
const prefix = rekeyPrefix(rekeyedBy);
|
|
136
|
+
if (!baseline) return {
|
|
137
|
+
kind: "no-baseline",
|
|
138
|
+
summary: `${prefix}no earlier build of this project in the cache to compare with`,
|
|
139
|
+
changes: [],
|
|
140
|
+
changeCount: 0,
|
|
141
|
+
baseline: null,
|
|
142
|
+
rekeyedBy
|
|
143
|
+
};
|
|
144
|
+
if (!changes.length) return {
|
|
145
|
+
kind: "same-sources",
|
|
146
|
+
summary: `${prefix}native inputs match the last build; no cached app for this configuration or target`,
|
|
147
|
+
changes: [],
|
|
148
|
+
changeCount: 0,
|
|
149
|
+
baseline,
|
|
150
|
+
rekeyedBy
|
|
151
|
+
};
|
|
152
|
+
const described = changes.map((change, index) => ({
|
|
153
|
+
change,
|
|
154
|
+
index,
|
|
155
|
+
...describeChange(change)
|
|
156
|
+
})).toSorted((a, b) => CATEGORY_RANK[a.category] - CATEGORY_RANK[b.category] || a.index - b.index);
|
|
157
|
+
const dependencyMoved = described.some((entry) => entry.category === "native-dependency");
|
|
158
|
+
const labels = [...new Set(described.filter((entry) => !(dependencyMoved && entry.category === "autolinking")).map((entry) => entry.label))];
|
|
159
|
+
const more = labels.length > 1 ? ` (+${labels.length - 1} more)` : "";
|
|
160
|
+
return {
|
|
161
|
+
kind: "changed",
|
|
162
|
+
summary: `${prefix}${labels[0]}${more}`,
|
|
163
|
+
changes: described.slice(0, MISS_CHANGE_CAP).map(({ change, category }) => ({
|
|
164
|
+
source: change.name,
|
|
165
|
+
change: change.change,
|
|
166
|
+
category
|
|
167
|
+
})),
|
|
168
|
+
changeCount: changes.length,
|
|
169
|
+
baseline,
|
|
170
|
+
rekeyedBy
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function explainBuildMiss({ root, platform, current, rekeyedBy = [], baselineDeps, differ = expoFingerprint.diffFingerprints }) {
|
|
174
|
+
const baseline = findMissBaseline(root, platform, baselineDeps);
|
|
175
|
+
const changes = baseline ? diffFingerprintSources({
|
|
176
|
+
previous: baseline.sources,
|
|
177
|
+
previousHash: baseline.fingerprint,
|
|
178
|
+
current,
|
|
179
|
+
differ
|
|
180
|
+
}) : [];
|
|
181
|
+
return {
|
|
182
|
+
reason: missReasonFromChanges({
|
|
183
|
+
changes,
|
|
184
|
+
baseline: baseline ? {
|
|
185
|
+
fingerprint: baseline.fingerprint,
|
|
186
|
+
cacheKey: baseline.cacheKey,
|
|
187
|
+
from: baseline.from
|
|
188
|
+
} : null,
|
|
189
|
+
rekeyedBy
|
|
190
|
+
}),
|
|
191
|
+
changedNames: changes.map((change) => change.name),
|
|
192
|
+
previousHash: baseline?.fingerprint ?? null
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function predictBuildMiss({ root, platform, current, prebuild }) {
|
|
196
|
+
const { reason } = explainBuildMiss({
|
|
197
|
+
root,
|
|
198
|
+
platform,
|
|
199
|
+
current
|
|
200
|
+
});
|
|
201
|
+
const baseline = reason.baseline && {
|
|
202
|
+
fingerprint: reason.baseline.fingerprint,
|
|
203
|
+
from: reason.baseline.from
|
|
204
|
+
};
|
|
205
|
+
if (!prebuild || !baseline) return {
|
|
206
|
+
...reason,
|
|
207
|
+
baseline
|
|
208
|
+
};
|
|
209
|
+
const dir = platform === "ios" ? "ios/" : "android/";
|
|
210
|
+
return {
|
|
211
|
+
...reason,
|
|
212
|
+
kind: "prebuild-pending",
|
|
213
|
+
summary: `${reason.summary} (before prebuild ${prebuild}s ${dir})`,
|
|
214
|
+
baseline
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function skippedMissReason(summary) {
|
|
218
|
+
return {
|
|
219
|
+
kind: "cache-skipped",
|
|
220
|
+
summary,
|
|
221
|
+
changes: [],
|
|
222
|
+
changeCount: 0,
|
|
223
|
+
baseline: null,
|
|
224
|
+
rekeyedBy: []
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function fingerprintErrorMissReason(message) {
|
|
228
|
+
return {
|
|
229
|
+
kind: "fingerprint-error",
|
|
230
|
+
summary: `fingerprinting failed: ${message}`,
|
|
231
|
+
changes: [],
|
|
232
|
+
changeCount: 0,
|
|
233
|
+
baseline: null,
|
|
234
|
+
rekeyedBy: []
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
//#endregion
|
|
238
|
+
export { skippedMissReason as i, fingerprintErrorMissReason as n, predictBuildMiss as r, explainBuildMiss as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-Biv3arCO.mjs";
|
|
2
|
-
import { t as getExecutor } from "./exec-
|
|
3
|
-
import { C as saveConfig, D as withConfigLock, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-
|
|
4
|
-
import {
|
|
2
|
+
import { t as getExecutor } from "./exec-B81Qodjn.mjs";
|
|
3
|
+
import { C as saveConfig, D as withConfigLock, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-D0LhTY3S.mjs";
|
|
4
|
+
import { d as signalProcessTree, f as createPortProbe, o as parseNetstatPids } from "./metro-D_j9sN-B.mjs";
|
|
5
5
|
import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-Kqiifsk2.mjs";
|
|
6
6
|
import { realpathSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
@@ -69,7 +69,14 @@ function validatePortLabel(label) {
|
|
|
69
69
|
if (!/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/.test(label)) throw new Error("A port label must start with a letter and contain at most 64 letters, digits, underscores or hyphens.");
|
|
70
70
|
}
|
|
71
71
|
function portListeners(port, platform) {
|
|
72
|
-
if (platform === "win32")
|
|
72
|
+
if (platform === "win32") {
|
|
73
|
+
const out = getExecutor().runFile("netstat", ["-ano"], {
|
|
74
|
+
timeoutMs: 5e3,
|
|
75
|
+
rejectStderr: true
|
|
76
|
+
});
|
|
77
|
+
if (!/^\s*(?:Proto|TCP)\s/m.test(out)) throw new Error("netstat printed no TCP connection table.");
|
|
78
|
+
return parseNetstatPids(out, port);
|
|
79
|
+
}
|
|
73
80
|
let out;
|
|
74
81
|
try {
|
|
75
82
|
out = getExecutor().runFile("lsof", [
|
|
@@ -126,7 +133,7 @@ function releaseBrowserPort(projectPath, port) {
|
|
|
126
133
|
saveConfig(cfg);
|
|
127
134
|
}));
|
|
128
135
|
}
|
|
129
|
-
async function allocateNamedPort(projectPath, label, { isFree =
|
|
136
|
+
async function allocateNamedPort(projectPath, label, { isFree = createPortProbe() }) {
|
|
130
137
|
const root = realpathSync(projectPath);
|
|
131
138
|
return withPortsLock(async () => {
|
|
132
139
|
const existing = getProject(root)?.ports;
|