stim 1.11.0 → 1.12.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/dist/{activity-BtG4Va9l.mjs → activity-CCZJs__P.mjs} +4 -3
- package/dist/{android-C4zG2Tuc.mjs → android-75Sk2rIR.mjs} +25 -8
- package/dist/{android-C1q4l523.mjs → android-B7X-8H7h.mjs} +75 -32
- package/dist/{android-BA2i_KAV.mjs → android-BQiKJYK0.mjs} +1 -1
- package/dist/{android-cas-DfJkwCXW.mjs → android-cas-DzLPXiEn.mjs} +7 -7
- package/dist/{app-install-DHut6JnV.mjs → app-install-CsZi0SAT.mjs} +1 -1
- package/dist/{workspaces-COD2xCz-.mjs → budget-DbzW5VTD.mjs} +641 -32
- package/dist/{build-plan-CeAYgKAx.mjs → build-plan-CqntbR7b.mjs} +120 -35
- package/dist/{build-progress-CDwogz6R.mjs → build-progress-h60GPV27.mjs} +3 -3
- package/dist/{cache-manifest-Pubfp8wV.mjs → cache-manifest-DWPF4RKJ.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +16 -16
- package/dist/collector-run.mjs +4 -4
- package/dist/{command-output-D5z2_bcF.mjs → command-output-BWCj5Vh-.mjs} +1 -1
- package/dist/{config-BEq0Qw_a.mjs → config-0jCcMM0E.mjs} +10 -1
- package/dist/{dependency-state-r9UesA9a.mjs → dependency-state-DNN0yfx6.mjs} +1 -1
- package/dist/{deps-OF7CD5Dx.mjs → deps-CO-_7UOm.mjs} +2 -2
- package/dist/{device-BwH2iI3O.mjs → device-9r9xRYDa.mjs} +7 -7
- package/dist/{device-lease-D83nqeMX.mjs → device-lease-B9LAXIUH.mjs} +5 -5
- package/dist/{device-pool-DHj7cdPy.mjs → device-pool-BoezJd-c.mjs} +4 -4
- package/dist/{device-remote-BQZSnnmE.mjs → device-remote-C0_o-tJH.mjs} +254 -579
- package/dist/{doctor-D8QdMRMf.mjs → doctor-LfDlbR-N.mjs} +19 -18
- package/dist/{error-diagnostics-UYFSQwRy.mjs → error-diagnostics-CCxjn31V.mjs} +7 -7
- package/dist/{gc-COZteyiq.mjs → gc-C4nQFcTX.mjs} +203 -39
- package/dist/{guide-NDvTmMi-.mjs → guide-BPBlh9ML.mjs} +189 -38
- package/dist/{guide-status-CWvti2Lg.mjs → guide-status-i9ogHt4v.mjs} +2 -2
- package/dist/{idle-NETbeNiQ.mjs → idle-S3tFZ53_.mjs} +7 -7
- package/dist/{in-use-DVhlSoyn.mjs → in-use-D9XYEgFD.mjs} +7 -7
- package/dist/{ios-CQLKpNfr.mjs → ios-CDzWL1mj.mjs} +30 -29
- package/dist/{ios-DArbmwer.mjs → ios-CZWOHTTc.mjs} +23 -19
- package/dist/{ios-device-CwDZo0X4.mjs → ios-device-D9cLxVr5.mjs} +1 -1
- package/dist/{launch-verify-CuPDGXdr.mjs → launch-verify-B2oR_kFN.mjs} +2 -2
- package/dist/{logs-B44a1UeU.mjs → logs-SzuYudOj.mjs} +6 -6
- package/dist/{merge-state-DDxS-XIZ.mjs → merge-state-ytFQCeh4.mjs} +38 -8
- package/dist/{metro-BWLOJ_Wr.mjs → metro-Dzo30hvJ.mjs} +1 -1
- package/dist/{named-ports-Dc7neAlc.mjs → named-ports-Dn1o61D9.mjs} +3 -3
- package/dist/{ownership-BiojdtAp.mjs → ownership-B8d4kXBx.mjs} +49 -16
- package/dist/{ownership-D2xbLVoz.mjs → ownership-Dqnrjrio.mjs} +2 -2
- package/dist/{ports-DwBaRFJs.mjs → ports-Dp_QTwTC.mjs} +3 -3
- package/dist/{project-BXZzOABt.mjs → project-B8rbutVC.mjs} +4 -72
- package/dist/{reload-By9Dwsrt.mjs → reload-nocmx8KB.mjs} +9 -9
- package/dist/remote-cache-BRsRZru5.mjs +526 -0
- package/dist/{server-bare-D_RK1RCj.mjs → server-bare-Gn3ssSdK.mjs} +1 -1
- package/dist/{server-expo-o6H5gcBc.mjs → server-expo-CeT1nIIk.mjs} +2 -2
- package/dist/server-expo-eWi9Coof.mjs +2 -0
- package/dist/{settings-B5oFZEri.mjs → settings-BlyDn2Oz.mjs} +2 -2
- package/dist/{settings-C0ugALSC.mjs → settings-bE-Gu3Ti.mjs} +23 -11
- package/dist/settings.schema.json +22 -2
- package/dist/{simslim-CIR3IYJO.mjs → simslim-COtEEP7x.mjs} +6 -5
- package/dist/{slot-launch-rggO1Esw.mjs → slot-launch-DIACGEfH.mjs} +4 -4
- package/dist/{spawn-claims-BJwXTMPt.mjs → spawn-claims-PT8aQpCa.mjs} +1 -1
- package/dist/{start-i8zc9VmS.mjs → start-BFstVBlx.mjs} +1 -1
- package/dist/{start-BSsf2tUs.mjs → start-BboE1HIS.mjs} +108 -17
- package/dist/{state-WGdIbi_d.mjs → state-DcDgzfu3.mjs} +15 -3
- package/dist/{stats-BAgJaLA4.mjs → stats-D8rUTPHd.mjs} +1 -1
- package/dist/{stats-DBYJ5bxL.mjs → stats-DiCtmluY.mjs} +4 -4
- package/dist/{status-Q-WDEGCB.mjs → status-BUASYyy_.mjs} +73 -28
- package/dist/{status-CitcBRsC.mjs → status-DI9Tjo7T.mjs} +41 -29
- package/dist/stim-desktop-D0xhpZt8.mjs +29 -0
- package/dist/{stop-rst5mL14.mjs → stop-BI7QY76M.mjs} +2 -2
- package/dist/{stop-DIhrvu0B.mjs → stop-Bn6v-GvS.mjs} +23 -16
- package/dist/supervisor-run.mjs +11 -11
- package/dist/{workspace-process-lock-Cx74RSDZ.mjs → workspace-process-lock-BvvJTfo_.mjs} +2 -2
- package/dist/{worktree-DhxDTK44.mjs → worktree-B5sTRskL.mjs} +1 -1
- package/dist/{worktree-KOjMX3zA.mjs → worktree-ChDL5fO1.mjs} +17 -16
- package/dist/{worktree-BlizKDpZ.mjs → worktree-DeBQSVtR.mjs} +3 -1
- package/dist/{xcode-B5SPD--o.mjs → xcode-BzplpQzc.mjs} +7 -7
- package/package.json +5 -5
- package/dist/budget-De3P2rq_.mjs +0 -620
- package/dist/native-run-D7yB_AsB.mjs +0 -143
- package/dist/server-expo-B-CCUJZj.mjs +0 -2
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
|
+
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
+
import { j as workspaceLogsDir } from "./metro-Dzo30hvJ.mjs";
|
|
4
|
+
import { u as resolvePackageJson } from "./project-B8rbutVC.mjs";
|
|
5
|
+
import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
|
|
6
|
+
import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-CeT1nIIk.mjs";
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { pathToFileURL } from "node:url";
|
|
11
|
+
import { format } from "node:util";
|
|
12
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
13
|
+
//#region src/engine/remote-cache.ts
|
|
14
|
+
const EAS_PROVIDER_PACKAGE = "eas-build-cache-provider";
|
|
15
|
+
const RESOLVE_TIMEOUT_MS = 3e4;
|
|
16
|
+
const UPLOAD_TIMEOUT_MS = 6e4;
|
|
17
|
+
const CONFIG_TIMEOUT_MS = 3e4;
|
|
18
|
+
const DYNAMIC_CONFIG_FILES = [
|
|
19
|
+
"app.config.ts",
|
|
20
|
+
"app.config.js",
|
|
21
|
+
"app.config.mjs",
|
|
22
|
+
"app.config.cjs"
|
|
23
|
+
];
|
|
24
|
+
const TIMED_OUT = Symbol("timed-out");
|
|
25
|
+
function dynamicConfigFile(root) {
|
|
26
|
+
for (const name of DYNAMIC_CONFIG_FILES) if (existsSync(join(root, name))) return name;
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function providerFromConfig(config) {
|
|
30
|
+
if (!config || typeof config !== "object") return null;
|
|
31
|
+
const expoField = config.expo;
|
|
32
|
+
const exp = expoField && typeof expoField === "object" ? expoField : config;
|
|
33
|
+
return exp.buildCacheProvider ?? exp.experiments?.buildCacheProvider ?? null;
|
|
34
|
+
}
|
|
35
|
+
function ownerFromConfig(config) {
|
|
36
|
+
if (!config || typeof config !== "object") return null;
|
|
37
|
+
const expoField = config.expo;
|
|
38
|
+
const owner = (expoField && typeof expoField === "object" ? expoField : config).owner;
|
|
39
|
+
return typeof owner === "string" && owner.trim() !== "" ? owner.trim() : null;
|
|
40
|
+
}
|
|
41
|
+
function normalizeProvider(raw) {
|
|
42
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
43
|
+
if (raw === "eas") return {
|
|
44
|
+
name: "eas",
|
|
45
|
+
reference: EAS_PROVIDER_PACKAGE,
|
|
46
|
+
options: {}
|
|
47
|
+
};
|
|
48
|
+
if (typeof raw === "object") {
|
|
49
|
+
const obj = raw;
|
|
50
|
+
if (typeof obj.plugin === "string" && obj.plugin.trim() !== "") {
|
|
51
|
+
const reference = obj.plugin.trim();
|
|
52
|
+
return {
|
|
53
|
+
name: reference,
|
|
54
|
+
reference,
|
|
55
|
+
options: obj.options && typeof obj.options === "object" ? obj.options : {}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { invalid: typeof raw === "string" ? `"${raw}"` : JSON.stringify(raw) };
|
|
60
|
+
}
|
|
61
|
+
function runOptionsFor(platform) {
|
|
62
|
+
return platform === "android" ? { variant: "debug" } : { configuration: "Debug" };
|
|
63
|
+
}
|
|
64
|
+
function isProviderPlugin(plugin) {
|
|
65
|
+
if (!plugin || typeof plugin !== "object") return false;
|
|
66
|
+
const p = plugin;
|
|
67
|
+
const resolves = typeof p.resolveBuildCache === "function" || typeof p.resolveRemoteBuildCache === "function";
|
|
68
|
+
const uploads = typeof p.uploadBuildCache === "function" || typeof p.uploadRemoteBuildCache === "function";
|
|
69
|
+
return resolves && uploads;
|
|
70
|
+
}
|
|
71
|
+
function cacheLevel(value) {
|
|
72
|
+
return value === "local" || value === "remote" ? value : false;
|
|
73
|
+
}
|
|
74
|
+
function exitAfterFlush(code = 0, { exit = (c) => process.exit(c), stream = process.stdout } = {}) {
|
|
75
|
+
try {
|
|
76
|
+
stream.write("", () => exit(code));
|
|
77
|
+
} catch {
|
|
78
|
+
exit(code);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function readProjectConfig(root, { run = null, timeoutMs = CONFIG_TIMEOUT_MS } = {}) {
|
|
82
|
+
const dynamic = dynamicConfigFile(root);
|
|
83
|
+
if (!dynamic) {
|
|
84
|
+
const file = join(root, "app.json");
|
|
85
|
+
if (!existsSync(file)) return {
|
|
86
|
+
config: null,
|
|
87
|
+
source: null
|
|
88
|
+
};
|
|
89
|
+
try {
|
|
90
|
+
return {
|
|
91
|
+
config: JSON.parse(readFileSync(file, "utf-8")),
|
|
92
|
+
source: "app.json"
|
|
93
|
+
};
|
|
94
|
+
} catch (err) {
|
|
95
|
+
return { unavailable: `app.json could not be parsed: ${firstLine(err)}` };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const bin = expoBinPath(root);
|
|
99
|
+
if (!bin) return { unavailable: `${dynamic} is code, so it has to be evaluated to read its buildCacheProvider, and the \`expo\` package is not resolvable from this project (no expo/package.json to read a bin from, and no node_modules/.bin/expo here or in any parent)` };
|
|
100
|
+
const exec = run || ((file, args, opts) => getExecutor().runFile(file, args, opts));
|
|
101
|
+
let stdout;
|
|
102
|
+
try {
|
|
103
|
+
stdout = exec(bin, [
|
|
104
|
+
"config",
|
|
105
|
+
"--json",
|
|
106
|
+
root
|
|
107
|
+
], { timeoutMs });
|
|
108
|
+
} catch (err) {
|
|
109
|
+
return { unavailable: `\`expo config --json\` failed: ${firstLine(err)}` };
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return {
|
|
113
|
+
config: JSON.parse(String(stdout)),
|
|
114
|
+
source: dynamic
|
|
115
|
+
};
|
|
116
|
+
} catch (err) {
|
|
117
|
+
return { unavailable: `\`expo config --json\` did not print JSON: ${firstLine(err)}` };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function loadPlugin(projectRoot, reference, { requireFrom = null } = {}) {
|
|
121
|
+
const localRequire = requireFrom ? requireFrom(projectRoot) : createRequire(join(projectRoot, "package.json"));
|
|
122
|
+
const file = localRequire.resolve(reference);
|
|
123
|
+
let mod;
|
|
124
|
+
try {
|
|
125
|
+
mod = localRequire(file);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (err?.code !== "ERR_REQUIRE_ESM") throw err;
|
|
128
|
+
mod = await import(pathToFileURL(file).href);
|
|
129
|
+
}
|
|
130
|
+
const plugin = mod?.default ?? mod;
|
|
131
|
+
if (!isProviderPlugin(plugin)) throw new Error(`"${reference}" does not export resolveBuildCache and uploadBuildCache functions`);
|
|
132
|
+
return plugin;
|
|
133
|
+
}
|
|
134
|
+
async function loadProjectProvider(projectRoot, { isExpo = true, run = null, requireFrom = null, timeoutMs = CONFIG_TIMEOUT_MS } = {}) {
|
|
135
|
+
if (!isExpo) return { none: true };
|
|
136
|
+
const read = readProjectConfig(projectRoot, {
|
|
137
|
+
run,
|
|
138
|
+
timeoutMs
|
|
139
|
+
});
|
|
140
|
+
if (read.unavailable) return { unavailable: read.unavailable };
|
|
141
|
+
const normalized = normalizeProvider(providerFromConfig(read.config));
|
|
142
|
+
if (!normalized) return { none: true };
|
|
143
|
+
if (normalized.invalid) return { unavailable: `buildCacheProvider is ${normalized.invalid}, which is not "eas" or { plugin: <module> }` };
|
|
144
|
+
if (normalized.reference === "@stim-cli/expo-build-cache") return { none: true };
|
|
145
|
+
let plugin;
|
|
146
|
+
try {
|
|
147
|
+
plugin = await loadPlugin(projectRoot, normalized.reference, { requireFrom });
|
|
148
|
+
} catch (err) {
|
|
149
|
+
const missing = err?.code === "MODULE_NOT_FOUND";
|
|
150
|
+
return { unavailable: normalized.name === "eas" && missing ? `the EAS build cache needs the \`${EAS_PROVIDER_PACKAGE}\` package, which is not installed in this project` : `${normalized.name} could not be loaded: ${firstLine(err)}` };
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
provider: {
|
|
154
|
+
plugin,
|
|
155
|
+
options: normalized.options ?? {}
|
|
156
|
+
},
|
|
157
|
+
name: normalized.name,
|
|
158
|
+
owner: ownerFromConfig(read.config)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const WHOAMI_TIMEOUT_MS = 15e3;
|
|
162
|
+
const EAS_CLI_PACKAGE = "eas-cli";
|
|
163
|
+
const EAS_CLI_BIN = "eas";
|
|
164
|
+
function parseWhoami({ stdout = "", stderr = "", exitCode = 0 } = {}) {
|
|
165
|
+
const out = stripAnsi(stdout);
|
|
166
|
+
const combined = `${out}\n${stripAnsi(stderr)}`;
|
|
167
|
+
if (/^\s*Not logged in\s*$/m.test(combined)) return { loggedOut: true };
|
|
168
|
+
if (exitCode !== 0) return { unknown: firstLine(combined.trim() || `eas whoami exited ${exitCode}`) };
|
|
169
|
+
const lines = out.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
170
|
+
if (lines.length === 0) return { unknown: "eas whoami printed nothing" };
|
|
171
|
+
const raw = lines[0];
|
|
172
|
+
if (raw === void 0) return { unknown: "eas whoami printed nothing" };
|
|
173
|
+
const viaToken = /\(authenticated using EXPO_TOKEN\)\s*$/.test(raw);
|
|
174
|
+
const display = raw.replace(/\s*\(authenticated using EXPO_TOKEN\)\s*$/, "").trim();
|
|
175
|
+
const accounts = [];
|
|
176
|
+
for (const line of lines) {
|
|
177
|
+
const name = /^\u2022\s*(\S+)\s*\(Role:/.exec(line)?.[1];
|
|
178
|
+
if (name !== void 0) accounts.push(name);
|
|
179
|
+
}
|
|
180
|
+
if (accounts.length === 0 && !display.endsWith("(robot)") && display !== "robot") accounts.push(display);
|
|
181
|
+
return {
|
|
182
|
+
loggedIn: true,
|
|
183
|
+
account: display,
|
|
184
|
+
accounts: accounts.length ? accounts : null,
|
|
185
|
+
viaToken
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function isEasAuthFailureText(text) {
|
|
189
|
+
const t = stripAnsi(text || "");
|
|
190
|
+
if (t.trim() === "") return false;
|
|
191
|
+
return /not logged in/i.test(t) || /\beas login\b/i.test(t) || /EXPO_TOKEN/.test(t) || /unauthorized/i.test(t) || /not authorized/i.test(t) || /authentication (failed|required)/i.test(t);
|
|
192
|
+
}
|
|
193
|
+
function easAuthNote(status) {
|
|
194
|
+
const { code, account, owner, reason, phase = "resolve" } = status || {};
|
|
195
|
+
const because = reason ? ` (${reason})` : "";
|
|
196
|
+
if (code === "logged-out") return `eas is not authenticated${because} -- run \`eas login\` (or set EXPO_TOKEN); ` + (phase === "upload" ? "this build stayed in the local cache" : "building with the local cache only");
|
|
197
|
+
if (code === "wrong-account") return `eas is authenticated as ${account}, and this project's owner is ${owner} -- run \`eas login\` as a member of ${owner} (or set EXPO_TOKEN); consulting the EAS cache anyway`;
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
function resolveEasCliBin(projectRoot, { lookupPath = null } = {}) {
|
|
201
|
+
const fromPackage = expoBinFromPackage(resolvePackageJson(projectRoot, EAS_CLI_PACKAGE), EAS_CLI_BIN);
|
|
202
|
+
if (fromPackage) return {
|
|
203
|
+
file: fromPackage,
|
|
204
|
+
source: "project"
|
|
205
|
+
};
|
|
206
|
+
const shim = findBinUpward(projectRoot, EAS_CLI_BIN);
|
|
207
|
+
if (shim) return {
|
|
208
|
+
file: shim,
|
|
209
|
+
source: "project"
|
|
210
|
+
};
|
|
211
|
+
const onPath = lookupPath ? lookupPath() : getExecutor().findExecutable(EAS_CLI_BIN);
|
|
212
|
+
const file = (String(onPath || "").split("\n")[0] ?? "").trim();
|
|
213
|
+
return file ? {
|
|
214
|
+
file,
|
|
215
|
+
source: "path"
|
|
216
|
+
} : null;
|
|
217
|
+
}
|
|
218
|
+
const easAuthCache = /* @__PURE__ */ new Map();
|
|
219
|
+
function checkEasAuth({ projectRoot, owner = null, run = null, resolveBin = null, timeoutMs = WHOAMI_TIMEOUT_MS, cache = easAuthCache }) {
|
|
220
|
+
const key = `${projectRoot}::${owner || ""}`;
|
|
221
|
+
if (cache?.has(key)) return cache.get(key);
|
|
222
|
+
const answer = probeEasAuth({
|
|
223
|
+
projectRoot,
|
|
224
|
+
owner,
|
|
225
|
+
run,
|
|
226
|
+
resolveBin,
|
|
227
|
+
timeoutMs
|
|
228
|
+
});
|
|
229
|
+
cache?.set(key, answer);
|
|
230
|
+
return answer;
|
|
231
|
+
}
|
|
232
|
+
function probeEasAuth({ projectRoot, owner, run, resolveBin, timeoutMs }) {
|
|
233
|
+
const bin = (resolveBin || resolveEasCliBin)(projectRoot);
|
|
234
|
+
if (!bin) return {
|
|
235
|
+
failed: true,
|
|
236
|
+
code: "no-cli",
|
|
237
|
+
reason: "no `eas` executable is resolvable from this project or on PATH",
|
|
238
|
+
remedy: "Install eas-cli (`npm i -g eas-cli`, or as a project devDependency), then run `eas login`."
|
|
239
|
+
};
|
|
240
|
+
const exec = run || ((file, args, opts) => getExecutor().runFile(file, args, opts));
|
|
241
|
+
let result;
|
|
242
|
+
try {
|
|
243
|
+
result = {
|
|
244
|
+
stdout: String(exec(bin.file, ["whoami"], { timeoutMs }) ?? ""),
|
|
245
|
+
exitCode: 0
|
|
246
|
+
};
|
|
247
|
+
} catch (e) {
|
|
248
|
+
const err = e;
|
|
249
|
+
if (err?.code === "ETIMEDOUT" || err?.signal === "SIGTERM" || err?.killed) return { unknown: `eas whoami timed out after ${timeoutMs}ms` };
|
|
250
|
+
result = {
|
|
251
|
+
stdout: String(err?.stdout ?? ""),
|
|
252
|
+
stderr: String(err?.stderr ?? err?.message ?? ""),
|
|
253
|
+
exitCode: typeof err?.status === "number" ? err.status : 1
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const parsed = parseWhoami(result);
|
|
257
|
+
if (parsed.loggedOut) return {
|
|
258
|
+
failed: true,
|
|
259
|
+
code: "logged-out",
|
|
260
|
+
reason: "eas whoami says \"Not logged in\"",
|
|
261
|
+
remedy: "Run `eas login` (or set EXPO_TOKEN)."
|
|
262
|
+
};
|
|
263
|
+
if (parsed.unknown) return { unknown: parsed.unknown };
|
|
264
|
+
if (owner && Array.isArray(parsed.accounts) && !parsed.accounts.includes(owner)) return {
|
|
265
|
+
failed: true,
|
|
266
|
+
code: "wrong-account",
|
|
267
|
+
account: parsed.account,
|
|
268
|
+
accounts: parsed.accounts,
|
|
269
|
+
owner,
|
|
270
|
+
reason: `eas is authenticated as ${parsed.account} (accounts: ${parsed.accounts.join(", ")}), which does not include this project's owner ${owner}`,
|
|
271
|
+
remedy: `Run \`eas login\` as a member of ${owner}, or set EXPO_TOKEN to a token for it.`
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
ok: true,
|
|
275
|
+
account: parsed.account,
|
|
276
|
+
accounts: parsed.accounts,
|
|
277
|
+
viaToken: parsed.viaToken,
|
|
278
|
+
source: bin.source
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const capturing = [];
|
|
282
|
+
const abandoned = /* @__PURE__ */ new Set();
|
|
283
|
+
let patched = null;
|
|
284
|
+
const PROVIDER_CONTEXT = new AsyncLocalStorage();
|
|
285
|
+
function uploadDestination(lines) {
|
|
286
|
+
const text = (lines || []).map(stripAnsi);
|
|
287
|
+
for (const line of text) {
|
|
288
|
+
const url = /(https?:\/\/[^\s'"]+)/.exec(line)?.[1];
|
|
289
|
+
if (url !== void 0) return url.replace(/[.,)\]]+$/, "");
|
|
290
|
+
}
|
|
291
|
+
for (const line of text) {
|
|
292
|
+
const slug = /\bto\s+(@?[\w.-]+\/[\w.-]+)/i.exec(line)?.[1];
|
|
293
|
+
if (slug !== void 0) return slug.replace(/[.,)\]]+$/, "");
|
|
294
|
+
}
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
function providerNote(text) {
|
|
298
|
+
return `${"cache".padEnd(11)} ${text}`;
|
|
299
|
+
}
|
|
300
|
+
function currentFrame() {
|
|
301
|
+
const store = PROVIDER_CONTEXT.getStore();
|
|
302
|
+
return store && (capturing.includes(store) || abandoned.has(store)) ? store : null;
|
|
303
|
+
}
|
|
304
|
+
function install() {
|
|
305
|
+
if (patched && process.stdout.write === patched.patchedWrite) return;
|
|
306
|
+
const stdout = process.stdout;
|
|
307
|
+
const write = stdout.write.bind(stdout);
|
|
308
|
+
const log = console.log;
|
|
309
|
+
const passthrough = write;
|
|
310
|
+
const patchedWrite = ((chunk, encoding, callback) => {
|
|
311
|
+
const frame = currentFrame();
|
|
312
|
+
if (!frame) return passthrough(chunk, encoding, callback);
|
|
313
|
+
const cb = typeof encoding === "function" ? encoding : callback;
|
|
314
|
+
absorb(frame, typeof chunk === "string" ? chunk : String(chunk));
|
|
315
|
+
if (typeof cb === "function") cb();
|
|
316
|
+
return true;
|
|
317
|
+
});
|
|
318
|
+
const patchedLog = (...args) => {
|
|
319
|
+
const frame = currentFrame();
|
|
320
|
+
if (!frame) return log(...args);
|
|
321
|
+
absorb(frame, `${format(...args)}\n`);
|
|
322
|
+
};
|
|
323
|
+
stdout.write = patchedWrite;
|
|
324
|
+
console.log = patchedLog;
|
|
325
|
+
patched = {
|
|
326
|
+
stdout,
|
|
327
|
+
write,
|
|
328
|
+
log,
|
|
329
|
+
patchedWrite,
|
|
330
|
+
patchedLog
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function uninstall() {
|
|
334
|
+
if (!patched || capturing.length || abandoned.size) return;
|
|
335
|
+
if (patched.stdout.write === patched.patchedWrite) patched.stdout.write = patched.write;
|
|
336
|
+
if (console.log === patched.patchedLog) console.log = patched.log;
|
|
337
|
+
patched = null;
|
|
338
|
+
}
|
|
339
|
+
function absorb(frame, chunk) {
|
|
340
|
+
try {
|
|
341
|
+
process.stderr.write(chunk);
|
|
342
|
+
} catch {}
|
|
343
|
+
frame.pending += chunk;
|
|
344
|
+
let index = frame.pending.indexOf("\n");
|
|
345
|
+
while (index !== -1) {
|
|
346
|
+
emitLine(frame, frame.pending.slice(0, index));
|
|
347
|
+
frame.pending = frame.pending.slice(index + 1);
|
|
348
|
+
index = frame.pending.indexOf("\n");
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function emitLine(frame, raw) {
|
|
352
|
+
const line = stripAnsi(raw).trim();
|
|
353
|
+
if (line === "") return;
|
|
354
|
+
frame.lines.push(line);
|
|
355
|
+
const writer = frame.writer();
|
|
356
|
+
try {
|
|
357
|
+
writer?.write({
|
|
358
|
+
src: "build",
|
|
359
|
+
level: "debug",
|
|
360
|
+
event: "provider",
|
|
361
|
+
msg: line
|
|
362
|
+
});
|
|
363
|
+
} catch {}
|
|
364
|
+
frame.onLine?.(line);
|
|
365
|
+
}
|
|
366
|
+
function beginCapture({ logWriter = null, projectRoot = null, platform = null, onLine = null } = {}) {
|
|
367
|
+
let own = null;
|
|
368
|
+
const frame = {
|
|
369
|
+
lines: [],
|
|
370
|
+
pending: "",
|
|
371
|
+
onLine,
|
|
372
|
+
writer: () => {
|
|
373
|
+
if (logWriter) return logWriter;
|
|
374
|
+
if (own) return own;
|
|
375
|
+
if (!projectRoot || !platform) return null;
|
|
376
|
+
own = createNdjsonWriter(join(workspaceLogsDir(projectRoot), `build-${platform}.ndjson`));
|
|
377
|
+
return own;
|
|
378
|
+
},
|
|
379
|
+
close: () => {
|
|
380
|
+
own?.close?.();
|
|
381
|
+
own = null;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
capturing.push(frame);
|
|
385
|
+
install();
|
|
386
|
+
return frame;
|
|
387
|
+
}
|
|
388
|
+
function endCapture(frame) {
|
|
389
|
+
if (!frame) return;
|
|
390
|
+
const at = capturing.lastIndexOf(frame);
|
|
391
|
+
if (at !== -1) capturing.splice(at, 1);
|
|
392
|
+
abandoned.delete(frame);
|
|
393
|
+
if (frame.pending !== "") {
|
|
394
|
+
const rest = frame.pending;
|
|
395
|
+
frame.pending = "";
|
|
396
|
+
emitLine(frame, rest);
|
|
397
|
+
}
|
|
398
|
+
frame.close();
|
|
399
|
+
uninstall();
|
|
400
|
+
}
|
|
401
|
+
function abandonCapture(frame, work) {
|
|
402
|
+
if (!frame) return;
|
|
403
|
+
const at = capturing.lastIndexOf(frame);
|
|
404
|
+
if (at !== -1) capturing.splice(at, 1);
|
|
405
|
+
abandoned.add(frame);
|
|
406
|
+
Promise.resolve(work).then(() => endCapture(frame), () => endCapture(frame));
|
|
407
|
+
}
|
|
408
|
+
async function resolveRemote({ provider, platform, projectRoot, fingerprintHash, runOptions = null, timeoutMs = RESOLVE_TIMEOUT_MS, logWriter = null } = {}) {
|
|
409
|
+
if (!provider?.plugin || !fingerprintHash) return null;
|
|
410
|
+
const opts = runOptions || runOptionsFor(platform);
|
|
411
|
+
const outcome = await withBudget(async () => {
|
|
412
|
+
const props = {
|
|
413
|
+
fingerprintHash: await providerFingerprint({
|
|
414
|
+
provider,
|
|
415
|
+
platform,
|
|
416
|
+
projectRoot,
|
|
417
|
+
runOptions: opts
|
|
418
|
+
}) ?? fingerprintHash,
|
|
419
|
+
platform,
|
|
420
|
+
runOptions: opts,
|
|
421
|
+
projectRoot
|
|
422
|
+
};
|
|
423
|
+
return typeof provider.plugin.resolveBuildCache === "function" ? provider.plugin.resolveBuildCache(props, provider.options) : provider.plugin.resolveRemoteBuildCache(props, provider.options);
|
|
424
|
+
}, timeoutMs, {
|
|
425
|
+
logWriter,
|
|
426
|
+
projectRoot,
|
|
427
|
+
platform
|
|
428
|
+
});
|
|
429
|
+
if (outcome.timedOut) return { timedOut: true };
|
|
430
|
+
if (outcome.error) return { failed: firstLine(outcome.error) };
|
|
431
|
+
const appPath = typeof outcome.value === "string" ? outcome.value.trim() : "";
|
|
432
|
+
if (!appPath) return null;
|
|
433
|
+
if (!existsSync(appPath)) return { failed: `returned ${appPath}, which does not exist` };
|
|
434
|
+
return { appPath };
|
|
435
|
+
}
|
|
436
|
+
async function uploadRemote({ provider, platform, projectRoot, fingerprintHash, buildPath, runOptions = null, timeoutMs = UPLOAD_TIMEOUT_MS, logWriter = null, note = (line) => console.error(line) } = {}) {
|
|
437
|
+
if (!provider?.plugin || !fingerprintHash || !buildPath) return { skipped: true };
|
|
438
|
+
const opts = runOptions || runOptionsFor(platform);
|
|
439
|
+
let announced = false;
|
|
440
|
+
const onLine = (line) => {
|
|
441
|
+
if (announced) return;
|
|
442
|
+
const dest = uploadDestination([line]);
|
|
443
|
+
if (!dest) return;
|
|
444
|
+
announced = true;
|
|
445
|
+
note(providerNote(`uploading to ${dest}`));
|
|
446
|
+
};
|
|
447
|
+
const outcome = await withBudget(async () => {
|
|
448
|
+
const props = {
|
|
449
|
+
projectRoot,
|
|
450
|
+
platform,
|
|
451
|
+
fingerprintHash: await providerFingerprint({
|
|
452
|
+
provider,
|
|
453
|
+
platform,
|
|
454
|
+
projectRoot,
|
|
455
|
+
runOptions: opts
|
|
456
|
+
}) ?? fingerprintHash,
|
|
457
|
+
buildPath,
|
|
458
|
+
runOptions: opts
|
|
459
|
+
};
|
|
460
|
+
return typeof provider.plugin.uploadBuildCache === "function" ? provider.plugin.uploadBuildCache(props, provider.options) : provider.plugin.uploadRemoteBuildCache(props, provider.options);
|
|
461
|
+
}, timeoutMs, {
|
|
462
|
+
logWriter,
|
|
463
|
+
projectRoot,
|
|
464
|
+
platform,
|
|
465
|
+
onLine
|
|
466
|
+
});
|
|
467
|
+
if (outcome.timedOut) return { timedOut: true };
|
|
468
|
+
if (outcome.error) return { failed: firstLine(outcome.error) };
|
|
469
|
+
if (typeof outcome.value !== "string" || outcome.value.trim() === "") {
|
|
470
|
+
const authLine = outcome.lines.find((line) => isEasAuthFailureText(line));
|
|
471
|
+
return { failed: authLine ? firstLine(authLine) : "the provider returned no upload destination" };
|
|
472
|
+
}
|
|
473
|
+
const destination = uploadDestination(outcome.lines);
|
|
474
|
+
return destination ? {
|
|
475
|
+
uploaded: true,
|
|
476
|
+
destination
|
|
477
|
+
} : { uploaded: true };
|
|
478
|
+
}
|
|
479
|
+
async function providerFingerprint({ provider, platform, projectRoot, runOptions }) {
|
|
480
|
+
if (typeof provider.plugin.calculateFingerprintHash !== "function") return null;
|
|
481
|
+
try {
|
|
482
|
+
const hash = await provider.plugin.calculateFingerprintHash({
|
|
483
|
+
projectRoot,
|
|
484
|
+
platform,
|
|
485
|
+
runOptions
|
|
486
|
+
}, provider.options);
|
|
487
|
+
return typeof hash === "string" && hash.trim() !== "" ? hash.trim() : null;
|
|
488
|
+
} catch {
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
async function withBudget(factory, ms, capture) {
|
|
493
|
+
let timer = null;
|
|
494
|
+
const timeout = new Promise((resolve) => {
|
|
495
|
+
timer = setTimeout(() => resolve(TIMED_OUT), ms);
|
|
496
|
+
timer?.unref?.();
|
|
497
|
+
});
|
|
498
|
+
const frame = beginCapture(capture || {});
|
|
499
|
+
const work = Promise.resolve().then(() => PROVIDER_CONTEXT.run(frame, factory)).then((value) => ({ value }), (error) => ({ error }));
|
|
500
|
+
try {
|
|
501
|
+
const settled = await Promise.race([work, timeout]);
|
|
502
|
+
if (settled === TIMED_OUT) {
|
|
503
|
+
abandonCapture(frame, work);
|
|
504
|
+
return {
|
|
505
|
+
timedOut: true,
|
|
506
|
+
lines: frame.lines
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
endCapture(frame);
|
|
510
|
+
return {
|
|
511
|
+
...settled,
|
|
512
|
+
lines: frame.lines
|
|
513
|
+
};
|
|
514
|
+
} catch (err) {
|
|
515
|
+
endCapture(frame);
|
|
516
|
+
throw err;
|
|
517
|
+
} finally {
|
|
518
|
+
if (timer) clearTimeout(timer);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
function firstLine(err) {
|
|
522
|
+
const line = (String(err?.message || err || "unknown error").trim().split("\n")[0] ?? "").trim();
|
|
523
|
+
return line.length > 200 ? `${line.slice(0, 197)}...` : line;
|
|
524
|
+
}
|
|
525
|
+
//#endregion
|
|
526
|
+
export { easAuthNote as a, loadProjectProvider as c, readProjectConfig as d, resolveEasCliBin as f, checkEasAuth as i, ownerFromConfig as l, uploadRemote as m, UPLOAD_TIMEOUT_MS as n, exitAfterFlush as o, resolveRemote as p, cacheLevel as r, isEasAuthFailureText as s, RESOLVE_TIMEOUT_MS as t, providerFromConfig as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as __require, t as __commonJSMin } from "./rolldown-runtime-BsOwBuO_.mjs";
|
|
2
2
|
import { n as supervisorError } from "./errors-B6W7FkxQ.mjs";
|
|
3
|
-
import { w as projectMetroSharedCache } from "./settings-
|
|
3
|
+
import { w as projectMetroSharedCache } from "./settings-BlyDn2Oz.mjs";
|
|
4
4
|
import { a as metroStoreRoot, o as registerMetroStore, t as appendCacheStore } from "./metro-store-DzeWkfqW.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { isAbsolute, join, relative, sep } from "node:path";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
2
|
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
3
|
-
import { u as resolvePackageJson } from "./project-
|
|
3
|
+
import { u as resolvePackageJson } from "./project-B8rbutVC.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 { w as projectMetroSharedCache } from "./settings-
|
|
6
|
+
import { w as projectMetroSharedCache } from "./settings-BlyDn2Oz.mjs";
|
|
7
7
|
import { a as metroStoreRoot, i as metroStoreConfirmedRoot, n as expoMetroConfigPath, o as registerMetroStore, r as expoMetroStoreEnv } from "./metro-store-DzeWkfqW.mjs";
|
|
8
8
|
import { accessSync, constants, existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import { LOG_ROTATE_BYTES } from "@stim-cli/core";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { s as gitCommonDir, y as repoRoot } from "./worktree-
|
|
1
|
+
import { _ as loadConfig$1, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-0jCcMM0E.mjs";
|
|
2
|
+
import { s as gitCommonDir, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
|
|
3
3
|
import { existsSync, readFileSync, realpathSync, statSync } from "fs";
|
|
4
4
|
import { isAbsolute, join, relative, resolve, sep } from "path";
|
|
5
5
|
import { ANDROID_COMPILER_CACHE_CHOICES, ANDROID_PCH_CHOICES, REMOTE_DEVICE_BACKENDS, SETTINGS, SETTING_GROUPS, TUNNEL_MODES, acceptsShape, expectedShape, isLayeredSetting, settingDefinition, settingValueError } from "@stim-cli/core/state";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { s as gitCommonDir, y as repoRoot } from "./worktree-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { D as writeConfigSetting, E as withConfigLock$1, _ as loadConfig$1, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-0jCcMM0E.mjs";
|
|
2
|
+
import { s as gitCommonDir, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
|
|
3
|
+
import { i as findProjectRoot, t as NO_PROJECT_REFUSAL } from "./project-B8rbutVC.mjs";
|
|
4
|
+
import { n as stimDesktopInstalled, t as settingDefault } from "./stim-desktop-D0xhpZt8.mjs";
|
|
5
|
+
import { D as readCommittedSettings, L as unknownSettingKeys } from "./settings-BlyDn2Oz.mjs";
|
|
5
6
|
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
7
|
import { SETTINGS, SETTING_SCOPES, coerceSettingText, isJsonObject, isSensitiveReference, settingDefinition, settingValueError } from "@stim-cli/core/state";
|
|
7
8
|
import { join } from "node:path";
|
|
@@ -27,12 +28,14 @@ function readContext(env) {
|
|
|
27
28
|
const projectPath = findProjectRoot(process.cwd());
|
|
28
29
|
const start = projectPath ?? process.cwd();
|
|
29
30
|
const common = gitCommonDir(start);
|
|
31
|
+
let installed;
|
|
30
32
|
return {
|
|
31
33
|
projectPath,
|
|
32
34
|
gitCommonDir: common,
|
|
33
35
|
repoRoot: common ? repoRoot(start) ?? projectPath : null,
|
|
34
36
|
machine: loadConfig$1(),
|
|
35
|
-
env
|
|
37
|
+
env,
|
|
38
|
+
desktopInstalled: () => installed ??= stimDesktopInstalled()
|
|
36
39
|
};
|
|
37
40
|
}
|
|
38
41
|
function valueAt(settings, key) {
|
|
@@ -85,6 +88,7 @@ function settingEntry(context, setting) {
|
|
|
85
88
|
const winner = PRECEDENCE.find((scope) => scope in layers);
|
|
86
89
|
let value = null;
|
|
87
90
|
let origin = null;
|
|
91
|
+
let defaultReason = null;
|
|
88
92
|
if (env) {
|
|
89
93
|
value = masked(setting, envSettingValue(setting, envValue));
|
|
90
94
|
origin = "env";
|
|
@@ -95,8 +99,10 @@ function settingEntry(context, setting) {
|
|
|
95
99
|
value = layers[winner];
|
|
96
100
|
origin = winner;
|
|
97
101
|
} else if (setting.default !== void 0) {
|
|
98
|
-
|
|
102
|
+
const fallback = settingDefault(setting, context.desktopInstalled);
|
|
103
|
+
value = fallback.value;
|
|
99
104
|
origin = "default";
|
|
105
|
+
defaultReason = fallback.reason;
|
|
100
106
|
}
|
|
101
107
|
return {
|
|
102
108
|
key: setting.key,
|
|
@@ -107,7 +113,8 @@ function settingEntry(context, setting) {
|
|
|
107
113
|
name: "STIM_HOME",
|
|
108
114
|
value: context.env.STIM_HOME
|
|
109
115
|
} } : {},
|
|
110
|
-
...setting.sensitive ? { sensitive: true } : {}
|
|
116
|
+
...setting.sensitive ? { sensitive: true } : {},
|
|
117
|
+
...defaultReason ? { defaultReason } : {}
|
|
111
118
|
};
|
|
112
119
|
}
|
|
113
120
|
function unknownEntries(context) {
|
|
@@ -269,6 +276,10 @@ function writeSetting(context, setting, scope, value) {
|
|
|
269
276
|
function formatValue(value) {
|
|
270
277
|
return typeof value === "string" ? value : JSON.stringify(value);
|
|
271
278
|
}
|
|
279
|
+
function formatOrigin(entry) {
|
|
280
|
+
if (entry.origin === null) return "unset";
|
|
281
|
+
return entry.defaultReason ? `${entry.origin}: ${entry.defaultReason}` : entry.origin;
|
|
282
|
+
}
|
|
272
283
|
const CONSOLE = {
|
|
273
284
|
out: (line) => console.log(line),
|
|
274
285
|
note: (line) => console.error(line)
|
|
@@ -302,9 +313,8 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
|
|
|
302
313
|
}
|
|
303
314
|
const width = Math.max(...payload.settings.map((entry) => entry.key.length));
|
|
304
315
|
for (const entry of payload.settings) {
|
|
305
|
-
const origin = entry.origin ?? "unset";
|
|
306
316
|
const shown = entry.origin === null ? "" : formatValue(entry.value);
|
|
307
|
-
io.out(`${entry.key.padEnd(width)} ${shown}${shown ? " " : ""}${chalk.dim(`(${
|
|
317
|
+
io.out(`${entry.key.padEnd(width)} ${shown}${shown ? " " : ""}${chalk.dim(`(${formatOrigin(entry)})`)}`);
|
|
308
318
|
}
|
|
309
319
|
for (const entry of payload.unknown) io.note(chalk.yellow(`Warning: ${entry.key} in ${entry.file} is not read by Stim.`));
|
|
310
320
|
}));
|
|
@@ -323,7 +333,9 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
|
|
|
323
333
|
} : entry));
|
|
324
334
|
return;
|
|
325
335
|
}
|
|
326
|
-
if (value
|
|
336
|
+
if (value === null) return;
|
|
337
|
+
io.out(formatValue(value));
|
|
338
|
+
if (!scope && entry.defaultReason) io.note(chalk.dim(`(${formatOrigin(entry)})`));
|
|
327
339
|
}));
|
|
328
340
|
settings.command("set <key> <value>").description("Write a setting to one layer").option("--scope <scope>", `the layer to write: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the written setting as JSON").action((key, raw, opts, command) => run(wantsJson(opts, command), io, () => {
|
|
329
341
|
const setting = requireSetting(key);
|
|
@@ -363,7 +375,7 @@ function report(io, json, write, setting, context, verb) {
|
|
|
363
375
|
}));
|
|
364
376
|
return;
|
|
365
377
|
}
|
|
366
|
-
const effective = entry.origin === null ? "unset" : `${formatValue(entry.value)} (${entry
|
|
378
|
+
const effective = entry.origin === null ? "unset" : `${formatValue(entry.value)} (${formatOrigin(entry)})`;
|
|
367
379
|
if (!write.changed) {
|
|
368
380
|
io.out(`${write.key} was not set in ${write.file}; effective value: ${effective}`);
|
|
369
381
|
return;
|