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,35 +1,15 @@
1
- import { t as getExecutor } from "./exec-DWhCZDGm.mjs";
1
+ import { t as getExecutor } from "./exec-B81Qodjn.mjs";
2
2
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
3
- import { l as phaseLine } from "./command-output-CBtzyIgF.mjs";
3
+ import { l as phaseLine } from "./command-output-BjPN99ZB.mjs";
4
+ import { o as androidHome } from "./android-BsYNR81W.mjs";
4
5
  import { a as spawnDeclared } from "./spawn-claims-Kqiifsk2.mjs";
5
- import { o as androidHome } from "./android-DC3ZLuw0.mjs";
6
- import { P as readCcacheActivity, T as startBuildHeartbeat, g as HEARTBEAT_INTERVAL_MS, j as CCACHE_UNAVAILABLE } from "./toolchain-Bnyd_K3A.mjs";
6
+ import { a as readCcacheActivity, n as CCACHE_UNAVAILABLE } from "./ccache-CjHQ5F8g.mjs";
7
+ import { M as startBuildHeartbeat, y as HEARTBEAT_INTERVAL_MS } from "./toolchain-DqyDXs30.mjs";
7
8
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
8
9
  import { dirname, isAbsolute, join, relative, sep } from "node:path";
9
10
  import { fileURLToPath } from "node:url";
10
- import chalk from "chalk";
11
11
  import { createHash } from "node:crypto";
12
- /** The ABI name a build for every ABI has to fit; `stim android` narrows a build to the device's. */
13
- const LONGEST_ANDROID_ABI = "armeabi-v7a";
14
- function androidPathRoom(root, { abi = null, variant = null, platform = process.platform } = {}) {
15
- if (platform !== "win32") return null;
16
- const abiName = abi ?? LONGEST_ANDROID_ABI;
17
- const tail = 198 + (/release$/i.test(variant ?? "") ? 14 : 5) - 5 + abiName.length;
18
- const longest = root.length + tail;
19
- if (longest < 240) return null;
20
- return {
21
- root,
22
- abi: abiName,
23
- longest,
24
- maxRootLength: 239 - tail
25
- };
26
- }
27
- function androidPathRoomMessage({ root, abi, longest, maxRootLength }) {
28
- return `The project root ${root} is ${root.length} characters, so the longest known Android native object path (react_codegen_safeareacontext for ${abi}) reaches ${longest} characters, past the 239 the NDK's ninja can be given on Windows; the root can be at most ${maxRootLength} characters.`;
29
- }
30
- function androidPathRoomRemedy({ root }) {
31
- return `Map the project to a drive letter (\`subst X: "${root}"\`) and run Stim from X:\\, or move it under a shorter root.`;
32
- }
12
+ import chalk from "chalk";
33
13
  const MAX_MESSAGE_LENGTH = 300;
34
14
  const KOTLIN_URI = /^e:\s+file:\/\/(\/\S+?):(\d+):(\d+)\s+(.*)$/;
35
15
  const KOTLIN_PAREN = /^e:\s+(\S+?):\s*\((\d+),\s*(\d+)\):\s*(.*)$/;
@@ -290,44 +270,12 @@ function assembleTaskFor(variant) {
290
270
  }
291
271
  const LAST_LINES = 20;
292
272
  const TRANSCRIPT_LINES = 2e3;
293
- function androidDir(root) {
294
- return join(root, "android");
295
- }
296
- function gradlewPath(root) {
297
- return join(androidDir(root), process.platform === "win32" ? "gradlew.bat" : "gradlew");
298
- }
299
- function apkOutputsDir(root) {
300
- return join(androidDir(root), "app", "build", "outputs", "apk");
301
- }
302
- function debugApkDir(root) {
303
- return join(apkOutputsDir(root), "debug");
304
- }
305
- function discoverAndroidProject(root) {
306
- const dir = androidDir(root);
307
- if (!existsSync(dir)) return {
308
- failed: true,
309
- code: BUILD_ERROR,
310
- reason: `No android/ directory in ${root}.`,
311
- remedy: "Generate it (`npx expo prebuild -p android`, which `stim android` runs itself on an Expo project) or check out the native sources."
312
- };
313
- const gradlew = gradlewPath(root);
314
- if (!existsSync(gradlew)) return {
315
- failed: true,
316
- code: BUILD_ERROR,
317
- reason: `${gradlew} does not exist, so there is no gradle wrapper to build with.`,
318
- remedy: "Restore the wrapper (`gradle wrapper` in android/, or regenerate the project with `npx expo prebuild -p android --clean`)."
319
- };
320
- return {
321
- androidDir: dir,
322
- gradlew
323
- };
324
- }
325
- function androidSdkRefusal({ sdkPath, sdkExists, hasLocalProperties }) {
273
+ function androidSdkRefusal({ sdkPath, sdkExists, hasLocalProperties, localPropertiesPath }) {
326
274
  if (sdkExists || hasLocalProperties) return null;
327
275
  return {
328
276
  code: BUILD_ERROR,
329
277
  reason: `No Android SDK at ${sdkPath}.`,
330
- remedy: "Set ANDROID_HOME to the Android SDK (Android Studio installs it at ~/Library/Android/sdk), or write sdk.dir into android/local.properties. JAVA_HOME must point at a JDK 17 install as well."
278
+ remedy: `Set ANDROID_HOME to the Android SDK (Android Studio installs it at ~/Library/Android/sdk), or write sdk.dir into ${localPropertiesPath}. JAVA_HOME must point at a JDK 17 install as well.`
331
279
  };
332
280
  }
333
281
  function pickDebugApk(files) {
@@ -392,8 +340,7 @@ function listApkSubdirs(base, prefix = [], depth = 0) {
392
340
  }
393
341
  return dirs;
394
342
  }
395
- function findVariantApkDir(root, variant) {
396
- const base = apkOutputsDir(root);
343
+ function findVariantApkDir(base, variant) {
397
344
  const wanted = variant.trim().toLowerCase();
398
345
  for (const segments of listApkSubdirs(base)) if (variantNameOf(segments).toLowerCase() === wanted) return join(base, ...segments);
399
346
  return null;
@@ -410,25 +357,25 @@ function findDebugApksUnder(base) {
410
357
  }
411
358
  return found.toSorted();
412
359
  }
413
- function locateApk(root, transcript = "", variant = null) {
360
+ function locateApk(project, transcript = "", variant = null) {
414
361
  const fromTranscript = parseApkFromTranscript(transcript);
415
362
  if (fromTranscript) {
416
- const abs = isAbsolute(fromTranscript) ? fromTranscript : join(androidDir(root), fromTranscript);
363
+ const abs = isAbsolute(fromTranscript) ? fromTranscript : join(project.directory, fromTranscript);
417
364
  if (existsSync(abs)) return { apkPath: abs };
418
365
  }
419
366
  if (variant) {
420
- const dir = findVariantApkDir(root, variant);
367
+ const dir = findVariantApkDir(project.outputsDir, variant);
421
368
  return { apkPath: dir ? apkInDir(dir) : null };
422
369
  }
423
- const direct = apkInDir(debugApkDir(root));
370
+ const direct = apkInDir(join(project.outputsDir, "debug"));
424
371
  if (direct) return { apkPath: direct };
425
- const found = findDebugApksUnder(apkOutputsDir(root));
372
+ const found = findDebugApksUnder(project.outputsDir);
426
373
  if (found.length === 1) {
427
374
  const apk = found[0];
428
- const suggested = variantNameOf(relative(apkOutputsDir(root), apk).split(sep).slice(0, -1));
375
+ const suggested = variantNameOf(relative(project.outputsDir, apk).split(sep).slice(0, -1));
429
376
  return {
430
377
  apkPath: apk,
431
- note: `no APK in ${relative(androidDir(root), debugApkDir(root))}; using ${relative(androidDir(root), apk)}${suggested ? ` -- set the android.variant setting to "${suggested}" to build this variant explicitly` : ""}`
378
+ note: `no APK in ${relative(project.directory, join(project.outputsDir, "debug"))}; using ${relative(project.directory, apk)}${suggested ? ` -- set the android.variant setting to "${suggested}" to build this variant explicitly` : ""}`
432
379
  };
433
380
  }
434
381
  if (found.length > 1) return {
@@ -585,48 +532,21 @@ function parseProductFlavors(source) {
585
532
  dimensions
586
533
  };
587
534
  }
588
- function readProductFlavors(root) {
589
- return parseProductFlavors(readOrNull(join(androidDir(root), "app", "build.gradle")));
590
- }
591
- function productFlavorRefusal({ flavors, variant }) {
592
- if (variant) return null;
593
- if (!flavors.known || flavors.dimensions.length === 0) return null;
594
- let combinations = [[]];
595
- for (const group of flavors.dimensions) combinations = combinations.flatMap((combination) => group.map((flavor) => combination.concat(flavor)));
596
- if (combinations.length < 2) return null;
597
- const count = flavors.dimensions.reduce((total, group) => total + group.length, 0);
598
- const variants = combinations.map((combination) => variantNameOf(combination.concat("debug")));
599
- return {
600
- code: "STIM_BAD_ARG",
601
- reason: `android/app/build.gradle declares ${count} product flavors, so \`./gradlew ${ASSEMBLE_TASK}\` builds an APK for each of them and nothing says which flavor to install.`,
602
- remedy: `Pass \`--variant ${variants[0]}\` or set the android.variant setting -- e.g. {"android": {"variant": "${variants[0]}"}} in .stim.json. The debug variants are: ${variants.join(", ")}.`
603
- };
604
- }
605
- function gradleArgs(task, { buildCache = true, abi = null } = {}) {
535
+ function gradleArgs(task, { buildCache = true, projectArgs = [] } = {}) {
606
536
  return [
607
537
  task,
608
538
  ...buildCache ? ["--build-cache"] : ["--no-build-cache"],
609
- ...abi ? [`-PreactNativeArchitectures=${abi}`] : []
539
+ ...projectArgs
610
540
  ];
611
541
  }
612
- async function buildAndroid({ root, logWriter, variant = null, abi = null }, { spawnFn = null, now = Date.now, env = process.env, buildCache = true, ccache = null, cas = null, pch = "auto", compilerCacheDisabled = false, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line), onNote = (line) => console.error(line), platform = process.platform } = {}) {
613
- const project = discoverAndroidProject(root);
614
- if (project.failed) return {
615
- ok: false,
616
- code: project.code,
617
- reason: project.reason,
618
- remedy: project.remedy,
619
- diagnostics: [],
620
- truncated: 0,
621
- lastLines: [],
622
- durationMs: 0
623
- };
542
+ async function buildGradle({ root, logWriter, variant = null, project, task, projectArgs = [], preflightFailure = null, locate }, { spawnFn = null, now = Date.now, env = process.env, buildCache = true, ccache = null, cas = null, pch = "auto", compilerCacheDisabled = false, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line), onNote = (line) => console.error(line) } = {}) {
624
543
  const sdk = androidHome(env);
625
544
  const sdkExists = existsSync(sdk);
626
545
  const refusal = androidSdkRefusal({
627
546
  sdkPath: sdk,
628
547
  sdkExists,
629
- hasLocalProperties: existsSync(join(project.androidDir, "local.properties"))
548
+ hasLocalProperties: existsSync(join(project.directory, "local.properties")),
549
+ localPropertiesPath: relative(root, join(project.directory, "local.properties")).split(sep).join("/")
630
550
  });
631
551
  if (refusal) return {
632
552
  ok: false,
@@ -636,26 +556,21 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
636
556
  lastLines: [],
637
557
  durationMs: 0
638
558
  };
639
- const room = androidPathRoom(root, {
640
- abi,
641
- variant,
642
- platform
643
- });
644
- if (room) return {
559
+ if (preflightFailure) return {
645
560
  ok: false,
646
- code: "STIM_PATH_TOO_LONG",
647
- reason: androidPathRoomMessage(room),
648
- remedy: androidPathRoomRemedy(room),
561
+ ...preflightFailure,
649
562
  diagnostics: [],
650
563
  truncated: 0,
651
564
  lastLines: [],
652
565
  durationMs: 0
653
566
  };
567
+ const wrapper = `./${relative(project.directory, project.gradlew).split(sep).join("/")}`;
568
+ const moduleTask = task.includes(":") ? task : `${project.module === ":" ? "" : project.module}:${task}`;
569
+ const tasksTask = `${project.module === ":" ? "" : project.module}:tasks`;
654
570
  const spawn = spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts));
655
- const task = assembleTaskFor(variant);
656
571
  const args = gradleArgs(task, {
657
572
  buildCache,
658
- abi
573
+ projectArgs
659
574
  });
660
575
  if (cas) {
661
576
  args.push("--init-script", cas.initScript);
@@ -709,7 +624,7 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
709
624
  let child;
710
625
  try {
711
626
  child = spawnDeclared(() => spawn(project.gradlew, args, {
712
- cwd: project.androidDir,
627
+ cwd: project.directory,
713
628
  stdio: [
714
629
  "ignore",
715
630
  "pipe",
@@ -726,7 +641,7 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
726
641
  }
727
642
  }));
728
643
  } catch (err) {
729
- return spawnFailure(err, project, now() - startedAt);
644
+ return spawnFailure(err, root, project, now() - startedAt);
730
645
  }
731
646
  const outReader = createLineReader(push);
732
647
  const errReader = createLineReader(push);
@@ -748,7 +663,7 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
748
663
  const transcript = window.join("\n");
749
664
  const ccacheActivity = ccache ? readCcacheActivity(ccache.statsLog) : CCACHE_UNAVAILABLE;
750
665
  if (result.error) return {
751
- ...spawnFailure(result.error, project, durationMs),
666
+ ...spawnFailure(result.error, root, project, durationMs),
752
667
  lastLines: tail.slice(),
753
668
  ccache: ccacheActivity
754
669
  };
@@ -758,7 +673,7 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
758
673
  return {
759
674
  ok: false,
760
675
  code: BUILD_ERROR,
761
- reason: `\`./gradlew ${task}\` failed (${how}).`,
676
+ reason: `\`${wrapper} ${task}\` failed (${how}).`,
762
677
  diagnostics: shown,
763
678
  truncated,
764
679
  lastLines: tail.slice(),
@@ -766,23 +681,32 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
766
681
  ccache: ccacheActivity
767
682
  };
768
683
  }
769
- const located = locateApk(root, transcript, variant);
684
+ const located = locate ? await locate() : locateApk(project, transcript, variant);
685
+ if ("code" in located) return {
686
+ ok: false,
687
+ ...located,
688
+ diagnostics: [],
689
+ truncated: 0,
690
+ lastLines: tail.slice(),
691
+ durationMs,
692
+ ccache: ccacheActivity
693
+ };
770
694
  if (!located.apkPath && located.candidates?.length) return {
771
695
  ok: false,
772
696
  code: BUILD_ERROR,
773
- reason: `\`./gradlew ${task}\` left ${located.candidates.length} debug APKs under ${apkOutputsDir(root)}, and nothing says which flavor to install.`,
774
- remedy: `Set the android.variant setting to the variant to install -- e.g. {"android": {"variant": "${variantNameOf(relative(apkOutputsDir(root), located.candidates[0]).split(sep).slice(0, -1))}"}} in .stim.json.`,
697
+ reason: `\`${wrapper} ${task}\` left ${located.candidates.length} debug APKs under ${project.outputsDir}, and nothing says which flavor to install.`,
698
+ remedy: `Set the android.variant setting to the variant to install -- e.g. {"android": {"variant": "${variantNameOf(relative(project.outputsDir, located.candidates[0]).split(sep).slice(0, -1))}"}} in .stim.json.`,
775
699
  diagnostics: [],
776
700
  truncated: 0,
777
- lastLines: located.candidates.map((c) => relative(androidDir(root), c)),
701
+ lastLines: located.candidates.map((c) => relative(project.directory, c)),
778
702
  durationMs,
779
703
  ccache: ccacheActivity
780
704
  };
781
705
  if (!located.apkPath) return {
782
706
  ok: false,
783
707
  code: BUILD_ERROR,
784
- reason: variant ? `\`./gradlew ${task}\` succeeded but produced no APK under ${apkOutputsDir(root)} for variant "${variant}".` : `\`./gradlew ${task}\` succeeded but produced no APK in ${debugApkDir(root)}.`,
785
- remedy: variant ? `Check that the android.variant setting ("${variant}") names a real variant (\`./gradlew :app:tasks\` lists the assemble tasks).` : `Check that ${task} builds the app module (\`./gradlew :app:${task}\` in android/) and that no flavour redirects the output.`,
708
+ reason: variant ? `\`${wrapper} ${task}\` succeeded but produced no APK under ${project.outputsDir} for variant "${variant}".` : `\`${wrapper} ${task}\` succeeded but produced no APK in ${join(project.outputsDir, "debug")}.`,
709
+ remedy: variant ? `Check that the android.variant setting ("${variant}") names a real variant (\`${wrapper} ${tasksTask}\` lists the assemble tasks).` : `Check that ${task} builds the ${project.module.replace(/^:/, "") || "root"} module (\`${wrapper} ${moduleTask}\` in ${relative(root, project.directory).split(sep).join("/") || "."}/) and that no flavour redirects the output.`,
786
710
  diagnostics: [],
787
711
  truncated: 0,
788
712
  lastLines: tail.slice(),
@@ -793,6 +717,7 @@ async function buildAndroid({ root, logWriter, variant = null, abi = null }, { s
793
717
  ok: true,
794
718
  apkPath: located.apkPath,
795
719
  apkNote: located.note ?? null,
720
+ ...located.androidPackage ? { androidPackage: located.androidPackage } : {},
796
721
  durationMs,
797
722
  lastLines: tail.slice(),
798
723
  ccache: ccacheActivity
@@ -804,7 +729,7 @@ function resetStatsLog(statsLog) {
804
729
  rmSync(statsLog, { force: true });
805
730
  } catch {}
806
731
  }
807
- function spawnFailure(err, project, durationMs) {
732
+ function spawnFailure(err, root, project, durationMs) {
808
733
  const nodeErr = err;
809
734
  const message = String(nodeErr?.message || err || "");
810
735
  const permissionDenied = nodeErr?.code === "EACCES" || /EACCES|permission denied/i.test(message);
@@ -812,7 +737,7 @@ function spawnFailure(err, project, durationMs) {
812
737
  ok: false,
813
738
  code: BUILD_ERROR,
814
739
  reason: `Could not run ${project.gradlew}: ${message}`,
815
- remedy: permissionDenied ? `Make the wrapper executable: \`chmod +x ${project.gradlew}\`.` : "Check that the gradle wrapper is intact (android/gradlew and android/gradle/wrapper/) and that JAVA_HOME points at a JDK 17 install.",
740
+ remedy: permissionDenied ? `Make the wrapper executable: \`chmod +x ${project.gradlew}\`.` : `Check that the gradle wrapper is intact (${relative(root, project.gradlew)} and ${relative(root, join(project.directory, "gradle", "wrapper"))}/) and that JAVA_HOME points at a JDK 17 install.`,
816
741
  diagnostics: [],
817
742
  truncated: 0,
818
743
  lastLines: [],
@@ -838,4 +763,4 @@ function readOrNull(file) {
838
763
  }
839
764
  }
840
765
  //#endregion
841
- export { gradlewPath as a, formatDiagnostic as c, androidPathRoomRemedy as d, buildAndroid as i, androidPathRoom as l, apkOutputsDir as n, productFlavorRefusal as o, assembleTaskFor as r, readProductFlavors as s, androidSdkRefusal as t, androidPathRoomMessage as u };
766
+ export { buildGradle as a, formatDiagnostic as c, assembleTaskFor as i, BUILD_ERROR as n, parseProductFlavors as o, androidSdkRefusal as r, variantNameOf as s, ASSEMBLE_TASK as t };