stim 1.1.0 → 1.3.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 +37 -0
- package/dist/{android-CC5bUer7.mjs → android-BW8i_YxU.mjs} +1 -1
- package/dist/android-BqVIJoG7.mjs +1368 -0
- package/dist/{android-DnZlT3aU.mjs → android-CqcW1hrP.mjs} +205 -58
- package/dist/{android-cas-DGlTStWu.mjs → android-cas-BR5YJBYv.mjs} +6 -6
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{app-install-oZIQRbdD.mjs → app-install-DIp9riNx.mjs} +29 -21
- package/dist/{build-slots-CgacA9zQ.mjs → build-slots-C3-R4XQr.mjs} +3 -3
- package/dist/{cache-manifest-oeH18ERr.mjs → cache-manifest-CXR-Y8pH.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +13 -13
- package/dist/collector-run.d.mts +4 -1
- package/dist/collector-run.mjs +36 -11
- package/dist/{config-D7uu8Gbq.mjs → config-CcefMY2Q.mjs} +94 -13
- package/dist/{deps-64wVnpZc.mjs → deps-Spz8ozgo.mjs} +2 -2
- package/dist/{dev-client-Bvky1hya.mjs → dev-client-BjisHDB5.mjs} +250 -10
- package/dist/{device-DJKv5Qej.mjs → device-BkiW-gkk.mjs} +19 -11
- package/dist/{device-lease-D-G3SgVe.mjs → device-lease-BJYybF-2.mjs} +107 -83
- package/dist/{device-pool-BlHXnYYs.mjs → device-pool-CPbLGfrB.mjs} +19 -13
- package/dist/{device-remote-CCgkG82J.mjs → device-remote-AkYCKS8U.mjs} +8 -8
- package/dist/{doctor-DlVxTtMq.mjs → doctor-Bmv86UUW.mjs} +18 -26
- package/dist/{doctor-BRF9aAJ3.mjs → doctor-fAMXC4vl.mjs} +10 -10
- package/dist/{error-diagnostics-B5IJwv3-.mjs → error-diagnostics-DHC31rXA.mjs} +65 -55
- package/dist/{exec-bsN9MJXb.mjs → exec-CyylIdq9.mjs} +4 -2
- package/dist/{gc-DhXdgSdt.mjs → gc-GGu-8ULN.mjs} +90 -67
- package/dist/{guide-DrhrDBo5.mjs → guide-92CPA21s.mjs} +414 -47
- package/dist/{ios-CK1Vrk6Q.mjs → ios-BSXFeO5H.mjs} +200 -59
- package/dist/{ios-BZxKPuqP.mjs → ios-Deh5js5V.mjs} +147 -40
- package/dist/{ios-device-CdSm0GDw.mjs → ios-device-CWOM_S44.mjs} +2 -2
- package/dist/{ios-device-CYbuRNXR.mjs → ios-device-D3pzTKQE.mjs} +1 -1
- package/dist/{logs-Dxoy16Qv.mjs → logs-DPNF4C9s.mjs} +9 -6
- package/dist/{logs-query-oqn47Ffx.mjs → logs-query-R-Cqc6Qv.mjs} +22 -5
- package/dist/{metro-B01H3EuD.mjs → metro-CORqXyTL.mjs} +3 -3
- package/dist/{ndjson-DcAtEx_K.mjs → ndjson-BZwI1NBv.mjs} +5 -2
- package/dist/{ownership-D8HmSv2E.mjs → ownership-8O073GIC.mjs} +3 -3
- package/dist/{ownership-B9QIdQOw.mjs → ownership-BpCKiRlQ.mjs} +4 -4
- package/dist/{ownership-claim-CeJLEpjD.mjs → ownership-claim-Bf2CAfw3.mjs} +4 -3
- package/dist/{project-COj6nzzh.mjs → project-fKmuIaMI.mjs} +2 -2
- package/dist/{reclaim-BPvN2HlP.mjs → reclaim-iW9Cad7k.mjs} +80 -73
- package/dist/{reload-DYZEBbZy.mjs → reload-DazHDSFA.mjs} +32 -24
- package/dist/{server-bare-BYHqEeyw.mjs → server-bare-DEzPZLvf.mjs} +7 -2
- package/dist/server-expo-44em5Pmg.mjs +2 -0
- package/dist/{server-expo-BEMr_m6p.mjs → server-expo-DizT4OMk.mjs} +5 -5
- package/dist/{settings-BSwrY4FZ.mjs → settings-DEJf6_kJ.mjs} +26 -5
- package/dist/slot-launch-cci0xvmC.mjs +19 -0
- package/dist/{start-ByCylYtB.mjs → start-mObjQH2W.mjs} +12 -12
- package/dist/{state-IYEY-zi8.mjs → state-B3XA2wp2.mjs} +9 -9
- package/dist/{stats-wqxPm7Tv.mjs → stats-BR-kwj0B.mjs} +1 -1
- package/dist/{stats-DZ4Q5J-7.mjs → stats-CaaQr4yN.mjs} +3 -3
- package/dist/{status-Dia0XTqG.mjs → status-BxQNqu9t.mjs} +86 -25
- package/dist/{stop-D6o5zAdm.mjs → stop-CrHGcjrV.mjs} +2 -2
- package/dist/{stop-BApyaF21.mjs → stop-DimGXEKY.mjs} +93 -42
- package/dist/supervisor-run.d.mts +1 -2
- package/dist/supervisor-run.mjs +5 -5
- package/dist/{remote-cache-DOi5-zLj.mjs → teardown-ClFp1Aax.mjs} +889 -830
- package/dist/{workspace-process-lock-CxOO9-pf.mjs → workspace-process-lock-3NcQnZ0X.mjs} +1 -1
- package/dist/{worktree-DxEmUI_n.mjs → worktree-DxTgN1CJ.mjs} +16 -16
- package/dist/{worktree-Dx3ZC5lS.mjs → worktree-Eq6TLH8N.mjs} +7 -3
- package/dist/{xcode-CDB6fytw.mjs → xcode-D7sAp-Zy.mjs} +256 -103
- package/package.json +5 -5
- package/shim/bundle-response.cjs +5 -0
- package/dist/android-xmyGBNy5.mjs +0 -665
- package/dist/build-lock-vE45ZzJZ.mjs +0 -645
- package/dist/server-expo-rb0k-0w7.mjs +0 -2
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { P as volumeRootFor, g as loadConfig, u as getConfigDir } from "./config-
|
|
3
|
-
import { D as workspaceLogsDir } from "./state-
|
|
4
|
-
import { f as listWorktrees } from "./worktree-
|
|
5
|
-
import { a as findProjectRoot, c as projectShortcut } from "./project-
|
|
6
|
-
import { a as isMetroRunning, i as resolveProjectMetro } from "./metro-
|
|
7
|
-
import { S as readParked, v as POOL_SETTING_REMEDY, x as parkedMaxSetting } from "./remote-cache-DOi5-zLj.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
+
import { P as volumeRootFor, g as loadConfig, u as getConfigDir, z as projectDeviceSlots } from "./config-CcefMY2Q.mjs";
|
|
3
|
+
import { D as workspaceLogsDir } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { f as listWorktrees } from "./worktree-Eq6TLH8N.mjs";
|
|
5
|
+
import { a as findProjectRoot, c as projectShortcut } from "./project-fKmuIaMI.mjs";
|
|
6
|
+
import { a as isMetroRunning, i as resolveProjectMetro } from "./metro-CORqXyTL.mjs";
|
|
8
7
|
import { a as formatElapsed, r as clockTime, u as plural } from "./command-output-8wHMEde0.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
8
|
+
import { N as resolveOwnedAvdSerial } from "./android-BqVIJoG7.mjs";
|
|
9
|
+
import { a as POOL_SETTING_REMEDY, c as parkedMaxSetting, l as readParked } from "./teardown-ClFp1Aax.mjs";
|
|
10
|
+
import { u as listAllIosSims } from "./ios-Deh5js5V.mjs";
|
|
11
|
+
import { i as listLeaseFiles } from "./device-lease-BJYybF-2.mjs";
|
|
12
|
+
import { s as queryLogs } from "./logs-query-R-Cqc6Qv.mjs";
|
|
13
|
+
import { t as resolveSupervisorTarget } from "./ownership-BpCKiRlQ.mjs";
|
|
14
|
+
import { i as readSupervisorState } from "./stop-DimGXEKY.mjs";
|
|
14
15
|
import { existsSync } from "fs";
|
|
15
16
|
import { totalmem } from "os";
|
|
16
17
|
import chalk from "chalk";
|
|
@@ -23,24 +24,54 @@ function poolLine({ platform, parked, max }) {
|
|
|
23
24
|
const what = plural(parked, `parked ${platform === "ios" ? "iOS simulator" : "Android emulator"}`);
|
|
24
25
|
return max > 0 ? `pool: ${what} (max ${max})` : `pool: ${what} (parking off; gc --delete removes them)`;
|
|
25
26
|
}
|
|
26
|
-
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, supervisor = null, logs = null } = {}) {
|
|
27
|
+
function environmentState(project, { simsByUdid = {}, metro = null, worktrees = [], simsAvailable = true, androidRuntime = null, androidRuntimes = {}, supervisor = null, logs = null } = {}) {
|
|
27
28
|
const ios = project.platforms?.ios;
|
|
28
29
|
const android = project.platforms?.android;
|
|
29
30
|
const sim = ios ? simsByUdid[ios.deviceUdid] : null;
|
|
30
31
|
const simBooted = Boolean(sim && sim.state === "Booted");
|
|
31
32
|
const metroRunning = Boolean(metro?.metro);
|
|
32
|
-
const
|
|
33
|
+
const androidDetected = androidRuntime ? Boolean(androidRuntime.serial) : Boolean(android?.serial);
|
|
34
|
+
let live = simBooted || metroRunning || androidDetected;
|
|
33
35
|
let memoryMb = 0;
|
|
34
36
|
if (simBooted) memoryMb += IOS_SIM_MB;
|
|
35
|
-
if (
|
|
37
|
+
if (androidDetected) memoryMb += ANDROID_EMULATOR_MB;
|
|
36
38
|
if (metroRunning) memoryMb += METRO_MB;
|
|
37
39
|
const warnings = [];
|
|
38
40
|
if (metro?.notOurs) warnings.push(`port ${project.metroPort}: ${metro.notOurs}`);
|
|
39
41
|
if (ios && !sim && simsAvailable) warnings.push(`recorded sim ${ios.deviceUdid} no longer exists`);
|
|
40
42
|
if (simBooted && project.metroPort && !metroRunning) warnings.push("simulator is booted with no Metro serving it");
|
|
43
|
+
if (androidRuntime && android?.avdName) {
|
|
44
|
+
const recordedSerial = android.consolePort ? `emulator-${android.consolePort}` : android.serial;
|
|
45
|
+
if (androidRuntime.serial && recordedSerial && androidRuntime.serial !== recordedSerial) warnings.push(`owned AVD ${android.avdName} changed serial (${recordedSerial} -> ${androidRuntime.serial}); rerun your \`stim android\` command in this workspace to restore Metro forwarding, then reopen agent-device on ${androidRuntime.serial}`);
|
|
46
|
+
if (androidRuntime.state === "missing") warnings.push(`recorded AVD ${android.avdName} no longer exists`);
|
|
47
|
+
if (androidRuntime.state === "not-detected") warnings.push(`owned AVD ${android.avdName} is not detected by adb; rerun your \`stim android\` command in this workspace to reconnect`);
|
|
48
|
+
if (androidRuntime.error) warnings.push(`could not check owned AVD ${android.avdName}: ${androidRuntime.error}`);
|
|
49
|
+
}
|
|
41
50
|
if (supervisor && supervisor.alive === false) warnings.push(`stale supervisor record for ${project.__path}`);
|
|
51
|
+
const slots = [];
|
|
52
|
+
for (const { slot, platforms } of projectDeviceSlots(project).slice(1)) {
|
|
53
|
+
const deviceState = environmentState({
|
|
54
|
+
...project,
|
|
55
|
+
platforms,
|
|
56
|
+
deviceSlots: void 0
|
|
57
|
+
}, {
|
|
58
|
+
simsByUdid,
|
|
59
|
+
simsAvailable,
|
|
60
|
+
metro,
|
|
61
|
+
androidRuntime: androidRuntimes[slot]
|
|
62
|
+
});
|
|
63
|
+
slots.push({
|
|
64
|
+
slot,
|
|
65
|
+
ios: deviceState.ios,
|
|
66
|
+
android: deviceState.android
|
|
67
|
+
});
|
|
68
|
+
memoryMb += deviceState.memoryMb - (metroRunning ? METRO_MB : 0);
|
|
69
|
+
live ||= deviceState.live;
|
|
70
|
+
warnings.push(...deviceState.warnings.map((warning) => `${slot}: ${warning}`));
|
|
71
|
+
}
|
|
42
72
|
return {
|
|
43
73
|
path: project.__path,
|
|
74
|
+
...slots.length ? { slots } : {},
|
|
44
75
|
live,
|
|
45
76
|
memoryMb,
|
|
46
77
|
warnings,
|
|
@@ -53,7 +84,11 @@ function environmentState(project, { simsByUdid = {}, metro = null, worktrees =
|
|
|
53
84
|
android: android ? {
|
|
54
85
|
name: android.avdName ?? android.serial,
|
|
55
86
|
owned: Boolean(android.owned),
|
|
56
|
-
physical: Boolean(android.serial && !android.avdName)
|
|
87
|
+
physical: Boolean(android.serial && !android.avdName),
|
|
88
|
+
...androidRuntime ? {
|
|
89
|
+
serial: androidRuntime.serial,
|
|
90
|
+
state: androidRuntime.state
|
|
91
|
+
} : {}
|
|
57
92
|
} : null,
|
|
58
93
|
metro: project.metroPort ? {
|
|
59
94
|
port: project.metroPort,
|
|
@@ -130,6 +165,7 @@ function deviceLeaseStates(entries, { root, now }) {
|
|
|
130
165
|
return {
|
|
131
166
|
path: entry.path,
|
|
132
167
|
platform: entry.platform,
|
|
168
|
+
...lease?.slot ? { slot: lease.slot } : {},
|
|
133
169
|
id: entry.id,
|
|
134
170
|
deviceName: lease?.deviceName ?? null,
|
|
135
171
|
holder: lease?.holder ?? null,
|
|
@@ -145,7 +181,7 @@ function deviceLeaseLines(states, now) {
|
|
|
145
181
|
if (states.length === 0) return [];
|
|
146
182
|
const lines = [`Device leases (${states.length}):`];
|
|
147
183
|
for (const state of states) {
|
|
148
|
-
const device = `${state.platform} ${state.id ?? state.path}${state.deviceName ? ` (${state.deviceName})` : ""}`;
|
|
184
|
+
const device = `${state.platform}${state.slot ? ` [${state.slot}]` : ""} ${state.id ?? state.path}${state.deviceName ? ` (${state.deviceName})` : ""}`;
|
|
149
185
|
if (!state.parsed || state.expiresAt === null) {
|
|
150
186
|
lines.push(` ${device} -- unreadable lease file, so nothing may take the device: ${state.path}`);
|
|
151
187
|
continue;
|
|
@@ -191,6 +227,8 @@ function statusCommand(program) {
|
|
|
191
227
|
metro,
|
|
192
228
|
worktrees,
|
|
193
229
|
simsAvailable,
|
|
230
|
+
androidRuntimes: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? readAndroidRuntime(platforms.android.avdName) : null])),
|
|
231
|
+
androidRuntime: proj.platforms?.android?.owned && proj.platforms.android.avdName ? readAndroidRuntime(proj.platforms.android.avdName) : null,
|
|
194
232
|
supervisor,
|
|
195
233
|
logs: logFacts(path)
|
|
196
234
|
}));
|
|
@@ -260,14 +298,22 @@ function statusCommand(program) {
|
|
|
260
298
|
const errs = n > 0 ? chalk.yellow(` (${n} error${n === 1 ? "" : "s"} since the last marker)`) : "";
|
|
261
299
|
console.log(chalk.dim(` logs: ${state.logs.dir}`) + errs);
|
|
262
300
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
301
|
+
for (const deviceState of [{
|
|
302
|
+
slot: "default",
|
|
303
|
+
ios: state.ios,
|
|
304
|
+
android: state.android
|
|
305
|
+
}, ...state.slots ?? []]) {
|
|
306
|
+
const slotLabel = deviceState.slot === "default" ? "" : ` [${deviceState.slot}]`;
|
|
307
|
+
if (deviceState.ios) {
|
|
308
|
+
const booted = deviceState.ios.state === "Booted" ? chalk.green("booted") : chalk.dim(deviceState.ios.state.toLowerCase());
|
|
309
|
+
const owned = deviceState.ios.owned ? chalk.dim(" (owned)") : "";
|
|
310
|
+
console.log(` ios${slotLabel}: ${chalk.cyan(deviceState.ios.name ?? deviceState.ios.udid)} ${booted}${owned}`);
|
|
311
|
+
}
|
|
312
|
+
if (deviceState.android) {
|
|
313
|
+
const kind = deviceState.android.physical ? chalk.dim("(physical)") : chalk.dim("(emulator)");
|
|
314
|
+
const observed = deviceState.android.state ? ` ${deviceState.android.state}${deviceState.android.serial ? ` (${deviceState.android.serial})` : ""}` : "";
|
|
315
|
+
console.log(` android${slotLabel}: ${chalk.cyan(deviceState.android.name)} ${kind}${observed}${deviceState.android.owned ? chalk.dim(" (owned)") : ""}`);
|
|
316
|
+
}
|
|
271
317
|
}
|
|
272
318
|
for (const w of state.warnings) console.log(chalk.yellow(` ! ${w}`));
|
|
273
319
|
}
|
|
@@ -297,6 +343,21 @@ function statusCommand(program) {
|
|
|
297
343
|
if (cap.overCapacity) console.log(chalk.yellow("Over comfortable capacity. A machine that swaps is slower than one working in sequence -- release one before starting another."));
|
|
298
344
|
});
|
|
299
345
|
}
|
|
346
|
+
function readAndroidRuntime(avdName) {
|
|
347
|
+
try {
|
|
348
|
+
const resolved = resolveOwnedAvdSerial(avdName, { timeoutMs: 5e3 });
|
|
349
|
+
return {
|
|
350
|
+
serial: resolved.serial ?? null,
|
|
351
|
+
state: resolved.serial ? "detected" : resolved.missing ? "missing" : resolved.notRunning ? "not-detected" : "unknown"
|
|
352
|
+
};
|
|
353
|
+
} catch (error) {
|
|
354
|
+
return {
|
|
355
|
+
serial: null,
|
|
356
|
+
state: "unknown",
|
|
357
|
+
error: String(error?.message || error).split("\n")[0]
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
}
|
|
300
361
|
function readVolumes(projectPath) {
|
|
301
362
|
const roots = [.../* @__PURE__ */ new Set([
|
|
302
363
|
"/",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as resolveSupervisorTarget } from "./ownership-
|
|
2
|
-
import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-
|
|
1
|
+
import { t as resolveSupervisorTarget } from "./ownership-BpCKiRlQ.mjs";
|
|
2
|
+
import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-DimGXEKY.mjs";
|
|
3
3
|
export { clearCollectorState, clearSupervisorState, stopCommand as default, readCollectorState, readSupervisorState, resolveCollectorTargets, resolveSupervisorTarget, runStop };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { C as withConfigLock, D as sameProcessRecord, E as inspectProcessIdentity, O as waitForProcessExit, S as upsertProject, a as clearSupervisor, f as getProject } from "./config-
|
|
2
|
-
import { _ as writeWorkspaceState, a as clearRemoteSession, c as readMetroTunnel, i as clearManagedMetroTunnel, m as withWorkspaceStateLock, o as clearWorkspaceStateKeys, p as readWorkspaceState, s as clearWorkspaceSupervisor, u as readRemoteSession } from "./state-
|
|
3
|
-
import { a as findProjectRoot } from "./project-
|
|
4
|
-
import { i as resolveProjectMetro, n as killMetroTree, r as pidExists } from "./metro-
|
|
5
|
-
import { n as verifyCollectorOwnership } from "./ownership-
|
|
6
|
-
import { d as resolveEasCliBin, h as teardownOwnedIosSim, m as teardownOwnedAvd } from "./remote-cache-DOi5-zLj.mjs";
|
|
1
|
+
import { C as withConfigLock, D as sameProcessRecord, E as inspectProcessIdentity, L as deviceSlotPlatforms, O as waitForProcessExit, R as parseDeviceSlotKey, S as upsertProject, V as validateDeviceSlot, a as clearSupervisor, f as getProject, z as projectDeviceSlots } from "./config-CcefMY2Q.mjs";
|
|
2
|
+
import { T as workspaceDir, _ as writeWorkspaceState, a as clearRemoteSession, c as readMetroTunnel, i as clearManagedMetroTunnel, m as withWorkspaceStateLock, o as clearWorkspaceStateKeys, p as readWorkspaceState, s as clearWorkspaceSupervisor, u as readRemoteSession } from "./state-B3XA2wp2.mjs";
|
|
3
|
+
import { a as findProjectRoot } from "./project-fKmuIaMI.mjs";
|
|
4
|
+
import { i as resolveProjectMetro, n as killMetroTree, r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
5
|
+
import { n as verifyCollectorOwnership } from "./ownership-8O073GIC.mjs";
|
|
7
6
|
import { f as releasedLeaseFact, l as phaseLine, u as plural } from "./command-output-8wHMEde0.mjs";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { n as teardownOwnedIosSim, t as teardownOwnedAvd, x as resolveEasCliBin } from "./teardown-ClFp1Aax.mjs";
|
|
8
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-3NcQnZ0X.mjs";
|
|
9
|
+
import { l as releaseWorkspaceLeases } from "./device-lease-BJYybF-2.mjs";
|
|
10
|
+
import { i as endRecordedSession } from "./device-remote-AkYCKS8U.mjs";
|
|
11
|
+
import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-BpCKiRlQ.mjs";
|
|
11
12
|
import chalk from "chalk";
|
|
12
13
|
//#region src/commands/stop.ts
|
|
13
14
|
const DEFAULT_WAIT_MS = 1e4;
|
|
@@ -101,7 +102,47 @@ function defaultTeardownRemoteSession(root, sessionId) {
|
|
|
101
102
|
easBin: resolveEasCliBin(root)?.file ?? null
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
|
-
async function runStop(
|
|
105
|
+
async function runStop(options) {
|
|
106
|
+
if (options.slot === void 0) return stopWorkspace(options);
|
|
107
|
+
const slot = validateDeviceSlot(options.slot);
|
|
108
|
+
const root = options.root;
|
|
109
|
+
const project = options.project === void 0 ? getProject(root) : options.project;
|
|
110
|
+
const records = options.collectors === void 0 ? readCollectorState(root) : options.collectors;
|
|
111
|
+
const collectors = Object.fromEntries(Object.entries(records ?? {}).filter(([key]) => parseDeviceSlotKey(key)?.slot === slot));
|
|
112
|
+
const result = await stopWorkspace({
|
|
113
|
+
...options,
|
|
114
|
+
project: project ? {
|
|
115
|
+
...project,
|
|
116
|
+
platforms: deviceSlotPlatforms(project, slot),
|
|
117
|
+
deviceSlots: void 0,
|
|
118
|
+
supervisor: void 0,
|
|
119
|
+
metroPort: null
|
|
120
|
+
} : null,
|
|
121
|
+
state: null,
|
|
122
|
+
collectors,
|
|
123
|
+
remoteDevice: null,
|
|
124
|
+
metroTunnel: null,
|
|
125
|
+
clearCollectors: (projectRoot, expected) => withWorkspaceStateLock(projectRoot, () => {
|
|
126
|
+
clearCollectorState(projectRoot, expected);
|
|
127
|
+
return !Object.keys(readCollectorState(projectRoot)).some((key) => parseDeviceSlotKey(key)?.slot === slot);
|
|
128
|
+
}),
|
|
129
|
+
clearState: () => true,
|
|
130
|
+
clearRegistration: async () => true,
|
|
131
|
+
releaseLeases: (projectRoot) => releaseWorkspaceLeases(projectRoot, { slot })
|
|
132
|
+
});
|
|
133
|
+
result.outcomes.port = {
|
|
134
|
+
status: "kept",
|
|
135
|
+
port: project?.metroPort ?? null,
|
|
136
|
+
reason: "The workspace server is shared by all slots."
|
|
137
|
+
};
|
|
138
|
+
result.outcomes.metro = {
|
|
139
|
+
status: "skipped",
|
|
140
|
+
reason: "The workspace server is shared by all slots."
|
|
141
|
+
};
|
|
142
|
+
result.summary = summarize(root, result.outcomes, result.ok);
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
async function stopWorkspace({ root, project = void 0, state = void 0, collectors = void 0, signalCollector = (pid) => process.kill(pid, "SIGTERM"), verifyCollector = verifyCollectorOwnership, clearCollectors = clearCollectorState, isAlive = pidExists, killGroup = killMetroTree, inspectIdentity = inspectProcessIdentity, waitForDeath = void 0, waitMs = DEFAULT_WAIT_MS, resolveMetro = resolveProjectMetro, teardownIos = teardownOwnedIosSim, teardownAvd = teardownOwnedAvd, remoteDevice = void 0, teardownRemoteSession = defaultTeardownRemoteSession, metroTunnel = void 0, stopMetroTunnel = stopTunnel, releaseLeases = releaseWorkspaceLeases, freePort = defaultFreePort, clearRegistration = defaultClearRegistration, clearState = clearSupervisorState, report = (line) => console.error(line) }) {
|
|
105
146
|
const proj = project === void 0 ? getProject(root) : project;
|
|
106
147
|
const sup = state === void 0 ? readSupervisorState(root) : state;
|
|
107
148
|
const collectorRecords = collectors === void 0 ? readCollectorState(root) : collectors;
|
|
@@ -235,7 +276,7 @@ async function runStop({ root, project = void 0, state = void 0, collectors = vo
|
|
|
235
276
|
teardownAvd,
|
|
236
277
|
report
|
|
237
278
|
});
|
|
238
|
-
if (
|
|
279
|
+
if (Object.values(outcomes.device).some((device) => device?.status === "failed")) ok = false;
|
|
239
280
|
}
|
|
240
281
|
const remote = remoteDevice === void 0 ? readRemoteSession(root) : remoteDevice;
|
|
241
282
|
const sessionId = typeof remote?.sessionId === "string" ? remote.sessionId : null;
|
|
@@ -461,34 +502,38 @@ function shutDownDevices(project, { teardownIos, teardownAvd, report }) {
|
|
|
461
502
|
ios: null,
|
|
462
503
|
android: null
|
|
463
504
|
};
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
505
|
+
for (const { slot, platforms } of projectDeviceSlots(project)) {
|
|
506
|
+
const iosKey = slot === "default" ? "ios" : `ios:${slot}`;
|
|
507
|
+
const androidKey = slot === "default" ? "android" : `android:${slot}`;
|
|
508
|
+
const ios = platforms.ios;
|
|
509
|
+
const iosUdid = ios?.deviceUdid;
|
|
510
|
+
const iosName = ios?.deviceName;
|
|
511
|
+
if (iosUdid) {
|
|
512
|
+
if (!ios?.owned) {
|
|
513
|
+
device[iosKey] = {
|
|
514
|
+
status: "skipped",
|
|
515
|
+
kind: "not-owned",
|
|
516
|
+
label: iosUdid,
|
|
517
|
+
reason: "Stim does not own this device"
|
|
518
|
+
};
|
|
519
|
+
report(chalk.dim(phaseLine("device", `${iosUdid} is not Stim-owned, leaving it running`)));
|
|
520
|
+
} else device[iosKey] = reportDevice(iosUdid, teardownIos(iosUdid, {
|
|
521
|
+
del: false,
|
|
522
|
+
label: iosName
|
|
523
|
+
}), report);
|
|
524
|
+
}
|
|
525
|
+
const android = platforms.android;
|
|
526
|
+
if (android?.avdName) {
|
|
527
|
+
if (!android.owned) {
|
|
528
|
+
device[androidKey] = {
|
|
529
|
+
status: "skipped",
|
|
530
|
+
kind: "not-owned",
|
|
531
|
+
label: android.avdName,
|
|
532
|
+
reason: "Stim does not own this device"
|
|
533
|
+
};
|
|
534
|
+
report(chalk.dim(phaseLine("device", `${android.avdName} is not Stim-owned, leaving it running`)));
|
|
535
|
+
} else device[androidKey] = reportDevice(android.avdName, teardownAvd(android.avdName, { del: false }), report);
|
|
536
|
+
}
|
|
492
537
|
}
|
|
493
538
|
return device;
|
|
494
539
|
}
|
|
@@ -539,7 +584,7 @@ function summarize(root, outcomes, ok) {
|
|
|
539
584
|
if (outcomes.metro.status === "not-managed") parts.push(`external server on port ${outcomes.metro.port} left alone`);
|
|
540
585
|
if (outcomes.metro.status === "refused") parts.push(`port ${outcomes.metro.port} refused`);
|
|
541
586
|
if (outcomes.metro.status === "failed") parts.push(`port ${outcomes.metro.port} could not be freed`);
|
|
542
|
-
const devicesByPlatform =
|
|
587
|
+
const devicesByPlatform = Object.entries(outcomes.device).filter(([key]) => key !== "remote");
|
|
543
588
|
for (const [platform, o] of devicesByPlatform) {
|
|
544
589
|
if (!o) continue;
|
|
545
590
|
if (o.status === "shut-down") parts.push(`${platform} ${o.label} shut down`);
|
|
@@ -571,13 +616,19 @@ async function defaultClearRegistration(root, expected) {
|
|
|
571
616
|
}
|
|
572
617
|
}
|
|
573
618
|
function stopCommand(program) {
|
|
574
|
-
program.command("stop").description("The inverse of `start`: halt this workspace's supervisor, shut the owned device down (never deleted), and free the reserved port. Non-destructive -- the device stays assigned, so coming back costs a boot. Acts on the current workspace.").option("--json", "print the per-step outcomes as JSON").action(async (opts) => {
|
|
619
|
+
program.command("stop").description("The inverse of `start`: halt this workspace's supervisor, shut the owned device down (never deleted), and free the reserved port. Non-destructive -- the device stays assigned, so coming back costs a boot. Acts on the current workspace.").option("--slot <name>", "Stop only this device slot, keeping the shared server running", validateDeviceSlot).option("--json", "print the per-step outcomes as JSON").action(async (opts) => {
|
|
575
620
|
const root = findProjectRoot(process.cwd());
|
|
576
621
|
if (!root) {
|
|
577
622
|
console.error(chalk.red("Not inside a project (no package.json found above the current directory)."));
|
|
578
623
|
process.exit(1);
|
|
579
624
|
}
|
|
580
|
-
const { ok, outcomes, summary } = await
|
|
625
|
+
const { ok, outcomes, summary } = await withWorkspaceProcessLock(workspaceDir(root), "native-run", () => runStop({
|
|
626
|
+
root,
|
|
627
|
+
slot: opts.slot
|
|
628
|
+
}), {
|
|
629
|
+
external: true,
|
|
630
|
+
waitMs: 18e5
|
|
631
|
+
});
|
|
581
632
|
if (opts.json) console.log(JSON.stringify({
|
|
582
633
|
root,
|
|
583
634
|
ok,
|
|
@@ -13,12 +13,11 @@ interface WorkspaceState {
|
|
|
13
13
|
supervisor?: Record<string, unknown>;
|
|
14
14
|
collectors?: Record<string, unknown>;
|
|
15
15
|
lastBuild?: Record<string, unknown>;
|
|
16
|
-
launches?:
|
|
16
|
+
launches?: Record<string, WorkspaceLaunchRecord>;
|
|
17
17
|
remoteDevice?: Record<string, unknown>;
|
|
18
18
|
metroTunnel?: Record<string, unknown>;
|
|
19
19
|
[key: string]: unknown;
|
|
20
20
|
}
|
|
21
|
-
type WorkspaceLaunchPlatform = "ios" | "android";
|
|
22
21
|
interface WorkspaceLaunchRecord {
|
|
23
22
|
appId: string;
|
|
24
23
|
deviceId: string;
|
package/dist/supervisor-run.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { T as captureProcessToken, a as clearSupervisor, x as setSupervisor } from "./config-
|
|
2
|
-
import { r as createNdjsonWriter } from "./ndjson-
|
|
3
|
-
import { D as workspaceLogsDir, _ as writeWorkspaceState, h as writePidFile, l as readPidFile, m as withWorkspaceStateLock, n as MODE_EXPO, p as readWorkspaceState, r as clearExpoMetroTunnel, s as clearWorkspaceSupervisor, t as MODE_BARE } from "./state-
|
|
4
|
-
import { i as detectIsExpo } from "./project-
|
|
1
|
+
import { T as captureProcessToken, a as clearSupervisor, x as setSupervisor } from "./config-CcefMY2Q.mjs";
|
|
2
|
+
import { r as createNdjsonWriter } from "./ndjson-BZwI1NBv.mjs";
|
|
3
|
+
import { D as workspaceLogsDir, _ as writeWorkspaceState, h as writePidFile, l as readPidFile, m as withWorkspaceStateLock, n as MODE_EXPO, p as readWorkspaceState, r as clearExpoMetroTunnel, s as clearWorkspaceSupervisor, t as MODE_BARE } from "./state-B3XA2wp2.mjs";
|
|
4
|
+
import { i as detectIsExpo } from "./project-fKmuIaMI.mjs";
|
|
5
5
|
import { t as describeError } from "./errors-B6W7FkxQ.mjs";
|
|
6
6
|
import { existsSync, realpathSync } from "node:fs";
|
|
7
7
|
import { isAbsolute, join, resolve } from "node:path";
|
|
@@ -97,7 +97,7 @@ async function runSupervisor({ root, port, tunnel = false, isExpo = detectIsExpo
|
|
|
97
97
|
};
|
|
98
98
|
let server;
|
|
99
99
|
try {
|
|
100
|
-
server = await (mode === "expo-child" ? startExpo || (await import("./server-expo-
|
|
100
|
+
server = await (mode === "expo-child" ? startExpo || (await import("./server-expo-44em5Pmg.mjs")).startExpoServer : startBare || (await import("./server-bare-DEzPZLvf.mjs")).startBareServer)({
|
|
101
101
|
root,
|
|
102
102
|
port,
|
|
103
103
|
logsDir,
|