stim 1.14.0 → 1.16.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.
- package/README.md +2 -0
- package/dist/activity-BxwdD81S.mjs +609 -0
- package/dist/agent-device-usage-output-Dpih1Tfa.mjs +411 -0
- package/dist/{android-d6rGq1pA.mjs → android-B_NumVyQ.mjs} +169 -81
- package/dist/{android-LbPFRWVL.mjs → android-Ift4kVvt.mjs} +517 -413
- package/dist/android-cas-8U4DPqeR.mjs +167 -0
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{android-XpvCrV7q.mjs → android-r2rBL8kV.mjs} +2 -2
- package/dist/{app-install-BpgSgkJj.mjs → app-install-CKWdbXIX.mjs} +128 -151
- package/dist/attempt-Bk2ouQVL.mjs +39 -0
- package/dist/budget-DjrURfQn.mjs +2700 -0
- package/dist/{build-plan-Dcr-3ie0.mjs → build-plan-DjeSb2Xl.mjs} +192 -653
- package/dist/build-slots-rUk77xqh.mjs +132 -0
- package/dist/{cache-manifest-C68QQ0ua.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-BPCiC3ZX.mjs → chrome-BrcVWQyD.mjs} +1 -1
- package/dist/cli-BkYZ_6hy.mjs +51 -0
- package/dist/cli.mjs +6 -42
- package/dist/client-BTY686R6.mjs +1368 -0
- package/dist/collector-run.mjs +9 -195
- package/dist/{command-output-DVcpw6eE.mjs → command-output-DnJMdEY-.mjs} +1 -1
- package/dist/{config-lvc7d3C2.mjs → config-D0DbpZtM.mjs} +28 -29
- package/dist/{created-devices-CllH_8eb.mjs → created-devices-D5owjN4C.mjs} +2 -2
- package/dist/{dependency-state-DsT7aKeo.mjs → dependency-state-B6cMXZab.mjs} +2 -2
- package/dist/{deps-D9IcKqXS.mjs → deps-urbmfXig.mjs} +3 -3
- package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
- package/dist/dev-client-CroAIjjj.mjs +43 -0
- package/dist/{device-CjuuAJjQ.mjs → device-DZQjF7H5.mjs} +8 -7
- package/dist/device-capacity-BHwxNBlu.mjs +136 -0
- package/dist/device-host-worker.d.mts +1 -0
- package/dist/device-host-worker.mjs +964 -0
- package/dist/device-ios-BadmeL2V.mjs +381 -0
- package/dist/{device-lease-5c3WrVRm.mjs → device-lease-D-hLqx1b.mjs} +43 -36
- package/dist/{device-pool-BiyDyPP-.mjs → device-lease-run-CqjShqWW.mjs} +6 -126
- package/dist/device-pool-CUaEWMMm.mjs +125 -0
- package/dist/{device-remote-D87zEzaq.mjs → device-remote-D5WVWqOq.mjs} +69 -163
- package/dist/{doctor-x9pnU9fq.mjs → doctor-Cimf-gGB.mjs} +241 -103
- package/dist/{error-diagnostics-C5HzcwCW.mjs → error-diagnostics-B9L4Ae0x.mjs} +15 -18
- package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
- package/dist/{gc-ko6mUAYD.mjs → gc-Bqy4bjEu.mjs} +599 -108
- package/dist/{android-cas-iZK3DOCr.mjs → gradle-BsO1MdsH.mjs} +8 -294
- package/dist/{guide-6R0VNFqI.mjs → guide-B_uyKTxW.mjs} +2511 -239
- package/dist/{guide-status-BZrFPIA_.mjs → guide-status-CjEZMAD4.mjs} +3 -3
- package/dist/hosted-client-a-WmqE2L.mjs +197 -0
- package/dist/hosted-ios-CIWelIqf.mjs +220 -0
- package/dist/hosted-logs-D5g041Q3.mjs +187 -0
- package/dist/hosted-macos-BSZyIb3y.mjs +135 -0
- package/dist/idle-DYVymG92.mjs +1099 -0
- package/dist/idle-shutdown-CTsDnAde.mjs +122 -0
- package/dist/in-use-DvBw0Kxo.mjs +130 -0
- package/dist/{ios-BwDPrnYQ.mjs → ios-BaInn3sW.mjs} +201 -10
- package/dist/ios-Cr1h5gnO.mjs +189 -0
- package/dist/{ios-P1f5nm2n.mjs → ios-aq3QoGI3.mjs} +1159 -633
- package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
- package/dist/{ios-device-DGglU3E_.mjs → ios-device-FfCN_C8p.mjs} +12 -7
- package/dist/ios-state-DS5UpYTH.mjs +48 -0
- package/dist/{launch-verify-Deg4tB3Z.mjs → launch-verify-2DBRizjo.mjs} +5 -5
- package/dist/logs-CHEVK8zD.mjs +371 -0
- package/dist/machines-BIBUdhpj.mjs +265 -0
- package/dist/macos-CSYEAFmF.mjs +473 -0
- package/dist/macos-run.d.mts +5 -0
- package/dist/macos-run.mjs +2 -0
- package/dist/maintenance-run.d.mts +4 -0
- package/dist/maintenance-run.mjs +254 -0
- package/dist/{metro-CcEo8Fl8.mjs → metro-BeK1ZPz1.mjs} +20 -120
- package/dist/metro-gateway-BJ-rxQAB.mjs +84 -0
- package/dist/{named-ports-Blg8IxOh.mjs → named-ports-Bk_YXEmE.mjs} +6 -59
- package/dist/native-run-NaBrRFtQ.mjs +147 -0
- package/dist/{native-runtime-DjBHRg5m.mjs → native-runtime-DBzRnEKS.mjs} +9 -5
- package/dist/{ndjson-CDY9IkVC.mjs → ndjson-PclOIwVY.mjs} +2 -2
- package/dist/offload-worker.d.mts +122 -0
- package/dist/offload-worker.mjs +606 -0
- package/dist/{ownership-DyYDF5ww.mjs → ownership-DiA16AsN.mjs} +3 -2
- package/dist/ownership-hCkPzGmr.mjs +571 -0
- package/dist/{page-BHUzTDFt.mjs → page-QF_Ke10s.mjs} +7 -2
- package/dist/{ports-BguS83ex.mjs → ports-R2k4Knz3.mjs} +3 -3
- package/dist/prebuild-D2fsca_Z.mjs +213 -0
- package/dist/preview-DhVbvPAZ.mjs +318 -0
- package/dist/process-identity-BmRm1qV0.mjs +12 -0
- package/dist/{project-CWlvEaeN.mjs → project-Du91Ilvc.mjs} +74 -19
- package/dist/pull-request-pxnDCQzn.mjs +322 -0
- package/dist/pull-requests.d.mts +120 -0
- package/dist/pull-requests.mjs +2 -0
- package/dist/recordings-BIXOzVnr.mjs +37 -0
- package/dist/{reload-BiniwsSZ.mjs → reload-rM9jV1fz.mjs} +109 -24
- package/dist/{remote-cache-CcR6o6lI.mjs → remote-cache-C8-V13XN.mjs} +5 -5
- package/dist/run-f4vI6EnK.mjs +119 -0
- package/dist/{server-bare-DGfgyJ5J.mjs → server-bare-CpPGmnmO.mjs} +33 -15
- package/dist/server-expo-CVqO2c35.mjs +2 -0
- package/dist/{server-expo-BVuwQ65v.mjs → server-expo-MC0rHlOC.mjs} +8 -12
- package/dist/settings-BBpMcDbD.mjs +25 -0
- package/dist/{settings-B-fsC-Om.mjs → settings-ZkDzkzvB.mjs} +22 -10
- package/dist/settings-oTSkkNrM.mjs +1439 -0
- package/dist/settings.schema.json +845 -97
- package/dist/{simslim-DrDN4WuV.mjs → simslim-B8-7AoTI.mjs} +8 -132
- package/dist/{slot-launch-D5t8EiMf.mjs → slot-launch-B8VrHxn1.mjs} +11 -8
- package/dist/{spawn-claims-Drw_o-Fb.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
- package/dist/spawn-entry-jw19m8Nl.mjs +17 -0
- package/dist/stage-CzaiwFsI.mjs +143 -0
- package/dist/start-CX8Ig-U2.mjs +2 -0
- package/dist/{start-s4RXp1wy.mjs → start-ClDfwXa4.mjs} +116 -65
- package/dist/state-3DwSQIBK.mjs +41 -0
- package/dist/state-B4PQFXMW.d.mts +12 -0
- package/dist/{state-Dk9RVXI7.mjs → state-C1jB7Q8q.mjs} +70 -8
- package/dist/{state-DHqvsbqC.mjs → state-DcW6vOd_.mjs} +7 -4
- package/dist/stats-CEZ_i5je.mjs +77 -0
- package/dist/{status-BgAuxESg.mjs → status-BuvBFeII.mjs} +118 -20
- package/dist/{status-BsPAnfOI.mjs → status-Cs7VLg9D.mjs} +542 -283
- package/dist/status-DlKvVJBE.mjs +49 -0
- package/dist/stdout-reader-C8yjre1x.mjs +23 -0
- package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
- package/dist/stim-footprint.swift +32 -0
- package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
- package/dist/stop-B0Yxtmiy.mjs +48 -0
- package/dist/{stop-BzreOWJp.mjs → stop-Bffozsac.mjs} +83 -16
- package/dist/{stop-BWIF_6BK.mjs → stop-Dt_dM16A.mjs} +2 -2
- package/dist/stop-cause-CidxIqup.mjs +97 -0
- package/dist/supervisor-run.d.mts +43 -11
- package/dist/supervisor-run.mjs +363 -24
- package/dist/support-CAP8qDUF.mjs +316 -0
- package/dist/support-D4aYJniO.mjs +201 -0
- package/dist/teardown-CL6vDs2Y.mjs +727 -0
- package/dist/{xcode-Cp5KvK9x.mjs → toolchain-DkUflduf.mjs} +364 -14
- package/dist/trigger-Bemu8ytw.mjs +65 -0
- package/dist/trigger-CXts6qt1.mjs +2 -0
- package/dist/warm-progress-CpGv3Wb6.mjs +732 -0
- package/dist/{web-BsQs1WlO.mjs → web-DWUaMp8P.mjs} +37 -21
- package/dist/web-run.mjs +310 -13
- package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
- package/dist/workspace-state-B8-aJ1_5.mjs +371 -0
- package/dist/workspaces-BV4pdHFz.mjs +306 -0
- package/dist/{worktree-UrQWXSeb.mjs → worktree-K-xj9Db0.mjs} +625 -256
- package/dist/worktree-jnG8Iph5.mjs +2 -0
- package/package.json +10 -5
- package/shim/bundle-response.cjs +28 -12
- package/dist/activity-CYVDcrt3.mjs +0 -356
- package/dist/budget-CGDkhvv_.mjs +0 -1745
- package/dist/build-progress-DxKpwnaS.mjs +0 -247
- package/dist/idle-DXtx3RbX.mjs +0 -191
- package/dist/in-use-DlqBDKqY.mjs +0 -249
- package/dist/logs-Civ4gbBH.mjs +0 -486
- package/dist/merge-state-ytFQCeh4.mjs +0 -262
- package/dist/server-expo-DIHDhvGg.mjs +0 -2
- package/dist/settings-D61iNOsB.mjs +0 -629
- package/dist/start-Cetfvy8l.mjs +0 -2
- package/dist/stats-CFpFGlJV.mjs +0 -62
- package/dist/stats-CX1Z8Tca.mjs +0 -368
- package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
- package/dist/stop-cause-hjGBOZTG.mjs +0 -1231
- package/dist/worktree-BVrHsYZG.mjs +0 -752
- package/dist/worktree-CHWWvm5v.mjs +0 -2
- package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
3
|
+
import { r as detectIsExpo } from "./project-Du91Ilvc.mjs";
|
|
4
|
+
import { a as updateWorkspaceState, r as readWorkspaceState } from "./workspace-state-B8-aJ1_5.mjs";
|
|
5
|
+
import { a as spawnDeclared } from "./spawn-claims-D0XfSe8u.mjs";
|
|
6
|
+
import { i as expoBinRefusal, r as expoBinPath } from "./server-expo-MC0rHlOC.mjs";
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
//#region src/engine/prebuild.ts
|
|
10
|
+
const PREBUILD_ERROR = "STIM_PREBUILD_FAILED";
|
|
11
|
+
const LAST_LINES = 20;
|
|
12
|
+
function nativeDirName(platform) {
|
|
13
|
+
return platform === "android" ? "android" : "ios";
|
|
14
|
+
}
|
|
15
|
+
function nativeDir(root, platform) {
|
|
16
|
+
return join(root, nativeDirName(platform));
|
|
17
|
+
}
|
|
18
|
+
function nativeDirInFingerprint(sources, platform) {
|
|
19
|
+
const dir = nativeDirName(platform);
|
|
20
|
+
return sources.some((source) => source.type === "dir" && source.filePath === dir && source.hash != null);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* @expo/fingerprint leaves a native directory out of the hash when git ignores it (CNG), so the cache
|
|
24
|
+
* key only covers that directory when this workspace's recorded prebuild ran on the same fingerprint.
|
|
25
|
+
*/
|
|
26
|
+
function prebuildAction({ isExpo, nativeDirExists, nativeDirFingerprinted, nativeDirTracked, generatedFrom, fingerprint }) {
|
|
27
|
+
if (!isExpo) return "none";
|
|
28
|
+
if (!nativeDirExists) return "generate";
|
|
29
|
+
if (nativeDirFingerprinted || generatedFrom === fingerprint) return "none";
|
|
30
|
+
return nativeDirTracked ? "refuse" : "regenerate";
|
|
31
|
+
}
|
|
32
|
+
function prebuildRecord(state) {
|
|
33
|
+
const record = state?.prebuild;
|
|
34
|
+
return record && typeof record === "object" ? record : {};
|
|
35
|
+
}
|
|
36
|
+
function gitTracksNativeDir(root, platform) {
|
|
37
|
+
try {
|
|
38
|
+
return getExecutor().runFile("git", [
|
|
39
|
+
"-C",
|
|
40
|
+
root,
|
|
41
|
+
"ls-files",
|
|
42
|
+
"--",
|
|
43
|
+
nativeDirName(platform)
|
|
44
|
+
], { env: {
|
|
45
|
+
LC_ALL: "C",
|
|
46
|
+
LANGUAGE: "C"
|
|
47
|
+
} }).trim() !== "";
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (error?.code === "ENOENT") return false;
|
|
50
|
+
return !/not a git repository \(or any (of the parent directories|parent up to mount point)/.test(String(error?.message));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function planPrebuild(root, platform, { isExpo, fingerprint, sources }) {
|
|
54
|
+
const nativeDirExists = existsSync(nativeDir(root, platform));
|
|
55
|
+
const fingerprinted = nativeDirInFingerprint(sources, platform);
|
|
56
|
+
const generatedFrom = prebuildRecord(readWorkspaceState(root))[platform];
|
|
57
|
+
return prebuildAction({
|
|
58
|
+
isExpo,
|
|
59
|
+
nativeDirExists,
|
|
60
|
+
nativeDirFingerprinted: fingerprinted,
|
|
61
|
+
nativeDirTracked: nativeDirExists && !fingerprinted && gitTracksNativeDir(root, platform),
|
|
62
|
+
generatedFrom: typeof generatedFrom === "string" ? generatedFrom : null,
|
|
63
|
+
fingerprint
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function recordPrebuild(root, platform, fingerprint) {
|
|
67
|
+
updateWorkspaceState(root, (state) => ({
|
|
68
|
+
...state,
|
|
69
|
+
prebuild: {
|
|
70
|
+
...prebuildRecord(state),
|
|
71
|
+
[platform]: fingerprint
|
|
72
|
+
}
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
function staleNativeDirRefusal(platform) {
|
|
76
|
+
const dir = nativeDirName(platform);
|
|
77
|
+
return {
|
|
78
|
+
code: PREBUILD_ERROR,
|
|
79
|
+
message: `The fingerprint leaves ${dir}/ out of the cache key, and Stim cannot show that ${dir}/ was generated from the current app config. Git tracks files in it, or could not say whether it does, so Stim will not regenerate it with \`expo prebuild --clean\`.`,
|
|
80
|
+
remedy: `Stop excluding ${dir}/ from the fingerprint (check .fingerprintignore) so the cache key covers its files, or add ${dir}/ to .gitignore and untrack it so Stim regenerates it from the app config.`
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function prebuildRefusal({ isExpo, platform, nativeDirExists }) {
|
|
84
|
+
if (nativeDirExists || isExpo) return null;
|
|
85
|
+
const dir = nativeDirName(platform);
|
|
86
|
+
return {
|
|
87
|
+
code: PREBUILD_ERROR,
|
|
88
|
+
message: `This project has no ${dir}/ directory and is not an Expo (CNG) project, so Stim cannot generate one.`,
|
|
89
|
+
remedy: `Check out or generate the native project (\`npx @react-native-community/cli init\` produced one originally), or add \`expo\` to the project so \`expo prebuild\` can create ${dir}/.`
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function prebuildFailure(logWriter, result) {
|
|
93
|
+
logWriter?.write?.({
|
|
94
|
+
src: "build",
|
|
95
|
+
level: "error",
|
|
96
|
+
msg: result.reason || "Expo prebuild failed.",
|
|
97
|
+
event: "prebuild_failed"
|
|
98
|
+
});
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
async function runPrebuild(root, platform, logWriter, { spawnFn = null, now = Date.now, isExpo = null, clean = false } = {}) {
|
|
102
|
+
const dirExists = existsSync(nativeDir(root, platform));
|
|
103
|
+
const refusal = prebuildRefusal({
|
|
104
|
+
isExpo: isExpo === null ? detectIsExpo(root) : isExpo,
|
|
105
|
+
platform,
|
|
106
|
+
nativeDirExists: dirExists
|
|
107
|
+
});
|
|
108
|
+
if (refusal) return prebuildFailure(logWriter, {
|
|
109
|
+
failed: true,
|
|
110
|
+
code: refusal.code,
|
|
111
|
+
reason: refusal.message,
|
|
112
|
+
remedy: refusal.remedy,
|
|
113
|
+
error: refusal,
|
|
114
|
+
lastLines: []
|
|
115
|
+
});
|
|
116
|
+
const bin = expoBinPath(root);
|
|
117
|
+
if (!bin) {
|
|
118
|
+
const binRefusal = expoBinRefusal(root, "prebuild");
|
|
119
|
+
return prebuildFailure(logWriter, {
|
|
120
|
+
failed: true,
|
|
121
|
+
code: PREBUILD_ERROR,
|
|
122
|
+
reason: binRefusal.message,
|
|
123
|
+
remedy: binRefusal.remedy,
|
|
124
|
+
lastLines: []
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const spawn = spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts));
|
|
128
|
+
const startedAt = now();
|
|
129
|
+
const tail = [];
|
|
130
|
+
const push = (line) => {
|
|
131
|
+
const msg = stripAnsi(String(line)).trimEnd();
|
|
132
|
+
if (!msg.trim()) return;
|
|
133
|
+
tail.push(msg);
|
|
134
|
+
if (tail.length > LAST_LINES) tail.shift();
|
|
135
|
+
logWriter?.write?.({
|
|
136
|
+
src: "build",
|
|
137
|
+
level: "debug",
|
|
138
|
+
msg,
|
|
139
|
+
raw: true,
|
|
140
|
+
event: "prebuild"
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
let child;
|
|
144
|
+
try {
|
|
145
|
+
child = spawnDeclared(() => spawn(bin, [
|
|
146
|
+
"prebuild",
|
|
147
|
+
"-p",
|
|
148
|
+
platform,
|
|
149
|
+
"--no-install",
|
|
150
|
+
...clean ? ["--clean"] : []
|
|
151
|
+
], {
|
|
152
|
+
cwd: root,
|
|
153
|
+
stdio: [
|
|
154
|
+
"ignore",
|
|
155
|
+
"pipe",
|
|
156
|
+
"pipe"
|
|
157
|
+
],
|
|
158
|
+
env: {
|
|
159
|
+
...process.env,
|
|
160
|
+
FORCE_COLOR: "0",
|
|
161
|
+
CI: "1"
|
|
162
|
+
}
|
|
163
|
+
}));
|
|
164
|
+
} catch (err) {
|
|
165
|
+
return prebuildFailure(logWriter, {
|
|
166
|
+
failed: true,
|
|
167
|
+
code: PREBUILD_ERROR,
|
|
168
|
+
reason: `Could not run \`expo prebuild\`: ${err?.message || err}`,
|
|
169
|
+
lastLines: []
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const outReader = createLineReader(push);
|
|
173
|
+
const errReader = createLineReader(push);
|
|
174
|
+
child.stdout?.setEncoding?.("utf-8");
|
|
175
|
+
child.stderr?.setEncoding?.("utf-8");
|
|
176
|
+
child.stdout?.on("data", (chunk) => outReader.push(chunk));
|
|
177
|
+
child.stderr?.on("data", (chunk) => errReader.push(chunk));
|
|
178
|
+
const result = await waitForChild(child);
|
|
179
|
+
outReader.flush();
|
|
180
|
+
errReader.flush();
|
|
181
|
+
const durationMs = now() - startedAt;
|
|
182
|
+
if (result.error) return prebuildFailure(logWriter, {
|
|
183
|
+
failed: true,
|
|
184
|
+
code: PREBUILD_ERROR,
|
|
185
|
+
reason: `Could not run \`expo prebuild\`: ${result.error?.message || result.error}`,
|
|
186
|
+
lastLines: tail.slice(),
|
|
187
|
+
durationMs
|
|
188
|
+
});
|
|
189
|
+
if (result.code !== 0) {
|
|
190
|
+
const how = result.signal ? `signal ${result.signal}` : `exit code ${result.code}`;
|
|
191
|
+
return prebuildFailure(logWriter, {
|
|
192
|
+
failed: true,
|
|
193
|
+
code: PREBUILD_ERROR,
|
|
194
|
+
reason: `\`expo prebuild -p ${platform}\` failed (${how}).`,
|
|
195
|
+
lastLines: tail.slice(),
|
|
196
|
+
durationMs
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (!existsSync(nativeDir(root, platform))) return prebuildFailure(logWriter, {
|
|
200
|
+
failed: true,
|
|
201
|
+
code: PREBUILD_ERROR,
|
|
202
|
+
reason: `\`expo prebuild -p ${platform}\` succeeded but did not create ${nativeDirName(platform)}/.`,
|
|
203
|
+
lastLines: tail.slice(),
|
|
204
|
+
durationMs
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
ok: true,
|
|
208
|
+
durationMs,
|
|
209
|
+
nativeDir: nativeDir(root, platform)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//#endregion
|
|
213
|
+
export { staleNativeDirRefusal as i, recordPrebuild as n, runPrebuild as r, planPrebuild as t };
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { P as measuredDirectorySize } from "./config-D0DbpZtM.mjs";
|
|
2
|
+
import { o as findProjectRoot$1 } from "./project-Du91Ilvc.mjs";
|
|
3
|
+
import { X as discoverCaches, j as planCacheEmptying, o as readVolumeSpace, r as enforceBudget, s as resolveBudget } from "./budget-DjrURfQn.mjs";
|
|
4
|
+
import { o as canonicalPath } from "./in-use-DvBw0Kxo.mjs";
|
|
5
|
+
import { h as listBuildLocks } from "./device-lease-D-hLqx1b.mjs";
|
|
6
|
+
import { n as listBuildSlots } from "./build-slots-rUk77xqh.mjs";
|
|
7
|
+
import { j as readHostMemoryPressure } from "./ios-BaInn3sW.mjs";
|
|
8
|
+
import { a as collectWorkspaceOutputs } from "./workspaces-BV4pdHFz.mjs";
|
|
9
|
+
import { t as resolveMaintenanceSettings } from "./settings-BBpMcDbD.mjs";
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { buildCacheRoot, configDir, metroCacheRoot } from "@stim-cli/core";
|
|
13
|
+
import { buildWorkerRoot, loadConfig, readMaintenanceState, sharedCcache, sharedCompilationCache } from "@stim-cli/core/state";
|
|
14
|
+
import { cpus, freemem, loadavg, totalmem } from "node:os";
|
|
15
|
+
//#region src/maintenance/measure.ts
|
|
16
|
+
function measurePressure(settings, previous, now) {
|
|
17
|
+
const config = loadConfig();
|
|
18
|
+
const level = readHostMemoryPressure();
|
|
19
|
+
const availableBytes = process.platform === "darwin" ? null : freemem();
|
|
20
|
+
const warningSince = level === "warning" ? previous?.warningSince ?? now : null;
|
|
21
|
+
const pressured = settings.memoryPressureLevel !== "off" && (level === "critical" || settings.memoryPressureLevel === "warning" && warningSince !== null && now - warningSince >= settings.memoryWarningMinutes * 6e4 || availableBytes !== null && availableBytes < (settings.minAvailableMemoryGb === void 0 ? totalmem() * .1 : settings.minAvailableMemoryGb * 1024 ** 3));
|
|
22
|
+
return {
|
|
23
|
+
disk: readVolumeSpace([
|
|
24
|
+
configDir(),
|
|
25
|
+
...Object.keys(config?.projects ?? {}),
|
|
26
|
+
buildWorkerRoot(config)
|
|
27
|
+
]),
|
|
28
|
+
memory: {
|
|
29
|
+
level,
|
|
30
|
+
availableBytes,
|
|
31
|
+
pressured
|
|
32
|
+
},
|
|
33
|
+
warningSince
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function sizeScanDeferred(settings) {
|
|
37
|
+
return loadavg()[0] / Math.max(1, cpus().length) > settings.maxLoadPerCore;
|
|
38
|
+
}
|
|
39
|
+
function cacheBlocked(entry, discovered = discoverCaches()) {
|
|
40
|
+
return planCacheEmptying([{
|
|
41
|
+
...entry,
|
|
42
|
+
note: "",
|
|
43
|
+
prune: "entries",
|
|
44
|
+
...discovered.some((cache) => canonicalPath(cache.dir) === canonicalPath(entry.dir) && cache.source === "registered") ? { source: "registered" } : {}
|
|
45
|
+
}], false)[0]?.machineGlobal ?? (entry.category === "compilation-cache" && [...listBuildLocks(), ...listBuildSlots()].some((item) => item.alive || item.unresolved) ? "a build lock or slot is live or unresolved" : void 0);
|
|
46
|
+
}
|
|
47
|
+
function measureSizes(now, failure) {
|
|
48
|
+
const sizes = [];
|
|
49
|
+
const outputs = collectWorkspaceOutputs({
|
|
50
|
+
olderThan: null,
|
|
51
|
+
now,
|
|
52
|
+
sizeTimeoutMs: 12e4
|
|
53
|
+
});
|
|
54
|
+
for (const entry of outputs.workspaces) {
|
|
55
|
+
if (entry.bytes === null) {
|
|
56
|
+
failure(entry.dir, entry.projectRoot ?? void 0);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
sizes.push({
|
|
60
|
+
name: "workspace build outputs",
|
|
61
|
+
category: "workspace-outputs",
|
|
62
|
+
dir: entry.dir,
|
|
63
|
+
bytes: entry.bytes,
|
|
64
|
+
measuredAt: now,
|
|
65
|
+
...entry.projectRoot ? { workspace: canonicalPath(entry.projectRoot) } : {},
|
|
66
|
+
idleDays: entry.idleDays,
|
|
67
|
+
...!entry.willClear ? { blocked: entry.keptReason ?? "workspace ownership is unresolved" } : {}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const known = [
|
|
71
|
+
{
|
|
72
|
+
name: "shared build cache",
|
|
73
|
+
dir: buildCacheRoot(),
|
|
74
|
+
category: "build-cache"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "Metro transform caches",
|
|
78
|
+
dir: metroCacheRoot(),
|
|
79
|
+
category: "metro-cache"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "ccache",
|
|
83
|
+
dir: sharedCcache(),
|
|
84
|
+
category: "ccache"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "Swift compilation cache",
|
|
88
|
+
dir: sharedCompilationCache(),
|
|
89
|
+
category: "compilation-cache"
|
|
90
|
+
}
|
|
91
|
+
];
|
|
92
|
+
const discovered = discoverCaches();
|
|
93
|
+
for (const cache of discovered) {
|
|
94
|
+
if (cache.source !== "registered" && !canonicalPath(cache.dir).startsWith(`${canonicalPath(configDir())}/`)) continue;
|
|
95
|
+
if (cache.prune === "report-only") continue;
|
|
96
|
+
const dir = canonicalPath(cache.dir);
|
|
97
|
+
if (known.some((item) => dir === canonicalPath(item.dir) || dir.startsWith(`${canonicalPath(item.dir)}/`))) continue;
|
|
98
|
+
const category = cache.name.startsWith("Metro transform cache") ? "metro-cache" : /^(Expo build cache|native build cache|Build cache)$/.test(cache.name) ? "build-cache" : "other";
|
|
99
|
+
known.push({
|
|
100
|
+
name: cache.name,
|
|
101
|
+
dir: cache.dir,
|
|
102
|
+
category
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
for (const entry of known) {
|
|
106
|
+
if (!existsSync(entry.dir)) continue;
|
|
107
|
+
const bytes = measuredDirectorySize(entry.dir, { timeoutMs: 12e4 });
|
|
108
|
+
if (bytes === null) {
|
|
109
|
+
failure(entry.dir);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const blocked = cacheBlocked(entry, discovered);
|
|
113
|
+
sizes.push({
|
|
114
|
+
...entry,
|
|
115
|
+
bytes,
|
|
116
|
+
measuredAt: now,
|
|
117
|
+
...blocked ? { blocked } : {}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return sizes;
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/maintenance/plan.ts
|
|
124
|
+
function plan({ pressure, sizes, settings, budget, diskSteps = [], protectedRoot, scoped = false, projects = [] }) {
|
|
125
|
+
const actions = [];
|
|
126
|
+
const blocked = [];
|
|
127
|
+
const skips = [];
|
|
128
|
+
const add = (action) => {
|
|
129
|
+
if (!actions.some((entry) => entry.kind === action.kind && entry.target === action.target)) actions.push(action);
|
|
130
|
+
};
|
|
131
|
+
const floor = Math.max(budget.minFreeDiskMb, budget.hardFloorDiskMb);
|
|
132
|
+
const low = pressure?.disk.filter((disk) => disk.freeMb < floor) ?? [];
|
|
133
|
+
const reason = low.map((disk) => `free disk ${(disk.freeMb / 1024).toFixed(1)}G on ${disk.volume} under the ${(floor / 1024).toFixed(1)}G floor`).join("; ");
|
|
134
|
+
const kinds = {
|
|
135
|
+
"idle-devices": "would-shutdown-device",
|
|
136
|
+
"idle-dev-servers": "would-stop-workspace",
|
|
137
|
+
"workspace-outputs": "would-clear-outputs",
|
|
138
|
+
"stale-cache-entries": "would-trim-cache"
|
|
139
|
+
};
|
|
140
|
+
if (low.length) {
|
|
141
|
+
for (const step of diskSteps) {
|
|
142
|
+
if (scoped && step.step === "idle-devices") continue;
|
|
143
|
+
for (const target of step.targets) {
|
|
144
|
+
const workspace = projects.find((root) => root === target || target.endsWith(` in ${root}`)) ?? (step.step === "idle-dev-servers" || step.step === "workspace-outputs" ? target : void 0);
|
|
145
|
+
if (workspace === protectedRoot || target === protectedRoot) continue;
|
|
146
|
+
const size = workspace && step.step !== "idle-devices" ? sizes.find((entry) => entry.workspace === workspace && entry.category === "workspace-outputs") : void 0;
|
|
147
|
+
add({
|
|
148
|
+
kind: kinds[step.step],
|
|
149
|
+
target,
|
|
150
|
+
bytes: step.step === "workspace-outputs" ? size?.bytes ?? 0 : 0,
|
|
151
|
+
reason: `${size?.idleDays == null ? "" : `idle ${size.idleDays} days, `}${reason}`,
|
|
152
|
+
...workspace ? { workspace } : {}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (step.failures) blocked.push(`Could not plan ${step.step}: ${step.failures} failures`);
|
|
156
|
+
}
|
|
157
|
+
if (actions.length === 0) blocked.push(`${reason}; no reclaimable disk targets`);
|
|
158
|
+
}
|
|
159
|
+
const caps = [
|
|
160
|
+
[
|
|
161
|
+
"workspace-outputs",
|
|
162
|
+
settings.workspaceOutputsMaxGb,
|
|
163
|
+
"would-clear-outputs"
|
|
164
|
+
],
|
|
165
|
+
[
|
|
166
|
+
"build-cache",
|
|
167
|
+
settings.buildCacheMaxGb,
|
|
168
|
+
"would-trim-cache"
|
|
169
|
+
],
|
|
170
|
+
[
|
|
171
|
+
"metro-cache",
|
|
172
|
+
settings.metroCacheMaxGb,
|
|
173
|
+
"would-trim-cache"
|
|
174
|
+
],
|
|
175
|
+
[
|
|
176
|
+
"compilation-cache",
|
|
177
|
+
settings.swiftCompilationCacheMaxGb,
|
|
178
|
+
"would-empty-cache"
|
|
179
|
+
]
|
|
180
|
+
];
|
|
181
|
+
for (const [category, capGb, kind] of caps) {
|
|
182
|
+
const entries = sizes.filter((size) => size.category === category);
|
|
183
|
+
const total = entries.reduce((sum, size) => sum + size.bytes, 0);
|
|
184
|
+
const cap = capGb * 1024 ** 3;
|
|
185
|
+
if (cap === 0 || total <= cap) continue;
|
|
186
|
+
let remaining = total;
|
|
187
|
+
const targetBytes = cap * settings.capTargetPercent / 100;
|
|
188
|
+
const why = `${category} ${(total / 1024 ** 3).toFixed(1)}G over the ${capGb}G cap; target ${(targetBytes / 1024 ** 3).toFixed(1)}G`;
|
|
189
|
+
for (const size of entries.toSorted((a, b) => (b.idleDays ?? 0) - (a.idleDays ?? 0))) {
|
|
190
|
+
if (remaining <= targetBytes) break;
|
|
191
|
+
const kept = size.workspace === protectedRoot ? "the triggering workspace is protected" : size.blocked;
|
|
192
|
+
if (kept) {
|
|
193
|
+
skips.push({
|
|
194
|
+
target: size.dir,
|
|
195
|
+
reason: kept,
|
|
196
|
+
...size.workspace ? { workspace: size.workspace } : {}
|
|
197
|
+
});
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const bytes = kind === "would-trim-cache" ? Math.min(size.bytes, remaining - targetBytes) : size.bytes;
|
|
201
|
+
add({
|
|
202
|
+
kind,
|
|
203
|
+
target: size.workspace ?? size.dir,
|
|
204
|
+
bytes,
|
|
205
|
+
reason: `${!size.workspace || size.idleDays == null ? "" : `idle ${size.idleDays} days, `}${why}`,
|
|
206
|
+
...size.workspace ? { workspace: size.workspace } : {}
|
|
207
|
+
});
|
|
208
|
+
remaining -= bytes;
|
|
209
|
+
}
|
|
210
|
+
if (remaining > targetBytes) blocked.push(`${why}; eligible targets cannot reach the target`);
|
|
211
|
+
}
|
|
212
|
+
if (pressure?.memory.pressured) skips.push({
|
|
213
|
+
target: "memory",
|
|
214
|
+
reason: "memory pressure observed; stopping helpers and idle workspaces is not active in report-only mode"
|
|
215
|
+
});
|
|
216
|
+
return {
|
|
217
|
+
actions,
|
|
218
|
+
blocked,
|
|
219
|
+
skips
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/maintenance/preview.ts
|
|
224
|
+
function triggeringRoot() {
|
|
225
|
+
return canonicalPath(findProjectRoot$1(process.cwd()) ?? join(configDir(), "maintenance", "no-project"));
|
|
226
|
+
}
|
|
227
|
+
async function plannedMaintenance(pressure, sizes, settings, { devices = true } = {}) {
|
|
228
|
+
const resolved = resolveBudget();
|
|
229
|
+
if (resolved.error) throw new Error(resolved.error);
|
|
230
|
+
const budget = {
|
|
231
|
+
...resolved.budget,
|
|
232
|
+
maxCommittedMemoryMb: 0,
|
|
233
|
+
maxLiveWorkspaces: 0
|
|
234
|
+
};
|
|
235
|
+
const root = triggeringRoot();
|
|
236
|
+
const floor = Math.max(budget.minFreeDiskMb, budget.hardFloorDiskMb);
|
|
237
|
+
const low = pressure?.disk.some((disk) => disk.freeMb < floor);
|
|
238
|
+
const outcome = low ? await enforceBudget({
|
|
239
|
+
root,
|
|
240
|
+
note: () => {},
|
|
241
|
+
dryRun: true,
|
|
242
|
+
budget
|
|
243
|
+
}, { volumes: () => pressure.disk }) : null;
|
|
244
|
+
if (outcome && outcome.status !== "ok") throw new Error(outcome.refusal.message);
|
|
245
|
+
const outputs = collectWorkspaceOutputs({
|
|
246
|
+
olderThan: null,
|
|
247
|
+
now: Date.now(),
|
|
248
|
+
measure: false
|
|
249
|
+
});
|
|
250
|
+
const result = plan({
|
|
251
|
+
pressure,
|
|
252
|
+
sizes: sizes.map((size) => {
|
|
253
|
+
if (size.category === "compilation-cache") return {
|
|
254
|
+
...size,
|
|
255
|
+
blocked: cacheBlocked(size)
|
|
256
|
+
};
|
|
257
|
+
if (!size.workspace) return size;
|
|
258
|
+
const current = outputs.workspaces.find((entry) => entry.projectRoot && canonicalPath(entry.projectRoot) === size.workspace);
|
|
259
|
+
return Object.assign({}, size, { blocked: current?.willClear ? void 0 : current?.keptReason ?? "workspace outputs cannot be resolved" });
|
|
260
|
+
}),
|
|
261
|
+
settings,
|
|
262
|
+
budget,
|
|
263
|
+
diskSteps: outcome?.status === "ok" ? outcome.reclaimed.filter((step) => devices || step.step !== "idle-devices") : [],
|
|
264
|
+
protectedRoot: root,
|
|
265
|
+
scoped: Boolean(process.env.STIM_HOME),
|
|
266
|
+
projects: Object.keys(loadConfig()?.projects ?? {}).map(canonicalPath)
|
|
267
|
+
});
|
|
268
|
+
if (low) result.skips.push(...outputs.workspaces.filter((entry) => !entry.willClear && entry.keptReason).map((entry) => ({
|
|
269
|
+
target: entry.dir,
|
|
270
|
+
reason: entry.keptReason,
|
|
271
|
+
workspace: entry.projectRoot ?? void 0
|
|
272
|
+
})));
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
async function previewMaintenance({ devices = true } = {}) {
|
|
276
|
+
let settings;
|
|
277
|
+
try {
|
|
278
|
+
settings = resolveMaintenanceSettings();
|
|
279
|
+
const state = readMaintenanceState();
|
|
280
|
+
if (settings.invalid && settings.mode === "off") return {
|
|
281
|
+
mode: "off",
|
|
282
|
+
pressure: null,
|
|
283
|
+
actions: [],
|
|
284
|
+
blocked: [],
|
|
285
|
+
skips: [],
|
|
286
|
+
invalid: settings.invalid,
|
|
287
|
+
note: settings.invalid
|
|
288
|
+
};
|
|
289
|
+
if (settings.mode === "off") return {
|
|
290
|
+
mode: "off",
|
|
291
|
+
pressure: null,
|
|
292
|
+
actions: [],
|
|
293
|
+
blocked: [],
|
|
294
|
+
skips: [],
|
|
295
|
+
note: "maintenance.mode is off"
|
|
296
|
+
};
|
|
297
|
+
const pressure = measurePressure(settings, state?.pressure ?? null, Date.now());
|
|
298
|
+
return {
|
|
299
|
+
...await plannedMaintenance(pressure, state?.sizes ?? [], settings, { devices }),
|
|
300
|
+
mode: settings.mode,
|
|
301
|
+
...settings.invalid ? { invalid: settings.invalid } : {},
|
|
302
|
+
pressure,
|
|
303
|
+
note: settings.invalid ?? (state === null ? "no pass has run yet; sizes have not been measured" : null)
|
|
304
|
+
};
|
|
305
|
+
} catch (error) {
|
|
306
|
+
return {
|
|
307
|
+
mode: settings?.mode ?? "off",
|
|
308
|
+
...settings?.invalid ? { invalid: settings.invalid } : {},
|
|
309
|
+
pressure: null,
|
|
310
|
+
actions: [],
|
|
311
|
+
blocked: [String(error)],
|
|
312
|
+
skips: [],
|
|
313
|
+
note: "maintenance preview failed"
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
export { sizeScanDeferred as a, measureSizes as i, previewMaintenance as n, measurePressure as r, plannedMaintenance as t };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { n as __exportAll, r as __reExport } from "./rolldown-runtime-BsOwBuO_.mjs";
|
|
2
|
+
//#region src/ownership-claim.ts
|
|
3
|
+
var ownership_claim_exports = /* @__PURE__ */ __exportAll({});
|
|
4
|
+
import * as import__stim_cli_core_ownership_claim from "@stim-cli/core/ownership-claim";
|
|
5
|
+
__reExport(ownership_claim_exports, import__stim_cli_core_ownership_claim);
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/process-identity.ts
|
|
8
|
+
var process_identity_exports = /* @__PURE__ */ __exportAll({});
|
|
9
|
+
import * as import__stim_cli_core_process_identity from "@stim-cli/core/process-identity";
|
|
10
|
+
__reExport(process_identity_exports, import__stim_cli_core_process_identity);
|
|
11
|
+
//#endregion
|
|
12
|
+
export { ownership_claim_exports as n, process_identity_exports as t };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { _ as loadConfig, g as isPathPrefix, l as findEnclosingWorktreeRoot, p as getProject } from "./config-
|
|
2
|
-
import {
|
|
3
|
-
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
1
|
+
import { _ as loadConfig$1, g as isPathPrefix, l as findEnclosingWorktreeRoot, p as getProject } from "./config-D0DbpZtM.mjs";
|
|
2
|
+
import { U as webSettings, gt as repoRoot, z as settingValueAt } from "./settings-oTSkkNrM.mjs";
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from "fs";
|
|
4
4
|
import { basename, dirname, join, resolve } from "path";
|
|
5
|
+
import { findProjectRoot, findProjectRoot as findProjectRoot$1 } from "@stim-cli/core/state";
|
|
5
6
|
//#region src/workspace/project.ts
|
|
6
7
|
/**
|
|
7
8
|
* The realpath of `name`'s package.json in the nearest `node_modules` at or above `projectRoot`.
|
|
@@ -37,23 +38,13 @@ const NO_PROJECT_REFUSAL = {
|
|
|
37
38
|
message: "Not in a React Native project (no package.json found).",
|
|
38
39
|
remedy: "Run this from the app directory -- the one holding package.json."
|
|
39
40
|
};
|
|
40
|
-
function findProjectRoot(startDir) {
|
|
41
|
-
let dir;
|
|
42
|
-
try {
|
|
43
|
-
dir = realpathSync(resolve(startDir));
|
|
44
|
-
} catch {
|
|
45
|
-
dir = resolve(startDir);
|
|
46
|
-
}
|
|
47
|
-
while (true) {
|
|
48
|
-
if (existsSync(join(dir, "package.json"))) return dir;
|
|
49
|
-
const parent = dirname(dir);
|
|
50
|
-
if (parent === dir) return null;
|
|
51
|
-
dir = parent;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
41
|
function findServerWorkspace(startDir) {
|
|
55
42
|
const nearest = findProjectRoot(startDir);
|
|
56
43
|
if (!nearest) return null;
|
|
44
|
+
if (existsSync(join(nearest, "Package.swift"))) return {
|
|
45
|
+
root: nearest,
|
|
46
|
+
from: null
|
|
47
|
+
};
|
|
57
48
|
if (appProjectProblem(nearest)?.kind !== "not-an-app") return {
|
|
58
49
|
root: nearest,
|
|
59
50
|
from: null
|
|
@@ -68,7 +59,7 @@ function findServerWorkspace(startDir) {
|
|
|
68
59
|
from: null
|
|
69
60
|
};
|
|
70
61
|
const worktree = expandedRealpath(top);
|
|
71
|
-
const apps = Object.keys(loadConfig()?.projects ?? {}).filter((path) => {
|
|
62
|
+
const apps = Object.keys(loadConfig$1()?.projects ?? {}).filter((path) => {
|
|
72
63
|
if (path === nearest || !isPathPrefix(worktree, expandedRealpath(path)) || appProjectProblem(path) !== null) return false;
|
|
73
64
|
const owner = repoRoot(path);
|
|
74
65
|
return owner !== null && expandedRealpath(owner) === worktree;
|
|
@@ -162,6 +153,70 @@ function detectIsExpo(projectRoot) {
|
|
|
162
153
|
if (podfileUsesExpoModules(projectRoot)) return true;
|
|
163
154
|
return false;
|
|
164
155
|
}
|
|
156
|
+
function detectPlatforms(root, settings) {
|
|
157
|
+
const platforms = /* @__PURE__ */ new Set();
|
|
158
|
+
const product = settingValueAt(settings, "macos.product");
|
|
159
|
+
const infoPlist = settingValueAt(settings, "macos.infoPlist");
|
|
160
|
+
if (existsSync(join(root, "Package.swift")) && product && infoPlist) platforms.add("macos");
|
|
161
|
+
if (webSettings(settings).url !== null) platforms.add("web");
|
|
162
|
+
const pkg = readPackageJson(root);
|
|
163
|
+
const deps = {
|
|
164
|
+
...pkg?.dependencies,
|
|
165
|
+
...pkg?.devDependencies
|
|
166
|
+
};
|
|
167
|
+
if (detectIsExpo(root)) {
|
|
168
|
+
const appJson = readAppJson(root);
|
|
169
|
+
const config = appJson?.expo ?? appJson;
|
|
170
|
+
const text = readAppConfigText(root);
|
|
171
|
+
const explicit = (text ? literalPlatforms(text) : null) ?? config?.platforms;
|
|
172
|
+
if (Array.isArray(explicit)) {
|
|
173
|
+
for (const platform of explicit) if (platform === "ios" || platform === "android" || platform === "web") platforms.add(platform);
|
|
174
|
+
} else {
|
|
175
|
+
platforms.add("ios");
|
|
176
|
+
platforms.add("android");
|
|
177
|
+
if ("react-native-web" in deps || isPackageResolvable(root, "react-native-web")) platforms.add("web");
|
|
178
|
+
}
|
|
179
|
+
} else if (declaresAppDependency(pkg)) {
|
|
180
|
+
let ios = [];
|
|
181
|
+
try {
|
|
182
|
+
ios = readdirSync(join(root, "ios"));
|
|
183
|
+
} catch {}
|
|
184
|
+
if (ios.some((name) => name.endsWith(".xcodeproj") || name.endsWith(".xcworkspace"))) platforms.add("ios");
|
|
185
|
+
if ([
|
|
186
|
+
"build.gradle",
|
|
187
|
+
"build.gradle.kts",
|
|
188
|
+
"settings.gradle",
|
|
189
|
+
"settings.gradle.kts"
|
|
190
|
+
].some((name) => existsSync(join(root, "android", name)))) platforms.add("android");
|
|
191
|
+
}
|
|
192
|
+
return [
|
|
193
|
+
"ios",
|
|
194
|
+
"android",
|
|
195
|
+
"macos",
|
|
196
|
+
"web"
|
|
197
|
+
].filter((platform) => platforms.has(platform));
|
|
198
|
+
}
|
|
199
|
+
function literalPlatforms(text) {
|
|
200
|
+
const tokens = text.match(/\/\*[\s\S]*?\*\/|\/\/[^\n]*|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`|[A-Za-z_$][\w$]*|[^\s]/g)?.filter((token) => !token.startsWith("//") && !token.startsWith("/*")) ?? [];
|
|
201
|
+
let open = 0;
|
|
202
|
+
const index = tokens.findIndex((token, i) => {
|
|
203
|
+
if (token === "[") open++;
|
|
204
|
+
else if (token === "]") open--;
|
|
205
|
+
return open === 0 && (token === "platforms" || token === "\"platforms\"" || token === "'platforms'") && tokens[i + 1] === ":";
|
|
206
|
+
});
|
|
207
|
+
if (index < 0 || tokens[index + 2] !== "[") return null;
|
|
208
|
+
const platforms = [];
|
|
209
|
+
let i = index + 3;
|
|
210
|
+
while (tokens[i] !== "]") {
|
|
211
|
+
const value = tokens[i]?.match(/^(['"])([a-z]+)\1$/)?.[2];
|
|
212
|
+
if (value === void 0) return null;
|
|
213
|
+
platforms.push(value);
|
|
214
|
+
i++;
|
|
215
|
+
if (tokens[i] === ",") i++;
|
|
216
|
+
else if (tokens[i] !== "]") return null;
|
|
217
|
+
}
|
|
218
|
+
return tokens[i + 1] === "," || tokens[i + 1] === "}" ? platforms : null;
|
|
219
|
+
}
|
|
165
220
|
function looksLikeExpoConfig(appJson) {
|
|
166
221
|
if (!appJson || typeof appJson !== "object" || Array.isArray(appJson)) return false;
|
|
167
222
|
if (appJson.expo) return true;
|
|
@@ -213,4 +268,4 @@ function readAppConfigText(projectRoot) {
|
|
|
213
268
|
return null;
|
|
214
269
|
}
|
|
215
270
|
//#endregion
|
|
216
|
-
export {
|
|
271
|
+
export { findCommandWorkspace as a, isPackageResolvable as c, readAppConfigText as d, readAppJson as f, detectPlatforms as i, ownedDeviceLabel as l, appProjectProblem as n, findProjectRoot$1 as o, resolvePackageJson as p, detectIsExpo as r, findServerWorkspace as s, NO_PROJECT_REFUSAL as t, projectShortcut as u };
|