stim 1.9.0 → 1.10.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.
Files changed (83) hide show
  1. package/dist/{android-_y4Ohi5z.mjs → android-787HhP5w.mjs} +119 -29
  2. package/dist/{android-BPGizezh.mjs → android-DBkeHwpm.mjs} +168 -95
  3. package/dist/{android-DEgo4oCo.mjs → android-DPov-fv2.mjs} +2 -2
  4. package/dist/{android-cas-eiExNLf7.mjs → android-cas-CITmIeWY.mjs} +9 -8
  5. package/dist/android-cas-compiler.mjs +1 -1
  6. package/dist/{app-install-Uf3a83Tv.mjs → app-install-CrJ6t_bv.mjs} +2 -2
  7. package/dist/budget-BP4jZZL4.mjs +620 -0
  8. package/dist/build-progress-BXx-ZBe4.mjs +512 -0
  9. package/dist/{cache-manifest-Dg7OnMrp.mjs → cache-manifest-Pubfp8wV.mjs} +1 -1
  10. package/dist/cache-manifest.mjs +1 -1
  11. package/dist/cli.mjs +16 -16
  12. package/dist/collector-run.d.mts +5 -1
  13. package/dist/collector-run.mjs +7 -7
  14. package/dist/{command-output-gByVmIjy.mjs → command-output-D5z2_bcF.mjs} +1 -1
  15. package/dist/{config-Cp9lM3wX.mjs → config-BEq0Qw_a.mjs} +14 -131
  16. package/dist/{dependency-state-Bq5DcLGn.mjs → dependency-state-r9UesA9a.mjs} +2 -2
  17. package/dist/{deps-Cip5vUm1.mjs → deps-DP4eWqea.mjs} +3 -3
  18. package/dist/{detached-entry-KEu0_AXL.mjs → detached-entry-DJHoca49.mjs} +1 -1
  19. package/dist/{dev-client-HyqISM0h.mjs → dev-client-92U593KT.mjs} +137 -250
  20. package/dist/{device-D4U-xLty.mjs → device-DhTZe7L4.mjs} +7 -7
  21. package/dist/{build-lock-DPXPLgTc.mjs → device-lease-CbEaIk7b.mjs} +370 -12
  22. package/dist/{device-pool-CnTAz8X1.mjs → device-pool-Di8Q-9Ro.mjs} +4 -4
  23. package/dist/{device-remote-AQ5rQPqr.mjs → device-remote-Dy1jGj3U.mjs} +547 -468
  24. package/dist/{doctor-B_Ei3bZu.mjs → doctor-B-inAJmt.mjs} +58 -22
  25. package/dist/{error-diagnostics-Vfz83GCF.mjs → error-diagnostics-xxWKNO3-.mjs} +11 -12
  26. package/dist/{exec-jIAlgilk.mjs → exec-DK8KaVHK.mjs} +3 -2
  27. package/dist/{gc-Ckw8RQHi.mjs → gc-ChPFZMRC.mjs} +500 -1114
  28. package/dist/{guide-BiAbhs1J.mjs → guide-DwmaD_Wa.mjs} +882 -528
  29. package/dist/guide-status-CWvti2Lg.mjs +125 -0
  30. package/dist/idle-DpRLp5lj.mjs +157 -0
  31. package/dist/in-use-CjUluqIX.mjs +245 -0
  32. package/dist/{ios-BL2NFckr.mjs → ios-B2Fpqvlb.mjs} +25 -59
  33. package/dist/{ios-BzUJWk1K.mjs → ios-Dd-hYJBh.mjs} +130 -89
  34. package/dist/{ios-device-DPsSm0v_.mjs → ios-device-BiOsSVzd.mjs} +1 -1
  35. package/dist/{ios-device-D972i9wf.mjs → ios-device-CtRdEVjx.mjs} +3 -3
  36. package/dist/{launch-verify-Q_OtW1Rf.mjs → launch-verify-CQS_Kg-C.mjs} +5 -5
  37. package/dist/{logs-CI9NQSK7.mjs → logs-MARIy6m9.mjs} +9 -9
  38. package/dist/{metro-DrLHaMn2.mjs → metro-BWLOJ_Wr.mjs} +116 -10
  39. package/dist/{named-ports-CmLQSIRj.mjs → named-ports-DiTfSz6p.mjs} +4 -4
  40. package/dist/{ndjson-9uFNRwfe.mjs → ndjson-CDY9IkVC.mjs} +3 -56
  41. package/dist/{ndjson-DvHSsNU9.d.mts → ndjson-Du3j0AQ9.d.mts} +1 -0
  42. package/dist/{ownership-D15Op8vN.mjs → ownership-D2xbLVoz.mjs} +2 -3
  43. package/dist/ownership-DZjdx8Gq.mjs +1180 -0
  44. package/dist/{ports-BNKoWVWZ.mjs → ports-CLSSFOuz.mjs} +3 -3
  45. package/dist/{project-DS112DYB.mjs → project-BXZzOABt.mjs} +2 -2
  46. package/dist/{reload-ZNJUo1pl.mjs → reload-DoETJ3rl.mjs} +9 -10
  47. package/dist/{server-bare-DWkkcIxV.mjs → server-bare-DVbb7kXH.mjs} +1 -1
  48. package/dist/{server-expo-B_lctBR3.mjs → server-expo-BvOCeakp.mjs} +4 -4
  49. package/dist/server-expo-DBVTdult.mjs +2 -0
  50. package/dist/{settings-D030k0t4.mjs → settings-DOugPlPz.mjs} +16 -428
  51. package/dist/{settings-BKNh5rl4.mjs → settings-EWYNwe72.mjs} +16 -14
  52. package/dist/settings.schema.json +75 -0
  53. package/dist/{simslim-B_LsGLuJ.mjs → simslim-Ca3487H6.mjs} +182 -5
  54. package/dist/{slot-launch-DU9A-gYw.mjs → slot-launch-C5cg0fmk.mjs} +4 -4
  55. package/dist/{spawn-claims-Dn3C_N6w.mjs → spawn-claims-CUleC2cM.mjs} +1 -1
  56. package/dist/{start-DYkkKF0s.mjs → start-F9gv5dcC.mjs} +147 -98
  57. package/dist/start-VoFsPSes.mjs +2 -0
  58. package/dist/{state-NcJzMEBF.mjs → state-WGdIbi_d.mjs} +2 -2
  59. package/dist/{stats-DG9e66Rz.mjs → stats-BAgJaLA4.mjs} +1 -1
  60. package/dist/{stats-B63-JVAY.mjs → stats-DBYJ5bxL.mjs} +4 -4
  61. package/dist/{status-S6ehL4Ui.mjs → status-DLCD-o3s.mjs} +63 -231
  62. package/dist/status-Dr4fRkym.mjs +216 -0
  63. package/dist/{guide-status-BAMVU0ZA.mjs → stim-installations-CINXy_su.mjs} +3 -124
  64. package/dist/{stop-BO28HGqF.mjs → stop-Dj4pfmyv.mjs} +22 -18
  65. package/dist/{stop-T1R-cZRz.mjs → stop-ZvOeTmKb.mjs} +2 -2
  66. package/dist/supervisor-run.d.mts +11 -2
  67. package/dist/supervisor-run.mjs +185 -17
  68. package/dist/{workspace-process-lock-DWaiRD0e.mjs → workspace-process-lock-BXA96myD.mjs} +2 -2
  69. package/dist/workspaces-BTUyFfkv.mjs +1003 -0
  70. package/dist/{worktree-DKhSF0UX.mjs → worktree-4aZg2NnI.mjs} +1 -1
  71. package/dist/{worktree-LGB-UwgG.mjs → worktree-BMS7GeqB.mjs} +40 -122
  72. package/dist/{worktree-R_cUlE7s.mjs → worktree-BlizKDpZ.mjs} +143 -18
  73. package/dist/{xcode-BZqyxh3e.mjs → xcode-B2tBkf0m.mjs} +9 -158
  74. package/package.json +6 -5
  75. package/dist/build-progress-CVqkfPC6.mjs +0 -188
  76. package/dist/device-lease-Crs-HkJY.mjs +0 -366
  77. package/dist/logs-query-Cqma3WIu.mjs +0 -298
  78. package/dist/ownership-DCQPuWEc.mjs +0 -489
  79. package/dist/public-http-probe-CyMDrQ3c.mjs +0 -61
  80. package/dist/server-expo-CeILEu86.mjs +0 -2
  81. package/dist/sim-pool-KaIsp2Ft.mjs +0 -723
  82. package/dist/spawn-entry-nCE6m770.mjs +0 -14
  83. package/dist/workspace-state-DF2gCFhx.mjs +0 -169
@@ -1,489 +0,0 @@
1
- import { D as process_identity_exports, k as ownership_claim_exports, u as getConfigDir } from "./config-Cp9lM3wX.mjs";
2
- import { t as getExecutor } from "./exec-jIAlgilk.mjs";
3
- import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { a as pidExists, l as signalProcessTree } from "./metro-DrLHaMn2.mjs";
5
- import { r as workspaceProcessLockPath, t as withWorkspaceProcessLock } from "./workspace-process-lock-DWaiRD0e.mjs";
6
- import { t as probePublicHttp } from "./public-http-probe-CyMDrQ3c.mjs";
7
- import { closeSync, mkdirSync, openSync, readFileSync, unlinkSync } from "node:fs";
8
- import { basename, join, resolve, sep } from "node:path";
9
- import { createHash, randomUUID } from "node:crypto";
10
- //#region src/engine/tunnel.ts
11
- function tunnelArgv(provider, port, ngrokUrl, logFile) {
12
- if (provider === "cloudflared") return {
13
- bin: "cloudflared",
14
- args: [
15
- "tunnel",
16
- "--url",
17
- `http://127.0.0.1:${port}`,
18
- ...logFile ? ["--logfile", logFile] : []
19
- ]
20
- };
21
- return {
22
- bin: "ngrok",
23
- args: [
24
- "http",
25
- String(port),
26
- `--log=${logFile || "stdout"}`,
27
- "--log-format=json",
28
- ...ngrokUrl ? ["--url", ngrokUrl] : []
29
- ]
30
- };
31
- }
32
- const CLOUDFLARED_URL_RE = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/i;
33
- function parseCloudflaredLine(line) {
34
- const match = line.match(CLOUDFLARED_URL_RE);
35
- return match ? match[0] : null;
36
- }
37
- function parseNgrokLine(line) {
38
- let data;
39
- try {
40
- data = JSON.parse(line);
41
- } catch {
42
- return null;
43
- }
44
- if (typeof data !== "object" || data === null) return null;
45
- const url = data.url;
46
- return typeof url === "string" && /^https?:\/\//i.test(url) ? url : null;
47
- }
48
- function parserFor(provider) {
49
- return provider === "cloudflared" ? parseCloudflaredLine : parseNgrokLine;
50
- }
51
- const URL_TIMEOUT_MS = 15e3;
52
- const REACHABLE_TIMEOUT_MS = 24e4;
53
- const REACHABLE_POLL_MS = 2e3;
54
- const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
55
- async function withManagedTunnelLock(root, fn, options = {}) {
56
- return withWorkspaceProcessLock(managedTunnelLockRoot(root), "metro-tunnel", fn, {
57
- ...options,
58
- rejectOwnerPurposes: ["workspace removal"]
59
- });
60
- }
61
- async function withManagedTunnelRemovalLock(root, fn, options = {}) {
62
- return withWorkspaceProcessLock(managedTunnelLockRoot(root), "metro-tunnel", fn, {
63
- ...options,
64
- ownerPurpose: "workspace removal"
65
- });
66
- }
67
- async function withManagedRemoteWorktreeLock(worktreeRoot, fn, options = {}) {
68
- return withWorkspaceProcessLock(managedRemoteWorktreeLockRoot(worktreeRoot), "managed-remote", fn, {
69
- ...options,
70
- external: true,
71
- rejectOwnerPurposes: ["worktree removal"]
72
- });
73
- }
74
- async function withManagedRemoteWorktreeRemovalLock(worktreeRoot, fn, options = {}) {
75
- return withWorkspaceProcessLock(managedRemoteWorktreeLockRoot(worktreeRoot), "managed-remote", fn, {
76
- ...options,
77
- external: true,
78
- ownerPurpose: "worktree removal"
79
- });
80
- }
81
- function managedLockHolders(root) {
82
- const locks = [{
83
- label: "managed tunnel",
84
- path: workspaceProcessLockPath(managedTunnelLockRoot(root), "metro-tunnel", false)
85
- }, {
86
- label: "managed remote",
87
- path: workspaceProcessLockPath(managedRemoteWorktreeLockRoot(root), "managed-remote", true)
88
- }];
89
- const reasons = [];
90
- for (const { label, path } of locks) {
91
- const claims = (0, ownership_claim_exports.readClaimSet)(path);
92
- const holder = claims.live[0];
93
- if (holder) {
94
- const purpose = typeof holder.details.purpose === "string" ? ` for ${holder.details.purpose}` : "";
95
- reasons.push(`the ${label} lock is held${purpose}`);
96
- } else if (claims.unresolved[0]) reasons.push(`the ${label} lock cannot be resolved: ${claims.unresolved[0].reason}`);
97
- }
98
- return reasons;
99
- }
100
- function managedTunnelLockRoot(root) {
101
- const key = createHash("sha256").update(resolve(root)).digest("hex");
102
- return join(getConfigDir(), "process-locks", key);
103
- }
104
- function managedRemoteWorktreeLockRoot(worktreeRoot) {
105
- const key = createHash("sha256").update(resolve(worktreeRoot)).digest("hex");
106
- return join(getConfigDir(), "process-locks", "worktrees", key);
107
- }
108
- async function defaultProbeReachable(url, signal) {
109
- const status = await probePublicHttp(url, signal);
110
- return status !== null && status > 0;
111
- }
112
- function waitForUrl(child, parseLine, timeoutMs) {
113
- return new Promise((resolve) => {
114
- let settled = false;
115
- let timer;
116
- let onOut;
117
- let onErr;
118
- let onError;
119
- let onExit;
120
- const finish = (url, exited = false) => {
121
- if (settled) return;
122
- settled = true;
123
- clearTimeout(timer);
124
- child.stdout?.removeListener("data", onOut);
125
- child.stderr?.removeListener("data", onErr);
126
- child.removeListener("error", onError);
127
- child.removeListener("exit", onExit);
128
- resolve({
129
- url,
130
- exited
131
- });
132
- };
133
- const onLine = (line) => {
134
- if (settled) return;
135
- const url = parseLine(line);
136
- if (url) finish(url);
137
- };
138
- const outReader = createLineReader(onLine);
139
- const errReader = createLineReader(onLine);
140
- onOut = (chunk) => outReader.push(chunk);
141
- onErr = (chunk) => errReader.push(chunk);
142
- onError = () => finish(null);
143
- onExit = () => finish(null, true);
144
- child.stdout?.setEncoding?.("utf-8");
145
- child.stderr?.setEncoding?.("utf-8");
146
- child.stdout?.on("data", onOut);
147
- child.stderr?.on("data", onErr);
148
- child.on("error", onError);
149
- child.on("exit", onExit);
150
- timer = setTimeout(() => finish(null), timeoutMs);
151
- });
152
- }
153
- function waitForFileUrl(child, logFile, parseLine, timeoutMs) {
154
- return new Promise((resolve) => {
155
- let settled = false;
156
- const finish = (url, exited = false) => {
157
- if (settled) return;
158
- settled = true;
159
- clearInterval(interval);
160
- clearTimeout(timer);
161
- child.removeListener("error", onError);
162
- child.removeListener("exit", onExit);
163
- resolve({
164
- url,
165
- exited
166
- });
167
- };
168
- const probe = () => {
169
- try {
170
- for (const line of readFileSync(logFile, "utf-8").split(/\r?\n/)) {
171
- const url = parseLine(line);
172
- if (url) return finish(url);
173
- }
174
- } catch {}
175
- };
176
- const onError = () => finish(null);
177
- const onExit = () => finish(null, true);
178
- child.on("error", onError);
179
- child.on("exit", onExit);
180
- const interval = setInterval(probe, 25);
181
- const timer = setTimeout(() => finish(null), timeoutMs);
182
- probe();
183
- });
184
- }
185
- function createTunnelLogFile(provider) {
186
- const dir = join(getConfigDir(), "tunnel-logs");
187
- mkdirSync(dir, { recursive: true });
188
- const path = join(dir, `${provider}-${randomUUID()}.log`);
189
- closeSync(openSync(path, "wx", 384));
190
- return path;
191
- }
192
- function removeTunnelLogFile(path) {
193
- if (!path) return;
194
- try {
195
- unlinkSync(path);
196
- } catch {}
197
- }
198
- function removeRecordedTunnelLogFile(path) {
199
- if (!path) return;
200
- const dir = resolve(join(getConfigDir(), "tunnel-logs"));
201
- const resolved = resolve(path);
202
- if (!resolved.startsWith(`${dir}${sep}`) || resolve(join(dir, basename(resolved))) !== resolved) return;
203
- removeTunnelLogFile(resolved);
204
- }
205
- async function waitUntilReachable({ url, now, sleep, probe, timeoutMs }) {
206
- const deadline = now() + timeoutMs;
207
- for (;;) {
208
- if (await probe(url, new AbortController().signal).catch(() => false)) return true;
209
- if (now() >= deadline) return false;
210
- await sleep(REACHABLE_POLL_MS);
211
- }
212
- }
213
- const CLEANUP_TIMEOUT_MS = 1e3;
214
- const CLEANUP_POLL_MS = 25;
215
- async function startTunnel({ provider, port, spawnFn = null, urlTimeoutMs = URL_TIMEOUT_MS, reachableTimeoutMs = REACHABLE_TIMEOUT_MS, probeReachable = defaultProbeReachable, now = Date.now, sleep = defaultSleep, ngrokUrl = null, requireReachable = true, cleanupTimeoutMs = CLEANUP_TIMEOUT_MS, isChildAlive = pidExists, readProcessToken = process_identity_exports.captureProcessToken, logFile = null }) {
216
- const spawn = spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts));
217
- const outputFile = logFile || (spawnFn ? null : createTunnelLogFile(provider));
218
- const { bin, args } = tunnelArgv(provider, port, ngrokUrl, outputFile);
219
- let child;
220
- try {
221
- child = spawn(bin, args, {
222
- stdio: outputFile ? [
223
- "ignore",
224
- "ignore",
225
- "ignore"
226
- ] : [
227
- "ignore",
228
- "pipe",
229
- "pipe"
230
- ],
231
- detached: true
232
- });
233
- } catch (err) {
234
- removeTunnelLogFile(outputFile);
235
- return {
236
- failed: true,
237
- reason: `Could not start ${provider}: ${describe(err)}`
238
- };
239
- }
240
- let childExited = false;
241
- child.once("exit", () => {
242
- childExited = true;
243
- });
244
- const cleanup = async (alreadyExited = childExited) => {
245
- const stopped = await terminateChild(child, {
246
- alreadyExited,
247
- timeoutMs: cleanupTimeoutMs,
248
- now,
249
- sleep,
250
- isAlive: isChildAlive
251
- });
252
- if (stopped) removeTunnelLogFile(outputFile);
253
- return stopped ? { status: "stopped" } : {
254
- status: "failed",
255
- reason: `Sent SIGKILL but could not confirm that pid ${child.pid ?? "unknown"} exited.`
256
- };
257
- };
258
- const failAfterCleanup = async (reason, alreadyExited = childExited) => {
259
- const stopped = await cleanup(alreadyExited);
260
- return stopped.status === "stopped" ? {
261
- failed: true,
262
- reason
263
- } : {
264
- failed: true,
265
- reason: `${reason} ${stopped.reason}`,
266
- cleanupFailed: true
267
- };
268
- };
269
- const pid = child.pid;
270
- if (!pid) return failAfterCleanup(`${provider} started but reported no pid.`);
271
- const captureChildIdentity = () => {
272
- try {
273
- return readProcessToken(pid);
274
- } catch {
275
- return null;
276
- }
277
- };
278
- const initialProcessToken = captureChildIdentity();
279
- if (!initialProcessToken) return failAfterCleanup(`${provider} started but its process identity token could not be read.`);
280
- const { url, exited } = outputFile ? await waitForFileUrl(child, outputFile, parserFor(provider), urlTimeoutMs) : await waitForUrl(child, parserFor(provider), urlTimeoutMs);
281
- if (!url) return failAfterCleanup(exited ? `${provider} exited before printing a tunnel URL.` : `${provider} did not print a tunnel URL within ${urlTimeoutMs}ms.`, exited || childExited);
282
- if (!outputFile) resumeChildPipes(child);
283
- if (requireReachable) {
284
- if (!await waitUntilReachable({
285
- url,
286
- now,
287
- sleep,
288
- probe: probeReachable,
289
- timeoutMs: reachableTimeoutMs
290
- })) return failAfterCleanup(`${url} did not become reachable within ${reachableTimeoutMs}ms; ${provider} may still be registering, or the network path is blocked.`);
291
- }
292
- const finalProcessToken = captureChildIdentity();
293
- if (!finalProcessToken || finalProcessToken !== initialProcessToken) return failAfterCleanup(`${provider} process identity changed before its tunnel could be recorded.`);
294
- if (!outputFile) unrefChildPipes(child);
295
- child.unref?.();
296
- if (childExited) return failAfterCleanup(`${provider} exited before its tunnel could be recorded.`, true);
297
- return {
298
- url,
299
- pid,
300
- processToken: initialProcessToken,
301
- logFile: outputFile,
302
- cleanup: () => cleanup()
303
- };
304
- }
305
- async function startTunnelSequence({ providers, port, ngrokUrl = null, requireReachable = true, start = startTunnel }) {
306
- const failures = [];
307
- for (const provider of providers) {
308
- const result = await start({
309
- provider,
310
- port,
311
- ngrokUrl: provider === "ngrok" ? ngrokUrl : null,
312
- requireReachable
313
- });
314
- if (!("failed" in result)) return {
315
- provider,
316
- ...result
317
- };
318
- failures.push(`${provider}: ${result.reason}`);
319
- if (result.cleanupFailed) return {
320
- failed: true,
321
- reason: failures.join(" ")
322
- };
323
- }
324
- return {
325
- failed: true,
326
- reason: failures.join(" ") || "No managed tunnel provider was selected."
327
- };
328
- }
329
- function closeChildPipes(child) {
330
- child.stdout?.destroy?.();
331
- child.stderr?.destroy?.();
332
- }
333
- function unrefChildPipes(child) {
334
- resumeChildPipes(child);
335
- for (const stream of [child.stdout, child.stderr]) stream?.unref?.();
336
- }
337
- function resumeChildPipes(child) {
338
- child.stdout?.resume?.();
339
- child.stderr?.resume?.();
340
- }
341
- async function signalAndWaitForExit(child, signal, { timeoutMs, now, sleep, isAlive, platform }) {
342
- let exited = false;
343
- const onExit = () => {
344
- exited = true;
345
- };
346
- child.once("exit", onExit);
347
- try {
348
- if (platform === "win32" && child.pid) signalProcessTree(child.pid, signal, { platform });
349
- child.kill(signal);
350
- } catch (err) {
351
- child.removeListener("exit", onExit);
352
- return isEsrch(err);
353
- }
354
- const hasExited = () => exited;
355
- const deadline = now() + timeoutMs;
356
- while (!hasExited() && now() < deadline) await sleep(CLEANUP_POLL_MS);
357
- if (!hasExited() && child.pid && !isAlive(child.pid)) exited = true;
358
- child.removeListener("exit", onExit);
359
- return hasExited();
360
- }
361
- async function terminateChild(child, { alreadyExited, timeoutMs, now, sleep, isAlive, platform = process.platform }) {
362
- if (alreadyExited) {
363
- closeChildPipes(child);
364
- return true;
365
- }
366
- if (await signalAndWaitForExit(child, "SIGTERM", {
367
- timeoutMs,
368
- now,
369
- sleep,
370
- isAlive,
371
- platform
372
- })) {
373
- closeChildPipes(child);
374
- return true;
375
- }
376
- const killed = await signalAndWaitForExit(child, "SIGKILL", {
377
- timeoutMs,
378
- now,
379
- sleep,
380
- isAlive,
381
- platform
382
- });
383
- closeChildPipes(child);
384
- return killed;
385
- }
386
- function describe(err) {
387
- return err?.message || String(err);
388
- }
389
- const STOP_TIMEOUT_MS = 5e3;
390
- const STOP_POLL_MS = 100;
391
- function isEsrch(err) {
392
- return err?.code === "ESRCH";
393
- }
394
- async function stopTunnel(record, { isAlive = pidExists, inspectIdentity = process_identity_exports.inspectProcessIdentity, platform = process.platform, kill = (pid) => signalProcessTree(pid, "SIGTERM", { platform }), now = Date.now, sleep = defaultSleep, timeoutMs = STOP_TIMEOUT_MS } = {}) {
395
- const missing = () => {
396
- removeRecordedTunnelLogFile(record?.logFile);
397
- return { status: "missing" };
398
- };
399
- const pid = record?.pid;
400
- if (!pid || !isAlive(pid)) return missing();
401
- if (!record.processToken) return {
402
- status: "failed",
403
- reason: `tunnel pid ${pid} has no process identity token, so Stim cannot verify ownership. Keep the record. Inspect the process, stop it with the provider tooling, remove the stale metroTunnel state, and retry.`
404
- };
405
- const identity = inspectIdentity(record);
406
- if (identity === "gone" || identity === "different") return missing();
407
- if (identity !== "same") return {
408
- status: "failed",
409
- reason: `could not verify the process identity for tunnel pid ${pid}; refusing to signal it.`
410
- };
411
- try {
412
- kill(pid);
413
- } catch (err) {
414
- return isEsrch(err) ? missing() : {
415
- status: "failed",
416
- reason: describe(err)
417
- };
418
- }
419
- const deadline = now() + timeoutMs;
420
- const exited = () => {
421
- if (!isAlive(pid)) return true;
422
- const current = inspectIdentity(record);
423
- return current === "gone" || current === "different";
424
- };
425
- while (now() < deadline && !exited()) await sleep(STOP_POLL_MS);
426
- if (!exited()) return {
427
- status: "failed",
428
- reason: `pid ${pid} did not exit within ${timeoutMs}ms.`
429
- };
430
- removeRecordedTunnelLogFile(record.logFile);
431
- return { status: "stopped" };
432
- }
433
- //#endregion
434
- //#region src/supervisor/ownership.ts
435
- function resolveSupervisorTarget({ state, record, reservedPort, isAlive = pidExists, inspectIdentity = process_identity_exports.inspectProcessIdentity } = {}) {
436
- const statePid = numberOrNull(state?.pid);
437
- const recordPid = numberOrNull(record?.pid);
438
- const pid = statePid ?? recordPid;
439
- if (!pid) return { status: "none" };
440
- if (statePid && recordPid && statePid !== recordPid) return {
441
- status: "unverified",
442
- pid,
443
- reason: `workspace state.json records supervisor pid ${statePid} but the registry records pid ${recordPid}`
444
- };
445
- if (!isAlive(pid)) return {
446
- status: "stale",
447
- pid
448
- };
449
- const port = numberOrNull(state?.port) ?? numberOrNull(record?.port);
450
- if (reservedPort !== null && reservedPort !== void 0 && port !== null && port !== reservedPort) return {
451
- status: "unverified",
452
- pid,
453
- reason: `supervisor pid ${pid} records port ${port}, but this project reserved port ${reservedPort}`
454
- };
455
- if (reservedPort !== null && reservedPort !== void 0 && port === null) return {
456
- status: "unverified",
457
- pid,
458
- reason: `supervisor pid ${pid} has no recorded port, so it cannot be matched against reserved port ${reservedPort}`
459
- };
460
- const identityRecord = statePid ? state : record;
461
- if (statePid && recordPid && state?.processToken !== record?.processToken) return {
462
- status: "unverified",
463
- pid,
464
- reason: "workspace state and registry process identities disagree"
465
- };
466
- const identity = inspectIdentity(identityRecord);
467
- if (identity === "gone" || identity === "different") return {
468
- status: "stale",
469
- pid
470
- };
471
- if (identity !== "same") return {
472
- status: "unverified",
473
- pid,
474
- reason: "the recorded process identity could not be verified"
475
- };
476
- return {
477
- status: "ours",
478
- processToken: identityRecord.processToken,
479
- pid,
480
- port,
481
- mode: state?.mode ?? record?.mode ?? null,
482
- startedAt: state?.startedAt ?? record?.startedAt ?? null
483
- };
484
- }
485
- function numberOrNull(v) {
486
- return typeof v === "number" && Number.isSafeInteger(v) && v > 0 ? v : null;
487
- }
488
- //#endregion
489
- export { terminateChild as a, withManagedTunnelLock as c, stopTunnel as i, withManagedTunnelRemovalLock as l, managedLockHolders as n, withManagedRemoteWorktreeLock as o, startTunnelSequence as r, withManagedRemoteWorktreeRemovalLock as s, resolveSupervisorTarget as t };
@@ -1,61 +0,0 @@
1
- import { resolve4 } from "node:dns/promises";
2
- import { request } from "node:https";
3
- //#region src/engine/public-http-probe.ts
4
- const DNS_TIMEOUT_MS = 5e3;
5
- async function resolveAddresses(hostname, signal) {
6
- if (signal.aborted) throw signal.reason;
7
- let timer;
8
- let onAbort;
9
- const unavailable = new Promise((_resolve, reject) => {
10
- onAbort = () => reject(signal.reason);
11
- signal.addEventListener("abort", onAbort, { once: true });
12
- if (signal.aborted) onAbort();
13
- else timer = setTimeout(() => reject(/* @__PURE__ */ new Error("DNS lookup timed out")), DNS_TIMEOUT_MS);
14
- });
15
- try {
16
- return await Promise.race([resolve4(hostname), unavailable]);
17
- } finally {
18
- clearTimeout(timer);
19
- if (onAbort) signal.removeEventListener("abort", onAbort);
20
- }
21
- }
22
- async function probePublicHttp(url, signal) {
23
- try {
24
- return (await fetch(url, {
25
- signal,
26
- redirect: "follow"
27
- })).status;
28
- } catch (error) {
29
- const cause = error?.cause;
30
- if (cause?.code !== "ENOTFOUND" && cause?.code !== "EAI_AGAIN") return null;
31
- }
32
- const hostname = new URL(url).hostname;
33
- if (!hostname.endsWith(".trycloudflare.com")) return null;
34
- let addresses;
35
- try {
36
- addresses = await resolveAddresses(hostname, signal);
37
- } catch {
38
- return null;
39
- }
40
- const firstAddress = addresses[0];
41
- if (!firstAddress) return null;
42
- return new Promise((resolve) => {
43
- const request$1 = request(url, {
44
- signal,
45
- lookup: (_hostname, options, callback) => {
46
- if (options.all) callback(null, addresses.map((address) => ({
47
- address,
48
- family: 4
49
- })));
50
- else callback(null, firstAddress, 4);
51
- }
52
- }, (response) => {
53
- response.resume();
54
- resolve(response.statusCode ?? null);
55
- });
56
- request$1.on("error", () => resolve(null));
57
- request$1.end();
58
- });
59
- }
60
- //#endregion
61
- export { probePublicHttp as t };
@@ -1,2 +0,0 @@
1
- import { p as startExpoServer } from "./server-expo-B_lctBR3.mjs";
2
- export { startExpoServer };