stim 1.17.2 → 1.18.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 (150) hide show
  1. package/README.md +50 -1
  2. package/dist/{activity-IRvJY_ru.mjs → activity-BxnkDZDi.mjs} +4 -4
  3. package/dist/{agent-device-usage-output-BK41vnzN.mjs → agent-device-usage-output-CZ66YA4T.mjs} +8 -8
  4. package/dist/android-BKA16DTf.mjs +4 -0
  5. package/dist/{android-B9yaNKwa.mjs → android-BvwuMUJ9.mjs} +192 -98
  6. package/dist/{android-DE4v59Mb.mjs → android-CBwCNicO.mjs} +2 -2
  7. package/dist/{android-B_YNZy61.mjs → android-DC3ZLuw0.mjs} +9 -9
  8. package/dist/{android-cas-ZFpjJBL_.mjs → android-cas-BBFyr9CA.mjs} +5 -5
  9. package/dist/android-cas-compiler.mjs +2 -2
  10. package/dist/api-D0VtFhqk.mjs +152 -0
  11. package/dist/api-run.d.mts +1 -0
  12. package/dist/api-run.mjs +145 -0
  13. package/dist/api.d.mts +212 -0
  14. package/dist/api.mjs +2 -0
  15. package/dist/{app-install-VPkI5WEg.mjs → app-install-D-PUENug.mjs} +3 -3
  16. package/dist/{attempt-Bk2ouQVL.mjs → attempt-DW-mQqM7.mjs} +14 -4
  17. package/dist/{budget-DfcgFdQB.mjs → budget-DIhL2BKx.mjs} +1578 -58
  18. package/dist/build-facts-DcLv2HSd.d.mts +111 -0
  19. package/dist/{cache-manifest-DnUHBJaU.mjs → cache-manifest-BI7ozfmH.mjs} +3 -3
  20. package/dist/cache-manifest.mjs +1 -1
  21. package/dist/{chrome-BrcVWQyD.mjs → chrome-DJnmnS5q.mjs} +1 -1
  22. package/dist/cli-DNJMwADx.mjs +68 -0
  23. package/dist/cli.mjs +1 -1
  24. package/dist/{client-SvBdgObD.mjs → client-DzhapoMB.mjs} +139 -32
  25. package/dist/collector-run.mjs +9 -9
  26. package/dist/{command-output-CDAIFD-8.mjs → command-output-CBtzyIgF.mjs} +2 -2
  27. package/dist/{config-D0DbpZtM.mjs → config-CgYMahz7.mjs} +5 -5
  28. package/dist/{created-devices-CpvzBL25.mjs → created-devices-DKbeWsiK.mjs} +2 -2
  29. package/dist/{dependency-state-CLcBHH2M.mjs → dependency-state-xKoOypBm.mjs} +2 -2
  30. package/dist/{detached-entry-CiTEgMR1.mjs → detached-entry-BLfcgc4O.mjs} +1 -1
  31. package/dist/{dev-client-B-XC4uRH.mjs → dev-client-CLnIH02x.mjs} +2 -2
  32. package/dist/{device-C8IOoJPv.mjs → device-D7oCHGWi.mjs} +8 -8
  33. package/dist/{device-capacity-ZC4XSZ4R.mjs → device-capacity-EUOOYr8T.mjs} +13 -13
  34. package/dist/device-host-worker.mjs +19 -19
  35. package/dist/{device-ios-C2Um-XUR.mjs → device-ios-6MewKKnc.mjs} +13 -13
  36. package/dist/{device-lease-DpoS36_u.mjs → device-lease-Co-EwifR.mjs} +9 -9
  37. package/dist/{device-lease-run-B8YltIH_.mjs → device-lease-run-w1xhCqIW.mjs} +4 -4
  38. package/dist/{device-pool-3o7s5lo4.mjs → device-pool-F5WvRPtD.mjs} +3 -3
  39. package/dist/{device-remote-hFSkpfQu.mjs → device-remote-tHbd1fKy.mjs} +15 -15
  40. package/dist/{doctor-CFv1fCrF.mjs → doctor-B9ckYUoU.mjs} +33 -30
  41. package/dist/{error-diagnostics-C-NMnhrk.mjs → error-diagnostics-BRXOqDzG.mjs} +11 -11
  42. package/dist/{exec-CaErVv7t.mjs → exec-DWhCZDGm.mjs} +65 -2
  43. package/dist/{gc-DEmkg3Xh.mjs → gc-Dh6mXOKC.mjs} +23 -469
  44. package/dist/{gradle-dJpre3Yn.mjs → gradle-C6GKnunQ.mjs} +6 -6
  45. package/dist/{guide-status-Du-ZQ3FD.mjs → guide-status-Bhf9SJXc.mjs} +3 -3
  46. package/dist/{guide-CSmhMTf8.mjs → guide-tm6igAaa.mjs} +290 -53
  47. package/dist/{hosted-android-E1Heoqnv.mjs → hosted-android-Bv285t_t.mjs} +3 -3
  48. package/dist/{hosted-client-Bp4knSwu.mjs → hosted-client-C-rMtppF.mjs} +2 -2
  49. package/dist/{hosted-ios-BnbeYOUD.mjs → hosted-ios-D5mNmtj4.mjs} +1 -1
  50. package/dist/{hosted-logs-OcgIBvCT.mjs → hosted-logs-DN8Iz4mJ.mjs} +9 -9
  51. package/dist/{hosted-macos-DcxKjtfH.mjs → hosted-macos-B-wEjlwG.mjs} +5 -5
  52. package/dist/{hosted-native-1Ebbig4w.mjs → hosted-native-DeeOG8xZ.mjs} +6 -6
  53. package/dist/{idle-shutdown-IGyNV8Cr.mjs → idle-shutdown-jjtxAn5C.mjs} +7 -8
  54. package/dist/{ios-DSfnPfse.mjs → ios-B3SbOWdw.mjs} +19 -7
  55. package/dist/{ios-Cr1h5gnO.mjs → ios-Bvbf0SGY.mjs} +1 -1
  56. package/dist/{ios-BJ4XUSe1.mjs → ios-CPdkoKaa.mjs} +181 -95
  57. package/dist/ios-DNpdygiv.mjs +7 -0
  58. package/dist/{ios-device-Ee7sDXfp.mjs → ios-device-Bn7jWDB1.mjs} +1 -1
  59. package/dist/{ios-device-pAN4t54-.mjs → ios-device-vOaByMhw.mjs} +3 -3
  60. package/dist/{ios-state-8L3lgum6.mjs → ios-state-B2pES6Vs.mjs} +1 -1
  61. package/dist/{launch-verify-lTnWZikR.mjs → launch-verify-hskNcWkZ.mjs} +5 -5
  62. package/dist/{logs-BAaS7gS2.mjs → logs-1Ylc1Ri6.mjs} +13 -13
  63. package/dist/macos-Ck7OBMNY.mjs +2 -0
  64. package/dist/{macos-BIRQS90f.mjs → macos-DF6C7wUU.mjs} +118 -34
  65. package/dist/macos-run.mjs +1 -1
  66. package/dist/maintenance-run.mjs +349 -47
  67. package/dist/{metro-g8NqiJp-.mjs → metro-Dh8T4Ytd.mjs} +5 -5
  68. package/dist/{metro-gateway-C-ijGI2F.mjs → metro-gateway-CEUw9RMH.mjs} +4 -4
  69. package/dist/{metro-store-CDDZHtPl.mjs → metro-store-BAHFcJm6.mjs} +16 -2
  70. package/dist/{named-ports-C8m8EQs2.mjs → named-ports-BFIz1Shz.mjs} +61 -6
  71. package/dist/{native-run-D1Q56rAD.mjs → native-run-B06FkmZx.mjs} +4 -4
  72. package/dist/{native-runtime-BEK171xQ.mjs → native-runtime-D_603JiC.mjs} +6 -6
  73. package/dist/{ndjson-PclOIwVY.mjs → ndjson-LGZAMsqa.mjs} +8 -4
  74. package/dist/offload-worker.d.mts +3 -17
  75. package/dist/offload-worker.mjs +10 -11
  76. package/dist/{ownership-DyRQru0q.mjs → ownership-D6Se7gg_.mjs} +3 -3
  77. package/dist/{page-QF_Ke10s.mjs → page-Bv9s2KwY.mjs} +1 -1
  78. package/dist/placement-log-BcPhRwR4.mjs +84 -0
  79. package/dist/{build-plan-BDsSi09V.mjs → plan-placement-CtxkCO54.mjs} +122 -48
  80. package/dist/{ports-4nYqxPWC.mjs → ports-BLTtfBq-.mjs} +3 -3
  81. package/dist/{prebuild-D7RUMkwN.mjs → prebuild-juCyreaR.mjs} +5 -5
  82. package/dist/preview-D5V07Nrl.mjs +987 -0
  83. package/dist/{rolldown-runtime-BsOwBuO_.mjs → process-identity-Biv3arCO.mjs} +11 -1
  84. package/dist/{project-D47Rh0ly.mjs → project-C3ChRLZy.mjs} +4 -68
  85. package/dist/projects-DD7dBTCj.mjs +92 -0
  86. package/dist/{pull-request-pxnDCQzn.mjs → pull-request-u4vp7zmK.mjs} +1 -1
  87. package/dist/pull-requests.mjs +1 -1
  88. package/dist/{recordings-BNgsD1Tr.mjs → recordings-BAWltsVt.mjs} +1 -1
  89. package/dist/{reload-DcRxj3qG.mjs → reload-DvyWzVjJ.mjs} +15 -15
  90. package/dist/{remote-cache-Ci4DQYYj.mjs → remote-cache-BGg7aGIZ.mjs} +5 -5
  91. package/dist/{run-CkE9y0nc.mjs → run-vhtDgpHO.mjs} +5 -5
  92. package/dist/{server-bare-BkrSxSsZ.mjs → server-bare-B9E7S1aR.mjs} +4 -5
  93. package/dist/server-expo-Db9HBUoa.mjs +2 -0
  94. package/dist/{server-expo-CHTyXD0G.mjs → server-expo-DoBHhuzK.mjs} +5 -6
  95. package/dist/{settings-SR9OmW9h.mjs → settings-Byp2AQ_E.mjs} +6 -5
  96. package/dist/{settings-Cfd-0r2d.mjs → settings-CQyMElEP.mjs} +24 -763
  97. package/dist/{settings-BBpMcDbD.mjs → settings-Djl-mpjX.mjs} +1 -1
  98. package/dist/settings.schema.json +126 -3
  99. package/dist/{simslim-BWNrc3M3.mjs → simslim-EHBQ2R4G.mjs} +7 -7
  100. package/dist/{slot-launch-DmjBmpQV.mjs → slot-launch-C1nqh4mu.mjs} +6 -6
  101. package/dist/{spawn-claims-D0XfSe8u.mjs → spawn-claims-Kqiifsk2.mjs} +1 -1
  102. package/dist/{spawn-entry-jw19m8Nl.mjs → spawn-entry-Dcb7sDUz.mjs} +1 -0
  103. package/dist/{stage-CzaiwFsI.mjs → stage-g_WqWeaE.mjs} +14 -3
  104. package/dist/{start-DUz3mYdb.mjs → start-D-IeOyoK.mjs} +19 -19
  105. package/dist/{start-AlfCPRVU.mjs → start-NTc1Ifqs.mjs} +1 -1
  106. package/dist/{state-PeQiJuIu.mjs → state-BG-aAk4k.mjs} +4 -4
  107. package/dist/{state-B4PQFXMW.d.mts → state-lKh8shBp.d.mts} +2 -3
  108. package/dist/{state-DyaNTgfR.mjs → state-xnqpx3AD.mjs} +2 -2
  109. package/dist/{stats-Bq4fJOdB.mjs → stats-DY6ekz8F.mjs} +5 -5
  110. package/dist/{status-DlKvVJBE.mjs → status-BEeL6IKz.mjs} +6 -4
  111. package/dist/{status-BA2pehwf.mjs → status-DCjZeE-K.mjs} +33 -34
  112. package/dist/{status-CzS4bPO9.mjs → status-Dcr0Qexd.mjs} +5 -5
  113. package/dist/{stim-desktop-Cnz8CPnl.mjs → stim-desktop-Behws_fi.mjs} +1 -1
  114. package/dist/{stim-installations-QMEI32v1.mjs → stim-installations-aR_WsNOA.mjs} +1 -1
  115. package/dist/{stop-BIiM49EY.mjs → stop-BGhKMOuH.mjs} +5 -5
  116. package/dist/{stop-DQIasgKp.mjs → stop-BTjs3xbc.mjs} +17 -18
  117. package/dist/{stop-zF1y04f2.mjs → stop-DIJtD2GL.mjs} +2 -2
  118. package/dist/supervisor-run.d.mts +24 -22
  119. package/dist/supervisor-run.mjs +21 -22
  120. package/dist/{support-CsJNVfOc.mjs → support-BaayeYCf.mjs} +7 -7
  121. package/dist/{support-WvD__tSV.mjs → support-Bwvbrq5-.mjs} +5 -5
  122. package/dist/{toolchain-DNyR3NPq.mjs → toolchain-Bnyd_K3A.mjs} +471 -22
  123. package/dist/{trigger-Bemu8ytw.mjs → trigger-CJMhwXe8.mjs} +5 -5
  124. package/dist/trigger-DWAq9hkw.mjs +2 -0
  125. package/dist/{warm-progress-DF4JRvYI.mjs → warm-progress-CjB-MP6H.mjs} +7 -7
  126. package/dist/web-B6_bFDn7.mjs +2 -0
  127. package/dist/{web-Dl0KSRHf.mjs → web-DTU0uiWj.mjs} +22 -22
  128. package/dist/web-run.mjs +10 -10
  129. package/dist/{workspace-state-DqcCbpE7.mjs → workspace-state-C59dqG-Z.mjs} +3 -3
  130. package/dist/{ownership-BMLqyBgJ.mjs → workspaces-xXItD8Dj.mjs} +577 -23
  131. package/dist/{worktree-j3IcFAI5.mjs → worktree-BJfnU6r5.mjs} +1 -1
  132. package/dist/{worktree-Be_7NLKy.mjs → worktree-BSYlofkq.mjs} +234 -35
  133. package/dist/worktree-CsKYexJM.mjs +753 -0
  134. package/package.json +10 -5
  135. package/dist/build-progress-D0WkjCPd.mjs +0 -1036
  136. package/dist/build-slots-41v_d2x9.mjs +0 -142
  137. package/dist/cli-CYXb29oE.mjs +0 -51
  138. package/dist/deps-iKw0eD4P.mjs +0 -438
  139. package/dist/errors-B6W7FkxQ.mjs +0 -15
  140. package/dist/idle-BXG__1BA.mjs +0 -176
  141. package/dist/in-use-CvGOUn-x.mjs +0 -130
  142. package/dist/preview-B-g9d7kV.mjs +0 -318
  143. package/dist/process-identity-BmRm1qV0.mjs +0 -12
  144. package/dist/server-expo-CeakhI8P.mjs +0 -2
  145. package/dist/state-BKa8wNN5.mjs +0 -148
  146. package/dist/stop-cause-rhmGfwvt.mjs +0 -97
  147. package/dist/trigger-CXts6qt1.mjs +0 -2
  148. package/dist/watchman-APYjXSQa.mjs +0 -48
  149. package/dist/workspace-process-lock-2mNzOlaB.mjs +0 -58
  150. package/dist/workspaces-Bcib97-6.mjs +0 -306
@@ -1,148 +0,0 @@
1
- import { B as parseDeviceSlotKey, R as deviceSlotKey } from "./config-D0DbpZtM.mjs";
2
- import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
3
- import { C as workspaceStateFile, a as updateWorkspaceState, h as supervisorPidFile, o as withWorkspaceStateLock, r as readWorkspaceState, t as clearWorkspaceStateKey } from "./workspace-state-DqcCbpE7.mjs";
4
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
- import { dirname } from "node:path";
6
- //#region src/supervisor/state.ts
7
- const MODE_BARE = "bare-inproc";
8
- const MODE_EXPO = "expo-child";
9
- function readMetroTunnel(root) {
10
- const record = readWorkspaceState(root)?.metroTunnel;
11
- if (!record || typeof record !== "object") return null;
12
- const kind = record.kind;
13
- const url = record.url;
14
- if (typeof url !== "string" || url.length === 0) return null;
15
- if (kind === "expo") return {
16
- kind: "expo",
17
- url
18
- };
19
- if (kind === "managed") {
20
- const provider = record.provider;
21
- const pid = record.pid;
22
- const port = record.port;
23
- const startedAt = record.startedAt;
24
- const processToken = record.processToken;
25
- const logFile = record.logFile;
26
- if (provider !== "ngrok" && provider !== "cloudflared" && provider !== "tailscale" || typeof pid !== "number" || typeof port !== "number") return null;
27
- return {
28
- kind: "managed",
29
- provider,
30
- pid,
31
- url,
32
- port,
33
- startedAt: typeof startedAt === "string" ? startedAt : "",
34
- processToken: typeof processToken === "string" && processToken.length > 0 ? processToken : null,
35
- ...typeof logFile === "string" && logFile.length > 0 ? { logFile } : {}
36
- };
37
- }
38
- return null;
39
- }
40
- function parseWorkspaceLaunchRecord(value) {
41
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
42
- const record = value;
43
- if (typeof record.appId !== "string" || record.appId.length === 0) return null;
44
- if (typeof record.deviceId !== "string" || record.deviceId.length === 0) return null;
45
- if (record.metroPort !== null && typeof record.metroPort !== "number") return null;
46
- if (typeof record.release !== "boolean") return null;
47
- if (typeof record.launchedAt !== "string") return null;
48
- return record;
49
- }
50
- function readWorkspaceLaunches(root) {
51
- const launches = readWorkspaceState(root)?.launches;
52
- if (!launches || typeof launches !== "object" || Array.isArray(launches)) return {};
53
- const records = {};
54
- for (const [key, value] of Object.entries(launches)) {
55
- const record = parseWorkspaceLaunchRecord(value);
56
- if (parseDeviceSlotKey(key) && record) records[key] = record;
57
- }
58
- return records;
59
- }
60
- function writeWorkspaceLaunch(root, platform, record, slot = "default") {
61
- updateWorkspaceState(root, (state) => {
62
- const launches = state.launches && typeof state.launches === "object" ? state.launches : {};
63
- return {
64
- ...state,
65
- launches: {
66
- ...launches,
67
- [deviceSlotKey(platform, slot)]: record
68
- }
69
- };
70
- });
71
- }
72
- function clearWorkspaceLaunches(root, slot) {
73
- updateWorkspaceState(root, (state) => {
74
- if (!state.launches || typeof state.launches !== "object") return state;
75
- const launches = { ...state.launches };
76
- delete launches[deviceSlotKey("ios", slot)];
77
- delete launches[deviceSlotKey("android", slot)];
78
- return {
79
- ...state,
80
- launches
81
- };
82
- });
83
- }
84
- function readRemoteSession(root) {
85
- const record = readWorkspaceState(root)?.remoteDevice;
86
- if (!record || typeof record !== "object") return null;
87
- const id = record.sessionId;
88
- if (typeof id !== "string" || id.length === 0) return null;
89
- const platform = record.platform;
90
- const startedAt = record.startedAt;
91
- const webPreviewUrl = record.webPreviewUrl;
92
- const deviceType = record.deviceType;
93
- return {
94
- platform: platform === "ios" || platform === "android" ? platform : null,
95
- sessionId: id,
96
- startedAt: typeof startedAt === "string" ? startedAt : null,
97
- webPreviewUrl: typeof webPreviewUrl === "string" && webPreviewUrl.length > 0 ? webPreviewUrl : null,
98
- deviceType: typeof deviceType === "string" && deviceType.length > 0 ? deviceType : null
99
- };
100
- }
101
- function readRemoteSessionId(root) {
102
- return readRemoteSession(root)?.sessionId ?? null;
103
- }
104
- function clearRemoteSession(root, expectedSessionId) {
105
- clearWorkspaceStateKey(root, "remoteDevice", (value) => {
106
- if (typeof value !== "object" || value === null) return false;
107
- return value.sessionId === expectedSessionId;
108
- });
109
- }
110
- function clearWorkspaceSupervisor(root, expected) {
111
- return withWorkspaceStateLock(root, () => {
112
- const current = readWorkspaceState(root)?.supervisor;
113
- if (current && expected !== void 0 && !(0, process_identity_exports.sameProcessRecord)(current, expected)) return false;
114
- clearWorkspaceStateKey(root, "supervisor", () => true);
115
- clearExpoMetroTunnel(root);
116
- if (expected === void 0 || readPidFile(root) === expected?.pid) rmSync(supervisorPidFile(root), { force: true });
117
- return true;
118
- });
119
- }
120
- function clearExpoMetroTunnel(root) {
121
- clearWorkspaceStateKey(root, "metroTunnel", (value) => {
122
- return typeof value === "object" && value !== null && value.kind === "expo";
123
- });
124
- }
125
- function clearManagedMetroTunnel(root, expected) {
126
- if (!existsSync(workspaceStateFile(root))) return true;
127
- return clearWorkspaceStateKey(root, "metroTunnel", (value) => {
128
- if (typeof value !== "object" || value === null) return false;
129
- const record = value;
130
- return record.kind === "managed" && record.provider === expected.provider && record.pid === expected.pid && record.url === expected.url && record.port === expected.port && record.startedAt === expected.startedAt && (record.processToken ?? null) === (expected.processToken ?? null) && (record.logFile ?? null) === (expected.logFile ?? null);
131
- });
132
- }
133
- function writePidFile(root, pid) {
134
- const file = supervisorPidFile(root);
135
- mkdirSync(dirname(file), { recursive: true });
136
- writeFileSync(file, `${pid}\n`);
137
- return file;
138
- }
139
- function readPidFile(root) {
140
- try {
141
- const pid = parseInt(readFileSync(supervisorPidFile(root), "utf-8").trim(), 10);
142
- return Number.isFinite(pid) ? pid : null;
143
- } catch {
144
- return null;
145
- }
146
- }
147
- //#endregion
148
- export { clearRemoteSession as a, readMetroTunnel as c, readRemoteSessionId as d, readWorkspaceLaunches as f, clearManagedMetroTunnel as i, readPidFile as l, writeWorkspaceLaunch as m, MODE_EXPO as n, clearWorkspaceLaunches as o, writePidFile as p, clearExpoMetroTunnel as r, clearWorkspaceSupervisor as s, MODE_BARE as t, readRemoteSession as u };
@@ -1,97 +0,0 @@
1
- import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
2
- import { c as writeWorkspaceState, t as clearWorkspaceStateKey, x as workspaceLogsDir$1 } from "./workspace-state-DqcCbpE7.mjs";
3
- import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
4
- import { join } from "node:path";
5
- import { LOG_ROTATE_BYTES } from "@stim-cli/core";
6
- import { DEV_SERVER_STOP_REQUEST_KEY, readDevServerStop, readDevServerStopRequest } from "@stim-cli/core/state";
7
- //#region src/supervisor/stop-cause.ts
8
- function requestDevServerStop(root, processToken, requester) {
9
- if (!processToken) return;
10
- try {
11
- writeWorkspaceState(root, { [DEV_SERVER_STOP_REQUEST_KEY]: {
12
- processToken,
13
- by: requester.by,
14
- pid: process.pid,
15
- at: (/* @__PURE__ */ new Date()).toISOString(),
16
- ...requester.workspace ? { workspace: requester.workspace } : {}
17
- } });
18
- } catch {}
19
- }
20
- function withdrawDevServerStopRequest(root, processToken) {
21
- if (!processToken) return;
22
- try {
23
- clearWorkspaceStateKey(root, DEV_SERVER_STOP_REQUEST_KEY, (value) => {
24
- return readDevServerStopRequest({ [DEV_SERVER_STOP_REQUEST_KEY]: value })?.processToken === processToken;
25
- });
26
- } catch {}
27
- }
28
- function devServerStopRecord(trigger, request, at) {
29
- if (request) return {
30
- reason: "requested",
31
- at,
32
- by: request.by,
33
- byPid: request.pid,
34
- ...request.workspace ? { byWorkspace: request.workspace } : {}
35
- };
36
- return trigger.kind === "signal" ? {
37
- reason: "signal",
38
- at,
39
- signal: trigger.signal
40
- } : {
41
- reason: "server-exited",
42
- at,
43
- mode: trigger.mode,
44
- code: trigger.code,
45
- signal: trigger.signal
46
- };
47
- }
48
- function describeDevServerStop(record) {
49
- if (record.reason === "idle") return `idle for ${record.idleMinutes} minutes (metro.idleStopMinutes)`;
50
- if (record.reason === "requested") return `stop requested by ${record.by} (pid ${record.byPid}${record.byWorkspace ? ` in ${record.byWorkspace}` : ""})`;
51
- if (record.reason === "signal") return `received ${record.signal} with no Stim stop request recorded, so it likely came from outside Stim`;
52
- const detail = record.signal ? `signal ${record.signal}` : `exit code ${record.code ?? "unknown"}`;
53
- const expoSignal = record.mode === "expo-child" && record.code === 0 ? "; Expo CLI also exits 0 on SIGTERM, and no Stim stop request was recorded" : "";
54
- return `the ${record.mode} dev server exited unexpectedly (${detail})${expoSignal}`;
55
- }
56
- function devServerStopLevel(record) {
57
- if (record.reason === "server-exited") return "error";
58
- return record.reason === "signal" ? "warn" : "info";
59
- }
60
- /** The log line for a recorded supervisor whose process is proven gone, or null while it may still run. */
61
- function vanishedSupervisorMessage(record) {
62
- if (!record || typeof record.pid !== "number") return null;
63
- const identity = (0, process_identity_exports.inspectProcessIdentity)(record);
64
- if (identity !== "gone" && identity !== "different") return null;
65
- const started = typeof record.startedAt === "string" ? ` (started ${record.startedAt})` : "";
66
- return `supervisor pid ${record.pid}${started} ${VANISHED}`;
67
- }
68
- const VANISHED = "is gone and recorded no cause: usually SIGKILL, a crash or a machine restart";
69
- function logVanishedSupervisor(root, record) {
70
- const msg = vanishedSupervisorMessage(record);
71
- if (!msg) return;
72
- const writer = createNdjsonWriter(join(workspaceLogsDir$1(root), "metro.ndjson"), { maxBytes: LOG_ROTATE_BYTES });
73
- writer.write({
74
- src: "metro",
75
- level: "warn",
76
- event: "supervisor_vanished",
77
- msg
78
- });
79
- writer.close();
80
- }
81
- /** The recorded stop, else a vanished supervisor when status proved the recorded one gone. */
82
- function metroLastStop(state, supervisor) {
83
- const recorded = readDevServerStop(state);
84
- if (recorded) return recorded;
85
- if (supervisor?.status !== "stale" || typeof supervisor.pid !== "number") return null;
86
- const startedAt = typeof supervisor.startedAt === "string" ? supervisor.startedAt : null;
87
- return {
88
- reason: "vanished",
89
- pid: supervisor.pid,
90
- startedAt
91
- };
92
- }
93
- function describeMetroLastStop(stop) {
94
- return stop.reason === "vanished" ? `supervisor pid ${stop.pid} ${VANISHED}` : describeDevServerStop(stop);
95
- }
96
- //#endregion
97
- export { logVanishedSupervisor as a, vanishedSupervisorMessage as c, devServerStopRecord as i, withdrawDevServerStopRequest as l, describeMetroLastStop as n, metroLastStop as o, devServerStopLevel as r, requestDevServerStop as s, describeDevServerStop as t };
@@ -1,2 +0,0 @@
1
- import { t as triggerMaintenance } from "./trigger-Bemu8ytw.mjs";
2
- export { triggerMaintenance };
@@ -1,48 +0,0 @@
1
- import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
- //#region src/watchman.ts
3
- /** Runs one watchman command with `--no-spawn`, so Stim never starts a daemon, and parses its JSON answer. */
4
- const runWatchman = async (args, timeoutMs) => JSON.parse(await getExecutor().runFileAsync("watchman", ["--no-spawn", ...args], { timeoutMs }));
5
- function parseWatchRoots(payload) {
6
- const roots = payload?.roots;
7
- if (!Array.isArray(roots)) return null;
8
- return roots.filter((root) => typeof root === "string");
9
- }
10
- function parseSubscriberNames(payload) {
11
- if (!payload || typeof payload !== "object" || "error" in payload) return null;
12
- const subscribers = payload.subscribers;
13
- if (subscribers === void 0) return [];
14
- if (!Array.isArray(subscribers)) return null;
15
- const names = [];
16
- for (const subscriber of subscribers) {
17
- const name = subscriber?.info?.name;
18
- if (typeof name !== "string") return null;
19
- names.push(name);
20
- }
21
- return names;
22
- }
23
- function parseTriggerCount(payload) {
24
- const triggers = payload?.triggers;
25
- return Array.isArray(triggers) ? triggers.length : null;
26
- }
27
- function parseWatchmanPid(payload) {
28
- const pid = payload?.pid;
29
- return typeof pid === "number" && Number.isInteger(pid) && pid > 0 ? pid : null;
30
- }
31
- /** The connected clients in a `debug-status` answer, or null when the answer does not list them. */
32
- function parseWatchmanClients(payload) {
33
- if (!payload || typeof payload !== "object" || "error" in payload) return null;
34
- const clients = payload.clients;
35
- if (!Array.isArray(clients)) return null;
36
- const parsed = [];
37
- for (const client of clients) {
38
- const peer = client?.peer;
39
- if (typeof peer?.pid !== "number") return null;
40
- parsed.push({
41
- pid: peer.pid,
42
- name: typeof peer.name === "string" ? peer.name : null
43
- });
44
- }
45
- return parsed;
46
- }
47
- //#endregion
48
- export { parseWatchmanPid as a, parseWatchmanClients as i, parseTriggerCount as n, runWatchman as o, parseWatchRoots as r, parseSubscriberNames as t };
@@ -1,58 +0,0 @@
1
- import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
2
- import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-D0XfSe8u.mjs";
3
- import { join } from "node:path";
4
- import { setTimeout } from "node:timers/promises";
5
- //#region src/engine/workspace-process-lock.ts
6
- const DEFAULT_WAIT_MS = 6e4;
7
- const POLL_MS = 25;
8
- function workspaceProcessLockError(err) {
9
- const code = err?.code;
10
- if (code === "STIM_LOCK_REFUSED") return "refused";
11
- if (code === "STIM_LOCK_TIMEOUT") return "timeout";
12
- return null;
13
- }
14
- function workspaceProcessLockPath(root, name, external) {
15
- return external ? join(root, `${name}.lock`) : join(root, ".stim", `${name}.lock`);
16
- }
17
- async function withWorkspaceProcessLock(root, name, fn, { now = Date.now, signal, sleep = (ms) => setTimeout(ms, void 0, { signal }), waitMs = DEFAULT_WAIT_MS, ownerPurpose, details = {}, onHeld, rejectOwnerPurposes = [], external = false, declareSpawns = false } = {}) {
18
- const path = workspaceProcessLockPath(root, name, external);
19
- const deadline = now() + waitMs;
20
- for (;;) {
21
- signal?.throwIfAborted();
22
- const attempt = (0, ownership_claim_exports.tryAcquireClaim)({
23
- root: path,
24
- mode: "exclusive",
25
- label: `${name} lock`,
26
- details: ownerPurpose ? {
27
- ...details,
28
- purpose: ownerPurpose
29
- } : details
30
- });
31
- if (attempt.pending) (0, ownership_claim_exports.releaseClaim)(attempt.pending);
32
- if (attempt.acquired) {
33
- if (declareSpawns) declareSpawnsOn(attempt.acquired);
34
- try {
35
- return await fn(attempt.acquired);
36
- } finally {
37
- stopDeclaringSpawnsOn(attempt.acquired);
38
- (0, ownership_claim_exports.releaseClaim)(attempt.acquired);
39
- }
40
- }
41
- const holder = attempt.held ?? attempt.waitingFor?.[0];
42
- const purpose = holder?.details.purpose;
43
- if (typeof purpose === "string" && rejectOwnerPurposes.includes(purpose)) {
44
- const error = /* @__PURE__ */ new Error(`The ${name} lock at ${path} is held for ${purpose}.`);
45
- error.code = "STIM_LOCK_REFUSED";
46
- throw error;
47
- }
48
- if (holder && onHeld) await onHeld(holder);
49
- if (now() >= deadline) {
50
- const error = /* @__PURE__ */ new Error(`Timed out waiting for the ${name} lock at ${path}.`);
51
- error.code = "STIM_LOCK_TIMEOUT";
52
- throw error;
53
- }
54
- await sleep(POLL_MS);
55
- }
56
- }
57
- //#endregion
58
- export { workspaceProcessLockError as n, workspaceProcessLockPath as r, withWorkspaceProcessLock as t };
@@ -1,306 +0,0 @@
1
- import { M as isOnMountedVolume, N as listMountedVolumes, P as measuredDirectorySize, _ as loadConfig$1, d as getConfigDir, g as isPathPrefix, j as formatBytes } from "./config-D0DbpZtM.mjs";
2
- import { S as workspaceName, s as workspaceLastUsed } from "./workspace-state-DqcCbpE7.mjs";
3
- import { i as recordGcResult, n as withIdleWorkspace, o as canonicalPath, r as workspaceInUse, t as emptyWorkspaceDir } from "./in-use-CvGOUn-x.mjs";
4
- import { h as teardownOwnedBrowser } from "./ownership-BMLqyBgJ.mjs";
5
- import { existsSync, lstatSync, readdirSync, rmSync, statSync } from "fs";
6
- import { basename, isAbsolute, join, relative } from "path";
7
- import { isJsonObject, readJsonFile } from "@stim-cli/core/state";
8
- import chalk from "chalk";
9
- //#region src/commands/gc/workspaces.ts
10
- function workspacesRoot() {
11
- return join(getConfigDir(), "workspaces");
12
- }
13
- function isInsideWorkspaces(dir) {
14
- const rel = relative(canonicalPath(workspacesRoot()), canonicalPath(dir));
15
- return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
16
- }
17
- function readRecordedRoot(dir, name) {
18
- let parsed;
19
- try {
20
- parsed = readJsonFile(join(dir, "workspace.json"));
21
- } catch (error) {
22
- return {
23
- projectRoot: null,
24
- problem: error?.code === "ENOENT" ? "it has no workspace.json" : "its workspace.json does not parse"
25
- };
26
- }
27
- const projectRoot = isJsonObject(parsed) ? parsed.projectRoot : void 0;
28
- if (typeof projectRoot !== "string" || !isAbsolute(projectRoot)) return {
29
- projectRoot: null,
30
- problem: "its workspace.json records no absolute project root"
31
- };
32
- if (workspaceName(projectRoot) !== name) return {
33
- projectRoot: null,
34
- problem: `its workspace.json records ${projectRoot}, whose workspace directory has another name`
35
- };
36
- return {
37
- projectRoot,
38
- problem: null
39
- };
40
- }
41
- function listWorkspaceDirs() {
42
- const root = workspacesRoot();
43
- let names;
44
- try {
45
- names = readdirSync(root).toSorted();
46
- } catch {
47
- return [];
48
- }
49
- const entries = [];
50
- for (const name of names) {
51
- const dir = join(root, name);
52
- try {
53
- if (!statSync(dir).isDirectory()) continue;
54
- } catch {
55
- continue;
56
- }
57
- entries.push({
58
- dir,
59
- ...readRecordedRoot(dir, name)
60
- });
61
- }
62
- return entries;
63
- }
64
- function classifyWorkspaceDirs(entries, { registryKeys, exists, isMounted, inUse }) {
65
- const orphaned = [];
66
- const skipped = [];
67
- for (const { dir, projectRoot, problem } of entries) {
68
- if (projectRoot === null) {
69
- skipped.push({
70
- dir,
71
- reason: `workspace directory not resolved: ${problem ?? "unknown project root"}`
72
- });
73
- continue;
74
- }
75
- const present = exists(projectRoot);
76
- if (present === null) {
77
- skipped.push({
78
- dir,
79
- reason: `cannot tell whether its project root ${projectRoot} still exists`
80
- });
81
- continue;
82
- }
83
- if (present) continue;
84
- if (registryKeys.some((key) => isPathPrefix(projectRoot, key))) continue;
85
- if (!isMounted(projectRoot)) {
86
- skipped.push({
87
- dir,
88
- reason: `the volume of its project root ${projectRoot} is not mounted`
89
- });
90
- continue;
91
- }
92
- const reasons = inUse(projectRoot);
93
- if (reasons.length) {
94
- skipped.push({
95
- dir,
96
- reason: `its project root ${projectRoot} is gone, but ${reasons.join("; ")}`
97
- });
98
- continue;
99
- }
100
- orphaned.push({
101
- dir,
102
- projectRoot
103
- });
104
- }
105
- return {
106
- orphaned,
107
- skipped
108
- };
109
- }
110
- function rootPresence(path) {
111
- try {
112
- lstatSync(path);
113
- return true;
114
- } catch (error) {
115
- const code = error?.code;
116
- return code === "ENOENT" || code === "ENOTDIR" ? false : null;
117
- }
118
- }
119
- function collectOrphanedWorkspaces(registryKeys, mountedVolumes, { measure = true } = {}) {
120
- const classified = classifyWorkspaceDirs(listWorkspaceDirs(), {
121
- registryKeys,
122
- exists: rootPresence,
123
- isMounted: (path) => isOnMountedVolume(path, mountedVolumes),
124
- inUse: (root) => workspaceInUse(root)
125
- });
126
- return {
127
- orphaned: measure ? classified.orphaned.map((entry) => Object.assign({}, entry, { bytes: sizeOf(entry.dir) })) : classified.orphaned,
128
- skipped: classified.skipped
129
- };
130
- }
131
- const REBUILD_COST = "The next build of an unchanged app installs from the shared build cache; after a native change the compilation cache speeds the rebuild, but on React Native 0.86 Swift does not use it (explicit modules are off), so that build recompiles Swift. The next stim macos in a cleared workspace is a full Swift build.";
132
- const WORKSPACE_OUTPUT_DIRS = [
133
- "derived-data",
134
- "gradle-build",
135
- "android-cas",
136
- "cache-provider"
137
- ];
138
- const DAY_MS = 864e5;
139
- function planWorkspaceOutputs(entries, { olderThan, now }) {
140
- return entries.map(({ dir, projectRoot, problem, bytes, lastUsed, inUse }) => {
141
- const idleDays = Number.isFinite(lastUsed) ? Math.max(0, Math.floor((now - lastUsed) / DAY_MS)) : null;
142
- const [keptCode, keptReason] = projectRoot === null ? ["unresolved", `workspace directory not resolved: ${problem ?? "unknown project root"}`] : inUse.length ? ["in-use", `in use: ${inUse.join("; ")}`] : olderThan === null ? [null, null] : idleDays === null ? ["last-use-unknown", "its last use is unknown"] : idleDays < olderThan ? ["recently-used", `used ${idleDays}d ago, within --older-than ${olderThan}`] : [null, null];
143
- return {
144
- dir,
145
- projectRoot,
146
- bytes,
147
- idleDays,
148
- willClear: keptCode === null,
149
- keptCode,
150
- keptReason
151
- };
152
- });
153
- }
154
- const SIZE_TIMEOUT_MS = 6e4;
155
- function sizeOf(dir, timeoutMs = SIZE_TIMEOUT_MS) {
156
- return measuredDirectorySize(dir, { timeoutMs });
157
- }
158
- function outputPaths(dir) {
159
- const paths = WORKSPACE_OUTPUT_DIRS.map((name) => join(dir, name)).filter((path) => existsSync(path));
160
- const macos = join(dir, "macos");
161
- try {
162
- if (!lstatSync(macos).isDirectory()) return paths;
163
- for (const entry of readdirSync(macos, { withFileTypes: true })) if (entry.name === "build" || entry.name.endsWith(".app") || entry.name.startsWith("staging-") && entry.isDirectory()) paths.push(join(macos, entry.name));
164
- } catch {}
165
- return paths;
166
- }
167
- function outputBytes(paths, timeoutMs) {
168
- let total = 0;
169
- for (const path of paths) {
170
- const size = sizeOf(path, timeoutMs);
171
- if (size === null) return null;
172
- total += size;
173
- }
174
- return total;
175
- }
176
- function collectWorkspaceOutputs({ olderThan, now, exclude = [], measure = true, sizeTimeoutMs = SIZE_TIMEOUT_MS }) {
177
- const mountedVolumes = listMountedVolumes();
178
- const entries = listWorkspaceDirs().filter((entry) => !exclude.includes(entry.dir)).filter((entry) => entry.projectRoot === null || isOnMountedVolume(entry.projectRoot, mountedVolumes)).map((entry) => Object.assign({}, entry, { paths: outputPaths(entry.dir) })).filter((entry) => entry.paths.length > 0).map(({ paths, ...entry }) => Object.assign({}, entry, { bytes: measure ? outputBytes(paths, sizeTimeoutMs) : null })).map((entry) => Object.assign({}, entry, {
179
- lastUsed: entry.projectRoot === null ? NaN : workspaceLastUsed(entry.projectRoot),
180
- inUse: entry.projectRoot === null ? [] : workspaceInUse(entry.projectRoot)
181
- }));
182
- return {
183
- root: workspacesRoot(),
184
- workspaces: planWorkspaceOutputs(entries, {
185
- olderThan,
186
- now
187
- })
188
- };
189
- }
190
- async function clearWorkspaceOutputs(report, { olderThan, now = Date.now() }) {
191
- let failures = 0;
192
- let cleared = 0;
193
- const clearedRoots = [];
194
- for (const entry of report.workspaces) {
195
- const root = entry.projectRoot;
196
- if (!entry.willClear || root === null) {
197
- if (entry.keptReason) {
198
- console.log(chalk.dim(`Kept the build outputs of ${root ?? entry.dir}: ${entry.keptReason}`));
199
- recordGcResult("workspaceOutputs", "kept", root ?? entry.dir, {
200
- bytes: entry.bytes,
201
- detail: entry.keptReason
202
- });
203
- }
204
- continue;
205
- }
206
- let run;
207
- try {
208
- run = await withIdleWorkspace(root, () => {
209
- const [again] = planWorkspaceOutputs([{
210
- ...entry,
211
- problem: null,
212
- lastUsed: workspaceLastUsed(root),
213
- inUse: []
214
- }], {
215
- olderThan,
216
- now
217
- });
218
- if (again?.keptReason) return again.keptReason;
219
- for (const path of outputPaths(entry.dir)) rmSync(path, {
220
- recursive: true,
221
- force: true
222
- });
223
- return null;
224
- }, { purpose: "gc" });
225
- } catch (error) {
226
- failures++;
227
- console.log(chalk.red(`Could not clear the build outputs of ${root}: ${error?.message || String(error)}`));
228
- recordGcResult("workspaceOutputs", "failed", root, {
229
- bytes: entry.bytes,
230
- detail: error?.message || String(error)
231
- });
232
- continue;
233
- }
234
- const kept = run.ran ? run.value : `in use: ${run.reasons.join("; ")}`;
235
- if (kept) {
236
- console.log(chalk.yellow(`Kept the build outputs of ${root}: ${kept}`));
237
- recordGcResult("workspaceOutputs", "kept", root, {
238
- bytes: entry.bytes,
239
- detail: kept
240
- });
241
- continue;
242
- }
243
- cleared += entry.bytes ?? 0;
244
- clearedRoots.push(root);
245
- console.log(chalk.green(`Cleared the build outputs of ${root} (${sizeText(entry.bytes)})`));
246
- recordGcResult("workspaceOutputs", "done", root, { bytes: entry.bytes });
247
- }
248
- if (cleared) console.log(chalk.dim(`Cleared ${formatBytes(cleared)} of workspace build outputs. ${REBUILD_COST}`));
249
- return {
250
- failures,
251
- cleared: clearedRoots
252
- };
253
- }
254
- function stillOrphaned({ dir, projectRoot }) {
255
- if (readRecordedRoot(dir, basename(dir)).projectRoot !== projectRoot || rootPresence(projectRoot) !== false || !isOnMountedVolume(projectRoot)) return false;
256
- return !Object.keys(loadConfig$1()?.projects ?? {}).some((key) => isPathPrefix(projectRoot, key));
257
- }
258
- async function deleteOrphanedWorkspaces(orphaned) {
259
- let failures = 0;
260
- for (const entry of orphaned) {
261
- if (!existsSync(entry.dir)) continue;
262
- let run;
263
- try {
264
- run = await withIdleWorkspace(entry.projectRoot, async () => {
265
- if (!stillOrphaned(entry)) return false;
266
- const browser = await teardownOwnedBrowser(entry.projectRoot, { deleteProfile: true });
267
- if (browser.status === "failed" || browser.status === "skipped") throw new Error(`its owned Chrome profile was kept: ${browser.reason}`);
268
- emptyWorkspaceDir(entry.dir);
269
- return true;
270
- }, { purpose: "gc" });
271
- } catch (error) {
272
- failures++;
273
- console.log(chalk.red(`Could not remove ${entry.dir}: ${error?.message || error}`));
274
- recordGcResult("workspaceDirectory", "failed", entry.dir, {
275
- bytes: entry.bytes ?? null,
276
- detail: error?.message || String(error)
277
- });
278
- continue;
279
- }
280
- if (!run.ran) {
281
- console.log(chalk.yellow(`Kept ${entry.dir}: ${run.reasons.join("; ")}`));
282
- recordGcResult("workspaceDirectory", "kept", entry.dir, {
283
- bytes: entry.bytes ?? null,
284
- detail: run.reasons.join("; ")
285
- });
286
- continue;
287
- }
288
- if (!run.value) {
289
- console.log(chalk.yellow(`Kept ${entry.dir}: it can no longer be confirmed orphaned.`));
290
- recordGcResult("workspaceDirectory", "kept", entry.dir, {
291
- bytes: entry.bytes ?? null,
292
- detail: "it can no longer be confirmed orphaned"
293
- });
294
- continue;
295
- }
296
- const size = entry.bytes === void 0 ? "" : ` (${sizeText(entry.bytes)})`;
297
- console.log(chalk.green(`Removed the orphaned workspace directory ${entry.dir}${size}`));
298
- recordGcResult("workspaceDirectory", "done", entry.dir, { bytes: entry.bytes ?? null });
299
- }
300
- return failures;
301
- }
302
- function sizeText(bytes) {
303
- return bytes === null ? "size unknown" : formatBytes(bytes);
304
- }
305
- //#endregion
306
- export { collectWorkspaceOutputs as a, listWorkspaceDirs as c, collectOrphanedWorkspaces as i, rootPresence as l, WORKSPACE_OUTPUT_DIRS as n, deleteOrphanedWorkspaces as o, clearWorkspaceOutputs as r, isInsideWorkspaces as s, REBUILD_COST as t, sizeText as u };