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
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import { B as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
1
|
+
import { B as parseDeviceSlotKey, p as getProject, z as deviceSlotPlatforms } from "./config-D0DbpZtM.mjs";
|
|
2
|
+
import { f as refuseNoProject, l as phaseLine } from "./command-output-DnJMdEY-.mjs";
|
|
3
|
+
import { a as findCommandWorkspace } from "./project-Du91Ilvc.mjs";
|
|
4
|
+
import { l as resolveProjectMetro } from "./metro-BeK1ZPz1.mjs";
|
|
5
|
+
import { i as recordWorkspaceUse, r as readWorkspaceState$1 } from "./workspace-state-B8-aJ1_5.mjs";
|
|
6
|
+
import { o as readWebRecord, r as cdpEndpoint, u as webFacts } from "./state-C1jB7Q8q.mjs";
|
|
7
|
+
import { f as readWorkspaceLaunches } from "./state-DcW6vOd_.mjs";
|
|
8
|
+
import { J as resolveOwnedAvdSerial } from "./android-B_NumVyQ.mjs";
|
|
9
|
+
import { w as resolveOwnedIosSim } from "./ios-BaInn3sW.mjs";
|
|
10
|
+
import { l as probeHostedSession } from "./hosted-client-a-WmqE2L.mjs";
|
|
11
|
+
import { p as ensureMetroReverse, s as androidAppProcess, v as iosAppProcess } from "./app-install-CKWdbXIX.mjs";
|
|
12
|
+
import { n as nativeRunCommand } from "./slot-launch-B8VrHxn1.mjs";
|
|
13
|
+
import { t as readHostedIos } from "./ios-state-DS5UpYTH.mjs";
|
|
14
|
+
import { n as sendToOwnedPage, t as liveWebRecord } from "./page-QF_Ke10s.mjs";
|
|
15
|
+
import { hostedIosRecords } from "@stim-cli/core/state";
|
|
12
16
|
import chalk from "chalk";
|
|
13
17
|
import { WebSocket } from "ws";
|
|
14
18
|
//#region src/engine/reload.ts
|
|
@@ -31,7 +35,11 @@ function peerMatches(query, role, appId) {
|
|
|
31
35
|
if (role === "ios") return query.get("role")?.toLowerCase() === "ios";
|
|
32
36
|
return query.get("app") === appId;
|
|
33
37
|
}
|
|
34
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Asks Metro for its peers and reloads the ones matching `role` and `appId`. With `peersOnly`, it sends nothing and
|
|
40
|
+
* only reports the outcome a reload would have, so a caller can wait for the app to connect.
|
|
41
|
+
*/
|
|
42
|
+
function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, peersOnly = false }) {
|
|
35
43
|
const roleName = ROLE_NAMES[role];
|
|
36
44
|
return new Promise((resolve) => {
|
|
37
45
|
const requestId = `stim-reload-${process.pid}-${Date.now()}`;
|
|
@@ -72,6 +80,15 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
|
|
|
72
80
|
const query = peerQuery(metadata);
|
|
73
81
|
return query ? peerMatches(query, role, appId) : false;
|
|
74
82
|
});
|
|
83
|
+
if (rolePeers.length === 0 && peersOnly) {
|
|
84
|
+
finish({
|
|
85
|
+
failed: true,
|
|
86
|
+
noPeer: true,
|
|
87
|
+
peers,
|
|
88
|
+
reason: `No ${roleName} React Native app is connected to Metro on port ${port}.`
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
75
92
|
if (rolePeers.length === 0) {
|
|
76
93
|
socket.send(JSON.stringify({
|
|
77
94
|
version: 2,
|
|
@@ -86,7 +103,7 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
|
|
|
86
103
|
});
|
|
87
104
|
return;
|
|
88
105
|
}
|
|
89
|
-
for (const [id] of rolePeers) socket.send(JSON.stringify({
|
|
106
|
+
if (!peersOnly) for (const [id] of rolePeers) socket.send(JSON.stringify({
|
|
90
107
|
version: 2,
|
|
91
108
|
method: "reload",
|
|
92
109
|
target: id
|
|
@@ -98,7 +115,7 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
|
|
|
98
115
|
});
|
|
99
116
|
return;
|
|
100
117
|
}
|
|
101
|
-
socket.send(JSON.stringify({
|
|
118
|
+
if (!peersOnly) socket.send(JSON.stringify({
|
|
102
119
|
version: 2,
|
|
103
120
|
method: "reload"
|
|
104
121
|
}));
|
|
@@ -130,8 +147,16 @@ const DEFAULT_DEPS = {
|
|
|
130
147
|
const facts = webFacts(readWebRecord(root));
|
|
131
148
|
return facts?.status === "unverified" ? "unverified" : liveWebRecord(facts?.record ?? null);
|
|
132
149
|
},
|
|
133
|
-
reloadPage: (record) => sendToOwnedPage(record, "Page.reload")
|
|
150
|
+
reloadPage: (record) => sendToOwnedPage(record, "Page.reload"),
|
|
151
|
+
ensureReverse: (serial, metroPort) => ensureMetroReverse({
|
|
152
|
+
serial,
|
|
153
|
+
metroPort
|
|
154
|
+
}),
|
|
155
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
134
156
|
};
|
|
157
|
+
const RECONNECT_POLL_MS = 500;
|
|
158
|
+
const RECONNECT_POLLS = 16;
|
|
159
|
+
const RECONNECT_UNOBSERVED_MS = 2500;
|
|
135
160
|
function failure(code, message, remedy) {
|
|
136
161
|
return {
|
|
137
162
|
code,
|
|
@@ -143,8 +168,9 @@ function describe(error) {
|
|
|
143
168
|
return error instanceof Error ? error.message : String(error);
|
|
144
169
|
}
|
|
145
170
|
async function reloadBrowser(browser, metroPort, d) {
|
|
171
|
+
let pageUrl;
|
|
146
172
|
try {
|
|
147
|
-
await d.reloadPage(browser);
|
|
173
|
+
pageUrl = await d.reloadPage(browser);
|
|
148
174
|
} catch (error) {
|
|
149
175
|
return {
|
|
150
176
|
ok: false,
|
|
@@ -157,10 +183,11 @@ async function reloadBrowser(browser, metroPort, d) {
|
|
|
157
183
|
platform: "web",
|
|
158
184
|
deviceId: cdpEndpoint(browser.cdpPort),
|
|
159
185
|
deviceName: browser.version ?? "Chrome",
|
|
160
|
-
appId:
|
|
186
|
+
appId: pageUrl,
|
|
161
187
|
metroPort: metroPort !== null && new URL(browser.url).port === String(metroPort) ? metroPort : null,
|
|
162
188
|
strategy: "cdp",
|
|
163
|
-
targets: 1
|
|
189
|
+
targets: 1,
|
|
190
|
+
reverseRestored: []
|
|
164
191
|
}
|
|
165
192
|
};
|
|
166
193
|
}
|
|
@@ -259,15 +286,45 @@ async function runReload({ root, platform = null, deps = {} }) {
|
|
|
259
286
|
ok: false,
|
|
260
287
|
error: failure("STIM_RELOAD_STOPPED", "No owned Chrome is running for this workspace.", "Run `stim web` first.")
|
|
261
288
|
};
|
|
289
|
+
const hosted = platform === "android" ? {} : readHostedIos(root);
|
|
290
|
+
const hostedFailures = {};
|
|
291
|
+
if (platform !== "android") for (const slot of Object.keys(hostedIosRecords(readWorkspaceState$1(root)))) {
|
|
292
|
+
if (hosted[slot]) continue;
|
|
293
|
+
try {
|
|
294
|
+
readHostedIos(root, slot);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
hostedFailures[slot] = {
|
|
297
|
+
platform: "ios",
|
|
298
|
+
error: failure("STIM_HOSTING_REFUSED", describe(error), error instanceof Error && "remedy" in error && typeof error.remedy === "string" ? error.remedy : null)
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const hostedProbes = Object.fromEntries(await Promise.all(Object.entries(hosted).map(async ([slot, placement]) => [slot, await probeHostedSession(placement)])));
|
|
262
303
|
const launches = d.readLaunches(root);
|
|
263
304
|
const inspected = Object.entries(launches).flatMap(([key, record]) => {
|
|
264
305
|
const parsed = parseDeviceSlotKey(key);
|
|
265
306
|
if (!parsed || platform && parsed.platform !== platform) return [];
|
|
307
|
+
if (parsed.platform === "ios" && hostedFailures[parsed.slot]) return [];
|
|
308
|
+
const placement = parsed.platform === "ios" ? hosted[parsed.slot] : void 0;
|
|
309
|
+
if (placement && record.deviceId === placement.session) {
|
|
310
|
+
const probe = hostedProbes[parsed.slot];
|
|
311
|
+
return [probe.state === "ready" ? {
|
|
312
|
+
platform: "ios",
|
|
313
|
+
slot: parsed.slot,
|
|
314
|
+
record,
|
|
315
|
+
hosted: true,
|
|
316
|
+
deviceName: `${placement.device?.name ?? "iOS simulator"} on ${placement.machine}`
|
|
317
|
+
} : {
|
|
318
|
+
platform: "ios",
|
|
319
|
+
error: failure("STIM_RELOAD_PROBE_FAILED", `The iOS session on ${placement.machine} is ${probe.state}.`, `Run stim ios --remote ${placement.machine} or stim stop to reconcile it.`)
|
|
320
|
+
}];
|
|
321
|
+
}
|
|
266
322
|
return [inspectTarget(parsed.platform, record, {
|
|
267
323
|
...project,
|
|
268
324
|
platforms: deviceSlotPlatforms(project, parsed.slot)
|
|
269
325
|
}, d, parsed.slot)];
|
|
270
326
|
});
|
|
327
|
+
inspected.push(...Object.values(hostedFailures));
|
|
271
328
|
const live = inspected.filter((target) => !isTargetFailure(target));
|
|
272
329
|
const livePlatforms = new Set(live.map((target) => target.platform));
|
|
273
330
|
if (browser) livePlatforms.add("web");
|
|
@@ -307,21 +364,47 @@ async function runReload({ root, platform = null, deps = {} }) {
|
|
|
307
364
|
ok: false,
|
|
308
365
|
error: failure("STIM_NO_METRO", `Port ${port} is not serving this workspace's Metro.`, "Run `stim start`, then retry.")
|
|
309
366
|
};
|
|
310
|
-
const stopped = processFailure(target.platform, target.record, d, target.slot);
|
|
367
|
+
const stopped = target.hosted ? null : processFailure(target.platform, target.record, d, target.slot);
|
|
311
368
|
if (stopped) return {
|
|
312
369
|
ok: false,
|
|
313
370
|
error: stopped
|
|
314
371
|
};
|
|
315
|
-
const
|
|
372
|
+
const reverseRestored = [];
|
|
373
|
+
const reverseChecked = target.platform === "android" ? live.filter((c) => c.platform === "android" && !c.record.release && c.record.metroPort === port) : [];
|
|
374
|
+
for (const candidate of reverseChecked) {
|
|
375
|
+
const serial = candidate.record.deviceId;
|
|
376
|
+
const ensured = d.ensureReverse(serial, port);
|
|
377
|
+
if (ensured.failed) return {
|
|
378
|
+
ok: false,
|
|
379
|
+
error: failure("STIM_RELOAD_FAILED", `Stim could not check or restore the adb reverse for Metro port ${port} on ${serial}: ${ensured.reason}`, `Run \`adb -s ${serial} reverse tcp:${port} tcp:${port}\`, then \`stim reload android\` again.`)
|
|
380
|
+
};
|
|
381
|
+
if (ensured.restored) reverseRestored.push(serial);
|
|
382
|
+
}
|
|
383
|
+
const request = {
|
|
316
384
|
role: target.platform,
|
|
317
385
|
appId: target.record.appId
|
|
318
|
-
}
|
|
386
|
+
};
|
|
387
|
+
const expectedPeers = reverseChecked.filter((c) => c.record.appId === target.record.appId).length;
|
|
388
|
+
for (let poll = 0; reverseRestored.length && poll < RECONNECT_POLLS; poll++) {
|
|
389
|
+
const peers = await d.reloadMetro(port, {
|
|
390
|
+
...request,
|
|
391
|
+
peersOnly: true
|
|
392
|
+
});
|
|
393
|
+
if (peers.broadcast) await d.sleep(RECONNECT_UNOBSERVED_MS);
|
|
394
|
+
if (peers.unreachable || peers.broadcast || peers.ok && peers.targets >= expectedPeers) break;
|
|
395
|
+
await d.sleep(RECONNECT_POLL_MS);
|
|
396
|
+
}
|
|
397
|
+
const reloaded = await d.reloadMetro(port, request);
|
|
319
398
|
if (!reloaded.ok) {
|
|
320
|
-
const stoppedAfterMetro = processFailure(target.platform, target.record, d, target.slot);
|
|
399
|
+
const stoppedAfterMetro = target.hosted ? null : processFailure(target.platform, target.record, d, target.slot);
|
|
321
400
|
if (stoppedAfterMetro) return {
|
|
322
401
|
ok: false,
|
|
323
402
|
error: stoppedAfterMetro
|
|
324
403
|
};
|
|
404
|
+
if (target.hosted) return {
|
|
405
|
+
ok: false,
|
|
406
|
+
error: failure("STIM_RELOAD_FAILED", reloaded.reason, `Metro could not confirm a peer for the hosted iOS app. Check the app on its hosting Mac and run stim reload ios again.`)
|
|
407
|
+
};
|
|
325
408
|
const snapshot = `agent-device snapshot -i --platform ${target.platform} --${target.platform === "ios" ? "udid" : "serial"} ${target.record.deviceId}`;
|
|
326
409
|
const relaunch = `agent-device open ${target.record.appId} --platform ${target.platform} --${target.platform === "ios" ? "udid" : "serial"} ${target.record.deviceId} --metro-port ${port} --relaunch`;
|
|
327
410
|
const firstBundle = target.platform === "ios" ? " If it stays unreachable, an error in the first bundle leaves iOS without a packager connection at all, and no retry will make it a peer." : "";
|
|
@@ -342,7 +425,8 @@ async function runReload({ root, platform = null, deps = {} }) {
|
|
|
342
425
|
appId: target.record.appId,
|
|
343
426
|
metroPort: port,
|
|
344
427
|
strategy,
|
|
345
|
-
targets: reloaded.targets ?? null
|
|
428
|
+
targets: reloaded.targets ?? null,
|
|
429
|
+
reverseRestored
|
|
346
430
|
}
|
|
347
431
|
};
|
|
348
432
|
}
|
|
@@ -386,7 +470,8 @@ function registerReload(program, deps = {}) {
|
|
|
386
470
|
return;
|
|
387
471
|
}
|
|
388
472
|
const scope = facts.strategy === "metro-broadcast" ? ` This Metro cannot name its connected apps, so the reload request was broadcast to all of them and Stim cannot confirm ${facts.appId} was one. Check the expected UI on ${facts.deviceId}; if nothing changed, reload from the app's own error screen or dev menu.` : facts.targets && facts.targets > 1 ? ` ${facts.targets} devices are running this app on that Metro and the reload request addressed all of them, not only ${facts.deviceId}.` : "";
|
|
389
|
-
|
|
473
|
+
const restored = facts.reverseRestored.length ? ` The adb reverse for tcp:${facts.metroPort} was missing on ${facts.reverseRestored.join(", ")}, so Stim restored it first.` : "";
|
|
474
|
+
console.log(`Reload requested for ${facts.appId} on ${facts.deviceName} (${facts.deviceId}) via ${facts.strategy}; ${facts.platform} Metro port ${facts.metroPort}.${restored}${scope} Completion is not observed; verify the expected UI and run stim logs --errors.`);
|
|
390
475
|
}
|
|
391
476
|
});
|
|
392
477
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import { M as workspaceLogsDir } from "./metro-CcEo8Fl8.mjs";
|
|
4
|
-
import { f as resolvePackageJson } from "./project-CWlvEaeN.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
5
2
|
import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
|
|
6
|
-
import {
|
|
3
|
+
import { p as resolvePackageJson } from "./project-Du91Ilvc.mjs";
|
|
4
|
+
import { x as workspaceLogsDir } from "./workspace-state-B8-aJ1_5.mjs";
|
|
5
|
+
import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
|
|
6
|
+
import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-MC0rHlOC.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
3
|
+
import { i as macosRuntimeClaim, n as macosLogFile, o as updateMacosRecord, r as macosProcess } from "./state-3DwSQIBK.mjs";
|
|
4
|
+
import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
|
|
5
|
+
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
6
|
+
import { readMacosRecord } from "@stim-cli/core/state";
|
|
7
|
+
import { StringDecoder } from "node:string_decoder";
|
|
8
|
+
//#region src/macos/run.ts
|
|
9
|
+
function logLines(stream, write) {
|
|
10
|
+
const decoder = new StringDecoder("utf8");
|
|
11
|
+
let pending = "";
|
|
12
|
+
stream.on("data", (chunk) => {
|
|
13
|
+
pending += decoder.write(chunk);
|
|
14
|
+
while (pending.length > 65536 && !pending.includes("\n")) {
|
|
15
|
+
write(pending.slice(0, 65536));
|
|
16
|
+
pending = pending.slice(65536);
|
|
17
|
+
}
|
|
18
|
+
const lines = pending.split("\n");
|
|
19
|
+
pending = lines.pop() ?? "";
|
|
20
|
+
for (const line of lines) write(line.replace(/\r$/, ""));
|
|
21
|
+
});
|
|
22
|
+
stream.on("end", () => {
|
|
23
|
+
pending += decoder.end();
|
|
24
|
+
if (pending) write(pending);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async function runMacosSupervisor(root, launchId) {
|
|
28
|
+
const record = readMacosRecord(root);
|
|
29
|
+
if (!record || record.launchId !== launchId || record.build.state !== "ok") throw new Error("The macOS launch record changed before its supervisor started.");
|
|
30
|
+
const owner = macosProcess(process.pid);
|
|
31
|
+
const attempt = (0, ownership_claim_exports.tryAcquireClaim)({
|
|
32
|
+
root: macosRuntimeClaim(root),
|
|
33
|
+
mode: "exclusive",
|
|
34
|
+
label: "macOS app"
|
|
35
|
+
});
|
|
36
|
+
if (attempt.pending) (0, ownership_claim_exports.releaseClaim)(attempt.pending);
|
|
37
|
+
const claim = attempt.acquired;
|
|
38
|
+
if (!claim) throw new Error(`The macOS runtime is already held at ${attempt.held?.path ?? macosRuntimeClaim(root)}.`);
|
|
39
|
+
const writer = createNdjsonWriter(macosLogFile(root), { maxBytes: LOG_ROTATE_BYTES });
|
|
40
|
+
let app;
|
|
41
|
+
let stopping = false;
|
|
42
|
+
let spawned = false;
|
|
43
|
+
let childExited = false;
|
|
44
|
+
try {
|
|
45
|
+
if (!(0, process_identity_exports.sameProcessRecord)(readMacosRecord(root)?.supervisor, record.supervisor) || !updateMacosRecord(root, record.supervisor, { supervisor: owner })) throw new Error("The macOS launch owner changed.");
|
|
46
|
+
(0, ownership_claim_exports.markClaimChildPending)(claim);
|
|
47
|
+
const child = getExecutor().spawn(record.executable, record.arguments, {
|
|
48
|
+
cwd: root,
|
|
49
|
+
stdio: [
|
|
50
|
+
"ignore",
|
|
51
|
+
"pipe",
|
|
52
|
+
"pipe"
|
|
53
|
+
],
|
|
54
|
+
env: {
|
|
55
|
+
...process.env,
|
|
56
|
+
NSUnbufferedIO: "YES"
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
spawned = child.pid !== void 0;
|
|
60
|
+
const ended = new Promise((resolve, reject) => {
|
|
61
|
+
child.once("error", reject);
|
|
62
|
+
child.once("close", () => {
|
|
63
|
+
childExited = true;
|
|
64
|
+
resolve();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
if (!child.pid) {
|
|
68
|
+
await ended;
|
|
69
|
+
throw new Error("The macOS app did not start.");
|
|
70
|
+
}
|
|
71
|
+
app = macosProcess(child.pid);
|
|
72
|
+
(0, ownership_claim_exports.setClaimChild)(claim, app);
|
|
73
|
+
if (!updateMacosRecord(root, owner, { app })) {
|
|
74
|
+
if ((0, process_identity_exports.inspectProcessIdentity)(app) === "same") process.kill(app.pid, "SIGTERM");
|
|
75
|
+
throw new Error("The macOS launch owner changed.");
|
|
76
|
+
}
|
|
77
|
+
const log = (level, msg) => writer.write({
|
|
78
|
+
src: "client",
|
|
79
|
+
platform: "macos",
|
|
80
|
+
level,
|
|
81
|
+
msg
|
|
82
|
+
});
|
|
83
|
+
if (child.stdout) logLines(child.stdout, (line) => log("info", line));
|
|
84
|
+
if (child.stderr) logLines(child.stderr, (line) => log("warn", line));
|
|
85
|
+
const stop = async () => {
|
|
86
|
+
if (stopping) return;
|
|
87
|
+
stopping = true;
|
|
88
|
+
for (const signal of ["SIGTERM", "SIGKILL"]) {
|
|
89
|
+
if (!app || (0, process_identity_exports.inspectProcessIdentity)(app) !== "same") return;
|
|
90
|
+
process.kill(app.pid, signal);
|
|
91
|
+
if (await (0, process_identity_exports.waitForProcessExit)(app, 5e3)) return;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
process.on("SIGTERM", stop);
|
|
95
|
+
process.on("SIGINT", stop);
|
|
96
|
+
log("info", `Started ${record.product} (pid ${app.pid}).`);
|
|
97
|
+
await ended;
|
|
98
|
+
process.off("SIGTERM", stop);
|
|
99
|
+
process.off("SIGINT", stop);
|
|
100
|
+
log(stopping || child.exitCode === 0 ? "info" : "error", `Exited ${record.product} (${child.exitCode ?? child.signalCode ?? "unknown"}).`);
|
|
101
|
+
updateMacosRecord(root, owner, {
|
|
102
|
+
app: void 0,
|
|
103
|
+
supervisor: void 0
|
|
104
|
+
});
|
|
105
|
+
} finally {
|
|
106
|
+
if (!spawned || childExited || app && ["gone", "different"].includes((0, process_identity_exports.inspectProcessIdentity)(app))) {
|
|
107
|
+
(0, ownership_claim_exports.clearClaimChild)(claim);
|
|
108
|
+
(0, ownership_claim_exports.releaseClaim)(claim);
|
|
109
|
+
}
|
|
110
|
+
writer.close();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (process.argv[1]?.endsWith("/macos-run.mjs") || process.argv[1]?.endsWith("/macos/run.ts")) {
|
|
114
|
+
const [root, launchId] = process.argv.slice(2);
|
|
115
|
+
if (!root || !launchId) throw new Error("macos-run needs a workspace and launch identity.");
|
|
116
|
+
await runMacosSupervisor(root, launchId);
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { runMacosSupervisor as n, logLines as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { i as __require, t as __commonJSMin } from "./rolldown-runtime-BsOwBuO_.mjs";
|
|
2
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
3
|
+
import { D as projectMetroSharedCache } from "./settings-oTSkkNrM.mjs";
|
|
3
4
|
import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { a as metroStoreRoot, o as registerMetroStore, t as appendCacheStore } from "./metro-store-DzeWkfqW.mjs";
|
|
5
|
+
import { a as metroStoreRoot, o as registerMetroStore, t as appendCacheStore } from "./metro-store-CDDZHtPl.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { isAbsolute, join, relative, sep } from "node:path";
|
|
8
8
|
//#endregion
|
|
@@ -14,6 +14,8 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
14
14
|
"::1",
|
|
15
15
|
"::ffff:127.0.0.1"
|
|
16
16
|
]);
|
|
17
|
+
const PROGRESS_PART = /^\{"done":(\d+),"total":(\d+),"percent":(\d+)\}$/;
|
|
18
|
+
const PROGRESS_INTERVAL_MS = 1e3;
|
|
17
19
|
function clientPidFromLsof(output, clientPort, serverPort) {
|
|
18
20
|
const connection = new RegExp(`:${clientPort}->\\S*:${serverPort}$`);
|
|
19
21
|
let pid = null;
|
|
@@ -36,7 +38,7 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
36
38
|
res.end("ready");
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
|
-
|
|
41
|
+
const prefetch = req.headers["x-stim-metro-warmup"] === "1";
|
|
40
42
|
let url;
|
|
41
43
|
try {
|
|
42
44
|
url = new URL(req.url, "http://localhost");
|
|
@@ -46,34 +48,50 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
46
48
|
const platform = url.searchParams.get("platform");
|
|
47
49
|
if (req.method !== "GET" || !/\.bundle\/*$/.test(url.pathname) || !["ios", "android"].includes(platform)) return next();
|
|
48
50
|
const requestId = randomUUID();
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
+
const kind = prefetch ? "prefetch" : "response";
|
|
52
|
+
const clientPid = platform === "ios" && !prefetch ? lookupClientPid(req, runLsof) : null;
|
|
53
|
+
const send = (ts, stage, statusCode, pid, progress) => {
|
|
51
54
|
try {
|
|
52
55
|
write({
|
|
53
56
|
ts,
|
|
54
57
|
src: "metro",
|
|
55
|
-
level:
|
|
56
|
-
event
|
|
58
|
+
level: stage === "failed" && !prefetch ? "error" : "debug",
|
|
59
|
+
event: `bundle_${kind}_${stage}`,
|
|
57
60
|
platform,
|
|
58
61
|
requestId,
|
|
59
|
-
statusCode,
|
|
60
|
-
msg: `${platform} bundle
|
|
62
|
+
...progress ?? { statusCode },
|
|
63
|
+
msg: progress ? `${platform} bundle ${progress.percent}%` : `${platform} bundle ${kind} ${stage}`,
|
|
61
64
|
...pid ? { clientPid: pid } : {}
|
|
62
65
|
});
|
|
63
66
|
} catch {}
|
|
64
67
|
};
|
|
65
|
-
const emit = (
|
|
68
|
+
const emit = (stage, statusCode, progress) => {
|
|
66
69
|
const ts = Date.now();
|
|
67
|
-
if (clientPid) clientPid.then((pid) => send(ts,
|
|
68
|
-
else send(ts,
|
|
70
|
+
if (clientPid) clientPid.then((pid) => send(ts, stage, statusCode, pid, progress));
|
|
71
|
+
else send(ts, stage, statusCode, null, progress);
|
|
72
|
+
};
|
|
73
|
+
emit("started");
|
|
74
|
+
const writeChunk = res.write;
|
|
75
|
+
let progressAt = 0;
|
|
76
|
+
res.write = function(chunk, ...rest) {
|
|
77
|
+
const part = typeof chunk === "string" && chunk.length < 100 ? PROGRESS_PART.exec(chunk) : null;
|
|
78
|
+
const now = part ? Date.now() : 0;
|
|
79
|
+
if (part && now - progressAt >= PROGRESS_INTERVAL_MS) {
|
|
80
|
+
progressAt = now;
|
|
81
|
+
emit("progress", void 0, {
|
|
82
|
+
done: Number(part[1]),
|
|
83
|
+
total: Number(part[2]),
|
|
84
|
+
percent: Number(part[3])
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return writeChunk.call(this, chunk, ...rest);
|
|
69
88
|
};
|
|
70
|
-
emit("bundle_response_started");
|
|
71
89
|
let ended = false;
|
|
72
90
|
const finish = (complete) => {
|
|
73
91
|
if (ended) return;
|
|
74
92
|
ended = true;
|
|
75
93
|
const success = complete && (res.statusCode === 200 || res.statusCode === 304);
|
|
76
|
-
emit(success ? "
|
|
94
|
+
emit(success ? "finished" : "failed", res.statusCode);
|
|
77
95
|
};
|
|
78
96
|
res.once("finish", () => finish(true));
|
|
79
97
|
res.once("close", () => finish(false));
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import { f as resolvePackageJson } from "./project-CWlvEaeN.mjs";
|
|
4
|
-
import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
5
2
|
import { n as stripAnsi, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { D as projectMetroSharedCache } from "./settings-oTSkkNrM.mjs";
|
|
4
|
+
import { p as resolvePackageJson } from "./project-Du91Ilvc.mjs";
|
|
5
|
+
import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
|
|
6
|
+
import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
|
|
7
|
+
import { a as metroStoreRoot, i as metroStoreConfirmedRoot, n as expoMetroConfigPath, o as registerMetroStore, r as expoMetroStoreEnv } from "./metro-store-CDDZHtPl.mjs";
|
|
8
8
|
import { accessSync, constants, existsSync, readFileSync } from "node:fs";
|
|
9
|
-
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
10
9
|
import { dirname, join, parse } from "node:path";
|
|
10
|
+
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
11
11
|
//#region src/supervisor/server-expo.ts
|
|
12
12
|
function delay(ms) {
|
|
13
13
|
return new Promise((resolve) => {
|
|
@@ -120,11 +120,7 @@ function recordFromLine(line, { stream = "stdout" } = {}) {
|
|
|
120
120
|
if (!msg.trim()) return null;
|
|
121
121
|
if (stream === "stderr" && msg.startsWith("stim-bundle-response: ")) try {
|
|
122
122
|
const record = JSON.parse(msg.slice(22));
|
|
123
|
-
if (record.src === "metro" && [
|
|
124
|
-
"bundle_response_started",
|
|
125
|
-
"bundle_response_finished",
|
|
126
|
-
"bundle_response_failed"
|
|
127
|
-
].includes(record.event) && ["ios", "android"].includes(record.platform) && typeof record.requestId === "string" && Number.isFinite(record.ts)) return record;
|
|
123
|
+
if (record.src === "metro" && /^bundle_(response|prefetch)_(started|progress|finished|failed)$/.test(record.event) && ["ios", "android"].includes(record.platform) && typeof record.requestId === "string" && Number.isFinite(record.ts)) return record;
|
|
128
124
|
} catch {}
|
|
129
125
|
const confirmed = metroStoreConfirmedRoot(msg);
|
|
130
126
|
if (confirmed) return {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SETTINGS, coerceSettingText, loadConfig, settingValueError } from "@stim-cli/core/state";
|
|
2
|
+
//#region src/maintenance/settings.ts
|
|
3
|
+
function resolveMaintenanceSettings(config = loadConfig(), env = process.env) {
|
|
4
|
+
const result = {};
|
|
5
|
+
const invalid = [];
|
|
6
|
+
let disabled = false;
|
|
7
|
+
for (const setting of SETTINGS.filter((entry) => entry.key.startsWith("maintenance.") || /^caches\..*MaxGb$/.test(entry.key))) {
|
|
8
|
+
const [group, name] = setting.key.split(".");
|
|
9
|
+
const rawEnv = setting.env ? env[setting.env] : void 0;
|
|
10
|
+
const layer = config?.[group];
|
|
11
|
+
const configured = layer && typeof layer === "object" ? layer[name] : void 0;
|
|
12
|
+
const value = rawEnv !== void 0 ? coerceSettingText(setting, rawEnv) : env.STIM_HOME && setting.scopedHomeValue !== void 0 ? setting.scopedHomeValue : env.CI && setting.ciValue !== void 0 ? setting.ciValue : configured === void 0 ? setting.default : configured;
|
|
13
|
+
const error = value === void 0 ? null : settingValueError(setting, value);
|
|
14
|
+
if (error) {
|
|
15
|
+
invalid.push(`${setting.key}: expected ${error}`);
|
|
16
|
+
if (group === "maintenance") disabled = true;
|
|
17
|
+
}
|
|
18
|
+
result[name] = error ? setting.default : value;
|
|
19
|
+
}
|
|
20
|
+
if (disabled) result.mode = "off";
|
|
21
|
+
if (invalid.length) result.invalid = invalid.join("; ");
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { resolveMaintenanceSettings as t };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as settingDefault, r as stimDesktopInstalled } from "./stim-desktop-
|
|
5
|
-
import {
|
|
1
|
+
import { D as withConfigLock$1, O as writeConfigSetting, _ as loadConfig$1, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-D0DbpZtM.mjs";
|
|
2
|
+
import { A as readCommittedSettings, H as unknownSettingKeys, gt as repoRoot, it as gitCommonDir } from "./settings-oTSkkNrM.mjs";
|
|
3
|
+
import { a as findCommandWorkspace, t as NO_PROJECT_REFUSAL } from "./project-Du91Ilvc.mjs";
|
|
4
|
+
import { n as settingDefault, r as stimDesktopInstalled } from "./stim-desktop-Cnz8CPnl.mjs";
|
|
5
|
+
import { n as recordingLayers, t as deleteTurnedOffRecordings } from "./recordings-BIXOzVnr.mjs";
|
|
6
6
|
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { SETTINGS, SETTING_SCOPES, coerceSettingText, isJsonObject, isSensitiveReference, settingDefinition, settingValueError } from "@stim-cli/core/state";
|
|
8
7
|
import { join } from "node:path";
|
|
8
|
+
import { SETTINGS, SETTING_SCOPES, coerceSettingText, isJsonObject, isSensitiveReference, settingDefinition, settingValueError } from "@stim-cli/core/state";
|
|
9
9
|
import chalk from "chalk";
|
|
10
10
|
//#region src/commands/settings.ts
|
|
11
11
|
const MASK = "********";
|
|
@@ -85,6 +85,7 @@ function settingEntry(context, setting) {
|
|
|
85
85
|
value: String(masked(setting, envValue))
|
|
86
86
|
} : void 0;
|
|
87
87
|
const scopedHome = !env && setting.scopedHomeValue !== void 0 && context.env.STIM_HOME;
|
|
88
|
+
const ci = !env && setting.ciValue !== void 0 && context.env.CI;
|
|
88
89
|
const winner = PRECEDENCE.find((scope) => scope in layers);
|
|
89
90
|
let value = null;
|
|
90
91
|
let origin = null;
|
|
@@ -95,6 +96,9 @@ function settingEntry(context, setting) {
|
|
|
95
96
|
} else if (scopedHome) {
|
|
96
97
|
value = setting.scopedHomeValue;
|
|
97
98
|
origin = "env";
|
|
99
|
+
} else if (ci) {
|
|
100
|
+
value = setting.ciValue;
|
|
101
|
+
origin = "env";
|
|
98
102
|
} else if (winner) {
|
|
99
103
|
value = layers[winner];
|
|
100
104
|
origin = winner;
|
|
@@ -112,6 +116,9 @@ function settingEntry(context, setting) {
|
|
|
112
116
|
...env ? { env } : scopedHome ? { env: {
|
|
113
117
|
name: "STIM_HOME",
|
|
114
118
|
value: context.env.STIM_HOME
|
|
119
|
+
} } : ci ? { env: {
|
|
120
|
+
name: "CI",
|
|
121
|
+
value: context.env.CI
|
|
115
122
|
} } : {},
|
|
116
123
|
...setting.sensitive ? { sensitive: true } : {},
|
|
117
124
|
...defaultReason ? { defaultReason } : {}
|
|
@@ -344,37 +351,42 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
|
|
|
344
351
|
if (setting.sensitive && scope === "committed" && !isSensitiveReference(value)) throw new Refusal("STIM_BAD_ARG", `${key} is sensitive, so a committed .stim.json takes only an env: or file: reference, never the secret.`, `Set the secret with --scope workspace or --scope repo, or commit a reference such as env:MY_KEYSTORE_PASSWORD.`);
|
|
345
352
|
const context = readContext(env, io.note);
|
|
346
353
|
const file = requireLayer(context, scope, setting);
|
|
354
|
+
const recording = setting.key === "recording.enabled" ? recordingLayers() : null;
|
|
347
355
|
const changed = writeSetting(context, setting, scope, value);
|
|
348
356
|
report(io, wantsJson(opts, command), {
|
|
349
357
|
key,
|
|
350
358
|
scope,
|
|
351
359
|
file,
|
|
352
360
|
changed
|
|
353
|
-
}, setting, readContext(env), "set");
|
|
361
|
+
}, setting, readContext(env), "set", recording);
|
|
354
362
|
}));
|
|
355
363
|
settings.command("unset <key>").description("Remove a setting from one layer").option("--scope <scope>", `the layer to clear: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting after removal as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, () => {
|
|
356
364
|
const setting = requireSetting(key);
|
|
357
365
|
const scope = readScope(opts.scope, setting);
|
|
358
366
|
const context = readContext(env, io.note);
|
|
359
367
|
const file = requireLayer(context, scope, setting);
|
|
368
|
+
const recording = setting.key === "recording.enabled" ? recordingLayers() : null;
|
|
360
369
|
const changed = writeSetting(context, setting, scope, void 0);
|
|
361
370
|
report(io, wantsJson(opts, command), {
|
|
362
371
|
key,
|
|
363
372
|
scope,
|
|
364
373
|
file,
|
|
365
374
|
changed
|
|
366
|
-
}, setting, readContext(env), "unset");
|
|
375
|
+
}, setting, readContext(env), "unset", recording);
|
|
367
376
|
}));
|
|
368
377
|
}
|
|
369
|
-
function report(io, json, write, setting, context, verb) {
|
|
378
|
+
function report(io, json, write, setting, context, verb, recordingBefore) {
|
|
370
379
|
const entry = settingEntry(context, setting);
|
|
380
|
+
const recordingsDeleted = recordingBefore ? deleteTurnedOffRecordings(recordingBefore) : null;
|
|
371
381
|
if (json) {
|
|
372
382
|
io.out(JSON.stringify({
|
|
373
383
|
...write,
|
|
374
|
-
setting: entry
|
|
384
|
+
setting: entry,
|
|
385
|
+
...recordingsDeleted ? { recordingsDeleted } : {}
|
|
375
386
|
}));
|
|
376
387
|
return;
|
|
377
388
|
}
|
|
389
|
+
for (const workspace of recordingsDeleted ?? []) io.note(`Deleted the device recordings of ${workspace}.`);
|
|
378
390
|
const effective = entry.origin === null ? "unset" : `${formatValue(entry.value)} (${formatOrigin(entry)})`;
|
|
379
391
|
if (!write.changed) {
|
|
380
392
|
io.out(`${write.key} was not set in ${write.file}; effective value: ${effective}`);
|