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,120 @@
|
|
|
1
|
+
//#region src/workspace/pull-request.d.ts
|
|
2
|
+
interface GhPullRequest {
|
|
3
|
+
number: number;
|
|
4
|
+
state: string;
|
|
5
|
+
url: string;
|
|
6
|
+
headRefOid: string;
|
|
7
|
+
mergedAt: string | null;
|
|
8
|
+
closedAt: string | null;
|
|
9
|
+
isCrossRepository?: boolean;
|
|
10
|
+
isDraft?: boolean;
|
|
11
|
+
headRepository?: {
|
|
12
|
+
name?: string | null;
|
|
13
|
+
} | null;
|
|
14
|
+
headRepositoryOwner?: {
|
|
15
|
+
login?: string | null;
|
|
16
|
+
} | null;
|
|
17
|
+
title?: string;
|
|
18
|
+
reviewDecision?: string | null;
|
|
19
|
+
commits?: {
|
|
20
|
+
nodes?: {
|
|
21
|
+
commit?: {
|
|
22
|
+
statusCheckRollup?: GhCheckRollup | null;
|
|
23
|
+
};
|
|
24
|
+
}[];
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
interface GhStateCount {
|
|
28
|
+
state: string;
|
|
29
|
+
count: number;
|
|
30
|
+
}
|
|
31
|
+
interface GhCheckRollup {
|
|
32
|
+
contexts?: {
|
|
33
|
+
checkRunCountsByState?: GhStateCount[];
|
|
34
|
+
statusContextCountsByState?: GhStateCount[];
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
interface CheckCounts {
|
|
38
|
+
passing: number;
|
|
39
|
+
failing: number;
|
|
40
|
+
pending: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The pull request whose head branch is the worktree's branch and whose commits include the worktree's HEAD.
|
|
44
|
+
* `containsHead` is false when the pull request's head is an ancestor of HEAD: HEAD has commits the pull request
|
|
45
|
+
* never had. `endedAt` is when it was merged or closed, in epoch milliseconds, and null while it is open.
|
|
46
|
+
*/
|
|
47
|
+
interface PullRequestFact {
|
|
48
|
+
number: number;
|
|
49
|
+
state: "open" | "merged" | "closed";
|
|
50
|
+
draft: boolean;
|
|
51
|
+
url: string;
|
|
52
|
+
head: string;
|
|
53
|
+
containsHead: boolean;
|
|
54
|
+
endedAt: number | null;
|
|
55
|
+
/** Present when the lookup asked for detail. */
|
|
56
|
+
title?: string;
|
|
57
|
+
reviewDecision?: "approved" | "changes-requested" | "review-required" | null;
|
|
58
|
+
checks?: CheckCounts | null;
|
|
59
|
+
}
|
|
60
|
+
/** Sums a head commit's check runs and commit statuses by outcome; null when the commit has no checks. */
|
|
61
|
+
declare function checkCounts(rollup: GhCheckRollup | null | undefined): CheckCounts | null;
|
|
62
|
+
type PullRequestLookup = {
|
|
63
|
+
pullRequest: PullRequestFact | null;
|
|
64
|
+
} | {
|
|
65
|
+
unavailable: string;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Picks the pull request that describes `head` among those `gh pr list --head <branch>` returned. One whose head is
|
|
69
|
+
* `head` wins, then one whose head contains `head`, then one whose head `head` contains. An open one wins a tier,
|
|
70
|
+
* then the newest. A pull request unrelated to `head` is from an earlier use of the branch name and is ignored. A
|
|
71
|
+
* cross-repository pull request is kept only when its head repository is one of `ownRepos` (this checkout's own git
|
|
72
|
+
* remotes, lowercased "owner/name"); otherwise it only shares the branch name with a stranger's fork and is ignored.
|
|
73
|
+
* `isAncestor(a, b)` answers whether commit `a` is an ancestor of commit `b`, and false when git cannot tell.
|
|
74
|
+
*/
|
|
75
|
+
declare function selectPullRequest(pulls: readonly GhPullRequest[], head: string, isAncestor: (ancestor: string, descendant: string) => boolean, ownRepos?: ReadonlySet<string>): PullRequestFact | null;
|
|
76
|
+
/**
|
|
77
|
+
* "owner/name", lowercased, parsed out of a git remote URL, or null when it doesn't match: https, `ssh://`, or
|
|
78
|
+
* scp-like (`[user@]host:owner/name`, which also covers an `~/.ssh/config` host alias in place of `user@host`).
|
|
79
|
+
*/
|
|
80
|
+
declare function parseRemoteRepo(url: string): string | null;
|
|
81
|
+
/**
|
|
82
|
+
* Asks GitHub, through `gh`, which pull requests have `branch` as their head, run from `cwd` so `gh` picks the
|
|
83
|
+
* repository from its remotes. Each call is one fixed `gh pr list` invocation. Once `gh` is missing, signed out or
|
|
84
|
+
* times out, every later lookup through the same function answers `unavailable` without running it again.
|
|
85
|
+
*/
|
|
86
|
+
declare function pullRequestLookup(): (cwd: string, branch: string, head: string) => PullRequestLookup;
|
|
87
|
+
/** A worktree whose pull request {@link pullRequestLookups} looks up: its path, branch and HEAD commit. */
|
|
88
|
+
interface PullRequestQuery {
|
|
89
|
+
cwd: string;
|
|
90
|
+
branch: string;
|
|
91
|
+
head: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* {@link pullRequestLookup} for every branch of one repository in one fixed `gh api graphql` call run from `repo`,
|
|
95
|
+
* which asks for the same 20 newest pull requests of each head branch that `gh pr list --head` returns. `gh` fills
|
|
96
|
+
* `{owner}` and `{repo}` from the remotes of `repo`; branch names travel as variables. Once `gh` is missing, signed
|
|
97
|
+
* out or times out, every later call through the same function answers `unavailable` without running it again.
|
|
98
|
+
* With `detail`, it also asks for each pull request's title, review decision and head commit check counts.
|
|
99
|
+
*/
|
|
100
|
+
declare function pullRequestLookups({ detail }?: {
|
|
101
|
+
detail?: boolean;
|
|
102
|
+
}): (repo: string, queries: readonly PullRequestQuery[]) => Promise<PullRequestLookup[]>;
|
|
103
|
+
/** The merged or closed pull request whose commits include HEAD, which makes the worktree removable. */
|
|
104
|
+
declare function endedPullRequest(lookup: PullRequestLookup | null): PullRequestFact | null;
|
|
105
|
+
/** "PR #123 merged", for reports. */
|
|
106
|
+
declare function describePullRequest(pr: Pick<PullRequestFact, "number" | "state">): string;
|
|
107
|
+
/** A linked worktree whose pull request {@link worktreePullRequests} looks up. */
|
|
108
|
+
interface WorktreeBranch {
|
|
109
|
+
path: string;
|
|
110
|
+
branch: string;
|
|
111
|
+
repository: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Looks up the pull request of each worktree's branch and HEAD, with one {@link pullRequestLookups} call per
|
|
115
|
+
* repository. The map holds null for a worktree without one, and leaves out a worktree whose HEAD git cannot read
|
|
116
|
+
* or whose lookup was unavailable.
|
|
117
|
+
*/
|
|
118
|
+
declare function worktreePullRequests(): (worktrees: readonly WorktreeBranch[]) => Promise<Map<string, PullRequestFact | null>>;
|
|
119
|
+
//#endregion
|
|
120
|
+
export { CheckCounts, GhCheckRollup, GhPullRequest, PullRequestFact, PullRequestLookup, PullRequestQuery, WorktreeBranch, checkCounts, describePullRequest, endedPullRequest, parseRemoteRepo, pullRequestLookup, pullRequestLookups, selectPullRequest, worktreePullRequests };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as pullRequestLookup, c as worktreePullRequests, i as parseRemoteRepo, n as describePullRequest, o as pullRequestLookups, r as endedPullRequest, s as selectPullRequest, t as checkCounts } from "./pull-request-pxnDCQzn.mjs";
|
|
2
|
+
export { checkCounts, describePullRequest, endedPullRequest, parseRemoteRepo, pullRequestLookup, pullRequestLookups, selectPullRequest, worktreePullRequests };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { c as gitCommonDirOnDisk } from "./worktree-C0c5Udwa.mjs";
|
|
2
|
+
import { existsSync, rmSync } from "node:fs";
|
|
3
|
+
import { loadConfig, recordingEnabled, workspaceRecordingsDir } from "@stim-cli/core/state";
|
|
4
|
+
//#region src/workspace/recordings.ts
|
|
5
|
+
/** `recording.enabled` for one registered workspace, from `STIM_RECORDING` and its workspace, repo and machine layers. */
|
|
6
|
+
function workspaceRecordingEnabled(path, project, config, env) {
|
|
7
|
+
const repo = gitCommonDirOnDisk(path);
|
|
8
|
+
return recordingEnabled(env, [
|
|
9
|
+
project.settings,
|
|
10
|
+
repo ? config?.repos?.[repo]?.settings : void 0,
|
|
11
|
+
config
|
|
12
|
+
]);
|
|
13
|
+
}
|
|
14
|
+
/** Every registered workspace's `recording.enabled` from the settings files alone, without `STIM_RECORDING`. */
|
|
15
|
+
function recordingLayers() {
|
|
16
|
+
const config = loadConfig();
|
|
17
|
+
return new Map(Object.entries(config?.projects ?? {}).map(([path, project]) => [path, workspaceRecordingEnabled(path, project, config, {})]));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Deletes the recordings of every workspace a settings write turned off, comparing the settings files before
|
|
21
|
+
* (`before`, from {@link recordingLayers}) and after it, and returns those workspaces. stim-server stops
|
|
22
|
+
* recording them once `stim status` shows the change.
|
|
23
|
+
*/
|
|
24
|
+
function deleteTurnedOffRecordings(before) {
|
|
25
|
+
return [...recordingLayers()].flatMap(([path, enabled]) => {
|
|
26
|
+
if (enabled || before.get(path) === false) return [];
|
|
27
|
+
const dir = workspaceRecordingsDir(path);
|
|
28
|
+
if (!existsSync(dir)) return [];
|
|
29
|
+
rmSync(dir, {
|
|
30
|
+
recursive: true,
|
|
31
|
+
force: true
|
|
32
|
+
});
|
|
33
|
+
return [path];
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { recordingLayers as n, workspaceRecordingEnabled as r, deleteTurnedOffRecordings as t };
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { B as
|
|
2
|
-
import {
|
|
3
|
-
import { i as findCommandWorkspace } from "./project-
|
|
4
|
-
import { f as readWorkspaceLaunches } from "./state-
|
|
5
|
-
import { f as refuseNoProject, l as phaseLine } from "./command-output-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { n as
|
|
1
|
+
import { B as parseDeviceSlotKey, p as getProject, z as deviceSlotPlatforms } from "./config-D0DbpZtM.mjs";
|
|
2
|
+
import { i as recordWorkspaceUse } from "./workspace-state-CL2V2Ons.mjs";
|
|
3
|
+
import { i as findCommandWorkspace } from "./project-CV3tDFHl.mjs";
|
|
4
|
+
import { f as readWorkspaceLaunches } from "./state-CaeaHbDA.mjs";
|
|
5
|
+
import { f as refuseNoProject, l as phaseLine } from "./command-output-CliHHn7a.mjs";
|
|
6
|
+
import { J as resolveOwnedAvdSerial } from "./android-Db2eEMaf.mjs";
|
|
7
|
+
import { l as resolveProjectMetro } from "./metro-Di8EN2Tb.mjs";
|
|
8
|
+
import { o as readWebRecord, r as cdpEndpoint, u as webFacts } from "./state-DFm77wRn.mjs";
|
|
9
|
+
import { w as resolveOwnedIosSim } from "./ios-3CtCRhwr.mjs";
|
|
10
|
+
import { p as ensureMetroReverse, s as androidAppProcess, v as iosAppProcess } from "./app-install-CAAplXAt.mjs";
|
|
11
|
+
import { n as nativeRunCommand } from "./slot-launch-BY0BrOLh.mjs";
|
|
12
|
+
import { n as sendToOwnedPage, t as liveWebRecord } from "./page-QF_Ke10s.mjs";
|
|
12
13
|
import chalk from "chalk";
|
|
13
14
|
import { WebSocket } from "ws";
|
|
14
15
|
//#region src/engine/reload.ts
|
|
@@ -31,7 +32,11 @@ function peerMatches(query, role, appId) {
|
|
|
31
32
|
if (role === "ios") return query.get("role")?.toLowerCase() === "ios";
|
|
32
33
|
return query.get("app") === appId;
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Asks Metro for its peers and reloads the ones matching `role` and `appId`. With `peersOnly`, it sends nothing and
|
|
37
|
+
* only reports the outcome a reload would have, so a caller can wait for the app to connect.
|
|
38
|
+
*/
|
|
39
|
+
function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS, peersOnly = false }) {
|
|
35
40
|
const roleName = ROLE_NAMES[role];
|
|
36
41
|
return new Promise((resolve) => {
|
|
37
42
|
const requestId = `stim-reload-${process.pid}-${Date.now()}`;
|
|
@@ -72,6 +77,15 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
|
|
|
72
77
|
const query = peerQuery(metadata);
|
|
73
78
|
return query ? peerMatches(query, role, appId) : false;
|
|
74
79
|
});
|
|
80
|
+
if (rolePeers.length === 0 && peersOnly) {
|
|
81
|
+
finish({
|
|
82
|
+
failed: true,
|
|
83
|
+
noPeer: true,
|
|
84
|
+
peers,
|
|
85
|
+
reason: `No ${roleName} React Native app is connected to Metro on port ${port}.`
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
75
89
|
if (rolePeers.length === 0) {
|
|
76
90
|
socket.send(JSON.stringify({
|
|
77
91
|
version: 2,
|
|
@@ -86,7 +100,7 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
|
|
|
86
100
|
});
|
|
87
101
|
return;
|
|
88
102
|
}
|
|
89
|
-
for (const [id] of rolePeers) socket.send(JSON.stringify({
|
|
103
|
+
if (!peersOnly) for (const [id] of rolePeers) socket.send(JSON.stringify({
|
|
90
104
|
version: 2,
|
|
91
105
|
method: "reload",
|
|
92
106
|
target: id
|
|
@@ -98,7 +112,7 @@ function reloadThroughMetro(port, { role, appId, timeoutMs = METRO_TIMEOUT_MS })
|
|
|
98
112
|
});
|
|
99
113
|
return;
|
|
100
114
|
}
|
|
101
|
-
socket.send(JSON.stringify({
|
|
115
|
+
if (!peersOnly) socket.send(JSON.stringify({
|
|
102
116
|
version: 2,
|
|
103
117
|
method: "reload"
|
|
104
118
|
}));
|
|
@@ -130,8 +144,16 @@ const DEFAULT_DEPS = {
|
|
|
130
144
|
const facts = webFacts(readWebRecord(root));
|
|
131
145
|
return facts?.status === "unverified" ? "unverified" : liveWebRecord(facts?.record ?? null);
|
|
132
146
|
},
|
|
133
|
-
reloadPage: (record) => sendToOwnedPage(record, "Page.reload")
|
|
147
|
+
reloadPage: (record) => sendToOwnedPage(record, "Page.reload"),
|
|
148
|
+
ensureReverse: (serial, metroPort) => ensureMetroReverse({
|
|
149
|
+
serial,
|
|
150
|
+
metroPort
|
|
151
|
+
}),
|
|
152
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
134
153
|
};
|
|
154
|
+
const RECONNECT_POLL_MS = 500;
|
|
155
|
+
const RECONNECT_POLLS = 16;
|
|
156
|
+
const RECONNECT_UNOBSERVED_MS = 2500;
|
|
135
157
|
function failure(code, message, remedy) {
|
|
136
158
|
return {
|
|
137
159
|
code,
|
|
@@ -143,8 +165,9 @@ function describe(error) {
|
|
|
143
165
|
return error instanceof Error ? error.message : String(error);
|
|
144
166
|
}
|
|
145
167
|
async function reloadBrowser(browser, metroPort, d) {
|
|
168
|
+
let pageUrl;
|
|
146
169
|
try {
|
|
147
|
-
await d.reloadPage(browser);
|
|
170
|
+
pageUrl = await d.reloadPage(browser);
|
|
148
171
|
} catch (error) {
|
|
149
172
|
return {
|
|
150
173
|
ok: false,
|
|
@@ -157,10 +180,11 @@ async function reloadBrowser(browser, metroPort, d) {
|
|
|
157
180
|
platform: "web",
|
|
158
181
|
deviceId: cdpEndpoint(browser.cdpPort),
|
|
159
182
|
deviceName: browser.version ?? "Chrome",
|
|
160
|
-
appId:
|
|
183
|
+
appId: pageUrl,
|
|
161
184
|
metroPort: metroPort !== null && new URL(browser.url).port === String(metroPort) ? metroPort : null,
|
|
162
185
|
strategy: "cdp",
|
|
163
|
-
targets: 1
|
|
186
|
+
targets: 1,
|
|
187
|
+
reverseRestored: []
|
|
164
188
|
}
|
|
165
189
|
};
|
|
166
190
|
}
|
|
@@ -312,10 +336,32 @@ async function runReload({ root, platform = null, deps = {} }) {
|
|
|
312
336
|
ok: false,
|
|
313
337
|
error: stopped
|
|
314
338
|
};
|
|
315
|
-
const
|
|
339
|
+
const reverseRestored = [];
|
|
340
|
+
const reverseChecked = target.platform === "android" ? live.filter((c) => c.platform === "android" && !c.record.release && c.record.metroPort === port) : [];
|
|
341
|
+
for (const candidate of reverseChecked) {
|
|
342
|
+
const serial = candidate.record.deviceId;
|
|
343
|
+
const ensured = d.ensureReverse(serial, port);
|
|
344
|
+
if (ensured.failed) return {
|
|
345
|
+
ok: false,
|
|
346
|
+
error: failure("STIM_RELOAD_FAILED", `Stim could not check or restore the adb reverse for Metro port ${port} on ${serial}: ${ensured.reason}`, `Run \`adb -s ${serial} reverse tcp:${port} tcp:${port}\`, then \`stim reload android\` again.`)
|
|
347
|
+
};
|
|
348
|
+
if (ensured.restored) reverseRestored.push(serial);
|
|
349
|
+
}
|
|
350
|
+
const request = {
|
|
316
351
|
role: target.platform,
|
|
317
352
|
appId: target.record.appId
|
|
318
|
-
}
|
|
353
|
+
};
|
|
354
|
+
const expectedPeers = reverseChecked.filter((c) => c.record.appId === target.record.appId).length;
|
|
355
|
+
for (let poll = 0; reverseRestored.length && poll < RECONNECT_POLLS; poll++) {
|
|
356
|
+
const peers = await d.reloadMetro(port, {
|
|
357
|
+
...request,
|
|
358
|
+
peersOnly: true
|
|
359
|
+
});
|
|
360
|
+
if (peers.broadcast) await d.sleep(RECONNECT_UNOBSERVED_MS);
|
|
361
|
+
if (peers.unreachable || peers.broadcast || peers.ok && peers.targets >= expectedPeers) break;
|
|
362
|
+
await d.sleep(RECONNECT_POLL_MS);
|
|
363
|
+
}
|
|
364
|
+
const reloaded = await d.reloadMetro(port, request);
|
|
319
365
|
if (!reloaded.ok) {
|
|
320
366
|
const stoppedAfterMetro = processFailure(target.platform, target.record, d, target.slot);
|
|
321
367
|
if (stoppedAfterMetro) return {
|
|
@@ -342,7 +388,8 @@ async function runReload({ root, platform = null, deps = {} }) {
|
|
|
342
388
|
appId: target.record.appId,
|
|
343
389
|
metroPort: port,
|
|
344
390
|
strategy,
|
|
345
|
-
targets: reloaded.targets ?? null
|
|
391
|
+
targets: reloaded.targets ?? null,
|
|
392
|
+
reverseRestored
|
|
346
393
|
}
|
|
347
394
|
};
|
|
348
395
|
}
|
|
@@ -386,7 +433,8 @@ function registerReload(program, deps = {}) {
|
|
|
386
433
|
return;
|
|
387
434
|
}
|
|
388
435
|
const scope = facts.strategy === "metro-broadcast" ? ` This Metro cannot name its connected apps, so the reload request was broadcast to all of them and Stim cannot confirm ${facts.appId} was one. Check the expected UI on ${facts.deviceId}; if nothing changed, reload from the app's own error screen or dev menu.` : facts.targets && facts.targets > 1 ? ` ${facts.targets} devices are running this app on that Metro and the reload request addressed all of them, not only ${facts.deviceId}.` : "";
|
|
389
|
-
|
|
436
|
+
const restored = facts.reverseRestored.length ? ` The adb reverse for tcp:${facts.metroPort} was missing on ${facts.reverseRestored.join(", ")}, so Stim restored it first.` : "";
|
|
437
|
+
console.log(`Reload requested for ${facts.appId} on ${facts.deviceName} (${facts.deviceId}) via ${facts.strategy}; ${facts.platform} Metro port ${facts.metroPort}.${restored}${scope} Completion is not observed; verify the expected UI and run stim logs --errors.`);
|
|
390
438
|
}
|
|
391
439
|
});
|
|
392
440
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
2
|
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { f as resolvePackageJson } from "./project-
|
|
3
|
+
import { C as workspaceLogsDir } from "./workspace-state-CL2V2Ons.mjs";
|
|
4
|
+
import { f as resolvePackageJson } from "./project-CV3tDFHl.mjs";
|
|
5
5
|
import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
|
|
6
|
-
import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-
|
|
6
|
+
import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-DhtX6bom.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
|
+
import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
3
|
+
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
4
|
+
import { i as macosRuntimeClaim, n as macosLogFile, o as updateMacosRecord, r as macosProcess } from "./state-BxCgeTQu.mjs";
|
|
5
|
+
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
6
|
+
import { readMacosRecord } from "@stim-cli/core/state";
|
|
7
|
+
import { StringDecoder } from "node:string_decoder";
|
|
8
|
+
//#region src/macos/run.ts
|
|
9
|
+
function logLines(stream, write) {
|
|
10
|
+
const decoder = new StringDecoder("utf8");
|
|
11
|
+
let pending = "";
|
|
12
|
+
stream.on("data", (chunk) => {
|
|
13
|
+
pending += decoder.write(chunk);
|
|
14
|
+
while (pending.length > 65536 && !pending.includes("\n")) {
|
|
15
|
+
write(pending.slice(0, 65536));
|
|
16
|
+
pending = pending.slice(65536);
|
|
17
|
+
}
|
|
18
|
+
const lines = pending.split("\n");
|
|
19
|
+
pending = lines.pop() ?? "";
|
|
20
|
+
for (const line of lines) write(line.replace(/\r$/, ""));
|
|
21
|
+
});
|
|
22
|
+
stream.on("end", () => {
|
|
23
|
+
pending += decoder.end();
|
|
24
|
+
if (pending) write(pending);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async function runMacosSupervisor(root, launchId) {
|
|
28
|
+
const record = readMacosRecord(root);
|
|
29
|
+
if (!record || record.launchId !== launchId || record.build.state !== "ok") throw new Error("The macOS launch record changed before its supervisor started.");
|
|
30
|
+
const owner = macosProcess(process.pid);
|
|
31
|
+
const attempt = (0, ownership_claim_exports.tryAcquireClaim)({
|
|
32
|
+
root: macosRuntimeClaim(root),
|
|
33
|
+
mode: "exclusive",
|
|
34
|
+
label: "macOS app"
|
|
35
|
+
});
|
|
36
|
+
if (attempt.pending) (0, ownership_claim_exports.releaseClaim)(attempt.pending);
|
|
37
|
+
const claim = attempt.acquired;
|
|
38
|
+
if (!claim) throw new Error(`The macOS runtime is already held at ${attempt.held?.path ?? macosRuntimeClaim(root)}.`);
|
|
39
|
+
const writer = createNdjsonWriter(macosLogFile(root), { maxBytes: LOG_ROTATE_BYTES });
|
|
40
|
+
let app;
|
|
41
|
+
let stopping = false;
|
|
42
|
+
let spawned = false;
|
|
43
|
+
let childExited = false;
|
|
44
|
+
try {
|
|
45
|
+
if (!(0, process_identity_exports.sameProcessRecord)(readMacosRecord(root)?.supervisor, record.supervisor) || !updateMacosRecord(root, record.supervisor, { supervisor: owner })) throw new Error("The macOS launch owner changed.");
|
|
46
|
+
(0, ownership_claim_exports.markClaimChildPending)(claim);
|
|
47
|
+
const child = getExecutor().spawn(record.executable, record.arguments, {
|
|
48
|
+
cwd: root,
|
|
49
|
+
stdio: [
|
|
50
|
+
"ignore",
|
|
51
|
+
"pipe",
|
|
52
|
+
"pipe"
|
|
53
|
+
],
|
|
54
|
+
env: {
|
|
55
|
+
...process.env,
|
|
56
|
+
NSUnbufferedIO: "YES"
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
spawned = child.pid !== void 0;
|
|
60
|
+
const ended = new Promise((resolve, reject) => {
|
|
61
|
+
child.once("error", reject);
|
|
62
|
+
child.once("close", () => {
|
|
63
|
+
childExited = true;
|
|
64
|
+
resolve();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
if (!child.pid) {
|
|
68
|
+
await ended;
|
|
69
|
+
throw new Error("The macOS app did not start.");
|
|
70
|
+
}
|
|
71
|
+
app = macosProcess(child.pid);
|
|
72
|
+
(0, ownership_claim_exports.setClaimChild)(claim, app);
|
|
73
|
+
if (!updateMacosRecord(root, owner, { app })) {
|
|
74
|
+
if ((0, process_identity_exports.inspectProcessIdentity)(app) === "same") process.kill(app.pid, "SIGTERM");
|
|
75
|
+
throw new Error("The macOS launch owner changed.");
|
|
76
|
+
}
|
|
77
|
+
const log = (level, msg) => writer.write({
|
|
78
|
+
src: "client",
|
|
79
|
+
platform: "macos",
|
|
80
|
+
level,
|
|
81
|
+
msg
|
|
82
|
+
});
|
|
83
|
+
if (child.stdout) logLines(child.stdout, (line) => log("info", line));
|
|
84
|
+
if (child.stderr) logLines(child.stderr, (line) => log("warn", line));
|
|
85
|
+
const stop = async () => {
|
|
86
|
+
if (stopping) return;
|
|
87
|
+
stopping = true;
|
|
88
|
+
for (const signal of ["SIGTERM", "SIGKILL"]) {
|
|
89
|
+
if (!app || (0, process_identity_exports.inspectProcessIdentity)(app) !== "same") return;
|
|
90
|
+
process.kill(app.pid, signal);
|
|
91
|
+
if (await (0, process_identity_exports.waitForProcessExit)(app, 5e3)) return;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
process.on("SIGTERM", stop);
|
|
95
|
+
process.on("SIGINT", stop);
|
|
96
|
+
log("info", `Started ${record.product} (pid ${app.pid}).`);
|
|
97
|
+
await ended;
|
|
98
|
+
process.off("SIGTERM", stop);
|
|
99
|
+
process.off("SIGINT", stop);
|
|
100
|
+
log(stopping || child.exitCode === 0 ? "info" : "error", `Exited ${record.product} (${child.exitCode ?? child.signalCode ?? "unknown"}).`);
|
|
101
|
+
updateMacosRecord(root, owner, {
|
|
102
|
+
app: void 0,
|
|
103
|
+
supervisor: void 0
|
|
104
|
+
});
|
|
105
|
+
} finally {
|
|
106
|
+
if (!spawned || childExited || app && ["gone", "different"].includes((0, process_identity_exports.inspectProcessIdentity)(app))) {
|
|
107
|
+
(0, ownership_claim_exports.clearClaimChild)(claim);
|
|
108
|
+
(0, ownership_claim_exports.releaseClaim)(claim);
|
|
109
|
+
}
|
|
110
|
+
writer.close();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (process.argv[1]?.endsWith("/macos-run.mjs") || process.argv[1]?.endsWith("/macos/run.ts")) {
|
|
114
|
+
const [root, launchId] = process.argv.slice(2);
|
|
115
|
+
if (!root || !launchId) throw new Error("macos-run needs a workspace and launch identity.");
|
|
116
|
+
await runMacosSupervisor(root, launchId);
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { runMacosSupervisor as n, logLines as t };
|
|
@@ -1,20 +1,44 @@
|
|
|
1
1
|
import { i as __require, t as __commonJSMin } from "./rolldown-runtime-BsOwBuO_.mjs";
|
|
2
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
3
|
import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { a as metroStoreRoot, o as registerMetroStore, t as appendCacheStore } from "./metro-store-
|
|
4
|
+
import { E as projectMetroSharedCache } from "./settings-CduVcoxj.mjs";
|
|
5
|
+
import { a as metroStoreRoot, o as registerMetroStore, t as appendCacheStore } from "./metro-store-CDDZHtPl.mjs";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
6
7
|
import { isAbsolute, join, relative, sep } from "node:path";
|
|
7
8
|
//#endregion
|
|
8
9
|
//#region src/supervisor/server-bare.ts
|
|
9
10
|
var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
10
11
|
const { randomUUID } = __require("node:crypto");
|
|
11
|
-
|
|
12
|
+
const LOOPBACK = /* @__PURE__ */ new Set([
|
|
13
|
+
"127.0.0.1",
|
|
14
|
+
"::1",
|
|
15
|
+
"::ffff:127.0.0.1"
|
|
16
|
+
]);
|
|
17
|
+
const PROGRESS_PART = /^\{"done":(\d+),"total":(\d+),"percent":(\d+)\}$/;
|
|
18
|
+
const PROGRESS_INTERVAL_MS = 1e3;
|
|
19
|
+
function clientPidFromLsof(output, clientPort, serverPort) {
|
|
20
|
+
const connection = new RegExp(`:${clientPort}->\\S*:${serverPort}$`);
|
|
21
|
+
let pid = null;
|
|
22
|
+
for (const line of String(output).split("\n")) if (line.startsWith("p")) pid = Number(line.slice(1));
|
|
23
|
+
else if (line.startsWith("n") && connection.test(line) && Number.isInteger(pid) && pid > 0) return pid;
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function lookupClientPid(req, runLsof) {
|
|
27
|
+
const { remoteAddress, remotePort, localPort } = req.socket;
|
|
28
|
+
if (!runLsof || !LOOPBACK.has(remoteAddress)) return null;
|
|
29
|
+
return Promise.resolve().then(() => runLsof([
|
|
30
|
+
"-nP",
|
|
31
|
+
`-iTCP:${remotePort}`,
|
|
32
|
+
"-Fpn"
|
|
33
|
+
])).then((output) => clientPidFromLsof(output, remotePort, localPort)).catch(() => null);
|
|
34
|
+
}
|
|
35
|
+
function bundleResponseMiddleware(write, { runLsof } = {}) {
|
|
12
36
|
return (req, res, next) => {
|
|
13
37
|
if (req.method === "GET" && req.url === "/_stim/metro-warmup") {
|
|
14
38
|
res.end("ready");
|
|
15
39
|
return;
|
|
16
40
|
}
|
|
17
|
-
|
|
41
|
+
const prefetch = req.headers["x-stim-metro-warmup"] === "1";
|
|
18
42
|
let url;
|
|
19
43
|
try {
|
|
20
44
|
url = new URL(req.url, "http://localhost");
|
|
@@ -24,27 +48,50 @@ var import_bundle_response = (/* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
24
48
|
const platform = url.searchParams.get("platform");
|
|
25
49
|
if (req.method !== "GET" || !/\.bundle\/*$/.test(url.pathname) || !["ios", "android"].includes(platform)) return next();
|
|
26
50
|
const requestId = randomUUID();
|
|
27
|
-
const
|
|
51
|
+
const kind = prefetch ? "prefetch" : "response";
|
|
52
|
+
const clientPid = platform === "ios" && !prefetch ? lookupClientPid(req, runLsof) : null;
|
|
53
|
+
const send = (ts, stage, statusCode, pid, progress) => {
|
|
28
54
|
try {
|
|
29
55
|
write({
|
|
30
|
-
ts
|
|
56
|
+
ts,
|
|
31
57
|
src: "metro",
|
|
32
|
-
level:
|
|
33
|
-
event
|
|
58
|
+
level: stage === "failed" && !prefetch ? "error" : "debug",
|
|
59
|
+
event: `bundle_${kind}_${stage}`,
|
|
34
60
|
platform,
|
|
35
61
|
requestId,
|
|
36
|
-
statusCode,
|
|
37
|
-
msg: `${platform} bundle
|
|
62
|
+
...progress ?? { statusCode },
|
|
63
|
+
msg: progress ? `${platform} bundle ${progress.percent}%` : `${platform} bundle ${kind} ${stage}`,
|
|
64
|
+
...pid ? { clientPid: pid } : {}
|
|
38
65
|
});
|
|
39
66
|
} catch {}
|
|
40
67
|
};
|
|
41
|
-
emit(
|
|
68
|
+
const emit = (stage, statusCode, progress) => {
|
|
69
|
+
const ts = Date.now();
|
|
70
|
+
if (clientPid) clientPid.then((pid) => send(ts, stage, statusCode, pid, progress));
|
|
71
|
+
else send(ts, stage, statusCode, null, progress);
|
|
72
|
+
};
|
|
73
|
+
emit("started");
|
|
74
|
+
const writeChunk = res.write;
|
|
75
|
+
let progressAt = 0;
|
|
76
|
+
res.write = function(chunk, ...rest) {
|
|
77
|
+
const part = typeof chunk === "string" && chunk.length < 100 ? PROGRESS_PART.exec(chunk) : null;
|
|
78
|
+
const now = part ? Date.now() : 0;
|
|
79
|
+
if (part && now - progressAt >= PROGRESS_INTERVAL_MS) {
|
|
80
|
+
progressAt = now;
|
|
81
|
+
emit("progress", void 0, {
|
|
82
|
+
done: Number(part[1]),
|
|
83
|
+
total: Number(part[2]),
|
|
84
|
+
percent: Number(part[3])
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return writeChunk.call(this, chunk, ...rest);
|
|
88
|
+
};
|
|
42
89
|
let ended = false;
|
|
43
90
|
const finish = (complete) => {
|
|
44
91
|
if (ended) return;
|
|
45
92
|
ended = true;
|
|
46
93
|
const success = complete && (res.statusCode === 200 || res.statusCode === 304);
|
|
47
|
-
emit(success ? "
|
|
94
|
+
emit(success ? "finished" : "failed", res.statusCode);
|
|
48
95
|
};
|
|
49
96
|
res.once("finish", () => finish(true));
|
|
50
97
|
res.once("close", () => finish(false));
|
|
@@ -296,7 +343,7 @@ async function startBareServer({ root, port, logsDir, writer = null, deps = null
|
|
|
296
343
|
});
|
|
297
344
|
const httpServer = await metro.runServer(config, {
|
|
298
345
|
unstable_extraMiddleware: [
|
|
299
|
-
(0, import_bundle_response.bundleResponseMiddleware)((record) => writer?.write(record)),
|
|
346
|
+
(0, import_bundle_response.bundleResponseMiddleware)((record) => writer?.write(record), { runLsof: process.platform === "darwin" ? (args) => getExecutor().runFileAsync("lsof", args, { timeoutMs: 2e3 }) : void 0 }),
|
|
300
347
|
symbolicationReporterMiddleware(reporter),
|
|
301
348
|
communityMiddleware,
|
|
302
349
|
middleware
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
1
|
+
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
2
|
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import { f as resolvePackageJson } from "./project-
|
|
3
|
+
import { f as resolvePackageJson } from "./project-CV3tDFHl.mjs";
|
|
4
4
|
import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
|
|
5
5
|
import { n as stripAnsi, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { a as metroStoreRoot, i as metroStoreConfirmedRoot, n as expoMetroConfigPath, o as registerMetroStore, r as expoMetroStoreEnv } from "./metro-store-
|
|
6
|
+
import { E as projectMetroSharedCache } from "./settings-CduVcoxj.mjs";
|
|
7
|
+
import { a as metroStoreRoot, i as metroStoreConfirmedRoot, n as expoMetroConfigPath, o as registerMetroStore, r as expoMetroStoreEnv } from "./metro-store-CDDZHtPl.mjs";
|
|
8
8
|
import { accessSync, constants, existsSync, readFileSync } from "node:fs";
|
|
9
|
-
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
10
9
|
import { dirname, join, parse } from "node:path";
|
|
10
|
+
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
11
11
|
//#region src/supervisor/server-expo.ts
|
|
12
12
|
function delay(ms) {
|
|
13
13
|
return new Promise((resolve) => {
|
|
@@ -120,11 +120,7 @@ function recordFromLine(line, { stream = "stdout" } = {}) {
|
|
|
120
120
|
if (!msg.trim()) return null;
|
|
121
121
|
if (stream === "stderr" && msg.startsWith("stim-bundle-response: ")) try {
|
|
122
122
|
const record = JSON.parse(msg.slice(22));
|
|
123
|
-
if (record.src === "metro" && [
|
|
124
|
-
"bundle_response_started",
|
|
125
|
-
"bundle_response_finished",
|
|
126
|
-
"bundle_response_failed"
|
|
127
|
-
].includes(record.event) && ["ios", "android"].includes(record.platform) && typeof record.requestId === "string" && Number.isFinite(record.ts)) return record;
|
|
123
|
+
if (record.src === "metro" && /^bundle_(response|prefetch)_(started|progress|finished|failed)$/.test(record.event) && ["ios", "android"].includes(record.platform) && typeof record.requestId === "string" && Number.isFinite(record.ts)) return record;
|
|
128
124
|
} catch {}
|
|
129
125
|
const confirmed = metroStoreConfirmedRoot(msg);
|
|
130
126
|
if (confirmed) return {
|