stim 1.12.0 → 1.13.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 +3 -1
- package/dist/{activity-CCZJs__P.mjs → activity-DfVKZTEB.mjs} +42 -25
- package/dist/{android-BQiKJYK0.mjs → android-BHfAu2mf.mjs} +1 -1
- package/dist/{android-B7X-8H7h.mjs → android-CD8pr8Q2.mjs} +62 -47
- package/dist/{android-cas-DzLPXiEn.mjs → android-cas-B9Kv9aIy.mjs} +9 -7
- package/dist/{android-75Sk2rIR.mjs → android-qx_31wJo.mjs} +395 -116
- package/dist/{app-install-CsZi0SAT.mjs → app-install-CDFY2nUL.mjs} +1 -1
- package/dist/{budget-DbzW5VTD.mjs → budget-E5o91NR1.mjs} +154 -37
- package/dist/{build-plan-CqntbR7b.mjs → build-plan-BTa93o_r.mjs} +21 -88
- package/dist/{build-progress-h60GPV27.mjs → build-progress-l7d-X-ZP.mjs} +75 -7
- package/dist/cdp-Dq_ypAlJ.mjs +115 -0
- package/dist/chrome-B5hWgQJS.mjs +61 -0
- package/dist/cli.mjs +16 -15
- package/dist/collector-run.mjs +14 -8
- package/dist/{command-output-BWCj5Vh-.mjs → command-output-BIL7rlX7.mjs} +1 -1
- package/dist/created-devices-Cd558h31.mjs +37 -0
- package/dist/{deps-CO-_7UOm.mjs → deps-2Wo81np9.mjs} +1 -1
- package/dist/{device-9r9xRYDa.mjs → device-Cf7vl-so.mjs} +6 -6
- package/dist/{device-lease-B9LAXIUH.mjs → device-lease-CL9dZf73.mjs} +52 -3
- package/dist/{device-pool-BoezJd-c.mjs → device-pool-MuoiyRcu.mjs} +3 -3
- package/dist/{device-remote-C0_o-tJH.mjs → device-remote-DT9ngZiD.mjs} +10 -10
- package/dist/{doctor-LfDlbR-N.mjs → doctor-D2iysNNH.mjs} +47 -18
- package/dist/{error-diagnostics-CCxjn31V.mjs → error-diagnostics-BoiOhck8.mjs} +6 -6
- package/dist/{gc-C4nQFcTX.mjs → gc-eA-PRBX8.mjs} +853 -126
- package/dist/{guide-BPBlh9ML.mjs → guide-BfZ0OmiP.mjs} +736 -110
- package/dist/{guide-status-i9ogHt4v.mjs → guide-status-BaMYu55M.mjs} +1 -1
- package/dist/{idle-S3tFZ53_.mjs → idle-DxLi5OkN.mjs} +42 -9
- package/dist/{in-use-D9XYEgFD.mjs → in-use-wYEaKQM9.mjs} +9 -5
- package/dist/{ios-CDzWL1mj.mjs → ios-CcfCeZ19.mjs} +98 -54
- package/dist/{ios-CZWOHTTc.mjs → ios-CmEzZiOj.mjs} +10 -5
- package/dist/{ios-device-D9cLxVr5.mjs → ios-device-BW-t_Lkv.mjs} +1 -1
- package/dist/{launch-verify-B2oR_kFN.mjs → launch-verify-CuJaBpEa.mjs} +33 -20
- package/dist/{logs-SzuYudOj.mjs → logs-DcSRbC2t.mjs} +11 -10
- package/dist/{metro-Dzo30hvJ.mjs → metro-BPeY1YMh.mjs} +4 -4
- package/dist/{named-ports-Dn1o61D9.mjs → named-ports-n7tnJsI8.mjs} +78 -6
- package/dist/native-runtime-CiiFHt0e.mjs +74 -0
- package/dist/{ownership-Dqnrjrio.mjs → ownership-Bz2kETAS.mjs} +1 -1
- package/dist/{ownership-B8d4kXBx.mjs → ownership-PUP4Dwai.mjs} +134 -209
- package/dist/page-BTu7I60K.mjs +29 -0
- package/dist/{ports-Dp_QTwTC.mjs → ports-C5UutqpJ.mjs} +4 -4
- package/dist/{project-B8rbutVC.mjs → project-DGeclhvO.mjs} +53 -17
- package/dist/{reload-nocmx8KB.mjs → reload-C-cV5yy_.mjs} +79 -20
- package/dist/{remote-cache-BRsRZru5.mjs → remote-cache--aehr4Pr.mjs} +3 -3
- package/dist/{server-bare-Gn3ssSdK.mjs → server-bare-Bq8BpSIo.mjs} +1 -1
- package/dist/server-expo-BeYwP_Xy.mjs +2 -0
- package/dist/{server-expo-CeT1nIIk.mjs → server-expo-DUCg52-K.mjs} +2 -2
- package/dist/{settings-bE-Gu3Ti.mjs → settings-ssVBToDR.mjs} +10 -10
- package/dist/{settings-BlyDn2Oz.mjs → settings-xB0Frkg6.mjs} +11 -2
- package/dist/settings.schema.json +53 -1
- package/dist/{simslim-COtEEP7x.mjs → simslim-Bbg9UWrt.mjs} +12 -6
- package/dist/{slot-launch-DIACGEfH.mjs → slot-launch-BIWEW-wI.mjs} +3 -3
- package/dist/{start-BboE1HIS.mjs → start-BZhItkiL.mjs} +11 -10
- package/dist/{start-BFstVBlx.mjs → start-Rw2GD3nV.mjs} +1 -1
- package/dist/{state-DcDgzfu3.mjs → state-DwAU2_-D.mjs} +1 -1
- package/dist/state-l1pYwOre.mjs +148 -0
- package/dist/{stats-DiCtmluY.mjs → stats-CaSwmsSZ.mjs} +2 -2
- package/dist/{status-DI9Tjo7T.mjs → status-TJlL0HWo.mjs} +624 -103
- package/dist/{status-BUASYyy_.mjs → status-sszP4XKU.mjs} +59 -2
- package/dist/{stim-desktop-D0xhpZt8.mjs → stim-desktop-CXt8-Z3J.mjs} +13 -2
- package/dist/{stop-Bn6v-GvS.mjs → stop-BZ2qMiBP.mjs} +37 -12
- package/dist/{stop-BI7QY76M.mjs → stop-DskDKNTU.mjs} +2 -2
- package/dist/supervisor-run.mjs +10 -10
- package/dist/web-run.d.mts +22 -0
- package/dist/web-run.mjs +481 -0
- package/dist/web-sWXd5iek.mjs +394 -0
- package/dist/{worktree-B5sTRskL.mjs → worktree-3cBa-bQt.mjs} +1 -1
- package/dist/{worktree-ChDL5fO1.mjs → worktree-D4Do_XiQ.mjs} +226 -19
- package/dist/{xcode-BzplpQzc.mjs → xcode-LM6A8cNZ.mjs} +5 -5
- package/package.json +5 -5
- package/dist/server-expo-eWi9Coof.mjs +0 -2
- package/dist/workspace-process-lock-BvvJTfo_.mjs +0 -57
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { WebSocket } from "ws";
|
|
2
|
+
//#region src/web/cdp.ts
|
|
3
|
+
const COMMAND_TIMEOUT_MS = 15e3;
|
|
4
|
+
function connectCdp(url, { timeoutMs = 5e3 } = {}) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const socket = new WebSocket(url, {
|
|
7
|
+
perMessageDeflate: false,
|
|
8
|
+
maxPayload: 268435456
|
|
9
|
+
});
|
|
10
|
+
const pending = /* @__PURE__ */ new Map();
|
|
11
|
+
const eventListeners = [];
|
|
12
|
+
const closeListeners = [];
|
|
13
|
+
let nextId = 1;
|
|
14
|
+
let closed = false;
|
|
15
|
+
const timer = setTimeout(() => {
|
|
16
|
+
socket.terminate();
|
|
17
|
+
reject(/* @__PURE__ */ new Error(`DevTools did not accept a connection at ${url} within ${timeoutMs}ms`));
|
|
18
|
+
}, timeoutMs);
|
|
19
|
+
socket.on("message", (data) => {
|
|
20
|
+
let message;
|
|
21
|
+
try {
|
|
22
|
+
message = JSON.parse(String(data));
|
|
23
|
+
} catch {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (typeof message.id === "number") {
|
|
27
|
+
const waiter = pending.get(message.id);
|
|
28
|
+
if (!waiter) return;
|
|
29
|
+
pending.delete(message.id);
|
|
30
|
+
if (message.error) waiter.reject(new Error(message.error.message ?? "DevTools command failed"));
|
|
31
|
+
else waiter.resolve(message.result ?? {});
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (typeof message.method === "string") {
|
|
35
|
+
const event = {
|
|
36
|
+
method: message.method,
|
|
37
|
+
params: message.params ?? {},
|
|
38
|
+
...message.sessionId ? { sessionId: message.sessionId } : {}
|
|
39
|
+
};
|
|
40
|
+
for (const listener of eventListeners) listener(event);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
socket.on("close", () => {
|
|
44
|
+
closed = true;
|
|
45
|
+
for (const waiter of pending.values()) waiter.reject(/* @__PURE__ */ new Error("DevTools connection closed"));
|
|
46
|
+
pending.clear();
|
|
47
|
+
for (const listener of closeListeners) listener();
|
|
48
|
+
});
|
|
49
|
+
socket.on("error", (error) => {
|
|
50
|
+
clearTimeout(timer);
|
|
51
|
+
reject(error);
|
|
52
|
+
});
|
|
53
|
+
socket.on("open", () => {
|
|
54
|
+
clearTimeout(timer);
|
|
55
|
+
resolve({
|
|
56
|
+
send(method, params = {}, sessionId) {
|
|
57
|
+
if (closed) return Promise.reject(/* @__PURE__ */ new Error("DevTools connection closed"));
|
|
58
|
+
const id = nextId++;
|
|
59
|
+
return new Promise((resolveCommand, rejectCommand) => {
|
|
60
|
+
const commandTimer = setTimeout(() => {
|
|
61
|
+
pending.delete(id);
|
|
62
|
+
rejectCommand(/* @__PURE__ */ new Error(`DevTools command ${method} timed out`));
|
|
63
|
+
}, COMMAND_TIMEOUT_MS);
|
|
64
|
+
pending.set(id, {
|
|
65
|
+
resolve: (value) => {
|
|
66
|
+
clearTimeout(commandTimer);
|
|
67
|
+
resolveCommand(value);
|
|
68
|
+
},
|
|
69
|
+
reject: (error) => {
|
|
70
|
+
clearTimeout(commandTimer);
|
|
71
|
+
rejectCommand(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
socket.send(JSON.stringify({
|
|
75
|
+
id,
|
|
76
|
+
method,
|
|
77
|
+
params,
|
|
78
|
+
...sessionId ? { sessionId } : {}
|
|
79
|
+
}));
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
onEvent(listener) {
|
|
83
|
+
eventListeners.push(listener);
|
|
84
|
+
},
|
|
85
|
+
onClose(listener) {
|
|
86
|
+
if (closed) listener();
|
|
87
|
+
else closeListeners.push(listener);
|
|
88
|
+
},
|
|
89
|
+
close() {
|
|
90
|
+
socket.close();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Connects to the browser DevTools endpoint on loopback `port` only when the process serving it is `chromePid`,
|
|
98
|
+
* the Chrome Stim started. Chrome reports its own browser process through `SystemInfo.getProcessInfo`.
|
|
99
|
+
*/
|
|
100
|
+
async function connectOwnedBrowser(port, chromePid) {
|
|
101
|
+
const { webSocketDebuggerUrl } = await (await fetch(`http://127.0.0.1:${port}/json/version`, { signal: AbortSignal.timeout(2e3) })).json();
|
|
102
|
+
if (typeof webSocketDebuggerUrl !== "string" || !webSocketDebuggerUrl.startsWith(`ws://127.0.0.1:${port}/`)) throw new Error(`port ${port} does not serve a browser DevTools endpoint`);
|
|
103
|
+
const cdp = await connectCdp(webSocketDebuggerUrl);
|
|
104
|
+
try {
|
|
105
|
+
const { processInfo } = await cdp.send("SystemInfo.getProcessInfo");
|
|
106
|
+
const browser = processInfo?.find((entry) => entry.type === "browser")?.id;
|
|
107
|
+
if (browser !== chromePid) throw new Error(`port ${port} is served by browser pid ${browser ?? "unknown"}, not the owned Chrome ${chromePid}`);
|
|
108
|
+
return cdp;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
cdp.close();
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { connectOwnedBrowser as t };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
//#region src/web/chrome.ts
|
|
6
|
+
const CHROME_INSTALL_REMEDY = "Install Google Chrome from https://www.google.com/chrome/ (or Chromium), then run `stim doctor`.";
|
|
7
|
+
const MAC_APPS = [["Google Chrome.app", "Google Chrome"], ["Chromium.app", "Chromium"]];
|
|
8
|
+
const PATH_NAMES = [
|
|
9
|
+
"google-chrome",
|
|
10
|
+
"google-chrome-stable",
|
|
11
|
+
"chromium",
|
|
12
|
+
"chromium-browser"
|
|
13
|
+
];
|
|
14
|
+
function chromeCandidates(host, { home = homedir(), env = process.env } = {}) {
|
|
15
|
+
if (host === "darwin") return ["/Applications", join(home, "Applications")].flatMap((dir) => MAC_APPS.map(([app, binary]) => join(dir, app, "Contents", "MacOS", binary)));
|
|
16
|
+
if (host === "win32") return [
|
|
17
|
+
env.PROGRAMFILES,
|
|
18
|
+
env["PROGRAMFILES(X86)"],
|
|
19
|
+
env.LOCALAPPDATA
|
|
20
|
+
].filter((dir) => Boolean(dir)).map((dir) => join(dir, "Google", "Chrome", "Application", "chrome.exe"));
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
/** The installed Chrome or Chromium executable Stim launches, or null when none is installed. */
|
|
24
|
+
function findChrome({ host = process.platform, exists = existsSync, findExecutable = (name) => getExecutor().findExecutable(name) } = {}) {
|
|
25
|
+
const installed = chromeCandidates(host).find((path) => exists(path));
|
|
26
|
+
if (installed) return installed;
|
|
27
|
+
for (const name of PATH_NAMES) {
|
|
28
|
+
const found = findExecutable(name);
|
|
29
|
+
if (found) return found;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const DESKTOP_WINDOW = {
|
|
34
|
+
width: 1280,
|
|
35
|
+
height: 800
|
|
36
|
+
};
|
|
37
|
+
const PHONE_SCREEN = {
|
|
38
|
+
width: 390,
|
|
39
|
+
height: 844,
|
|
40
|
+
deviceScaleFactor: 3
|
|
41
|
+
};
|
|
42
|
+
function chromeArgs({ profile, port, headless, ignoreCertificateErrors, viewport }) {
|
|
43
|
+
const window = viewport === "phone" ? PHONE_SCREEN : DESKTOP_WINDOW;
|
|
44
|
+
return [
|
|
45
|
+
`--user-data-dir=${profile}`,
|
|
46
|
+
`--remote-debugging-port=${port}`,
|
|
47
|
+
...headless ? ["--headless"] : [],
|
|
48
|
+
`--window-size=${window.width},${window.height}`,
|
|
49
|
+
"--no-first-run",
|
|
50
|
+
"--no-default-browser-check",
|
|
51
|
+
"--disable-search-engine-choice-screen",
|
|
52
|
+
"--disable-background-networking",
|
|
53
|
+
"--disable-sync",
|
|
54
|
+
"--password-store=basic",
|
|
55
|
+
"--use-mock-keychain",
|
|
56
|
+
...ignoreCertificateErrors ? ["--ignore-certificate-errors"] : [],
|
|
57
|
+
"about:blank"
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { findChrome as i, PHONE_SCREEN as n, chromeArgs as r, CHROME_INSTALL_REMEDY as t };
|
package/dist/cli.mjs
CHANGED
|
@@ -4,21 +4,22 @@ import { readFileSync } from "node:fs";
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
//#region bin/cli.ts
|
|
6
6
|
const commands = /* @__PURE__ */ new Map([
|
|
7
|
-
["doctor", () => import("./doctor-
|
|
8
|
-
["worktree", () => import("./worktree-
|
|
9
|
-
["start", () => import("./start-
|
|
10
|
-
["ports", () => import("./ports-
|
|
11
|
-
["stop", () => import("./stop-
|
|
12
|
-
["ios", () => import("./ios-
|
|
13
|
-
["android", () => import("./android-
|
|
14
|
-
["
|
|
15
|
-
["
|
|
16
|
-
["
|
|
17
|
-
["
|
|
18
|
-
["
|
|
19
|
-
["
|
|
20
|
-
["
|
|
21
|
-
["
|
|
7
|
+
["doctor", () => import("./doctor-D2iysNNH.mjs")],
|
|
8
|
+
["worktree", () => import("./worktree-3cBa-bQt.mjs")],
|
|
9
|
+
["start", () => import("./start-Rw2GD3nV.mjs")],
|
|
10
|
+
["ports", () => import("./ports-C5UutqpJ.mjs")],
|
|
11
|
+
["stop", () => import("./stop-DskDKNTU.mjs")],
|
|
12
|
+
["ios", () => import("./ios-CcfCeZ19.mjs")],
|
|
13
|
+
["android", () => import("./android-CD8pr8Q2.mjs")],
|
|
14
|
+
["web", () => import("./web-sWXd5iek.mjs")],
|
|
15
|
+
["reload", () => import("./reload-C-cV5yy_.mjs")],
|
|
16
|
+
["device", () => import("./device-Cf7vl-so.mjs")],
|
|
17
|
+
["logs", () => import("./logs-DcSRbC2t.mjs")],
|
|
18
|
+
["settings", () => import("./settings-ssVBToDR.mjs")],
|
|
19
|
+
["status", () => import("./status-TJlL0HWo.mjs")],
|
|
20
|
+
["stats", () => import("./stats-CaSwmsSZ.mjs")],
|
|
21
|
+
["gc", () => import("./gc-eA-PRBX8.mjs")],
|
|
22
|
+
["guide", () => import("./guide-BfZ0OmiP.mjs")]
|
|
22
23
|
]);
|
|
23
24
|
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
24
25
|
const program = new Command();
|
package/dist/collector-run.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { G as validateDeviceSlot, O as process_identity_exports, z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
3
|
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { M as workspaceLogsDir } from "./metro-BPeY1YMh.mjs";
|
|
5
5
|
import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
6
6
|
import { a as startIosDeviceConsole, i as parseDeviceConsoleLine } from "./ios-device-BiOsSVzd.mjs";
|
|
7
|
-
import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-
|
|
8
|
-
import { a as watchAppPid, i as waitForAppPid, n as parseLogcatLine, r as startAndroidLogcat, t as androidClockOffset } from "./android-
|
|
7
|
+
import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-Bz2kETAS.mjs";
|
|
8
|
+
import { a as watchAppPid, i as waitForAppPid, n as parseLogcatLine, r as startAndroidLogcat, t as androidClockOffset } from "./android-BHfAu2mf.mjs";
|
|
9
9
|
import { existsSync } from "node:fs";
|
|
10
10
|
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
11
11
|
import { isAbsolute, join, resolve } from "node:path";
|
|
@@ -95,6 +95,12 @@ const NOISE_RULES = [
|
|
|
95
95
|
exactSubsystem: "com.apple.UIKit",
|
|
96
96
|
category: "UIFocus",
|
|
97
97
|
messageEquals: "RCTScrollViewComponentView implements focusItemsInRect: - caching for linear focus movement is limited as long as this view is on screen."
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "cfnetwork-performance-diagnostic",
|
|
101
|
+
exactSubsystem: "com.apple.runtime-issues",
|
|
102
|
+
category: "CFNetwork Performance Diagnostic",
|
|
103
|
+
level: "warn"
|
|
98
104
|
}
|
|
99
105
|
];
|
|
100
106
|
function ruleMatches(rule, { subsystem, category, message }) {
|
|
@@ -106,21 +112,21 @@ function ruleMatches(rule, { subsystem, category, message }) {
|
|
|
106
112
|
if (rule.messageIncludes && !rule.messageIncludes.some((p) => message.includes(p))) return false;
|
|
107
113
|
return true;
|
|
108
114
|
}
|
|
109
|
-
function
|
|
115
|
+
function matchingNoiseRule(event) {
|
|
110
116
|
const subsystem = typeof event?.subsystem === "string" ? event.subsystem : "";
|
|
111
117
|
const category = typeof event?.category === "string" ? event.category : "";
|
|
112
118
|
const message = typeof event?.eventMessage === "string" ? event.eventMessage : "";
|
|
113
|
-
|
|
119
|
+
return NOISE_RULES.find((rule) => ruleMatches(rule, {
|
|
114
120
|
subsystem,
|
|
115
121
|
category,
|
|
116
122
|
message
|
|
117
|
-
}))
|
|
118
|
-
return null;
|
|
123
|
+
}));
|
|
119
124
|
}
|
|
120
125
|
function levelForEvent(event) {
|
|
121
126
|
const level = levelFromMessageType(event?.messageType);
|
|
122
127
|
if (level !== "error" && level !== "fatal") return level;
|
|
123
|
-
|
|
128
|
+
const rule = matchingNoiseRule(event);
|
|
129
|
+
return rule ? rule.level ?? "info" : level;
|
|
124
130
|
}
|
|
125
131
|
function procFromImagePath(path) {
|
|
126
132
|
if (typeof path !== "string" || !path) return null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as NO_PROJECT_REFUSAL } from "./project-
|
|
1
|
+
import { t as NO_PROJECT_REFUSAL } from "./project-DGeclhvO.mjs";
|
|
2
2
|
import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
|
|
3
3
|
import { quotedPath } from "@stim-cli/core";
|
|
4
4
|
import chalk from "chalk";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { d as getConfigDir } from "./config-0jCcMM0E.mjs";
|
|
2
|
+
import { F as withDirLock } from "./metro-BPeY1YMh.mjs";
|
|
3
|
+
import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { createdDevicesFile, createdDevicesLock, readCreatedDevices, readCreatedDevices as readCreatedDevices$1 } from "@stim-cli/core/state";
|
|
5
|
+
//#region src/devices/created-devices.ts
|
|
6
|
+
function update(platform, change) {
|
|
7
|
+
const dir = getConfigDir();
|
|
8
|
+
withDirLock(createdDevicesLock(), () => {
|
|
9
|
+
const current = readCreatedDevices();
|
|
10
|
+
const entries = new Set(current[platform]);
|
|
11
|
+
if (!change(entries)) return;
|
|
12
|
+
const next = {
|
|
13
|
+
version: 1,
|
|
14
|
+
ios: [...current.ios],
|
|
15
|
+
android: [...current.android],
|
|
16
|
+
web: [...current.web],
|
|
17
|
+
[platform]: [...entries]
|
|
18
|
+
};
|
|
19
|
+
const file = createdDevicesFile();
|
|
20
|
+
const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
21
|
+
writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`);
|
|
22
|
+
try {
|
|
23
|
+
renameSync(tmp, file);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
rmSync(tmp, { force: true });
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}, { ensureParent: () => mkdirSync(dir, { recursive: true }) });
|
|
29
|
+
}
|
|
30
|
+
function recordCreatedDevice(platform, id) {
|
|
31
|
+
update(platform, (entries) => entries.size !== entries.add(id).size);
|
|
32
|
+
}
|
|
33
|
+
function forgetCreatedDevice(platform, id) {
|
|
34
|
+
update(platform, (entries) => entries.delete(id));
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { readCreatedDevices$1 as n, recordCreatedDevice as r, forgetCreatedDevice as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
2
|
import { a as spawnDeclared } from "./spawn-claims-PT8aQpCa.mjs";
|
|
3
3
|
import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
4
|
-
import { d as startBuildHeartbeat, m as bundlerPin, n as HEARTBEAT_INTERVAL_MS } from "./xcode-
|
|
4
|
+
import { d as startBuildHeartbeat, m as bundlerPin, n as HEARTBEAT_INTERVAL_MS } from "./xcode-LM6A8cNZ.mjs";
|
|
5
5
|
import { existsSync, readFileSync } from "node:fs";
|
|
6
6
|
import { delimiter, dirname, join, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { homedir } from "node:os";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { H as parseDeviceSlotOption, U as projectDeviceSlots, p as getProject, z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { r as clockTime } from "./command-output-
|
|
4
|
-
import { n as fileLeaseIo, o as parseLeaseDuration, p as takeLease, u as releaseWorkspaceLeases } from "./device-lease-
|
|
5
|
-
import {
|
|
6
|
-
import { d as waitForDevice, s as parseDeviceWait, t as selectFromPool } from "./device-pool-
|
|
7
|
-
import { a as iosPoolCandidates, c as listIosDevices, o as iosPoolNoCandidatesRefusal, s as isWirelessIosDevice, u as resolveIosPhysicalDevice } from "./ios-device-
|
|
2
|
+
import { a as findProjectRoot, t as NO_PROJECT_REFUSAL } from "./project-DGeclhvO.mjs";
|
|
3
|
+
import { r as clockTime } from "./command-output-BIL7rlX7.mjs";
|
|
4
|
+
import { n as fileLeaseIo, o as parseLeaseDuration, p as takeLease, u as releaseWorkspaceLeases } from "./device-lease-CL9dZf73.mjs";
|
|
5
|
+
import { D as listAdbDevices, H as physicalDeviceModel, J as resolvePhysicalDevice, M as memoizeEmulatorProbe, T as getAvdNameForSerial, W as probeEmulatorSerial, o as androidPoolCandidates, s as androidPoolNoCandidatesRefusal } from "./android-qx_31wJo.mjs";
|
|
6
|
+
import { d as waitForDevice, s as parseDeviceWait, t as selectFromPool } from "./device-pool-MuoiyRcu.mjs";
|
|
7
|
+
import { a as iosPoolCandidates, c as listIosDevices, o as iosPoolNoCandidatesRefusal, s as isWirelessIosDevice, u as resolveIosPhysicalDevice } from "./ios-device-BW-t_Lkv.mjs";
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
//#region src/commands/device.ts
|
|
10
10
|
const DEFAULT_FOR = "5m";
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { A as ownership_claim_exports, G as validateDeviceSlot, V as parseDeviceSlotKey, d as getConfigDir, z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
3
|
import { r as register } from "./cache-manifest-DWPF4RKJ.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { C as sharedBuildCache, F as withDirLock, b as writeWorkspaceState, h as readWorkspaceState, m as clearWorkspaceStateKeys, v as withWorkspaceStateLock } from "./metro-BPeY1YMh.mjs";
|
|
5
5
|
import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-PT8aQpCa.mjs";
|
|
6
|
-
import { a as formatElapsed, i as formatDuration, m as shortHash } from "./command-output-
|
|
6
|
+
import { a as formatElapsed, i as formatDuration, m as shortHash } from "./command-output-BIL7rlX7.mjs";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
9
9
|
import { join } from "path";
|
|
10
10
|
import { artifactIn, buildCacheKey, resolveArtifact, storeArtifact } from "@stim-cli/core";
|
|
11
11
|
import { join as join$1 } from "node:path";
|
|
12
12
|
import { createHash, randomBytes } from "node:crypto";
|
|
13
|
+
import { isDeepStrictEqual } from "util";
|
|
13
14
|
import * as expoFingerprint from "@expo/fingerprint";
|
|
14
15
|
import { buildUploadTimeoutMs } from "@stim-cli/cache";
|
|
15
16
|
const ASSET_MANIFEST_FILE = "assets-manifest.json";
|
|
@@ -388,6 +389,54 @@ async function refingerprintAfterMutation({ projectRoot, platform, previousHash,
|
|
|
388
389
|
moved: computed.hash !== previousHash
|
|
389
390
|
};
|
|
390
391
|
}
|
|
392
|
+
const CONFIG_INPUT_REASONS = /* @__PURE__ */ new Set([
|
|
393
|
+
"expoConfig",
|
|
394
|
+
"expoConfigPlugins",
|
|
395
|
+
"expoConfigExternalFile"
|
|
396
|
+
]);
|
|
397
|
+
function writtenByBuild(name, platform) {
|
|
398
|
+
return name === platform || name.startsWith(`${platform}/`) || name.startsWith("node_modules/") || name.includes("/node_modules/");
|
|
399
|
+
}
|
|
400
|
+
const PREBUILD_WRITTEN_IDS = [["ios", "bundleIdentifier"], ["android", "package"]];
|
|
401
|
+
function expoConfigContents(sources) {
|
|
402
|
+
const source = sources.find((s) => s.type === "contents" && s.id === "expoConfig");
|
|
403
|
+
if (source?.type !== "contents") return null;
|
|
404
|
+
try {
|
|
405
|
+
const parsed = JSON.parse(String(source.contents));
|
|
406
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
407
|
+
} catch {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function onlyPrebuildIdsAdded(before, after) {
|
|
412
|
+
const previous = expoConfigContents(before);
|
|
413
|
+
const current = expoConfigContents(after);
|
|
414
|
+
if (!previous || !current) return false;
|
|
415
|
+
const stripped = { ...current };
|
|
416
|
+
for (const [section, key] of PREBUILD_WRITTEN_IDS) {
|
|
417
|
+
const was = previous[section];
|
|
418
|
+
const now = stripped[section];
|
|
419
|
+
if (now?.[key] === void 0 || was?.[key] !== void 0) continue;
|
|
420
|
+
const rest = { ...now };
|
|
421
|
+
delete rest[key];
|
|
422
|
+
if (was === void 0 && Object.keys(rest).length === 0) delete stripped[section];
|
|
423
|
+
else stripped[section] = rest;
|
|
424
|
+
}
|
|
425
|
+
return isDeepStrictEqual(previous, stripped);
|
|
426
|
+
}
|
|
427
|
+
function configInputsChanged(before, after, { prebuildRan }) {
|
|
428
|
+
return compareSourceLists(before, after).filter((change) => change.reasons.some((reason) => CONFIG_INPUT_REASONS.has(reason))).filter((change) => !(prebuildRan && change.name === "expoConfig" && onlyPrebuildIdsAdded(before, after))).map((change) => change.name);
|
|
429
|
+
}
|
|
430
|
+
function inputsChangedDuringBuild({ platform, lookup, prebuildRan, compiled, current }) {
|
|
431
|
+
const names = new Set(configInputsChanged(lookup, current, { prebuildRan }));
|
|
432
|
+
for (const change of compareSourceLists(compiled, current)) if (!writtenByBuild(change.name, platform)) names.add(change.name);
|
|
433
|
+
return [...names];
|
|
434
|
+
}
|
|
435
|
+
function changedDuringBuildLine(changed) {
|
|
436
|
+
const shown = changed.slice(0, 3);
|
|
437
|
+
const more = changed.length > shown.length ? `, and ${changed.length - shown.length} more` : "";
|
|
438
|
+
return `${shown.join(", ")}${more} changed while the build ran, so the artifact may not match its key; the build will be installed but not cached`;
|
|
439
|
+
}
|
|
391
440
|
function untrackedNativeFiles({ projectRoot, exec = getExecutor() }) {
|
|
392
441
|
let out;
|
|
393
442
|
try {
|
|
@@ -1055,4 +1104,4 @@ function withHolderLock(io, root, fn) {
|
|
|
1055
1104
|
return io.withHolderLock ? io.withHolderLock(root, fn) : fn();
|
|
1056
1105
|
}
|
|
1057
1106
|
//#endregion
|
|
1058
|
-
export {
|
|
1107
|
+
export { providerDownloadPath as A, captureAssetManifest as B, diffFingerprintSources as C, fingerprintProject as D, fingerprintDiffRecord as E, storedAssetManifest as F, readAssetManifest as H, storedSources as I, untrackedMissLine as L, refingerprintAfterMutation as M, resolveBuild as N, inputsChangedDuringBuild as O, storeBuild as P, untrackedNativeFiles as R, configInputsChanged as S, filesystemBuildCapability as T, compareAssetManifests as V, waitForBuild as _, parseLease as a, buildCacheKey as b, raiseLease as c, removeExpiredLease as d, selectPoolDevice as f, releaseBuildLock as g, listBuildLocks as h, listLeaseFiles as i, providerUploadOutcome as j, prepareProviderDownloadDir as k, releaseRunLease as l, acquireBuildLock as m, fileLeaseIo as n, parseLeaseDuration as o, takeLease as p, leaseIsExpired as r, parseWorkspaceLeases as s, deviceLeasePath as t, releaseWorkspaceLeases as u, waitForSharedBuild as v, entryDir as w, changedDuringBuildLine as x, artifactIn as y, assetDiffReason as z };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
|
|
2
|
-
import { a as formatElapsed, r as clockTime } from "./command-output-
|
|
3
|
-
import { a as parseLease, c as raiseLease, f as selectPoolDevice, l as releaseRunLease, n as fileLeaseIo, p as takeLease, r as leaseIsExpired, t as deviceLeasePath } from "./device-lease-
|
|
4
|
-
import { a as VERIFY_TIMEOUT_MS, p as APP_READINESS_TIMEOUT_MS } from "./launch-verify-
|
|
2
|
+
import { a as formatElapsed, r as clockTime } from "./command-output-BIL7rlX7.mjs";
|
|
3
|
+
import { a as parseLease, c as raiseLease, f as selectPoolDevice, l as releaseRunLease, n as fileLeaseIo, p as takeLease, r as leaseIsExpired, t as deviceLeasePath } from "./device-lease-CL9dZf73.mjs";
|
|
4
|
+
import { a as VERIFY_TIMEOUT_MS, p as APP_READINESS_TIMEOUT_MS } from "./launch-verify-CuJaBpEa.mjs";
|
|
5
5
|
//#region src/engine/device-lease-run.ts
|
|
6
6
|
const LEASE_STEP_FLOOR_MS = 6e4;
|
|
7
7
|
const DEBUG_VERIFY_STEP_MS = VERIFY_TIMEOUT_MS + APP_READINESS_TIMEOUT_MS;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { d as getConfigDir } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as clearRemoteSession, c as readMetroTunnel, u as readRemoteSession } from "./state-
|
|
3
|
+
import { A as workspaceId, F as withDirLock, M as workspaceLogsDir, P as workspaceStateFile, _ as updateWorkspaceState, a as pidExists, h as readWorkspaceState$1, k as workspaceDir, p as clearWorkspaceStateKey } from "./metro-BPeY1YMh.mjs";
|
|
4
|
+
import { c as ownedDeviceLabel } from "./project-DGeclhvO.mjs";
|
|
5
|
+
import { a as clearRemoteSession, c as readMetroTunnel, u as readRemoteSession } from "./state-DwAU2_-D.mjs";
|
|
6
6
|
import { i as signalDeclaredSpawns, r as refuseDeclaredSpawns, t as allowDeclaredSpawns } from "./spawn-claims-PT8aQpCa.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import { a as formatElapsed } from "./command-output-
|
|
9
|
-
import {
|
|
10
|
-
import { u as probePublicHttp } from "./ownership-
|
|
11
|
-
import { C as sanitizeDeviceLabel } from "./ios-
|
|
12
|
-
import { a as LAUNCH_ERROR, i as INSTALL_ERROR, l as devClientDeepLink } from "./app-install-
|
|
13
|
-
import { c as readMetroRecords, o as isBundleProof } from "./launch-verify-
|
|
7
|
+
import { a as withWorkspaceProcessLock } from "./named-ports-n7tnJsI8.mjs";
|
|
8
|
+
import { a as formatElapsed } from "./command-output-BIL7rlX7.mjs";
|
|
9
|
+
import { V as planMetroReach } from "./settings-xB0Frkg6.mjs";
|
|
10
|
+
import { u as probePublicHttp } from "./ownership-PUP4Dwai.mjs";
|
|
11
|
+
import { C as sanitizeDeviceLabel } from "./ios-CmEzZiOj.mjs";
|
|
12
|
+
import { a as LAUNCH_ERROR, i as INSTALL_ERROR, l as devClientDeepLink } from "./app-install-CDFY2nUL.mjs";
|
|
13
|
+
import { c as readMetroRecords, o as isBundleProof } from "./launch-verify-CuJaBpEa.mjs";
|
|
14
14
|
import { t as compareStimVersions } from "./stim-installations-CINXy_su.mjs";
|
|
15
15
|
import { existsSync, mkdirSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { easMachineStateRoot, easMachineStateRoot as easMachineStateRoot$1, easSessionLedgerFile, easSessionLedgerLock, readEasSessionLedger, readEasSessionLedger as readEasSessionLedger$1, readJsonObject, validEasSessionClaim } from "@stim-cli/core/state";
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { _ as loadConfig$1, s as configCorruptRepair, u as getConcurrencyLimits } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { C as sharedBuildCache, O as workspaceDerivedData } from "./metro-BPeY1YMh.mjs";
|
|
4
4
|
import { D as makeTemporaryDirectory, E as filesystemDevice, a as dirtyFingerprintFiles, h as locallyKnownUpstream, k as temporaryRoot, m as listWorktrees, s as gitCommonDir, x as resolveSourceCheckout, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { d as quotedPath, f as refuseNoProject, l as phaseLine, u as plural } from "./command-output-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { F as settingsLayers,
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { f as resolveEasCliBin, i as checkEasAuth$1, l as ownerFromConfig, u as providerFromConfig } from "./remote-cache
|
|
14
|
-
import { D as MIN_EAS_CLI_SIMULATOR_VERSION, O as easCliSupport, k as easCliUpgradeRemedy, s as readInstalledEasCliVersion } from "./device-remote-
|
|
5
|
+
import { a as findProjectRoot, n as appProjectProblem, r as detectIsExpo, s as isPackageResolvable } from "./project-DGeclhvO.mjs";
|
|
6
|
+
import { d as quotedPath, f as refuseNoProject, l as phaseLine, u as plural } from "./command-output-BIL7rlX7.mjs";
|
|
7
|
+
import { C as diffFingerprintSources, D as fingerprintProject, h as listBuildLocks } from "./device-lease-CL9dZf73.mjs";
|
|
8
|
+
import { D as listAdbDevices, E as hostSystemImageArch, a as androidHome, ct as parkedMaxSetting, rt as POOL_SETTING_REMEDY } from "./android-qx_31wJo.mjs";
|
|
9
|
+
import { F as settingsLayers, G as resolveOptimizations, L as unknownSettingKeys, N as settingOrigin, O as remoteAndroidSetting, P as settingShapeErrors, R as webSettings, T as projectOptimizations, U as compilerCacheFallbackMessage, a as SETTING_SHAPE_REMEDY, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, j as resolveSettings, k as remoteIosSetting, n as PATH_SETTINGS, v as iosSimSlimProfileSetting, y as mergeSettingsLayers } from "./settings-xB0Frkg6.mjs";
|
|
10
|
+
import { O as hostMemoryPressureAdvice, k as readHostMemoryPressure, l as listAllIosSims } from "./ios-CmEzZiOj.mjs";
|
|
11
|
+
import { o as listBuildSlots } from "./in-use-wYEaKQM9.mjs";
|
|
12
|
+
import { i as findChrome, t as CHROME_INSTALL_REMEDY } from "./chrome-B5hWgQJS.mjs";
|
|
13
|
+
import { f as resolveEasCliBin, i as checkEasAuth$1, l as ownerFromConfig, u as providerFromConfig } from "./remote-cache--aehr4Pr.mjs";
|
|
14
|
+
import { D as MIN_EAS_CLI_SIMULATOR_VERSION, O as easCliSupport, k as easCliUpgradeRemedy, s as readInstalledEasCliVersion } from "./device-remote-DT9ngZiD.mjs";
|
|
15
15
|
import { n as inspectStimVersions, t as compareStimVersions } from "./stim-installations-CINXy_su.mjs";
|
|
16
|
-
import { a as liveOwnedDeviceCount,
|
|
17
|
-
import { n as budgetLine, r as inspectBudget } from "./budget-
|
|
18
|
-
import {
|
|
19
|
-
import { h as podInstallCommand, i as ccacheEnabled, o as detectXcodeMajor } from "./xcode-
|
|
20
|
-
import { n as recordDoctorRun } from "./guide-status-
|
|
16
|
+
import { a as liveOwnedDeviceCount, d as MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION, n as simslimIsOnPath } from "./simslim-Bbg9UWrt.mjs";
|
|
17
|
+
import { n as budgetLine, r as inspectBudget } from "./budget-E5o91NR1.mjs";
|
|
18
|
+
import { _ as androidPathRoomRemedy, a as apkOutputsDir, f as projectCmakeLauncher, g as androidPathRoomMessage, h as androidPathRoom, i as androidSdkRefusal, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-B9Kv9aIy.mjs";
|
|
19
|
+
import { h as podInstallCommand, i as ccacheEnabled, o as detectXcodeMajor } from "./xcode-LM6A8cNZ.mjs";
|
|
20
|
+
import { n as recordDoctorRun } from "./guide-status-BaMYu55M.mjs";
|
|
21
21
|
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-DNN0yfx6.mjs";
|
|
22
22
|
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
23
23
|
import { InvalidArgumentError } from "commander";
|
|
@@ -846,6 +846,15 @@ function checkCcacheConflict(podfileSource, podfileProperties) {
|
|
|
846
846
|
if (!ccacheEnabled(podfileProperties)) return null;
|
|
847
847
|
return finding("cost", "ccache is enabled, so Stim leaves Xcode compilation caching off", "The ccache launcher script is what disables explicitly built modules, which compilation caching requires -- so enabling both tends to mean neither works. Stim will not add its compilation-cache settings to a build whose project has apple.ccacheEnabled=true, and in its default configuration ccache hashes the working directory and every absolute include path, so it misses across worktrees. (Stim relocates ccache itself on Android, where it drives the compile and can set CCACHE_BASEDIR and CCACHE_NOHASHDIR; the Podfile launcher script here is the project's, not Stim's.)", "Pick one, and on Xcode 26 the compilation cache is the one that survives a different workspace path -- Stim supplies it on its own builds as soon as ccache is off. Turn it off where the value comes FROM: on Expo that is the expo-build-properties plugin in the app config (ios.ccacheEnabled), because prebuild rewrites ios/Podfile.properties.json from it; on a bare project edit ios/Podfile.properties.json directly. Then re-run pod install (or let `stim ios` do it).");
|
|
848
848
|
}
|
|
849
|
+
function checkChrome({ usesWeb, chrome = findChrome }) {
|
|
850
|
+
if (!usesWeb() || chrome()) return null;
|
|
851
|
+
return finding("cost", "No Chrome is installed, so `stim web` cannot open this app", "`stim web` drives the installed Google Chrome or Chromium with a Stim-owned profile, and found neither in /Applications, ~/Applications, Program Files or on PATH. This project renders on the web (web.url is set, app.json lists the web platform, or react-native-web is installed).", CHROME_INSTALL_REMEDY);
|
|
852
|
+
}
|
|
853
|
+
function projectUsesWeb(projectRoot, settings, appConfig, platform) {
|
|
854
|
+
if (platform) return false;
|
|
855
|
+
const platforms = (appConfig?.expo ?? appConfig)?.platforms;
|
|
856
|
+
return webSettings(settings).url !== null || Array.isArray(platforms) && platforms.includes("web") || isPackageResolvable(projectRoot, "react-native-web");
|
|
857
|
+
}
|
|
849
858
|
function checkCcacheInstalled(onPath) {
|
|
850
859
|
if (onPath) return null;
|
|
851
860
|
return finding("cost", "ccache is not on PATH, so Android C++ recompiles in every worktree", "Stim resolves the launcher with a PATH lookup for `ccache` -- the same lookup the build itself uses -- and found nothing, so it passes no CMAKE_C_COMPILER_LAUNCHER / CMAKE_CXX_COMPILER_LAUNCHER to Gradle and every AGP CMake task compiles without one. Those tasks are uncacheable by Gradle, so not one C++ object crosses a worktree. Measured on trailhead (arm64, fresh worktree): 49.6s without the launcher against 34.2s with it.", "brew install ccache, then delete android/app/.cxx and node_modules/**/android/.cxx once so CMake reconfigures with the launcher. The shell that runs Stim must have the install location on PATH -- agent shells often lack /opt/homebrew/bin.");
|
|
@@ -955,7 +964,7 @@ function checkXcodeEnvLineEndings(projectRoot, platform, host) {
|
|
|
955
964
|
if (!content.includes("\r")) return null;
|
|
956
965
|
return finding("cost", "ios/.xcode.env has CRLF line endings", "An EAS build uploads the working-tree bytes of ios/.xcode.env, and Xcode sources that file with sh on the build worker, where each carriage return becomes part of the line and the build fails with `: command not found`. On Windows the usual cause is core.autocrlf=true rewriting the file at checkout.", "Run `git config core.autocrlf input` then `git checkout -- ios/.xcode.env`, or add `ios/.xcode.env text eol=lf` to .gitattributes and check the file out again.");
|
|
957
966
|
}
|
|
958
|
-
function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null, easAuth = checkEasAuth$1, concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, remoteEnv = process.env, lookupAgentDevice = null, lookupEasCli = null, lookupSimSlim = null, memoryPressure = readHostMemoryPressure, lookupCcache = null, platform, host = process.platform } = {}) {
|
|
967
|
+
function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null, easAuth = checkEasAuth$1, concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, remoteEnv = process.env, lookupAgentDevice = null, lookupEasCli = null, lookupSimSlim = null, memoryPressure = readHostMemoryPressure, lookupCcache = null, lookupChrome, platform, host = process.platform } = {}) {
|
|
959
968
|
const localIos = platform !== "android" && host === "darwin";
|
|
960
969
|
const read = (rel) => {
|
|
961
970
|
const p = join(projectRoot, rel);
|
|
@@ -1062,6 +1071,11 @@ function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null,
|
|
|
1062
1071
|
localIos && optimizations?.ios.compilationCache ? checkCcacheConflict(podfile, podfileProperties) : null,
|
|
1063
1072
|
...platform === "ios" || optimizations?.android.compilerCache !== "ccache" ? [] : androidCcacheFindings(projectRoot, platform, lookupCcache),
|
|
1064
1073
|
checkAndroidPathRoom(projectRoot, platform, host),
|
|
1074
|
+
checkAndroidSdk(projectRoot, platform),
|
|
1075
|
+
checkChrome({
|
|
1076
|
+
usesWeb: () => projectUsesWeb(projectRoot, projectSettings, appConfig, platform),
|
|
1077
|
+
chrome: lookupChrome
|
|
1078
|
+
}),
|
|
1065
1079
|
remoteBuildCache ? checkBuildCacheProvider(appConfig, sdkMajor, isExpo, dynamicConfig) : null,
|
|
1066
1080
|
easFinding,
|
|
1067
1081
|
easBuildDownloadFinding,
|
|
@@ -1090,6 +1104,21 @@ function checkAndroidPathRoom(projectRoot, platform, host, hostArch = process.ar
|
|
|
1090
1104
|
...finding("cost", "The project path leaves no room for Android native object paths", `${androidPathRoomMessage(room)} \`stim android\` refuses to build here with STIM_PATH_TOO_LONG, because Gradle would fail deep inside ninja instead.`, androidPathRoomRemedy(room))
|
|
1091
1105
|
};
|
|
1092
1106
|
}
|
|
1107
|
+
function checkAndroidSdk(projectRoot, platform) {
|
|
1108
|
+
const androidDir = join(projectRoot, "android");
|
|
1109
|
+
if (platform === "ios" || platform !== "android" && !existsSync$1(androidDir)) return null;
|
|
1110
|
+
const sdkPath = androidHome();
|
|
1111
|
+
const refusal = androidSdkRefusal({
|
|
1112
|
+
sdkPath,
|
|
1113
|
+
sdkExists: existsSync$1(sdkPath),
|
|
1114
|
+
hasLocalProperties: existsSync$1(join(androidDir, "local.properties"))
|
|
1115
|
+
});
|
|
1116
|
+
if (!refusal) return null;
|
|
1117
|
+
return {
|
|
1118
|
+
code: "android-sdk-missing",
|
|
1119
|
+
...finding("cost", "No Android SDK was found", `${refusal.reason} \`stim android\` refuses with ${refusal.code} before Gradle runs.`, refusal.remedy)
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1093
1122
|
function androidCcacheFindings(projectRoot, platform, lookupCcache) {
|
|
1094
1123
|
if (platform !== "android" && !existsSync$1(join(projectRoot, "android"))) return [];
|
|
1095
1124
|
const onPath = lookupCcache ? lookupCcache() : ccacheIsOnPath();
|
|
@@ -1342,7 +1371,7 @@ function doctorSuccessLines(platform, stim, budget = null) {
|
|
|
1342
1371
|
}
|
|
1343
1372
|
if (platform !== "ios") {
|
|
1344
1373
|
lines.push("", "Android");
|
|
1345
|
-
lines.push(phaseLine("setup", "warm state"));
|
|
1374
|
+
lines.push(phaseLine("setup", "Android SDK, warm state"));
|
|
1346
1375
|
lines.push(phaseLine("caches", "Metro, Gradle, ccache, build provider"));
|
|
1347
1376
|
lines.push(phaseLine("devices", "remote device"));
|
|
1348
1377
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { B as deviceSlotPlatforms, p as getProject, z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { f as readWorkspaceLaunches } from "./state-
|
|
5
|
-
import { v as launchErrorPreview } from "./command-output-
|
|
6
|
-
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-
|
|
7
|
-
import { a as androidHome, l as androidToolCwd } from "./android-
|
|
3
|
+
import { F as withDirLock, c as resolveProjectMetro, h as readWorkspaceState$1 } from "./metro-BPeY1YMh.mjs";
|
|
4
|
+
import { f as readWorkspaceLaunches } from "./state-DwAU2_-D.mjs";
|
|
5
|
+
import { v as launchErrorPreview } from "./command-output-BIL7rlX7.mjs";
|
|
6
|
+
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-CL9dZf73.mjs";
|
|
7
|
+
import { a as androidHome, l as androidToolCwd } from "./android-qx_31wJo.mjs";
|
|
8
8
|
import { r as deviceConsoleLevel } from "./ios-device-BiOsSVzd.mjs";
|
|
9
|
-
import { n as parseLogcatLine, t as androidClockOffset } from "./android-
|
|
9
|
+
import { n as parseLogcatLine, t as androidClockOffset } from "./android-BHfAu2mf.mjs";
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { attachExpoErrorContext, readLogRecords, sortByTs } from "@stim-cli/core/state";
|
|
12
12
|
import { basename, dirname, join, resolve, sep } from "node:path";
|