stim 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{activity-DfVKZTEB.mjs → activity-B2-kb7k0.mjs} +281 -41
- package/dist/{android-BHfAu2mf.mjs → android-CYmq0jNi.mjs} +2 -2
- package/dist/{android-CD8pr8Q2.mjs → android-Cu_L4RpL.mjs} +524 -412
- package/dist/{android-qx_31wJo.mjs → android-Db2eEMaf.mjs} +152 -65
- package/dist/android-cas-PnKfAdB2.mjs +167 -0
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{app-install-CDFY2nUL.mjs → app-install-CAAplXAt.mjs} +162 -173
- package/dist/{budget-E5o91NR1.mjs → budget-CMiqghig.mjs} +1048 -77
- package/dist/{build-plan-BTa93o_r.mjs → build-plan-aeGMFX7e.mjs} +193 -650
- package/dist/build-progress-C2Jv1AtA.mjs +872 -0
- package/dist/build-slots-Df1ApSuH.mjs +127 -0
- package/dist/{cache-manifest-DWPF4RKJ.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-B5hWgQJS.mjs → chrome-BrcVWQyD.mjs} +4 -4
- package/dist/cli-0cX5s4NM.mjs +45 -0
- package/dist/cli.mjs +6 -42
- package/dist/client-C2IS36Qf.mjs +1333 -0
- package/dist/collector-run.mjs +8 -7
- package/dist/{command-output-BIL7rlX7.mjs → command-output-CliHHn7a.mjs} +1 -1
- package/dist/{config-0jCcMM0E.mjs → config-D0DbpZtM.mjs} +29 -29
- package/dist/{created-devices-Cd558h31.mjs → created-devices-BwVb3liH.mjs} +2 -2
- package/dist/{dependency-state-DNN0yfx6.mjs → dependency-state-BmsjKZ2H.mjs} +2 -2
- package/dist/{deps-2Wo81np9.mjs → deps-BFlKbOIp.mjs} +3 -3
- package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
- package/dist/dev-client-CjzLoNs0.mjs +80 -0
- package/dist/{device-Cf7vl-so.mjs → device-BZ1IyS5A.mjs} +7 -7
- package/dist/device-capacity-DMuKC7nx.mjs +136 -0
- package/dist/device-host-worker.d.mts +1 -0
- package/dist/device-host-worker.mjs +769 -0
- package/dist/device-ios-DMQBUPus.mjs +381 -0
- package/dist/{device-lease-CL9dZf73.mjs → device-lease-W5Pi1q38.mjs} +43 -36
- package/dist/{device-pool-MuoiyRcu.mjs → device-pool-B2r38YjS.mjs} +4 -4
- package/dist/{device-remote-DT9ngZiD.mjs → device-remote-9ulPsdhY.mjs} +68 -162
- package/dist/{doctor-D2iysNNH.mjs → doctor-BcE5xsBn.mjs} +191 -99
- package/dist/{error-diagnostics-BoiOhck8.mjs → error-diagnostics-Cb0P1WLS.mjs} +12 -11
- package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
- package/dist/{gc-eA-PRBX8.mjs → gc-BuL1Genr.mjs} +430 -102
- package/dist/{android-cas-B9Kv9aIy.mjs → gradle-CmdOBq1d.mjs} +8 -294
- package/dist/{guide-BfZ0OmiP.mjs → guide-cCSGRFd3.mjs} +2052 -240
- package/dist/{guide-status-BaMYu55M.mjs → guide-status-CIoWK6mG.mjs} +3 -3
- package/dist/hosted-macos-DwowNU7W.mjs +447 -0
- package/dist/idle-shutdown-B5LPaNyY.mjs +122 -0
- package/dist/in-use-CndPMilN.mjs +110 -0
- package/dist/{ios-CmEzZiOj.mjs → ios-3CtCRhwr.mjs} +201 -10
- package/dist/{ios-CcfCeZ19.mjs → ios-Chob8ny7.mjs} +560 -259
- package/dist/{ios-device-BW-t_Lkv.mjs → ios-device-DERmMmk-.mjs} +12 -7
- package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
- package/dist/{launch-verify-CuJaBpEa.mjs → launch-verify-CLlofxRt.mjs} +42 -11
- package/dist/{logs-DcSRbC2t.mjs → logs-h9h6MUvE.mjs} +95 -13
- package/dist/machine-usage-D_YYMzfR.mjs +283 -0
- package/dist/machines-CYtOCqcj.mjs +259 -0
- package/dist/macos-BwtbUtTN.mjs +468 -0
- package/dist/macos-run.d.mts +5 -0
- package/dist/macos-run.mjs +2 -0
- package/dist/{merge-state-ytFQCeh4.mjs → merge-state-BnxLNQiM.mjs} +22 -12
- package/dist/{metro-BPeY1YMh.mjs → metro-Di8EN2Tb.mjs} +20 -120
- package/dist/{named-ports-n7tnJsI8.mjs → named-ports-Dj_XBNaL.mjs} +8 -64
- package/dist/native-run-DFDoIRbY.mjs +147 -0
- package/dist/{native-runtime-CiiFHt0e.mjs → native-runtime-i6OkVg-w.mjs} +11 -6
- package/dist/offload-worker.d.mts +121 -0
- package/dist/offload-worker.mjs +601 -0
- package/dist/{ownership-Bz2kETAS.mjs → ownership-BkYxUtuj.mjs} +3 -2
- package/dist/{page-BTu7I60K.mjs → page-QF_Ke10s.mjs} +7 -2
- package/dist/{ports-C5UutqpJ.mjs → ports-DddwttKM.mjs} +3 -3
- package/dist/prebuild-BvxDlD6C.mjs +213 -0
- package/dist/process-identity-BmRm1qV0.mjs +12 -0
- package/dist/{project-DGeclhvO.mjs → project-CV3tDFHl.mjs} +9 -18
- 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-GEXp4iBT.mjs +37 -0
- package/dist/{reload-C-cV5yy_.mjs → reload-ChPiwvot.mjs} +70 -22
- package/dist/{remote-cache--aehr4Pr.mjs → remote-cache-CO2elm_b.mjs} +4 -4
- package/dist/run-B-xqRrsg.mjs +119 -0
- package/dist/{server-bare-Bq8BpSIo.mjs → server-bare-X7PUgizL.mjs} +60 -13
- package/dist/{server-expo-DUCg52-K.mjs → server-expo-DhtX6bom.mjs} +6 -10
- package/dist/server-expo-KJeD109I.mjs +2 -0
- package/dist/{settings-xB0Frkg6.mjs → settings-CduVcoxj.mjs} +77 -26
- package/dist/{settings-ssVBToDR.mjs → settings-DbL6uhH8.mjs} +16 -10
- package/dist/settings.schema.json +357 -2
- package/dist/{simslim-Bbg9UWrt.mjs → simslim-Ciluxlq4.mjs} +8 -132
- package/dist/slot-launch-BY0BrOLh.mjs +65 -0
- package/dist/{spawn-claims-PT8aQpCa.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
- package/dist/spawn-entry-DncpJvWL.mjs +16 -0
- package/dist/stage-CzaiwFsI.mjs +143 -0
- package/dist/start-CPO4wRg7.mjs +2 -0
- package/dist/{start-BZhItkiL.mjs → start-CUD9nasA.mjs} +108 -61
- package/dist/state-B4PQFXMW.d.mts +12 -0
- package/dist/state-BxCgeTQu.mjs +41 -0
- package/dist/{state-DwAU2_-D.mjs → state-CaeaHbDA.mjs} +7 -4
- package/dist/{state-l1pYwOre.mjs → state-DFm77wRn.mjs} +67 -5
- package/dist/stats-DBLLFmKd.mjs +66 -0
- package/dist/{status-TJlL0HWo.mjs → status-DYXxNOT0.mjs} +425 -260
- package/dist/{status-sszP4XKU.mjs → status-l84Gbvp2.mjs} +122 -20
- 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-BZ2qMiBP.mjs → stop-Bad61z_2.mjs} +128 -19
- package/dist/stop-Bvf1MflS.mjs +48 -0
- package/dist/{stop-DskDKNTU.mjs → stop-CceYh1yG.mjs} +2 -2
- package/dist/stop-cause-CZ_Mr-v9.mjs +665 -0
- package/dist/supervisor-run.d.mts +44 -12
- package/dist/supervisor-run.mjs +276 -33
- package/dist/support-CDQbDkL5.mjs +315 -0
- package/dist/support-WLOzVKUv.mjs +176 -0
- package/dist/teardown-BYuQafiA.mjs +718 -0
- package/dist/{xcode-LM6A8cNZ.mjs → toolchain-DmeYjXD9.mjs} +363 -13
- package/dist/warm-progress-DVHLN4uC.mjs +463 -0
- package/dist/{idle-DxLi5OkN.mjs → watchman-Bx0wceoF.mjs} +55 -8
- package/dist/{web-sWXd5iek.mjs → web-k6w8-HnE.mjs} +39 -22
- package/dist/web-run.mjs +326 -13
- package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
- package/dist/workspace-state-CL2V2Ons.mjs +371 -0
- package/dist/worktree-BT_uULFx.mjs +2 -0
- package/dist/{worktree-DeBQSVtR.mjs → worktree-C0c5Udwa.mjs} +55 -54
- package/dist/{worktree-D4Do_XiQ.mjs → worktree-qXKzADSC.mjs} +161 -255
- package/package.json +10 -5
- package/shim/bundle-response.cjs +55 -10
- package/shim/bundle-response.d.cts +1 -0
- package/shim/expo-metro-config.cjs +10 -2
- package/dist/build-progress-l7d-X-ZP.mjs +0 -247
- package/dist/in-use-wYEaKQM9.mjs +0 -249
- package/dist/ownership-PUP4Dwai.mjs +0 -1138
- package/dist/server-expo-BeYwP_Xy.mjs +0 -2
- package/dist/slot-launch-BIWEW-wI.mjs +0 -19
- package/dist/start-Rw2GD3nV.mjs +0 -2
- package/dist/stats-CaSwmsSZ.mjs +0 -62
- package/dist/stats-D8rUTPHd.mjs +0 -368
- package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
- package/dist/worktree-3cBa-bQt.mjs +0 -2
- package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { validMacosResourceDestination } from "@stim-cli/core";
|
|
5
|
+
//#region src/macos/stage.ts
|
|
6
|
+
function validateInfoPlist(root, product, infoPlist) {
|
|
7
|
+
const plist = JSON.parse(getExecutor().runFile("plutil", [
|
|
8
|
+
"-convert",
|
|
9
|
+
"json",
|
|
10
|
+
"-o",
|
|
11
|
+
"-",
|
|
12
|
+
realpathSync(resolve(root, infoPlist))
|
|
13
|
+
]));
|
|
14
|
+
if (typeof plist.CFBundleIdentifier !== "string" || plist.CFBundleExecutable !== product) throw new Error("macos.infoPlist must name a CFBundleIdentifier and the selected product as CFBundleExecutable.");
|
|
15
|
+
if (plist.CFBundleURLTypes || plist.SUFeedURL) throw new Error("Use a development Info.plist without shared URL schemes or an update feed.");
|
|
16
|
+
if (plist.LSMinimumSystemVersion !== void 0 && typeof plist.LSMinimumSystemVersion !== "string") throw new Error("macos.infoPlist LSMinimumSystemVersion must be a string. See stim guide macos.");
|
|
17
|
+
return {
|
|
18
|
+
bundleId: plist.CFBundleIdentifier,
|
|
19
|
+
minimumSystemVersion: plist.LSMinimumSystemVersion
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function resourceError(key, entry, reason) {
|
|
23
|
+
throw new Error(`${key} entry ${JSON.stringify(entry)}: ${reason}. See stim guide macos.`);
|
|
24
|
+
}
|
|
25
|
+
function containsSymlink(dir) {
|
|
26
|
+
return readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isSymbolicLink() || entry.isDirectory() && containsSymlink(join(dir, entry.name)));
|
|
27
|
+
}
|
|
28
|
+
function overlaps(a, b) {
|
|
29
|
+
a = a.normalize("NFC").toLowerCase();
|
|
30
|
+
b = b.normalize("NFC").toLowerCase();
|
|
31
|
+
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
32
|
+
}
|
|
33
|
+
function resolveBundleExtras(root, repository, resources = {}, assetCatalog) {
|
|
34
|
+
const boundary = realpathSync(repository);
|
|
35
|
+
const sourcePath = (key, entry) => {
|
|
36
|
+
if (typeof entry !== "string" || !entry || isAbsolute(entry) || entry.includes("\0")) resourceError(key, entry, "source must be a non-empty relative path");
|
|
37
|
+
let source;
|
|
38
|
+
try {
|
|
39
|
+
source = realpathSync(resolve(root, entry));
|
|
40
|
+
} catch {
|
|
41
|
+
resourceError(key, entry, "source does not exist");
|
|
42
|
+
}
|
|
43
|
+
const path = relative(boundary, source);
|
|
44
|
+
if (path === ".." || path.startsWith(`..${sep}`) || isAbsolute(path)) resourceError(key, entry, "source leaves the repository");
|
|
45
|
+
if (path === "") resourceError(key, entry, "source is the repository root");
|
|
46
|
+
const stat = statSync(source);
|
|
47
|
+
if (!stat.isFile() && !stat.isDirectory()) resourceError(key, entry, "source must be a regular file or directory");
|
|
48
|
+
if (stat.isDirectory() && containsSymlink(source)) resourceError(key, entry, "source directory contains a symbolic link");
|
|
49
|
+
return source;
|
|
50
|
+
};
|
|
51
|
+
let catalog;
|
|
52
|
+
if (assetCatalog !== void 0 && assetCatalog !== null) {
|
|
53
|
+
catalog = sourcePath("macos.assetCatalog", assetCatalog);
|
|
54
|
+
if (!catalog.endsWith(".xcassets") || !statSync(catalog).isDirectory()) resourceError("macos.assetCatalog", assetCatalog, "catalog must be a .xcassets directory");
|
|
55
|
+
}
|
|
56
|
+
if (!resources || typeof resources !== "object" || Array.isArray(resources)) resourceError("macos.resources", resources, "expected an object");
|
|
57
|
+
const entries = Object.entries(resources);
|
|
58
|
+
if (entries.length > 256) {
|
|
59
|
+
const [destination, source] = entries[256];
|
|
60
|
+
resourceError(`macos.resources[${JSON.stringify(destination)}]`, source, "at most 256 entries are allowed");
|
|
61
|
+
}
|
|
62
|
+
const reserved = catalog ? ["Assets.car"] : [];
|
|
63
|
+
const resolved = [];
|
|
64
|
+
for (const [destination, source] of entries) {
|
|
65
|
+
const key = `macos.resources[${JSON.stringify(destination)}]`;
|
|
66
|
+
if (!validMacosResourceDestination(destination)) resourceError(key, source, "invalid destination");
|
|
67
|
+
if (reserved.some((other) => overlaps(destination, other))) resourceError(key, source, "destination collides with another resource");
|
|
68
|
+
reserved.push(destination);
|
|
69
|
+
resolved.push([destination, sourcePath(key, source)]);
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
resources: Object.fromEntries(resolved),
|
|
73
|
+
assetCatalog: catalog
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function stageBundle(root, product, infoPlist, bin, bundle, bundleId, extras = { resources: {} }) {
|
|
77
|
+
const { minimumSystemVersion } = validateInfoPlist(root, product, infoPlist);
|
|
78
|
+
for (const entry of readdirSync(bin).filter((name) => name.endsWith(".bundle"))) for (const [destination, source] of Object.entries(extras.resources)) if (overlaps(destination, entry)) resourceError(`macos.resources[${JSON.stringify(destination)}]`, source, `destination collides with ${entry}`);
|
|
79
|
+
const exec = getExecutor();
|
|
80
|
+
rmSync(bundle, {
|
|
81
|
+
recursive: true,
|
|
82
|
+
force: true
|
|
83
|
+
});
|
|
84
|
+
const contents = join(bundle, "Contents");
|
|
85
|
+
mkdirSync(join(contents, "MacOS"), { recursive: true });
|
|
86
|
+
mkdirSync(join(contents, "Resources"), { recursive: true });
|
|
87
|
+
mkdirSync(join(contents, "Frameworks"), { recursive: true });
|
|
88
|
+
const executable = join(contents, "MacOS", product);
|
|
89
|
+
cpSync(join(bin, product), executable);
|
|
90
|
+
cpSync(resolve(root, infoPlist), join(contents, "Info.plist"));
|
|
91
|
+
exec.runFile("/usr/libexec/PlistBuddy", [
|
|
92
|
+
"-c",
|
|
93
|
+
`Set :CFBundleIdentifier ${bundleId}`,
|
|
94
|
+
join(contents, "Info.plist")
|
|
95
|
+
]);
|
|
96
|
+
for (const entry of readdirSync(bin)) if (entry.endsWith(".framework")) {
|
|
97
|
+
const target = join(contents, "Frameworks", entry);
|
|
98
|
+
cpSync(join(bin, entry), target, {
|
|
99
|
+
recursive: true,
|
|
100
|
+
dereference: false,
|
|
101
|
+
verbatimSymlinks: true
|
|
102
|
+
});
|
|
103
|
+
exec.runFile("codesign", [
|
|
104
|
+
"--force",
|
|
105
|
+
"--sign",
|
|
106
|
+
"-",
|
|
107
|
+
target
|
|
108
|
+
]);
|
|
109
|
+
} else if (entry.endsWith(".bundle")) cpSync(join(bin, entry), join(contents, "Resources", entry), { recursive: true });
|
|
110
|
+
const frameworkPath = "@executable_path/../Frameworks";
|
|
111
|
+
if (!exec.runFile("otool", ["-l", executable]).includes(frameworkPath)) exec.runFile("install_name_tool", [
|
|
112
|
+
"-add_rpath",
|
|
113
|
+
frameworkPath,
|
|
114
|
+
executable
|
|
115
|
+
]);
|
|
116
|
+
for (const [destination, source] of Object.entries(extras.resources)) {
|
|
117
|
+
const target = join(contents, "Resources", destination);
|
|
118
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
119
|
+
cpSync(source, target, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
if (extras.assetCatalog) {
|
|
122
|
+
exec.runFile("xcrun", [
|
|
123
|
+
"actool",
|
|
124
|
+
extras.assetCatalog,
|
|
125
|
+
"--compile",
|
|
126
|
+
join(contents, "Resources"),
|
|
127
|
+
"--platform",
|
|
128
|
+
"macosx",
|
|
129
|
+
...minimumSystemVersion === void 0 ? [] : ["--minimum-deployment-target", minimumSystemVersion],
|
|
130
|
+
"--output-partial-info-plist",
|
|
131
|
+
"/dev/null"
|
|
132
|
+
]);
|
|
133
|
+
if (!existsSync(join(contents, "Resources", "Assets.car"))) resourceError("macos.assetCatalog", extras.assetCatalog, "actool did not produce Assets.car");
|
|
134
|
+
}
|
|
135
|
+
exec.runFile("codesign", [
|
|
136
|
+
"--force",
|
|
137
|
+
"--sign",
|
|
138
|
+
"-",
|
|
139
|
+
bundle
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
export { stageBundle as n, validateInfoPlist as r, resolveBundleExtras as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as registerStart, c as startDevServer, d as tailLines, f as wantsExpoOwnTunnel, i as readLogTail, l as startFacts, n as liveSupervisor, o as resolveWorkspaceMetroPort, r as parseWait, s as startCommand, t as failureEvidence, u as supervisorEntry } from "./start-CUD9nasA.mjs";
|
|
2
|
+
export { startCommand as default, failureEvidence, liveSupervisor, parseWait, readLogTail, registerStart, resolveWorkspaceMetroPort, startDevServer, startFacts, supervisorEntry, tailLines, wantsExpoOwnTunnel };
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { E as upsertProject, p as getProject } from "./config-D0DbpZtM.mjs";
|
|
3
|
+
import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
3
4
|
import { i as levelRank } from "./ndjson-CDY9IkVC.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { s as gitCommonDir, y as repoRoot } from "./worktree-
|
|
6
|
-
import { a as findProjectRoot, d as readAppJson, n as appProjectProblem, r as detectIsExpo, t as NO_PROJECT_REFUSAL, u as readAppConfigText } from "./project-
|
|
7
|
-
import { n as windowsLauncherArgs } from "./detached-entry-
|
|
8
|
-
import { c as readMetroTunnel, i as clearManagedMetroTunnel } from "./state-
|
|
9
|
-
import {
|
|
10
|
-
import { _ as stepTimer, l as phaseLine } from "./command-output-
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { d as
|
|
14
|
-
import {
|
|
5
|
+
import { C as workspaceLogsDir, _ as supervisorLogFile, c as writeWorkspaceState, i as recordWorkspaceUse, n as clearWorkspaceStateKeys, p as ensureWorkspaceStorage, r as readWorkspaceState$1 } from "./workspace-state-CL2V2Ons.mjs";
|
|
6
|
+
import { s as gitCommonDir, y as repoRoot } from "./worktree-C0c5Udwa.mjs";
|
|
7
|
+
import { a as findProjectRoot$1, d as readAppJson, n as appProjectProblem, r as detectIsExpo, t as NO_PROJECT_REFUSAL, u as readAppConfigText } from "./project-CV3tDFHl.mjs";
|
|
8
|
+
import { n as windowsLauncherArgs } from "./detached-entry-CiTEgMR1.mjs";
|
|
9
|
+
import { c as readMetroTunnel, i as clearManagedMetroTunnel } from "./state-CaeaHbDA.mjs";
|
|
10
|
+
import { n as workspaceProcessLockError, t as withWorkspaceProcessLock } from "./workspace-process-lock-BL7Q0HCO.mjs";
|
|
11
|
+
import { _ as stepTimer, l as phaseLine } from "./command-output-CliHHn7a.mjs";
|
|
12
|
+
import { a as workspaceLinks, i as workspaceLinkLine } from "./stim-desktop-Cnz8CPnl.mjs";
|
|
13
|
+
import { l as resolveProjectMetro, o as pidExists, p as reserveMetroPort, u as signalProcessTree } from "./metro-Di8EN2Tb.mjs";
|
|
14
|
+
import { A as remoteAndroidSetting, B as unknownSettingKeys, C as metroTunnelSettingError, H as PUBLIC_METRO_ENV, L as settingShapeErrors, M as resolveCacheProviderConfig, N as resolveSettings, O as publicUrlSetting, S as metroPortSetting, T as ngrokUrlSetting, U as detectProviders, W as planMetroReach, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, f as deviceIdleShutdownMinutesSetting, j as remoteIosSetting, x as metroIdleStopMinutesSetting, z as tunnelModeSetting } from "./settings-CduVcoxj.mjs";
|
|
15
|
+
import { _ as withManagedTunnelLock, f as startTunnelSequence, h as withManagedRemoteWorktreeLock, m as terminateChild, p as stopTunnel, u as resolveSupervisorTarget } from "./stop-cause-CZ_Mr-v9.mjs";
|
|
16
|
+
import { t as spawnEntry } from "./spawn-entry-DncpJvWL.mjs";
|
|
17
|
+
import { d as readProjectConfig } from "./remote-cache-CO2elm_b.mjs";
|
|
18
|
+
import { t as budgetGate, tt as stopOwnedMetroForReset } from "./budget-CMiqghig.mjs";
|
|
15
19
|
import { appendFileSync, mkdirSync, openSync, readFileSync } from "node:fs";
|
|
20
|
+
import { dirname } from "node:path";
|
|
21
|
+
import { EventEmitter } from "node:events";
|
|
16
22
|
import { existsSync as existsSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1 } from "fs";
|
|
17
|
-
import { join } from "path";
|
|
23
|
+
import { join as join$1 } from "path";
|
|
18
24
|
import { IDLE_STOP_KEY, queryLogs } from "@stim-cli/core/state";
|
|
19
|
-
import { basename as basename$1, dirname as dirname$1, join as join$1 } from "node:path";
|
|
20
|
-
import { EventEmitter } from "node:events";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
25
|
import chalk from "chalk";
|
|
23
26
|
import { CACHE_PROVIDER_ENV, cacheProviderEnv } from "@stim-cli/cache";
|
|
24
27
|
//#region src/workspace/app-id.ts
|
|
@@ -60,7 +63,7 @@ function detectAndroidPackage(projectRoot) {
|
|
|
60
63
|
return detectAppIds(projectRoot).androidPackage;
|
|
61
64
|
}
|
|
62
65
|
function detectBundleIdFromPbxproj(projectRoot) {
|
|
63
|
-
const iosDir = join(projectRoot, "ios");
|
|
66
|
+
const iosDir = join$1(projectRoot, "ios");
|
|
64
67
|
if (!existsSync$1(iosDir)) return null;
|
|
65
68
|
let entries;
|
|
66
69
|
try {
|
|
@@ -70,7 +73,7 @@ function detectBundleIdFromPbxproj(projectRoot) {
|
|
|
70
73
|
}
|
|
71
74
|
for (const entry of entries) {
|
|
72
75
|
if (!entry.isDirectory() || !entry.name.endsWith(".xcodeproj")) continue;
|
|
73
|
-
const pbx = join(iosDir, entry.name, "project.pbxproj");
|
|
76
|
+
const pbx = join$1(iosDir, entry.name, "project.pbxproj");
|
|
74
77
|
if (!existsSync$1(pbx)) continue;
|
|
75
78
|
let text;
|
|
76
79
|
try {
|
|
@@ -93,7 +96,7 @@ function detectBundleIdFromPbxproj(projectRoot) {
|
|
|
93
96
|
return null;
|
|
94
97
|
}
|
|
95
98
|
function detectAndroidPackageFromGradle(projectRoot) {
|
|
96
|
-
const gradle = join(projectRoot, "android", "app", "build.gradle");
|
|
99
|
+
const gradle = join$1(projectRoot, "android", "app", "build.gradle");
|
|
97
100
|
if (!existsSync$1(gradle)) return null;
|
|
98
101
|
let text;
|
|
99
102
|
try {
|
|
@@ -108,18 +111,6 @@ function detectAndroidPackageFromGradle(projectRoot) {
|
|
|
108
111
|
return null;
|
|
109
112
|
}
|
|
110
113
|
//#endregion
|
|
111
|
-
//#region src/spawn-entry.ts
|
|
112
|
-
const DEV_ENTRIES = {
|
|
113
|
-
"supervisor-run": "./supervisor/run.ts",
|
|
114
|
-
"collector-run": "./collector/run.ts",
|
|
115
|
-
"web-run": "./web/run.ts"
|
|
116
|
-
};
|
|
117
|
-
function spawnEntry(name) {
|
|
118
|
-
const here = fileURLToPath(import.meta.url);
|
|
119
|
-
if (basename$1(dirname$1(here)) === "src") return fileURLToPath(new URL(DEV_ENTRIES[name], import.meta.url));
|
|
120
|
-
return join$1(dirname$1(here), `${name}.mjs`);
|
|
121
|
-
}
|
|
122
|
-
//#endregion
|
|
123
114
|
//#region src/commands/start.ts
|
|
124
115
|
const DEFAULT_WAIT_SECONDS = 60;
|
|
125
116
|
const POLL_MS = 500;
|
|
@@ -194,14 +185,14 @@ function recordedSupervisorProcess(pid) {
|
|
|
194
185
|
});
|
|
195
186
|
}
|
|
196
187
|
const RECORDED_SUPERVISOR_WAIT_MS = 15e3;
|
|
197
|
-
function providersOnPath() {
|
|
188
|
+
function providersOnPath(mode) {
|
|
198
189
|
return detectProviders((bin) => {
|
|
199
190
|
try {
|
|
200
191
|
return Boolean(getExecutor().findExecutable(bin));
|
|
201
192
|
} catch {
|
|
202
193
|
return false;
|
|
203
194
|
}
|
|
204
|
-
});
|
|
195
|
+
}, mode);
|
|
205
196
|
}
|
|
206
197
|
const DEFAULT_START_DEPS = {
|
|
207
198
|
providers: providersOnPath,
|
|
@@ -260,7 +251,7 @@ function registerStart(program, overrides = {}) {
|
|
|
260
251
|
remedy: "Pass a whole number of seconds, e.g. --wait 90."
|
|
261
252
|
});
|
|
262
253
|
const waitSeconds = wait.seconds;
|
|
263
|
-
const root = findProjectRoot(process.cwd());
|
|
254
|
+
const root = findProjectRoot$1(process.cwd());
|
|
264
255
|
if (!root) return fail(NO_PROJECT_REFUSAL);
|
|
265
256
|
const projectProblem = appProjectProblem(root);
|
|
266
257
|
if (projectProblem) return fail({
|
|
@@ -313,7 +304,8 @@ function registerStart(program, overrides = {}) {
|
|
|
313
304
|
out,
|
|
314
305
|
facts: result.facts,
|
|
315
306
|
waited: result.waited,
|
|
316
|
-
reclaimed: result.reclaimed
|
|
307
|
+
reclaimed: result.reclaimed,
|
|
308
|
+
links: workspaceLinks(root)
|
|
317
309
|
});
|
|
318
310
|
});
|
|
319
311
|
}
|
|
@@ -376,6 +368,11 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
376
368
|
};
|
|
377
369
|
if (resetCache) {
|
|
378
370
|
await gateBudget();
|
|
371
|
+
const pin = metroPortSetting(root);
|
|
372
|
+
if (pin.port !== null || pin.error) {
|
|
373
|
+
const pinCheck = await resolveWorkspaceMetroPort(root, note, "start", false);
|
|
374
|
+
if (typeof pinCheck !== "number") return fail(pinCheck);
|
|
375
|
+
}
|
|
379
376
|
try {
|
|
380
377
|
await stopOwnedMetroForReset(root);
|
|
381
378
|
} catch (error) {
|
|
@@ -390,7 +387,7 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
390
387
|
}
|
|
391
388
|
const logsDir = workspaceLogsDir(root);
|
|
392
389
|
const logFile = supervisorLogFile(root);
|
|
393
|
-
const port = await resolvePort(root, note);
|
|
390
|
+
const port = await resolvePort(root, note, fail);
|
|
394
391
|
let publicOrigin = remote ? publicUrl : null;
|
|
395
392
|
let resolution = await resolveProjectMetro(port, root);
|
|
396
393
|
let supervisor = liveSupervisor({
|
|
@@ -510,7 +507,9 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
510
507
|
...tunnel ? ["--tunnel"] : [],
|
|
511
508
|
...resetCache ? ["--reset-cache"] : [],
|
|
512
509
|
"--idle-stop-minutes",
|
|
513
|
-
String(metroIdleStopMinutesSetting(settings))
|
|
510
|
+
String(metroIdleStopMinutesSetting(settings)),
|
|
511
|
+
"--device-idle-minutes",
|
|
512
|
+
String(deviceIdleShutdownMinutesSetting(settings))
|
|
514
513
|
];
|
|
515
514
|
const childEnv = {
|
|
516
515
|
...process.env,
|
|
@@ -540,7 +539,7 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
540
539
|
return null;
|
|
541
540
|
};
|
|
542
541
|
if (remote && !tunnel && !publicUrl && tunnelMode !== "off") {
|
|
543
|
-
const available = d.providers();
|
|
542
|
+
const available = d.providers(tunnelMode);
|
|
544
543
|
const plan = planMetroReach({
|
|
545
544
|
mode: tunnelMode,
|
|
546
545
|
metroPort: port,
|
|
@@ -554,7 +553,7 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
554
553
|
remedy: plan.remedy
|
|
555
554
|
});
|
|
556
555
|
if ("start" in plan) {
|
|
557
|
-
const candidates = tunnelMode === "auto" ? available : [plan.start];
|
|
556
|
+
const candidates = tunnelMode === "auto" ? available.filter((provider) => provider !== "tailscale") : [plan.start];
|
|
558
557
|
const expectedStableUrl = ngrokUrlSetting(settings);
|
|
559
558
|
let acquisition;
|
|
560
559
|
try {
|
|
@@ -722,6 +721,7 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
722
721
|
if ("failed" in acquisition) return fail(acquisition.failed);
|
|
723
722
|
publicOrigin = acquisition.origin;
|
|
724
723
|
managedTunnel = acquisition.tunnel;
|
|
724
|
+
if (managedTunnel.record.provider === "tailscale") note(phaseLine("lan", `tailnet-only Metro: ${publicOrigin}`));
|
|
725
725
|
resolution = await resolveProjectMetro(port, root);
|
|
726
726
|
supervisor = liveSupervisor({
|
|
727
727
|
state: readWorkspaceState$1(root),
|
|
@@ -911,7 +911,7 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
911
911
|
};
|
|
912
912
|
const startLocked = async () => {
|
|
913
913
|
try {
|
|
914
|
-
return await withWorkspaceProcessLock(dirname
|
|
914
|
+
return await withWorkspaceProcessLock(dirname(workspaceLogsDir(root)), "metro-start", runStart, { external: true });
|
|
915
915
|
} catch (error) {
|
|
916
916
|
if (workspaceProcessLockError(error) !== "timeout") throw error;
|
|
917
917
|
return fail({
|
|
@@ -956,24 +956,69 @@ async function startDevServer({ root, settings, waitSeconds = DEFAULT_WAIT_SECON
|
|
|
956
956
|
};
|
|
957
957
|
}
|
|
958
958
|
}
|
|
959
|
-
async function resolvePort(root, note) {
|
|
959
|
+
async function resolvePort(root, note, fail) {
|
|
960
|
+
const result = await resolveWorkspaceMetroPort(root, note, "start");
|
|
961
|
+
return typeof result === "number" ? result : fail(result);
|
|
962
|
+
}
|
|
963
|
+
async function resolveWorkspaceMetroPort(root, note, command, reserve = true) {
|
|
964
|
+
const setting = metroPortSetting(root);
|
|
965
|
+
if (setting.error) return {
|
|
966
|
+
code: "STIM_BAD_ARG",
|
|
967
|
+
message: setting.error,
|
|
968
|
+
remedy: SETTING_SHAPE_REMEDY
|
|
969
|
+
};
|
|
970
|
+
const pinned = setting.port;
|
|
960
971
|
const project = getProject(root);
|
|
961
972
|
const recorded = project?.metroPort;
|
|
962
|
-
if (
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
973
|
+
if (pinned === null && command === "web") return recorded ?? await reserveMetroPort(root);
|
|
974
|
+
if (recorded) {
|
|
975
|
+
const supervisor = resolveSupervisorTarget({
|
|
976
|
+
state: readWorkspaceState$1(root)?.supervisor,
|
|
977
|
+
record: project.supervisor,
|
|
978
|
+
reservedPort: recorded
|
|
979
|
+
});
|
|
980
|
+
if (supervisor.status !== "none" && supervisor.status !== "stale") {
|
|
981
|
+
if (pinned === null || recorded === pinned) return recorded;
|
|
982
|
+
if (supervisor.status === "unverified") return {
|
|
983
|
+
code: "STIM_BAD_ARG",
|
|
984
|
+
message: `Cannot move this workspace's Metro to metro.port ${pinned}: ${supervisor.reason}.`,
|
|
985
|
+
remedy: `Stop that supervisor with the tool that started it, then retry, or restore metro.port to ${recorded}. Stim leaves unverified processes alone.`
|
|
986
|
+
};
|
|
987
|
+
return {
|
|
988
|
+
code: "STIM_BAD_ARG",
|
|
989
|
+
message: `This workspace's dev server is running on port ${recorded}, and metro.port pins it to ${pinned}.`,
|
|
990
|
+
remedy: "Run `stim stop`, then retry, or unset or restore metro.port."
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
if (pinned !== null) {
|
|
995
|
+
const held = await resolveProjectMetro(pinned, root);
|
|
996
|
+
if (held.notOurs) return {
|
|
997
|
+
code: "STIM_BAD_ARG",
|
|
998
|
+
message: `Port ${pinned} is held by something else (${held.notOurs}), and metro.port pins this workspace's Metro to it.`,
|
|
999
|
+
remedy: "Stop the process on that port, or set another metro.port."
|
|
1000
|
+
};
|
|
1001
|
+
if (recorded === pinned) return recorded;
|
|
1002
|
+
} else if (recorded) {
|
|
1003
|
+
const held = await resolveProjectMetro(recorded, root);
|
|
1004
|
+
if (!held.notOurs) return recorded;
|
|
1005
|
+
const fresh = await reserveMetroPort(root);
|
|
1006
|
+
if (fresh !== recorded) {
|
|
1007
|
+
note(chalk.yellow(`Port ${recorded} is held by something else (${held.notOurs}).`));
|
|
1008
|
+
note(chalk.dim(`Reserved port ${fresh} for this project instead.`));
|
|
1009
|
+
}
|
|
1010
|
+
return fresh;
|
|
1011
|
+
}
|
|
1012
|
+
if (!reserve && pinned !== null) return pinned;
|
|
1013
|
+
try {
|
|
1014
|
+
return await reserveMetroPort(root, void 0, void 0, pinned);
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
return {
|
|
1017
|
+
code: "STIM_BAD_ARG",
|
|
1018
|
+
message: error.message,
|
|
1019
|
+
remedy: "Give each workspace its own metro.port, in the workspace layer or the environment."
|
|
1020
|
+
};
|
|
975
1021
|
}
|
|
976
|
-
return fresh;
|
|
977
1022
|
}
|
|
978
1023
|
async function waitForMetro({ root, port, seconds, aborted = () => false, probe = resolveProjectMetro }) {
|
|
979
1024
|
const deadline = Date.now() + seconds * 1e3;
|
|
@@ -1014,17 +1059,19 @@ function failureEvidence({ logFile, logsDir, sinceTs }) {
|
|
|
1014
1059
|
if (recent.length > 0) lines.push(fellBack ? "Full records: `stim logs`" : "Full records: `stim logs --errors`");
|
|
1015
1060
|
return lines;
|
|
1016
1061
|
}
|
|
1017
|
-
function report({ json, out, facts, waited, reclaimed }) {
|
|
1062
|
+
function report({ json, out, facts, waited, reclaimed, links }) {
|
|
1018
1063
|
if (json) {
|
|
1019
|
-
console.log(JSON.stringify(
|
|
1064
|
+
console.log(JSON.stringify({
|
|
1020
1065
|
...facts,
|
|
1021
|
-
|
|
1022
|
-
|
|
1066
|
+
...links ? { links } : {},
|
|
1067
|
+
...reclaimed.length ? { reclaimed } : {}
|
|
1068
|
+
}));
|
|
1023
1069
|
return;
|
|
1024
1070
|
}
|
|
1025
1071
|
const who = facts.supervisorPid ? `supervisor pid ${facts.supervisorPid}${facts.mode ? ` (${facts.mode})` : ""}` : "started outside Stim";
|
|
1026
1072
|
out(chalk.green(`OK: dev server on port ${facts.port}, ${who}${facts.alreadyRunning ? " (already running)" : ""} ${waited}`));
|
|
1027
1073
|
out(chalk.dim(phaseLine("logs", facts.logsDir)));
|
|
1074
|
+
if (links) console.error(chalk.dim(workspaceLinkLine(links)));
|
|
1028
1075
|
}
|
|
1029
1076
|
//#endregion
|
|
1030
|
-
export { registerStart as a,
|
|
1077
|
+
export { registerStart as a, startDevServer as c, tailLines as d, wantsExpoOwnTunnel as f, detectBundleId as h, readLogTail as i, startFacts as l, detectAppIds as m, liveSupervisor as n, resolveWorkspaceMetroPort as o, detectAndroidPackage as p, parseWait as r, startCommand as s, failureEvidence as t, supervisorEntry as u };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import "@stim-cli/core/state";
|
|
2
|
+
import * as import__stim_cli_core_process_identity from "@stim-cli/core/process-identity";
|
|
3
|
+
//#endregion
|
|
4
|
+
//#region src/supervisor/state.d.ts
|
|
5
|
+
declare const MODE_BARE = "bare-inproc";
|
|
6
|
+
declare const MODE_EXPO = "expo-child";
|
|
7
|
+
declare function clearWorkspaceSupervisor(root: string, expected?: process_identity_d_exports.ProcessRecord | null): boolean;
|
|
8
|
+
declare function clearExpoMetroTunnel(root: string): void;
|
|
9
|
+
declare function writePidFile(root: string, pid: number): string;
|
|
10
|
+
declare function readPidFile(root: string): number | null;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { readPidFile as a, clearWorkspaceSupervisor as i, MODE_EXPO as n, writePidFile as o, clearExpoMetroTunnel as r, MODE_BARE as t };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
2
|
+
import { C as workspaceLogsDir, a as updateWorkspaceState, b as workspaceDir, r as readWorkspaceState$1 } from "./workspace-state-CL2V2Ons.mjs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readMacosRecord } from "@stim-cli/core/state";
|
|
5
|
+
//#region src/macos/state.ts
|
|
6
|
+
const macosDir = (root) => join(workspaceDir(root), "macos");
|
|
7
|
+
const macosLogFile = (root) => join(workspaceLogsDir(root), "macos.ndjson");
|
|
8
|
+
const macosRuntimeClaim = (root) => join(macosDir(root), "runtime.lock");
|
|
9
|
+
function macosProcess(pid) {
|
|
10
|
+
const processToken = (0, process_identity_exports.captureProcessToken)(pid);
|
|
11
|
+
const start = (0, process_identity_exports.processStartMicros)(pid);
|
|
12
|
+
if (!processToken || start.status !== "running") throw Object.assign(/* @__PURE__ */ new Error(`Cannot verify macOS process ${pid}; refusing unmanaged launch.`), { code: "STIM_CLAIM_UNAVAILABLE" });
|
|
13
|
+
return {
|
|
14
|
+
pid,
|
|
15
|
+
processToken,
|
|
16
|
+
startedAtMicros: start.startedAtMicros
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function requiredMacosRecord(root) {
|
|
20
|
+
const record = readMacosRecord(root);
|
|
21
|
+
if (!record && readWorkspaceState$1(root)?.macos !== void 0) throw Object.assign(/* @__PURE__ */ new Error("The recorded macOS owner is malformed; repair its workspace state before running."), { code: "STIM_MACOS_OWNER_UNVERIFIED" });
|
|
22
|
+
return record;
|
|
23
|
+
}
|
|
24
|
+
function updateMacosRecord(root, owner, patch) {
|
|
25
|
+
let updated = false;
|
|
26
|
+
updateWorkspaceState(root, (state) => {
|
|
27
|
+
const record = readMacosRecord(root);
|
|
28
|
+
if (!record || !(0, process_identity_exports.sameProcessRecord)(record.supervisor, owner)) return state;
|
|
29
|
+
updated = true;
|
|
30
|
+
return {
|
|
31
|
+
...state,
|
|
32
|
+
macos: {
|
|
33
|
+
...record,
|
|
34
|
+
...patch
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return updated;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { requiredMacosRecord as a, macosRuntimeClaim as i, macosLogFile as n, updateMacosRecord as o, macosProcess as r, macosDir as t };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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 { T as workspaceStateFile, a as updateWorkspaceState, o as withWorkspaceStateLock, r as readWorkspaceState, t as clearWorkspaceStateKey, v as supervisorPidFile } from "./workspace-state-CL2V2Ons.mjs";
|
|
3
4
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
5
|
import { dirname } from "node:path";
|
|
5
6
|
//#region src/supervisor/state.ts
|
|
@@ -22,7 +23,7 @@ function readMetroTunnel(root) {
|
|
|
22
23
|
const startedAt = record.startedAt;
|
|
23
24
|
const processToken = record.processToken;
|
|
24
25
|
const logFile = record.logFile;
|
|
25
|
-
if (provider !== "ngrok" && provider !== "cloudflared" || typeof pid !== "number" || typeof port !== "number") return null;
|
|
26
|
+
if (provider !== "ngrok" && provider !== "cloudflared" && provider !== "tailscale" || typeof pid !== "number" || typeof port !== "number") return null;
|
|
26
27
|
return {
|
|
27
28
|
kind: "managed",
|
|
28
29
|
provider,
|
|
@@ -88,11 +89,13 @@ function readRemoteSession(root) {
|
|
|
88
89
|
const platform = record.platform;
|
|
89
90
|
const startedAt = record.startedAt;
|
|
90
91
|
const webPreviewUrl = record.webPreviewUrl;
|
|
92
|
+
const deviceType = record.deviceType;
|
|
91
93
|
return {
|
|
92
94
|
platform: platform === "ios" || platform === "android" ? platform : null,
|
|
93
95
|
sessionId: id,
|
|
94
96
|
startedAt: typeof startedAt === "string" ? startedAt : null,
|
|
95
|
-
webPreviewUrl: typeof webPreviewUrl === "string" && webPreviewUrl.length > 0 ? webPreviewUrl : null
|
|
97
|
+
webPreviewUrl: typeof webPreviewUrl === "string" && webPreviewUrl.length > 0 ? webPreviewUrl : null,
|
|
98
|
+
deviceType: typeof deviceType === "string" && deviceType.length > 0 ? deviceType : null
|
|
96
99
|
};
|
|
97
100
|
}
|
|
98
101
|
function readRemoteSessionId(root) {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
2
|
+
import { C as workspaceLogsDir, a as updateWorkspaceState, b as workspaceDir, c as writeWorkspaceState, r as readWorkspaceState$1, t as clearWorkspaceStateKey } from "./workspace-state-CL2V2Ons.mjs";
|
|
3
|
+
import { o as pidExists } from "./metro-Di8EN2Tb.mjs";
|
|
4
|
+
import { readFileSync, readlinkSync, rmSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
+
import { rotatedLogPath } from "@stim-cli/core";
|
|
7
|
+
import { WEB_VIEWPORTS } from "@stim-cli/core/state";
|
|
6
8
|
import { hostname } from "node:os";
|
|
7
9
|
//#region src/web/profile.ts
|
|
8
10
|
const SINGLETON_FILES = [
|
|
@@ -144,5 +146,65 @@ function webFacts(record) {
|
|
|
144
146
|
status: supervisor === "same" && chrome === "running" ? "running" : "orphaned"
|
|
145
147
|
};
|
|
146
148
|
}
|
|
149
|
+
const PAGE_FAILURES = /* @__PURE__ */ new Set(["web_document_failed", "web_page_crashed"]);
|
|
150
|
+
const NAVIGATION = Buffer.from("\"event\":\"web_navigation\"");
|
|
151
|
+
const PAGE_EVENT = "\"event\":\"web_";
|
|
152
|
+
/**
|
|
153
|
+
* The latest page load in the web log's `lines`: the newest `web_navigation` marker, whether a document failure, a
|
|
154
|
+
* crash or the load event followed it, and the newest in-app route change after it. Null before the first
|
|
155
|
+
* navigation.
|
|
156
|
+
*/
|
|
157
|
+
function latestPageLoad(lines) {
|
|
158
|
+
let failure = null;
|
|
159
|
+
let loaded = false;
|
|
160
|
+
let route = null;
|
|
161
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
162
|
+
let record;
|
|
163
|
+
try {
|
|
164
|
+
record = JSON.parse(lines[i]);
|
|
165
|
+
} catch {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (record.event === "web_navigation" && typeof record.url === "string") {
|
|
169
|
+
const moved = route !== null && route !== record.url ? { route } : {};
|
|
170
|
+
if (failure !== null) return {
|
|
171
|
+
url: record.url,
|
|
172
|
+
state: "failed",
|
|
173
|
+
error: failure,
|
|
174
|
+
...moved
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
url: record.url,
|
|
178
|
+
state: loaded ? "loaded" : "loading",
|
|
179
|
+
...moved
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (typeof record.event !== "string") continue;
|
|
183
|
+
if (record.event === "web_route" && typeof record.url === "string") route ??= record.url;
|
|
184
|
+
if (PAGE_FAILURES.has(record.event)) failure = typeof record.msg === "string" ? record.msg : record.event;
|
|
185
|
+
else if (record.event === "web_page_loaded") loaded = true;
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
/** The page lines from the newest navigation on, in the web log or, right after a rotation, its previous file. */
|
|
190
|
+
function pageLines(file) {
|
|
191
|
+
for (const path of [file, rotatedLogPath(file)]) {
|
|
192
|
+
let bytes;
|
|
193
|
+
try {
|
|
194
|
+
bytes = readFileSync(path);
|
|
195
|
+
} catch {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const at = bytes.lastIndexOf(NAVIGATION);
|
|
199
|
+
if (at < 0) continue;
|
|
200
|
+
const start = bytes.lastIndexOf(10, at) + 1;
|
|
201
|
+
return bytes.subarray(start).toString("utf8").split("\n").filter((line) => line.includes(PAGE_EVENT));
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
function readWebPage(root) {
|
|
206
|
+
const lines = pageLines(webLogFile(root));
|
|
207
|
+
return lines ? latestPageLoad(lines) : null;
|
|
208
|
+
}
|
|
147
209
|
//#endregion
|
|
148
|
-
export {
|
|
210
|
+
export { removeSingletonFiles as _, readWebPage as a, webClaimRoot as c, webLogFile as d, webProfileDir as f, liveProfileHolder as g, chromeProcessState as h, clearWebRecord as i, webDir as l, writeWebRecord as m, browserLogFile as n, readWebRecord as o, webSupervisorLogFile as p, cdpEndpoint as r, updateWebRecord as s, CDP_PORT_LABEL as t, webFacts as u };
|