stim 1.14.0 → 1.15.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 (130) hide show
  1. package/README.md +2 -0
  2. package/dist/{activity-CYVDcrt3.mjs → activity-B2-kb7k0.mjs} +281 -41
  3. package/dist/{android-XpvCrV7q.mjs → android-CYmq0jNi.mjs} +2 -2
  4. package/dist/{android-LbPFRWVL.mjs → android-Cu_L4RpL.mjs} +502 -407
  5. package/dist/{android-d6rGq1pA.mjs → android-Db2eEMaf.mjs} +152 -65
  6. package/dist/android-cas-PnKfAdB2.mjs +167 -0
  7. package/dist/android-cas-compiler.mjs +2 -2
  8. package/dist/{app-install-BpgSgkJj.mjs → app-install-CAAplXAt.mjs} +95 -161
  9. package/dist/{budget-CGDkhvv_.mjs → budget-CMiqghig.mjs} +1038 -73
  10. package/dist/{build-plan-Dcr-3ie0.mjs → build-plan-aeGMFX7e.mjs} +193 -653
  11. package/dist/build-progress-C2Jv1AtA.mjs +872 -0
  12. package/dist/build-slots-Df1ApSuH.mjs +127 -0
  13. package/dist/{cache-manifest-C68QQ0ua.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
  14. package/dist/cache-manifest.mjs +1 -1
  15. package/dist/{chrome-BPCiC3ZX.mjs → chrome-BrcVWQyD.mjs} +1 -1
  16. package/dist/cli-0cX5s4NM.mjs +45 -0
  17. package/dist/cli.mjs +6 -42
  18. package/dist/client-C2IS36Qf.mjs +1333 -0
  19. package/dist/collector-run.mjs +8 -7
  20. package/dist/{command-output-DVcpw6eE.mjs → command-output-CliHHn7a.mjs} +1 -1
  21. package/dist/{config-lvc7d3C2.mjs → config-D0DbpZtM.mjs} +28 -29
  22. package/dist/{created-devices-CllH_8eb.mjs → created-devices-BwVb3liH.mjs} +2 -2
  23. package/dist/{dependency-state-DsT7aKeo.mjs → dependency-state-BmsjKZ2H.mjs} +2 -2
  24. package/dist/{deps-D9IcKqXS.mjs → deps-BFlKbOIp.mjs} +3 -3
  25. package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
  26. package/dist/dev-client-CjzLoNs0.mjs +80 -0
  27. package/dist/{device-CjuuAJjQ.mjs → device-BZ1IyS5A.mjs} +7 -7
  28. package/dist/device-capacity-DMuKC7nx.mjs +136 -0
  29. package/dist/device-host-worker.d.mts +1 -0
  30. package/dist/device-host-worker.mjs +769 -0
  31. package/dist/device-ios-DMQBUPus.mjs +381 -0
  32. package/dist/{device-lease-5c3WrVRm.mjs → device-lease-W5Pi1q38.mjs} +43 -36
  33. package/dist/{device-pool-BiyDyPP-.mjs → device-pool-B2r38YjS.mjs} +4 -4
  34. package/dist/{device-remote-D87zEzaq.mjs → device-remote-9ulPsdhY.mjs} +68 -162
  35. package/dist/{doctor-x9pnU9fq.mjs → doctor-BcE5xsBn.mjs} +191 -99
  36. package/dist/{error-diagnostics-C5HzcwCW.mjs → error-diagnostics-Cb0P1WLS.mjs} +12 -11
  37. package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
  38. package/dist/{gc-ko6mUAYD.mjs → gc-BuL1Genr.mjs} +429 -101
  39. package/dist/{android-cas-iZK3DOCr.mjs → gradle-CmdOBq1d.mjs} +8 -294
  40. package/dist/{guide-6R0VNFqI.mjs → guide-cCSGRFd3.mjs} +1959 -222
  41. package/dist/{guide-status-BZrFPIA_.mjs → guide-status-CIoWK6mG.mjs} +3 -3
  42. package/dist/hosted-macos-DwowNU7W.mjs +447 -0
  43. package/dist/idle-shutdown-B5LPaNyY.mjs +122 -0
  44. package/dist/in-use-CndPMilN.mjs +110 -0
  45. package/dist/{ios-BwDPrnYQ.mjs → ios-3CtCRhwr.mjs} +201 -10
  46. package/dist/{ios-P1f5nm2n.mjs → ios-Chob8ny7.mjs} +512 -263
  47. package/dist/{ios-device-DGglU3E_.mjs → ios-device-DERmMmk-.mjs} +12 -7
  48. package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
  49. package/dist/{launch-verify-Deg4tB3Z.mjs → launch-verify-CLlofxRt.mjs} +4 -4
  50. package/dist/{logs-Civ4gbBH.mjs → logs-h9h6MUvE.mjs} +95 -13
  51. package/dist/machine-usage-D_YYMzfR.mjs +283 -0
  52. package/dist/machines-CYtOCqcj.mjs +259 -0
  53. package/dist/macos-BwtbUtTN.mjs +468 -0
  54. package/dist/macos-run.d.mts +5 -0
  55. package/dist/macos-run.mjs +2 -0
  56. package/dist/{merge-state-ytFQCeh4.mjs → merge-state-BnxLNQiM.mjs} +22 -12
  57. package/dist/{metro-CcEo8Fl8.mjs → metro-Di8EN2Tb.mjs} +20 -120
  58. package/dist/{named-ports-Blg8IxOh.mjs → named-ports-Dj_XBNaL.mjs} +6 -59
  59. package/dist/native-run-DFDoIRbY.mjs +147 -0
  60. package/dist/{native-runtime-DjBHRg5m.mjs → native-runtime-i6OkVg-w.mjs} +9 -5
  61. package/dist/offload-worker.d.mts +121 -0
  62. package/dist/offload-worker.mjs +601 -0
  63. package/dist/{ownership-DyYDF5ww.mjs → ownership-BkYxUtuj.mjs} +3 -2
  64. package/dist/{page-BHUzTDFt.mjs → page-QF_Ke10s.mjs} +7 -2
  65. package/dist/{ports-BguS83ex.mjs → ports-DddwttKM.mjs} +3 -3
  66. package/dist/prebuild-BvxDlD6C.mjs +213 -0
  67. package/dist/process-identity-BmRm1qV0.mjs +12 -0
  68. package/dist/{project-CWlvEaeN.mjs → project-CV3tDFHl.mjs} +9 -18
  69. package/dist/pull-request-pxnDCQzn.mjs +322 -0
  70. package/dist/pull-requests.d.mts +120 -0
  71. package/dist/pull-requests.mjs +2 -0
  72. package/dist/recordings-GEXp4iBT.mjs +37 -0
  73. package/dist/{reload-BiniwsSZ.mjs → reload-ChPiwvot.mjs} +70 -22
  74. package/dist/{remote-cache-CcR6o6lI.mjs → remote-cache-CO2elm_b.mjs} +4 -4
  75. package/dist/run-B-xqRrsg.mjs +119 -0
  76. package/dist/{server-bare-DGfgyJ5J.mjs → server-bare-X7PUgizL.mjs} +33 -15
  77. package/dist/{server-expo-BVuwQ65v.mjs → server-expo-DhtX6bom.mjs} +6 -10
  78. package/dist/server-expo-KJeD109I.mjs +2 -0
  79. package/dist/{settings-D61iNOsB.mjs → settings-CduVcoxj.mjs} +77 -26
  80. package/dist/{settings-B-fsC-Om.mjs → settings-DbL6uhH8.mjs} +16 -10
  81. package/dist/settings.schema.json +357 -2
  82. package/dist/{simslim-DrDN4WuV.mjs → simslim-Ciluxlq4.mjs} +8 -132
  83. package/dist/{slot-launch-D5t8EiMf.mjs → slot-launch-BY0BrOLh.mjs} +6 -6
  84. package/dist/{spawn-claims-Drw_o-Fb.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
  85. package/dist/spawn-entry-DncpJvWL.mjs +16 -0
  86. package/dist/stage-CzaiwFsI.mjs +143 -0
  87. package/dist/start-CPO4wRg7.mjs +2 -0
  88. package/dist/{start-s4RXp1wy.mjs → start-CUD9nasA.mjs} +108 -61
  89. package/dist/state-B4PQFXMW.d.mts +12 -0
  90. package/dist/state-BxCgeTQu.mjs +41 -0
  91. package/dist/{state-DHqvsbqC.mjs → state-CaeaHbDA.mjs} +7 -4
  92. package/dist/{state-Dk9RVXI7.mjs → state-DFm77wRn.mjs} +67 -5
  93. package/dist/stats-DBLLFmKd.mjs +66 -0
  94. package/dist/{status-BsPAnfOI.mjs → status-DYXxNOT0.mjs} +423 -268
  95. package/dist/{status-BgAuxESg.mjs → status-l84Gbvp2.mjs} +116 -20
  96. package/dist/stdout-reader-C8yjre1x.mjs +23 -0
  97. package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
  98. package/dist/stim-footprint.swift +32 -0
  99. package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
  100. package/dist/{stop-BzreOWJp.mjs → stop-Bad61z_2.mjs} +38 -12
  101. package/dist/stop-Bvf1MflS.mjs +48 -0
  102. package/dist/{stop-BWIF_6BK.mjs → stop-CceYh1yG.mjs} +2 -2
  103. package/dist/stop-cause-CZ_Mr-v9.mjs +665 -0
  104. package/dist/supervisor-run.d.mts +43 -11
  105. package/dist/supervisor-run.mjs +227 -19
  106. package/dist/support-CDQbDkL5.mjs +315 -0
  107. package/dist/support-WLOzVKUv.mjs +176 -0
  108. package/dist/teardown-BYuQafiA.mjs +718 -0
  109. package/dist/{xcode-Cp5KvK9x.mjs → toolchain-DmeYjXD9.mjs} +363 -13
  110. package/dist/warm-progress-DVHLN4uC.mjs +463 -0
  111. package/dist/{idle-DXtx3RbX.mjs → watchman-Bx0wceoF.mjs} +55 -8
  112. package/dist/{web-BsQs1WlO.mjs → web-k6w8-HnE.mjs} +37 -20
  113. package/dist/web-run.mjs +309 -12
  114. package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
  115. package/dist/workspace-state-CL2V2Ons.mjs +371 -0
  116. package/dist/worktree-BT_uULFx.mjs +2 -0
  117. package/dist/{worktree-BVrHsYZG.mjs → worktree-C0c5Udwa.mjs} +55 -54
  118. package/dist/{worktree-UrQWXSeb.mjs → worktree-qXKzADSC.mjs} +154 -252
  119. package/package.json +10 -5
  120. package/shim/bundle-response.cjs +28 -12
  121. package/dist/build-progress-DxKpwnaS.mjs +0 -247
  122. package/dist/in-use-DlqBDKqY.mjs +0 -249
  123. package/dist/server-expo-DIHDhvGg.mjs +0 -2
  124. package/dist/start-Cetfvy8l.mjs +0 -2
  125. package/dist/stats-CFpFGlJV.mjs +0 -62
  126. package/dist/stats-CX1Z8Tca.mjs +0 -368
  127. package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
  128. package/dist/stop-cause-hjGBOZTG.mjs +0 -1231
  129. package/dist/worktree-CHWWvm5v.mjs +0 -2
  130. package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
@@ -0,0 +1,167 @@
1
+ import { d as getConfigDir } from "./config-D0DbpZtM.mjs";
2
+ import { r as register } from "./cache-manifest-DnUHBJaU.mjs";
3
+ import { E as withDirLock, p as ensureWorkspaceStorage } from "./workspace-state-CL2V2Ons.mjs";
4
+ import { createHash, randomUUID } from "node:crypto";
5
+ import { accessSync, constants, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, symlinkSync, writeFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { isJsonObject, readJsonFile } from "@stim-cli/core/state";
8
+ import { fileURLToPath } from "node:url";
9
+ //#region src/engine/android-cas.ts
10
+ const CAS_TOOLCHAIN_FIELDS = [
11
+ "clang",
12
+ "clangxx",
13
+ "lld",
14
+ "ar",
15
+ "ranlib",
16
+ "ndk",
17
+ "resourceDir"
18
+ ];
19
+ const CAS_TOOLCHAIN_BINARIES = [
20
+ "clang",
21
+ "clangxx",
22
+ "lld",
23
+ "ar",
24
+ "ranlib"
25
+ ];
26
+ function executableFile(path) {
27
+ try {
28
+ accessSync(path, constants.X_OK);
29
+ return statSync(path).isFile();
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
34
+ function directory(path) {
35
+ try {
36
+ return statSync(path).isDirectory();
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ function isAndroidCasToolchain(value) {
42
+ return CAS_TOOLCHAIN_FIELDS.every((field) => typeof value[field] === "string");
43
+ }
44
+ function readAndroidCasToolchain(manifest) {
45
+ const parsed = readJsonFile(manifest);
46
+ const toolchain = isJsonObject(parsed) ? parsed : {};
47
+ if (!isAndroidCasToolchain(toolchain)) {
48
+ const missing = CAS_TOOLCHAIN_FIELDS.filter((field) => typeof toolchain[field] !== "string");
49
+ throw new Error(`${manifest} declares no ${missing.join(", ")}.`);
50
+ }
51
+ const notExecutable = CAS_TOOLCHAIN_BINARIES.filter((field) => !executableFile(toolchain[field]));
52
+ if (notExecutable.length > 0) throw new Error(`${manifest} names no executable ${notExecutable.join(", ")}.`);
53
+ if (!directory(toolchain.resourceDir)) throw new Error(`${manifest} names resourceDir ${toolchain.resourceDir}, which is not a directory.`);
54
+ const ndkProperties = readFileSync(join(toolchain.ndk, "source.properties"), "utf8");
55
+ const ndkVersion = /Pkg.Revision\s*=\s*([^\r\n]+)/.exec(ndkProperties)?.[1]?.trim();
56
+ if (!ndkVersion) throw new Error(`Missing NDK version in ${toolchain.ndk}/source.properties.`);
57
+ return {
58
+ toolchain,
59
+ ndkVersion,
60
+ ndkProperties
61
+ };
62
+ }
63
+ function resolveAndroidCompilerCache({ optimizations, use, env = process.env }) {
64
+ if (optimizations.android.compilerCache !== "cas") return {
65
+ cas: null,
66
+ optimizations
67
+ };
68
+ const manifest = optimizations.android.casToolchain;
69
+ try {
70
+ return {
71
+ cas: use(manifest),
72
+ optimizations
73
+ };
74
+ } catch (error) {
75
+ const fromEnvironment = Boolean(env.STIM_ANDROID_CAS_TOOLCHAIN);
76
+ return {
77
+ cas: null,
78
+ optimizations: {
79
+ ...optimizations,
80
+ android: {
81
+ ...optimizations.android,
82
+ compilerCache: "ccache",
83
+ compilerCacheFallback: {
84
+ key: fromEnvironment ? "STIM_ANDROID_CAS_TOOLCHAIN" : "optimizations.android.casToolchain",
85
+ reason: `could not be used: ${error.message.replace(/\.$/, "")}`,
86
+ fromEnvironment,
87
+ manifest
88
+ }
89
+ }
90
+ }
91
+ };
92
+ }
93
+ }
94
+ function resolveAndroidCas(root, env = process.env) {
95
+ const manifest = env.STIM_ANDROID_CAS_TOOLCHAIN;
96
+ if (!manifest) return null;
97
+ const { toolchain, ndkVersion, ndkProperties } = readAndroidCasToolchain(manifest);
98
+ const scripts = [
99
+ "shim/android-cas.gradle",
100
+ "shim/android-cas.toolchain.cmake",
101
+ "shim/android-cas-pch.cmake",
102
+ "dist/android-cas-compiler.mjs"
103
+ ].map((name) => {
104
+ const path = [`../${name}`, `../../${name}`].map((candidate) => fileURLToPath(new URL(candidate, import.meta.url))).find((candidate) => existsSync(candidate));
105
+ if (!path) throw new Error(`Stim installation is missing ${name}.`);
106
+ return path;
107
+ });
108
+ const hash = createHash("sha256").update(JSON.stringify(toolchain));
109
+ for (const path of [
110
+ ...scripts,
111
+ toolchain.clang,
112
+ toolchain.clangxx,
113
+ toolchain.lld,
114
+ toolchain.ar,
115
+ toolchain.ranlib
116
+ ]) hash.update(readFileSync(path));
117
+ hash.update(ndkProperties);
118
+ const id = `apple-cas-${hash.digest("hex")}`;
119
+ const dir = join(getConfigDir(), "android-cas", id);
120
+ const state = join(ensureWorkspaceStorage(root), "android-cas", id);
121
+ const context = join(state, "context.json");
122
+ mkdirSync(state, { recursive: true });
123
+ mkdirSync(dir, { recursive: true });
124
+ withDirLock(join(state, "setup.lock"), () => {
125
+ for (const name of ["clang", "clang++"]) {
126
+ const path = join(state, name);
127
+ const temporary = `${path}.${randomUUID()}.tmp`;
128
+ symlinkSync(scripts[3], temporary);
129
+ renameSync(temporary, path);
130
+ }
131
+ const temporary = `${context}.${process.pid}.tmp`;
132
+ writeFileSync(temporary, JSON.stringify({
133
+ ...toolchain,
134
+ source: realpathSync(root),
135
+ state,
136
+ cache: dir
137
+ }));
138
+ renameSync(temporary, context);
139
+ });
140
+ register({
141
+ dir,
142
+ name: "android-cas",
143
+ prune: "atomic",
144
+ note: "Experimental Android compiler CAS"
145
+ });
146
+ return {
147
+ id,
148
+ dir,
149
+ initScript: scripts[0],
150
+ env: {
151
+ STIM_ANDROID_CAS_CONTEXT: context,
152
+ STIM_ANDROID_CAS_SOURCE_ROOT: realpathSync(root),
153
+ STIM_ANDROID_CAS_STATE: state,
154
+ STIM_ANDROID_CAS_NDK: toolchain.ndk,
155
+ STIM_ANDROID_CAS_NDK_VERSION: ndkVersion,
156
+ STIM_ANDROID_CAS_AR: toolchain.ar,
157
+ STIM_ANDROID_CAS_RANLIB: toolchain.ranlib,
158
+ STIM_ANDROID_CAS_CMAKE_TOOLCHAIN: scripts[1],
159
+ STIM_ANDROID_CAS_CMAKE_PCH: scripts[2],
160
+ CMAKE_C_COMPILER_LAUNCHER: "",
161
+ CMAKE_CXX_COMPILER_LAUNCHER: "",
162
+ CCACHE_DISABLE: "1"
163
+ }
164
+ };
165
+ }
166
+ //#endregion
167
+ export { resolveAndroidCas as n, resolveAndroidCompilerCache as r, readAndroidCasToolchain as t };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
+ import { t as getExecutor } from "./exec-CaErVv7t.mjs";
3
+ import { createHash, randomUUID } from "node:crypto";
3
4
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
5
  import { join } from "node:path";
5
- import { createHash, randomUUID } from "node:crypto";
6
6
  import { once } from "node:events";
7
7
  //#region bin/android-cas-compiler.ts
8
8
  const context = process.env.STIM_ANDROID_CAS_CONTEXT;
@@ -1,138 +1,6 @@
1
- import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
- import { T as uninstallIosApp, c as iosSimulatorFailureAdvice, p as listUserApps } from "./ios-BwDPrnYQ.mjs";
3
- import { closeSync, lstatSync, openSync, readSync, readdirSync } from "node:fs";
4
- import { isAbsolute, join } from "node:path";
5
- import { createHash } from "node:crypto";
6
- //#region src/engine/installed-artifact.ts
7
- const READ_CHUNK_BYTES = 1048576;
8
- const DEVICE_PATH_TIMEOUT_MS = 3e4;
9
- const DEVICE_HASH_TIMEOUT_MS = 12e4;
10
- const SHA256_HEX = /^[0-9a-f]{64}$/;
11
- function parseInstalledApkPath(text) {
12
- if (typeof text !== "string") return null;
13
- const paths = [];
14
- for (const raw of text.split("\n")) {
15
- const line = raw.trim();
16
- if (!line.startsWith("package:")) continue;
17
- const path = line.slice(8);
18
- if (path.startsWith("/")) paths.push(path);
19
- }
20
- return paths.length === 1 ? paths[0] : null;
21
- }
22
- function parseDeviceSha256(text) {
23
- if (typeof text !== "string") return null;
24
- const first = text.trim().split(/\s+/)[0] ?? "";
25
- return SHA256_HEX.test(first) ? first : null;
26
- }
27
- function parseAppContainerPath(text) {
28
- if (typeof text !== "string") return null;
29
- const lines = text.split("\n").map((line) => line.trim()).filter(Boolean);
30
- return lines.length === 1 && isAbsolute(lines[0]) ? lines[0] : null;
31
- }
32
- function artifactsMatch(local, installed) {
33
- return Boolean(local) && local === installed;
34
- }
35
- function hashFile(file) {
36
- let fd = null;
37
- try {
38
- fd = openSync(file, "r");
39
- const digest = createHash("sha256");
40
- const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
41
- for (;;) {
42
- const read = readSync(fd, buffer, 0, READ_CHUNK_BYTES, null);
43
- if (read <= 0) break;
44
- digest.update(buffer.subarray(0, read));
45
- }
46
- return digest.digest("hex");
47
- } catch {
48
- return null;
49
- } finally {
50
- if (fd !== null) try {
51
- closeSync(fd);
52
- } catch {}
53
- }
54
- }
55
- function hashBundle(dir) {
56
- const digest = createHash("sha256");
57
- const walk = (abs, rel) => {
58
- let names;
59
- try {
60
- names = readdirSync(abs);
61
- } catch {
62
- return false;
63
- }
64
- for (const name of names.toSorted()) {
65
- const child = join(abs, name);
66
- const path = rel === "" ? name : `${rel}/${name}`;
67
- let stat;
68
- try {
69
- stat = lstatSync(child);
70
- } catch {
71
- return false;
72
- }
73
- if (stat.isDirectory()) {
74
- if (!walk(child, path)) return false;
75
- continue;
76
- }
77
- if (!stat.isFile()) return false;
78
- const file = hashFile(child);
79
- if (file === null) return false;
80
- digest.update(`${path}\0${file}\n`);
81
- }
82
- return true;
83
- };
84
- return walk(dir, "") ? digest.digest("hex") : null;
85
- }
86
- function deviceHoldsApk({ serial, packageName, apkPath }, { exec = null } = {}) {
87
- const e = exec || getExecutor();
88
- let path;
89
- try {
90
- path = parseInstalledApkPath(e.runFile("adb", [
91
- "-s",
92
- serial,
93
- "shell",
94
- "pm",
95
- "path",
96
- packageName
97
- ], { timeoutMs: DEVICE_PATH_TIMEOUT_MS }));
98
- } catch {
99
- return false;
100
- }
101
- if (!path) return false;
102
- let installed;
103
- try {
104
- installed = parseDeviceSha256(e.runFile("adb", [
105
- "-s",
106
- serial,
107
- "shell",
108
- "sha256sum",
109
- path
110
- ], { timeoutMs: DEVICE_HASH_TIMEOUT_MS }));
111
- } catch {
112
- return false;
113
- }
114
- if (!installed) return false;
115
- return artifactsMatch(hashFile(apkPath), installed);
116
- }
117
- function deviceHoldsBundle({ udid, bundleId, appPath }, { exec = null } = {}) {
118
- const e = exec || getExecutor();
119
- let container;
120
- try {
121
- container = parseAppContainerPath(e.runFile("xcrun", [
122
- "simctl",
123
- "get_app_container",
124
- udid,
125
- bundleId
126
- ], { timeoutMs: DEVICE_PATH_TIMEOUT_MS }));
127
- } catch {
128
- return false;
129
- }
130
- if (!container) return false;
131
- const installed = hashBundle(container);
132
- if (!installed) return false;
133
- return artifactsMatch(hashBundle(appPath), installed);
134
- }
135
- //#endregion
1
+ import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
+ import { D as uninstallIosApp, M as deviceHoldsApk, N as deviceHoldsBundle, l as iosSimulatorFailureAdvice, m as listUserApps } from "./ios-3CtCRhwr.mjs";
3
+ import { t as DEV_MENU_LAUNCH_ARGS } from "./ios-device-Ee7sDXfp.mjs";
136
4
  //#region src/engine/app-install.ts
137
5
  const INSTALL_ERROR = "STIM_INSTALL_FAILED";
138
6
  const LAUNCH_ERROR = "STIM_LAUNCH_FAILED";
@@ -142,12 +10,37 @@ const IOS_SCHEME_APPROVAL_OPENER = "com.apple.CoreSimulator.CoreSimulatorBridge"
142
10
  const IOS_DEV_MENU_OFF_KEYS = ["EXDevMenuShowsAtLaunch", "EXDevMenuShowFloatingActionButton"];
143
11
  const DEV_CLIENT_ONBOARDING_QUERY = "disableOnboarding=1";
144
12
  const DEV_CLIENT_DISABLE_FAB_QUERY = "disableFab=1";
13
+ const DEV_CLIENT_DEV_MENU_OFF_QUERY = "disableFab=1&disableAutoLaunch=1";
14
+ const DEV_CLIENT_RESERVED_DEV_MENU_OFF_QUERY = "__expo_disable_fab=1&__expo_disable_auto_launch=1";
145
15
  const ANDROID_DISABLE_AUTO_LAUNCH_EXTRA = "EXDevMenuDisableAutoLaunch";
16
+ const IOS_DEV_MENU_OFF_DEFAULTS_PLIST = [
17
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
18
+ "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">",
19
+ "<plist version=\"1.0\">",
20
+ "<dict>",
21
+ ...IOS_DEV_MENU_OFF_KEYS.flatMap((key) => [` <key>${key}</key>`, " <false/>"]),
22
+ "</dict>",
23
+ "</plist>",
24
+ ""
25
+ ].join("\n");
26
+ function writeIosDevMenuOffDefaults(udid, bundleId, exec) {
27
+ for (const key of IOS_DEV_MENU_OFF_KEYS) exec.runFile("xcrun", [
28
+ "simctl",
29
+ "spawn",
30
+ udid,
31
+ "defaults",
32
+ "write",
33
+ bundleId,
34
+ key,
35
+ "-bool",
36
+ "false"
37
+ ], { timeoutMs: 6e4 });
38
+ }
146
39
  function describeIosSimulatorFailure(error, exec) {
147
40
  const detail = describe(error);
148
41
  return error?.code === "ETIMEDOUT" ? `${detail}. ${iosSimulatorFailureAdvice(exec)}` : detail;
149
42
  }
150
- function installIosApp({ udid, appPath, bundleId = null, devClientScheme = null, proveInstalled = true }, { exec = null, now = null } = {}) {
43
+ function installIosApp({ udid, appPath, bundleId = null, devClientScheme = null, schemeApprovals = [], proveInstalled = true }, { exec = null, now = null } = {}) {
151
44
  const e = exec || getExecutor();
152
45
  const artifactStartedAt = now?.();
153
46
  const skipped = bundleId && proveInstalled ? deviceHoldsBundle({
@@ -174,20 +67,13 @@ function installIosApp({ udid, appPath, bundleId = null, devClientScheme = null,
174
67
  }
175
68
  const artifactFinishedAt = now?.();
176
69
  const artifactDurationMs = artifactStartedAt !== void 0 && artifactFinishedAt !== void 0 ? artifactFinishedAt - artifactStartedAt : void 0;
177
- const preparationStartedAt = bundleId && devClientScheme ? artifactFinishedAt : void 0;
178
- if (bundleId && devClientScheme) try {
179
- for (const key of IOS_DEV_MENU_OFF_KEYS) e.runFile("xcrun", [
180
- "simctl",
181
- "spawn",
182
- udid,
183
- "defaults",
184
- "write",
185
- bundleId,
186
- key,
187
- "-bool",
188
- "false"
189
- ], { timeoutMs: 6e4 });
190
- for (const key of iosSchemeApprovalKeys(bundleId, devClientScheme)) e.runFile("xcrun", [
70
+ const devMenuKeys = bundleId && devClientScheme && !skipped ? IOS_DEV_MENU_OFF_KEYS : [];
71
+ const missingApprovals = (bundleId && devClientScheme ? iosSchemeApprovalKeys(bundleId, devClientScheme) : []).filter((key) => !schemeApprovals.includes(`${key}=${bundleId}`));
72
+ const preparing = bundleId && (devMenuKeys.length > 0 || missingApprovals.length > 0);
73
+ const preparationStartedAt = preparing ? artifactFinishedAt : void 0;
74
+ if (bundleId && preparing) try {
75
+ if (devMenuKeys.length > 0) writeIosDevMenuOffDefaults(udid, bundleId, e);
76
+ for (const key of missingApprovals) e.runFile("xcrun", [
191
77
  "simctl",
192
78
  "spawn",
193
79
  udid,
@@ -208,7 +94,8 @@ function installIosApp({ udid, appPath, bundleId = null, devClientScheme = null,
208
94
  const devClientPreparationDurationMs = now && preparationStartedAt !== void 0 ? now() - preparationStartedAt : void 0;
209
95
  const timing = {
210
96
  ...artifactDurationMs === void 0 ? {} : { artifactDurationMs },
211
- ...devClientPreparationDurationMs === void 0 ? {} : { devClientPreparationDurationMs }
97
+ ...devClientPreparationDurationMs === void 0 ? {} : { devClientPreparationDurationMs },
98
+ ...missingApprovals.length > 0 ? { schemeApprovals: [...schemeApprovals, ...missingApprovals.map((key) => `${key}=${bundleId}`)] } : {}
212
99
  };
213
100
  return skipped ? {
214
101
  ok: true,
@@ -230,6 +117,7 @@ function clearOtherUserApps({ udid, keep }, { list = listUserApps, uninstall = u
230
117
  } catch {
231
118
  return {
232
119
  listed: false,
120
+ kept: false,
233
121
  removed,
234
122
  failed
235
123
  };
@@ -245,6 +133,7 @@ function clearOtherUserApps({ udid, keep }, { list = listUserApps, uninstall = u
245
133
  }
246
134
  return {
247
135
  listed: true,
136
+ kept: keep ? installed.includes(keep) : false,
248
137
  removed,
249
138
  failed
250
139
  };
@@ -252,12 +141,13 @@ function clearOtherUserApps({ udid, keep }, { list = listUserApps, uninstall = u
252
141
  function jsLocationValue(metroPort) {
253
142
  return `localhost:${metroPort}`;
254
143
  }
255
- function devClientDeepLink(scheme, projectOrigin) {
256
- const projectUrl = `${projectOrigin.replace(/\/+$/, "")}/?${DEV_CLIENT_ONBOARDING_QUERY}`;
257
- return `${scheme}://expo-development-client/?url=${encodeURIComponent(projectUrl)}&${DEV_CLIENT_DISABLE_FAB_QUERY}`;
144
+ function devClientDeepLink(scheme, projectOrigin, { devMenuParams = false } = {}) {
145
+ const projectQuery = devMenuParams ? `${DEV_CLIENT_ONBOARDING_QUERY}&${DEV_CLIENT_DEV_MENU_OFF_QUERY}&${DEV_CLIENT_RESERVED_DEV_MENU_OFF_QUERY}` : DEV_CLIENT_ONBOARDING_QUERY;
146
+ const projectUrl = `${projectOrigin.replace(/\/+$/, "")}/?${projectQuery}`;
147
+ return `${scheme}://expo-development-client/?url=${encodeURIComponent(projectUrl)}&${devMenuParams ? DEV_CLIENT_DEV_MENU_OFF_QUERY : DEV_CLIENT_DISABLE_FAB_QUERY}`;
258
148
  }
259
- function devClientUrl(scheme, metroPort, host = "localhost") {
260
- return devClientDeepLink(scheme, `http://${host}:${metroPort}`);
149
+ function devClientUrl(scheme, metroPort, host = "localhost", options = {}) {
150
+ return devClientDeepLink(scheme, `http://${host}:${metroPort}`, options);
261
151
  }
262
152
  function iosSchemeApprovalKeys(bundleId, devClientScheme) {
263
153
  return [.../* @__PURE__ */ new Set([bundleId, devClientScheme])].map((target) => `${IOS_SCHEME_APPROVAL_OPENER}-->${target}`);
@@ -299,7 +189,7 @@ function launchedIosAppAfterNoHandle(error, udid, bundleId, exec) {
299
189
  if (!stderr.includes("domain=NSPOSIXErrorDomain, code=3") || !stderr.includes(`Application launch for '${bundleId}' did not return a process handle nor launch error.`)) return null;
300
190
  return iosAppProcess(udid, bundleId, { exec }) ?? null;
301
191
  }
302
- function launchIosApp({ udid, bundleId, metroPort, devClientScheme = null, consolePaths }, { exec = null } = {}) {
192
+ function launchIosApp({ udid, bundleId, metroPort, devClientScheme = null, devMenuParams = false, consolePaths }, { exec = null } = {}) {
303
193
  const e = exec || getExecutor();
304
194
  const launchArgs = [
305
195
  "simctl",
@@ -348,16 +238,27 @@ function launchIosApp({ udid, bundleId, metroPort, devClientScheme = null, conso
348
238
  };
349
239
  }
350
240
  if (devClientScheme) {
351
- const url = devClientUrl(devClientScheme, metroPort);
241
+ const url = devClientUrl(devClientScheme, metroPort, "localhost", { devMenuParams });
242
+ const viaInitialUrl = Boolean(consolePaths) && runningPid === null;
243
+ if (!viaInitialUrl) try {
244
+ writeIosDevMenuOffDefaults(udid, bundleId, e);
245
+ } catch (err) {
246
+ return {
247
+ failed: true,
248
+ code: LAUNCH_ERROR,
249
+ reason: `Could not turn off ${bundleId}'s dev menu before opening it (defaults write): ${describeIosSimulatorFailure(err, e)}`
250
+ };
251
+ }
352
252
  let launchedWithInitialUrl = false;
353
253
  try {
354
- if (consolePaths && runningPid === null) {
254
+ if (viaInitialUrl) {
355
255
  const initialUrl = new URL(url).searchParams.get("url");
356
256
  launchedWithInitialUrl = true;
357
257
  const pid = parseLaunchedPid(e.runFile("xcrun", [
358
258
  ...launchArgs,
359
259
  "--initialUrl",
360
- initialUrl
260
+ initialUrl,
261
+ ...DEV_MENU_LAUNCH_ARGS
361
262
  ], { timeoutMs: 6e4 }));
362
263
  return {
363
264
  ok: true,
@@ -560,6 +461,39 @@ function reverseMetroPorts({ serial, metroPort, devicePorts = null }, { exec = n
560
461
  reversed: pairs.map(([device, host]) => `tcp:${device}->tcp:${host}`)
561
462
  };
562
463
  }
464
+ function hasMetroReverse(listing, metroPort) {
465
+ return String(listing ?? "").split("\n").some((line) => {
466
+ const cols = line.trim().split(/\s+/);
467
+ return cols[1] === `tcp:${metroPort}` && cols[2] === `tcp:${metroPort}`;
468
+ });
469
+ }
470
+ /** Re-applies the launch's `metroPort` reverse when the device no longer has it. */
471
+ function ensureMetroReverse({ serial, metroPort }, { exec = null } = {}) {
472
+ const e = exec || getExecutor();
473
+ let listing;
474
+ try {
475
+ listing = e.runFile("adb", [
476
+ "-s",
477
+ serial,
478
+ "reverse",
479
+ "--list"
480
+ ], ADB_SHELL_OPTIONS);
481
+ } catch {
482
+ return {
483
+ failed: true,
484
+ reason: `adb reverse --list failed on ${serial}`
485
+ };
486
+ }
487
+ if (hasMetroReverse(listing, metroPort)) return { restored: false };
488
+ const reversed = reverseMetroPorts({
489
+ serial,
490
+ metroPort
491
+ }, { exec: e });
492
+ return reversed.failed ? {
493
+ failed: true,
494
+ reason: reversed.reason ?? "adb reverse failed"
495
+ } : { restored: true };
496
+ }
563
497
  const EMULATOR_HOST_LOOPBACK = "127.0.0.1";
564
498
  const PHYSICAL_HOST_LOOPBACK = "localhost";
565
499
  function androidMetroHost(physical) {
@@ -871,4 +805,4 @@ function androidAppProcess(serial, packageName, { exec = null } = {}) {
871
805
  }
872
806
  }
873
807
  //#endregion
874
- export { launchAndroidReleaseApp as _, LAUNCH_ERROR as a, clearOtherUserApps as c, deviceShellArg as d, installAndroidApp as f, launchAndroidApp as g, iosAppProcess as h, INSTALL_ERROR as i, devClientDeepLink as l, installIosApp as m, ANDROID_DISABLE_AUTO_LAUNCH_EXTRA as n, androidAppProcess as o, installConflictKind as p, DEFAULT_METRO_PORT as r, androidDevClientUrl as s, ADB_INSTALL_TIMEOUT_MS as t, devClientUrl as u, launchIosApp as v, restartedAppNote as y };
808
+ export { restartedAppNote as S, installIosApp as _, IOS_DEV_MENU_OFF_DEFAULTS_PLIST as a, launchAndroidReleaseApp as b, androidDevClientUrl as c, devClientUrl as d, deviceShellArg as f, installConflictKind as g, installAndroidApp as h, INSTALL_ERROR as i, clearOtherUserApps as l, hasMetroReverse as m, ANDROID_DISABLE_AUTO_LAUNCH_EXTRA as n, LAUNCH_ERROR as o, ensureMetroReverse as p, DEFAULT_METRO_PORT as r, androidAppProcess as s, ADB_INSTALL_TIMEOUT_MS as t, devClientDeepLink as u, iosAppProcess as v, launchIosApp as x, launchAndroidApp as y };