stim 1.14.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 (152) hide show
  1. package/README.md +2 -0
  2. package/dist/activity-BxwdD81S.mjs +609 -0
  3. package/dist/agent-device-usage-output-Dpih1Tfa.mjs +411 -0
  4. package/dist/{android-d6rGq1pA.mjs → android-B_NumVyQ.mjs} +169 -81
  5. package/dist/{android-LbPFRWVL.mjs → android-Ift4kVvt.mjs} +517 -413
  6. package/dist/android-cas-8U4DPqeR.mjs +167 -0
  7. package/dist/android-cas-compiler.mjs +2 -2
  8. package/dist/{android-XpvCrV7q.mjs → android-r2rBL8kV.mjs} +2 -2
  9. package/dist/{app-install-BpgSgkJj.mjs → app-install-CKWdbXIX.mjs} +128 -151
  10. package/dist/attempt-Bk2ouQVL.mjs +39 -0
  11. package/dist/budget-DjrURfQn.mjs +2700 -0
  12. package/dist/{build-plan-Dcr-3ie0.mjs → build-plan-DjeSb2Xl.mjs} +192 -653
  13. package/dist/build-slots-rUk77xqh.mjs +132 -0
  14. package/dist/{cache-manifest-C68QQ0ua.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
  15. package/dist/cache-manifest.mjs +1 -1
  16. package/dist/{chrome-BPCiC3ZX.mjs → chrome-BrcVWQyD.mjs} +1 -1
  17. package/dist/cli-BkYZ_6hy.mjs +51 -0
  18. package/dist/cli.mjs +6 -42
  19. package/dist/client-BTY686R6.mjs +1368 -0
  20. package/dist/collector-run.mjs +9 -195
  21. package/dist/{command-output-DVcpw6eE.mjs → command-output-DnJMdEY-.mjs} +1 -1
  22. package/dist/{config-lvc7d3C2.mjs → config-D0DbpZtM.mjs} +28 -29
  23. package/dist/{created-devices-CllH_8eb.mjs → created-devices-D5owjN4C.mjs} +2 -2
  24. package/dist/{dependency-state-DsT7aKeo.mjs → dependency-state-B6cMXZab.mjs} +2 -2
  25. package/dist/{deps-D9IcKqXS.mjs → deps-urbmfXig.mjs} +3 -3
  26. package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
  27. package/dist/dev-client-CroAIjjj.mjs +43 -0
  28. package/dist/{device-CjuuAJjQ.mjs → device-DZQjF7H5.mjs} +8 -7
  29. package/dist/device-capacity-BHwxNBlu.mjs +136 -0
  30. package/dist/device-host-worker.d.mts +1 -0
  31. package/dist/device-host-worker.mjs +964 -0
  32. package/dist/device-ios-BadmeL2V.mjs +381 -0
  33. package/dist/{device-lease-5c3WrVRm.mjs → device-lease-D-hLqx1b.mjs} +43 -36
  34. package/dist/{device-pool-BiyDyPP-.mjs → device-lease-run-CqjShqWW.mjs} +6 -126
  35. package/dist/device-pool-CUaEWMMm.mjs +125 -0
  36. package/dist/{device-remote-D87zEzaq.mjs → device-remote-D5WVWqOq.mjs} +69 -163
  37. package/dist/{doctor-x9pnU9fq.mjs → doctor-Cimf-gGB.mjs} +241 -103
  38. package/dist/{error-diagnostics-C5HzcwCW.mjs → error-diagnostics-B9L4Ae0x.mjs} +15 -18
  39. package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
  40. package/dist/{gc-ko6mUAYD.mjs → gc-Bqy4bjEu.mjs} +599 -108
  41. package/dist/{android-cas-iZK3DOCr.mjs → gradle-BsO1MdsH.mjs} +8 -294
  42. package/dist/{guide-6R0VNFqI.mjs → guide-B_uyKTxW.mjs} +2511 -239
  43. package/dist/{guide-status-BZrFPIA_.mjs → guide-status-CjEZMAD4.mjs} +3 -3
  44. package/dist/hosted-client-a-WmqE2L.mjs +197 -0
  45. package/dist/hosted-ios-CIWelIqf.mjs +220 -0
  46. package/dist/hosted-logs-D5g041Q3.mjs +187 -0
  47. package/dist/hosted-macos-BSZyIb3y.mjs +135 -0
  48. package/dist/idle-DYVymG92.mjs +1099 -0
  49. package/dist/idle-shutdown-CTsDnAde.mjs +122 -0
  50. package/dist/in-use-DvBw0Kxo.mjs +130 -0
  51. package/dist/{ios-BwDPrnYQ.mjs → ios-BaInn3sW.mjs} +201 -10
  52. package/dist/ios-Cr1h5gnO.mjs +189 -0
  53. package/dist/{ios-P1f5nm2n.mjs → ios-aq3QoGI3.mjs} +1159 -633
  54. package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
  55. package/dist/{ios-device-DGglU3E_.mjs → ios-device-FfCN_C8p.mjs} +12 -7
  56. package/dist/ios-state-DS5UpYTH.mjs +48 -0
  57. package/dist/{launch-verify-Deg4tB3Z.mjs → launch-verify-2DBRizjo.mjs} +5 -5
  58. package/dist/logs-CHEVK8zD.mjs +371 -0
  59. package/dist/machines-BIBUdhpj.mjs +265 -0
  60. package/dist/macos-CSYEAFmF.mjs +473 -0
  61. package/dist/macos-run.d.mts +5 -0
  62. package/dist/macos-run.mjs +2 -0
  63. package/dist/maintenance-run.d.mts +4 -0
  64. package/dist/maintenance-run.mjs +254 -0
  65. package/dist/{metro-CcEo8Fl8.mjs → metro-BeK1ZPz1.mjs} +20 -120
  66. package/dist/metro-gateway-BJ-rxQAB.mjs +84 -0
  67. package/dist/{named-ports-Blg8IxOh.mjs → named-ports-Bk_YXEmE.mjs} +6 -59
  68. package/dist/native-run-NaBrRFtQ.mjs +147 -0
  69. package/dist/{native-runtime-DjBHRg5m.mjs → native-runtime-DBzRnEKS.mjs} +9 -5
  70. package/dist/{ndjson-CDY9IkVC.mjs → ndjson-PclOIwVY.mjs} +2 -2
  71. package/dist/offload-worker.d.mts +122 -0
  72. package/dist/offload-worker.mjs +606 -0
  73. package/dist/{ownership-DyYDF5ww.mjs → ownership-DiA16AsN.mjs} +3 -2
  74. package/dist/ownership-hCkPzGmr.mjs +571 -0
  75. package/dist/{page-BHUzTDFt.mjs → page-QF_Ke10s.mjs} +7 -2
  76. package/dist/{ports-BguS83ex.mjs → ports-R2k4Knz3.mjs} +3 -3
  77. package/dist/prebuild-D2fsca_Z.mjs +213 -0
  78. package/dist/preview-DhVbvPAZ.mjs +318 -0
  79. package/dist/process-identity-BmRm1qV0.mjs +12 -0
  80. package/dist/{project-CWlvEaeN.mjs → project-Du91Ilvc.mjs} +74 -19
  81. package/dist/pull-request-pxnDCQzn.mjs +322 -0
  82. package/dist/pull-requests.d.mts +120 -0
  83. package/dist/pull-requests.mjs +2 -0
  84. package/dist/recordings-BIXOzVnr.mjs +37 -0
  85. package/dist/{reload-BiniwsSZ.mjs → reload-rM9jV1fz.mjs} +109 -24
  86. package/dist/{remote-cache-CcR6o6lI.mjs → remote-cache-C8-V13XN.mjs} +5 -5
  87. package/dist/run-f4vI6EnK.mjs +119 -0
  88. package/dist/{server-bare-DGfgyJ5J.mjs → server-bare-CpPGmnmO.mjs} +33 -15
  89. package/dist/server-expo-CVqO2c35.mjs +2 -0
  90. package/dist/{server-expo-BVuwQ65v.mjs → server-expo-MC0rHlOC.mjs} +8 -12
  91. package/dist/settings-BBpMcDbD.mjs +25 -0
  92. package/dist/{settings-B-fsC-Om.mjs → settings-ZkDzkzvB.mjs} +22 -10
  93. package/dist/settings-oTSkkNrM.mjs +1439 -0
  94. package/dist/settings.schema.json +845 -97
  95. package/dist/{simslim-DrDN4WuV.mjs → simslim-B8-7AoTI.mjs} +8 -132
  96. package/dist/{slot-launch-D5t8EiMf.mjs → slot-launch-B8VrHxn1.mjs} +11 -8
  97. package/dist/{spawn-claims-Drw_o-Fb.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
  98. package/dist/spawn-entry-jw19m8Nl.mjs +17 -0
  99. package/dist/stage-CzaiwFsI.mjs +143 -0
  100. package/dist/start-CX8Ig-U2.mjs +2 -0
  101. package/dist/{start-s4RXp1wy.mjs → start-ClDfwXa4.mjs} +116 -65
  102. package/dist/state-3DwSQIBK.mjs +41 -0
  103. package/dist/state-B4PQFXMW.d.mts +12 -0
  104. package/dist/{state-Dk9RVXI7.mjs → state-C1jB7Q8q.mjs} +70 -8
  105. package/dist/{state-DHqvsbqC.mjs → state-DcW6vOd_.mjs} +7 -4
  106. package/dist/stats-CEZ_i5je.mjs +77 -0
  107. package/dist/{status-BgAuxESg.mjs → status-BuvBFeII.mjs} +118 -20
  108. package/dist/{status-BsPAnfOI.mjs → status-Cs7VLg9D.mjs} +542 -283
  109. package/dist/status-DlKvVJBE.mjs +49 -0
  110. package/dist/stdout-reader-C8yjre1x.mjs +23 -0
  111. package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
  112. package/dist/stim-footprint.swift +32 -0
  113. package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
  114. package/dist/stop-B0Yxtmiy.mjs +48 -0
  115. package/dist/{stop-BzreOWJp.mjs → stop-Bffozsac.mjs} +83 -16
  116. package/dist/{stop-BWIF_6BK.mjs → stop-Dt_dM16A.mjs} +2 -2
  117. package/dist/stop-cause-CidxIqup.mjs +97 -0
  118. package/dist/supervisor-run.d.mts +43 -11
  119. package/dist/supervisor-run.mjs +363 -24
  120. package/dist/support-CAP8qDUF.mjs +316 -0
  121. package/dist/support-D4aYJniO.mjs +201 -0
  122. package/dist/teardown-CL6vDs2Y.mjs +727 -0
  123. package/dist/{xcode-Cp5KvK9x.mjs → toolchain-DkUflduf.mjs} +364 -14
  124. package/dist/trigger-Bemu8ytw.mjs +65 -0
  125. package/dist/trigger-CXts6qt1.mjs +2 -0
  126. package/dist/warm-progress-CpGv3Wb6.mjs +732 -0
  127. package/dist/{web-BsQs1WlO.mjs → web-DWUaMp8P.mjs} +37 -21
  128. package/dist/web-run.mjs +310 -13
  129. package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
  130. package/dist/workspace-state-B8-aJ1_5.mjs +371 -0
  131. package/dist/workspaces-BV4pdHFz.mjs +306 -0
  132. package/dist/{worktree-UrQWXSeb.mjs → worktree-K-xj9Db0.mjs} +625 -256
  133. package/dist/worktree-jnG8Iph5.mjs +2 -0
  134. package/package.json +10 -5
  135. package/shim/bundle-response.cjs +28 -12
  136. package/dist/activity-CYVDcrt3.mjs +0 -356
  137. package/dist/budget-CGDkhvv_.mjs +0 -1745
  138. package/dist/build-progress-DxKpwnaS.mjs +0 -247
  139. package/dist/idle-DXtx3RbX.mjs +0 -191
  140. package/dist/in-use-DlqBDKqY.mjs +0 -249
  141. package/dist/logs-Civ4gbBH.mjs +0 -486
  142. package/dist/merge-state-ytFQCeh4.mjs +0 -262
  143. package/dist/server-expo-DIHDhvGg.mjs +0 -2
  144. package/dist/settings-D61iNOsB.mjs +0 -629
  145. package/dist/start-Cetfvy8l.mjs +0 -2
  146. package/dist/stats-CFpFGlJV.mjs +0 -62
  147. package/dist/stats-CX1Z8Tca.mjs +0 -368
  148. package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
  149. package/dist/stop-cause-hjGBOZTG.mjs +0 -1231
  150. package/dist/worktree-BVrHsYZG.mjs +0 -752
  151. package/dist/worktree-CHWWvm5v.mjs +0 -2
  152. package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
@@ -0,0 +1,122 @@
1
+ import { R as deviceSlotKey, _ as loadConfig$1 } from "./config-D0DbpZtM.mjs";
2
+ import { o as formatLongDuration } from "./command-output-DnJMdEY-.mjs";
3
+ import { a as updateWorkspaceState, r as readWorkspaceState$1 } from "./workspace-state-B8-aJ1_5.mjs";
4
+ import { o as canonicalPath } from "./in-use-DvBw0Kxo.mjs";
5
+ import { n as collectOwnedDeviceActivity, s as workspaceBuildInProgress } from "./idle-DYVymG92.mjs";
6
+ import { u as listAllIosSims } from "./ios-BaInn3sW.mjs";
7
+ import { i as teardownOwnedAvd, o as teardownOwnedIosSim } from "./teardown-CL6vDs2Y.mjs";
8
+ import { DEVICE_IDLE_SHUTDOWN_KEY, readDeviceIdleShutdowns } from "@stim-cli/core/state";
9
+ //#region src/devices/idle-shutdown.ts
10
+ const SIM_LIST_TIMEOUT_MS = 1e4;
11
+ const MINUTE_MS = 6e4;
12
+ /**
13
+ * How long a booted owned device has been idle, when that is at least `idleMs` and nothing keeps it in use: no
14
+ * driver, Stim or agent-device lock, or unreadable activity evidence, no build in the workspace, and no activity
15
+ * (including an open stim-server viewer) for `idleMs`. Null keeps the device running.
16
+ */
17
+ function idleShutdownDueMs(activity, { idleMs, now, buildInProgress, platform = process.platform }) {
18
+ if (buildInProgress || activity.state === "driven") return null;
19
+ const unknown = platform === "win32" ? activity.basis.filter((basis) => basis !== "driver-process") : activity.basis;
20
+ if (activity.state === "unknown" && unknown.length > 0) return null;
21
+ const last = Date.parse(activity.lastActivityAt ?? "");
22
+ if (!Number.isFinite(last)) return null;
23
+ const idle = now - last;
24
+ return idle >= idleMs ? idle : null;
25
+ }
26
+ function listSims() {
27
+ try {
28
+ return listAllIosSims({ timeoutMs: SIM_LIST_TIMEOUT_MS });
29
+ } catch {
30
+ return [];
31
+ }
32
+ }
33
+ /** The workspace's booted owned simulators and emulators that have been idle for `idleMs` or more. */
34
+ function dueIdleDevices(root, idleMs, now = Date.now()) {
35
+ const config = loadConfig$1();
36
+ const self = canonicalPath(root);
37
+ const entry = Object.entries(config?.projects ?? {}).find(([path]) => canonicalPath(path) === self);
38
+ if (!config || !entry) return [];
39
+ const buildInProgress = workspaceBuildInProgress(entry[0]);
40
+ return collectOwnedDeviceActivity({
41
+ ...config,
42
+ projects: { [entry[0]]: entry[1] }
43
+ }, listSims(), now).flatMap((device) => {
44
+ const idleForMs = idleShutdownDueMs(device.activity, {
45
+ idleMs,
46
+ now,
47
+ buildInProgress
48
+ });
49
+ return idleForMs === null ? [] : [{
50
+ device,
51
+ idleForMs
52
+ }];
53
+ });
54
+ }
55
+ /**
56
+ * Shuts down, through centralized teardown, each of the workspace's owned devices that is still idle for `idleMs`,
57
+ * and records why. The caller holds the workspace's native-run lock, so no `ios` or `android` run is booting or
58
+ * installing on them.
59
+ */
60
+ function shutDownIdleDevices(root, idleMs, log, now = Date.now()) {
61
+ let shutDown = 0;
62
+ for (const { device, idleForMs } of dueIdleDevices(root, idleMs, now)) {
63
+ const what = `${device.kind === "ios" ? "simulator" : "emulator"} ${device.name}`;
64
+ const outcome = device.kind === "ios" ? teardownOwnedIosSim(device.id, {
65
+ label: device.name,
66
+ workspace: root
67
+ }) : teardownOwnedAvd(device.id, {
68
+ owner: {
69
+ projectPath: device.project,
70
+ slot: device.slot
71
+ },
72
+ workspace: root
73
+ });
74
+ if (outcome.status === "torn-down") {
75
+ shutDown++;
76
+ const idleMinutes = Math.floor(idleForMs / MINUTE_MS);
77
+ try {
78
+ updateWorkspaceState(root, (state) => ({
79
+ ...state,
80
+ [DEVICE_IDLE_SHUTDOWN_KEY]: {
81
+ ...readDeviceIdleShutdowns(state),
82
+ [deviceSlotKey(device.kind, device.slot)]: {
83
+ at: new Date(now).toISOString(),
84
+ idleMinutes
85
+ }
86
+ }
87
+ }));
88
+ } catch (error) {
89
+ log({
90
+ level: "warn",
91
+ event: "device_idle_shutdown_failed",
92
+ msg: `shut down idle ${what} but could not record it: ${error?.message || error}`
93
+ });
94
+ }
95
+ log({
96
+ level: "info",
97
+ event: "device_idle_shutdown",
98
+ msg: `shut down ${what}, idle ${formatLongDuration(idleForMs)}`
99
+ });
100
+ } else if (outcome.status !== "missing") log({
101
+ level: "warn",
102
+ event: "device_idle_shutdown_failed",
103
+ msg: `could not shut down idle ${what}: ${outcome.reason}`
104
+ });
105
+ }
106
+ return shutDown;
107
+ }
108
+ /** Forgets the slot's idle shutdown once a run boots its device again. */
109
+ function clearDeviceIdleShutdown(root, platform, slot = "default") {
110
+ const key = deviceSlotKey(platform, slot);
111
+ if (!(key in readDeviceIdleShutdowns(readWorkspaceState$1(root)))) return;
112
+ updateWorkspaceState(root, (state) => {
113
+ const { [key]: _cleared, ...rest } = readDeviceIdleShutdowns(state);
114
+ const { [DEVICE_IDLE_SHUTDOWN_KEY]: _all, ...others } = state;
115
+ return Object.keys(rest).length ? {
116
+ ...others,
117
+ [DEVICE_IDLE_SHUTDOWN_KEY]: rest
118
+ } : others;
119
+ });
120
+ }
121
+ //#endregion
122
+ export { dueIdleDevices as n, shutDownIdleDevices as r, clearDeviceIdleShutdown as t };
@@ -0,0 +1,130 @@
1
+ import { p as getProject } from "./config-D0DbpZtM.mjs";
2
+ import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
3
+ import { r as readWorkspaceState$1, v as workspaceDir } from "./workspace-state-B8-aJ1_5.mjs";
4
+ import { o as readWebRecord, u as webFacts } from "./state-C1jB7Q8q.mjs";
5
+ import { h as listBuildLocks } from "./device-lease-D-hLqx1b.mjs";
6
+ import { n as listBuildSlots } from "./build-slots-rUk77xqh.mjs";
7
+ import { n as workspaceProcessLockError, r as workspaceProcessLockPath, t as withWorkspaceProcessLock } from "./workspace-process-lock-BL7Q0HCO.mjs";
8
+ import { i as macosRuntimeClaim } from "./state-3DwSQIBK.mjs";
9
+ import { n as managedLockHolders, t as resolveSupervisorTarget } from "./ownership-hCkPzGmr.mjs";
10
+ import { lstatSync, readdirSync, rmSync, rmdirSync, unlinkSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { realpathSync as realpathSync$1 } from "fs";
13
+ import { resolve as resolve$1 } from "path";
14
+ import { hostedIosRecords, macosAppState, parseHostedIosPlacement, readMacosRecord, unreadableHostedIos } from "@stim-cli/core/state";
15
+ //#region src/commands/gc/paths.ts
16
+ function canonicalPath(p) {
17
+ try {
18
+ return realpathSync$1(p);
19
+ } catch {
20
+ return resolve$1(p);
21
+ }
22
+ }
23
+ //#endregion
24
+ //#region src/commands/gc/results.ts
25
+ const results = [];
26
+ function recordGcResult(kind, status, label, { id = null, bytes = null, detail = null } = {}) {
27
+ results.push({
28
+ kind,
29
+ status,
30
+ label,
31
+ id,
32
+ bytes,
33
+ detail
34
+ });
35
+ }
36
+ function takeGcResults() {
37
+ return results.splice(0);
38
+ }
39
+ //#endregion
40
+ //#region src/workspace/in-use.ts
41
+ const NATIVE_RUN = "native-run";
42
+ const NATIVE_RUN_HELD = "a stim ios, android or stop run holds its native-run.lock";
43
+ function workspaceInUse(root, { supervisor = true, managedLocks = true, hosted = true, nativeRun = true } = {}) {
44
+ const reasons = [];
45
+ if (supervisor) {
46
+ const project = getProject(root);
47
+ const target = resolveSupervisorTarget({
48
+ state: readWorkspaceState$1(root)?.supervisor,
49
+ record: project?.supervisor,
50
+ reservedPort: project?.metroPort
51
+ });
52
+ if (target.status === "ours") reasons.push(`its dev server supervisor (pid ${target.pid}) is running`);
53
+ else if (target.status === "unverified") reasons.push(`its dev server supervisor cannot be verified: ${target.reason ?? "unknown identity"}`);
54
+ const macos = macosAppState(readMacosRecord(root));
55
+ if (macos?.host) reasons.push(`its macOS app runs on ${macos.host.machine}`);
56
+ else if (macos?.state === "running" || macos?.state === "orphaned" || macos?.build.state === "running") reasons.push("its macOS app or build is running");
57
+ else if (macos?.state === "unverified" || !macos && readWorkspaceState$1(root)?.macos !== void 0) reasons.push("its macOS process owner cannot be verified");
58
+ const runtime = (0, ownership_claim_exports.readClaimSet)(macosRuntimeClaim(root));
59
+ if (runtime.live.length) reasons.push("its macOS runtime claim is held");
60
+ else if (runtime.unresolved[0]) reasons.push(`its macOS runtime cannot be verified: ${runtime.unresolved[0].reason}`);
61
+ const browser = webFacts(readWebRecord(root));
62
+ if (browser?.status === "running" || browser?.status === "orphaned") reasons.push(`its owned Chrome (pid ${browser.record.chromeProcess?.pid}) is running`);
63
+ else if (browser?.status === "unverified") reasons.push("its owned Chrome cannot be verified");
64
+ }
65
+ if (nativeRun) {
66
+ const claims = (0, ownership_claim_exports.readClaimSet)(workspaceProcessLockPath(workspaceDir(root), NATIVE_RUN, true));
67
+ if (claims.live.length) reasons.push(NATIVE_RUN_HELD);
68
+ else if (claims.unresolved[0]) reasons.push(`its native-run.lock cannot be resolved: ${claims.unresolved[0].reason}`);
69
+ }
70
+ for (const [slot, record] of Object.entries(hosted ? hostedIosRecords(readWorkspaceState$1(root)) : {})) {
71
+ const placement = parseHostedIosPlacement(record);
72
+ reasons.push(placement ? `its iOS simulator runs on ${placement.machine}` : unreadableHostedIos(slot));
73
+ }
74
+ const self = canonicalPath(root);
75
+ for (const [kind, entries] of [["build lock", listBuildLocks()], ["build slot", listBuildSlots()]]) for (const entry of entries) {
76
+ if (!entry.alive && !entry.unresolved) continue;
77
+ if (entry.projectRoot !== null && canonicalPath(entry.projectRoot) === self) reasons.push(`a ${entry.alive ? "live" : "unresolvable"} ${kind} at ${entry.path} names it`);
78
+ }
79
+ if (managedLocks) reasons.push(...managedLockHolders(root));
80
+ return reasons;
81
+ }
82
+ function emptyWorkspaceDir(dir) {
83
+ if (lstatSync(dir).isSymbolicLink()) {
84
+ unlinkSync(dir);
85
+ return;
86
+ }
87
+ for (const name of readdirSync(dir)) if (name !== `${NATIVE_RUN}.lock`) rmSync(join(dir, name), {
88
+ recursive: true,
89
+ force: true
90
+ });
91
+ }
92
+ async function withIdleWorkspace(root, fn, { purpose, ...checks }) {
93
+ try {
94
+ return await withWorkspaceProcessLock(workspaceDir(root), NATIVE_RUN, async () => {
95
+ const reasons = workspaceInUse(root, {
96
+ ...checks,
97
+ nativeRun: false
98
+ });
99
+ if (reasons.length) return {
100
+ ran: false,
101
+ reasons
102
+ };
103
+ return {
104
+ ran: true,
105
+ value: await fn()
106
+ };
107
+ }, {
108
+ external: true,
109
+ waitMs: 0,
110
+ ownerPurpose: purpose
111
+ });
112
+ } catch (error) {
113
+ if (workspaceProcessLockError(error)) return {
114
+ ran: false,
115
+ reasons: [NATIVE_RUN_HELD]
116
+ };
117
+ if ((0, ownership_claim_exports.isClaimRefusal)(error) || (0, ownership_claim_exports.isClaimUnavailable)(error)) return {
118
+ ran: false,
119
+ reasons: [`its native-run.lock cannot be taken: ${error.reason}`]
120
+ };
121
+ throw error;
122
+ } finally {
123
+ try {
124
+ const dir = workspaceDir(root);
125
+ if (!lstatSync(dir).isSymbolicLink()) rmdirSync(dir);
126
+ } catch {}
127
+ }
128
+ }
129
+ //#endregion
130
+ export { takeGcResults as a, recordGcResult as i, withIdleWorkspace as n, canonicalPath as o, workspaceInUse as r, emptyWorkspaceDir as t };
@@ -1,13 +1,144 @@
1
- import { _ as loadConfig$1 } from "./config-lvc7d3C2.mjs";
2
- import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
1
+ import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
+ import { _ as loadConfig$1 } from "./config-D0DbpZtM.mjs";
3
3
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { n as settingDefault, t as STIM_DESKTOP_OPEN_OPTIONS } from "./stim-desktop-CXt8-Z3J.mjs";
5
- import { nt as isStimOwnedSim } from "./android-d6rGq1pA.mjs";
6
- import { r as recordCreatedDevice, t as forgetCreatedDevice } from "./created-devices-CllH_8eb.mjs";
7
- import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { r as recordCreatedDevice, t as forgetCreatedDevice } from "./created-devices-D5owjN4C.mjs";
5
+ import { at as isStimOwnedSim } from "./android-B_NumVyQ.mjs";
6
+ import { n as settingDefault, t as STIM_DESKTOP_OPEN_OPTIONS } from "./stim-desktop-Cnz8CPnl.mjs";
7
+ import { createHash } from "node:crypto";
8
+ import { closeSync, existsSync, lstatSync, mkdtempSync, openSync, readSync, readdirSync, rmSync, writeFileSync } from "node:fs";
9
+ import { dirname, isAbsolute, join, resolve } from "node:path";
8
10
  import { IOS_SIMULATOR_APPS, settingDefinition } from "@stim-cli/core/state";
9
- import { dirname, join, resolve } from "node:path";
10
11
  import { tmpdir } from "node:os";
12
+ //#region src/engine/installed-artifact.ts
13
+ const READ_CHUNK_BYTES = 1048576;
14
+ const DEVICE_PATH_TIMEOUT_MS = 3e4;
15
+ const DEVICE_HASH_TIMEOUT_MS = 12e4;
16
+ const SHA256_HEX = /^[0-9a-f]{64}$/;
17
+ function parseInstalledApkPath(text) {
18
+ if (typeof text !== "string") return null;
19
+ const paths = [];
20
+ for (const raw of text.split("\n")) {
21
+ const line = raw.trim();
22
+ if (!line.startsWith("package:")) continue;
23
+ const path = line.slice(8);
24
+ if (path.startsWith("/")) paths.push(path);
25
+ }
26
+ return paths.length === 1 ? paths[0] : null;
27
+ }
28
+ function parseDeviceSha256(text) {
29
+ if (typeof text !== "string") return null;
30
+ const first = text.trim().split(/\s+/)[0] ?? "";
31
+ return SHA256_HEX.test(first) ? first : null;
32
+ }
33
+ function parseAppContainerPath(text) {
34
+ if (typeof text !== "string") return null;
35
+ const lines = text.split("\n").map((line) => line.trim()).filter(Boolean);
36
+ return lines.length === 1 && isAbsolute(lines[0]) ? lines[0] : null;
37
+ }
38
+ function artifactsMatch(local, installed) {
39
+ return Boolean(local) && local === installed;
40
+ }
41
+ function hashFile(file) {
42
+ let fd = null;
43
+ try {
44
+ fd = openSync(file, "r");
45
+ const digest = createHash("sha256");
46
+ const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
47
+ for (;;) {
48
+ const read = readSync(fd, buffer, 0, READ_CHUNK_BYTES, null);
49
+ if (read <= 0) break;
50
+ digest.update(buffer.subarray(0, read));
51
+ }
52
+ return digest.digest("hex");
53
+ } catch {
54
+ return null;
55
+ } finally {
56
+ if (fd !== null) try {
57
+ closeSync(fd);
58
+ } catch {}
59
+ }
60
+ }
61
+ function hashBundle(dir) {
62
+ const digest = createHash("sha256");
63
+ const walk = (abs, rel) => {
64
+ let names;
65
+ try {
66
+ names = readdirSync(abs);
67
+ } catch {
68
+ return false;
69
+ }
70
+ for (const name of names.toSorted()) {
71
+ const child = join(abs, name);
72
+ const path = rel === "" ? name : `${rel}/${name}`;
73
+ let stat;
74
+ try {
75
+ stat = lstatSync(child);
76
+ } catch {
77
+ return false;
78
+ }
79
+ if (stat.isDirectory()) {
80
+ if (!walk(child, path)) return false;
81
+ continue;
82
+ }
83
+ if (!stat.isFile()) return false;
84
+ const file = hashFile(child);
85
+ if (file === null) return false;
86
+ digest.update(`${path}\0${file}\n`);
87
+ }
88
+ return true;
89
+ };
90
+ return walk(dir, "") ? digest.digest("hex") : null;
91
+ }
92
+ function deviceHoldsApk({ serial, packageName, apkPath }, { exec = null } = {}) {
93
+ const e = exec || getExecutor();
94
+ let path;
95
+ try {
96
+ path = parseInstalledApkPath(e.runFile("adb", [
97
+ "-s",
98
+ serial,
99
+ "shell",
100
+ "pm",
101
+ "path",
102
+ packageName
103
+ ], { timeoutMs: DEVICE_PATH_TIMEOUT_MS }));
104
+ } catch {
105
+ return false;
106
+ }
107
+ if (!path) return false;
108
+ let installed;
109
+ try {
110
+ installed = parseDeviceSha256(e.runFile("adb", [
111
+ "-s",
112
+ serial,
113
+ "shell",
114
+ "sha256sum",
115
+ path
116
+ ], { timeoutMs: DEVICE_HASH_TIMEOUT_MS }));
117
+ } catch {
118
+ return false;
119
+ }
120
+ if (!installed) return false;
121
+ return artifactsMatch(hashFile(apkPath), installed);
122
+ }
123
+ function deviceHoldsBundle({ udid, bundleId, appPath }, { exec = null } = {}) {
124
+ const e = exec || getExecutor();
125
+ let container;
126
+ try {
127
+ container = parseAppContainerPath(e.runFile("xcrun", [
128
+ "simctl",
129
+ "get_app_container",
130
+ udid,
131
+ bundleId
132
+ ], { timeoutMs: DEVICE_PATH_TIMEOUT_MS }));
133
+ } catch {
134
+ return false;
135
+ }
136
+ if (!container) return false;
137
+ const installed = hashBundle(container);
138
+ if (!installed) return false;
139
+ return artifactsMatch(hashBundle(appPath), installed);
140
+ }
141
+ //#endregion
11
142
  //#region src/host-memory.ts
12
143
  function readHostMemoryPressure(exec = getExecutor(), platform = process.platform) {
13
144
  if (platform !== "darwin") return null;
@@ -201,7 +332,7 @@ async function awaitBootCommand(args, attemptMs, onLine) {
201
332
  const detail = lines.length ? `: ${lines.join(" | ")}` : "";
202
333
  throw new Error(`${command} failed with exit code ${result.code ?? "unknown"}${detail}`);
203
334
  }
204
- async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = BOOTSTATUS_ATTEMPT_MS, simulatorApp, label = udid, out = () => {} } = {}) {
335
+ async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = BOOTSTATUS_ATTEMPT_MS, simulatorApp, openViewer = true, label = udid, out = () => {} } = {}) {
205
336
  const exec = getExecutor();
206
337
  const viewer = configuredIosSimulatorViewer(simulatorApp);
207
338
  const started = Date.now();
@@ -280,7 +411,7 @@ async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = B
280
411
  } finally {
281
412
  clearInterval(monitor);
282
413
  }
283
- viewer.open(udid);
414
+ if (openViewer) viewer.open(udid);
284
415
  }
285
416
  function shutdownIosSim(udid) {
286
417
  getExecutor().runQuiet(`xcrun simctl shutdown ${udid}`, SIMCTL_OPTIONS);
@@ -432,6 +563,66 @@ function resetIosKeychain(udid) {
432
563
  "reset"
433
564
  ], SIMCTL_OPTIONS);
434
565
  }
566
+ const CLEARED_CONTAINER_DIRS = [
567
+ "Documents",
568
+ "Library",
569
+ "tmp",
570
+ "SystemData"
571
+ ];
572
+ function clearIosAppData(udid, bundleId, { defaultsPlist = null } = {}) {
573
+ const exec = getExecutor();
574
+ if (defaultsPlist) exec.runFile("xcrun", [
575
+ "simctl",
576
+ "spawn",
577
+ udid,
578
+ "defaults",
579
+ "import",
580
+ bundleId,
581
+ "-"
582
+ ], {
583
+ ...SIMCTL_OPTIONS,
584
+ input: defaultsPlist
585
+ });
586
+ else try {
587
+ exec.runFile("xcrun", [
588
+ "simctl",
589
+ "spawn",
590
+ udid,
591
+ "defaults",
592
+ "delete",
593
+ bundleId
594
+ ], SIMCTL_OPTIONS);
595
+ } catch (error) {
596
+ if (!/Domain .* not found/.test(String(error?.message))) throw error;
597
+ }
598
+ const output = exec.runFile("xcrun", [
599
+ "simctl",
600
+ "get_app_container",
601
+ udid,
602
+ bundleId,
603
+ "data"
604
+ ], SIMCTL_OPTIONS);
605
+ const container = parseAppContainerPath(output);
606
+ if (!container) throw new Error(`simctl get_app_container returned no data container for ${bundleId}: ${JSON.stringify(output)}`);
607
+ for (const name of CLEARED_CONTAINER_DIRS) {
608
+ const dir = join(container, name);
609
+ let stat;
610
+ try {
611
+ stat = lstatSync(dir);
612
+ } catch (error) {
613
+ if (error?.code === "ENOENT") continue;
614
+ throw error;
615
+ }
616
+ if (!stat.isDirectory()) {
617
+ rmSync(dir, { force: true });
618
+ continue;
619
+ }
620
+ for (const child of readdirSync(dir)) rmSync(join(dir, child), {
621
+ recursive: true,
622
+ force: true
623
+ });
624
+ }
625
+ }
435
626
  function uninstallIosApp(udid, bundleId) {
436
627
  getExecutor().runFile("xcrun", [
437
628
  "simctl",
@@ -526,4 +717,4 @@ function listIosRuntimes() {
526
717
  }));
527
718
  }
528
719
  //#endregion
529
- export { sanitizeDeviceLabel as C, parseIosSimulatorApp as D, configuredIosSimulatorViewer as E, hostMemoryPressureAdvice as O, resolveOwnedIosSim as S, uninstallIosApp as T, parseSimctlList as _, deleteParkedIosSim as a, resetIosPrivacy as b, iosSimulatorFailureAdvice as c, listIosDeviceTypes as d, listIosRuntimes as f, parseRuntimeVersion as g, parkedSimName as h, deleteIosSim as i, readHostMemoryPressure as k, listAllIosSims as l, ownedSimName as m, bootIosSim as n, eraseIosSim as o, listUserApps as p, createOwnedIosSim as r, iosRuntimeMatches as s, IOS_BOOT_TIMEOUT_MS as t, listAllIosSimsAsync as u, renameIosSim as v, shutdownIosSim as w, resolveIosCreation as x, resetIosKeychain as y };
720
+ export { hostMemoryPressureAdvice as A, resolveIosCreation as C, uninstallIosApp as D, shutdownIosSim as E, deviceHoldsApk as M, deviceHoldsBundle as N, configuredIosSimulatorViewer as O, resetIosPrivacy as S, sanitizeDeviceLabel as T, parseRuntimeVersion as _, deleteIosSim as a, renameIosSim as b, iosRuntimeMatches as c, listAllIosSimsAsync as d, listIosDeviceTypes as f, parkedSimName as g, ownedSimName as h, createOwnedIosSim as i, readHostMemoryPressure as j, parseIosSimulatorApp as k, iosSimulatorFailureAdvice as l, listUserApps as m, bootIosSim as n, deleteParkedIosSim as o, listIosRuntimes as p, clearIosAppData as r, eraseIosSim as s, IOS_BOOT_TIMEOUT_MS as t, listAllIosSims as u, parseSimctlList as v, resolveOwnedIosSim as w, resetIosKeychain as x, pickDefaultIosCreation as y };
@@ -0,0 +1,189 @@
1
+ import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
+ //#region src/collector/ios.ts
3
+ const MESSAGE_TYPE_LEVEL = {
4
+ Debug: "debug",
5
+ Info: "info",
6
+ Default: "info",
7
+ Error: "error",
8
+ Fault: "fatal"
9
+ };
10
+ function levelFromMessageType(messageType) {
11
+ return MESSAGE_TYPE_LEVEL[messageType] ?? "info";
12
+ }
13
+ const NOISE_RULES = [
14
+ {
15
+ id: "network",
16
+ subsystem: "com.apple.network"
17
+ },
18
+ {
19
+ id: "network-default-subsystem",
20
+ messagePrefix: [
21
+ "nw_socket",
22
+ "nw_connection",
23
+ "nw_protocol",
24
+ "nw_endpoint",
25
+ "nw_path",
26
+ "nw_resolver",
27
+ "nw_flow",
28
+ "nw_read_request",
29
+ "nw_write_request",
30
+ "tcp_input"
31
+ ]
32
+ },
33
+ {
34
+ id: "sectrust",
35
+ subsystem: "com.apple.securityd"
36
+ },
37
+ {
38
+ id: "sectrust-default-subsystem",
39
+ messagePrefix: [
40
+ "SecTrust",
41
+ "SecOSStatus",
42
+ "TrustResultType"
43
+ ]
44
+ },
45
+ {
46
+ id: "webkit",
47
+ subsystem: "com.apple.WebKit"
48
+ },
49
+ {
50
+ id: "webkit-default-subsystem",
51
+ messagePrefix: [
52
+ "WebPrivacy",
53
+ "GPUProcessProxy",
54
+ "WebProcessProxy"
55
+ ]
56
+ },
57
+ {
58
+ id: "audio-factory",
59
+ messageIncludes: ["AddInstanceForFactory"]
60
+ },
61
+ {
62
+ id: "coreui",
63
+ subsystem: "com.apple.coreui"
64
+ },
65
+ {
66
+ id: "coreui-default-subsystem",
67
+ messagePrefix: [
68
+ "CUICatalog:",
69
+ "CoreUI:",
70
+ "CoreThemeDefinition"
71
+ ]
72
+ },
73
+ {
74
+ id: "uiscene-deprecation",
75
+ messageIncludes: [
76
+ "UIScene lifecycle will soon be required",
77
+ "`UIScene` lifecycle will soon be required",
78
+ "must migrate to UIScene",
79
+ "migrate to UIScene lifecycle"
80
+ ]
81
+ },
82
+ {
83
+ id: "react-native-focus-cache",
84
+ exactSubsystem: "com.apple.UIKit",
85
+ category: "UIFocus",
86
+ messageEquals: "RCTScrollViewComponentView implements focusItemsInRect: - caching for linear focus movement is limited as long as this view is on screen."
87
+ },
88
+ {
89
+ id: "cfnetwork-performance-diagnostic",
90
+ exactSubsystem: "com.apple.runtime-issues",
91
+ category: "CFNetwork Performance Diagnostic",
92
+ level: "warn"
93
+ }
94
+ ];
95
+ function ruleMatches(rule, { subsystem, category, message }) {
96
+ if (rule.subsystem && subsystem !== rule.subsystem && !subsystem.startsWith(`${rule.subsystem}.`)) return false;
97
+ if (rule.exactSubsystem && subsystem !== rule.exactSubsystem) return false;
98
+ if (rule.category && category !== rule.category) return false;
99
+ if (rule.messageEquals && message !== rule.messageEquals) return false;
100
+ if (rule.messagePrefix && !rule.messagePrefix.some((p) => message.startsWith(p))) return false;
101
+ if (rule.messageIncludes && !rule.messageIncludes.some((p) => message.includes(p))) return false;
102
+ return true;
103
+ }
104
+ function matchingNoiseRule(event) {
105
+ const subsystem = typeof event?.subsystem === "string" ? event.subsystem : "";
106
+ const category = typeof event?.category === "string" ? event.category : "";
107
+ const message = typeof event?.eventMessage === "string" ? event.eventMessage : "";
108
+ return NOISE_RULES.find((rule) => ruleMatches(rule, {
109
+ subsystem,
110
+ category,
111
+ message
112
+ }));
113
+ }
114
+ function levelForEvent(event) {
115
+ const level = levelFromMessageType(event?.messageType);
116
+ if (level !== "error" && level !== "fatal") return level;
117
+ const rule = matchingNoiseRule(event);
118
+ return rule ? rule.level ?? "info" : level;
119
+ }
120
+ function procFromImagePath(path) {
121
+ if (typeof path !== "string" || !path) return null;
122
+ const parts = path.split("/");
123
+ return parts[parts.length - 1] || null;
124
+ }
125
+ function tsFromEvent(event, now = Date.now) {
126
+ const parsed = Date.parse(event?.timestamp);
127
+ return Number.isFinite(parsed) ? parsed : now();
128
+ }
129
+ function recordFromLogEvent(event, { now = Date.now } = {}) {
130
+ if (!event || typeof event !== "object") return null;
131
+ const eventType = event.eventType;
132
+ if (eventType && eventType !== "logEvent") return null;
133
+ const msg = typeof event.eventMessage === "string" ? event.eventMessage : "";
134
+ if (!msg.trim()) return null;
135
+ const record = {
136
+ ts: tsFromEvent(event, now),
137
+ src: "device",
138
+ level: levelForEvent(event),
139
+ msg
140
+ };
141
+ const proc = procFromImagePath(event.processImagePath);
142
+ if (proc) record.proc = proc;
143
+ if (typeof event.subsystem === "string") record.subsystem = event.subsystem;
144
+ if (typeof event.category === "string") record.category = event.category;
145
+ return record;
146
+ }
147
+ function parseLogStreamLine(line, { now = Date.now } = {}) {
148
+ if (typeof line !== "string") return null;
149
+ const trimmed = line.trim();
150
+ if (!trimmed || trimmed[0] !== "{") return null;
151
+ let event;
152
+ try {
153
+ event = JSON.parse(trimmed);
154
+ } catch {
155
+ return null;
156
+ }
157
+ return recordFromLogEvent(event, { now });
158
+ }
159
+ function logStreamArgs(udid, appName, executableName) {
160
+ return [
161
+ "simctl",
162
+ "spawn",
163
+ udid,
164
+ "log",
165
+ "stream",
166
+ "--style",
167
+ "ndjson",
168
+ "--predicate",
169
+ `processImagePath ENDSWITH "/${appName}.app/${executableName && executableName.trim() !== "" ? executableName.trim() : appName}"`,
170
+ "--level",
171
+ "info"
172
+ ];
173
+ }
174
+ function appNameFromBundleId(bundleId) {
175
+ const parts = String(bundleId || "").split(".");
176
+ return parts[parts.length - 1] || String(bundleId || "");
177
+ }
178
+ function startIosLogStream({ udid, appName, executableName = null, spawnFn = null }) {
179
+ return (spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts)))("xcrun", logStreamArgs(udid, appName, executableName), {
180
+ stdio: [
181
+ "ignore",
182
+ "pipe",
183
+ "pipe"
184
+ ],
185
+ detached: false
186
+ });
187
+ }
188
+ //#endregion
189
+ export { parseLogStreamLine as n, startIosLogStream as r, appNameFromBundleId as t };