stim 1.17.2 → 1.18.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 +50 -1
- package/dist/{activity-IRvJY_ru.mjs → activity-BxnkDZDi.mjs} +4 -4
- package/dist/{agent-device-usage-output-BK41vnzN.mjs → agent-device-usage-output-CZ66YA4T.mjs} +8 -8
- package/dist/android-BKA16DTf.mjs +4 -0
- package/dist/{android-B9yaNKwa.mjs → android-BvwuMUJ9.mjs} +192 -98
- package/dist/{android-DE4v59Mb.mjs → android-CBwCNicO.mjs} +2 -2
- package/dist/{android-B_YNZy61.mjs → android-DC3ZLuw0.mjs} +9 -9
- package/dist/{android-cas-ZFpjJBL_.mjs → android-cas-BBFyr9CA.mjs} +5 -5
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/api-D0VtFhqk.mjs +152 -0
- package/dist/api-run.d.mts +1 -0
- package/dist/api-run.mjs +145 -0
- package/dist/api.d.mts +212 -0
- package/dist/api.mjs +2 -0
- package/dist/{app-install-VPkI5WEg.mjs → app-install-D-PUENug.mjs} +3 -3
- package/dist/{attempt-Bk2ouQVL.mjs → attempt-DW-mQqM7.mjs} +14 -4
- package/dist/{budget-DfcgFdQB.mjs → budget-DIhL2BKx.mjs} +1578 -58
- package/dist/build-facts-DcLv2HSd.d.mts +111 -0
- package/dist/{cache-manifest-DnUHBJaU.mjs → cache-manifest-BI7ozfmH.mjs} +3 -3
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-BrcVWQyD.mjs → chrome-DJnmnS5q.mjs} +1 -1
- package/dist/cli-DNJMwADx.mjs +68 -0
- package/dist/cli.mjs +1 -1
- package/dist/{client-SvBdgObD.mjs → client-DzhapoMB.mjs} +139 -32
- package/dist/collector-run.mjs +9 -9
- package/dist/{command-output-CDAIFD-8.mjs → command-output-CBtzyIgF.mjs} +2 -2
- package/dist/{config-D0DbpZtM.mjs → config-CgYMahz7.mjs} +5 -5
- package/dist/{created-devices-CpvzBL25.mjs → created-devices-DKbeWsiK.mjs} +2 -2
- package/dist/{dependency-state-CLcBHH2M.mjs → dependency-state-xKoOypBm.mjs} +2 -2
- package/dist/{detached-entry-CiTEgMR1.mjs → detached-entry-BLfcgc4O.mjs} +1 -1
- package/dist/{dev-client-B-XC4uRH.mjs → dev-client-CLnIH02x.mjs} +2 -2
- package/dist/{device-C8IOoJPv.mjs → device-D7oCHGWi.mjs} +8 -8
- package/dist/{device-capacity-ZC4XSZ4R.mjs → device-capacity-EUOOYr8T.mjs} +13 -13
- package/dist/device-host-worker.mjs +19 -19
- package/dist/{device-ios-C2Um-XUR.mjs → device-ios-6MewKKnc.mjs} +13 -13
- package/dist/{device-lease-DpoS36_u.mjs → device-lease-Co-EwifR.mjs} +9 -9
- package/dist/{device-lease-run-B8YltIH_.mjs → device-lease-run-w1xhCqIW.mjs} +4 -4
- package/dist/{device-pool-3o7s5lo4.mjs → device-pool-F5WvRPtD.mjs} +3 -3
- package/dist/{device-remote-hFSkpfQu.mjs → device-remote-tHbd1fKy.mjs} +15 -15
- package/dist/{doctor-CFv1fCrF.mjs → doctor-B9ckYUoU.mjs} +33 -30
- package/dist/{error-diagnostics-C-NMnhrk.mjs → error-diagnostics-BRXOqDzG.mjs} +11 -11
- package/dist/{exec-CaErVv7t.mjs → exec-DWhCZDGm.mjs} +65 -2
- package/dist/{gc-DEmkg3Xh.mjs → gc-Dh6mXOKC.mjs} +23 -469
- package/dist/{gradle-dJpre3Yn.mjs → gradle-C6GKnunQ.mjs} +6 -6
- package/dist/{guide-status-Du-ZQ3FD.mjs → guide-status-Bhf9SJXc.mjs} +3 -3
- package/dist/{guide-CSmhMTf8.mjs → guide-tm6igAaa.mjs} +290 -53
- package/dist/{hosted-android-E1Heoqnv.mjs → hosted-android-Bv285t_t.mjs} +3 -3
- package/dist/{hosted-client-Bp4knSwu.mjs → hosted-client-C-rMtppF.mjs} +2 -2
- package/dist/{hosted-ios-BnbeYOUD.mjs → hosted-ios-D5mNmtj4.mjs} +1 -1
- package/dist/{hosted-logs-OcgIBvCT.mjs → hosted-logs-DN8Iz4mJ.mjs} +9 -9
- package/dist/{hosted-macos-DcxKjtfH.mjs → hosted-macos-B-wEjlwG.mjs} +5 -5
- package/dist/{hosted-native-1Ebbig4w.mjs → hosted-native-DeeOG8xZ.mjs} +6 -6
- package/dist/{idle-shutdown-IGyNV8Cr.mjs → idle-shutdown-jjtxAn5C.mjs} +7 -8
- package/dist/{ios-DSfnPfse.mjs → ios-B3SbOWdw.mjs} +19 -7
- package/dist/{ios-Cr1h5gnO.mjs → ios-Bvbf0SGY.mjs} +1 -1
- package/dist/{ios-BJ4XUSe1.mjs → ios-CPdkoKaa.mjs} +181 -95
- package/dist/ios-DNpdygiv.mjs +7 -0
- package/dist/{ios-device-Ee7sDXfp.mjs → ios-device-Bn7jWDB1.mjs} +1 -1
- package/dist/{ios-device-pAN4t54-.mjs → ios-device-vOaByMhw.mjs} +3 -3
- package/dist/{ios-state-8L3lgum6.mjs → ios-state-B2pES6Vs.mjs} +1 -1
- package/dist/{launch-verify-lTnWZikR.mjs → launch-verify-hskNcWkZ.mjs} +5 -5
- package/dist/{logs-BAaS7gS2.mjs → logs-1Ylc1Ri6.mjs} +13 -13
- package/dist/macos-Ck7OBMNY.mjs +2 -0
- package/dist/{macos-BIRQS90f.mjs → macos-DF6C7wUU.mjs} +118 -34
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +349 -47
- package/dist/{metro-g8NqiJp-.mjs → metro-Dh8T4Ytd.mjs} +5 -5
- package/dist/{metro-gateway-C-ijGI2F.mjs → metro-gateway-CEUw9RMH.mjs} +4 -4
- package/dist/{metro-store-CDDZHtPl.mjs → metro-store-BAHFcJm6.mjs} +16 -2
- package/dist/{named-ports-C8m8EQs2.mjs → named-ports-BFIz1Shz.mjs} +61 -6
- package/dist/{native-run-D1Q56rAD.mjs → native-run-B06FkmZx.mjs} +4 -4
- package/dist/{native-runtime-BEK171xQ.mjs → native-runtime-D_603JiC.mjs} +6 -6
- package/dist/{ndjson-PclOIwVY.mjs → ndjson-LGZAMsqa.mjs} +8 -4
- package/dist/offload-worker.d.mts +3 -17
- package/dist/offload-worker.mjs +10 -11
- package/dist/{ownership-DyRQru0q.mjs → ownership-D6Se7gg_.mjs} +3 -3
- package/dist/{page-QF_Ke10s.mjs → page-Bv9s2KwY.mjs} +1 -1
- package/dist/placement-log-BcPhRwR4.mjs +84 -0
- package/dist/{build-plan-BDsSi09V.mjs → plan-placement-CtxkCO54.mjs} +122 -48
- package/dist/{ports-4nYqxPWC.mjs → ports-BLTtfBq-.mjs} +3 -3
- package/dist/{prebuild-D7RUMkwN.mjs → prebuild-juCyreaR.mjs} +5 -5
- package/dist/preview-D5V07Nrl.mjs +987 -0
- package/dist/{rolldown-runtime-BsOwBuO_.mjs → process-identity-Biv3arCO.mjs} +11 -1
- package/dist/{project-D47Rh0ly.mjs → project-C3ChRLZy.mjs} +4 -68
- package/dist/projects-DD7dBTCj.mjs +92 -0
- package/dist/{pull-request-pxnDCQzn.mjs → pull-request-u4vp7zmK.mjs} +1 -1
- package/dist/pull-requests.mjs +1 -1
- package/dist/{recordings-BNgsD1Tr.mjs → recordings-BAWltsVt.mjs} +1 -1
- package/dist/{reload-DcRxj3qG.mjs → reload-DvyWzVjJ.mjs} +15 -15
- package/dist/{remote-cache-Ci4DQYYj.mjs → remote-cache-BGg7aGIZ.mjs} +5 -5
- package/dist/{run-CkE9y0nc.mjs → run-vhtDgpHO.mjs} +5 -5
- package/dist/{server-bare-BkrSxSsZ.mjs → server-bare-B9E7S1aR.mjs} +4 -5
- package/dist/server-expo-Db9HBUoa.mjs +2 -0
- package/dist/{server-expo-CHTyXD0G.mjs → server-expo-DoBHhuzK.mjs} +5 -6
- package/dist/{settings-SR9OmW9h.mjs → settings-Byp2AQ_E.mjs} +6 -5
- package/dist/{settings-Cfd-0r2d.mjs → settings-CQyMElEP.mjs} +24 -763
- package/dist/{settings-BBpMcDbD.mjs → settings-Djl-mpjX.mjs} +1 -1
- package/dist/settings.schema.json +126 -3
- package/dist/{simslim-BWNrc3M3.mjs → simslim-EHBQ2R4G.mjs} +7 -7
- package/dist/{slot-launch-DmjBmpQV.mjs → slot-launch-C1nqh4mu.mjs} +6 -6
- package/dist/{spawn-claims-D0XfSe8u.mjs → spawn-claims-Kqiifsk2.mjs} +1 -1
- package/dist/{spawn-entry-jw19m8Nl.mjs → spawn-entry-Dcb7sDUz.mjs} +1 -0
- package/dist/{stage-CzaiwFsI.mjs → stage-g_WqWeaE.mjs} +14 -3
- package/dist/{start-DUz3mYdb.mjs → start-D-IeOyoK.mjs} +19 -19
- package/dist/{start-AlfCPRVU.mjs → start-NTc1Ifqs.mjs} +1 -1
- package/dist/{state-PeQiJuIu.mjs → state-BG-aAk4k.mjs} +4 -4
- package/dist/{state-B4PQFXMW.d.mts → state-lKh8shBp.d.mts} +2 -3
- package/dist/{state-DyaNTgfR.mjs → state-xnqpx3AD.mjs} +2 -2
- package/dist/{stats-Bq4fJOdB.mjs → stats-DY6ekz8F.mjs} +5 -5
- package/dist/{status-DlKvVJBE.mjs → status-BEeL6IKz.mjs} +6 -4
- package/dist/{status-BA2pehwf.mjs → status-DCjZeE-K.mjs} +33 -34
- package/dist/{status-CzS4bPO9.mjs → status-Dcr0Qexd.mjs} +5 -5
- package/dist/{stim-desktop-Cnz8CPnl.mjs → stim-desktop-Behws_fi.mjs} +1 -1
- package/dist/{stim-installations-QMEI32v1.mjs → stim-installations-aR_WsNOA.mjs} +1 -1
- package/dist/{stop-BIiM49EY.mjs → stop-BGhKMOuH.mjs} +5 -5
- package/dist/{stop-DQIasgKp.mjs → stop-BTjs3xbc.mjs} +17 -18
- package/dist/{stop-zF1y04f2.mjs → stop-DIJtD2GL.mjs} +2 -2
- package/dist/supervisor-run.d.mts +24 -22
- package/dist/supervisor-run.mjs +21 -22
- package/dist/{support-CsJNVfOc.mjs → support-BaayeYCf.mjs} +7 -7
- package/dist/{support-WvD__tSV.mjs → support-Bwvbrq5-.mjs} +5 -5
- package/dist/{toolchain-DNyR3NPq.mjs → toolchain-Bnyd_K3A.mjs} +471 -22
- package/dist/{trigger-Bemu8ytw.mjs → trigger-CJMhwXe8.mjs} +5 -5
- package/dist/trigger-DWAq9hkw.mjs +2 -0
- package/dist/{warm-progress-DF4JRvYI.mjs → warm-progress-CjB-MP6H.mjs} +7 -7
- package/dist/web-B6_bFDn7.mjs +2 -0
- package/dist/{web-Dl0KSRHf.mjs → web-DTU0uiWj.mjs} +22 -22
- package/dist/web-run.mjs +10 -10
- package/dist/{workspace-state-DqcCbpE7.mjs → workspace-state-C59dqG-Z.mjs} +3 -3
- package/dist/{ownership-BMLqyBgJ.mjs → workspaces-xXItD8Dj.mjs} +577 -23
- package/dist/{worktree-j3IcFAI5.mjs → worktree-BJfnU6r5.mjs} +1 -1
- package/dist/{worktree-Be_7NLKy.mjs → worktree-BSYlofkq.mjs} +234 -35
- package/dist/worktree-CsKYexJM.mjs +753 -0
- package/package.json +10 -5
- package/dist/build-progress-D0WkjCPd.mjs +0 -1036
- package/dist/build-slots-41v_d2x9.mjs +0 -142
- package/dist/cli-CYXb29oE.mjs +0 -51
- package/dist/deps-iKw0eD4P.mjs +0 -438
- package/dist/errors-B6W7FkxQ.mjs +0 -15
- package/dist/idle-BXG__1BA.mjs +0 -176
- package/dist/in-use-CvGOUn-x.mjs +0 -130
- package/dist/preview-B-g9d7kV.mjs +0 -318
- package/dist/process-identity-BmRm1qV0.mjs +0 -12
- package/dist/server-expo-CeakhI8P.mjs +0 -2
- package/dist/state-BKa8wNN5.mjs +0 -148
- package/dist/stop-cause-rhmGfwvt.mjs +0 -97
- package/dist/trigger-CXts6qt1.mjs +0 -2
- package/dist/watchman-APYjXSQa.mjs +0 -48
- package/dist/workspace-process-lock-2mNzOlaB.mjs +0 -58
- package/dist/workspaces-Bcib97-6.mjs +0 -306
package/dist/state-BKa8wNN5.mjs
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { B as parseDeviceSlotKey, R as deviceSlotKey } from "./config-D0DbpZtM.mjs";
|
|
2
|
-
import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
3
|
-
import { C as workspaceStateFile, a as updateWorkspaceState, h as supervisorPidFile, o as withWorkspaceStateLock, r as readWorkspaceState, t as clearWorkspaceStateKey } from "./workspace-state-DqcCbpE7.mjs";
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
-
import { dirname } from "node:path";
|
|
6
|
-
//#region src/supervisor/state.ts
|
|
7
|
-
const MODE_BARE = "bare-inproc";
|
|
8
|
-
const MODE_EXPO = "expo-child";
|
|
9
|
-
function readMetroTunnel(root) {
|
|
10
|
-
const record = readWorkspaceState(root)?.metroTunnel;
|
|
11
|
-
if (!record || typeof record !== "object") return null;
|
|
12
|
-
const kind = record.kind;
|
|
13
|
-
const url = record.url;
|
|
14
|
-
if (typeof url !== "string" || url.length === 0) return null;
|
|
15
|
-
if (kind === "expo") return {
|
|
16
|
-
kind: "expo",
|
|
17
|
-
url
|
|
18
|
-
};
|
|
19
|
-
if (kind === "managed") {
|
|
20
|
-
const provider = record.provider;
|
|
21
|
-
const pid = record.pid;
|
|
22
|
-
const port = record.port;
|
|
23
|
-
const startedAt = record.startedAt;
|
|
24
|
-
const processToken = record.processToken;
|
|
25
|
-
const logFile = record.logFile;
|
|
26
|
-
if (provider !== "ngrok" && provider !== "cloudflared" && provider !== "tailscale" || typeof pid !== "number" || typeof port !== "number") return null;
|
|
27
|
-
return {
|
|
28
|
-
kind: "managed",
|
|
29
|
-
provider,
|
|
30
|
-
pid,
|
|
31
|
-
url,
|
|
32
|
-
port,
|
|
33
|
-
startedAt: typeof startedAt === "string" ? startedAt : "",
|
|
34
|
-
processToken: typeof processToken === "string" && processToken.length > 0 ? processToken : null,
|
|
35
|
-
...typeof logFile === "string" && logFile.length > 0 ? { logFile } : {}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
function parseWorkspaceLaunchRecord(value) {
|
|
41
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
42
|
-
const record = value;
|
|
43
|
-
if (typeof record.appId !== "string" || record.appId.length === 0) return null;
|
|
44
|
-
if (typeof record.deviceId !== "string" || record.deviceId.length === 0) return null;
|
|
45
|
-
if (record.metroPort !== null && typeof record.metroPort !== "number") return null;
|
|
46
|
-
if (typeof record.release !== "boolean") return null;
|
|
47
|
-
if (typeof record.launchedAt !== "string") return null;
|
|
48
|
-
return record;
|
|
49
|
-
}
|
|
50
|
-
function readWorkspaceLaunches(root) {
|
|
51
|
-
const launches = readWorkspaceState(root)?.launches;
|
|
52
|
-
if (!launches || typeof launches !== "object" || Array.isArray(launches)) return {};
|
|
53
|
-
const records = {};
|
|
54
|
-
for (const [key, value] of Object.entries(launches)) {
|
|
55
|
-
const record = parseWorkspaceLaunchRecord(value);
|
|
56
|
-
if (parseDeviceSlotKey(key) && record) records[key] = record;
|
|
57
|
-
}
|
|
58
|
-
return records;
|
|
59
|
-
}
|
|
60
|
-
function writeWorkspaceLaunch(root, platform, record, slot = "default") {
|
|
61
|
-
updateWorkspaceState(root, (state) => {
|
|
62
|
-
const launches = state.launches && typeof state.launches === "object" ? state.launches : {};
|
|
63
|
-
return {
|
|
64
|
-
...state,
|
|
65
|
-
launches: {
|
|
66
|
-
...launches,
|
|
67
|
-
[deviceSlotKey(platform, slot)]: record
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
function clearWorkspaceLaunches(root, slot) {
|
|
73
|
-
updateWorkspaceState(root, (state) => {
|
|
74
|
-
if (!state.launches || typeof state.launches !== "object") return state;
|
|
75
|
-
const launches = { ...state.launches };
|
|
76
|
-
delete launches[deviceSlotKey("ios", slot)];
|
|
77
|
-
delete launches[deviceSlotKey("android", slot)];
|
|
78
|
-
return {
|
|
79
|
-
...state,
|
|
80
|
-
launches
|
|
81
|
-
};
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
function readRemoteSession(root) {
|
|
85
|
-
const record = readWorkspaceState(root)?.remoteDevice;
|
|
86
|
-
if (!record || typeof record !== "object") return null;
|
|
87
|
-
const id = record.sessionId;
|
|
88
|
-
if (typeof id !== "string" || id.length === 0) return null;
|
|
89
|
-
const platform = record.platform;
|
|
90
|
-
const startedAt = record.startedAt;
|
|
91
|
-
const webPreviewUrl = record.webPreviewUrl;
|
|
92
|
-
const deviceType = record.deviceType;
|
|
93
|
-
return {
|
|
94
|
-
platform: platform === "ios" || platform === "android" ? platform : null,
|
|
95
|
-
sessionId: id,
|
|
96
|
-
startedAt: typeof startedAt === "string" ? startedAt : null,
|
|
97
|
-
webPreviewUrl: typeof webPreviewUrl === "string" && webPreviewUrl.length > 0 ? webPreviewUrl : null,
|
|
98
|
-
deviceType: typeof deviceType === "string" && deviceType.length > 0 ? deviceType : null
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
function readRemoteSessionId(root) {
|
|
102
|
-
return readRemoteSession(root)?.sessionId ?? null;
|
|
103
|
-
}
|
|
104
|
-
function clearRemoteSession(root, expectedSessionId) {
|
|
105
|
-
clearWorkspaceStateKey(root, "remoteDevice", (value) => {
|
|
106
|
-
if (typeof value !== "object" || value === null) return false;
|
|
107
|
-
return value.sessionId === expectedSessionId;
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
function clearWorkspaceSupervisor(root, expected) {
|
|
111
|
-
return withWorkspaceStateLock(root, () => {
|
|
112
|
-
const current = readWorkspaceState(root)?.supervisor;
|
|
113
|
-
if (current && expected !== void 0 && !(0, process_identity_exports.sameProcessRecord)(current, expected)) return false;
|
|
114
|
-
clearWorkspaceStateKey(root, "supervisor", () => true);
|
|
115
|
-
clearExpoMetroTunnel(root);
|
|
116
|
-
if (expected === void 0 || readPidFile(root) === expected?.pid) rmSync(supervisorPidFile(root), { force: true });
|
|
117
|
-
return true;
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
function clearExpoMetroTunnel(root) {
|
|
121
|
-
clearWorkspaceStateKey(root, "metroTunnel", (value) => {
|
|
122
|
-
return typeof value === "object" && value !== null && value.kind === "expo";
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
function clearManagedMetroTunnel(root, expected) {
|
|
126
|
-
if (!existsSync(workspaceStateFile(root))) return true;
|
|
127
|
-
return clearWorkspaceStateKey(root, "metroTunnel", (value) => {
|
|
128
|
-
if (typeof value !== "object" || value === null) return false;
|
|
129
|
-
const record = value;
|
|
130
|
-
return record.kind === "managed" && record.provider === expected.provider && record.pid === expected.pid && record.url === expected.url && record.port === expected.port && record.startedAt === expected.startedAt && (record.processToken ?? null) === (expected.processToken ?? null) && (record.logFile ?? null) === (expected.logFile ?? null);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
function writePidFile(root, pid) {
|
|
134
|
-
const file = supervisorPidFile(root);
|
|
135
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
136
|
-
writeFileSync(file, `${pid}\n`);
|
|
137
|
-
return file;
|
|
138
|
-
}
|
|
139
|
-
function readPidFile(root) {
|
|
140
|
-
try {
|
|
141
|
-
const pid = parseInt(readFileSync(supervisorPidFile(root), "utf-8").trim(), 10);
|
|
142
|
-
return Number.isFinite(pid) ? pid : null;
|
|
143
|
-
} catch {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
//#endregion
|
|
148
|
-
export { clearRemoteSession as a, readMetroTunnel as c, readRemoteSessionId as d, readWorkspaceLaunches as f, clearManagedMetroTunnel as i, readPidFile as l, writeWorkspaceLaunch as m, MODE_EXPO as n, clearWorkspaceLaunches as o, writePidFile as p, clearExpoMetroTunnel as r, clearWorkspaceSupervisor as s, MODE_BARE as t, readRemoteSession as u };
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
2
|
-
import { c as writeWorkspaceState, t as clearWorkspaceStateKey, x as workspaceLogsDir$1 } from "./workspace-state-DqcCbpE7.mjs";
|
|
3
|
-
import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
6
|
-
import { DEV_SERVER_STOP_REQUEST_KEY, readDevServerStop, readDevServerStopRequest } from "@stim-cli/core/state";
|
|
7
|
-
//#region src/supervisor/stop-cause.ts
|
|
8
|
-
function requestDevServerStop(root, processToken, requester) {
|
|
9
|
-
if (!processToken) return;
|
|
10
|
-
try {
|
|
11
|
-
writeWorkspaceState(root, { [DEV_SERVER_STOP_REQUEST_KEY]: {
|
|
12
|
-
processToken,
|
|
13
|
-
by: requester.by,
|
|
14
|
-
pid: process.pid,
|
|
15
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16
|
-
...requester.workspace ? { workspace: requester.workspace } : {}
|
|
17
|
-
} });
|
|
18
|
-
} catch {}
|
|
19
|
-
}
|
|
20
|
-
function withdrawDevServerStopRequest(root, processToken) {
|
|
21
|
-
if (!processToken) return;
|
|
22
|
-
try {
|
|
23
|
-
clearWorkspaceStateKey(root, DEV_SERVER_STOP_REQUEST_KEY, (value) => {
|
|
24
|
-
return readDevServerStopRequest({ [DEV_SERVER_STOP_REQUEST_KEY]: value })?.processToken === processToken;
|
|
25
|
-
});
|
|
26
|
-
} catch {}
|
|
27
|
-
}
|
|
28
|
-
function devServerStopRecord(trigger, request, at) {
|
|
29
|
-
if (request) return {
|
|
30
|
-
reason: "requested",
|
|
31
|
-
at,
|
|
32
|
-
by: request.by,
|
|
33
|
-
byPid: request.pid,
|
|
34
|
-
...request.workspace ? { byWorkspace: request.workspace } : {}
|
|
35
|
-
};
|
|
36
|
-
return trigger.kind === "signal" ? {
|
|
37
|
-
reason: "signal",
|
|
38
|
-
at,
|
|
39
|
-
signal: trigger.signal
|
|
40
|
-
} : {
|
|
41
|
-
reason: "server-exited",
|
|
42
|
-
at,
|
|
43
|
-
mode: trigger.mode,
|
|
44
|
-
code: trigger.code,
|
|
45
|
-
signal: trigger.signal
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function describeDevServerStop(record) {
|
|
49
|
-
if (record.reason === "idle") return `idle for ${record.idleMinutes} minutes (metro.idleStopMinutes)`;
|
|
50
|
-
if (record.reason === "requested") return `stop requested by ${record.by} (pid ${record.byPid}${record.byWorkspace ? ` in ${record.byWorkspace}` : ""})`;
|
|
51
|
-
if (record.reason === "signal") return `received ${record.signal} with no Stim stop request recorded, so it likely came from outside Stim`;
|
|
52
|
-
const detail = record.signal ? `signal ${record.signal}` : `exit code ${record.code ?? "unknown"}`;
|
|
53
|
-
const expoSignal = record.mode === "expo-child" && record.code === 0 ? "; Expo CLI also exits 0 on SIGTERM, and no Stim stop request was recorded" : "";
|
|
54
|
-
return `the ${record.mode} dev server exited unexpectedly (${detail})${expoSignal}`;
|
|
55
|
-
}
|
|
56
|
-
function devServerStopLevel(record) {
|
|
57
|
-
if (record.reason === "server-exited") return "error";
|
|
58
|
-
return record.reason === "signal" ? "warn" : "info";
|
|
59
|
-
}
|
|
60
|
-
/** The log line for a recorded supervisor whose process is proven gone, or null while it may still run. */
|
|
61
|
-
function vanishedSupervisorMessage(record) {
|
|
62
|
-
if (!record || typeof record.pid !== "number") return null;
|
|
63
|
-
const identity = (0, process_identity_exports.inspectProcessIdentity)(record);
|
|
64
|
-
if (identity !== "gone" && identity !== "different") return null;
|
|
65
|
-
const started = typeof record.startedAt === "string" ? ` (started ${record.startedAt})` : "";
|
|
66
|
-
return `supervisor pid ${record.pid}${started} ${VANISHED}`;
|
|
67
|
-
}
|
|
68
|
-
const VANISHED = "is gone and recorded no cause: usually SIGKILL, a crash or a machine restart";
|
|
69
|
-
function logVanishedSupervisor(root, record) {
|
|
70
|
-
const msg = vanishedSupervisorMessage(record);
|
|
71
|
-
if (!msg) return;
|
|
72
|
-
const writer = createNdjsonWriter(join(workspaceLogsDir$1(root), "metro.ndjson"), { maxBytes: LOG_ROTATE_BYTES });
|
|
73
|
-
writer.write({
|
|
74
|
-
src: "metro",
|
|
75
|
-
level: "warn",
|
|
76
|
-
event: "supervisor_vanished",
|
|
77
|
-
msg
|
|
78
|
-
});
|
|
79
|
-
writer.close();
|
|
80
|
-
}
|
|
81
|
-
/** The recorded stop, else a vanished supervisor when status proved the recorded one gone. */
|
|
82
|
-
function metroLastStop(state, supervisor) {
|
|
83
|
-
const recorded = readDevServerStop(state);
|
|
84
|
-
if (recorded) return recorded;
|
|
85
|
-
if (supervisor?.status !== "stale" || typeof supervisor.pid !== "number") return null;
|
|
86
|
-
const startedAt = typeof supervisor.startedAt === "string" ? supervisor.startedAt : null;
|
|
87
|
-
return {
|
|
88
|
-
reason: "vanished",
|
|
89
|
-
pid: supervisor.pid,
|
|
90
|
-
startedAt
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function describeMetroLastStop(stop) {
|
|
94
|
-
return stop.reason === "vanished" ? `supervisor pid ${stop.pid} ${VANISHED}` : describeDevServerStop(stop);
|
|
95
|
-
}
|
|
96
|
-
//#endregion
|
|
97
|
-
export { logVanishedSupervisor as a, vanishedSupervisorMessage as c, devServerStopRecord as i, withdrawDevServerStopRequest as l, describeMetroLastStop as n, metroLastStop as o, devServerStopLevel as r, requestDevServerStop as s, describeDevServerStop as t };
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
-
//#region src/watchman.ts
|
|
3
|
-
/** Runs one watchman command with `--no-spawn`, so Stim never starts a daemon, and parses its JSON answer. */
|
|
4
|
-
const runWatchman = async (args, timeoutMs) => JSON.parse(await getExecutor().runFileAsync("watchman", ["--no-spawn", ...args], { timeoutMs }));
|
|
5
|
-
function parseWatchRoots(payload) {
|
|
6
|
-
const roots = payload?.roots;
|
|
7
|
-
if (!Array.isArray(roots)) return null;
|
|
8
|
-
return roots.filter((root) => typeof root === "string");
|
|
9
|
-
}
|
|
10
|
-
function parseSubscriberNames(payload) {
|
|
11
|
-
if (!payload || typeof payload !== "object" || "error" in payload) return null;
|
|
12
|
-
const subscribers = payload.subscribers;
|
|
13
|
-
if (subscribers === void 0) return [];
|
|
14
|
-
if (!Array.isArray(subscribers)) return null;
|
|
15
|
-
const names = [];
|
|
16
|
-
for (const subscriber of subscribers) {
|
|
17
|
-
const name = subscriber?.info?.name;
|
|
18
|
-
if (typeof name !== "string") return null;
|
|
19
|
-
names.push(name);
|
|
20
|
-
}
|
|
21
|
-
return names;
|
|
22
|
-
}
|
|
23
|
-
function parseTriggerCount(payload) {
|
|
24
|
-
const triggers = payload?.triggers;
|
|
25
|
-
return Array.isArray(triggers) ? triggers.length : null;
|
|
26
|
-
}
|
|
27
|
-
function parseWatchmanPid(payload) {
|
|
28
|
-
const pid = payload?.pid;
|
|
29
|
-
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
30
|
-
}
|
|
31
|
-
/** The connected clients in a `debug-status` answer, or null when the answer does not list them. */
|
|
32
|
-
function parseWatchmanClients(payload) {
|
|
33
|
-
if (!payload || typeof payload !== "object" || "error" in payload) return null;
|
|
34
|
-
const clients = payload.clients;
|
|
35
|
-
if (!Array.isArray(clients)) return null;
|
|
36
|
-
const parsed = [];
|
|
37
|
-
for (const client of clients) {
|
|
38
|
-
const peer = client?.peer;
|
|
39
|
-
if (typeof peer?.pid !== "number") return null;
|
|
40
|
-
parsed.push({
|
|
41
|
-
pid: peer.pid,
|
|
42
|
-
name: typeof peer.name === "string" ? peer.name : null
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return parsed;
|
|
46
|
-
}
|
|
47
|
-
//#endregion
|
|
48
|
-
export { parseWatchmanPid as a, parseWatchmanClients as i, parseTriggerCount as n, runWatchman as o, parseWatchRoots as r, parseSubscriberNames as t };
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
2
|
-
import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-D0XfSe8u.mjs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { setTimeout } from "node:timers/promises";
|
|
5
|
-
//#region src/engine/workspace-process-lock.ts
|
|
6
|
-
const DEFAULT_WAIT_MS = 6e4;
|
|
7
|
-
const POLL_MS = 25;
|
|
8
|
-
function workspaceProcessLockError(err) {
|
|
9
|
-
const code = err?.code;
|
|
10
|
-
if (code === "STIM_LOCK_REFUSED") return "refused";
|
|
11
|
-
if (code === "STIM_LOCK_TIMEOUT") return "timeout";
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
function workspaceProcessLockPath(root, name, external) {
|
|
15
|
-
return external ? join(root, `${name}.lock`) : join(root, ".stim", `${name}.lock`);
|
|
16
|
-
}
|
|
17
|
-
async function withWorkspaceProcessLock(root, name, fn, { now = Date.now, signal, sleep = (ms) => setTimeout(ms, void 0, { signal }), waitMs = DEFAULT_WAIT_MS, ownerPurpose, details = {}, onHeld, rejectOwnerPurposes = [], external = false, declareSpawns = false } = {}) {
|
|
18
|
-
const path = workspaceProcessLockPath(root, name, external);
|
|
19
|
-
const deadline = now() + waitMs;
|
|
20
|
-
for (;;) {
|
|
21
|
-
signal?.throwIfAborted();
|
|
22
|
-
const attempt = (0, ownership_claim_exports.tryAcquireClaim)({
|
|
23
|
-
root: path,
|
|
24
|
-
mode: "exclusive",
|
|
25
|
-
label: `${name} lock`,
|
|
26
|
-
details: ownerPurpose ? {
|
|
27
|
-
...details,
|
|
28
|
-
purpose: ownerPurpose
|
|
29
|
-
} : details
|
|
30
|
-
});
|
|
31
|
-
if (attempt.pending) (0, ownership_claim_exports.releaseClaim)(attempt.pending);
|
|
32
|
-
if (attempt.acquired) {
|
|
33
|
-
if (declareSpawns) declareSpawnsOn(attempt.acquired);
|
|
34
|
-
try {
|
|
35
|
-
return await fn(attempt.acquired);
|
|
36
|
-
} finally {
|
|
37
|
-
stopDeclaringSpawnsOn(attempt.acquired);
|
|
38
|
-
(0, ownership_claim_exports.releaseClaim)(attempt.acquired);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const holder = attempt.held ?? attempt.waitingFor?.[0];
|
|
42
|
-
const purpose = holder?.details.purpose;
|
|
43
|
-
if (typeof purpose === "string" && rejectOwnerPurposes.includes(purpose)) {
|
|
44
|
-
const error = /* @__PURE__ */ new Error(`The ${name} lock at ${path} is held for ${purpose}.`);
|
|
45
|
-
error.code = "STIM_LOCK_REFUSED";
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
if (holder && onHeld) await onHeld(holder);
|
|
49
|
-
if (now() >= deadline) {
|
|
50
|
-
const error = /* @__PURE__ */ new Error(`Timed out waiting for the ${name} lock at ${path}.`);
|
|
51
|
-
error.code = "STIM_LOCK_TIMEOUT";
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
54
|
-
await sleep(POLL_MS);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
//#endregion
|
|
58
|
-
export { workspaceProcessLockError as n, workspaceProcessLockPath as r, withWorkspaceProcessLock as t };
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { M as isOnMountedVolume, N as listMountedVolumes, P as measuredDirectorySize, _ as loadConfig$1, d as getConfigDir, g as isPathPrefix, j as formatBytes } from "./config-D0DbpZtM.mjs";
|
|
2
|
-
import { S as workspaceName, s as workspaceLastUsed } from "./workspace-state-DqcCbpE7.mjs";
|
|
3
|
-
import { i as recordGcResult, n as withIdleWorkspace, o as canonicalPath, r as workspaceInUse, t as emptyWorkspaceDir } from "./in-use-CvGOUn-x.mjs";
|
|
4
|
-
import { h as teardownOwnedBrowser } from "./ownership-BMLqyBgJ.mjs";
|
|
5
|
-
import { existsSync, lstatSync, readdirSync, rmSync, statSync } from "fs";
|
|
6
|
-
import { basename, isAbsolute, join, relative } from "path";
|
|
7
|
-
import { isJsonObject, readJsonFile } from "@stim-cli/core/state";
|
|
8
|
-
import chalk from "chalk";
|
|
9
|
-
//#region src/commands/gc/workspaces.ts
|
|
10
|
-
function workspacesRoot() {
|
|
11
|
-
return join(getConfigDir(), "workspaces");
|
|
12
|
-
}
|
|
13
|
-
function isInsideWorkspaces(dir) {
|
|
14
|
-
const rel = relative(canonicalPath(workspacesRoot()), canonicalPath(dir));
|
|
15
|
-
return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
|
|
16
|
-
}
|
|
17
|
-
function readRecordedRoot(dir, name) {
|
|
18
|
-
let parsed;
|
|
19
|
-
try {
|
|
20
|
-
parsed = readJsonFile(join(dir, "workspace.json"));
|
|
21
|
-
} catch (error) {
|
|
22
|
-
return {
|
|
23
|
-
projectRoot: null,
|
|
24
|
-
problem: error?.code === "ENOENT" ? "it has no workspace.json" : "its workspace.json does not parse"
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
const projectRoot = isJsonObject(parsed) ? parsed.projectRoot : void 0;
|
|
28
|
-
if (typeof projectRoot !== "string" || !isAbsolute(projectRoot)) return {
|
|
29
|
-
projectRoot: null,
|
|
30
|
-
problem: "its workspace.json records no absolute project root"
|
|
31
|
-
};
|
|
32
|
-
if (workspaceName(projectRoot) !== name) return {
|
|
33
|
-
projectRoot: null,
|
|
34
|
-
problem: `its workspace.json records ${projectRoot}, whose workspace directory has another name`
|
|
35
|
-
};
|
|
36
|
-
return {
|
|
37
|
-
projectRoot,
|
|
38
|
-
problem: null
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
function listWorkspaceDirs() {
|
|
42
|
-
const root = workspacesRoot();
|
|
43
|
-
let names;
|
|
44
|
-
try {
|
|
45
|
-
names = readdirSync(root).toSorted();
|
|
46
|
-
} catch {
|
|
47
|
-
return [];
|
|
48
|
-
}
|
|
49
|
-
const entries = [];
|
|
50
|
-
for (const name of names) {
|
|
51
|
-
const dir = join(root, name);
|
|
52
|
-
try {
|
|
53
|
-
if (!statSync(dir).isDirectory()) continue;
|
|
54
|
-
} catch {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
entries.push({
|
|
58
|
-
dir,
|
|
59
|
-
...readRecordedRoot(dir, name)
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
return entries;
|
|
63
|
-
}
|
|
64
|
-
function classifyWorkspaceDirs(entries, { registryKeys, exists, isMounted, inUse }) {
|
|
65
|
-
const orphaned = [];
|
|
66
|
-
const skipped = [];
|
|
67
|
-
for (const { dir, projectRoot, problem } of entries) {
|
|
68
|
-
if (projectRoot === null) {
|
|
69
|
-
skipped.push({
|
|
70
|
-
dir,
|
|
71
|
-
reason: `workspace directory not resolved: ${problem ?? "unknown project root"}`
|
|
72
|
-
});
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
const present = exists(projectRoot);
|
|
76
|
-
if (present === null) {
|
|
77
|
-
skipped.push({
|
|
78
|
-
dir,
|
|
79
|
-
reason: `cannot tell whether its project root ${projectRoot} still exists`
|
|
80
|
-
});
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
if (present) continue;
|
|
84
|
-
if (registryKeys.some((key) => isPathPrefix(projectRoot, key))) continue;
|
|
85
|
-
if (!isMounted(projectRoot)) {
|
|
86
|
-
skipped.push({
|
|
87
|
-
dir,
|
|
88
|
-
reason: `the volume of its project root ${projectRoot} is not mounted`
|
|
89
|
-
});
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
const reasons = inUse(projectRoot);
|
|
93
|
-
if (reasons.length) {
|
|
94
|
-
skipped.push({
|
|
95
|
-
dir,
|
|
96
|
-
reason: `its project root ${projectRoot} is gone, but ${reasons.join("; ")}`
|
|
97
|
-
});
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
orphaned.push({
|
|
101
|
-
dir,
|
|
102
|
-
projectRoot
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
orphaned,
|
|
107
|
-
skipped
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function rootPresence(path) {
|
|
111
|
-
try {
|
|
112
|
-
lstatSync(path);
|
|
113
|
-
return true;
|
|
114
|
-
} catch (error) {
|
|
115
|
-
const code = error?.code;
|
|
116
|
-
return code === "ENOENT" || code === "ENOTDIR" ? false : null;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function collectOrphanedWorkspaces(registryKeys, mountedVolumes, { measure = true } = {}) {
|
|
120
|
-
const classified = classifyWorkspaceDirs(listWorkspaceDirs(), {
|
|
121
|
-
registryKeys,
|
|
122
|
-
exists: rootPresence,
|
|
123
|
-
isMounted: (path) => isOnMountedVolume(path, mountedVolumes),
|
|
124
|
-
inUse: (root) => workspaceInUse(root)
|
|
125
|
-
});
|
|
126
|
-
return {
|
|
127
|
-
orphaned: measure ? classified.orphaned.map((entry) => Object.assign({}, entry, { bytes: sizeOf(entry.dir) })) : classified.orphaned,
|
|
128
|
-
skipped: classified.skipped
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
const REBUILD_COST = "The next build of an unchanged app installs from the shared build cache; after a native change the compilation cache speeds the rebuild, but on React Native 0.86 Swift does not use it (explicit modules are off), so that build recompiles Swift. The next stim macos in a cleared workspace is a full Swift build.";
|
|
132
|
-
const WORKSPACE_OUTPUT_DIRS = [
|
|
133
|
-
"derived-data",
|
|
134
|
-
"gradle-build",
|
|
135
|
-
"android-cas",
|
|
136
|
-
"cache-provider"
|
|
137
|
-
];
|
|
138
|
-
const DAY_MS = 864e5;
|
|
139
|
-
function planWorkspaceOutputs(entries, { olderThan, now }) {
|
|
140
|
-
return entries.map(({ dir, projectRoot, problem, bytes, lastUsed, inUse }) => {
|
|
141
|
-
const idleDays = Number.isFinite(lastUsed) ? Math.max(0, Math.floor((now - lastUsed) / DAY_MS)) : null;
|
|
142
|
-
const [keptCode, keptReason] = projectRoot === null ? ["unresolved", `workspace directory not resolved: ${problem ?? "unknown project root"}`] : inUse.length ? ["in-use", `in use: ${inUse.join("; ")}`] : olderThan === null ? [null, null] : idleDays === null ? ["last-use-unknown", "its last use is unknown"] : idleDays < olderThan ? ["recently-used", `used ${idleDays}d ago, within --older-than ${olderThan}`] : [null, null];
|
|
143
|
-
return {
|
|
144
|
-
dir,
|
|
145
|
-
projectRoot,
|
|
146
|
-
bytes,
|
|
147
|
-
idleDays,
|
|
148
|
-
willClear: keptCode === null,
|
|
149
|
-
keptCode,
|
|
150
|
-
keptReason
|
|
151
|
-
};
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
const SIZE_TIMEOUT_MS = 6e4;
|
|
155
|
-
function sizeOf(dir, timeoutMs = SIZE_TIMEOUT_MS) {
|
|
156
|
-
return measuredDirectorySize(dir, { timeoutMs });
|
|
157
|
-
}
|
|
158
|
-
function outputPaths(dir) {
|
|
159
|
-
const paths = WORKSPACE_OUTPUT_DIRS.map((name) => join(dir, name)).filter((path) => existsSync(path));
|
|
160
|
-
const macos = join(dir, "macos");
|
|
161
|
-
try {
|
|
162
|
-
if (!lstatSync(macos).isDirectory()) return paths;
|
|
163
|
-
for (const entry of readdirSync(macos, { withFileTypes: true })) if (entry.name === "build" || entry.name.endsWith(".app") || entry.name.startsWith("staging-") && entry.isDirectory()) paths.push(join(macos, entry.name));
|
|
164
|
-
} catch {}
|
|
165
|
-
return paths;
|
|
166
|
-
}
|
|
167
|
-
function outputBytes(paths, timeoutMs) {
|
|
168
|
-
let total = 0;
|
|
169
|
-
for (const path of paths) {
|
|
170
|
-
const size = sizeOf(path, timeoutMs);
|
|
171
|
-
if (size === null) return null;
|
|
172
|
-
total += size;
|
|
173
|
-
}
|
|
174
|
-
return total;
|
|
175
|
-
}
|
|
176
|
-
function collectWorkspaceOutputs({ olderThan, now, exclude = [], measure = true, sizeTimeoutMs = SIZE_TIMEOUT_MS }) {
|
|
177
|
-
const mountedVolumes = listMountedVolumes();
|
|
178
|
-
const entries = listWorkspaceDirs().filter((entry) => !exclude.includes(entry.dir)).filter((entry) => entry.projectRoot === null || isOnMountedVolume(entry.projectRoot, mountedVolumes)).map((entry) => Object.assign({}, entry, { paths: outputPaths(entry.dir) })).filter((entry) => entry.paths.length > 0).map(({ paths, ...entry }) => Object.assign({}, entry, { bytes: measure ? outputBytes(paths, sizeTimeoutMs) : null })).map((entry) => Object.assign({}, entry, {
|
|
179
|
-
lastUsed: entry.projectRoot === null ? NaN : workspaceLastUsed(entry.projectRoot),
|
|
180
|
-
inUse: entry.projectRoot === null ? [] : workspaceInUse(entry.projectRoot)
|
|
181
|
-
}));
|
|
182
|
-
return {
|
|
183
|
-
root: workspacesRoot(),
|
|
184
|
-
workspaces: planWorkspaceOutputs(entries, {
|
|
185
|
-
olderThan,
|
|
186
|
-
now
|
|
187
|
-
})
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
async function clearWorkspaceOutputs(report, { olderThan, now = Date.now() }) {
|
|
191
|
-
let failures = 0;
|
|
192
|
-
let cleared = 0;
|
|
193
|
-
const clearedRoots = [];
|
|
194
|
-
for (const entry of report.workspaces) {
|
|
195
|
-
const root = entry.projectRoot;
|
|
196
|
-
if (!entry.willClear || root === null) {
|
|
197
|
-
if (entry.keptReason) {
|
|
198
|
-
console.log(chalk.dim(`Kept the build outputs of ${root ?? entry.dir}: ${entry.keptReason}`));
|
|
199
|
-
recordGcResult("workspaceOutputs", "kept", root ?? entry.dir, {
|
|
200
|
-
bytes: entry.bytes,
|
|
201
|
-
detail: entry.keptReason
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
let run;
|
|
207
|
-
try {
|
|
208
|
-
run = await withIdleWorkspace(root, () => {
|
|
209
|
-
const [again] = planWorkspaceOutputs([{
|
|
210
|
-
...entry,
|
|
211
|
-
problem: null,
|
|
212
|
-
lastUsed: workspaceLastUsed(root),
|
|
213
|
-
inUse: []
|
|
214
|
-
}], {
|
|
215
|
-
olderThan,
|
|
216
|
-
now
|
|
217
|
-
});
|
|
218
|
-
if (again?.keptReason) return again.keptReason;
|
|
219
|
-
for (const path of outputPaths(entry.dir)) rmSync(path, {
|
|
220
|
-
recursive: true,
|
|
221
|
-
force: true
|
|
222
|
-
});
|
|
223
|
-
return null;
|
|
224
|
-
}, { purpose: "gc" });
|
|
225
|
-
} catch (error) {
|
|
226
|
-
failures++;
|
|
227
|
-
console.log(chalk.red(`Could not clear the build outputs of ${root}: ${error?.message || String(error)}`));
|
|
228
|
-
recordGcResult("workspaceOutputs", "failed", root, {
|
|
229
|
-
bytes: entry.bytes,
|
|
230
|
-
detail: error?.message || String(error)
|
|
231
|
-
});
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
const kept = run.ran ? run.value : `in use: ${run.reasons.join("; ")}`;
|
|
235
|
-
if (kept) {
|
|
236
|
-
console.log(chalk.yellow(`Kept the build outputs of ${root}: ${kept}`));
|
|
237
|
-
recordGcResult("workspaceOutputs", "kept", root, {
|
|
238
|
-
bytes: entry.bytes,
|
|
239
|
-
detail: kept
|
|
240
|
-
});
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
cleared += entry.bytes ?? 0;
|
|
244
|
-
clearedRoots.push(root);
|
|
245
|
-
console.log(chalk.green(`Cleared the build outputs of ${root} (${sizeText(entry.bytes)})`));
|
|
246
|
-
recordGcResult("workspaceOutputs", "done", root, { bytes: entry.bytes });
|
|
247
|
-
}
|
|
248
|
-
if (cleared) console.log(chalk.dim(`Cleared ${formatBytes(cleared)} of workspace build outputs. ${REBUILD_COST}`));
|
|
249
|
-
return {
|
|
250
|
-
failures,
|
|
251
|
-
cleared: clearedRoots
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
function stillOrphaned({ dir, projectRoot }) {
|
|
255
|
-
if (readRecordedRoot(dir, basename(dir)).projectRoot !== projectRoot || rootPresence(projectRoot) !== false || !isOnMountedVolume(projectRoot)) return false;
|
|
256
|
-
return !Object.keys(loadConfig$1()?.projects ?? {}).some((key) => isPathPrefix(projectRoot, key));
|
|
257
|
-
}
|
|
258
|
-
async function deleteOrphanedWorkspaces(orphaned) {
|
|
259
|
-
let failures = 0;
|
|
260
|
-
for (const entry of orphaned) {
|
|
261
|
-
if (!existsSync(entry.dir)) continue;
|
|
262
|
-
let run;
|
|
263
|
-
try {
|
|
264
|
-
run = await withIdleWorkspace(entry.projectRoot, async () => {
|
|
265
|
-
if (!stillOrphaned(entry)) return false;
|
|
266
|
-
const browser = await teardownOwnedBrowser(entry.projectRoot, { deleteProfile: true });
|
|
267
|
-
if (browser.status === "failed" || browser.status === "skipped") throw new Error(`its owned Chrome profile was kept: ${browser.reason}`);
|
|
268
|
-
emptyWorkspaceDir(entry.dir);
|
|
269
|
-
return true;
|
|
270
|
-
}, { purpose: "gc" });
|
|
271
|
-
} catch (error) {
|
|
272
|
-
failures++;
|
|
273
|
-
console.log(chalk.red(`Could not remove ${entry.dir}: ${error?.message || error}`));
|
|
274
|
-
recordGcResult("workspaceDirectory", "failed", entry.dir, {
|
|
275
|
-
bytes: entry.bytes ?? null,
|
|
276
|
-
detail: error?.message || String(error)
|
|
277
|
-
});
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
if (!run.ran) {
|
|
281
|
-
console.log(chalk.yellow(`Kept ${entry.dir}: ${run.reasons.join("; ")}`));
|
|
282
|
-
recordGcResult("workspaceDirectory", "kept", entry.dir, {
|
|
283
|
-
bytes: entry.bytes ?? null,
|
|
284
|
-
detail: run.reasons.join("; ")
|
|
285
|
-
});
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
if (!run.value) {
|
|
289
|
-
console.log(chalk.yellow(`Kept ${entry.dir}: it can no longer be confirmed orphaned.`));
|
|
290
|
-
recordGcResult("workspaceDirectory", "kept", entry.dir, {
|
|
291
|
-
bytes: entry.bytes ?? null,
|
|
292
|
-
detail: "it can no longer be confirmed orphaned"
|
|
293
|
-
});
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
const size = entry.bytes === void 0 ? "" : ` (${sizeText(entry.bytes)})`;
|
|
297
|
-
console.log(chalk.green(`Removed the orphaned workspace directory ${entry.dir}${size}`));
|
|
298
|
-
recordGcResult("workspaceDirectory", "done", entry.dir, { bytes: entry.bytes ?? null });
|
|
299
|
-
}
|
|
300
|
-
return failures;
|
|
301
|
-
}
|
|
302
|
-
function sizeText(bytes) {
|
|
303
|
-
return bytes === null ? "size unknown" : formatBytes(bytes);
|
|
304
|
-
}
|
|
305
|
-
//#endregion
|
|
306
|
-
export { collectWorkspaceOutputs as a, listWorkspaceDirs as c, collectOrphanedWorkspaces as i, rootPresence as l, WORKSPACE_OUTPUT_DIRS as n, deleteOrphanedWorkspaces as o, clearWorkspaceOutputs as r, isInsideWorkspaces as s, REBUILD_COST as t, sizeText as u };
|