@stim-cli/core 1.20.0 → 1.20.2

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.
@@ -0,0 +1,151 @@
1
+ //#region state/status-derived.ts
2
+ const PLATFORMS = ["ios", "android"];
3
+ function isRunning(platform, device) {
4
+ if (platform === "ios") return device.state === "Booted";
5
+ return device.state === "detected" && !device.physical;
6
+ }
7
+ function appPresence(env, platform, device) {
8
+ if (!isRunning(platform, device) || device.app?.state === "running") return null;
9
+ const everBuilt = env.builds?.[platform]?.some((entry) => entry.result === "succeeded") ?? true;
10
+ if (env.lastBuilds?.[platform]?.status === "failed" && !everBuilt) return "none";
11
+ return device.app?.state === "stopped" ? "closed" : null;
12
+ }
13
+ function deviceSlots(env) {
14
+ return [{
15
+ slot: "default",
16
+ ios: env.ios,
17
+ android: env.android
18
+ }, ...env.slots ?? []];
19
+ }
20
+ function latestBuild(env) {
21
+ let latest = null;
22
+ for (const platform of PLATFORMS) {
23
+ const build = env.lastBuilds?.[platform];
24
+ if (build && (latest === null || Date.parse(build.startedAt) > Date.parse(latest.startedAt))) latest = build;
25
+ }
26
+ return latest;
27
+ }
28
+ function stage(kind, since, platform = null) {
29
+ return {
30
+ kind,
31
+ since: since ?? null,
32
+ platform,
33
+ closedApps: []
34
+ };
35
+ }
36
+ function workspaceStage(env) {
37
+ if (env.macos?.build.state === "running") return stage("building", env.macos.build.startedAt, "macos");
38
+ if (env.macos?.build.state === "failed") return stage("build-failed", env.macos.build.finishedAt ?? env.macos.build.startedAt, "macos");
39
+ if (env.build?.state === "running") return stage("building", env.build.startedAt, env.build.platform);
40
+ const macosApp = env.macos?.state === "running" || env.macos?.state === "orphaned" ? env.macos : null;
41
+ const live = env.live || macosApp !== null;
42
+ if (!live && env.phase === "warming") return stage("warming", env.phaseSince);
43
+ if (!live && env.phase === "ready") return stage("ready", env.phaseSince);
44
+ const latest = latestBuild(env);
45
+ if (latest?.status === "failed") return stage("build-failed", latest.finishedAt ?? latest.startedAt, latest.platform);
46
+ if (live || (env.remoteDevices?.length ?? 0) > 0) {
47
+ const closedApps = deviceSlots(env).flatMap(({ slot, ...devices }) => PLATFORMS.flatMap((platform) => {
48
+ const device = devices[platform];
49
+ return device && appPresence(env, platform, device) === "closed" ? [{
50
+ platform,
51
+ slot
52
+ }] : [];
53
+ }));
54
+ return {
55
+ ...stage("running", env.supervisor?.startedAt ?? macosApp?.build.finishedAt ?? macosApp?.build.startedAt),
56
+ closedApps
57
+ };
58
+ }
59
+ const lastStop = env.metro?.lastStop;
60
+ return stage("stopped", lastStop && "at" in lastStop ? lastStop.at : null);
61
+ }
62
+ function checksState(checks) {
63
+ if (!checks) return null;
64
+ if (checks.failing > 0) return "failing";
65
+ if (checks.pending > 0) return "pending";
66
+ return checks.passing > 0 ? "passing" : null;
67
+ }
68
+ function gitChip(worktree) {
69
+ const git = worktree.git;
70
+ if (!git) return null;
71
+ const pull = worktree.pullRequest;
72
+ const parts = [];
73
+ const ahead = git.ahead ?? 0;
74
+ const behind = git.behind ?? 0;
75
+ if (ahead || behind) parts.push({
76
+ kind: "arrows",
77
+ ahead,
78
+ behind
79
+ });
80
+ const uncommitted = git.changed + git.untracked;
81
+ if (uncommitted) parts.push({
82
+ kind: "changed",
83
+ count: uncommitted
84
+ });
85
+ if (git.mergedInto !== null) {
86
+ if (pull?.state !== "merged") parts.push({
87
+ kind: "merged",
88
+ into: git.mergedInto
89
+ });
90
+ } else if (git.upstream === null) parts.push({ kind: "no-upstream" });
91
+ return {
92
+ parts,
93
+ ci: pull ? checksState(pull.checks) : null
94
+ };
95
+ }
96
+ function buildCause(build) {
97
+ if (("result" in build ? build.result : build.status) !== "failed") return null;
98
+ const at = build.diagnostics?.find((d) => d.file && d.line !== null && d.line !== void 0);
99
+ if (at) return {
100
+ key: `${at.file}:${at.line}`,
101
+ file: at.file,
102
+ line: at.line
103
+ };
104
+ return {
105
+ key: build.errorCode ?? "failed",
106
+ file: null,
107
+ line: null
108
+ };
109
+ }
110
+ function withCauses(builds) {
111
+ if (!builds) return builds;
112
+ return Object.fromEntries(Object.entries(builds).map(([platform, list]) => [platform, list?.map((build) => withCause(build))]));
113
+ }
114
+ function withCause(build) {
115
+ const cause = buildCause(build);
116
+ return cause ? {
117
+ ...build,
118
+ cause
119
+ } : build;
120
+ }
121
+ function withGitChip(worktree) {
122
+ const chip = gitChip(worktree);
123
+ return chip ? {
124
+ ...worktree,
125
+ gitChip: chip
126
+ } : worktree;
127
+ }
128
+ /** The environment with the conclusions clients draw from it: `stage`, `appPresence`, `gitChip` and `cause`. */
129
+ function withDerivedFacts(env) {
130
+ const device = (platform, record) => record ? {
131
+ ...record,
132
+ appPresence: appPresence(env, platform, record)
133
+ } : record;
134
+ const derived = {
135
+ ...env,
136
+ stage: workspaceStage(env)
137
+ };
138
+ if (env.ios) derived.ios = device("ios", env.ios);
139
+ if (env.android) derived.android = device("android", env.android);
140
+ if (env.slots) derived.slots = env.slots.map((slot) => ({
141
+ ...slot,
142
+ ios: device("ios", slot.ios),
143
+ android: device("android", slot.android)
144
+ }));
145
+ if (env.worktree) derived.worktree = withGitChip(env.worktree);
146
+ if (env.lastBuilds) derived.lastBuilds = Object.fromEntries(Object.entries(env.lastBuilds).map(([platform, build]) => [platform, withCause(build)]));
147
+ if (env.builds) derived.builds = withCauses(env.builds);
148
+ return derived;
149
+ }
150
+ //#endregion
151
+ export { withGitChip as n, withDerivedFacts as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stim-cli/core",
3
- "version": "1.20.0",
3
+ "version": "1.20.2",
4
4
  "description": "Shared internal cache and runtime primitives for Stim packages.",
5
5
  "license": "MIT",
6
6
  "repository": {