stim 1.18.0 → 1.20.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 (178) hide show
  1. package/README.md +21 -4
  2. package/dist/{activity-BxnkDZDi.mjs → activity-BrGh9EAI.mjs} +3 -3
  3. package/dist/{agent-device-usage-output-CZ66YA4T.mjs → agent-device-usage-output-DVyv_hWj.mjs} +7 -7
  4. package/dist/android-0vv-OruW.mjs +6 -0
  5. package/dist/android-Brx6EKvJ.mjs +1258 -0
  6. package/dist/{android-DC3ZLuw0.mjs → android-BsYNR81W.mjs} +103 -45
  7. package/dist/{android-CBwCNicO.mjs → android-CK3fpEyZ.mjs} +2 -2
  8. package/dist/{android-cas-BBFyr9CA.mjs → android-cas-DCAuXryb.mjs} +9 -5
  9. package/dist/android-cas-compiler.mjs +1 -1
  10. package/dist/api-run.mjs +159 -8
  11. package/dist/{api-D0VtFhqk.mjs → api-zuX3ynYN.mjs} +9 -7
  12. package/dist/api.d.mts +104 -4
  13. package/dist/api.mjs +1 -1
  14. package/dist/{app-install-D-PUENug.mjs → app-install-0LgaQRT7.mjs} +39 -18
  15. package/dist/artifact-CnC0mfov.mjs +807 -0
  16. package/dist/artifact-DClXJNWx.mjs +772 -0
  17. package/dist/artifact-lifecycle-DzPpBYvK.mjs +30 -0
  18. package/dist/{web-DTU0uiWj.mjs → browser-web-CzBmhmgs.mjs} +136 -174
  19. package/dist/{budget-DIhL2BKx.mjs → budget-BONq9vXY.mjs} +3096 -3244
  20. package/dist/build-BixRI6sB.mjs +462 -0
  21. package/dist/build-plan-CP0tckNU.mjs +553 -0
  22. package/dist/{cache-manifest-BI7ozfmH.mjs → cache-manifest-qA3dT2x2.mjs} +1 -1
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/ccache-CjHQ5F8g.mjs +142 -0
  25. package/dist/{chrome-DJnmnS5q.mjs → chrome-Dp2lMLBe.mjs} +1 -1
  26. package/dist/{cli-DNJMwADx.mjs → cli-B2R8wH1F.mjs} +20 -20
  27. package/dist/cli.mjs +1 -1
  28. package/dist/{client-DzhapoMB.mjs → client-BLy1Pw2V.mjs} +172 -165
  29. package/dist/collector-run.d.mts +10 -0
  30. package/dist/collector-run.mjs +7 -7
  31. package/dist/{command-output-CBtzyIgF.mjs → command-output-BjPN99ZB.mjs} +2 -2
  32. package/dist/{config-CgYMahz7.mjs → config-D0LhTY3S.mjs} +13 -13
  33. package/dist/{created-devices-DKbeWsiK.mjs → created-devices-HU_DAb_Q.mjs} +7 -6
  34. package/dist/{dependency-state-xKoOypBm.mjs → dependency-state-B2m8eqsS.mjs} +2 -2
  35. package/dist/{detached-entry-BLfcgc4O.mjs → detached-entry-BXq4fIl-.mjs} +1 -1
  36. package/dist/{dev-client-CLnIH02x.mjs → dev-client-ClATaJoH.mjs} +2 -2
  37. package/dist/{device-D7oCHGWi.mjs → device-B7lsC0K1.mjs} +8 -8
  38. package/dist/device-DVCwAFlX.mjs +727 -0
  39. package/dist/{device-capacity-EUOOYr8T.mjs → device-capacity-Ca_ke1LE.mjs} +25 -15
  40. package/dist/device-host-worker.mjs +38 -18
  41. package/dist/{device-ios-6MewKKnc.mjs → device-ios-CRUqPxKw.mjs} +12 -11
  42. package/dist/{device-lease-Co-EwifR.mjs → device-lease-DHOBXGgS.mjs} +135 -22
  43. package/dist/{device-lease-run-w1xhCqIW.mjs → device-lease-run-CvDeHTkG.mjs} +4 -4
  44. package/dist/{device-pool-F5WvRPtD.mjs → device-pool-L2-5GxMy.mjs} +3 -3
  45. package/dist/{device-remote-tHbd1fKy.mjs → device-remote-Bmg42063.mjs} +17 -69
  46. package/dist/doctor-C2MSuMMg.mjs +515 -0
  47. package/dist/{doctor-B9ckYUoU.mjs → doctor-DPAqhVCK.mjs} +334 -721
  48. package/dist/doctor-watchman-CB4NnVZm.mjs +260 -0
  49. package/dist/{simslim-EHBQ2R4G.mjs → eas-build-Dw_ec2Km.mjs} +6 -152
  50. package/dist/{stim-installations-aR_WsNOA.mjs → eas-session-ledger-DZlC-Fq3.mjs} +57 -4
  51. package/dist/{error-diagnostics-BRXOqDzG.mjs → error-diagnostics-Du7I_GuY.mjs} +17 -12
  52. package/dist/errors-DzkMYh8Q.mjs +205 -0
  53. package/dist/{exec-DWhCZDGm.mjs → exec-B81Qodjn.mjs} +69 -15
  54. package/dist/{gc-Dh6mXOKC.mjs → gc-PWp34zGb.mjs} +23 -22
  55. package/dist/{gradle-C6GKnunQ.mjs → gradle-C2OEKCCI.mjs} +50 -125
  56. package/dist/{guide-tm6igAaa.mjs → guide-Dai9lphv.mjs} +862 -538
  57. package/dist/{hosted-android-Bv285t_t.mjs → hosted-android-DQ-Agsd8.mjs} +5 -5
  58. package/dist/{hosted-client-C-rMtppF.mjs → hosted-client-Io01s5By.mjs} +9 -3
  59. package/dist/{hosted-ios-D5mNmtj4.mjs → hosted-ios-DIxFnYp-.mjs} +3 -3
  60. package/dist/{hosted-logs-DN8Iz4mJ.mjs → hosted-logs-DP-ABU_M.mjs} +8 -8
  61. package/dist/{hosted-macos-B-wEjlwG.mjs → hosted-macos-Aziw9T_9.mjs} +7 -6
  62. package/dist/{hosted-native-DeeOG8xZ.mjs → hosted-native-BdAQi21M.mjs} +23 -16
  63. package/dist/{idle-shutdown-jjtxAn5C.mjs → idle-shutdown-DdMqoSUB.mjs} +7 -7
  64. package/dist/ios-BZ9dg2Fr.mjs +9 -0
  65. package/dist/{ios-B3SbOWdw.mjs → ios-CXLIUxXJ.mjs} +180 -24
  66. package/dist/ios-CZuv6gRv.mjs +1112 -0
  67. package/dist/{ios-Bvbf0SGY.mjs → ios-VGvNdsv2.mjs} +1 -1
  68. package/dist/{ios-device-Bn7jWDB1.mjs → ios-device-B1B14xND.mjs} +1 -1
  69. package/dist/{ios-device-vOaByMhw.mjs → ios-device-BreZOpM0.mjs} +3 -3
  70. package/dist/ios-project-B9drt_aY.mjs +197 -0
  71. package/dist/{ios-state-B2pES6Vs.mjs → ios-state-CjrL2qv-.mjs} +1 -1
  72. package/dist/js-swap-C8icNYIY.mjs +432 -0
  73. package/dist/launch-DxH0THLP.mjs +745 -0
  74. package/dist/launch-YrbqaIFj.mjs +1530 -0
  75. package/dist/{launch-verify-hskNcWkZ.mjs → launch-verify-BzRdbuO1.mjs} +26 -7
  76. package/dist/{logs-1Ylc1Ri6.mjs → logs-DHaRNfg7.mjs} +11 -11
  77. package/dist/macos-C0iljhsN.mjs +2 -0
  78. package/dist/{macos-DF6C7wUU.mjs → macos-V_3Ui7g4.mjs} +125 -155
  79. package/dist/macos-run.mjs +1 -1
  80. package/dist/maintenance-run.mjs +13 -10
  81. package/dist/{metro-Dh8T4Ytd.mjs → metro-D_j9sN-B.mjs} +209 -43
  82. package/dist/{metro-gateway-CEUw9RMH.mjs → metro-gateway-BBJldOdi.mjs} +2 -2
  83. package/dist/miss-reason-BPAzZS0r.mjs +238 -0
  84. package/dist/{named-ports-BFIz1Shz.mjs → named-ports-C2lvoPsb.mjs} +12 -5
  85. package/dist/native-android-lHzaew7r.mjs +226 -0
  86. package/dist/native-gradle-inputs-BQnIdAlL.mjs +356 -0
  87. package/dist/{native-runtime-D_603JiC.mjs → native-runtime-BRmWL7ru.mjs} +9 -8
  88. package/dist/native-xcode-inputs-eutS19jU.mjs +307 -0
  89. package/dist/native-xcode-ios-DP3cHLwu.mjs +434 -0
  90. package/dist/{ndjson-LGZAMsqa.mjs → ndjson-GOnbyvso.mjs} +6 -6
  91. package/dist/offload-worker.d.mts +12 -6
  92. package/dist/offload-worker.mjs +409 -73
  93. package/dist/{ownership-D6Se7gg_.mjs → ownership-DXzMMSx6.mjs} +2 -2
  94. package/dist/{placement-log-BcPhRwR4.mjs → placement-log-reFbjqEr.mjs} +7 -3
  95. package/dist/plan-BDk2AeY_.mjs +260 -0
  96. package/dist/plan-placement-D_YYlE6N.mjs +73 -0
  97. package/dist/{ports-BLTtfBq-.mjs → ports-jzvAJXXL.mjs} +3 -3
  98. package/dist/{prebuild-juCyreaR.mjs → prebuild-Bw44QxVh.mjs} +4 -4
  99. package/dist/{preview-D5V07Nrl.mjs → preview-BaBJ72Al.mjs} +51 -34
  100. package/dist/project-B8_duAzW.mjs +1067 -0
  101. package/dist/project-plan-BPwbLwQu.mjs +10 -0
  102. package/dist/{pull-request-u4vp7zmK.mjs → pull-request-vOhLNmIb.mjs} +1 -1
  103. package/dist/pull-requests.mjs +1 -1
  104. package/dist/react-native-android-chm1DMlA.mjs +921 -0
  105. package/dist/react-native-build-oAw6gQeW.mjs +239 -0
  106. package/dist/react-native-doctor-DYXoh-6I.mjs +78 -0
  107. package/dist/react-native-ios-SCTK_CT5.mjs +595 -0
  108. package/dist/{recordings-BAWltsVt.mjs → recordings-Bk-VivUV.mjs} +1 -1
  109. package/dist/{reload-DvyWzVjJ.mjs → reload-D34GkY78.mjs} +17 -14
  110. package/dist/remote-BU9UyhCJ.mjs +192 -0
  111. package/dist/{remote-cache-BGg7aGIZ.mjs → remote-cache-Bsts6f6Y.mjs} +5 -5
  112. package/dist/result-BDoRk1k3.mjs +186 -0
  113. package/dist/{run-vhtDgpHO.mjs → run-qvff78hv.mjs} +3 -3
  114. package/dist/{server-bare-B9E7S1aR.mjs → server-bare-dWjAarki.mjs} +6 -6
  115. package/dist/server-command-7XIKlWtO.mjs +69 -0
  116. package/dist/{server-expo-DoBHhuzK.mjs → server-expo-CsYu2aKL.mjs} +107 -82
  117. package/dist/server-expo-DV43vep4.mjs +2 -0
  118. package/dist/settings-Bbztm4oV.mjs +1503 -0
  119. package/dist/{settings-Byp2AQ_E.mjs → settings-CT3E71-i.mjs} +6 -7
  120. package/dist/{state-lKh8shBp.d.mts → settings-vk3mJGSm.d.mts} +4 -2
  121. package/dist/settings.schema.json +156 -6
  122. package/dist/simslim-ChMfe8rg.mjs +149 -0
  123. package/dist/{slot-launch-C1nqh4mu.mjs → slot-launch-B9hn96wd.mjs} +6 -6
  124. package/dist/{stage-g_WqWeaE.mjs → stage-BNKKdDNc.mjs} +6 -3
  125. package/dist/start-CbQCSnXQ.mjs +2 -0
  126. package/dist/{start-D-IeOyoK.mjs → start-CdvcTaXr.mjs} +113 -77
  127. package/dist/{state-xnqpx3AD.mjs → state-Boo0IMJq.mjs} +4 -2
  128. package/dist/{state-BG-aAk4k.mjs → state-DI84A-uu.mjs} +29 -10
  129. package/dist/{stats-DY6ekz8F.mjs → stats-BIIDrjA8.mjs} +6 -6
  130. package/dist/{status-BEeL6IKz.mjs → status-BDGHwkCs.mjs} +3 -1
  131. package/dist/{status-DCjZeE-K.mjs → status-DARMkc9q.mjs} +80 -294
  132. package/dist/status-watch-DvmI3SmN.mjs +296 -0
  133. package/dist/{stim-desktop-Behws_fi.mjs → stim-desktop-8GQX2OV8.mjs} +1 -1
  134. package/dist/{stop-DIJtD2GL.mjs → stop-CCZS-C9m.mjs} +2 -2
  135. package/dist/stop-WQPQHLuy.mjs +72 -0
  136. package/dist/{stop-BTjs3xbc.mjs → stop-iNemHsJC.mjs} +81 -33
  137. package/dist/supervisor-run.d.mts +7 -2
  138. package/dist/supervisor-run.mjs +32 -20
  139. package/dist/{support-Bwvbrq5-.mjs → support-CnE_SIjt.mjs} +17 -7
  140. package/dist/{support-BaayeYCf.mjs → support-DCco5fut.mjs} +61 -8
  141. package/dist/swiftpm-macos-afeNUExW.mjs +119 -0
  142. package/dist/{native-run-B06FkmZx.mjs → tailnet-CoJUb2tB.mjs} +113 -6
  143. package/dist/toolchain-BIupIro1.mjs +2 -0
  144. package/dist/{toolchain-Bnyd_K3A.mjs → toolchain-DqyDXs30.mjs} +225 -315
  145. package/dist/{trigger-CJMhwXe8.mjs → trigger-C0MWBi8O.mjs} +3 -3
  146. package/dist/trigger-SHLOWJ4O.mjs +2 -0
  147. package/dist/{warm-progress-CjB-MP6H.mjs → warm-progress-C3ASD6z5.mjs} +134 -37
  148. package/dist/{status-Dcr0Qexd.mjs → watchman-CQl51YZu.mjs} +75 -7
  149. package/dist/web-B3eldHFH.mjs +123 -0
  150. package/dist/web-BLXpOe6b.mjs +2 -0
  151. package/dist/web-run.mjs +10 -10
  152. package/dist/{workspace-state-C59dqG-Z.mjs → workspace-state-CSIFuuDa.mjs} +33 -33
  153. package/dist/{workspaces-xXItD8Dj.mjs → workspaces-D2xSHBDY.mjs} +1297 -1211
  154. package/dist/{worktree-BSYlofkq.mjs → worktree-BxDqaTev.mjs} +102 -63
  155. package/dist/worktree-q7_OZNY0.mjs +2 -0
  156. package/package.json +8 -6
  157. package/shim/bundle-response.cjs +2 -1
  158. package/shim/bundle-response.d.cts +1 -1
  159. package/shim/expo-metro-config.cjs +1 -1
  160. package/shim/native-android.gradle +101 -0
  161. package/dist/android-BKA16DTf.mjs +0 -4
  162. package/dist/android-BvwuMUJ9.mjs +0 -3572
  163. package/dist/guide-status-Bhf9SJXc.mjs +0 -125
  164. package/dist/ios-CPdkoKaa.mjs +0 -3953
  165. package/dist/ios-DNpdygiv.mjs +0 -7
  166. package/dist/macos-Ck7OBMNY.mjs +0 -2
  167. package/dist/metro-store-BAHFcJm6.mjs +0 -106
  168. package/dist/plan-placement-CtxkCO54.mjs +0 -1859
  169. package/dist/project-C3ChRLZy.mjs +0 -212
  170. package/dist/projects-DD7dBTCj.mjs +0 -92
  171. package/dist/server-expo-Db9HBUoa.mjs +0 -2
  172. package/dist/settings-CQyMElEP.mjs +0 -701
  173. package/dist/start-NTc1Ifqs.mjs +0 -2
  174. package/dist/stop-BGhKMOuH.mjs +0 -48
  175. package/dist/trigger-DWAq9hkw.mjs +0 -2
  176. package/dist/web-B6_bFDn7.mjs +0 -2
  177. package/dist/worktree-BJfnU6r5.mjs +0 -2
  178. package/dist/worktree-CsKYexJM.mjs +0 -753
@@ -0,0 +1,205 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, isAbsolute, join, resolve } from "node:path";
3
+ import { ANDROID_COMPILER_CACHE_CHOICES, ANDROID_PCH_CHOICES } from "@stim-cli/core/state";
4
+ import { fileURLToPath } from "node:url";
5
+ import { METRO_NAMED_CACHE_LAYOUT, metroCacheRoot, registerCache, sharedStoreRoot, tagSharedStore } from "@stim-cli/core";
6
+ import { createHash } from "node:crypto";
7
+ //#region src/optimizations.ts
8
+ function compilerCacheFallbackMessage({ fallback, compilerCache, file = null }) {
9
+ const origin = fallback.fromEnvironment ? "the environment" : file;
10
+ const backend = compilerCache === "none" ? "Android builds use no compiler cache, because optimizations.android.compilerCache is \"none\"." : "Android builds fall back to ccache when it is available.";
11
+ return `${fallback.key}${origin ? ` in ${origin}` : ""} ${fallback.reason}. ${backend}`;
12
+ }
13
+ function optimizationBuildProfile(platform, options) {
14
+ const selected = platform === "ios" ? {
15
+ ...options.ios,
16
+ swiftCompilationCache: options.ios.swiftCompilationCache ?? false
17
+ } : { pch: options.android.pch };
18
+ const defaults = platform === "ios" ? {
19
+ compilationCache: true,
20
+ swiftCompilationCache: false,
21
+ prefixMapping: true
22
+ } : { pch: "auto" };
23
+ if (JSON.stringify(selected) === JSON.stringify(defaults)) return void 0;
24
+ return `opt-${createHash("sha256").update(JSON.stringify(selected)).digest("hex").slice(0, 16)}`;
25
+ }
26
+ function resolveOptimizations(settings = {}, env = process.env) {
27
+ function choice(path, choices, fallback) {
28
+ const raw = optimizationValue(settings, path);
29
+ if (raw === void 0) return fallback;
30
+ if (typeof raw !== "string" || !choices.includes(raw)) throw new Error(`Invalid optimizations.${path}. Expected ${choices.join(", ")}.`);
31
+ return raw;
32
+ }
33
+ const compiler = choice("android.compilerCache", ANDROID_COMPILER_CACHE_CHOICES, "auto");
34
+ const fromEnvironment = Boolean(env.STIM_ANDROID_CAS_TOOLCHAIN);
35
+ const manifest = env.STIM_ANDROID_CAS_TOOLCHAIN || optimizationValue(settings, "android.casToolchain");
36
+ let fallback = null;
37
+ let toolchain = null;
38
+ if (manifest !== void 0) {
39
+ if (typeof manifest === "string" && isAbsolute(manifest) && !/[\r\n\0]/.test(manifest)) toolchain = manifest;
40
+ else fallback = {
41
+ key: fromEnvironment ? "STIM_ANDROID_CAS_TOOLCHAIN" : "optimizations.android.casToolchain",
42
+ reason: `is ${JSON.stringify(manifest)}, which is not an absolute path to a toolchain JSON manifest`,
43
+ fromEnvironment,
44
+ manifest: null
45
+ };
46
+ }
47
+ let compilerCache = compiler === "auto" ? toolchain ? "cas" : "ccache" : compiler;
48
+ if (compilerCache === "cas" && !toolchain) {
49
+ fallback ??= {
50
+ key: "optimizations.android.compilerCache",
51
+ reason: "is \"cas\", but no optimizations.android.casToolchain or STIM_ANDROID_CAS_TOOLCHAIN names the toolchain manifest",
52
+ fromEnvironment: false,
53
+ manifest: null
54
+ };
55
+ compilerCache = "ccache";
56
+ }
57
+ return {
58
+ buildCache: optimizationBoolean(settings, "buildCache"),
59
+ remoteBuildCache: optimizationBoolean(settings, "remoteBuildCache"),
60
+ releaseBundleSwap: optimizationBoolean(settings, "releaseBundleSwap"),
61
+ metroSharedCache: optimizationBoolean(settings, "metroSharedCache"),
62
+ metroWarmup: optimizationBoolean(settings, "metroWarmup"),
63
+ ios: {
64
+ compilationCache: optimizationBoolean(settings, "ios.compilationCache"),
65
+ swiftCompilationCache: optimizationValue(settings, "ios.swiftCompilationCache") === void 0 ? null : optimizationBoolean(settings, "ios.swiftCompilationCache"),
66
+ prefixMapping: optimizationBoolean(settings, "ios.prefixMapping")
67
+ },
68
+ android: {
69
+ compilerCache,
70
+ casToolchain: toolchain,
71
+ compilerCacheFallback: fallback,
72
+ pch: choice("android.pch", ANDROID_PCH_CHOICES, "auto"),
73
+ gradleBuildCache: optimizationBoolean(settings, "android.gradleBuildCache"),
74
+ targetAbiOnly: optimizationBoolean(settings, "android.targetAbiOnly")
75
+ }
76
+ };
77
+ }
78
+ function artifactCachePolicy(options, reuse, release) {
79
+ return {
80
+ read: reuse && options.buildCache && (!release || options.releaseBundleSwap),
81
+ write: options.buildCache,
82
+ remote: options.buildCache && options.remoteBuildCache
83
+ };
84
+ }
85
+ function optimizationValue(settings, path) {
86
+ let node = settings;
87
+ for (const key of ["optimizations", ...path.split(".")]) {
88
+ if (node === void 0) return void 0;
89
+ if (!node || typeof node !== "object" || Array.isArray(node)) throw new Error("Invalid optimizations setting. Expected nested objects.");
90
+ node = node[key];
91
+ }
92
+ return node;
93
+ }
94
+ function optimizationBoolean(settings, path, fallback = true) {
95
+ const raw = optimizationValue(settings, path);
96
+ if (raw === void 0) return fallback;
97
+ if (typeof raw !== "boolean") throw new Error(`Invalid optimizations.${path}. Expected true or false.`);
98
+ return raw;
99
+ }
100
+ function resolveMetroSharedCache(settings) {
101
+ return optimizationBoolean(settings, "metroSharedCache");
102
+ }
103
+ //#endregion
104
+ //#region src/supervisor/metro-store.ts
105
+ function metroStoreName(root) {
106
+ try {
107
+ const name = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"))?.name;
108
+ if (typeof name === "string" && name.trim() !== "") return name;
109
+ } catch {}
110
+ return "app";
111
+ }
112
+ function metroStoreRoot(root) {
113
+ return metroCacheRoot(metroStoreName(root));
114
+ }
115
+ function registerMetroStore(storeRoot) {
116
+ const parent = resolve(metroCacheRoot());
117
+ const dir = resolve(storeRoot);
118
+ registerCache({
119
+ dir,
120
+ name: "Metro transform cache",
121
+ prune: "entries",
122
+ entriesDepth: 2,
123
+ layout: METRO_NAMED_CACHE_LAYOUT,
124
+ note: "shared Metro transforms, installed by stim start; no eviction of its own",
125
+ replaces: dir === parent ? [] : [{
126
+ dir: parent,
127
+ name: "Metro transform cache",
128
+ prune: "entries",
129
+ entriesDepth: 2,
130
+ layout: null
131
+ }]
132
+ });
133
+ }
134
+ function hasStoreAt(stores, storeRoot) {
135
+ if (!Array.isArray(stores)) return false;
136
+ return stores.some((s) => sharedStoreRoot(s) === storeRoot);
137
+ }
138
+ function appendCacheStore(config, { storeRoot, FileStore }) {
139
+ if (!config || typeof config !== "object") return {
140
+ added: false,
141
+ storeRoot,
142
+ reason: "no config to add it to"
143
+ };
144
+ const stores = config.cacheStores;
145
+ if (typeof stores === "function") {
146
+ const original = stores;
147
+ config.cacheStores = (cache) => {
148
+ const resolved = original(cache);
149
+ return (Array.isArray(resolved) ? resolved : []).concat([tagSharedStore(new FileStore({ root: storeRoot }), storeRoot)]);
150
+ };
151
+ return {
152
+ added: true,
153
+ storeRoot
154
+ };
155
+ }
156
+ if (hasStoreAt(stores, storeRoot)) return {
157
+ added: false,
158
+ storeRoot,
159
+ reason: "a store already points at it"
160
+ };
161
+ config.cacheStores = [...Array.isArray(stores) ? stores : [], tagSharedStore(new FileStore({ root: storeRoot }), storeRoot)];
162
+ return {
163
+ added: true,
164
+ storeRoot
165
+ };
166
+ }
167
+ const EXPO_ADAPTER_FILE = "expo-metro-config.cjs";
168
+ function expoMetroConfigPath(fromUrl = import.meta.url) {
169
+ const here = dirname(fileURLToPath(fromUrl));
170
+ for (const rel of ["../shim", "../../shim"]) {
171
+ const candidate = resolve(here, rel, EXPO_ADAPTER_FILE);
172
+ if (existsSync(candidate)) return candidate;
173
+ }
174
+ return null;
175
+ }
176
+ const STORE_OK_PREFIX = "stim-metro-store: sharing Metro transforms through ";
177
+ function metroStoreConfirmedRoot(line) {
178
+ if (!line.startsWith(STORE_OK_PREFIX)) return null;
179
+ const root = line.slice(51).trim();
180
+ return root === "" ? null : root;
181
+ }
182
+ function expoMetroStoreEnv({ root, storeRoot, adapterPath, existingOverride }) {
183
+ return {
184
+ EXPO_OVERRIDE_METRO_CONFIG: adapterPath,
185
+ STIM_METRO_STORE: storeRoot,
186
+ STIM_PROJECT_ROOT: root,
187
+ ...existingOverride ? { STIM_EXPO_METRO_CONFIG: existingOverride } : {}
188
+ };
189
+ }
190
+ //#endregion
191
+ //#region src/supervisor/errors.ts
192
+ function supervisorError(code, message, remedy) {
193
+ const err = new Error(message);
194
+ err.code = code;
195
+ if (remedy) err.remedy = remedy;
196
+ return err;
197
+ }
198
+ function describeError(err) {
199
+ if (!err) return "unknown error";
200
+ const e = err;
201
+ const message = e.message || String(err);
202
+ return `${e.code ? `${e.code}: ` : ""}${message}${e.remedy ? ` Remedy: ${e.remedy}` : ""}`;
203
+ }
204
+ //#endregion
205
+ export { expoMetroStoreEnv as a, registerMetroStore as c, optimizationBuildProfile as d, resolveMetroSharedCache as f, expoMetroConfigPath as i, artifactCachePolicy as l, supervisorError as n, metroStoreConfirmedRoot as o, resolveOptimizations as p, appendCacheStore as r, metroStoreRoot as s, describeError as t, compilerCacheFallbackMessage as u };
@@ -12,6 +12,28 @@ function nameTimeout(error, command, timeoutMs) {
12
12
  if (error?.code === "ETIMEDOUT" && error instanceof Error) error.message = `Command timed out after ${timeoutMs}ms: ${command}`;
13
13
  return error;
14
14
  }
15
+ const WINDOWS_BATCH_FILE = /\.(?:bat|cmd)$/i;
16
+ const BATCH_UNSAFE_ARGUMENT = /["\r\n]/;
17
+ function isUnsafeBatchSpawn(target, args, platform = process.platform) {
18
+ return platform === "win32" && WINDOWS_BATCH_FILE.test(target) && args.some((arg) => BATCH_UNSAFE_ARGUMENT.test(arg));
19
+ }
20
+ function refuseUnsafeBatchArguments(file, args) {
21
+ if (process.platform !== "win32") return;
22
+ const target = which.sync(file, { nothrow: true }) ?? file;
23
+ if (isUnsafeBatchSpawn(target, args)) throw new Error(`Refusing to run ${basename(target)}: an argument contains a character cmd.exe could misinterpret (a double quote or a line break).`);
24
+ }
25
+ function redactError(error, values) {
26
+ const secrets = values?.filter(Boolean) ?? [];
27
+ if (secrets.length === 0 || !error || typeof error !== "object") return error;
28
+ const scrub = (text) => secrets.reduce((acc, secret) => acc.split(secret).join("***"), text);
29
+ const fields = error;
30
+ for (const key of Object.getOwnPropertyNames(error)) {
31
+ const value = fields[key];
32
+ if (typeof value === "string") fields[key] = scrub(value);
33
+ else if (Array.isArray(value)) fields[key] = value.map((item) => typeof item === "string" ? scrub(item) : item);
34
+ }
35
+ return error;
36
+ }
15
37
  const defaultExecutor = {
16
38
  run(cmd, { timeoutMs, killSignal, cwd, env } = {}) {
17
39
  const opts = {
@@ -36,16 +58,17 @@ const defaultExecutor = {
36
58
  throw nameTimeout(error, cmd, timeoutMs);
37
59
  }
38
60
  },
39
- runFile(file, args = [], { timeoutMs, killSignal, cwd, env, omitEnv, input, untrimmed } = {}) {
61
+ runFile(file, args = [], { timeoutMs, killSignal, cwd, env, omitEnv, input, untrimmed, rejectStderr, detachedSilent, redact } = {}) {
40
62
  const opts = {
41
63
  encoding: "utf-8",
42
- stdio: [
64
+ stdio: detachedSilent ? "ignore" : [
43
65
  "pipe",
44
66
  "pipe",
45
67
  "pipe"
46
68
  ],
47
69
  maxBuffer: MAX_BUFFER
48
70
  };
71
+ if (detachedSilent) opts.detached = true;
49
72
  if (timeoutMs) opts.timeout = timeoutMs;
50
73
  if (killSignal) opts.killSignal = killSignal;
51
74
  if (cwd) opts.cwd = cwd;
@@ -58,19 +81,25 @@ const defaultExecutor = {
58
81
  for (const key of omitEnv ?? []) delete childEnv[key];
59
82
  opts.env = childEnv;
60
83
  }
84
+ refuseUnsafeBatchArguments(file, args);
61
85
  const result = spawn.sync(file, args, opts);
62
- if (result.error) throw nameTimeout(Object.assign(result.error, result), [file, ...args].join(" "), timeoutMs);
63
- if (result.status !== 0) {
86
+ if (result.error) throw redactError(nameTimeout(Object.assign(result.error, result), [file, ...args].join(" "), timeoutMs), redact);
87
+ if (result.status !== 0 || rejectStderr && String(result.stderr ?? "").trim()) {
64
88
  const stderr = String(result.stderr ?? "");
65
89
  const message = `Command failed: ${[file, ...args].join(" ")}${stderr ? `\n${stderr}` : ""}`;
66
- throw Object.assign(new Error(message), result);
90
+ throw redactError(Object.assign(new Error(message), result), redact);
67
91
  }
92
+ if (detachedSilent) return "";
68
93
  return untrimmed ? String(result.stdout) : String(result.stdout).trim();
69
94
  },
70
- runFileAsync(file, args = [], { timeoutMs, killSignal, cwd, env, omitEnv } = {}) {
95
+ runFileAsync(file, args = [], { timeoutMs, killSignal, cwd, env, omitEnv, rejectStderr, onSpawn, detachedSilent, redact } = {}) {
71
96
  const command = [file, ...args].join(" ");
72
97
  return new Promise((resolve, reject) => {
73
- const opts = { stdio: [
98
+ refuseUnsafeBatchArguments(file, args);
99
+ const opts = detachedSilent ? {
100
+ stdio: "ignore",
101
+ detached: true
102
+ } : { stdio: [
74
103
  "ignore",
75
104
  "pipe",
76
105
  "pipe"
@@ -85,6 +114,13 @@ const defaultExecutor = {
85
114
  opts.env = childEnv;
86
115
  }
87
116
  const child = spawn(file, args, opts);
117
+ try {
118
+ onSpawn?.(child);
119
+ } catch (error) {
120
+ child.kill("SIGKILL");
121
+ reject(error);
122
+ return;
123
+ }
88
124
  const stdout = [];
89
125
  const stderr = [];
90
126
  let timedOut = false;
@@ -96,7 +132,7 @@ const defaultExecutor = {
96
132
  child.stderr?.on("data", (chunk) => stderr.push(chunk));
97
133
  child.on("error", (error) => {
98
134
  clearTimeout(timer);
99
- reject(error);
135
+ reject(redactError(error, redact));
100
136
  });
101
137
  child.on("close", (status, signal) => {
102
138
  clearTimeout(timer);
@@ -108,9 +144,9 @@ const defaultExecutor = {
108
144
  stdout: out,
109
145
  stderr: err
110
146
  };
111
- if (timedOut) reject(nameTimeout(Object.assign(new Error(command), result, { code: "ETIMEDOUT" }), command, timeoutMs));
112
- else if (status !== 0) reject(Object.assign(/* @__PURE__ */ new Error(`Command failed: ${command}${err ? `\n${err}` : ""}`), result));
113
- else resolve(out.trim());
147
+ if (timedOut) reject(redactError(nameTimeout(Object.assign(new Error(command), result, { code: "ETIMEDOUT" }), command, timeoutMs), redact));
148
+ else if (status !== 0 || rejectStderr && err.trim()) reject(redactError(Object.assign(/* @__PURE__ */ new Error(`Command failed: ${command}${err ? `\n${err}` : ""}`), result), redact));
149
+ else resolve(detachedSilent ? "" : out.trim());
114
150
  });
115
151
  });
116
152
  },
@@ -129,6 +165,7 @@ const defaultExecutor = {
129
165
  }
130
166
  },
131
167
  spawn(cmd, args = [], opts = {}) {
168
+ refuseUnsafeBatchArguments(cmd, args);
132
169
  return spawn(cmd, args, opts);
133
170
  },
134
171
  findExecutable(name) {
@@ -146,21 +183,30 @@ function outcomeOf(error) {
146
183
  ...code ? { code } : {}
147
184
  };
148
185
  }
186
+ let executionId = 0;
149
187
  function timedSync(fn, program) {
150
188
  return (...args) => {
151
189
  if (!debugLog.enabled()) return fn(...args);
190
+ const id = ++executionId;
191
+ const name = program(...args);
152
192
  const started = performance.now();
193
+ debugLog.log("exec.start", {
194
+ program: name,
195
+ executionId: id
196
+ });
153
197
  try {
154
198
  const out = fn(...args);
155
199
  debugLog.log("exec", {
156
- program: program(...args),
200
+ program: name,
201
+ executionId: id,
157
202
  ms: Math.round(performance.now() - started),
158
203
  ok: true
159
204
  });
160
205
  return out;
161
206
  } catch (error) {
162
207
  debugLog.log("exec", {
163
- program: program(...args),
208
+ program: name,
209
+ executionId: id,
164
210
  ms: Math.round(performance.now() - started),
165
211
  ...outcomeOf(error)
166
212
  });
@@ -174,18 +220,26 @@ let active = {
174
220
  runFile: timedSync((file, args, opts) => defaultExecutor.runFile(file, args, opts), (file) => basename(file)),
175
221
  async runFileAsync(file, args, opts) {
176
222
  if (!debugLog.enabled()) return defaultExecutor.runFileAsync(file, args, opts);
223
+ const id = ++executionId;
224
+ const name = basename(file);
177
225
  const started = performance.now();
226
+ debugLog.log("exec.start", {
227
+ program: name,
228
+ executionId: id
229
+ });
178
230
  try {
179
231
  const out = await defaultExecutor.runFileAsync(file, args, opts);
180
232
  debugLog.log("exec", {
181
- program: basename(file),
233
+ program: name,
234
+ executionId: id,
182
235
  ms: Math.round(performance.now() - started),
183
236
  ok: true
184
237
  });
185
238
  return out;
186
239
  } catch (error) {
187
240
  debugLog.log("exec", {
188
- program: basename(file),
241
+ program: name,
242
+ executionId: id,
189
243
  ms: Math.round(performance.now() - started),
190
244
  ...outcomeOf(error)
191
245
  });
@@ -1,30 +1,31 @@
1
1
  import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-Biv3arCO.mjs";
2
- import { t as getExecutor } from "./exec-DWhCZDGm.mjs";
3
- import { h as shortUdid, o as formatLongDuration, u as plural } from "./command-output-CBtzyIgF.mjs";
4
- import { A as directorySize, D as withConfigLock$1, F as volumeRootFor, H as projectDeviceSlots, M as isOnMountedVolume, N as listMountedVolumes, S as removeProject, _ as loadConfig$1, j as formatBytes, k as acquireAvdClaim } from "./config-CgYMahz7.mjs";
5
- import { i as detectIsExpo, s as findProjectRoot$1 } from "./project-C3ChRLZy.mjs";
6
- import { C as workspaceStateFile, s as workspaceLastUsed, v as workspaceDir, w as withDirLock$1 } from "./workspace-state-C59dqG-Z.mjs";
7
- import { $ as describeUnverifiableDevices, $t as sizeCaches, At as phase, C as idleDeviceLines, Ct as memoryCacheKind, Dt as memoryWorkPending, Et as memorySweepIsScoped, G as DEVICE_LIST_TIMEOUT_MS, J as collectParkedSims, K as collectDeviceLeases, Ot as reclaimMemory, Q as describeParkedSims, T as shutDownIdleDevices, Tt as memoryScope, X as deleteParkedSims, Y as deleteParkedAvds, Z as deleteProjectDevices, Zt as discoverCaches, _t as trimCaches, at as unverifiedDeviceCommand, ct as includesArchives, dt as includesWorkspaceOutputs, et as deviceSweepIsScoped, ft as isWorkspacesScope, gt as selectsBeyondCaches, ht as selectCaches, it as findStaleProjectDevices, kt as scopedMemoryReport, lt as includesParkedDevices, mt as previewScopedEmptying, nt as findOrphanedDevices, ot as withAndroidAvdSizes, pt as planCacheEmptying, q as collectParkedAvds, rt as findStaleDeviceRecords, st as emptyCaches, tt as eraseParkedDevices, ut as includesRecordings, vt as parseArchiveSelector, w as parseIdleDuration, wt as memoryLines, x as collectIdleDevices, xt as collectMemoryReport } from "./budget-DIhL2BKx.mjs";
8
- import { F as takeGcResults, I as canonicalPath, M as listBuildSlots, P as recordGcResult, a as collectWorkspaceOutputs, c as listWorkspaceDirs, f as withIdleWorkspace, i as collectOrphanedWorkspaces, l as rootPresence, n as WORKSPACE_OUTPUT_DIRS, o as deleteOrphanedWorkspaces, p as workspaceInUse, r as clearWorkspaceOutputs, s as isInsideWorkspaces, t as REBUILD_COST, u as sizeText } from "./workspaces-xXItD8Dj.mjs";
9
- import { d as removeExpiredLease, h as listBuildLocks } from "./device-lease-Co-EwifR.mjs";
10
- import { n as readCreatedDevices$1, t as forgetCreatedDevice } from "./created-devices-DKbeWsiK.mjs";
11
- import { A as listAvds, H as parseAvdSystemImage, I as ownedAvdDirectory, M as listOrphanedAvdDirectories, V as parseAvdDeviceProfile, _ as avdStorageRoots, at as isStimOwnedSim, d as androidToolPath, ft as parkedMaxSetting, it as isStimOwnedAvd, j as listInstalledSystemImages, m as avdNameAbsent, o as androidHome, ot as POOL_SETTING_REMEDY, p as avdIniPaths, pt as readParked } from "./android-DC3ZLuw0.mjs";
12
- import { d as listAllIosSims } from "./ios-B3SbOWdw.mjs";
13
- import { f as resolveEasCliBin } from "./remote-cache-BGg7aGIZ.mjs";
14
- import { C as listOwnedSessionsArgs, D as verifyStoppedSession, E as stopSessionArgs, S as isDefinitiveMissingSessionError, T as parseSessionListPage, b as getSessionArgs, d as withRemoteSessionLock, f as withEasProjectLock, h as removeEasSessionClaim, m as readEasSessionLedger$1, p as easMachineStateRoot$1, x as inspectSessionForTeardown, y as findOrphanedOwnedSessions } from "./device-remote-tHbd1fKy.mjs";
15
- import { r as readCollectors } from "./ownership-D6Se7gg_.mjs";
16
- import { c as worktreePullRequestNote, l as worktreeRemovalReason, n as previewMaintenance, o as collectWorktreeSweep, s as removeWorktrees } from "./preview-D5V07Nrl.mjs";
17
- import { _ as deleteSelectedArchives, g as reclaimProject, h as describeDereferenced, v as sweepArchiveStaging } from "./worktree-BSYlofkq.mjs";
18
- import { i as getSwiftpmCacheUsage, n as swiftpmCacheLines, r as getAgentDeviceUsage, t as agentDeviceLines } from "./agent-device-usage-output-CZ66YA4T.mjs";
2
+ import { t as getExecutor } from "./exec-B81Qodjn.mjs";
3
+ import { A as directorySize, D as withConfigLock$1, F as volumeRootFor, H as projectDeviceSlots, M as isOnMountedVolume, N as listMountedVolumes, S as removeProject, _ as loadConfig$1, j as formatBytes, k as acquireAvdClaim } from "./config-D0LhTY3S.mjs";
4
+ import { d as removeExpiredLease, h as listBuildLocks } from "./device-lease-DHOBXGgS.mjs";
5
+ import { D as withDirLock$1, E as workspaceStateFile, s as workspaceLastUsed, x as workspaceDir } from "./workspace-state-CSIFuuDa.mjs";
6
+ import { h as shortUdid, o as formatLongDuration, u as plural } from "./command-output-BjPN99ZB.mjs";
7
+ import { _ as detectIsExpo, r as findProjectRoot } from "./project-B8_duAzW.mjs";
8
+ import { A as listAvds, H as parseAvdSystemImage, I as ownedAvdDirectory, M as listOrphanedAvdDirectories, V as parseAvdDeviceProfile, _ as avdStorageRoots, at as POOL_SETTING_REMEDY, d as androidToolPath, dt as parkedMaxSetting, ft as readParked, it as isStimOwnedSim, j as listInstalledSystemImages, m as avdNameAbsent, o as androidHome, p as avdIniPaths, rt as isStimOwnedAvd } from "./android-BsYNR81W.mjs";
9
+ import { n as readCreatedDevices$1, t as forgetCreatedDevice } from "./created-devices-HU_DAb_Q.mjs";
10
+ import { C as recordGcResult, I as listBuildSlots, T as canonicalPath, a as collectWorkspaceOutputs, c as listWorkspaceDirs, f as withIdleWorkspace, i as collectOrphanedWorkspaces, l as rootPresence, n as WORKSPACE_OUTPUT_DIRS, o as deleteOrphanedWorkspaces, p as workspaceInUse, r as clearWorkspaceOutputs, s as isInsideWorkspaces, t as REBUILD_COST, u as sizeText, w as takeGcResults } from "./workspaces-D2xSHBDY.mjs";
11
+ import { $ as memoryWorkPending, A as findStaleProjectDevices, B as previewScopedEmptying, C as deleteProjectDevices, D as eraseParkedDevices, E as deviceSweepIsScoped, F as includesParkedDevices, H as selectsBeyondCaches, I as includesRecordings, L as includesWorkspaceOutputs, M as withAndroidAvdSizes, N as emptyCaches, O as findOrphanedDevices, P as includesArchives, Q as memorySweepIsScoped, R as isWorkspacesScope, S as deleteParkedSims, T as describeUnverifiableDevices, U as trimCaches, V as selectCaches, W as parseArchiveSelector, X as memoryLines, Y as memoryCacheKind, Z as memoryScope, _ as DEVICE_LIST_TIMEOUT_MS, at as discoverCaches, b as collectParkedSims, d as collectIdleDevices, et as reclaimMemory, h as shutDownIdleDevices, j as unverifiedDeviceCommand, k as findStaleDeviceRecords, m as parseIdleDuration, nt as phase, p as idleDeviceLines, q as collectMemoryReport, st as sizeCaches, tt as scopedMemoryReport, v as collectDeviceLeases, w as describeParkedSims, x as deleteParkedAvds, y as collectParkedAvds, z as planCacheEmptying } from "./budget-BONq9vXY.mjs";
12
+ import { f as resolveEasCliBin } from "./remote-cache-Bsts6f6Y.mjs";
13
+ import { d as listAllIosSims } from "./ios-CXLIUxXJ.mjs";
14
+ import { C as parseSessionListPage, T as verifyStoppedSession, _ as findOrphanedOwnedSessions, b as isDefinitiveMissingSessionError, d as withRemoteSessionLock, f as withEasProjectLock, v as getSessionArgs, w as stopSessionArgs, x as listOwnedSessionsArgs, y as inspectSessionForTeardown } from "./device-remote-Bmg42063.mjs";
15
+ import { a as removeEasSessionClaim, n as easMachineStateRoot$1, r as readEasSessionLedger$1 } from "./eas-session-ledger-DZlC-Fq3.mjs";
16
+ import { r as readCollectors } from "./ownership-DXzMMSx6.mjs";
17
+ import { c as removeWorktrees, l as worktreePullRequestNote, n as previewMaintenance, s as collectWorktreeSweep, u as worktreeRemovalReason } from "./preview-BaBJ72Al.mjs";
18
+ import { _ as reclaimProject, g as describeDereferenced, v as deleteSelectedArchives, y as sweepArchiveStaging } from "./worktree-BxDqaTev.mjs";
19
+ import { i as getSwiftpmCacheUsage, n as swiftpmCacheLines, r as getAgentDeviceUsage, t as agentDeviceLines } from "./agent-device-usage-output-DVyv_hWj.mjs";
19
20
  import { existsSync, lstatSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
20
21
  import { basename, dirname, join } from "node:path";
21
22
  import { basename as basename$1, dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1 } from "path";
22
23
  import { assertHostedDeviceLedger, deviceHostArea, deviceHostRoot, hostedDeviceId, isJsonObject, listRecordedDevices, listStatusCacheEntries, maintenanceRunClaims, parseHostedPlatformDevice, readArchives, readHostedDevice, readHostedDeviceLedger, readHostedSessions, recordedBytes } from "@stim-cli/core/state";
23
24
  import { fileURLToPath } from "node:url";
24
- import chalk from "chalk";
25
25
  import { closeSync as closeSync$1, existsSync as existsSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readSync as readSync$1, readdirSync as readdirSync$1, renameSync as renameSync$1, rmSync as rmSync$1, statSync as statSync$1, utimesSync as utimesSync$1, writeFileSync as writeFileSync$1 } from "fs";
26
- import { InvalidArgumentError } from "commander";
27
26
  import { LOG_ROTATE_BYTES, rotatedLogPath } from "@stim-cli/core";
27
+ import { InvalidArgumentError } from "commander";
28
+ import chalk from "chalk";
28
29
  //#region src/commands/gc/archives.ts
29
30
  function stagingOrNone() {
30
31
  try {
@@ -222,7 +223,7 @@ function claimStateAbsence(claim) {
222
223
  };
223
224
  }
224
225
  function collectEasSessionSweep(config, deps) {
225
- const projectRoot = (deps.findProjectRoot ?? findProjectRoot$1)(process.cwd());
226
+ const projectRoot = (deps.findProjectRoot ?? findProjectRoot)(process.cwd());
226
227
  const empty = (notices = []) => ({
227
228
  projectScope: projectRoot,
228
229
  orphaned: [],
@@ -990,7 +991,7 @@ function namedPortLines(ports = []) {
990
991
  return [
991
992
  `Orphaned named ports (${ports.length}):`,
992
993
  ...ports.map(({ project, label, port }) => ` ${project}: ${label} (${port})`),
993
- " --delete stops TCP listeners and releases these allocations."
994
+ " --delete releases these allocations without stopping listeners."
994
995
  ];
995
996
  }
996
997
  function orphanedWorkspaceLines(orphaned) {
@@ -2437,7 +2438,7 @@ async function sweep(opts, deps) {
2437
2438
  });
2438
2439
  let projectRoot = null;
2439
2440
  try {
2440
- projectRoot = (deps.findProjectRoot ?? findProjectRoot$1)(process.cwd());
2441
+ projectRoot = (deps.findProjectRoot ?? findProjectRoot)(process.cwd());
2441
2442
  if (!projectRoot) return runGcCore(opts, {
2442
2443
  ...deps,
2443
2444
  precollectedEasSessionSweep: {