stim 1.15.0 → 1.16.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 (117) hide show
  1. package/dist/{activity-B2-kb7k0.mjs → activity-BxwdD81S.mjs} +29 -16
  2. package/dist/agent-device-usage-output-Dpih1Tfa.mjs +411 -0
  3. package/dist/{android-Db2eEMaf.mjs → android-B_NumVyQ.mjs} +21 -20
  4. package/dist/{android-Cu_L4RpL.mjs → android-Ift4kVvt.mjs} +56 -47
  5. package/dist/{android-cas-PnKfAdB2.mjs → android-cas-8U4DPqeR.mjs} +1 -1
  6. package/dist/{android-CYmq0jNi.mjs → android-r2rBL8kV.mjs} +1 -1
  7. package/dist/{app-install-CAAplXAt.mjs → app-install-CKWdbXIX.mjs} +48 -5
  8. package/dist/attempt-Bk2ouQVL.mjs +39 -0
  9. package/dist/{budget-CMiqghig.mjs → budget-DjrURfQn.mjs} +356 -366
  10. package/dist/{build-plan-aeGMFX7e.mjs → build-plan-DjeSb2Xl.mjs} +19 -20
  11. package/dist/{build-slots-Df1ApSuH.mjs → build-slots-rUk77xqh.mjs} +7 -2
  12. package/dist/{cli-0cX5s4NM.mjs → cli-BkYZ_6hy.mjs} +23 -17
  13. package/dist/cli.mjs +1 -1
  14. package/dist/{client-C2IS36Qf.mjs → client-BTY686R6.mjs} +57 -22
  15. package/dist/collector-run.mjs +5 -192
  16. package/dist/{command-output-CliHHn7a.mjs → command-output-DnJMdEY-.mjs} +1 -1
  17. package/dist/{created-devices-BwVb3liH.mjs → created-devices-D5owjN4C.mjs} +1 -1
  18. package/dist/{dependency-state-BmsjKZ2H.mjs → dependency-state-B6cMXZab.mjs} +1 -1
  19. package/dist/{deps-BFlKbOIp.mjs → deps-urbmfXig.mjs} +2 -2
  20. package/dist/{dev-client-CjzLoNs0.mjs → dev-client-CroAIjjj.mjs} +3 -40
  21. package/dist/{device-BZ1IyS5A.mjs → device-DZQjF7H5.mjs} +7 -6
  22. package/dist/{device-capacity-DMuKC7nx.mjs → device-capacity-BHwxNBlu.mjs} +2 -2
  23. package/dist/device-host-worker.mjs +223 -28
  24. package/dist/{device-ios-DMQBUPus.mjs → device-ios-BadmeL2V.mjs} +7 -7
  25. package/dist/{device-lease-W5Pi1q38.mjs → device-lease-D-hLqx1b.mjs} +2 -2
  26. package/dist/{device-pool-B2r38YjS.mjs → device-lease-run-CqjShqWW.mjs} +5 -125
  27. package/dist/device-pool-CUaEWMMm.mjs +125 -0
  28. package/dist/{device-remote-9ulPsdhY.mjs → device-remote-D5WVWqOq.mjs} +12 -12
  29. package/dist/{doctor-BcE5xsBn.mjs → doctor-Cimf-gGB.mjs} +80 -34
  30. package/dist/{error-diagnostics-Cb0P1WLS.mjs → error-diagnostics-B9L4Ae0x.mjs} +11 -15
  31. package/dist/{gc-BuL1Genr.mjs → gc-Bqy4bjEu.mjs} +194 -31
  32. package/dist/{gradle-CmdOBq1d.mjs → gradle-BsO1MdsH.mjs} +4 -4
  33. package/dist/{guide-cCSGRFd3.mjs → guide-B_uyKTxW.mjs} +588 -53
  34. package/dist/{guide-status-CIoWK6mG.mjs → guide-status-CjEZMAD4.mjs} +1 -1
  35. package/dist/hosted-client-a-WmqE2L.mjs +197 -0
  36. package/dist/hosted-ios-CIWelIqf.mjs +220 -0
  37. package/dist/hosted-logs-D5g041Q3.mjs +187 -0
  38. package/dist/hosted-macos-BSZyIb3y.mjs +135 -0
  39. package/dist/{build-progress-C2Jv1AtA.mjs → idle-DYVymG92.mjs} +233 -6
  40. package/dist/{idle-shutdown-B5LPaNyY.mjs → idle-shutdown-CTsDnAde.mjs} +6 -6
  41. package/dist/{in-use-CndPMilN.mjs → in-use-DvBw0Kxo.mjs} +29 -9
  42. package/dist/{ios-3CtCRhwr.mjs → ios-BaInn3sW.mjs} +2 -2
  43. package/dist/ios-Cr1h5gnO.mjs +189 -0
  44. package/dist/{ios-Chob8ny7.mjs → ios-aq3QoGI3.mjs} +729 -452
  45. package/dist/{ios-device-DERmMmk-.mjs → ios-device-FfCN_C8p.mjs} +1 -1
  46. package/dist/ios-state-DS5UpYTH.mjs +48 -0
  47. package/dist/{launch-verify-CLlofxRt.mjs → launch-verify-2DBRizjo.mjs} +3 -3
  48. package/dist/logs-CHEVK8zD.mjs +371 -0
  49. package/dist/{machines-CYtOCqcj.mjs → machines-BIBUdhpj.mjs} +16 -10
  50. package/dist/{macos-BwtbUtTN.mjs → macos-CSYEAFmF.mjs} +22 -17
  51. package/dist/macos-run.mjs +1 -1
  52. package/dist/maintenance-run.d.mts +4 -0
  53. package/dist/maintenance-run.mjs +254 -0
  54. package/dist/{metro-Di8EN2Tb.mjs → metro-BeK1ZPz1.mjs} +1 -1
  55. package/dist/metro-gateway-BJ-rxQAB.mjs +84 -0
  56. package/dist/{named-ports-Dj_XBNaL.mjs → named-ports-Bk_YXEmE.mjs} +1 -1
  57. package/dist/{native-run-DFDoIRbY.mjs → native-run-NaBrRFtQ.mjs} +2 -2
  58. package/dist/{native-runtime-i6OkVg-w.mjs → native-runtime-DBzRnEKS.mjs} +6 -6
  59. package/dist/{ndjson-CDY9IkVC.mjs → ndjson-PclOIwVY.mjs} +2 -2
  60. package/dist/offload-worker.d.mts +1 -0
  61. package/dist/offload-worker.mjs +13 -8
  62. package/dist/{ownership-BkYxUtuj.mjs → ownership-DiA16AsN.mjs} +2 -2
  63. package/dist/{stop-cause-CZ_Mr-v9.mjs → ownership-hCkPzGmr.mjs} +4 -98
  64. package/dist/{ports-DddwttKM.mjs → ports-R2k4Knz3.mjs} +2 -2
  65. package/dist/{prebuild-BvxDlD6C.mjs → prebuild-D2fsca_Z.mjs} +4 -4
  66. package/dist/preview-DhVbvPAZ.mjs +318 -0
  67. package/dist/{project-CV3tDFHl.mjs → project-Du91Ilvc.mjs} +67 -3
  68. package/dist/{recordings-GEXp4iBT.mjs → recordings-BIXOzVnr.mjs} +1 -1
  69. package/dist/{reload-ChPiwvot.mjs → reload-rM9jV1fz.mjs} +49 -12
  70. package/dist/{remote-cache-CO2elm_b.mjs → remote-cache-C8-V13XN.mjs} +4 -4
  71. package/dist/{run-B-xqRrsg.mjs → run-f4vI6EnK.mjs} +2 -2
  72. package/dist/{server-bare-X7PUgizL.mjs → server-bare-CpPGmnmO.mjs} +1 -1
  73. package/dist/server-expo-CVqO2c35.mjs +2 -0
  74. package/dist/{server-expo-DhtX6bom.mjs → server-expo-MC0rHlOC.mjs} +4 -4
  75. package/dist/settings-BBpMcDbD.mjs +25 -0
  76. package/dist/{settings-DbL6uhH8.mjs → settings-ZkDzkzvB.mjs} +10 -4
  77. package/dist/settings-oTSkkNrM.mjs +1439 -0
  78. package/dist/settings.schema.json +432 -39
  79. package/dist/{simslim-Ciluxlq4.mjs → simslim-B8-7AoTI.mjs} +3 -3
  80. package/dist/{slot-launch-BY0BrOLh.mjs → slot-launch-B8VrHxn1.mjs} +10 -7
  81. package/dist/{spawn-entry-DncpJvWL.mjs → spawn-entry-jw19m8Nl.mjs} +1 -0
  82. package/dist/{start-CPO4wRg7.mjs → start-CX8Ig-U2.mjs} +1 -1
  83. package/dist/{start-CUD9nasA.mjs → start-ClDfwXa4.mjs} +21 -17
  84. package/dist/{state-BxCgeTQu.mjs → state-3DwSQIBK.mjs} +2 -2
  85. package/dist/{state-DFm77wRn.mjs → state-C1jB7Q8q.mjs} +5 -5
  86. package/dist/{state-CaeaHbDA.mjs → state-DcW6vOd_.mjs} +1 -1
  87. package/dist/{stats-DBLLFmKd.mjs → stats-CEZ_i5je.mjs} +16 -5
  88. package/dist/{status-l84Gbvp2.mjs → status-BuvBFeII.mjs} +5 -3
  89. package/dist/{status-DYXxNOT0.mjs → status-Cs7VLg9D.mjs} +148 -44
  90. package/dist/status-DlKvVJBE.mjs +49 -0
  91. package/dist/{stop-Bvf1MflS.mjs → stop-B0Yxtmiy.mjs} +3 -3
  92. package/dist/{stop-Bad61z_2.mjs → stop-Bffozsac.mjs} +61 -20
  93. package/dist/{stop-CceYh1yG.mjs → stop-Dt_dM16A.mjs} +2 -2
  94. package/dist/stop-cause-CidxIqup.mjs +97 -0
  95. package/dist/supervisor-run.mjs +148 -17
  96. package/dist/{support-CDQbDkL5.mjs → support-CAP8qDUF.mjs} +4 -3
  97. package/dist/{support-WLOzVKUv.mjs → support-D4aYJniO.mjs} +34 -9
  98. package/dist/{teardown-BYuQafiA.mjs → teardown-CL6vDs2Y.mjs} +56 -47
  99. package/dist/{toolchain-DmeYjXD9.mjs → toolchain-DkUflduf.mjs} +10 -10
  100. package/dist/trigger-Bemu8ytw.mjs +65 -0
  101. package/dist/trigger-CXts6qt1.mjs +2 -0
  102. package/dist/{warm-progress-DVHLN4uC.mjs → warm-progress-CpGv3Wb6.mjs} +274 -5
  103. package/dist/{web-k6w8-HnE.mjs → web-DWUaMp8P.mjs} +15 -16
  104. package/dist/web-run.mjs +5 -5
  105. package/dist/{workspace-state-CL2V2Ons.mjs → workspace-state-B8-aJ1_5.mjs} +33 -33
  106. package/dist/workspaces-BV4pdHFz.mjs +306 -0
  107. package/dist/{worktree-qXKzADSC.mjs → worktree-K-xj9Db0.mjs} +497 -30
  108. package/dist/{worktree-BT_uULFx.mjs → worktree-jnG8Iph5.mjs} +1 -1
  109. package/package.json +5 -5
  110. package/dist/hosted-macos-DwowNU7W.mjs +0 -447
  111. package/dist/logs-h9h6MUvE.mjs +0 -568
  112. package/dist/machine-usage-D_YYMzfR.mjs +0 -283
  113. package/dist/merge-state-BnxLNQiM.mjs +0 -272
  114. package/dist/server-expo-KJeD109I.mjs +0 -2
  115. package/dist/settings-CduVcoxj.mjs +0 -680
  116. package/dist/watchman-Bx0wceoF.mjs +0 -238
  117. package/dist/worktree-C0c5Udwa.mjs +0 -753
@@ -1,25 +1,24 @@
1
1
  import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
2
  import { D as withConfigLock$1, H as projectDeviceSlots, _ as loadConfig$1, a as clearDevice, b as releaseAndroidConsolePort, i as clearAndroidBootPending, k as acquireAvdClaim, t as allConsolePortsAndSerials, w as setDevice, z as deviceSlotPlatforms } from "./config-D0DbpZtM.mjs";
3
- import { m as sharedBuildCache } from "./workspace-state-CL2V2Ons.mjs";
4
- import { D as makeTemporaryDirectory, O as removeTemporaryEntry, c as gitCommonDirOnDisk } from "./worktree-C0c5Udwa.mjs";
5
- import { c as ownedDeviceLabel } from "./project-CV3tDFHl.mjs";
6
3
  import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
7
- import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-CliHHn7a.mjs";
8
- import { C as diffFingerprintSources, I as storedSources, w as entryDir, y as artifactIn } from "./device-lease-W5Pi1q38.mjs";
9
- import { A as listAvds, B as ownedAvdSystemImage, E as getAvdNameForSerial, F as ownedAvdDeviceProfile, J as resolveOwnedAvdSerial, L as ownedAvdMatchesConfiguration, O as listAdbDevices, P as nextConsolePort, R as ownedAvdName, W as pickDefaultSystemImage, b as createOwnedAvd, dt as parkedMaxSetting, f as assertOwnedAvdStopped, ft as readParked, g as avdPoolConfiguration, j as listInstalledSystemImages, lt as isLegacyDeletionClaim, n as OWNED_AVD_CONFIG_DEFAULTS, ot as adoptParked, t as DEFAULT_AVD_DEVICE_PROFILE, tt as waitForBoot, v as bootAndroidEmulator, y as configureNewOwnedAvd } from "./android-Db2eEMaf.mjs";
10
- import { o as pidExists } from "./metro-Di8EN2Tb.mjs";
11
- import { l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting } from "./settings-CduVcoxj.mjs";
12
- import { i as teardownOwnedAvd, s as teardownParkedAvd } from "./teardown-BYuQafiA.mjs";
13
- import { j as readHostMemoryPressure, u as listAllIosSims } from "./ios-3CtCRhwr.mjs";
14
- import { o as estimateBuild, p as readStats } from "./build-progress-C2Jv1AtA.mjs";
15
- import { t as clearDeviceIdleShutdown } from "./idle-shutdown-B5LPaNyY.mjs";
16
- import { i as liveOwnedDeviceCount } from "./device-capacity-DMuKC7nx.mjs";
17
- import { b as tailLines, u as HEARTBEAT_INTERVAL_MS, y as startBuildHeartbeat } from "./toolchain-DmeYjXD9.mjs";
18
- import { t as cleanLine } from "./server-expo-DhtX6bom.mjs";
19
- import { i as staleNativeDirRefusal } from "./prebuild-BvxDlD6C.mjs";
20
- import { i as ensureOwnedIosDevice, r as ensureIosBooted } from "./device-ios-DMQBUPus.mjs";
21
- import { a as easAuthNote } from "./remote-cache-CO2elm_b.mjs";
22
- import { t as reconcileSimSlim } from "./simslim-Ciluxlq4.mjs";
4
+ import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-DnJMdEY-.mjs";
5
+ import { Tt as removeTemporaryEntry, at as gitCommonDirOnDisk, l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting, wt as makeTemporaryDirectory } from "./settings-oTSkkNrM.mjs";
6
+ import { l as ownedDeviceLabel } from "./project-Du91Ilvc.mjs";
7
+ import { o as pidExists } from "./metro-BeK1ZPz1.mjs";
8
+ import { d as sharedBuildCache } from "./workspace-state-B8-aJ1_5.mjs";
9
+ import { C as diffFingerprintSources, I as storedSources, w as entryDir, y as artifactIn } from "./device-lease-D-hLqx1b.mjs";
10
+ import { b as readStats$1, p as estimateBuild } from "./idle-DYVymG92.mjs";
11
+ import { A as listAvds, B as ownedAvdSystemImage, E as getAvdNameForSerial, F as ownedAvdDeviceProfile, J as resolveOwnedAvdSerial, L as ownedAvdMatchesConfiguration, O as listAdbDevices, P as nextConsolePort, R as ownedAvdName, W as pickDefaultSystemImage, b as createOwnedAvd, f as assertOwnedAvdStopped, ft as parkedMaxSetting, g as avdPoolConfiguration, j as listInstalledSystemImages, n as OWNED_AVD_CONFIG_DEFAULTS, pt as readParked, st as adoptParked, t as DEFAULT_AVD_DEVICE_PROFILE, tt as waitForBoot, ut as isLegacyDeletionClaim, v as bootAndroidEmulator, y as configureNewOwnedAvd } from "./android-B_NumVyQ.mjs";
12
+ import { j as readHostMemoryPressure, u as listAllIosSims } from "./ios-BaInn3sW.mjs";
13
+ import { i as teardownOwnedAvd, s as teardownParkedAvd } from "./teardown-CL6vDs2Y.mjs";
14
+ import { b as tailLines, u as HEARTBEAT_INTERVAL_MS, y as startBuildHeartbeat } from "./toolchain-DkUflduf.mjs";
15
+ import { t as cleanLine } from "./server-expo-MC0rHlOC.mjs";
16
+ import { t as clearDeviceIdleShutdown } from "./idle-shutdown-CTsDnAde.mjs";
17
+ import { i as liveOwnedDeviceCount } from "./device-capacity-BHwxNBlu.mjs";
18
+ import { i as staleNativeDirRefusal } from "./prebuild-D2fsca_Z.mjs";
19
+ import { i as ensureOwnedIosDevice, r as ensureIosBooted } from "./device-ios-BadmeL2V.mjs";
20
+ import { a as easAuthNote } from "./remote-cache-C8-V13XN.mjs";
21
+ import { t as reconcileSimSlim } from "./simslim-B8-7AoTI.mjs";
23
22
  import { randomUUID } from "node:crypto";
24
23
  import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
25
24
  import { basename, dirname, join, relative } from "node:path";
@@ -1467,7 +1466,7 @@ async function planCachedBuild(lookup, deps) {
1467
1466
  function planPayload({ platform, slot, projectKey }, found) {
1468
1467
  const { refusal, missReason, ...rest } = found;
1469
1468
  const outcome = refusal ? null : found.cacheHit ? "hit" : "cold";
1470
- const estimate = outcome ? estimateBuild(readStats().record?.history?.[projectKey], platform, outcome) : {
1469
+ const estimate = outcome ? estimateBuild(readStats$1().record?.history?.[projectKey], platform, outcome) : {
1471
1470
  expectedMs: null,
1472
1471
  basis: 0
1473
1472
  };
@@ -1,6 +1,6 @@
1
1
  import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
2
+ import { a as formatElapsed } from "./command-output-DnJMdEY-.mjs";
2
3
  import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-D0XfSe8u.mjs";
3
- import { a as formatElapsed } from "./command-output-CliHHn7a.mjs";
4
4
  import { readdirSync, statSync } from "node:fs";
5
5
  import { join } from "node:path";
6
6
  import { buildSlotsDir, tryAcquireBuildSlotClaim } from "@stim-cli/core/state";
@@ -60,13 +60,18 @@ async function acquireBuildSlot({ max, root = null, logFile = null, now = Date.n
60
60
  };
61
61
  const started = now();
62
62
  let lastProgress = started;
63
+ let waited = false;
63
64
  for (;;) {
64
65
  const got = tryAcquireBuildSlot({
65
66
  max,
66
67
  root,
67
68
  logFile
68
69
  });
69
- if (got) return got;
70
+ if (got) return {
71
+ ...got,
72
+ slotWaitMs: waited ? Math.max(0, Math.round(now() - started)) : 0
73
+ };
74
+ waited = true;
70
75
  const elapsed = now() - started;
71
76
  if (elapsed >= ceilingMs) {
72
77
  const err = /* @__PURE__ */ new Error(`Waited ${formatElapsed(elapsed)} for one of ${max} build slots, and every slot is held by a process that is still running, or by a holder Stim cannot identify. Slots live under ` + buildSlotsDir() + "; remove a slot directory whose builder is not really building, or raise concurrency.maxBuilds.");
@@ -3,23 +3,23 @@ import { readFileSync } from "node:fs";
3
3
  import { Command } from "commander";
4
4
  //#region bin/cli.ts
5
5
  const commands = /* @__PURE__ */ new Map([
6
- ["doctor", () => import("./doctor-BcE5xsBn.mjs")],
7
- ["worktree", () => import("./worktree-BT_uULFx.mjs")],
8
- ["start", () => import("./start-CPO4wRg7.mjs")],
9
- ["ports", () => import("./ports-DddwttKM.mjs")],
10
- ["stop", () => import("./stop-CceYh1yG.mjs")],
11
- ["ios", () => import("./ios-Chob8ny7.mjs")],
12
- ["android", () => import("./android-Cu_L4RpL.mjs")],
13
- ["web", () => import("./web-k6w8-HnE.mjs")],
14
- ["macos", () => import("./macos-BwtbUtTN.mjs")],
15
- ["reload", () => import("./reload-ChPiwvot.mjs")],
16
- ["device", () => import("./device-BZ1IyS5A.mjs")],
17
- ["logs", () => import("./logs-h9h6MUvE.mjs")],
18
- ["settings", () => import("./settings-DbL6uhH8.mjs")],
19
- ["status", () => import("./status-DYXxNOT0.mjs")],
20
- ["stats", () => import("./stats-DBLLFmKd.mjs")],
21
- ["gc", () => import("./gc-BuL1Genr.mjs")],
22
- ["guide", () => import("./guide-cCSGRFd3.mjs")]
6
+ ["doctor", () => import("./doctor-Cimf-gGB.mjs")],
7
+ ["worktree", () => import("./worktree-jnG8Iph5.mjs")],
8
+ ["start", () => import("./start-CX8Ig-U2.mjs")],
9
+ ["ports", () => import("./ports-R2k4Knz3.mjs")],
10
+ ["stop", () => import("./stop-Dt_dM16A.mjs")],
11
+ ["ios", () => import("./ios-aq3QoGI3.mjs")],
12
+ ["android", () => import("./android-Ift4kVvt.mjs")],
13
+ ["web", () => import("./web-DWUaMp8P.mjs")],
14
+ ["macos", () => import("./macos-CSYEAFmF.mjs")],
15
+ ["reload", () => import("./reload-rM9jV1fz.mjs")],
16
+ ["device", () => import("./device-DZQjF7H5.mjs")],
17
+ ["logs", () => import("./logs-CHEVK8zD.mjs")],
18
+ ["settings", () => import("./settings-ZkDzkzvB.mjs")],
19
+ ["status", () => import("./status-Cs7VLg9D.mjs")],
20
+ ["stats", () => import("./stats-CEZ_i5je.mjs")],
21
+ ["gc", () => import("./gc-Bqy4bjEu.mjs")],
22
+ ["guide", () => import("./guide-B_uyKTxW.mjs")]
23
23
  ]);
24
24
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
25
25
  const program = new Command();
@@ -33,6 +33,12 @@ try {
33
33
  const modules = await Promise.all([...commands.values()].map((load) => load()));
34
34
  for (const module of modules) module.default(program, pkg.version);
35
35
  }
36
+ program.hook("preAction", async (_command, action) => {
37
+ try {
38
+ const { triggerMaintenance } = await import("./trigger-CXts6qt1.mjs");
39
+ triggerMaintenance(action.name());
40
+ } catch {}
41
+ });
36
42
  await program.parseAsync();
37
43
  } catch (err) {
38
44
  const code = err?.code;
package/dist/cli.mjs CHANGED
@@ -4,6 +4,6 @@ const encode = (version) => version.split(".", 3).reduce((sum, part) => sum * 1e
4
4
  if (encode(process.versions.node) < encode("22.12.0")) {
5
5
  process.stderr.write(`STIM_NODE_UNSUPPORTED: Stim needs Node 22.12.0 or later; this is Node ${process.versions.node} at ${process.execPath}. To run Stim where a project pins an older Node, see https://stim.appandflow.com/docs/requirements#older-node-pins\n`);
6
6
  process.exitCode = 1;
7
- } else import("./cli-0cX5s4NM.mjs");
7
+ } else import("./cli-BkYZ_6hy.mjs");
8
8
  //#endregion
9
9
  export {};
@@ -1,14 +1,31 @@
1
1
  import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
2
  import { _ as loadConfig$1, d as getConfigDir } from "./config-D0DbpZtM.mjs";
3
- import { E as withDirLock } from "./workspace-state-CL2V2Ons.mjs";
4
- import { T as CCACHE_UNAVAILABLE, a as toolchainMismatches, l as COMPILATION_CACHE_UNAVAILABLE, s as manifestDigest } from "./toolchain-DmeYjXD9.mjs";
3
+ import { w as withDirLock } from "./workspace-state-B8-aJ1_5.mjs";
4
+ import { T as CCACHE_UNAVAILABLE, a as toolchainMismatches, l as COMPILATION_CACHE_UNAVAILABLE, s as manifestDigest } from "./toolchain-DkUflduf.mjs";
5
5
  import { createHash } from "node:crypto";
6
6
  import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync, writeSync } from "node:fs";
7
7
  import { basename, dirname, join, relative } from "node:path";
8
8
  import { InvalidArgumentError } from "commander";
9
- import { OFFLOAD_MODES, buildMachinesFile, buildMachinesLock, endpoint, findPeer, isJsonObject, parseMachine, parseMachine as parseMachine$1, pinnedEndpoint, readBuildMachines, saturation } from "@stim-cli/core/state";
9
+ import { OFFLOAD_MODES, buildMachinesFile, buildMachinesLock, endpoint, findPeer as findPeer$1, isJsonObject, parseMachine, parseMachine as parseMachine$1, pinnedEndpoint, readBuildMachines, saturation } from "@stim-cli/core/state";
10
10
  import { hostname } from "node:os";
11
11
  import { WebSocket } from "ws";
12
+ //#region src/offload/access-ticket.ts
13
+ function readAccessTicket() {
14
+ const ticket = process.env.STIM_ACCESS_TICKET?.trim();
15
+ return ticket && /^[A-Za-z0-9_-]{43}$/.test(ticket) ? {
16
+ ticket,
17
+ ticketHash: createHash("sha256").update(ticket).digest("hex")
18
+ } : void 0;
19
+ }
20
+ function readHostPermissions(value) {
21
+ const host = value;
22
+ return host && typeof host.name === "string" && typeof host.screenRecording === "boolean" && typeof host.accessibility === "boolean" ? {
23
+ name: host.name,
24
+ screenRecording: host.screenRecording,
25
+ accessibility: host.accessibility
26
+ } : void 0;
27
+ }
28
+ //#endregion
12
29
  //#region src/offload/tailnet.ts
13
30
  const MAC_APP_TAILSCALE = "/Applications/Tailscale.app/Contents/MacOS/Tailscale";
14
31
  const HELLO_TIMEOUT_MS = 1e4;
@@ -164,9 +181,11 @@ function offloadFindings(entry, problems) {
164
181
  }));
165
182
  }
166
183
  async function requestAccess(entry, peer, port, deviceName, io) {
184
+ const ticket = readAccessTicket();
167
185
  const reply = await io.hello(endpoint(peer, port), {
168
186
  request: "build",
169
- deviceName
187
+ deviceName,
188
+ ...ticket ? { setupTicket: ticket.ticket } : {}
170
189
  });
171
190
  if (!("result" in reply) || !reply.result.approval || !reply.result.deviceToken) {
172
191
  const reason = "failed" in reply ? reply.failed : "error" in reply ? reply.error.message : "it granted no request";
@@ -186,7 +205,8 @@ async function requestAccess(entry, peer, port, deviceName, io) {
186
205
  deviceId: reply.result.device.id,
187
206
  deviceToken: reply.result.deviceToken,
188
207
  state: "pending",
189
- requestedAt: (/* @__PURE__ */ new Date()).toISOString()
208
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
209
+ ...ticket ? { ticketHash: ticket.ticketHash } : {}
190
210
  };
191
211
  updateCredentials((credentials) => [...credentials.filter((each) => each.machine !== entry), credential]);
192
212
  return {
@@ -209,7 +229,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
209
229
  },
210
230
  finding: note(`Build machine ${entry} is not a tailnet name`, "Expected `name` or `name:port`.")
211
231
  };
212
- const peer = findPeer(status, parsed.name);
232
+ const peer = findPeer$1(status, parsed.name);
213
233
  if (peer === "missing" || peer === "ambiguous") {
214
234
  const detail = peer === "missing" ? "No peer on this tailnet has that name." : "Several peers match that name.";
215
235
  return {
@@ -251,6 +271,8 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
251
271
  };
252
272
  const reply = await io.hello(endpoint(peer, parsed.port), { deviceToken: credential.deviceToken });
253
273
  if ("result" in reply && reply.result.capabilities.includes("build")) {
274
+ const permissions = readHostPermissions(reply.result.host);
275
+ const host = permissions ? { host: permissions } : {};
254
276
  if (credential.state !== "approved") updateCredentials((credentials) => credentials.map((each) => each.machine === entry ? {
255
277
  ...each,
256
278
  state: "approved"
@@ -258,7 +280,8 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
258
280
  if (!check) return {
259
281
  report: {
260
282
  ...paired,
261
- state: "approved"
283
+ state: "approved",
284
+ ...host
262
285
  },
263
286
  finding: null
264
287
  };
@@ -270,6 +293,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
270
293
  report: {
271
294
  ...paired,
272
295
  state: "approved",
296
+ ...host,
273
297
  offloadable: problems.length === 0,
274
298
  reasons: problems.map((problem) => problem.reason),
275
299
  problems,
@@ -279,13 +303,17 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
279
303
  extra: offloadFindings(entry, problems)
280
304
  };
281
305
  }
282
- if ("error" in reply && reply.error.code === "approval-pending") return {
283
- report: {
284
- ...paired,
285
- state: "pending"
286
- },
287
- finding: note(`Build machine ${entry} has not approved this Mac yet`, `Requested at ${credential.requestedAt}.`, approval(entry, credential.deviceId))
288
- };
306
+ if ("error" in reply && reply.error.code === "approval-pending") {
307
+ const ticket = fix && credential.state !== "approved" ? readAccessTicket() : void 0;
308
+ if (ticket && credential.ticketHash !== ticket.ticketHash) return requestAccess(entry, peer, parsed.port, deviceName, io);
309
+ return {
310
+ report: {
311
+ ...paired,
312
+ state: "pending"
313
+ },
314
+ finding: note(`Build machine ${entry} has not approved this Mac yet`, `Requested at ${credential.requestedAt}.`, approval(entry, credential.deviceId))
315
+ };
316
+ }
289
317
  if ("error" in reply && reply.error.code === "unauthorized") {
290
318
  if (fix) return requestAccess(entry, peer, parsed.port, deviceName, io);
291
319
  return {
@@ -309,7 +337,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
309
337
  * Doctor findings and a report for each `offload.machines` entry. The worker's node is pinned when access is
310
338
  * requested; a later connection goes only to the current MagicDNS name of that same node, checked before the token
311
339
  * is sent. With `fix`, requests access from a named machine this Mac holds no pairing for, requests again when the
312
- * pinned node forgot this Mac, and forgets pairings of machines no longer named. With `check`, each approved
340
+ * pinned node forgot this Mac or, with `STIM_ACCESS_TICKET` set, when a pending request carries another ticket, and forgets pairings of machines no longer named. With `check`, each approved
313
341
  * machine is asked for one build offer and reports every reason it would not take this project's build.
314
342
  */
315
343
  async function inspectBuildMachines({ fix, check = null }, io = realIo, entries = configuredMachines()) {
@@ -591,8 +619,10 @@ var BuildConnection = class BuildConnection {
591
619
  ended = false;
592
620
  keepalive;
593
621
  socket;
594
- constructor(socket) {
622
+ features;
623
+ constructor(socket, features) {
595
624
  this.socket = socket;
625
+ this.features = features;
596
626
  closeOnExit(socket);
597
627
  this.keepalive = setInterval(() => {
598
628
  if (this.watched && Date.now() - this.heard > SILENT_MS) return void socket.terminate();
@@ -647,14 +677,15 @@ var BuildConnection = class BuildConnection {
647
677
  headers: { Host: target.host }
648
678
  };
649
679
  const socket = new WebSocket(target.url, options);
650
- const fail = (reason, refused = false) => {
680
+ const fail = (reason, refused = false, code) => {
651
681
  clearTimeout(timer);
652
682
  socket.removeAllListeners();
653
683
  socket.on("error", () => {});
654
684
  socket.terminate();
655
685
  resolve({
656
686
  failure: reason,
657
- refused
687
+ refused,
688
+ ...code ? { code } : {}
658
689
  });
659
690
  };
660
691
  const timer = setTimeout(() => fail("no reply in time"), timeoutMs);
@@ -683,13 +714,17 @@ var BuildConnection = class BuildConnection {
683
714
  } catch {
684
715
  return fail("the reply was not a hello result");
685
716
  }
686
- if (isJsonObject(reply) && isJsonObject(reply.error)) return fail(String(reply.error.message), TURNED_AWAY.has(String(reply.error.code)));
717
+ if (isJsonObject(reply) && isJsonObject(reply.error)) return fail(String(reply.error.message), TURNED_AWAY.has(String(reply.error.code)), String(reply.error.code));
687
718
  const capabilities = isJsonObject(reply) && isJsonObject(reply.result) ? reply.result.capabilities : null;
688
- if (!Array.isArray(capabilities) || !capabilities.includes(capability)) return fail(`it has not granted this Mac ${capability === "build" ? "build" : "hosting"} access`, true);
689
- resolve(new BuildConnection(socket));
719
+ if (!Array.isArray(capabilities) || !capabilities.includes(capability)) return fail(`it has not granted this Mac ${capability === "build" ? "build" : "hosting"} access`, true, "forbidden");
720
+ const features = isJsonObject(reply) && isJsonObject(reply.result) ? reply.result.features : null;
721
+ resolve(new BuildConnection(socket, Array.isArray(features) ? features.filter((each) => typeof each === "string") : []));
690
722
  });
691
723
  });
692
724
  }
725
+ supports(feature) {
726
+ return this.features.includes(feature);
727
+ }
693
728
  request(method, params, timeoutMs = REQUEST_TIMEOUT_MS) {
694
729
  if (this.closed) return Promise.resolve({ error: {
695
730
  code: "closed",
@@ -1330,4 +1365,4 @@ function offloadCheck(projectRoot, targets) {
1330
1365
  };
1331
1366
  }
1332
1367
  //#endregion
1333
- export { findPeer as _, offloadBuild as a, realIo as b, placementLoad as c, OffloadRefusal as d, namedBuildMachine as f, endpoint as g, inspectBuildMachines as h, closeOffload as i, remotePhaseText as l, resolveBuildPlacement as m, buildPlacementCandidates as n, offloadCheck as o, parseBuildMachineOption as p, chooseBuildMachine as r, offloadPlacement as s, BuildConnection as t, simulatorRuntime as u, parseMachine$1 as v, pinnedEndpoint$1 as y };
1368
+ export { readHostPermissions as S, findPeer$1 as _, offloadBuild as a, realIo as b, placementLoad as c, OffloadRefusal as d, namedBuildMachine as f, endpoint as g, inspectBuildMachines as h, closeOffload as i, remotePhaseText as l, resolveBuildPlacement as m, buildPlacementCandidates as n, offloadCheck as o, parseBuildMachineOption as p, chooseBuildMachine as r, offloadPlacement as s, BuildConnection as t, simulatorRuntime as u, parseMachine$1 as v, readAccessTicket as x, pinnedEndpoint$1 as y };
@@ -1,203 +1,16 @@
1
- import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
1
  import { R as deviceSlotKey, W as validateDeviceSlot } from "./config-D0DbpZtM.mjs";
3
2
  import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
4
- import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
5
- import { C as workspaceLogsDir } from "./workspace-state-CL2V2Ons.mjs";
6
3
  import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
+ import { x as workspaceLogsDir } from "./workspace-state-B8-aJ1_5.mjs";
5
+ import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
7
6
  import { a as startIosDeviceConsole, i as parseDeviceConsoleLine } from "./ios-device-Ee7sDXfp.mjs";
8
- import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-BkYxUtuj.mjs";
9
- import { a as watchAppPid, i as waitForAppPid, n as parseLogcatLine, r as startAndroidLogcat, t as androidClockOffset } from "./android-CYmq0jNi.mjs";
7
+ import { n as parseLogStreamLine, r as startIosLogStream, t as appNameFromBundleId } from "./ios-Cr1h5gnO.mjs";
8
+ import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-DiA16AsN.mjs";
9
+ import { a as watchAppPid, i as waitForAppPid, n as parseLogcatLine, r as startAndroidLogcat, t as androidClockOffset } from "./android-r2rBL8kV.mjs";
10
10
  import { existsSync } from "node:fs";
11
11
  import { isAbsolute, join, resolve } from "node:path";
12
12
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
13
13
  import { fileURLToPath } from "node:url";
14
- //#region src/collector/ios.ts
15
- const MESSAGE_TYPE_LEVEL = {
16
- Debug: "debug",
17
- Info: "info",
18
- Default: "info",
19
- Error: "error",
20
- Fault: "fatal"
21
- };
22
- function levelFromMessageType(messageType) {
23
- return MESSAGE_TYPE_LEVEL[messageType] ?? "info";
24
- }
25
- const NOISE_RULES = [
26
- {
27
- id: "network",
28
- subsystem: "com.apple.network"
29
- },
30
- {
31
- id: "network-default-subsystem",
32
- messagePrefix: [
33
- "nw_socket",
34
- "nw_connection",
35
- "nw_protocol",
36
- "nw_endpoint",
37
- "nw_path",
38
- "nw_resolver",
39
- "nw_flow",
40
- "nw_read_request",
41
- "nw_write_request",
42
- "tcp_input"
43
- ]
44
- },
45
- {
46
- id: "sectrust",
47
- subsystem: "com.apple.securityd"
48
- },
49
- {
50
- id: "sectrust-default-subsystem",
51
- messagePrefix: [
52
- "SecTrust",
53
- "SecOSStatus",
54
- "TrustResultType"
55
- ]
56
- },
57
- {
58
- id: "webkit",
59
- subsystem: "com.apple.WebKit"
60
- },
61
- {
62
- id: "webkit-default-subsystem",
63
- messagePrefix: [
64
- "WebPrivacy",
65
- "GPUProcessProxy",
66
- "WebProcessProxy"
67
- ]
68
- },
69
- {
70
- id: "audio-factory",
71
- messageIncludes: ["AddInstanceForFactory"]
72
- },
73
- {
74
- id: "coreui",
75
- subsystem: "com.apple.coreui"
76
- },
77
- {
78
- id: "coreui-default-subsystem",
79
- messagePrefix: [
80
- "CUICatalog:",
81
- "CoreUI:",
82
- "CoreThemeDefinition"
83
- ]
84
- },
85
- {
86
- id: "uiscene-deprecation",
87
- messageIncludes: [
88
- "UIScene lifecycle will soon be required",
89
- "`UIScene` lifecycle will soon be required",
90
- "must migrate to UIScene",
91
- "migrate to UIScene lifecycle"
92
- ]
93
- },
94
- {
95
- id: "react-native-focus-cache",
96
- exactSubsystem: "com.apple.UIKit",
97
- category: "UIFocus",
98
- messageEquals: "RCTScrollViewComponentView implements focusItemsInRect: - caching for linear focus movement is limited as long as this view is on screen."
99
- },
100
- {
101
- id: "cfnetwork-performance-diagnostic",
102
- exactSubsystem: "com.apple.runtime-issues",
103
- category: "CFNetwork Performance Diagnostic",
104
- level: "warn"
105
- }
106
- ];
107
- function ruleMatches(rule, { subsystem, category, message }) {
108
- if (rule.subsystem && subsystem !== rule.subsystem && !subsystem.startsWith(`${rule.subsystem}.`)) return false;
109
- if (rule.exactSubsystem && subsystem !== rule.exactSubsystem) return false;
110
- if (rule.category && category !== rule.category) return false;
111
- if (rule.messageEquals && message !== rule.messageEquals) return false;
112
- if (rule.messagePrefix && !rule.messagePrefix.some((p) => message.startsWith(p))) return false;
113
- if (rule.messageIncludes && !rule.messageIncludes.some((p) => message.includes(p))) return false;
114
- return true;
115
- }
116
- function matchingNoiseRule(event) {
117
- const subsystem = typeof event?.subsystem === "string" ? event.subsystem : "";
118
- const category = typeof event?.category === "string" ? event.category : "";
119
- const message = typeof event?.eventMessage === "string" ? event.eventMessage : "";
120
- return NOISE_RULES.find((rule) => ruleMatches(rule, {
121
- subsystem,
122
- category,
123
- message
124
- }));
125
- }
126
- function levelForEvent(event) {
127
- const level = levelFromMessageType(event?.messageType);
128
- if (level !== "error" && level !== "fatal") return level;
129
- const rule = matchingNoiseRule(event);
130
- return rule ? rule.level ?? "info" : level;
131
- }
132
- function procFromImagePath(path) {
133
- if (typeof path !== "string" || !path) return null;
134
- const parts = path.split("/");
135
- return parts[parts.length - 1] || null;
136
- }
137
- function tsFromEvent(event, now = Date.now) {
138
- const parsed = Date.parse(event?.timestamp);
139
- return Number.isFinite(parsed) ? parsed : now();
140
- }
141
- function recordFromLogEvent(event, { now = Date.now } = {}) {
142
- if (!event || typeof event !== "object") return null;
143
- const eventType = event.eventType;
144
- if (eventType && eventType !== "logEvent") return null;
145
- const msg = typeof event.eventMessage === "string" ? event.eventMessage : "";
146
- if (!msg.trim()) return null;
147
- const record = {
148
- ts: tsFromEvent(event, now),
149
- src: "device",
150
- level: levelForEvent(event),
151
- msg
152
- };
153
- const proc = procFromImagePath(event.processImagePath);
154
- if (proc) record.proc = proc;
155
- if (typeof event.subsystem === "string") record.subsystem = event.subsystem;
156
- if (typeof event.category === "string") record.category = event.category;
157
- return record;
158
- }
159
- function parseLogStreamLine(line, { now = Date.now } = {}) {
160
- if (typeof line !== "string") return null;
161
- const trimmed = line.trim();
162
- if (!trimmed || trimmed[0] !== "{") return null;
163
- let event;
164
- try {
165
- event = JSON.parse(trimmed);
166
- } catch {
167
- return null;
168
- }
169
- return recordFromLogEvent(event, { now });
170
- }
171
- function logStreamArgs(udid, appName, executableName) {
172
- return [
173
- "simctl",
174
- "spawn",
175
- udid,
176
- "log",
177
- "stream",
178
- "--style",
179
- "ndjson",
180
- "--predicate",
181
- `processImagePath ENDSWITH "/${appName}.app/${executableName && executableName.trim() !== "" ? executableName.trim() : appName}"`,
182
- "--level",
183
- "info"
184
- ];
185
- }
186
- function appNameFromBundleId(bundleId) {
187
- const parts = String(bundleId || "").split(".");
188
- return parts[parts.length - 1] || String(bundleId || "");
189
- }
190
- function startIosLogStream({ udid, appName, executableName = null, spawnFn = null }) {
191
- return (spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts)))("xcrun", logStreamArgs(udid, appName, executableName), {
192
- stdio: [
193
- "ignore",
194
- "pipe",
195
- "pipe"
196
- ],
197
- detached: false
198
- });
199
- }
200
- //#endregion
201
14
  //#region src/collector/run.ts
202
15
  const PLATFORMS = ["ios", "android"];
203
16
  function parseArgs(argv) {
@@ -1,5 +1,5 @@
1
- import { t as NO_PROJECT_REFUSAL } from "./project-CV3tDFHl.mjs";
2
1
  import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
2
+ import { t as NO_PROJECT_REFUSAL } from "./project-Du91Ilvc.mjs";
3
3
  import { quotedPath } from "@stim-cli/core";
4
4
  import chalk from "chalk";
5
5
  //#region src/diagnostics/launch-error-preview.ts
@@ -1,5 +1,5 @@
1
1
  import { d as getConfigDir } from "./config-D0DbpZtM.mjs";
2
- import { E as withDirLock } from "./workspace-state-CL2V2Ons.mjs";
2
+ import { w as withDirLock } from "./workspace-state-B8-aJ1_5.mjs";
3
3
  import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { createdDevicesFile, createdDevicesLock, readCreatedDevices, readCreatedDevices as readCreatedDevices$1 } from "@stim-cli/core/state";
5
5
  //#region src/devices/created-devices.ts
@@ -1,5 +1,5 @@
1
1
  import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
- import { y as repoRoot } from "./worktree-C0c5Udwa.mjs";
2
+ import { gt as repoRoot } from "./settings-oTSkkNrM.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import { dirname, join, relative } from "node:path";
5
5
  //#region src/dependency-state.ts
@@ -1,7 +1,7 @@
1
1
  import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
- import { a as spawnDeclared } from "./spawn-claims-D0XfSe8u.mjs";
3
2
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { S as bundlerPin, u as HEARTBEAT_INTERVAL_MS, y as startBuildHeartbeat } from "./toolchain-DmeYjXD9.mjs";
3
+ import { a as spawnDeclared } from "./spawn-claims-D0XfSe8u.mjs";
4
+ import { S as bundlerPin, u as HEARTBEAT_INTERVAL_MS, y as startBuildHeartbeat } from "./toolchain-DkUflduf.mjs";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  import { delimiter, dirname, join, relative, resolve, sep } from "node:path";
7
7
  import { homedir } from "node:os";
@@ -1,5 +1,5 @@
1
- import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
- import { f as resolvePackageJson, s as isPackageResolvable } from "./project-CV3tDFHl.mjs";
1
+ import { c as isPackageResolvable, p as resolvePackageJson } from "./project-Du91Ilvc.mjs";
2
+ import { C as pickDevClientScheme, w as readBundleSchemes } from "./app-install-CKWdbXIX.mjs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { isJsonObject, readJsonObject } from "@stim-cli/core/state";
5
5
  //#region src/commands/dev-client.ts
@@ -14,43 +14,6 @@ function devClientScheme(root, appPath = null, { exec = null } = {}) {
14
14
  if (typeof scheme !== "string" || scheme.trim() === "") return void 0;
15
15
  return scheme.trim();
16
16
  }
17
- function schemesFromInfoPlist(plist) {
18
- const types = plist?.CFBundleURLTypes;
19
- if (!Array.isArray(types)) return [];
20
- const out = [];
21
- for (const type of types) {
22
- const schemes = type?.CFBundleURLSchemes;
23
- if (Array.isArray(schemes)) out.push(...schemes.filter((s) => typeof s === "string" && s.trim() !== ""));
24
- }
25
- return out;
26
- }
27
- function readBundleSchemes(appPath, { exec = null } = {}) {
28
- if (typeof appPath !== "string" || appPath.trim() === "") return [];
29
- const e = exec || getExecutor();
30
- let out;
31
- try {
32
- out = e.runFile("plutil", [
33
- "-convert",
34
- "json",
35
- "-o",
36
- "-",
37
- join(appPath, "Info.plist")
38
- ]);
39
- } catch {
40
- return [];
41
- }
42
- try {
43
- return schemesFromInfoPlist(JSON.parse(String(out)));
44
- } catch {
45
- return [];
46
- }
47
- }
48
- const THIRD_PARTY_SCHEME = /^(?:fb\d+|com\.googleusercontent\.apps\.|msauth\.|msauthv2|twitterkit-|db-[a-z0-9]+$|spotify|snapchat|com\.facebook)/i;
49
- function pickDevClientScheme(schemes) {
50
- const all = (Array.isArray(schemes) ? schemes : []).filter((s) => typeof s === "string" && s.trim() !== "").map((s) => s.trim()).filter((s) => !/^(?:https?|mailto|tel|sms|itms(?:-apps)?)$/i.test(s));
51
- const expo = all.filter((s) => s.startsWith("exp+"));
52
- return (expo.length ? expo : all.filter((s) => !THIRD_PARTY_SCHEME.test(s))).toSorted((a, b) => b.length - a.length)[0] ?? null;
53
- }
54
17
  function hasDevClient(root) {
55
18
  const pkg = readJsonObject(join(root, "package.json"));
56
19
  if ([pkg?.dependencies, pkg?.devDependencies].some((deps) => isJsonObject(deps) && "expo-dev-client" in deps)) return true;
@@ -77,4 +40,4 @@ function installedDevLauncherVersion(root) {
77
40
  return typeof version === "string" ? version : null;
78
41
  }
79
42
  //#endregion
80
- export { schemesFromInfoPlist as i, devClientTakesDevMenuParams as n, pickDevClientScheme as r, devClientScheme as t };
43
+ export { devClientTakesDevMenuParams as n, devClientScheme as t };