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
@@ -1,153 +1,18 @@
1
- import { t as getExecutor } from "./exec-DWhCZDGm.mjs";
1
+ import { t as getExecutor } from "./exec-B81Qodjn.mjs";
2
+ import { b as workspaceDerivedData } from "./workspace-state-CSIFuuDa.mjs";
2
3
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
3
- import { a as formatElapsed, l as phaseLine } from "./command-output-CBtzyIgF.mjs";
4
- import { _ as loadConfig$1 } from "./config-CgYMahz7.mjs";
5
- import { h as resolvePackageJson } from "./project-C3ChRLZy.mjs";
6
- import { _ as workspaceDerivedData, f as sharedCcache$1, p as sharedCompilationCache$1, x as workspaceLogsDir$1 } from "./workspace-state-C59dqG-Z.mjs";
7
- import { r as register } from "./cache-manifest-BI7ozfmH.mjs";
8
- import { o as machineNumber } from "./budget-DIhL2BKx.mjs";
4
+ import { a as formatElapsed, l as phaseLine } from "./command-output-BjPN99ZB.mjs";
5
+ import { o as androidHome } from "./android-BsYNR81W.mjs";
9
6
  import { a as spawnDeclared } from "./spawn-claims-Kqiifsk2.mjs";
10
- import { o as androidHome } from "./android-DC3ZLuw0.mjs";
11
- import { Q as resolveOptimizations } from "./settings-CQyMElEP.mjs";
12
- import { t as cleanLine } from "./server-expo-DoBHhuzK.mjs";
7
+ import { p as resolveOptimizations } from "./errors-DzkMYh8Q.mjs";
8
+ import { t as cleanLine } from "./server-expo-CsYu2aKL.mjs";
13
9
  import { createRequire } from "node:module";
14
- import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
10
+ import { existsSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
15
11
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
16
12
  import { stimBuildDigest } from "@stim-cli/core/state";
17
13
  import { fileURLToPath } from "node:url";
18
- import { homedir } from "node:os";
19
- import chalk from "chalk";
20
14
  import { createHash } from "node:crypto";
21
- const CCACHE_SLOPPINESS = "pch_defines,time_macros";
22
- const STATS_LOG_FILE = "ccache-stats.log";
23
- const CCACHE_UNAVAILABLE = {
24
- status: "unavailable",
25
- hits: null,
26
- misses: null,
27
- hitRatePercent: null
28
- };
29
- const CCACHE_NOT_RUN = {
30
- status: "not-run",
31
- hits: null,
32
- misses: null,
33
- hitRatePercent: null
34
- };
35
- function ccacheStatsLog(root) {
36
- return join(workspaceLogsDir$1(root), STATS_LOG_FILE);
37
- }
38
- function ccacheMaxSize(config = loadConfig$1(), env = process.env) {
39
- const { value, error } = machineNumber("caches.ccacheMaxGb", config, env);
40
- return error || value === void 0 ? "5G" : `${value}G`;
41
- }
42
- function ccacheEnvironment({ binary, dir, workspaceRoot, statsLog, maxSize = "5G" }) {
43
- return {
44
- CMAKE_C_COMPILER_LAUNCHER: binary,
45
- CMAKE_CXX_COMPILER_LAUNCHER: binary,
46
- CCACHE_DIR: dir,
47
- CCACHE_BASEDIR: workspaceRoot,
48
- CCACHE_NOHASHDIR: "true",
49
- CCACHE_SLOPPINESS,
50
- CCACHE_MAXSIZE: maxSize,
51
- CCACHE_STATSLOG: statsLog
52
- };
53
- }
54
- function parseCcacheBinary(output) {
55
- const first = String(output ?? "").split("\n")[0]?.trim();
56
- if (!first || !isAbsolute(first)) return null;
57
- return first;
58
- }
59
- const CMAKE_LAUNCHER = /CMAKE_(C|CXX)_COMPILER_LAUNCHER\b/;
60
- function projectCmakeLauncher(source) {
61
- if (typeof source !== "string") return null;
62
- const match = CMAKE_LAUNCHER.exec(source);
63
- return match ? `CMAKE_${match[1]}_COMPILER_LAUNCHER` : null;
64
- }
65
- const HIT_COUNTERS = /* @__PURE__ */ new Set(["direct_cache_hit", "preprocessed_cache_hit"]);
66
- function parseCcacheStatsLog(text) {
67
- if (typeof text !== "string") return null;
68
- let hits = 0;
69
- let misses = 0;
70
- for (const raw of text.split("\n")) {
71
- const line = raw.trim();
72
- if (HIT_COUNTERS.has(line)) hits += 1;
73
- else if (line === "cache_miss") misses += 1;
74
- }
75
- const total = hits + misses;
76
- if (total === 0) return null;
77
- return {
78
- status: "reported",
79
- hits,
80
- misses,
81
- hitRatePercent: Math.round(hits / total * 1e3) / 10
82
- };
83
- }
84
- function readCcacheActivity(statsLog) {
85
- let text;
86
- try {
87
- text = readFileSync(statsLog, "utf-8");
88
- } catch {
89
- return CCACHE_UNAVAILABLE;
90
- }
91
- return parseCcacheStatsLog(text) ?? CCACHE_UNAVAILABLE;
92
- }
93
- function ccacheActivityLine(activity) {
94
- if (activity.status === "reported") return `${activity.hits} hits / ${activity.misses} misses (${activity.hitRatePercent}%)`;
95
- if (activity.status === "not-run") return "not run; artifact cache supplied the app";
96
- return "unavailable; no C++ compile went through ccache";
97
- }
98
- function lookupCcache() {
99
- try {
100
- return parseCcacheBinary(getExecutor().findExecutable("ccache"));
101
- } catch {
102
- return null;
103
- }
104
- }
105
- function readOrNull$1(file) {
106
- try {
107
- return readFileSync(file, "utf-8");
108
- } catch {
109
- return null;
110
- }
111
- }
112
- function canonical(root) {
113
- try {
114
- return realpathSync(root);
115
- } catch {
116
- return root;
117
- }
118
- }
119
- function resolveCcache({ root, dir = sharedCcache$1(), lookup = lookupCcache, onNote = (line) => console.error(line) }) {
120
- const binary = lookup();
121
- if (!binary) {
122
- onNote(chalk.dim(phaseLine("cache", "ccache off (not installed; brew install ccache)")));
123
- return null;
124
- }
125
- const declared = projectCmakeLauncher(readOrNull$1(join(root, "android", "app", "build.gradle")));
126
- if (declared) {
127
- onNote(chalk.dim(phaseLine("cache", `ccache off (android/app/build.gradle sets ${declared} itself)`)));
128
- return null;
129
- }
130
- const statsLog = ccacheStatsLog(root);
131
- register({
132
- dir,
133
- name: "ccache",
134
- prune: "atomic",
135
- note: "ccache keeps itself under CCACHE_MAXSIZE, so it is emptied whole or not at all"
136
- });
137
- onNote(chalk.dim(phaseLine("cache", `ccache on (${dir})`)));
138
- return {
139
- dir,
140
- statsLog,
141
- env: ccacheEnvironment({
142
- binary,
143
- dir,
144
- workspaceRoot: canonical(root),
145
- statsLog,
146
- maxSize: ccacheMaxSize()
147
- })
148
- };
149
- }
150
- //#endregion
15
+ import { homedir, tmpdir } from "node:os";
151
16
  //#region src/engine/bundler.ts
152
17
  const COCOAPODS_SPEC = /^ {4}cocoapods \(/m;
153
18
  function bundlerPin(root) {
@@ -308,15 +173,6 @@ function describeDiagnostic(diagnostic) {
308
173
  }
309
174
  //#endregion
310
175
  //#region src/engine/xcode.ts
311
- const IOS_DIR = "ios";
312
- const PREBUILD_REMEDY = "Generate it with `npx expo prebuild -p ios` (stim ios does this automatically for an Expo project with no ios/ directory), or commit the native project.";
313
- function buildFailure(message, remedy) {
314
- return { error: {
315
- code: "STIM_BUILD_FAILED",
316
- message,
317
- remedy
318
- } };
319
- }
320
176
  function pickXcodeProject(entries) {
321
177
  const names = (Array.isArray(entries) ? entries : []).filter((e) => typeof e === "string");
322
178
  const workspaces = names.filter((e) => e.endsWith(".xcworkspace")).toSorted();
@@ -344,22 +200,6 @@ function pickXcodeProject(entries) {
344
200
  }
345
201
  return null;
346
202
  }
347
- function discoverXcodeProject(root) {
348
- const dir = join(root, IOS_DIR);
349
- let entries;
350
- try {
351
- entries = readdirSync(dir);
352
- } catch {
353
- return buildFailure(`No ${IOS_DIR}/ directory in ${root}.`, PREBUILD_REMEDY);
354
- }
355
- const picked = pickXcodeProject(entries);
356
- if (!picked) return buildFailure(`${dir} contains no .xcworkspace and no .xcodeproj.`, PREBUILD_REMEDY);
357
- return {
358
- ...picked,
359
- dir,
360
- path: join(dir, picked.file)
361
- };
362
- }
363
203
  function parseSchemeList(text) {
364
204
  const empty = {
365
205
  name: null,
@@ -429,12 +269,12 @@ function resolveScheme(project, { exec = null, scheme: requested = null } = {})
429
269
  return { error: {
430
270
  code: "STIM_NO_SCHEME",
431
271
  message: `No shared Xcode scheme named ${JSON.stringify(requested)} in ${project.path}. Available schemes: ${listing.schemes.join(", ") || "none"}.`,
432
- remedy: "Pass an exact available name with --scheme, or share the intended app scheme in Xcode."
272
+ remedy: "Pass an exact available name with --scheme or set it in ios.scheme, or share the intended app scheme in Xcode."
433
273
  } };
434
274
  }
435
275
  let scheme = pickScheme(listing.schemes, listing.name || project.name);
436
276
  if (!scheme && project.dir) try {
437
- const app = JSON.parse(readFileSync(join(project.dir, "..", "app.json"), "utf8"));
277
+ const app = JSON.parse(readFileSync(join(project.appRoot ?? join(project.dir, ".."), "app.json"), "utf8"));
438
278
  scheme = pickScheme(listing.schemes, app?.name);
439
279
  } catch {}
440
280
  if (!scheme) {
@@ -442,7 +282,7 @@ function resolveScheme(project, { exec = null, scheme: requested = null } = {})
442
282
  return { error: {
443
283
  code: "STIM_NO_SCHEME",
444
284
  message: `Could not select an app scheme in ${project.path} (schemes: ${found}).`,
445
- remedy: listing.schemes.length > 0 ? "Pass --scheme <name> to select the intended shared app scheme. Stim does not guess between unmatched schemes." : "Share the app scheme in Xcode (Product > Scheme > Manage Schemes, tick Shared) so xcodebuild can see it."
285
+ remedy: listing.schemes.length > 0 ? "Pass --scheme <name>, or set ios.scheme, to select the intended shared app scheme. Stim does not guess between unmatched schemes." : "Share the app scheme in Xcode (Product > Scheme > Manage Schemes, tick Shared) so xcodebuild can see it."
446
286
  } };
447
287
  }
448
288
  return {
@@ -462,18 +302,6 @@ function compilationPrefixMappings(workspaceRoot, derivedDataPath) {
462
302
  if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) mappings.push(`${derived}=/^derived-data`);
463
303
  return mappings.map((mapping) => /[\s"\\]/.test(mapping) ? `"${mapping.replace(/["\\]/g, "\\$&")}"` : mapping).join(" ");
464
304
  }
465
- function ccacheEnabled(podfileProperties) {
466
- if (!podfileProperties || typeof podfileProperties !== "object") return false;
467
- return podfileProperties["apple.ccacheEnabled"] === "true";
468
- }
469
- function readPodfileProperties(root) {
470
- try {
471
- const parsed = JSON.parse(readFileSync(join(root, IOS_DIR, "Podfile.properties.json"), "utf-8"));
472
- return parsed && typeof parsed === "object" ? parsed : null;
473
- } catch {
474
- return null;
475
- }
476
- }
477
305
  const SWIFT_PREFIX_MAPPING_MIN_SWIFT = {
478
306
  major: 6,
479
307
  minor: 4
@@ -483,40 +311,12 @@ function swiftPrefixMappingSupported(version) {
483
311
  const min = SWIFT_PREFIX_MAPPING_MIN_SWIFT;
484
312
  return version.major > min.major || version.major === min.major && version.minor >= min.minor;
485
313
  }
486
- const SWIFT_CACHE_MIN_REACT_NATIVE = {
487
- major: 0,
488
- minor: 87
489
- };
490
- function reactNativeSupportsSwiftCache(version) {
491
- if (!version) return false;
492
- const min = SWIFT_CACHE_MIN_REACT_NATIVE;
493
- return version.major > min.major || version.major === min.major && version.minor >= min.minor;
494
- }
495
- function parseReactNativeVersion(packageJson) {
496
- if (!packageJson || typeof packageJson !== "object") return null;
497
- const raw = packageJson.version;
498
- const m = typeof raw === "string" ? /^(\d+)\.(\d+)\./.exec(raw) : null;
499
- if (!m || m[1] === void 0 || m[2] === void 0) return null;
500
- return {
501
- major: parseInt(m[1], 10),
502
- minor: parseInt(m[2], 10)
503
- };
504
- }
505
- function detectReactNativeVersion(root) {
506
- const file = resolvePackageJson(root, "react-native");
507
- if (!file) return null;
508
- try {
509
- return parseReactNativeVersion(JSON.parse(readFileSync(file, "utf-8")));
510
- } catch {
511
- return null;
512
- }
513
- }
514
- function compilationCacheSettings({ workspaceRoot, derivedDataPath, casPath, xcodeMajor, swiftVersion = null, reactNativeVersion = null, ccache = false, optimizations = resolveOptimizations({}, {}).ios }) {
314
+ function compilationCacheSettings({ workspaceRoot, derivedDataPath, casPath, xcodeMajor, swiftVersion = null, swiftCacheCompatible = false, ccache = false, optimizations = resolveOptimizations({}, {}).ios }) {
515
315
  if (xcodeMajor === null || xcodeMajor === void 0) return [];
516
316
  if (xcodeMajor < 26) return [];
517
317
  if (ccache) return [];
518
318
  const swiftMappable = swiftPrefixMappingSupported(swiftVersion);
519
- const auto = swiftMappable && reactNativeSupportsSwiftCache(reactNativeVersion);
319
+ const auto = swiftMappable && swiftCacheCompatible;
520
320
  const swift = optimizations.compilationCache && (optimizations.swiftCompilationCache ?? auto);
521
321
  const mappings = optimizations.prefixMapping ? compilationPrefixMappings(workspaceRoot, derivedDataPath) : "";
522
322
  return [
@@ -552,34 +352,6 @@ function parseXcodeMajor(output) {
552
352
  function detectXcodeMajor(exec = null) {
553
353
  return parseXcodeMajor((exec || getExecutor()).runQuiet("xcodebuild -version", { timeoutMs: 1e4 }));
554
354
  }
555
- function resolveCompilationCacheSettings({ root, derivedDataPath, exec = null, casPath = sharedCompilationCache$1(), optimizations = resolveOptimizations({}, {}).ios, onNote = (line) => console.error(line) }) {
556
- const xcodeMajor = detectXcodeMajor(exec);
557
- const ccache = ccacheEnabled(readPodfileProperties(root));
558
- const probe = xcodeMajor !== null && xcodeMajor >= 26 && !ccache && optimizations.compilationCache && optimizations.swiftCompilationCache !== false;
559
- const swiftVersion = probe ? detectSwiftVersion(exec) : null;
560
- const reactNativeVersion = probe ? detectReactNativeVersion(root) : null;
561
- const settings = compilationCacheSettings({
562
- workspaceRoot: root,
563
- derivedDataPath,
564
- casPath,
565
- xcodeMajor,
566
- swiftVersion,
567
- reactNativeVersion,
568
- ccache,
569
- optimizations
570
- });
571
- if (settings.length > 0 && optimizations.compilationCache) {
572
- register({
573
- dir: casPath,
574
- name: "Xcode compilation cache",
575
- prune: "atomic",
576
- note: "shared Xcode compilation cache"
577
- });
578
- const swift = settings.includes("SWIFT_ENABLE_COMPILE_CACHE=YES") ? settings.includes("SWIFT_ENABLE_PREFIX_MAPPING=YES") ? "Swift on" : "Swift on, unmapped" : swiftVersion && !swiftPrefixMappingSupported(swiftVersion) ? `Swift off, ${swiftVersion.major}.${swiftVersion.minor} < ${SWIFT_PREFIX_MAPPING_MIN_SWIFT.major}.${SWIFT_PREFIX_MAPPING_MIN_SWIFT.minor}` : swiftVersion && reactNativeVersion && !reactNativeSupportsSwiftCache(reactNativeVersion) ? `Swift off, react-native ${reactNativeVersion.major}.${reactNativeVersion.minor} < ${SWIFT_CACHE_MIN_REACT_NATIVE.major}.${SWIFT_CACHE_MIN_REACT_NATIVE.minor}` : "Swift off";
579
- onNote(chalk.dim(phaseLine("cache", `compilation cache on (CAS at ${casPath}, ${swift})`)));
580
- }
581
- return settings;
582
- }
583
355
  function xcodebuildArgs({ project, scheme, udid = null, destination = null, configuration = "Debug", sdk = "iphonesimulator", derivedDataPath, extraArgs = [], buildSettings = [] }) {
584
356
  return [
585
357
  project.flag,
@@ -782,13 +554,13 @@ function compilationCacheActivityLine(activity) {
782
554
  if (activity.status === "not-run") return "not run; artifact cache supplied the app";
783
555
  return "unavailable; Xcode did not report reliable statistics";
784
556
  }
785
- async function buildIos({ root, udid = null, logWriter, project = null, scheme = null, configuration = "Debug", sdk = "iphonesimulator", destination = null, arch = null, derivedDataPath = null, extraArgs = [], compilationCache = void 0, optimizations = resolveOptimizations({}, {}).ios, now = () => Date.now(), exec = null, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line), onNote = (line) => console.error(line) }) {
786
- if (!root || typeof root !== "string") throw new TypeError("buildIos requires {root}");
787
- if (!logWriter || typeof logWriter.write !== "function") throw new TypeError("buildIos requires {logWriter} with a write() method");
788
- if (!udid && !destination) throw new TypeError("buildIos requires {udid} (or an explicit {destination})");
557
+ async function buildXcode({ root, udid = null, logWriter, project, scheme = null, configuration = "Debug", applicationTarget, sdk = "iphonesimulator", destination = null, arch = null, derivedDataPath = null, extraArgs = [], compilationCache, startedAt: clockStart, now = () => Date.now(), exec = null, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line) }) {
558
+ if (!root || typeof root !== "string") throw new TypeError("buildXcode requires {root}");
559
+ if (!logWriter || typeof logWriter.write !== "function") throw new TypeError("buildXcode requires {logWriter} with a write() method");
560
+ if (!udid && !destination) throw new TypeError("buildXcode requires {udid} (or an explicit {destination})");
789
561
  const executor = exec || getExecutor();
790
562
  const dd = derivedDataPath || (scheme ? join(workspaceDerivedData(root), `scheme-${createHash("sha256").update(scheme).digest("hex")}`) : workspaceDerivedData(root));
791
- const startedAt = now();
563
+ const startedAt = clockStart ?? now();
792
564
  const elapsed = () => now() - startedAt;
793
565
  const reportError = (message, remedy) => {
794
566
  logWriter.write({
@@ -799,23 +571,18 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
799
571
  ...remedy ? { remedy } : {}
800
572
  });
801
573
  };
802
- let target = project;
803
- if (!target) {
804
- const discovered = discoverXcodeProject(root);
805
- if (discovered.error) {
806
- reportError(discovered.error.message, discovered.error.remedy);
807
- return failedResult({
808
- code: discovered.error.code,
809
- diagnostics: [{
810
- message: discovered.error.message,
811
- remedy: discovered.error.remedy ?? void 0
812
- }],
813
- durationMs: elapsed()
814
- });
815
- }
816
- target = discovered;
574
+ if (project.error) {
575
+ reportError(project.error.message, project.error.remedy);
576
+ return failedResult({
577
+ code: project.error.code,
578
+ diagnostics: [{
579
+ message: project.error.message,
580
+ remedy: project.error.remedy ?? void 0
581
+ }],
582
+ durationMs: elapsed()
583
+ });
817
584
  }
818
- const resolvedTarget = target;
585
+ const resolvedTarget = project;
819
586
  const selected = resolveScheme(resolvedTarget, {
820
587
  exec: executor,
821
588
  scheme
@@ -832,12 +599,9 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
832
599
  });
833
600
  }
834
601
  const buildScheme = selected.scheme;
835
- const cacheSettings = compilationCache === void 0 ? resolveCompilationCacheSettings({
836
- root,
602
+ const cacheSettings = typeof compilationCache === "function" ? compilationCache({
837
603
  derivedDataPath: dd,
838
- exec: executor,
839
- onNote,
840
- optimizations
604
+ exec: executor
841
605
  }) : compilationCache || [];
842
606
  const buildSettings = arch ? [
843
607
  ...cacheSettings,
@@ -1019,6 +783,7 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
1019
783
  for (const item of Array.isArray(targets) ? targets : []) {
1020
784
  const settings = item?.buildSettings;
1021
785
  if (settings?.PRODUCT_TYPE !== "com.apple.product-type.application" || settings.PLATFORM_NAME !== sdk) continue;
786
+ if (applicationTarget && (settings.TARGET_NAME !== applicationTarget.name || typeof settings.PROJECT_FILE_PATH !== "string" || realpathSync(settings.PROJECT_FILE_PATH) !== realpathSync(applicationTarget.projectPath))) continue;
1022
787
  const dir = settings.TARGET_BUILD_DIR;
1023
788
  const name = settings.FULL_PRODUCT_NAME;
1024
789
  if (typeof dir !== "string" || !isAbsolute(dir) || typeof name !== "string" || basename(name) !== name || !name.endsWith(".app")) continue;
@@ -1155,7 +920,7 @@ function extractRubyHead(lines) {
1155
920
  }
1156
921
  return null;
1157
922
  }
1158
- function podsAreStale(lockText, manifestText) {
923
+ function podsAreStale(lockText, manifestText, dir = "ios/") {
1159
924
  const lock = normalize(lockText);
1160
925
  const manifest = normalize(manifestText);
1161
926
  if (lock === null && manifest === null) return {
@@ -1164,15 +929,15 @@ function podsAreStale(lockText, manifestText) {
1164
929
  };
1165
930
  if (lock === null) return {
1166
931
  stale: true,
1167
- reason: "ios/Podfile.lock is missing but ios/Pods exists"
932
+ reason: `${dir}Podfile.lock is missing but ${dir}Pods exists`
1168
933
  };
1169
934
  if (manifest === null) return {
1170
935
  stale: true,
1171
- reason: "ios/Pods/Manifest.lock is missing (pods have never been installed here)"
936
+ reason: `${dir}Pods/Manifest.lock is missing (pods have never been installed here)`
1172
937
  };
1173
938
  if (lock !== manifest) return {
1174
939
  stale: true,
1175
- reason: "ios/Podfile.lock and ios/Pods/Manifest.lock differ"
940
+ reason: `${dir}Podfile.lock and ${dir}Pods/Manifest.lock differ`
1176
941
  };
1177
942
  return { stale: false };
1178
943
  }
@@ -1180,14 +945,13 @@ function normalize(text) {
1180
945
  if (typeof text !== "string") return null;
1181
946
  return text.replace(/\r\n/g, "\n").trimEnd();
1182
947
  }
1183
- function podfilePath(root) {
1184
- return join(root, "ios", "Podfile");
1185
- }
1186
- function readPodState(root) {
948
+ function readPodState(root, directory = join(root, "ios")) {
949
+ const rel = relative(root, directory);
1187
950
  return {
1188
- hasPodfile: existsSync(podfilePath(root)),
1189
- lockText: readOrNull(join(root, "ios", "Podfile.lock")),
1190
- manifestText: readOrNull(join(root, "ios", "Pods", "Manifest.lock"))
951
+ hasPodfile: existsSync(join(directory, "Podfile")),
952
+ lockText: readOrNull(join(directory, "Podfile.lock")),
953
+ manifestText: readOrNull(join(directory, "Pods", "Manifest.lock")),
954
+ dir: rel ? `${rel}/` : ""
1191
955
  };
1192
956
  }
1193
957
  function readOrNull(file) {
@@ -1200,7 +964,96 @@ function readOrNull(file) {
1200
964
  function podEnv(root, options = {}) {
1201
965
  return podEnvForRuby(readRubyVersion(root), options);
1202
966
  }
1203
- function podEnvForRuby(version, { env = process.env, home = homedir(), exists = existsSync } = {}) {
967
+ const LOGIN_ENV_BEGIN = "@@ruby-env-begin@@";
968
+ const LOGIN_ENV_END = "@@ruby-env-end@@";
969
+ const LOGIN_ENV_SCRIPT = `printf '\\n${LOGIN_ENV_BEGIN}\\nPATH=%s\\nGEM_HOME=%s\\nGEM_PATH=%s\\n${LOGIN_ENV_END}\\n' "\$PATH" "\$GEM_HOME" "\$GEM_PATH" > "\$1"`;
970
+ function parseLoginRubyEnv(output) {
971
+ const lines = output.split("\n").map((line) => line.replace(/\r$/, ""));
972
+ const begin = lines.lastIndexOf(LOGIN_ENV_BEGIN);
973
+ const end = lines.indexOf(LOGIN_ENV_END, begin + 1);
974
+ if (begin < 0 || end < 0) return null;
975
+ const out = {};
976
+ for (const line of lines.slice(begin + 1, end)) {
977
+ const eq = line.indexOf("=");
978
+ if (eq < 0) continue;
979
+ const key = line.slice(0, eq);
980
+ const value = line.slice(eq + 1);
981
+ if (value && (key === "PATH" || key === "GEM_HOME" || key === "GEM_PATH")) out[key] = value;
982
+ }
983
+ return out;
984
+ }
985
+ const loginRubyEnvByShell = /* @__PURE__ */ new Map();
986
+ const LOGIN_ENV_OPTIONS = {
987
+ timeoutMs: 1e4,
988
+ killSignal: "SIGKILL",
989
+ detachedSilent: true
990
+ };
991
+ function readLoginRubyEnv(shell = process.env.SHELL, platform = process.platform) {
992
+ if (platform !== "darwin" || !shell || !isAbsolute(shell)) return null;
993
+ if (loginRubyEnvByShell.has(shell)) return loginRubyEnvByShell.get(shell) ?? null;
994
+ let dir = null;
995
+ let parsed = null;
996
+ try {
997
+ dir = mkdtempSync(join(tmpdir(), "stim-ruby-env-"));
998
+ const file = join(dir, "env");
999
+ getExecutor().runFile(shell, [
1000
+ "-lic",
1001
+ LOGIN_ENV_SCRIPT,
1002
+ "stim",
1003
+ file
1004
+ ], LOGIN_ENV_OPTIONS);
1005
+ parsed = parseLoginRubyEnv(readFileSync(file, "utf-8"));
1006
+ } catch {
1007
+ parsed = null;
1008
+ } finally {
1009
+ if (dir) rmSync(dir, {
1010
+ recursive: true,
1011
+ force: true
1012
+ });
1013
+ }
1014
+ loginRubyEnvByShell.set(shell, parsed);
1015
+ return parsed;
1016
+ }
1017
+ async function readLoginRubyEnvAsync(shell = process.env.SHELL, platform = process.platform) {
1018
+ if (platform !== "darwin" || !shell || !isAbsolute(shell)) return null;
1019
+ if (loginRubyEnvByShell.has(shell)) return loginRubyEnvByShell.get(shell) ?? null;
1020
+ let dir = null;
1021
+ let parsed = null;
1022
+ try {
1023
+ dir = mkdtempSync(join(tmpdir(), "stim-ruby-env-"));
1024
+ const file = join(dir, "env");
1025
+ await getExecutor().runFileAsync(shell, [
1026
+ "-lic",
1027
+ LOGIN_ENV_SCRIPT,
1028
+ "stim",
1029
+ file
1030
+ ], LOGIN_ENV_OPTIONS);
1031
+ parsed = parseLoginRubyEnv(readFileSync(file, "utf-8"));
1032
+ } catch {
1033
+ parsed = null;
1034
+ } finally {
1035
+ if (dir) rmSync(dir, {
1036
+ recursive: true,
1037
+ force: true
1038
+ });
1039
+ }
1040
+ loginRubyEnvByShell.set(shell, parsed);
1041
+ return parsed;
1042
+ }
1043
+ function rubyPathEntries(login, callerPath, exists) {
1044
+ const have = new Set((callerPath ?? "").split(delimiter));
1045
+ const gemDirs = [login.GEM_HOME, ...(login.GEM_PATH ?? "").split(delimiter)].filter((dir) => !!dir);
1046
+ return (login.PATH ?? "").split(delimiter).filter((entry) => {
1047
+ if (!entry || have.has(entry)) return false;
1048
+ if (gemDirs.some((gem) => entry === gem || entry.startsWith(gem + sep))) return true;
1049
+ return exists(join(entry, "ruby")) || exists(join(entry, "pod"));
1050
+ });
1051
+ }
1052
+ function prependPath(entries, existing) {
1053
+ const seen = /* @__PURE__ */ new Set();
1054
+ return [...entries, ...(existing ?? "").split(delimiter)].filter((entry) => entry && !seen.has(entry) && seen.add(entry)).join(delimiter);
1055
+ }
1056
+ function podEnvForRuby(version, { env = process.env, home = homedir(), exists = existsSync, loginEnv = readLoginRubyEnv } = {}) {
1204
1057
  const out = {
1205
1058
  ...env,
1206
1059
  FORCE_COLOR: "0",
@@ -1208,8 +1061,7 @@ function podEnvForRuby(version, { env = process.env, home = homedir(), exists =
1208
1061
  LANG: env.LANG ?? "en_US.UTF-8",
1209
1062
  LC_ALL: env.LC_ALL ?? env.LANG ?? "en_US.UTF-8"
1210
1063
  };
1211
- if (!version) return out;
1212
- const candidates = [
1064
+ const candidates = version ? [
1213
1065
  { bin: join(home, ".rbenv", "versions", version, "bin") },
1214
1066
  {
1215
1067
  bin: join(home, ".rvm", "rubies", `ruby-${version}`, "bin"),
@@ -1217,7 +1069,7 @@ function podEnvForRuby(version, { env = process.env, home = homedir(), exists =
1217
1069
  },
1218
1070
  { bin: join(home, ".asdf", "installs", "ruby", version, "bin") },
1219
1071
  { bin: join(home, ".local", "share", "mise", "installs", "ruby", version, "bin") }
1220
- ];
1072
+ ] : [];
1221
1073
  for (const c of candidates) {
1222
1074
  if (!exists(c.bin)) continue;
1223
1075
  out.PATH = `${c.bin}${delimiter}${out.PATH ?? ""}`;
@@ -1225,10 +1077,27 @@ function podEnvForRuby(version, { env = process.env, home = homedir(), exists =
1225
1077
  out.GEM_HOME = c.gems;
1226
1078
  out.GEM_PATH = c.gems;
1227
1079
  }
1228
- break;
1080
+ return out;
1229
1081
  }
1082
+ if (env.GEM_HOME) return out;
1083
+ const login = loginEnv();
1084
+ if (!login) return out;
1085
+ const rubyPath = rubyPathEntries(login, out.PATH, exists);
1086
+ if (rubyPath.length) out.PATH = prependPath(rubyPath, out.PATH);
1087
+ if (login.GEM_HOME) out.GEM_HOME = login.GEM_HOME;
1088
+ if (login.GEM_PATH) out.GEM_PATH = login.GEM_PATH;
1230
1089
  return out;
1231
1090
  }
1091
+ async function podEnvForRubyAsync(version) {
1092
+ let loginNeeded = false;
1093
+ const withoutLogin = podEnvForRuby(version, { loginEnv: () => {
1094
+ loginNeeded = true;
1095
+ return null;
1096
+ } });
1097
+ if (!loginNeeded) return withoutLogin;
1098
+ const login = await readLoginRubyEnvAsync();
1099
+ return podEnvForRuby(version, { loginEnv: () => login });
1100
+ }
1232
1101
  function readRubyVersion(root, { read = readFileSync } = {}) {
1233
1102
  try {
1234
1103
  const first = String(read(join(root, ".ruby-version"), "utf-8")).split("\n").map((l) => l.trim()).find((l) => l && !l.startsWith("#"));
@@ -1399,12 +1268,12 @@ function gemInstallRemedy(root, pin) {
1399
1268
  const version = readRubyVersion(root);
1400
1269
  return `${version ? `This repo pins ruby ${version} (.ruby-version), so put that ruby on PATH (rbenv/rvm/asdf/mise) first. ` : ""}Bundler could not install the gems ${pin.lockfile} pins, so \`bundle exec pod install\` cannot run. Run \`cd ${root} && bundle install\` and fix what it reports, then run again.`;
1401
1270
  }
1402
- async function runPodInstall(root, logWriter, { spawnFn = null, now = Date.now, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line) } = {}) {
1403
- const iosDir = join(root, "ios");
1271
+ async function runPodInstall(root, logWriter, { spawnFn = null, now = Date.now, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line), directory = join(root, "ios") } = {}) {
1272
+ const iosDir = directory;
1404
1273
  if (!existsSync(iosDir)) return {
1405
1274
  failed: true,
1406
1275
  code: DEPS_ERROR,
1407
- reason: `No ios/ directory in ${root}, so there is nothing to pod install.`,
1276
+ reason: `No ${relative(root, iosDir) || "."}/ directory in ${root}, so there is nothing to pod install.`,
1408
1277
  remedy: "Run `stim ios` on a project with native iOS sources, or let prebuild generate them.",
1409
1278
  lastLines: []
1410
1279
  };
@@ -1515,40 +1384,71 @@ function missingPod(err) {
1515
1384
  };
1516
1385
  }
1517
1386
  //#endregion
1518
- //#region src/offload/manifest.ts
1519
- function manifestDigest(entries) {
1520
- const hash = createHash("sha256");
1521
- for (const entry of entries.toSorted((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)) hash.update(`${entry.path}\0${entry.kind}\0${entry.sha256}\n`);
1522
- return hash.digest("hex");
1523
- }
1524
- //#endregion
1525
1387
  //#region src/offload/toolchain.ts
1526
1388
  const distDir = dirname(fileURLToPath(import.meta.url));
1527
1389
  function quiet(file, args) {
1528
1390
  return getExecutor().runFileQuiet(file, args, { timeoutMs: 2e4 });
1529
1391
  }
1530
- function iosToolchain(root) {
1531
- return iosToolchainForRuby(readRubyVersion(root));
1392
+ function iosToolchain(root, native) {
1393
+ return iosToolchainForRuby(native ? null : readRubyVersion(root), native);
1532
1394
  }
1533
- function iosToolchainForRuby(rubyVersion) {
1534
- const xcode = quiet("xcodebuild", ["-version"]);
1395
+ async function quietAsync(file, args) {
1396
+ try {
1397
+ return await getExecutor().runFileAsync(file, args, { timeoutMs: 2e4 });
1398
+ } catch {
1399
+ return null;
1400
+ }
1401
+ }
1402
+ async function iosToolchainAsync(root) {
1403
+ const rubyVersion = readRubyVersion(root);
1404
+ const [xcode, simulatorSdk, cocoapods] = await Promise.all([
1405
+ quietAsync("xcodebuild", ["-version"]),
1406
+ quietAsync("xcrun", [
1407
+ "--sdk",
1408
+ "iphonesimulator",
1409
+ "--show-sdk-version"
1410
+ ]),
1411
+ cocoapodsVersionAsync(rubyVersion)
1412
+ ]);
1413
+ return assembleIosToolchain(xcode, simulatorSdk, cocoapods);
1414
+ }
1415
+ function iosToolchainForRuby(rubyVersion, native) {
1416
+ return assembleIosToolchain(quiet("xcodebuild", ["-version"]), quiet("xcrun", [
1417
+ "--sdk",
1418
+ "iphonesimulator",
1419
+ "--show-sdk-version"
1420
+ ]), native ? null : cocoapodsVersion(rubyVersion));
1421
+ }
1422
+ function assembleIosToolchain(xcode, simulatorSdk, cocoapods) {
1535
1423
  return {
1536
1424
  stimBuild: stimBuildDigest(distDir),
1537
1425
  arch: process.arch,
1538
1426
  xcode: xcode ? xcode.trim().replace(/\n/g, " / ") : null,
1539
- simulatorSdk: quiet("xcrun", [
1540
- "--sdk",
1541
- "iphonesimulator",
1542
- "--show-sdk-version"
1543
- ])?.trim() ?? null,
1544
- cocoapods: cocoapodsVersion(rubyVersion)
1427
+ simulatorSdk: simulatorSdk?.trim() ?? null,
1428
+ cocoapods
1545
1429
  };
1546
1430
  }
1431
+ function podProbeEnv(env) {
1432
+ return Object.fromEntries(Object.entries(env).filter((entry) => entry[1] !== void 0));
1433
+ }
1434
+ function podVersionLine(output) {
1435
+ return output?.trim().split("\n").pop()?.trim() ?? null;
1436
+ }
1547
1437
  function cocoapodsVersion(rubyVersion) {
1548
- return getExecutor().runFileQuiet("pod", ["--version"], {
1438
+ return podVersionLine(getExecutor().runFileQuiet("pod", ["--version"], {
1549
1439
  timeoutMs: 2e4,
1550
- env: Object.fromEntries(Object.entries(podEnvForRuby(rubyVersion)).filter((entry) => entry[1] !== void 0))
1551
- })?.trim().split("\n").pop()?.trim() ?? null;
1440
+ env: podProbeEnv(podEnvForRuby(rubyVersion))
1441
+ }));
1442
+ }
1443
+ async function cocoapodsVersionAsync(rubyVersion) {
1444
+ try {
1445
+ return podVersionLine(await getExecutor().runFileAsync("pod", ["--version"], {
1446
+ timeoutMs: 2e4,
1447
+ env: podProbeEnv(await podEnvForRubyAsync(rubyVersion))
1448
+ }));
1449
+ } catch {
1450
+ return null;
1451
+ }
1552
1452
  }
1553
1453
  function macosToolchain() {
1554
1454
  const xcode = quiet("xcodebuild", ["-version"]);
@@ -1639,7 +1539,17 @@ function sdkPackages() {
1639
1539
  platforms
1640
1540
  };
1641
1541
  }
1642
- function workerToolchain(rubyVersion = null) {
1542
+ function workerToolchain(rubyVersion = null, native) {
1543
+ if (native === "gradle") return {
1544
+ ...androidToolchain(),
1545
+ xcode: null,
1546
+ simulatorSdk: null,
1547
+ cocoapods: null,
1548
+ macosSdk: null,
1549
+ bundler: null,
1550
+ runtimes: [],
1551
+ androidSdk: sdkPackages()
1552
+ };
1643
1553
  let listed = null;
1644
1554
  try {
1645
1555
  listed = JSON.parse(quiet("xcrun", [
@@ -1651,16 +1561,16 @@ function workerToolchain(rubyVersion = null) {
1651
1561
  ]) ?? "null");
1652
1562
  } catch {}
1653
1563
  return {
1654
- ...iosToolchainForRuby(rubyVersion),
1655
- macosSdk: quiet("xcrun", [
1564
+ ...iosToolchainForRuby(rubyVersion, native),
1565
+ macosSdk: native ? null : quiet("xcrun", [
1656
1566
  "--sdk",
1657
1567
  "macosx",
1658
1568
  "--show-sdk-version"
1659
1569
  ])?.trim() ?? null,
1660
- bundler: quiet("bundle", ["--version"])?.trim() || null,
1570
+ bundler: native ? null : quiet("bundle", ["--version"])?.trim() || null,
1661
1571
  runtimes: iphoneRuntimes(listed),
1662
- jdk: localJdk(),
1663
- androidSdk: sdkPackages()
1572
+ jdk: native ? null : localJdk(),
1573
+ androidSdk: native ? null : sdkPackages()
1664
1574
  };
1665
1575
  }
1666
1576
  /** The API level of an SDK `platforms/` directory: `android-37.0` and `android-37` are both 37. */
@@ -1728,12 +1638,12 @@ function toolchainMismatches(target, worker) {
1728
1638
  code: "simulator-sdk",
1729
1639
  reason: versionMismatch("simulator SDK", worker.simulatorSdk, ios.simulatorSdk)
1730
1640
  });
1731
- if (target.cocoapodsPinned) {
1641
+ if (!target.native && target.cocoapodsPinned) {
1732
1642
  if (!worker.bundler) out.push({
1733
1643
  code: "bundler",
1734
1644
  reason: "no Bundler there to run the CocoaPods this project's Gemfile.lock pins"
1735
1645
  });
1736
- } else if (worker.cocoapods !== ios.cocoapods) out.push({
1646
+ } else if (!target.native && worker.cocoapods !== ios.cocoapods) out.push({
1737
1647
  code: "cocoapods",
1738
1648
  reason: versionMismatch("CocoaPods", worker.cocoapods, ios.cocoapods)
1739
1649
  });
@@ -1744,4 +1654,4 @@ function toolchainMismatches(target, worker) {
1744
1654
  return out;
1745
1655
  }
1746
1656
  //#endregion
1747
- export { CCACHE_NOT_RUN as A, readBundleId as C, describeDiagnostic as D, tailLines as E, resolveCcache as F, ccacheActivityLine as M, projectCmakeLauncher as N, bundlerPin as O, readCcacheActivity as P, readBundleExecutable as S, startBuildHeartbeat as T, buildIos as _, toolchainMismatches as a, detectXcodeMajor as b, DEPS_ERROR as c, readRubyVersion as d, runCaptured as f, HEARTBEAT_INTERVAL_MS as g, COMPILATION_CACHE_UNAVAILABLE as h, macosToolchain as i, CCACHE_UNAVAILABLE as j, podInstallCommand as k, podsAreStale as l, COMPILATION_CACHE_NOT_RUN as m, androidToolchain as n, workerToolchain as o, runPodInstall as p, iosToolchain as r, manifestDigest as s, androidRequirements as t, readPodState as u, ccacheEnabled as v, resolveScheme as w, discoverXcodeProject as x, compilationCacheActivityLine as y };
1657
+ export { readBundleId as A, compilationCacheSettings as C, parseXcodeMajor as D, parseSwiftVersion as E, describeDiagnostic as F, bundlerPin as I, podInstallCommand as L, startBuildHeartbeat as M, swiftPrefixMappingSupported as N, pickXcodeProject as O, tailLines as P, compilationCacheActivityLine as S, detectXcodeMajor as T, COMPILATION_CACHE_NOT_RUN as _, iphoneRuntimes as a, SWIFT_PREFIX_MAPPING_MIN_SWIFT as b, parseAndroidRequirements as c, DEPS_ERROR as d, podsAreStale as f, runPodInstall as g, runCaptured as h, iosToolchainAsync as i, resolveScheme as j, readBundleExecutable as k, toolchainMismatches as l, readRubyVersion as m, androidToolchain as n, jdkMajor as o, readPodState as p, iosToolchain as r, macosToolchain as s, androidRequirements as t, workerToolchain as u, COMPILATION_CACHE_UNAVAILABLE as v, detectSwiftVersion as w, buildXcode as x, HEARTBEAT_INTERVAL_MS as y };