stim 1.12.0 → 1.13.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 (71) hide show
  1. package/README.md +3 -1
  2. package/dist/{activity-CCZJs__P.mjs → activity-DfVKZTEB.mjs} +42 -25
  3. package/dist/{android-BQiKJYK0.mjs → android-BHfAu2mf.mjs} +1 -1
  4. package/dist/{android-B7X-8H7h.mjs → android-CD8pr8Q2.mjs} +62 -47
  5. package/dist/{android-cas-DzLPXiEn.mjs → android-cas-B9Kv9aIy.mjs} +9 -7
  6. package/dist/{android-75Sk2rIR.mjs → android-qx_31wJo.mjs} +395 -116
  7. package/dist/{app-install-CsZi0SAT.mjs → app-install-CDFY2nUL.mjs} +1 -1
  8. package/dist/{budget-DbzW5VTD.mjs → budget-E5o91NR1.mjs} +154 -37
  9. package/dist/{build-plan-CqntbR7b.mjs → build-plan-BTa93o_r.mjs} +21 -88
  10. package/dist/{build-progress-h60GPV27.mjs → build-progress-l7d-X-ZP.mjs} +75 -7
  11. package/dist/cdp-Dq_ypAlJ.mjs +115 -0
  12. package/dist/chrome-B5hWgQJS.mjs +61 -0
  13. package/dist/cli.mjs +16 -15
  14. package/dist/collector-run.mjs +14 -8
  15. package/dist/{command-output-BWCj5Vh-.mjs → command-output-BIL7rlX7.mjs} +1 -1
  16. package/dist/created-devices-Cd558h31.mjs +37 -0
  17. package/dist/{deps-CO-_7UOm.mjs → deps-2Wo81np9.mjs} +1 -1
  18. package/dist/{device-9r9xRYDa.mjs → device-Cf7vl-so.mjs} +6 -6
  19. package/dist/{device-lease-B9LAXIUH.mjs → device-lease-CL9dZf73.mjs} +52 -3
  20. package/dist/{device-pool-BoezJd-c.mjs → device-pool-MuoiyRcu.mjs} +3 -3
  21. package/dist/{device-remote-C0_o-tJH.mjs → device-remote-DT9ngZiD.mjs} +10 -10
  22. package/dist/{doctor-LfDlbR-N.mjs → doctor-D2iysNNH.mjs} +47 -18
  23. package/dist/{error-diagnostics-CCxjn31V.mjs → error-diagnostics-BoiOhck8.mjs} +6 -6
  24. package/dist/{gc-C4nQFcTX.mjs → gc-eA-PRBX8.mjs} +853 -126
  25. package/dist/{guide-BPBlh9ML.mjs → guide-BfZ0OmiP.mjs} +736 -110
  26. package/dist/{guide-status-i9ogHt4v.mjs → guide-status-BaMYu55M.mjs} +1 -1
  27. package/dist/{idle-S3tFZ53_.mjs → idle-DxLi5OkN.mjs} +42 -9
  28. package/dist/{in-use-D9XYEgFD.mjs → in-use-wYEaKQM9.mjs} +9 -5
  29. package/dist/{ios-CDzWL1mj.mjs → ios-CcfCeZ19.mjs} +98 -54
  30. package/dist/{ios-CZWOHTTc.mjs → ios-CmEzZiOj.mjs} +10 -5
  31. package/dist/{ios-device-D9cLxVr5.mjs → ios-device-BW-t_Lkv.mjs} +1 -1
  32. package/dist/{launch-verify-B2oR_kFN.mjs → launch-verify-CuJaBpEa.mjs} +33 -20
  33. package/dist/{logs-SzuYudOj.mjs → logs-DcSRbC2t.mjs} +11 -10
  34. package/dist/{metro-Dzo30hvJ.mjs → metro-BPeY1YMh.mjs} +4 -4
  35. package/dist/{named-ports-Dn1o61D9.mjs → named-ports-n7tnJsI8.mjs} +78 -6
  36. package/dist/native-runtime-CiiFHt0e.mjs +74 -0
  37. package/dist/{ownership-Dqnrjrio.mjs → ownership-Bz2kETAS.mjs} +1 -1
  38. package/dist/{ownership-B8d4kXBx.mjs → ownership-PUP4Dwai.mjs} +134 -209
  39. package/dist/page-BTu7I60K.mjs +29 -0
  40. package/dist/{ports-Dp_QTwTC.mjs → ports-C5UutqpJ.mjs} +4 -4
  41. package/dist/{project-B8rbutVC.mjs → project-DGeclhvO.mjs} +53 -17
  42. package/dist/{reload-nocmx8KB.mjs → reload-C-cV5yy_.mjs} +79 -20
  43. package/dist/{remote-cache-BRsRZru5.mjs → remote-cache--aehr4Pr.mjs} +3 -3
  44. package/dist/{server-bare-Gn3ssSdK.mjs → server-bare-Bq8BpSIo.mjs} +1 -1
  45. package/dist/server-expo-BeYwP_Xy.mjs +2 -0
  46. package/dist/{server-expo-CeT1nIIk.mjs → server-expo-DUCg52-K.mjs} +2 -2
  47. package/dist/{settings-bE-Gu3Ti.mjs → settings-ssVBToDR.mjs} +10 -10
  48. package/dist/{settings-BlyDn2Oz.mjs → settings-xB0Frkg6.mjs} +11 -2
  49. package/dist/settings.schema.json +53 -1
  50. package/dist/{simslim-COtEEP7x.mjs → simslim-Bbg9UWrt.mjs} +12 -6
  51. package/dist/{slot-launch-DIACGEfH.mjs → slot-launch-BIWEW-wI.mjs} +3 -3
  52. package/dist/{start-BboE1HIS.mjs → start-BZhItkiL.mjs} +11 -10
  53. package/dist/{start-BFstVBlx.mjs → start-Rw2GD3nV.mjs} +1 -1
  54. package/dist/{state-DcDgzfu3.mjs → state-DwAU2_-D.mjs} +1 -1
  55. package/dist/state-l1pYwOre.mjs +148 -0
  56. package/dist/{stats-DiCtmluY.mjs → stats-CaSwmsSZ.mjs} +2 -2
  57. package/dist/{status-DI9Tjo7T.mjs → status-TJlL0HWo.mjs} +624 -103
  58. package/dist/{status-BUASYyy_.mjs → status-sszP4XKU.mjs} +59 -2
  59. package/dist/{stim-desktop-D0xhpZt8.mjs → stim-desktop-CXt8-Z3J.mjs} +13 -2
  60. package/dist/{stop-Bn6v-GvS.mjs → stop-BZ2qMiBP.mjs} +37 -12
  61. package/dist/{stop-BI7QY76M.mjs → stop-DskDKNTU.mjs} +2 -2
  62. package/dist/supervisor-run.mjs +10 -10
  63. package/dist/web-run.d.mts +22 -0
  64. package/dist/web-run.mjs +481 -0
  65. package/dist/web-sWXd5iek.mjs +394 -0
  66. package/dist/{worktree-B5sTRskL.mjs → worktree-3cBa-bQt.mjs} +1 -1
  67. package/dist/{worktree-ChDL5fO1.mjs → worktree-D4Do_XiQ.mjs} +226 -19
  68. package/dist/{xcode-BzplpQzc.mjs → xcode-LM6A8cNZ.mjs} +5 -5
  69. package/package.json +5 -5
  70. package/dist/server-expo-eWi9Coof.mjs +0 -2
  71. package/dist/workspace-process-lock-BvvJTfo_.mjs +0 -57
@@ -1,24 +1,18 @@
1
- import { l as findEnclosingWorktreeRoot, p as getProject } from "./config-0jCcMM0E.mjs";
1
+ import { _ as loadConfig, g as isPathPrefix, l as findEnclosingWorktreeRoot, p as getProject } from "./config-0jCcMM0E.mjs";
2
2
  import { y as repoRoot } from "./worktree-DeBQSVtR.mjs";
3
3
  import { existsSync, readFileSync, realpathSync } from "fs";
4
4
  import { basename, dirname, join, resolve } from "path";
5
- import { createRequire } from "module";
6
5
  //#region src/workspace/project.ts
7
- const requireFromHere = createRequire(import.meta.url);
6
+ /**
7
+ * The realpath of `name`'s package.json in the nearest `node_modules` at or above `projectRoot`.
8
+ * Unlike `require.resolve`, it ignores `NODE_PATH`, which pnpm's bin shims point at the workspace's
9
+ * hidden hoist directory holding every member's dependencies.
10
+ */
8
11
  function resolvePackageJson(projectRoot, name) {
9
- try {
10
- return requireFromHere.resolve(`${name}/package.json`, { paths: [projectRoot] });
11
- } catch {
12
- try {
13
- const main = requireFromHere.resolve(name, { paths: [projectRoot] });
14
- const marker = `/node_modules/${name}/`;
15
- const at = main.lastIndexOf(marker);
16
- if (at === -1) return null;
17
- const candidate = join(main.slice(0, at + marker.length), "package.json");
18
- return existsSync(candidate) ? candidate : null;
19
- } catch {
20
- return null;
21
- }
12
+ for (let dir = resolve(projectRoot);; dir = dirname(dir)) {
13
+ const candidate = join(dir, "node_modules", name, "package.json");
14
+ if (existsSync(candidate)) return realpathSync(candidate);
15
+ if (dirname(dir) === dir) return null;
22
16
  }
23
17
  }
24
18
  function isPackageResolvable(projectRoot, name) {
@@ -57,6 +51,48 @@ function findProjectRoot(startDir) {
57
51
  dir = parent;
58
52
  }
59
53
  }
54
+ function findServerWorkspace(startDir) {
55
+ const nearest = findProjectRoot(startDir);
56
+ if (!nearest) return null;
57
+ if (appProjectProblem(nearest)?.kind !== "not-an-app") return {
58
+ root: nearest,
59
+ from: null
60
+ };
61
+ if (Object.keys(getProject(nearest)?.ports ?? {}).length) return {
62
+ root: nearest,
63
+ from: null
64
+ };
65
+ const top = repoRoot(nearest);
66
+ if (!top) return {
67
+ root: nearest,
68
+ from: null
69
+ };
70
+ const worktree = expandedRealpath(top);
71
+ const apps = Object.keys(loadConfig()?.projects ?? {}).filter((path) => {
72
+ if (path === nearest || !isPathPrefix(worktree, expandedRealpath(path)) || appProjectProblem(path) !== null) return false;
73
+ const owner = repoRoot(path);
74
+ return owner !== null && expandedRealpath(owner) === worktree;
75
+ });
76
+ return apps.length === 1 ? {
77
+ root: apps[0],
78
+ from: nearest
79
+ } : {
80
+ root: nearest,
81
+ from: null
82
+ };
83
+ }
84
+ function findCommandWorkspace(startDir, note = (line) => console.error(line)) {
85
+ const workspace = findServerWorkspace(startDir);
86
+ if (workspace?.from) note(`Using the Stim workspace ${workspace.root}: ${workspace.from} is not a React Native or Expo app.`);
87
+ return workspace?.root ?? null;
88
+ }
89
+ function expandedRealpath(path) {
90
+ try {
91
+ return realpathSync.native(path);
92
+ } catch {
93
+ return resolve(path);
94
+ }
95
+ }
60
96
  function loadPackageJson(projectRoot) {
61
97
  const p = join(projectRoot, "package.json");
62
98
  if (!existsSync(p)) return {
@@ -177,4 +213,4 @@ function readAppConfigText(projectRoot) {
177
213
  return null;
178
214
  }
179
215
  //#endregion
180
- export { isPackageResolvable as a, readAppConfigText as c, findProjectRoot as i, readAppJson as l, appProjectProblem as n, ownedDeviceLabel as o, detectIsExpo as r, projectShortcut as s, NO_PROJECT_REFUSAL as t, resolvePackageJson as u };
216
+ export { findProjectRoot as a, ownedDeviceLabel as c, readAppJson as d, resolvePackageJson as f, findCommandWorkspace as i, projectShortcut as l, appProjectProblem as n, findServerWorkspace as o, detectIsExpo as r, isPackageResolvable as s, NO_PROJECT_REFUSAL as t, readAppConfigText as u };
@@ -1,12 +1,14 @@
1
1
  import { B as deviceSlotPlatforms, V as parseDeviceSlotKey, p as getProject } from "./config-0jCcMM0E.mjs";
2
- import { h as recordWorkspaceUse, s as resolveProjectMetro } from "./metro-Dzo30hvJ.mjs";
3
- import { i as findProjectRoot } from "./project-B8rbutVC.mjs";
4
- import { f as readWorkspaceLaunches } from "./state-DcDgzfu3.mjs";
5
- import { f as refuseNoProject, l as phaseLine } from "./command-output-BWCj5Vh-.mjs";
6
- import { W as resolveOwnedAvdSerial } from "./android-75Sk2rIR.mjs";
7
- import { S as resolveOwnedIosSim } from "./ios-CZWOHTTc.mjs";
8
- import { h as iosAppProcess, o as androidAppProcess } from "./app-install-CsZi0SAT.mjs";
9
- import { n as nativeRunCommand } from "./slot-launch-DIACGEfH.mjs";
2
+ import { c as resolveProjectMetro, g as recordWorkspaceUse } from "./metro-BPeY1YMh.mjs";
3
+ import { i as findCommandWorkspace } from "./project-DGeclhvO.mjs";
4
+ import { f as readWorkspaceLaunches } from "./state-DwAU2_-D.mjs";
5
+ import { f as refuseNoProject, l as phaseLine } from "./command-output-BIL7rlX7.mjs";
6
+ import { q as resolveOwnedAvdSerial } from "./android-qx_31wJo.mjs";
7
+ import { a as readWebRecord, l as webFacts, r as cdpEndpoint } from "./state-l1pYwOre.mjs";
8
+ import { S as resolveOwnedIosSim } from "./ios-CmEzZiOj.mjs";
9
+ import { h as iosAppProcess, o as androidAppProcess } from "./app-install-CDFY2nUL.mjs";
10
+ import { n as nativeRunCommand } from "./slot-launch-BIWEW-wI.mjs";
11
+ import { n as sendToOwnedPage, t as liveWebRecord } from "./page-BTu7I60K.mjs";
10
12
  import chalk from "chalk";
11
13
  import { WebSocket } from "ws";
12
14
  //#region src/engine/reload.ts
@@ -115,7 +117,7 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
115
117
  //#endregion
116
118
  //#region src/commands/reload.ts
117
119
  const DEFAULT_DEPS = {
118
- findProjectRoot,
120
+ findWorkspace: findCommandWorkspace,
119
121
  getProject,
120
122
  readLaunches: readWorkspaceLaunches,
121
123
  resolveIos: resolveOwnedIosSim,
@@ -123,7 +125,12 @@ const DEFAULT_DEPS = {
123
125
  iosProcess: iosAppProcess,
124
126
  androidProcess: androidAppProcess,
125
127
  resolveMetro: resolveProjectMetro,
126
- reloadMetro: reloadThroughMetro
128
+ reloadMetro: reloadThroughMetro,
129
+ readBrowser: (root) => {
130
+ const facts = webFacts(readWebRecord(root));
131
+ return facts?.status === "unverified" ? "unverified" : liveWebRecord(facts?.record ?? null);
132
+ },
133
+ reloadPage: (record) => sendToOwnedPage(record, "Page.reload")
127
134
  };
128
135
  function failure(code, message, remedy) {
129
136
  return {
@@ -135,6 +142,28 @@ function failure(code, message, remedy) {
135
142
  function describe(error) {
136
143
  return error instanceof Error ? error.message : String(error);
137
144
  }
145
+ async function reloadBrowser(browser, metroPort, d) {
146
+ try {
147
+ await d.reloadPage(browser);
148
+ } catch (error) {
149
+ return {
150
+ ok: false,
151
+ error: failure("STIM_RELOAD_FAILED", `The owned Chrome did not accept the reload: ${describe(error)}`, "Run `stim web` to reopen the page.")
152
+ };
153
+ }
154
+ return {
155
+ ok: true,
156
+ facts: {
157
+ platform: "web",
158
+ deviceId: cdpEndpoint(browser.cdpPort),
159
+ deviceName: browser.version ?? "Chrome",
160
+ appId: browser.url,
161
+ metroPort: metroPort !== null && new URL(browser.url).port === String(metroPort) ? metroPort : null,
162
+ strategy: "cdp",
163
+ targets: 1
164
+ }
165
+ };
166
+ }
138
167
  function processFailure(platform, record, d, slot = "default") {
139
168
  const process = platform === "ios" ? d.iosProcess(record.deviceId, record.appId) : d.androidProcess(record.deviceId, record.appId);
140
169
  if (process === void 0) {
@@ -220,6 +249,16 @@ async function runReload({ root, platform = null, deps = {} }) {
220
249
  ok: false,
221
250
  error: failure("STIM_NO_PROJECT", `No Stim environment is registered for ${root}.`, "Run `stim start` first.")
222
251
  };
252
+ const read = platform === null || platform === "web" ? d.readBrowser(root) : null;
253
+ if (platform === "web" && read === "unverified") return {
254
+ ok: false,
255
+ error: failure("STIM_RELOAD_PROBE_FAILED", "Stim could not verify the owned Chrome's supervisor or Chrome process.", "Run `stim status`, then follow `stim guide errors teardown`.")
256
+ };
257
+ const browser = read === "unverified" ? null : read;
258
+ if (platform === "web") return browser ? reloadBrowser(browser, project.metroPort ?? null, d) : {
259
+ ok: false,
260
+ error: failure("STIM_RELOAD_STOPPED", "No owned Chrome is running for this workspace.", "Run `stim web` first.")
261
+ };
223
262
  const launches = d.readLaunches(root);
224
263
  const inspected = Object.entries(launches).flatMap(([key, record]) => {
225
264
  const parsed = parseDeviceSlotKey(key);
@@ -230,14 +269,30 @@ async function runReload({ root, platform = null, deps = {} }) {
230
269
  }, d, parsed.slot)];
231
270
  });
232
271
  const live = inspected.filter((target) => !isTargetFailure(target));
233
- if (new Set(live.map((target) => target.platform)).size > 1) return {
234
- ok: false,
235
- error: failure("STIM_RELOAD_AMBIGUOUS", "Both the iOS and Android apps are running.", "Choose one with `stim reload ios` or `stim reload android`.")
236
- };
237
- if (live.length === 0) return {
272
+ const livePlatforms = new Set(live.map((target) => target.platform));
273
+ if (browser) livePlatforms.add("web");
274
+ if (livePlatforms.size > 1) {
275
+ const names = [...livePlatforms];
276
+ return {
277
+ ok: false,
278
+ error: failure("STIM_RELOAD_AMBIGUOUS", `More than one platform is live: ${names.join(", ")}.`, `Choose one with ${names.map((name) => `\`stim reload ${name}\``).join(" or ")}.`)
279
+ };
280
+ }
281
+ if (browser && inspected.length === 0) return reloadBrowser(browser, project.metroPort ?? null, d);
282
+ if (read === "unverified" && inspected.length === 0) return {
238
283
  ok: false,
239
- error: inspected.find(isTargetFailure)?.error ?? failure("STIM_RELOAD_STOPPED", platform ? `No ${platform} app launch is recorded for this workspace.` : "No live app launch is recorded.", platform ? `Run \`stim ${platform}\` first.` : "Run `stim ios` or `stim android` first.")
284
+ error: failure("STIM_RELOAD_PROBE_FAILED", "Stim could not verify the owned Chrome's supervisor or Chrome process.", "Run `stim status`, then follow `stim guide errors teardown`.")
240
285
  };
286
+ if (live.length === 0) {
287
+ const nativeFailure = inspected.find(isTargetFailure)?.error;
288
+ return {
289
+ ok: false,
290
+ error: (nativeFailure && browser ? {
291
+ ...nativeFailure,
292
+ remedy: `${nativeFailure.remedy ?? ""} To reload the owned Chrome page instead, run \`stim reload web\`.`.trim()
293
+ } : nativeFailure) ?? failure("STIM_RELOAD_STOPPED", platform ? `No ${platform} app launch is recorded for this workspace.` : "No live app launch is recorded.", platform ? `Run \`stim ${platform}\` first.` : "Run `stim ios` or `stim android` first.")
294
+ };
295
+ }
241
296
  const target = live.find((candidate) => !candidate.record.release && candidate.record.metroPort === project.metroPort) ?? live[0];
242
297
  if (target.record.release) return {
243
298
  ok: false,
@@ -292,9 +347,9 @@ async function runReload({ root, platform = null, deps = {} }) {
292
347
  };
293
348
  }
294
349
  function registerReload(program, deps = {}) {
295
- program.command("reload [platform]").description("Request a JavaScript reload in this workspace's live app without observing completion. Specify ios or android when both are live.").option("--json", "Emit the reload facts as one JSON line").action(async (value, opts) => {
296
- if (value !== void 0 && value !== "ios" && value !== "android") {
297
- const error = failure("STIM_BAD_ARG", `Unknown reload platform ${JSON.stringify(value)}.`, "Use ios or android.");
350
+ program.command("reload [platform]").description("Request a JavaScript reload in this workspace's live app, or reload its owned Chrome page, without observing completion. Specify ios, android or web when more than one is live.").option("--json", "Emit the reload facts as one JSON line").action(async (value, opts) => {
351
+ if (value !== void 0 && value !== "ios" && value !== "android" && value !== "web") {
352
+ const error = failure("STIM_BAD_ARG", `Unknown reload platform ${JSON.stringify(value)}.`, "Use ios, android or web.");
298
353
  if (opts.json) console.log(JSON.stringify(error));
299
354
  else {
300
355
  console.error(chalk.red(phaseLine("error", `${error.code}: ${error.message}`)));
@@ -303,7 +358,7 @@ function registerReload(program, deps = {}) {
303
358
  process.exitCode = 1;
304
359
  return;
305
360
  }
306
- const root = (deps.findProjectRoot ?? DEFAULT_DEPS.findProjectRoot)(process.cwd());
361
+ const root = (deps.findWorkspace ?? DEFAULT_DEPS.findWorkspace)(process.cwd());
307
362
  if (!root) {
308
363
  refuseNoProject({ json: Boolean(opts.json) });
309
364
  return;
@@ -326,6 +381,10 @@ function registerReload(program, deps = {}) {
326
381
  if (opts.json) console.log(JSON.stringify(result.facts));
327
382
  else {
328
383
  const facts = result.facts;
384
+ if (facts.strategy === "cdp") {
385
+ console.log(`Reload requested for ${facts.appId} in the owned Chrome (DevTools ${facts.deviceId}). Completion is not observed; run stim logs --errors.`);
386
+ return;
387
+ }
329
388
  const scope = facts.strategy === "metro-broadcast" ? ` This Metro cannot name its connected apps, so the reload request was broadcast to all of them and Stim cannot confirm ${facts.appId} was one. Check the expected UI on ${facts.deviceId}; if nothing changed, reload from the app's own error screen or dev menu.` : facts.targets && facts.targets > 1 ? ` ${facts.targets} devices are running this app on that Metro and the reload request addressed all of them, not only ${facts.deviceId}.` : "";
330
389
  console.log(`Reload requested for ${facts.appId} on ${facts.deviceName} (${facts.deviceId}) via ${facts.strategy}; ${facts.platform} Metro port ${facts.metroPort}.${scope} Completion is not observed; verify the expected UI and run stim logs --errors.`);
331
390
  }
@@ -1,9 +1,9 @@
1
1
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
2
  import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
3
- import { j as workspaceLogsDir } from "./metro-Dzo30hvJ.mjs";
4
- import { u as resolvePackageJson } from "./project-B8rbutVC.mjs";
3
+ import { M as workspaceLogsDir } from "./metro-BPeY1YMh.mjs";
4
+ import { f as resolvePackageJson } from "./project-DGeclhvO.mjs";
5
5
  import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
6
- import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-CeT1nIIk.mjs";
6
+ import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-DUCg52-K.mjs";
7
7
  import { createRequire } from "node:module";
8
8
  import { existsSync, readFileSync } from "node:fs";
9
9
  import { join } from "node:path";
@@ -1,6 +1,6 @@
1
1
  import { i as __require, t as __commonJSMin } from "./rolldown-runtime-BsOwBuO_.mjs";
2
2
  import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
3
- import { w as projectMetroSharedCache } from "./settings-BlyDn2Oz.mjs";
3
+ import { w as projectMetroSharedCache } from "./settings-xB0Frkg6.mjs";
4
4
  import { a as metroStoreRoot, o as registerMetroStore, t as appendCacheStore } from "./metro-store-DzeWkfqW.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { isAbsolute, join, relative, sep } from "node:path";
@@ -0,0 +1,2 @@
1
+ import { p as startExpoServer } from "./server-expo-DUCg52-K.mjs";
2
+ export { startExpoServer };
@@ -1,9 +1,9 @@
1
1
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
2
  import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
3
- import { u as resolvePackageJson } from "./project-B8rbutVC.mjs";
3
+ import { f as resolvePackageJson } from "./project-DGeclhvO.mjs";
4
4
  import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
5
5
  import { n as stripAnsi, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
6
- import { w as projectMetroSharedCache } from "./settings-BlyDn2Oz.mjs";
6
+ import { w as projectMetroSharedCache } from "./settings-xB0Frkg6.mjs";
7
7
  import { a as metroStoreRoot, i as metroStoreConfirmedRoot, n as expoMetroConfigPath, o as registerMetroStore, r as expoMetroStoreEnv } from "./metro-store-DzeWkfqW.mjs";
8
8
  import { accessSync, constants, existsSync, readFileSync } from "node:fs";
9
9
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
@@ -1,8 +1,8 @@
1
1
  import { D as writeConfigSetting, E as withConfigLock$1, _ as loadConfig$1, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-0jCcMM0E.mjs";
2
2
  import { s as gitCommonDir, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
3
- import { i as findProjectRoot, t as NO_PROJECT_REFUSAL } from "./project-B8rbutVC.mjs";
4
- import { n as stimDesktopInstalled, t as settingDefault } from "./stim-desktop-D0xhpZt8.mjs";
5
- import { D as readCommittedSettings, L as unknownSettingKeys } from "./settings-BlyDn2Oz.mjs";
3
+ import { i as findCommandWorkspace, t as NO_PROJECT_REFUSAL } from "./project-DGeclhvO.mjs";
4
+ import { n as settingDefault, r as stimDesktopInstalled } from "./stim-desktop-CXt8-Z3J.mjs";
5
+ import { D as readCommittedSettings, L as unknownSettingKeys } from "./settings-xB0Frkg6.mjs";
6
6
  import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
7
7
  import { SETTINGS, SETTING_SCOPES, coerceSettingText, isJsonObject, isSensitiveReference, settingDefinition, settingValueError } from "@stim-cli/core/state";
8
8
  import { join } from "node:path";
@@ -24,8 +24,8 @@ var Refusal = class extends Error {
24
24
  this.remedy = remedy;
25
25
  }
26
26
  };
27
- function readContext(env) {
28
- const projectPath = findProjectRoot(process.cwd());
27
+ function readContext(env, note = () => {}) {
28
+ const projectPath = findCommandWorkspace(process.cwd(), note);
29
29
  const start = projectPath ?? process.cwd();
30
30
  const common = gitCommonDir(start);
31
31
  let installed;
@@ -35,7 +35,7 @@ function readContext(env) {
35
35
  repoRoot: common ? repoRoot(start) ?? projectPath : null,
36
36
  machine: loadConfig$1(),
37
37
  env,
38
- desktopInstalled: () => installed ??= stimDesktopInstalled()
38
+ desktopInstalled: () => installed ??= stimDesktopInstalled(process.platform, env)
39
39
  };
40
40
  }
41
41
  function valueAt(settings, key) {
@@ -306,7 +306,7 @@ function wantsJson(opts, command) {
306
306
  }
307
307
  function registerSettings(program, io = CONSOLE, env = process.env) {
308
308
  const settings = program.command("settings").description("Show every Stim setting with its effective value and layer, or change one").option("--json", "print every setting, its origin, and each layer value as JSON").action((opts) => run(Boolean(opts.json), io, () => {
309
- const payload = settingsPayload(readContext(env));
309
+ const payload = settingsPayload(readContext(env, io.note));
310
310
  if (opts.json) {
311
311
  io.out(JSON.stringify(payload));
312
312
  return;
@@ -321,7 +321,7 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
321
321
  settings.command("get <key>").description("Print the effective value of a setting, or its value in one layer").option("--scope <scope>", `read one layer: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting entry as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, () => {
322
322
  const setting = requireSetting(key);
323
323
  const scope = opts.scope === void 0 ? null : readScope(opts.scope, setting);
324
- const context = readContext(env);
324
+ const context = readContext(env, io.note);
325
325
  const entry = settingEntry(context, setting);
326
326
  const value = scope ? entry.layers[scope] ?? null : entry.value;
327
327
  if (wantsJson(opts, command)) {
@@ -342,7 +342,7 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
342
342
  const scope = readScope(opts.scope, setting);
343
343
  const value = parseSettingValue(setting, raw);
344
344
  if (setting.sensitive && scope === "committed" && !isSensitiveReference(value)) throw new Refusal("STIM_BAD_ARG", `${key} is sensitive, so a committed .stim.json takes only an env: or file: reference, never the secret.`, `Set the secret with --scope workspace or --scope repo, or commit a reference such as env:MY_KEYSTORE_PASSWORD.`);
345
- const context = readContext(env);
345
+ const context = readContext(env, io.note);
346
346
  const file = requireLayer(context, scope, setting);
347
347
  const changed = writeSetting(context, setting, scope, value);
348
348
  report(io, wantsJson(opts, command), {
@@ -355,7 +355,7 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
355
355
  settings.command("unset <key>").description("Remove a setting from one layer").option("--scope <scope>", `the layer to clear: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting after removal as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, () => {
356
356
  const setting = requireSetting(key);
357
357
  const scope = readScope(opts.scope, setting);
358
- const context = readContext(env);
358
+ const context = readContext(env, io.note);
359
359
  const file = requireLayer(context, scope, setting);
360
360
  const changed = writeSetting(context, setting, scope, void 0);
361
361
  report(io, wantsJson(opts, command), {
@@ -2,7 +2,7 @@ import { _ as loadConfig$1, f as getConfigPath$1, h as getRepoSettings, m as get
2
2
  import { s as gitCommonDir, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
3
3
  import { existsSync, readFileSync, realpathSync, statSync } from "fs";
4
4
  import { isAbsolute, join, relative, resolve, sep } from "path";
5
- import { ANDROID_COMPILER_CACHE_CHOICES, ANDROID_PCH_CHOICES, REMOTE_DEVICE_BACKENDS, SETTINGS, SETTING_GROUPS, TUNNEL_MODES, acceptsShape, expectedShape, isLayeredSetting, settingDefinition, settingValueError } from "@stim-cli/core/state";
5
+ import { ANDROID_COMPILER_CACHE_CHOICES, ANDROID_PCH_CHOICES, REMOTE_DEVICE_BACKENDS, SETTINGS, SETTING_GROUPS, TUNNEL_MODES, WEB_VIEWPORTS, acceptsShape, expectedShape, isLayeredSetting, settingDefinition, settingValueError } from "@stim-cli/core/state";
6
6
  import { isAbsolute as isAbsolute$1 } from "node:path";
7
7
  import { createHash } from "node:crypto";
8
8
  //#region src/optimizations.ts
@@ -616,5 +616,14 @@ function normalizedHttpsUrl(raw) {
616
616
  return null;
617
617
  }
618
618
  }
619
+ function webSettings(settings) {
620
+ const url = settingValueAt(settings, "web.url");
621
+ const viewport = settingValueAt(settings, "web.viewport");
622
+ return {
623
+ url: typeof url === "string" ? url : null,
624
+ ignoreCertificateErrors: settingValueAt(settings, "web.ignoreCertificateErrors") === true,
625
+ viewport: WEB_VIEWPORTS.includes(viewport) ? viewport : "desktop"
626
+ };
627
+ }
619
628
  //#endregion
620
- export { resolveCacheProviderConfig as A, planMetroReach as B, ngrokUrlSetting as C, readCommittedSettings as D, publicUrlSetting as E, settingsLayers as F, compilerCacheFallbackMessage as H, tunnelModeSetting as I, unknownSettingKeys as L, settingFile as M, settingOrigin as N, remoteAndroidSetting as O, settingShapeErrors as P, PUBLIC_METRO_ENV as R, metroWarmupUrlSetting as S, projectOptimizations as T, optimizationBuildProfile as U, artifactCachePolicy as V, resolveOptimizations as W, iosSigningIdentitySha1SettingError as _, SETTING_SHAPE_REMEDY as a, metroIdleStopMinutesSetting as b, androidDataPartitionSizeBytes as c, cacheProviderSettingError as d, iosLanHostSetting as f, iosSigningIdentitySha1Setting as g, iosSigningIdentitySettingError as h, SETTINGS_WITH_RESOLVE_TIME_FALLBACK as i, resolveSettings as j, remoteIosSetting as k, androidDataPartitionSizeGbSetting as l, iosSigningIdentitySetting as m, PATH_SETTINGS as n, androidAvdConfigSetting as o, iosLanHostSettingError as p, REMOTE_DEVICE_BACKENDS as r, androidAvdConfigSettingError as s, ANDROID_AVD_CONFIG_HELP as t, androidDataPartitionSizeGbSettingError as u, iosSimSlimProfileSetting as v, projectMetroSharedCache as w, metroTunnelSettingError as x, mergeSettingsLayers as y, detectProviders as z };
629
+ export { resolveCacheProviderConfig as A, detectProviders as B, ngrokUrlSetting as C, readCommittedSettings as D, publicUrlSetting as E, settingsLayers as F, resolveOptimizations as G, artifactCachePolicy as H, tunnelModeSetting as I, unknownSettingKeys as L, settingFile as M, settingOrigin as N, remoteAndroidSetting as O, settingShapeErrors as P, webSettings as R, metroWarmupUrlSetting as S, projectOptimizations as T, compilerCacheFallbackMessage as U, planMetroReach as V, optimizationBuildProfile as W, iosSigningIdentitySha1SettingError as _, SETTING_SHAPE_REMEDY as a, metroIdleStopMinutesSetting as b, androidDataPartitionSizeBytes as c, cacheProviderSettingError as d, iosLanHostSetting as f, iosSigningIdentitySha1Setting as g, iosSigningIdentitySettingError as h, SETTINGS_WITH_RESOLVE_TIME_FALLBACK as i, resolveSettings as j, remoteIosSetting as k, androidDataPartitionSizeGbSetting as l, iosSigningIdentitySetting as m, PATH_SETTINGS as n, androidAvdConfigSetting as o, iosLanHostSettingError as p, REMOTE_DEVICE_BACKENDS as r, androidAvdConfigSettingError as s, ANDROID_AVD_CONFIG_HELP as t, androidDataPartitionSizeGbSettingError as u, iosSimSlimProfileSetting as v, projectMetroSharedCache as w, metroTunnelSettingError as x, mergeSettingsLayers as y, PUBLIC_METRO_ENV as z };
@@ -582,6 +582,58 @@
582
582
  },
583
583
  "additionalProperties": false
584
584
  },
585
+ "web": {
586
+ "type": "object",
587
+ "properties": {
588
+ "url": {
589
+ "description": "Page `stim web` opens; unset opens the Metro URL for Expo web",
590
+ "type": "string",
591
+ "pattern": "^https?://",
592
+ "x-stim": {
593
+ "key": "web.url",
594
+ "kind": "string",
595
+ "scopes": [
596
+ "workspace",
597
+ "repo",
598
+ "committed"
599
+ ]
600
+ }
601
+ },
602
+ "ignoreCertificateErrors": {
603
+ "description": "Accept self-signed dev certificates in Stim's owned Chrome profile",
604
+ "type": "boolean",
605
+ "default": false,
606
+ "x-stim": {
607
+ "key": "web.ignoreCertificateErrors",
608
+ "kind": "boolean",
609
+ "scopes": [
610
+ "workspace",
611
+ "repo",
612
+ "committed"
613
+ ]
614
+ }
615
+ },
616
+ "viewport": {
617
+ "description": "Viewport of the owned Chrome page: desktop, or phone for a 390x844 touch screen",
618
+ "type": "string",
619
+ "enum": [
620
+ "desktop",
621
+ "phone"
622
+ ],
623
+ "default": "desktop",
624
+ "x-stim": {
625
+ "key": "web.viewport",
626
+ "kind": "choice",
627
+ "scopes": [
628
+ "workspace",
629
+ "repo",
630
+ "committed"
631
+ ]
632
+ }
633
+ }
634
+ },
635
+ "additionalProperties": false
636
+ },
585
637
  "worktree": {
586
638
  "type": "object",
587
639
  "properties": {
@@ -1034,7 +1086,7 @@
1034
1086
  "type": "object",
1035
1087
  "properties": {
1036
1088
  "worktreeGraceMinutes": {
1037
- "description": "Minutes after a linked worktree last changed, or its branch merged, before gc removes it; 0 removes it at once",
1089
+ "description": "Minutes after a linked worktree last changed, or its branch or pull request finished, before gc removes it; 0 removes it at once",
1038
1090
  "type": "integer",
1039
1091
  "minimum": 0,
1040
1092
  "default": 120,
@@ -1,11 +1,11 @@
1
1
  import { A as ownership_claim_exports, B as deviceSlotPlatforms, O as process_identity_exports, U as projectDeviceSlots, _ as loadConfig, d as getConfigDir } from "./config-0jCcMM0E.mjs";
2
2
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
3
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { g as releaseBuildLock, m as acquireBuildLock } from "./device-lease-B9LAXIUH.mjs";
5
- import { E as listAdbDevices } from "./android-75Sk2rIR.mjs";
6
- import { l as listAllIosSims, s as iosRuntimeMatches } from "./ios-CZWOHTTc.mjs";
7
- import { f as resolveEasCliBin } from "./remote-cache-BRsRZru5.mjs";
8
- import { O as easCliSupport, k as easCliUpgradeRemedy, s as readInstalledEasCliVersion } from "./device-remote-C0_o-tJH.mjs";
4
+ import { g as releaseBuildLock, m as acquireBuildLock } from "./device-lease-CL9dZf73.mjs";
5
+ import { D as listAdbDevices } from "./android-qx_31wJo.mjs";
6
+ import { g as parseRuntimeVersion, l as listAllIosSims, s as iosRuntimeMatches } from "./ios-CmEzZiOj.mjs";
7
+ import { f as resolveEasCliBin } from "./remote-cache--aehr4Pr.mjs";
8
+ import { O as easCliSupport, k as easCliUpgradeRemedy, s as readInstalledEasCliVersion } from "./device-remote-DT9ngZiD.mjs";
9
9
  import { existsSync, realpathSync, statSync } from "node:fs";
10
10
  import { join } from "node:path";
11
11
  import { createHash } from "node:crypto";
@@ -305,6 +305,12 @@ function deviceTypeMismatch(recordedTypeId, requestedName, deviceTypes) {
305
305
  const recorded = (deviceTypes || []).find((d) => d.identifier === recordedTypeId);
306
306
  return `this project's sim is ${recorded ? recorded.name : recordedTypeId}, but --device-type asked for ${requestedName}`;
307
307
  }
308
+ function runtimeMismatch(recordedRuntimeId, requested, runtimes) {
309
+ if (!requested || !recordedRuntimeId) return null;
310
+ const wanted = runtimes.find((r) => iosRuntimeMatches(r, requested));
311
+ if (!wanted || wanted.identifier === recordedRuntimeId) return null;
312
+ return `this project's sim runs iOS ${parseRuntimeVersion(recordedRuntimeId)}, but --runtime asked for ${requested}`;
313
+ }
308
314
  function installedNames(names) {
309
315
  const unique = [...new Set(names.filter((n) => typeof n === "string" && n !== ""))];
310
316
  return unique.length > 0 ? unique.join(", ") : "none";
@@ -489,4 +495,4 @@ function simslimIsOnPath() {
489
495
  }
490
496
  }
491
497
  //#endregion
492
- export { liveOwnedDeviceCount as a, unknownIosDeviceTypeRefusal as c, easDeviceBuildRemedy as d, isEasBuildFailure as f, deviceTypeMismatch as i, unknownIosRuntimeRefusal as l, resolveEasDevelopmentBuild as m, simslimIsOnPath as n, unknownAndroidDeviceProfileRefusal as o, planEasDevelopmentBuild as p, checkDeviceCapacity as r, unknownAndroidSystemImageRefusal as s, reconcileSimSlim as t, MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION as u };
498
+ export { liveOwnedDeviceCount as a, unknownAndroidSystemImageRefusal as c, MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION as d, easDeviceBuildRemedy as f, resolveEasDevelopmentBuild as h, deviceTypeMismatch as i, unknownIosDeviceTypeRefusal as l, planEasDevelopmentBuild as m, simslimIsOnPath as n, runtimeMismatch as o, isEasBuildFailure as p, checkDeviceCapacity as r, unknownAndroidDeviceProfileRefusal as s, reconcileSimSlim as t, unknownIosRuntimeRefusal as u };
@@ -1,7 +1,7 @@
1
1
  import { p as getProject } from "./config-0jCcMM0E.mjs";
2
- import { m as readWorkspaceState } from "./metro-Dzo30hvJ.mjs";
3
- import { n as fileLeaseIo } from "./device-lease-B9LAXIUH.mjs";
4
- import { d as deviceShellArg } from "./app-install-CsZi0SAT.mjs";
2
+ import { h as readWorkspaceState } from "./metro-BPeY1YMh.mjs";
3
+ import { n as fileLeaseIo } from "./device-lease-CL9dZf73.mjs";
4
+ import { d as deviceShellArg } from "./app-install-CDFY2nUL.mjs";
5
5
  //#region src/engine/slot-launch.ts
6
6
  function launchSlotScope(root, slot = "default") {
7
7
  if (slot !== "default") return slot;
@@ -1,17 +1,17 @@
1
1
  import { O as process_identity_exports, T as upsertProject, p as getProject } from "./config-0jCcMM0E.mjs";
2
2
  import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
3
3
  import { i as levelRank } from "./ndjson-CDY9IkVC.mjs";
4
- import { T as supervisorLogFile, c as signalProcessTree, d as reserveMetroPort, h as recordWorkspaceUse, i as pidExists, j as workspaceLogsDir, m as readWorkspaceState$1, p as clearWorkspaceStateKeys, s as resolveProjectMetro, x as ensureWorkspaceStorage, y as writeWorkspaceState } from "./metro-Dzo30hvJ.mjs";
4
+ import { E as supervisorLogFile, M as workspaceLogsDir, S as ensureWorkspaceStorage, a as pidExists, b as writeWorkspaceState, c as resolveProjectMetro, f as reserveMetroPort, g as recordWorkspaceUse, h as readWorkspaceState$1, l as signalProcessTree, m as clearWorkspaceStateKeys } from "./metro-BPeY1YMh.mjs";
5
5
  import { s as gitCommonDir, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
6
- import { c as readAppConfigText, i as findProjectRoot, l as readAppJson, n as appProjectProblem, r as detectIsExpo, t as NO_PROJECT_REFUSAL } from "./project-B8rbutVC.mjs";
6
+ import { a as findProjectRoot, d as readAppJson, n as appProjectProblem, r as detectIsExpo, t as NO_PROJECT_REFUSAL, u as readAppConfigText } from "./project-DGeclhvO.mjs";
7
7
  import { n as windowsLauncherArgs } from "./detached-entry-DJHoca49.mjs";
8
- import { c as readMetroTunnel, i as clearManagedMetroTunnel } from "./state-DcDgzfu3.mjs";
9
- import { n as workspaceProcessLockError, t as withWorkspaceProcessLock } from "./workspace-process-lock-BvvJTfo_.mjs";
10
- import { _ as stepTimer, l as phaseLine } from "./command-output-BWCj5Vh-.mjs";
11
- import { A as resolveCacheProviderConfig, B as planMetroReach, C as ngrokUrlSetting, E as publicUrlSetting, I as tunnelModeSetting, L as unknownSettingKeys, O as remoteAndroidSetting, P as settingShapeErrors, R as PUBLIC_METRO_ENV, a as SETTING_SHAPE_REMEDY, b as metroIdleStopMinutesSetting, d as cacheProviderSettingError, j as resolveSettings, k as remoteIosSetting, x as metroTunnelSettingError, z as detectProviders } from "./settings-BlyDn2Oz.mjs";
12
- import { a as terminateChild, c as withManagedTunnelLock, i as stopTunnel, o as withManagedRemoteWorktreeLock, r as startTunnelSequence, t as resolveSupervisorTarget } from "./ownership-B8d4kXBx.mjs";
13
- import { d as readProjectConfig } from "./remote-cache-BRsRZru5.mjs";
14
- import { I as stopOwnedMetroForReset, t as budgetGate } from "./budget-DbzW5VTD.mjs";
8
+ import { c as readMetroTunnel, i as clearManagedMetroTunnel } from "./state-DwAU2_-D.mjs";
9
+ import { a as withWorkspaceProcessLock, o as workspaceProcessLockError } from "./named-ports-n7tnJsI8.mjs";
10
+ import { _ as stepTimer, l as phaseLine } from "./command-output-BIL7rlX7.mjs";
11
+ import { A as resolveCacheProviderConfig, B as detectProviders, C as ngrokUrlSetting, E as publicUrlSetting, I as tunnelModeSetting, L as unknownSettingKeys, O as remoteAndroidSetting, P as settingShapeErrors, V as planMetroReach, a as SETTING_SHAPE_REMEDY, b as metroIdleStopMinutesSetting, d as cacheProviderSettingError, j as resolveSettings, k as remoteIosSetting, x as metroTunnelSettingError, z as PUBLIC_METRO_ENV } from "./settings-xB0Frkg6.mjs";
12
+ import { a as terminateChild, c as withManagedTunnelLock, i as stopTunnel, o as withManagedRemoteWorktreeLock, r as startTunnelSequence, t as resolveSupervisorTarget } from "./ownership-PUP4Dwai.mjs";
13
+ import { d as readProjectConfig } from "./remote-cache--aehr4Pr.mjs";
14
+ import { I as stopOwnedMetroForReset, t as budgetGate } from "./budget-E5o91NR1.mjs";
15
15
  import { appendFileSync, mkdirSync, openSync, readFileSync } from "node:fs";
16
16
  import { existsSync as existsSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1 } from "fs";
17
17
  import { join } from "path";
@@ -111,7 +111,8 @@ function detectAndroidPackageFromGradle(projectRoot) {
111
111
  //#region src/spawn-entry.ts
112
112
  const DEV_ENTRIES = {
113
113
  "supervisor-run": "./supervisor/run.ts",
114
- "collector-run": "./collector/run.ts"
114
+ "collector-run": "./collector/run.ts",
115
+ "web-run": "./web/run.ts"
115
116
  };
116
117
  function spawnEntry(name) {
117
118
  const here = fileURLToPath(import.meta.url);
@@ -1,2 +1,2 @@
1
- import { a as registerStart, c as startFacts, d as wantsExpoOwnTunnel, i as readLogTail, l as supervisorEntry, n as liveSupervisor, o as startCommand, r as parseWait, s as startDevServer, t as failureEvidence, u as tailLines } from "./start-BboE1HIS.mjs";
1
+ import { a as registerStart, c as startFacts, d as wantsExpoOwnTunnel, i as readLogTail, l as supervisorEntry, n as liveSupervisor, o as startCommand, r as parseWait, s as startDevServer, t as failureEvidence, u as tailLines } from "./start-BZhItkiL.mjs";
2
2
  export { startCommand as default, failureEvidence, liveSupervisor, parseWait, readLogTail, registerStart, startDevServer, startFacts, supervisorEntry, tailLines, wantsExpoOwnTunnel };
@@ -1,5 +1,5 @@
1
1
  import { O as process_identity_exports, V as parseDeviceSlotKey, z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
2
- import { E as supervisorPidFile, N as workspaceStateFile, _ as withWorkspaceStateLock, f as clearWorkspaceStateKey, g as updateWorkspaceState, m as readWorkspaceState } from "./metro-Dzo30hvJ.mjs";
2
+ import { D as supervisorPidFile, P as workspaceStateFile, _ as updateWorkspaceState, h as readWorkspaceState, p as clearWorkspaceStateKey, v as withWorkspaceStateLock } from "./metro-BPeY1YMh.mjs";
3
3
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { dirname } from "node:path";
5
5
  //#region src/supervisor/state.ts