@wix/himalaya-cli 0.1113.0 → 0.1115.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/cli.mjs +949 -648
- package/guides/himi-mcp.md +16 -5
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1456,7 +1456,7 @@ function sentinelizeIdentity(body, identity) {
|
|
|
1456
1456
|
}
|
|
1457
1457
|
if (identity.name) {
|
|
1458
1458
|
const re = new RegExp(`\\b(${NAME_FIELDS.join("|")})(["']?\\s*[:=]\\s*)(["'])${escapeRe(identity.name)}\\3`, "g");
|
|
1459
|
-
out2 = out2.replace(re, (_m, key2,
|
|
1459
|
+
out2 = out2.replace(re, (_m, key2, sep18, q) => `${key2}${sep18}${q}__HIMI_APP_NAME__${q}`);
|
|
1460
1460
|
}
|
|
1461
1461
|
return out2;
|
|
1462
1462
|
}
|
|
@@ -2513,14 +2513,14 @@ function commitChange(repo, base, branch, rel, body) {
|
|
|
2513
2513
|
function runSelfTest() {
|
|
2514
2514
|
let failed2 = 0;
|
|
2515
2515
|
for (const testCase of SELF_TEST_CASES) {
|
|
2516
|
-
let
|
|
2516
|
+
let ok2 = false;
|
|
2517
2517
|
let thrown = null;
|
|
2518
2518
|
try {
|
|
2519
|
-
|
|
2519
|
+
ok2 = testCase.run() === true;
|
|
2520
2520
|
} catch (error) {
|
|
2521
2521
|
thrown = error?.message || String(error);
|
|
2522
2522
|
}
|
|
2523
|
-
if (
|
|
2523
|
+
if (ok2) {
|
|
2524
2524
|
process.stdout.write(` \u2713 ${testCase.name}
|
|
2525
2525
|
`);
|
|
2526
2526
|
continue;
|
|
@@ -3742,7 +3742,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
3742
3742
|
tokenCache.set(cacheKey, fromEnv);
|
|
3743
3743
|
return fromEnv;
|
|
3744
3744
|
}
|
|
3745
|
-
const token = await new Promise((
|
|
3745
|
+
const token = await new Promise((resolve54, reject) => {
|
|
3746
3746
|
let child;
|
|
3747
3747
|
try {
|
|
3748
3748
|
child = spawnImpl("wix", [...args]);
|
|
@@ -3771,12 +3771,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
3771
3771
|
child.stdout?.on("data", (d) => {
|
|
3772
3772
|
out2 += String(d);
|
|
3773
3773
|
const m = out2.match(TOKEN_RE);
|
|
3774
|
-
if (m) done(() =>
|
|
3774
|
+
if (m) done(() => resolve54(m[0]));
|
|
3775
3775
|
});
|
|
3776
3776
|
child.stderr?.on("data", (d) => {
|
|
3777
3777
|
out2 += String(d);
|
|
3778
3778
|
const m = out2.match(TOKEN_RE);
|
|
3779
|
-
if (m) done(() =>
|
|
3779
|
+
if (m) done(() => resolve54(m[0]));
|
|
3780
3780
|
});
|
|
3781
3781
|
child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
|
|
3782
3782
|
child.on("exit", (code) => done(() => reject(new Error(
|
|
@@ -3965,8 +3965,8 @@ function committedProvisioningPath(name) {
|
|
|
3965
3965
|
function committedShellFor(path2) {
|
|
3966
3966
|
const normalized = path2.replace(/\\/g, "/");
|
|
3967
3967
|
return SHELL_NAMES2.find((name) => {
|
|
3968
|
-
const
|
|
3969
|
-
return normalized ===
|
|
3968
|
+
const relative15 = committedProvisioningPath(name);
|
|
3969
|
+
return normalized === relative15 || normalized.endsWith(`/${relative15}`);
|
|
3970
3970
|
});
|
|
3971
3971
|
}
|
|
3972
3972
|
function isBrandable(repoRoot2, name) {
|
|
@@ -4486,7 +4486,7 @@ function confinementPlugin(contentRoot) {
|
|
|
4486
4486
|
}
|
|
4487
4487
|
function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
4488
4488
|
const seen = /* @__PURE__ */ new Set();
|
|
4489
|
-
const
|
|
4489
|
+
const refuse6 = (p, why) => {
|
|
4490
4490
|
throw new Error(
|
|
4491
4491
|
`refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
|
|
4492
4492
|
);
|
|
@@ -4552,7 +4552,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
|
4552
4552
|
try {
|
|
4553
4553
|
manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
|
|
4554
4554
|
} catch {
|
|
4555
|
-
|
|
4555
|
+
refuse6(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
|
|
4556
4556
|
}
|
|
4557
4557
|
const field = manifest?.tsconfig;
|
|
4558
4558
|
if (typeof field === "string" && field) {
|
|
@@ -4568,7 +4568,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
|
4568
4568
|
const real = realpathOrSelf(file);
|
|
4569
4569
|
if (seen.has(real)) return;
|
|
4570
4570
|
seen.add(real);
|
|
4571
|
-
if (!allows(real))
|
|
4571
|
+
if (!allows(real)) refuse6(file, "it is outside this content package");
|
|
4572
4572
|
let raw;
|
|
4573
4573
|
try {
|
|
4574
4574
|
raw = readFileSync10(real, "utf8");
|
|
@@ -4579,7 +4579,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
|
4579
4579
|
try {
|
|
4580
4580
|
parsed = JSON.parse(stripJsonc(raw));
|
|
4581
4581
|
} catch {
|
|
4582
|
-
|
|
4582
|
+
refuse6(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
|
|
4583
4583
|
}
|
|
4584
4584
|
const ext = parsed?.extends;
|
|
4585
4585
|
for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
|
|
@@ -8472,8 +8472,8 @@ function textOf(node) {
|
|
|
8472
8472
|
function plainText(node) {
|
|
8473
8473
|
if (typeOf(node) === "TEXT") return str(at(node, "textData", "text"));
|
|
8474
8474
|
const children = kids(node).filter(isObj);
|
|
8475
|
-
const
|
|
8476
|
-
return children.map(plainText).join(
|
|
8475
|
+
const sep18 = children.every((c) => typeOf(c) === "TEXT") ? "" : "\n";
|
|
8476
|
+
return children.map(plainText).join(sep18);
|
|
8477
8477
|
}
|
|
8478
8478
|
function alignOf(v) {
|
|
8479
8479
|
switch (v) {
|
|
@@ -13140,6 +13140,7 @@ function resolveIdiom(tokens, ctx = {}) {
|
|
|
13140
13140
|
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
13141
13141
|
var init_idiom = __esm({
|
|
13142
13142
|
"../../core/ts/src/idiom.ts"() {
|
|
13143
|
+
"use strict";
|
|
13143
13144
|
IDIOM_CONTEXTS = {
|
|
13144
13145
|
ios: { native: ["ios"] },
|
|
13145
13146
|
android: { native: ["material"] },
|
|
@@ -14806,8 +14807,8 @@ function matchWeightCss(available, desired) {
|
|
|
14806
14807
|
const upFrom = (n) => sorted2.find((w) => w >= n);
|
|
14807
14808
|
const downFrom = (n) => [...sorted2].reverse().find((w) => w <= n);
|
|
14808
14809
|
if (desired >= 400 && desired <= 500) {
|
|
14809
|
-
const
|
|
14810
|
-
return
|
|
14810
|
+
const within2 = sorted2.find((w) => w >= desired && w <= 500);
|
|
14811
|
+
return within2 ?? downFrom(desired) ?? upFrom(desired);
|
|
14811
14812
|
}
|
|
14812
14813
|
if (desired < 400) return downFrom(desired) ?? upFrom(desired);
|
|
14813
14814
|
return upFrom(desired) ?? downFrom(desired);
|
|
@@ -15930,29 +15931,29 @@ function matchRuleEx(rules, method, path2, ctx = {}) {
|
|
|
15930
15931
|
}
|
|
15931
15932
|
if (m.query) {
|
|
15932
15933
|
const q = ctx.query ?? {};
|
|
15933
|
-
let
|
|
15934
|
+
let ok2 = true;
|
|
15934
15935
|
for (const [k, v] of Object.entries(m.query)) {
|
|
15935
15936
|
if (q[k] !== v) {
|
|
15936
|
-
|
|
15937
|
+
ok2 = false;
|
|
15937
15938
|
break;
|
|
15938
15939
|
}
|
|
15939
15940
|
captures[`query.${k}`] = q[k];
|
|
15940
15941
|
}
|
|
15941
|
-
if (!
|
|
15942
|
+
if (!ok2) continue;
|
|
15942
15943
|
for (const [k, v] of Object.entries(q)) captures[`query.${k}`] = v;
|
|
15943
15944
|
} else if (ctx.query) {
|
|
15944
15945
|
for (const [k, v] of Object.entries(ctx.query)) captures[`query.${k}`] = v;
|
|
15945
15946
|
}
|
|
15946
15947
|
if (m.headers) {
|
|
15947
15948
|
const hh = lc(ctx.headers);
|
|
15948
|
-
let
|
|
15949
|
+
let ok2 = true;
|
|
15949
15950
|
for (const [k, v] of Object.entries(m.headers)) {
|
|
15950
15951
|
if (hh[k.toLowerCase()] !== v) {
|
|
15951
|
-
|
|
15952
|
+
ok2 = false;
|
|
15952
15953
|
break;
|
|
15953
15954
|
}
|
|
15954
15955
|
}
|
|
15955
|
-
if (!
|
|
15956
|
+
if (!ok2) continue;
|
|
15956
15957
|
}
|
|
15957
15958
|
if (m.bodyContains && !(ctx.body ?? "").includes(m.bodyContains)) continue;
|
|
15958
15959
|
return { rule: r, captures };
|
|
@@ -18574,11 +18575,11 @@ function appleScriptString(s) {
|
|
|
18574
18575
|
function runNotifier(cmd, args) {
|
|
18575
18576
|
return new Promise((done) => {
|
|
18576
18577
|
let settled = false;
|
|
18577
|
-
const finish2 = (
|
|
18578
|
+
const finish2 = (ok2) => {
|
|
18578
18579
|
if (!settled) {
|
|
18579
18580
|
settled = true;
|
|
18580
18581
|
clearTimeout(timer);
|
|
18581
|
-
done(
|
|
18582
|
+
done(ok2);
|
|
18582
18583
|
}
|
|
18583
18584
|
};
|
|
18584
18585
|
const child = spawn3(cmd, args, { stdio: "ignore" });
|
|
@@ -19465,10 +19466,10 @@ var init_preview = __esm({
|
|
|
19465
19466
|
}
|
|
19466
19467
|
},
|
|
19467
19468
|
kill: (pid, signal) => process.kill(pid, signal),
|
|
19468
|
-
portFree: (port) => new Promise((
|
|
19469
|
+
portFree: (port) => new Promise((resolve54) => {
|
|
19469
19470
|
const s = createServer2();
|
|
19470
|
-
s.once("error", () =>
|
|
19471
|
-
s.listen(port, "127.0.0.1", () => s.close(() =>
|
|
19471
|
+
s.once("error", () => resolve54(false));
|
|
19472
|
+
s.listen(port, "127.0.0.1", () => s.close(() => resolve54(true)));
|
|
19472
19473
|
}),
|
|
19473
19474
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
19474
19475
|
servingIdentity: async (origin) => {
|
|
@@ -20612,7 +20613,7 @@ async function injectRequest(listener, request) {
|
|
|
20612
20613
|
req.headers.host ??= url.host;
|
|
20613
20614
|
if (body && body.length > 0) req.push(body);
|
|
20614
20615
|
req.push(null);
|
|
20615
|
-
return await new Promise((
|
|
20616
|
+
return await new Promise((resolve54, reject) => {
|
|
20616
20617
|
const streamed = () => {
|
|
20617
20618
|
queueMicrotask(() => {
|
|
20618
20619
|
req.emit("close");
|
|
@@ -20628,7 +20629,7 @@ async function injectRequest(listener, request) {
|
|
|
20628
20629
|
else headers2.set(name, value);
|
|
20629
20630
|
}
|
|
20630
20631
|
const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
|
|
20631
|
-
|
|
20632
|
+
resolve54(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
|
|
20632
20633
|
}, streamed);
|
|
20633
20634
|
res.on("inject-error", reject);
|
|
20634
20635
|
try {
|
|
@@ -21334,7 +21335,7 @@ function redactBodyString(body) {
|
|
|
21334
21335
|
} catch {
|
|
21335
21336
|
}
|
|
21336
21337
|
}
|
|
21337
|
-
return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name,
|
|
21338
|
+
return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep18) => isSensitiveBodyName(name) ? `"${name}"${sep18}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep18) => isSensitiveBodyName(name) ? `"${name}"${sep18}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
|
|
21338
21339
|
}
|
|
21339
21340
|
function createWixGatewayState() {
|
|
21340
21341
|
return { mode: "record", rules: [], traffic: [], clients: /* @__PURE__ */ new Set(), seq: 0, ruleSeq: 0 };
|
|
@@ -23080,10 +23081,10 @@ function recordDeviceLayout(payload) {
|
|
|
23080
23081
|
}
|
|
23081
23082
|
async function handleDeviceLayoutReport(res, payload) {
|
|
23082
23083
|
const screenId = recordDeviceLayout(payload);
|
|
23083
|
-
const
|
|
23084
|
-
res.statusCode =
|
|
23084
|
+
const ok2 = screenId !== null;
|
|
23085
|
+
res.statusCode = ok2 ? 200 : 400;
|
|
23085
23086
|
res.setHeader("content-type", "application/json");
|
|
23086
|
-
res.end(JSON.stringify(
|
|
23087
|
+
res.end(JSON.stringify(ok2 ? { status: "ok", screenId } : { error: "invalid_layout" }));
|
|
23087
23088
|
return screenId;
|
|
23088
23089
|
}
|
|
23089
23090
|
async function handlePreviewHitTest(res, payload) {
|
|
@@ -23162,12 +23163,12 @@ function finalizeRecording(key2, rec) {
|
|
|
23162
23163
|
if (rec.finalize) return rec.finalize;
|
|
23163
23164
|
rec.finalize = (async () => {
|
|
23164
23165
|
clearTimeout(rec.autoStop);
|
|
23165
|
-
await new Promise((
|
|
23166
|
+
await new Promise((resolve54) => {
|
|
23166
23167
|
let done = false;
|
|
23167
23168
|
const finish2 = () => {
|
|
23168
23169
|
if (!done) {
|
|
23169
23170
|
done = true;
|
|
23170
|
-
|
|
23171
|
+
resolve54();
|
|
23171
23172
|
}
|
|
23172
23173
|
};
|
|
23173
23174
|
rec.child.once("close", finish2);
|
|
@@ -23278,7 +23279,7 @@ var init_preview2 = __esm({
|
|
|
23278
23279
|
DEVICE_LIST_TIMEOUT_MS = 5e3;
|
|
23279
23280
|
defaultRunner2 = {
|
|
23280
23281
|
capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
|
|
23281
|
-
return new Promise((
|
|
23282
|
+
return new Promise((resolve54, reject) => {
|
|
23282
23283
|
const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
23283
23284
|
const out2 = [];
|
|
23284
23285
|
const err = [];
|
|
@@ -23300,7 +23301,7 @@ var init_preview2 = __esm({
|
|
|
23300
23301
|
child.stderr.on("data", (b) => err.push(b));
|
|
23301
23302
|
child.on("error", (e) => settle(reject, e));
|
|
23302
23303
|
child.on("close", (code) => {
|
|
23303
|
-
if (code === 0) settle(
|
|
23304
|
+
if (code === 0) settle(resolve54, Buffer.concat(out2));
|
|
23304
23305
|
else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
23305
23306
|
});
|
|
23306
23307
|
});
|
|
@@ -24632,13 +24633,13 @@ function validate(rule, rawValue) {
|
|
|
24632
24633
|
return { rule: "type", type: rule.type };
|
|
24633
24634
|
}
|
|
24634
24635
|
if (rule.regex) {
|
|
24635
|
-
let
|
|
24636
|
+
let ok2;
|
|
24636
24637
|
try {
|
|
24637
|
-
|
|
24638
|
+
ok2 = new RegExp(`^(?:${rule.regex})$`).test(value);
|
|
24638
24639
|
} catch {
|
|
24639
|
-
|
|
24640
|
+
ok2 = true;
|
|
24640
24641
|
}
|
|
24641
|
-
if (!
|
|
24642
|
+
if (!ok2) return { rule: "regex" };
|
|
24642
24643
|
}
|
|
24643
24644
|
if (typeof rule.minLength === "number" && rule.minLength > 0 && value.length < rule.minLength) {
|
|
24644
24645
|
return { rule: "minLength", limit: rule.minLength };
|
|
@@ -27553,12 +27554,12 @@ function createRicosHostSession(o) {
|
|
|
27553
27554
|
flush() {
|
|
27554
27555
|
if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
|
|
27555
27556
|
const requestId2 = newId();
|
|
27556
|
-
return new Promise((
|
|
27557
|
+
return new Promise((resolve54) => {
|
|
27557
27558
|
const timer = t.setTimeout(() => {
|
|
27558
27559
|
flushes.delete(requestId2);
|
|
27559
|
-
|
|
27560
|
+
resolve54(null);
|
|
27560
27561
|
}, flushMs);
|
|
27561
|
-
flushes.set(requestId2, { resolve:
|
|
27562
|
+
flushes.set(requestId2, { resolve: resolve54, timer });
|
|
27562
27563
|
o.send({ v: 1, type: "requestContent", requestId: requestId2 });
|
|
27563
27564
|
});
|
|
27564
27565
|
},
|
|
@@ -27611,7 +27612,7 @@ async function runRicosImageUpload(o) {
|
|
|
27611
27612
|
};
|
|
27612
27613
|
session.insertMediaPlaceholder(requestId2);
|
|
27613
27614
|
try {
|
|
27614
|
-
const entry = await new Promise((
|
|
27615
|
+
const entry = await new Promise((resolve54) => {
|
|
27615
27616
|
let done = false;
|
|
27616
27617
|
let unsub = () => {
|
|
27617
27618
|
};
|
|
@@ -27620,7 +27621,7 @@ async function runRicosImageUpload(o) {
|
|
|
27620
27621
|
done = true;
|
|
27621
27622
|
t.clearTimeout(timer);
|
|
27622
27623
|
queueMicrotask(() => unsub());
|
|
27623
|
-
|
|
27624
|
+
resolve54(v);
|
|
27624
27625
|
};
|
|
27625
27626
|
const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
|
|
27626
27627
|
unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
|
|
@@ -27639,10 +27640,10 @@ async function runRicosImageUpload(o) {
|
|
|
27639
27640
|
} catch {
|
|
27640
27641
|
return fail2("read");
|
|
27641
27642
|
}
|
|
27642
|
-
const
|
|
27643
|
+
const sep18 = entry.uploadUrl.includes("?") ? "&" : "?";
|
|
27643
27644
|
let res;
|
|
27644
27645
|
try {
|
|
27645
|
-
res = await deps.fetch(`${entry.uploadUrl}${
|
|
27646
|
+
res = await deps.fetch(`${entry.uploadUrl}${sep18}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
|
|
27646
27647
|
} catch {
|
|
27647
27648
|
return fail2("put");
|
|
27648
27649
|
}
|
|
@@ -27657,14 +27658,14 @@ async function runRicosImageUpload(o) {
|
|
|
27657
27658
|
const d = root.file && typeof root.file === "object" ? root.file : root;
|
|
27658
27659
|
const id = typeof d.id === "string" ? d.id : "";
|
|
27659
27660
|
if (!id) return fail2("bad_descriptor");
|
|
27660
|
-
const
|
|
27661
|
+
const ok2 = session.resolveMedia(requestId2, {
|
|
27661
27662
|
id,
|
|
27662
27663
|
url: typeof d.url === "string" ? d.url : "",
|
|
27663
27664
|
...typeof d.width === "number" ? { width: d.width } : {},
|
|
27664
27665
|
...typeof d.height === "number" ? { height: d.height } : {},
|
|
27665
27666
|
mimeType: file.mimeType
|
|
27666
27667
|
});
|
|
27667
|
-
return
|
|
27668
|
+
return ok2 ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
|
|
27668
27669
|
} finally {
|
|
27669
27670
|
deps.dispatch({ actionId: `tier5.${svc}.clearUpload`, args: { requestId: requestId2 } });
|
|
27670
27671
|
}
|
|
@@ -29552,8 +29553,8 @@ function ensureCountUpRuntime() {
|
|
|
29552
29553
|
const neg = fixed.startsWith("-");
|
|
29553
29554
|
const body = neg ? fixed.slice(1) : fixed;
|
|
29554
29555
|
const [int2, frac] = body.split(".");
|
|
29555
|
-
const
|
|
29556
|
-
return (neg ? "-" : "") +
|
|
29556
|
+
const sep18 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
29557
|
+
return (neg ? "-" : "") + sep18 + (frac ? "." + frac : "");
|
|
29557
29558
|
};
|
|
29558
29559
|
const animateEl = (el) => {
|
|
29559
29560
|
const node = el;
|
|
@@ -30374,24 +30375,24 @@ function usesSchematicRoute(props) {
|
|
|
30374
30375
|
const hasRouteFeed = typeof props.routePath === "string" && props.routePath !== "";
|
|
30375
30376
|
return hasFeed && !hasRoute && !hasRouteFeed;
|
|
30376
30377
|
}
|
|
30377
|
-
function longitudeAt(x,
|
|
30378
|
-
return x / (TILE_PX * Math.pow(2,
|
|
30378
|
+
function longitudeAt(x, z3) {
|
|
30379
|
+
return x / (TILE_PX * Math.pow(2, z3)) * 360 - 180;
|
|
30379
30380
|
}
|
|
30380
|
-
function latitudeAt(y,
|
|
30381
|
-
const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2,
|
|
30381
|
+
function latitudeAt(y, z3) {
|
|
30382
|
+
const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z3));
|
|
30382
30383
|
return 180 / Math.PI * Math.atan(Math.sinh(n));
|
|
30383
30384
|
}
|
|
30384
|
-
function regionArgs(centerLat, centerLng,
|
|
30385
|
-
const cx = mercatorX(centerLng,
|
|
30386
|
-
const cy = mercatorY(centerLat,
|
|
30385
|
+
function regionArgs(centerLat, centerLng, z3, w, h) {
|
|
30386
|
+
const cx = mercatorX(centerLng, z3);
|
|
30387
|
+
const cy = mercatorY(centerLat, z3);
|
|
30387
30388
|
return {
|
|
30388
30389
|
latitude: centerLat,
|
|
30389
30390
|
longitude: centerLng,
|
|
30390
|
-
zoom:
|
|
30391
|
-
north: latitudeAt(cy - h / 2,
|
|
30392
|
-
south: latitudeAt(cy + h / 2,
|
|
30393
|
-
east: longitudeAt(cx + w / 2,
|
|
30394
|
-
west: longitudeAt(cx - w / 2,
|
|
30391
|
+
zoom: z3,
|
|
30392
|
+
north: latitudeAt(cy - h / 2, z3),
|
|
30393
|
+
south: latitudeAt(cy + h / 2, z3),
|
|
30394
|
+
east: longitudeAt(cx + w / 2, z3),
|
|
30395
|
+
west: longitudeAt(cx - w / 2, z3)
|
|
30395
30396
|
};
|
|
30396
30397
|
}
|
|
30397
30398
|
function decodeCamera(v) {
|
|
@@ -30421,9 +30422,9 @@ function resolveTileSource(source) {
|
|
|
30421
30422
|
const maxZoom = typeof s.maxZoom === "number" && s.maxZoom > 0 ? s.maxZoom : DEFAULT_TILE_MAX_ZOOM;
|
|
30422
30423
|
return { urlTemplate, attribution, maxZoom };
|
|
30423
30424
|
}
|
|
30424
|
-
function tileUrl(source,
|
|
30425
|
-
if (!source) return `https://tile.openstreetmap.org/${
|
|
30426
|
-
return source.urlTemplate.replace("{z}", String(
|
|
30425
|
+
function tileUrl(source, z3, x, y) {
|
|
30426
|
+
if (!source) return `https://tile.openstreetmap.org/${z3}/${x}/${y}.png`;
|
|
30427
|
+
return source.urlTemplate.replace("{z}", String(z3)).replace("{x}", String(x)).replace("{y}", String(y));
|
|
30427
30428
|
}
|
|
30428
30429
|
function parseShapeKind(raw) {
|
|
30429
30430
|
const k = typeof raw === "string" ? raw.toLowerCase() : "";
|
|
@@ -30440,12 +30441,12 @@ function circleRing(centreLat, centreLng, radiusM, segments = CIRCLE_SEGMENTS) {
|
|
|
30440
30441
|
return { latitude: centreLat + dLat * Math.sin(theta), longitude: centreLng + dLng * Math.cos(theta) };
|
|
30441
30442
|
});
|
|
30442
30443
|
}
|
|
30443
|
-
function distanceToPolylinePx(px, py, points,
|
|
30444
|
+
function distanceToPolylinePx(px, py, points, z3, originX, originY) {
|
|
30444
30445
|
if (points.length < 2) return null;
|
|
30445
30446
|
let best = Infinity;
|
|
30446
30447
|
for (let i = 0; i < points.length - 1; i++) {
|
|
30447
|
-
const ax = mercatorX(points[i].longitude,
|
|
30448
|
-
const bx = mercatorX(points[i + 1].longitude,
|
|
30448
|
+
const ax = mercatorX(points[i].longitude, z3) - originX, ay = mercatorY(points[i].latitude, z3) - originY;
|
|
30449
|
+
const bx = mercatorX(points[i + 1].longitude, z3) - originX, by = mercatorY(points[i + 1].latitude, z3) - originY;
|
|
30449
30450
|
const dx = bx - ax, dy = by - ay;
|
|
30450
30451
|
const lenSq = dx * dx + dy * dy;
|
|
30451
30452
|
const t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
|
|
@@ -30455,22 +30456,22 @@ function distanceToPolylinePx(px, py, points, z2, originX, originY) {
|
|
|
30455
30456
|
}
|
|
30456
30457
|
return best;
|
|
30457
30458
|
}
|
|
30458
|
-
function polygonContainsPx(px, py, points,
|
|
30459
|
+
function polygonContainsPx(px, py, points, z3, originX, originY) {
|
|
30459
30460
|
if (points.length < 3) return false;
|
|
30460
30461
|
let inside2 = false;
|
|
30461
30462
|
for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
|
|
30462
|
-
const xi = mercatorX(points[i].longitude,
|
|
30463
|
-
const xj = mercatorX(points[j].longitude,
|
|
30463
|
+
const xi = mercatorX(points[i].longitude, z3) - originX, yi = mercatorY(points[i].latitude, z3) - originY;
|
|
30464
|
+
const xj = mercatorX(points[j].longitude, z3) - originX, yj = mercatorY(points[j].latitude, z3) - originY;
|
|
30464
30465
|
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) inside2 = !inside2;
|
|
30465
30466
|
}
|
|
30466
30467
|
return inside2;
|
|
30467
30468
|
}
|
|
30468
|
-
function markerHit(px, py, markers,
|
|
30469
|
+
function markerHit(px, py, markers, z3, originX, originY) {
|
|
30469
30470
|
let best = null;
|
|
30470
30471
|
let bestDistance = MARKER_HIT_RADIUS;
|
|
30471
30472
|
markers.forEach((m, i) => {
|
|
30472
|
-
const dx = mercatorX(m.longitude,
|
|
30473
|
-
const dy = mercatorY(m.latitude,
|
|
30473
|
+
const dx = mercatorX(m.longitude, z3) - originX - px;
|
|
30474
|
+
const dy = mercatorY(m.latitude, z3) - originY - py;
|
|
30474
30475
|
const d = Math.sqrt(dx * dx + dy * dy);
|
|
30475
30476
|
if (d <= bestDistance) {
|
|
30476
30477
|
bestDistance = d;
|
|
@@ -30479,22 +30480,22 @@ function markerHit(px, py, markers, z2, originX, originY) {
|
|
|
30479
30480
|
});
|
|
30480
30481
|
return best;
|
|
30481
30482
|
}
|
|
30482
|
-
function mercatorX(lng,
|
|
30483
|
-
return (lng + 180) / 360 * TILE_PX * Math.pow(2,
|
|
30483
|
+
function mercatorX(lng, z3) {
|
|
30484
|
+
return (lng + 180) / 360 * TILE_PX * Math.pow(2, z3);
|
|
30484
30485
|
}
|
|
30485
|
-
function mercatorY(lat,
|
|
30486
|
+
function mercatorY(lat, z3) {
|
|
30486
30487
|
const s = Math.max(-85.05112878, Math.min(85.05112878, lat)) * Math.PI / 180;
|
|
30487
|
-
return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2,
|
|
30488
|
+
return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z3);
|
|
30488
30489
|
}
|
|
30489
30490
|
function fitZoom(pts, w, h, fallback) {
|
|
30490
30491
|
if (pts.length < 2 || w <= 0 || h <= 0) return fallback;
|
|
30491
30492
|
const lats = pts.map((p) => p.latitude), lngs = pts.map((p) => p.longitude);
|
|
30492
30493
|
const minLa = Math.min(...lats), maxLa = Math.max(...lats);
|
|
30493
30494
|
const minLo = Math.min(...lngs), maxLo = Math.max(...lngs);
|
|
30494
|
-
for (let
|
|
30495
|
-
const dx = Math.abs(mercatorX(maxLo,
|
|
30496
|
-
const dy = Math.abs(mercatorY(maxLa,
|
|
30497
|
-
if (dx <= w && dy <= h) return
|
|
30495
|
+
for (let z3 = 19; z3 >= 1; z3--) {
|
|
30496
|
+
const dx = Math.abs(mercatorX(maxLo, z3) - mercatorX(minLo, z3));
|
|
30497
|
+
const dy = Math.abs(mercatorY(maxLa, z3) - mercatorY(minLa, z3));
|
|
30498
|
+
if (dx <= w && dy <= h) return z3;
|
|
30498
30499
|
}
|
|
30499
30500
|
return 1;
|
|
30500
30501
|
}
|
|
@@ -34613,20 +34614,20 @@ var init_renderNode = __esm({
|
|
|
34613
34614
|
const fitted = shouldFit ? fitZoom(all, W - 48, H - 48, declared) : declared;
|
|
34614
34615
|
const baseLat = all.length && shouldFit ? (Math.min(...all.map((p) => p.latitude)) + Math.max(...all.map((p) => p.latitude))) / 2 : typeof props.latitude === "number" ? props.latitude : 37.7749;
|
|
34615
34616
|
const baseLng = all.length && shouldFit ? (Math.min(...all.map((p) => p.longitude)) + Math.max(...all.map((p) => p.longitude))) / 2 : typeof props.longitude === "number" ? props.longitude : -122.4194;
|
|
34616
|
-
const
|
|
34617
|
+
const z3 = userCam?.z ?? fitted;
|
|
34617
34618
|
const cLat = userCam?.lat ?? baseLat;
|
|
34618
34619
|
const cLng = userCam?.lng ?? baseLng;
|
|
34619
34620
|
React7.useEffect(() => {
|
|
34620
|
-
const resolved2 = resolveCamera(commandedCamera, cLat, cLng,
|
|
34621
|
+
const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z3);
|
|
34621
34622
|
if (!resolved2) return;
|
|
34622
34623
|
setUserCam({
|
|
34623
34624
|
lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
|
|
34624
34625
|
lng: resolved2.longitude,
|
|
34625
|
-
z: Math.max(1, Math.min(19, resolved2.zoom ??
|
|
34626
|
+
z: Math.max(1, Math.min(19, resolved2.zoom ?? z3))
|
|
34626
34627
|
});
|
|
34627
34628
|
}, [commandedCamera]);
|
|
34628
|
-
const originX = mercatorX(cLng,
|
|
34629
|
-
const originY = mercatorY(cLat,
|
|
34629
|
+
const originX = mercatorX(cLng, z3) - W / 2;
|
|
34630
|
+
const originY = mercatorY(cLat, z3) - H / 2;
|
|
34630
34631
|
const interactive = pinsOnly ? props.interactive === true : props.interactive !== false;
|
|
34631
34632
|
const resolvedTileSource = resolveTileSource(props.tileSource);
|
|
34632
34633
|
const fireMapEvent = (action, payload) => {
|
|
@@ -34644,7 +34645,7 @@ var init_renderNode = __esm({
|
|
|
34644
34645
|
const { kx, ky } = layoutScale(el);
|
|
34645
34646
|
const px = (e.clientX - r.left) * kx - el.clientLeft;
|
|
34646
34647
|
const py = (e.clientY - r.top) * ky - el.clientTop;
|
|
34647
|
-
const hit = markerHit(px, py, markers,
|
|
34648
|
+
const hit = markerHit(px, py, markers, z3, originX, originY);
|
|
34648
34649
|
if (hit !== null) {
|
|
34649
34650
|
const m = markers[hit];
|
|
34650
34651
|
const payload = { index: hit, latitude: m.latitude, longitude: m.longitude };
|
|
@@ -34655,10 +34656,10 @@ var init_renderNode = __esm({
|
|
|
34655
34656
|
const shapeIndex = shapes.findIndex((sh) => {
|
|
34656
34657
|
if (sh.kind === "unknown" || sh.points.length < 2) return false;
|
|
34657
34658
|
if (sh.kind === "line") {
|
|
34658
|
-
const d2 = distanceToPolylinePx(px, py, sh.points,
|
|
34659
|
+
const d2 = distanceToPolylinePx(px, py, sh.points, z3, originX, originY);
|
|
34659
34660
|
return d2 !== null && d2 <= SHAPE_HIT_RADIUS;
|
|
34660
34661
|
}
|
|
34661
|
-
return polygonContainsPx(px, py, sh.points,
|
|
34662
|
+
return polygonContainsPx(px, py, sh.points, z3, originX, originY);
|
|
34662
34663
|
});
|
|
34663
34664
|
if (shapeIndex >= 0 && props.onShapeTap) {
|
|
34664
34665
|
const sh = shapes[shapeIndex];
|
|
@@ -34667,15 +34668,15 @@ var init_renderNode = __esm({
|
|
|
34667
34668
|
fireMapEvent(props.onShapeTap, payload);
|
|
34668
34669
|
} else {
|
|
34669
34670
|
fireMapEvent(props.onMapTap, {
|
|
34670
|
-
latitude: latitudeAt(originY + py,
|
|
34671
|
-
longitude: longitudeAt(originX + px,
|
|
34671
|
+
latitude: latitudeAt(originY + py, z3),
|
|
34672
|
+
longitude: longitudeAt(originX + px, z3)
|
|
34672
34673
|
});
|
|
34673
34674
|
}
|
|
34674
34675
|
}
|
|
34675
34676
|
};
|
|
34676
34677
|
const onPointerDown = (e) => {
|
|
34677
34678
|
if (!interactive) return;
|
|
34678
|
-
dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z:
|
|
34679
|
+
dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z3, ...layoutScale(e.currentTarget) };
|
|
34679
34680
|
dragMovedRef.current = false;
|
|
34680
34681
|
};
|
|
34681
34682
|
const onPointerMove = (e) => {
|
|
@@ -34699,8 +34700,8 @@ var init_renderNode = __esm({
|
|
|
34699
34700
|
const onWheel = (e) => {
|
|
34700
34701
|
if (!interactive) return;
|
|
34701
34702
|
e.preventDefault();
|
|
34702
|
-
const next = Math.max(1, Math.min(19,
|
|
34703
|
-
if (next !==
|
|
34703
|
+
const next = Math.max(1, Math.min(19, z3 + (e.deltaY < 0 ? 1 : -1)));
|
|
34704
|
+
if (next !== z3) setUserCam({ lat: cLat, lng: cLng, z: next });
|
|
34704
34705
|
};
|
|
34705
34706
|
React7.useEffect(() => {
|
|
34706
34707
|
const action = props.onRegionChange;
|
|
@@ -34711,22 +34712,22 @@ var init_renderNode = __esm({
|
|
|
34711
34712
|
regionReportedRef.current = true;
|
|
34712
34713
|
return;
|
|
34713
34714
|
}
|
|
34714
|
-
fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng,
|
|
34715
|
+
fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z3, W, H) } });
|
|
34715
34716
|
}, 250);
|
|
34716
34717
|
return () => clearTimeout(t);
|
|
34717
|
-
}, [cLat, cLng,
|
|
34718
|
-
const sx = (p) => mercatorX(p.longitude,
|
|
34719
|
-
const sy = (p) => mercatorY(p.latitude,
|
|
34718
|
+
}, [cLat, cLng, z3, W, H, props.onRegionChange]);
|
|
34719
|
+
const sx = (p) => mercatorX(p.longitude, z3) - originX;
|
|
34720
|
+
const sy = (p) => mercatorY(p.latitude, z3) - originY;
|
|
34720
34721
|
const accent = C("accentPrimary", "#116DFF");
|
|
34721
|
-
const n = Math.pow(2,
|
|
34722
|
+
const n = Math.pow(2, z3);
|
|
34722
34723
|
const tiles = [];
|
|
34723
34724
|
for (let tx = Math.floor(originX / TILE_PX); tx <= Math.floor((originX + W) / TILE_PX); tx++) {
|
|
34724
34725
|
for (let ty = Math.floor(originY / TILE_PX); ty <= Math.floor((originY + H) / TILE_PX); ty++) {
|
|
34725
34726
|
if (ty < 0 || ty >= n) continue;
|
|
34726
34727
|
const wrapX = (tx % n + n) % n;
|
|
34727
34728
|
tiles.push({
|
|
34728
|
-
key: `${
|
|
34729
|
-
src: tileUrl(resolvedTileSource,
|
|
34729
|
+
key: `${z3}/${wrapX}/${ty}`,
|
|
34730
|
+
src: tileUrl(resolvedTileSource, z3, wrapX, ty),
|
|
34730
34731
|
left: tx * TILE_PX - originX,
|
|
34731
34732
|
top: ty * TILE_PX - originY
|
|
34732
34733
|
});
|
|
@@ -34738,7 +34739,7 @@ var init_renderNode = __esm({
|
|
|
34738
34739
|
ref: attachBox,
|
|
34739
34740
|
"data-map-mode": "tile",
|
|
34740
34741
|
"data-route-points": route.length,
|
|
34741
|
-
"data-map-zoom":
|
|
34742
|
+
"data-map-zoom": z3,
|
|
34742
34743
|
onClick: onSurfaceClick,
|
|
34743
34744
|
onPointerDown,
|
|
34744
34745
|
onPointerMove,
|
|
@@ -35904,7 +35905,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
35904
35905
|
const browser = globalThis;
|
|
35905
35906
|
browser.document.documentElement.style.colorScheme = selected;
|
|
35906
35907
|
await browser.document.fonts?.ready;
|
|
35907
|
-
await new Promise((
|
|
35908
|
+
await new Promise((resolve54) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve54())));
|
|
35908
35909
|
}, scheme);
|
|
35909
35910
|
}
|
|
35910
35911
|
async function renderPngBatch(items) {
|
|
@@ -39545,7 +39546,7 @@ async function handleWebWix(req, res, state) {
|
|
|
39545
39546
|
}
|
|
39546
39547
|
if (match) {
|
|
39547
39548
|
const mocked = match.rule.response;
|
|
39548
|
-
if (mocked.delayMs) await new Promise((
|
|
39549
|
+
if (mocked.delayMs) await new Promise((resolve54) => setTimeout(resolve54, mocked.delayMs));
|
|
39549
39550
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
39550
39551
|
record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
|
|
39551
39552
|
return reply(200, { status: mocked.status, body: responseBody ?? "" });
|
|
@@ -40539,8 +40540,8 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
40539
40540
|
}
|
|
40540
40541
|
async function serveStatic(req, res, root, prefix) {
|
|
40541
40542
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
40542
|
-
const
|
|
40543
|
-
const safe = normalize3(
|
|
40543
|
+
const relative15 = requested.replace(prefix, "").replace(/^\//, "");
|
|
40544
|
+
const safe = normalize3(relative15).replace(/^(\.\.[\/\\])+/, "");
|
|
40544
40545
|
const fullPath = resolve33(root, safe);
|
|
40545
40546
|
if (!fullPath.startsWith(root)) {
|
|
40546
40547
|
return send(res, 403, "forbidden");
|
|
@@ -41271,8 +41272,8 @@ function sha256hex(b) {
|
|
|
41271
41272
|
function stableStringify(value) {
|
|
41272
41273
|
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
41273
41274
|
if (Array.isArray(value)) return "[" + value.map(stableStringify).join(",") + "]";
|
|
41274
|
-
const
|
|
41275
|
-
return "{" + Object.keys(
|
|
41275
|
+
const object3 = value;
|
|
41276
|
+
return "{" + Object.keys(object3).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object3[key2])).join(",") + "}";
|
|
41276
41277
|
}
|
|
41277
41278
|
function manifestContent(m) {
|
|
41278
41279
|
const {
|
|
@@ -41644,12 +41645,12 @@ var init_query = __esm({
|
|
|
41644
41645
|
});
|
|
41645
41646
|
|
|
41646
41647
|
// ../../core/dev-server/src/crawl-input.ts
|
|
41647
|
-
function resolved(v,
|
|
41648
|
-
if (typeof v === "string") return v.startsWith("$service:") ?
|
|
41648
|
+
function resolved(v, resolve54) {
|
|
41649
|
+
if (typeof v === "string") return v.startsWith("$service:") ? resolve54(v) : v;
|
|
41649
41650
|
if (Array.isArray(v)) {
|
|
41650
41651
|
const out2 = v.flatMap((el) => {
|
|
41651
41652
|
if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
|
|
41652
|
-
const r =
|
|
41653
|
+
const r = resolve54(el);
|
|
41653
41654
|
return Array.isArray(r) ? r : [r];
|
|
41654
41655
|
});
|
|
41655
41656
|
return out2;
|
|
@@ -41663,9 +41664,9 @@ function hasRowBinding(props) {
|
|
|
41663
41664
|
return itemToken(v) || Array.isArray(v) && v.some(itemToken);
|
|
41664
41665
|
});
|
|
41665
41666
|
}
|
|
41666
|
-
function declaredOptionIds(props,
|
|
41667
|
+
function declaredOptionIds(props, resolve54) {
|
|
41667
41668
|
const literal = props.options ?? props.tabs ?? props.chips;
|
|
41668
|
-
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath,
|
|
41669
|
+
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve54) : void 0;
|
|
41669
41670
|
const raw = Array.isArray(bound) ? bound : literal;
|
|
41670
41671
|
if (!Array.isArray(raw)) return [];
|
|
41671
41672
|
const out2 = [];
|
|
@@ -41708,24 +41709,24 @@ function seedTokens(state, limit = 48) {
|
|
|
41708
41709
|
walk2(state, 0);
|
|
41709
41710
|
return out2;
|
|
41710
41711
|
}
|
|
41711
|
-
function synthesizeInput(control,
|
|
41712
|
+
function synthesizeInput(control, resolve54, tokens) {
|
|
41712
41713
|
const id = `${control.type}.${control.callback}`;
|
|
41713
41714
|
const row = SYNTHESIZED_CONTROLS[id];
|
|
41714
41715
|
if (!row) return null;
|
|
41715
41716
|
const props = control.props;
|
|
41716
41717
|
if (hasRowBinding(props)) return null;
|
|
41717
41718
|
if (row.from === "declared-options") {
|
|
41718
|
-
const ids = declaredOptionIds(props,
|
|
41719
|
+
const ids = declaredOptionIds(props, resolve54);
|
|
41719
41720
|
if (!ids.length) return null;
|
|
41720
41721
|
if (row.encoding === "string-array") {
|
|
41721
|
-
const currentRaw2 = resolved(props.selectedIds,
|
|
41722
|
+
const currentRaw2 = resolved(props.selectedIds, resolve54);
|
|
41722
41723
|
const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
|
|
41723
41724
|
const pick4 = ids.find((o) => !current3.includes(o));
|
|
41724
41725
|
if (pick4 === void 0) return null;
|
|
41725
41726
|
const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
|
|
41726
41727
|
return { key: row.key, value, from: row.from, current: current3, control: id };
|
|
41727
41728
|
}
|
|
41728
|
-
const currentRaw = resolved(props.selectedId,
|
|
41729
|
+
const currentRaw = resolved(props.selectedId, resolve54);
|
|
41729
41730
|
const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
|
|
41730
41731
|
const pick3 = ids.find((o) => o !== current2);
|
|
41731
41732
|
if (pick3 === void 0) return null;
|
|
@@ -41733,7 +41734,7 @@ function synthesizeInput(control, resolve53, tokens) {
|
|
|
41733
41734
|
}
|
|
41734
41735
|
if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
|
|
41735
41736
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
|
|
41736
|
-
const bound = binding2 === void 0 ? void 0 :
|
|
41737
|
+
const bound = binding2 === void 0 ? void 0 : resolve54(binding2);
|
|
41737
41738
|
const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
|
|
41738
41739
|
const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
|
|
41739
41740
|
const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
|
|
@@ -43218,8 +43219,8 @@ async function crawlScreenInner(opts) {
|
|
|
43218
43219
|
if (linkable.has(target)) return true;
|
|
43219
43220
|
for (const base of linkable) {
|
|
43220
43221
|
if (target.length > base.length + 1 && target.startsWith(base)) {
|
|
43221
|
-
const
|
|
43222
|
-
if (
|
|
43222
|
+
const sep18 = target[base.length];
|
|
43223
|
+
if (sep18 === "_" || sep18 === "/") return true;
|
|
43223
43224
|
}
|
|
43224
43225
|
}
|
|
43225
43226
|
return false;
|
|
@@ -46246,7 +46247,7 @@ var init_studio_timeline = __esm({
|
|
|
46246
46247
|
isStr = (x) => typeof x === "string";
|
|
46247
46248
|
isObj2 = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
|
|
46248
46249
|
strs = (x) => Array.isArray(x) && x.every(isStr);
|
|
46249
|
-
nullOr = (x,
|
|
46250
|
+
nullOr = (x, ok2) => x === null || isObj2(x) && ok2(x);
|
|
46250
46251
|
accentOf = (palette2) => {
|
|
46251
46252
|
for (const p of palette2 ?? []) {
|
|
46252
46253
|
const [name, hex2] = Array.isArray(p) ? p : [p.name, p.hex];
|
|
@@ -47196,16 +47197,16 @@ function pushSetupBodyBytes(body) {
|
|
|
47196
47197
|
return Buffer.byteLength(JSON.stringify(body), "utf8");
|
|
47197
47198
|
}
|
|
47198
47199
|
async function pushSetupRequest(options) {
|
|
47199
|
-
const
|
|
47200
|
-
if (!options.target.controlToken) return
|
|
47201
|
-
if (!options.wixToken) return
|
|
47202
|
-
if (credentialHostRefusal(options.target.control)) return
|
|
47203
|
-
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return
|
|
47200
|
+
const refuse6 = (error) => ({ ok: false, status: 0, body: null, error });
|
|
47201
|
+
if (!options.target.controlToken) return refuse6("control_token_required");
|
|
47202
|
+
if (!options.wixToken) return refuse6("wix_account_token_required");
|
|
47203
|
+
if (credentialHostRefusal(options.target.control)) return refuse6("insecure_target");
|
|
47204
|
+
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse6("invalid_preview_tag");
|
|
47204
47205
|
const setup = options.operation === "setup";
|
|
47205
|
-
if (setup && !options.body) return
|
|
47206
|
-
if (!setup && (!options.query?.app || !options.query?.site)) return
|
|
47206
|
+
if (setup && !options.body) return refuse6("push_setup_body_required");
|
|
47207
|
+
if (!setup && (!options.query?.app || !options.query?.site)) return refuse6("push_setup_query_required");
|
|
47207
47208
|
if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
|
|
47208
|
-
return
|
|
47209
|
+
return refuse6("push_setup_body_too_large");
|
|
47209
47210
|
}
|
|
47210
47211
|
const base = options.target.control.replace(/\/+$/, "");
|
|
47211
47212
|
let path2 = "/v1/admin/push/setup";
|
|
@@ -51023,8 +51024,8 @@ function baseOf(target, linkable, known) {
|
|
|
51023
51024
|
let best = null;
|
|
51024
51025
|
for (const base of linkable ?? []) {
|
|
51025
51026
|
if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
|
|
51026
|
-
const
|
|
51027
|
-
if ((
|
|
51027
|
+
const sep18 = target[base.length];
|
|
51028
|
+
if ((sep18 === "_" || sep18 === "/") && (!best || base.length > best.length)) best = base;
|
|
51028
51029
|
}
|
|
51029
51030
|
return best;
|
|
51030
51031
|
}
|
|
@@ -52265,7 +52266,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
52265
52266
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
52266
52267
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
52267
52268
|
const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
|
|
52268
|
-
return await new Promise((
|
|
52269
|
+
return await new Promise((resolve54, reject) => {
|
|
52269
52270
|
let settled = false;
|
|
52270
52271
|
const finish2 = (fn) => {
|
|
52271
52272
|
if (settled) return;
|
|
@@ -52302,7 +52303,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
52302
52303
|
}
|
|
52303
52304
|
const responseHeaders = new Headers();
|
|
52304
52305
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
52305
|
-
|
|
52306
|
+
resolve54(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
52306
52307
|
}));
|
|
52307
52308
|
});
|
|
52308
52309
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -52602,7 +52603,7 @@ function createLocalTestSandbox() {
|
|
|
52602
52603
|
}
|
|
52603
52604
|
})();
|
|
52604
52605
|
`;
|
|
52605
|
-
return await new Promise((
|
|
52606
|
+
return await new Promise((resolve54, reject) => {
|
|
52606
52607
|
const { port1, port2 } = new MessageChannel();
|
|
52607
52608
|
const serializableContext = {
|
|
52608
52609
|
auth: context.auth,
|
|
@@ -52678,7 +52679,7 @@ function createLocalTestSandbox() {
|
|
|
52678
52679
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
52679
52680
|
return;
|
|
52680
52681
|
}
|
|
52681
|
-
if (message.ok) finish2(() =>
|
|
52682
|
+
if (message.ok) finish2(() => resolve54({ value: message.value, durationMs: Date.now() - started }));
|
|
52682
52683
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
52683
52684
|
});
|
|
52684
52685
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -53855,9 +53856,187 @@ var init_cli_bridge = __esm({
|
|
|
53855
53856
|
}
|
|
53856
53857
|
});
|
|
53857
53858
|
|
|
53858
|
-
// src/mcp/tools.ts
|
|
53859
|
+
// src/mcp/file-tools.ts
|
|
53860
|
+
import { lstatSync as lstatSync12, mkdirSync as mkdirSync26, readdirSync as readdirSync27, readFileSync as readFileSync59, realpathSync as realpathSync7, rmSync as rmSync12, statSync as statSync13, writeFileSync as writeFileSync21, existsSync as existsSync54 } from "node:fs";
|
|
53861
|
+
import { dirname as dirname30, isAbsolute as isAbsolute5, join as join53, relative as relative11, resolve as resolve45, sep as sep14 } from "node:path";
|
|
53859
53862
|
import * as z from "zod";
|
|
53860
|
-
|
|
53863
|
+
function within(root, p) {
|
|
53864
|
+
return p === root || p.startsWith(root.endsWith(sep14) ? root : root + sep14);
|
|
53865
|
+
}
|
|
53866
|
+
function realish(p) {
|
|
53867
|
+
let cur = p;
|
|
53868
|
+
const tail = [];
|
|
53869
|
+
while (!existsSync54(cur)) {
|
|
53870
|
+
const up = dirname30(cur);
|
|
53871
|
+
if (up === cur) break;
|
|
53872
|
+
tail.unshift(cur.slice(up.length + (up.endsWith(sep14) ? 0 : 1)));
|
|
53873
|
+
cur = up;
|
|
53874
|
+
}
|
|
53875
|
+
return join53(realpathSync7(cur), ...tail);
|
|
53876
|
+
}
|
|
53877
|
+
async function confinedAppDir(args, deps) {
|
|
53878
|
+
const root = resolve45(await deps.defaultDir());
|
|
53879
|
+
const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
|
|
53880
|
+
if (!existsSync54(root)) return refuse4("no_workspace", `the workspace folder ${root} does not exist`);
|
|
53881
|
+
if (!within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
|
|
53882
|
+
return dir;
|
|
53883
|
+
}
|
|
53884
|
+
function confinedPath(appDir3, rel) {
|
|
53885
|
+
if (typeof rel !== "string" || !rel.trim()) return { error: "a path is required" };
|
|
53886
|
+
if (rel.includes("\0")) return { error: "a path may not contain NUL" };
|
|
53887
|
+
if (isAbsolute5(rel)) return { error: `"${rel}" is absolute \u2014 give a path inside the app folder` };
|
|
53888
|
+
const abs = resolve45(appDir3, rel);
|
|
53889
|
+
const real = realish(abs);
|
|
53890
|
+
const base = existsSync54(appDir3) ? realpathSync7(appDir3) : realish(appDir3);
|
|
53891
|
+
if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
|
|
53892
|
+
const first = relative11(base, real).split(sep14)[0];
|
|
53893
|
+
if (RESERVED.has(first)) return { error: `"${rel}" is inside ${first}/, which this tool does not touch` };
|
|
53894
|
+
return abs;
|
|
53895
|
+
}
|
|
53896
|
+
function listFiles(appDir3) {
|
|
53897
|
+
const files = [];
|
|
53898
|
+
const walk2 = (d) => {
|
|
53899
|
+
for (const e of readdirSync27(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
53900
|
+
if (RESERVED.has(e.name)) continue;
|
|
53901
|
+
if (e.isSymbolicLink()) continue;
|
|
53902
|
+
const p = join53(d, e.name);
|
|
53903
|
+
if (e.isDirectory()) {
|
|
53904
|
+
if (!walk2(p)) return false;
|
|
53905
|
+
} else if (e.isFile()) {
|
|
53906
|
+
if (files.length >= MAX_LISTED) return false;
|
|
53907
|
+
files.push({ path: relative11(appDir3, p).split(sep14).join("/"), bytes: statSync13(p).size });
|
|
53908
|
+
}
|
|
53909
|
+
}
|
|
53910
|
+
return true;
|
|
53911
|
+
};
|
|
53912
|
+
const complete = walk2(appDir3);
|
|
53913
|
+
return { files, truncated: !complete };
|
|
53914
|
+
}
|
|
53915
|
+
function fileTools() {
|
|
53916
|
+
return [
|
|
53917
|
+
{
|
|
53918
|
+
name: "himi_list_apps",
|
|
53919
|
+
title: "List apps in the workspace",
|
|
53920
|
+
description: "The apps (content packages) in the workspace folder: the folder itself if it is one, and each sub-folder that is. Pass an app's `dir` to the other tools.",
|
|
53921
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53922
|
+
inputSchema: z.object({}),
|
|
53923
|
+
handler: async (_a, d) => {
|
|
53924
|
+
const root = resolve45(await d.defaultDir());
|
|
53925
|
+
if (!existsSync54(root)) return ok({ ok: true, workspace: root, apps: [] });
|
|
53926
|
+
const apps = [];
|
|
53927
|
+
if (existsSync54(join53(root, CONTENT_MARKER))) apps.push(".");
|
|
53928
|
+
for (const e of readdirSync27(root, { withFileTypes: true })) {
|
|
53929
|
+
if (e.isDirectory() && !e.name.startsWith(".") && existsSync54(join53(root, e.name, CONTENT_MARKER))) apps.push(e.name);
|
|
53930
|
+
}
|
|
53931
|
+
return ok({ ok: true, workspace: root, apps: apps.sort() });
|
|
53932
|
+
}
|
|
53933
|
+
},
|
|
53934
|
+
{
|
|
53935
|
+
name: "himi_list_files",
|
|
53936
|
+
title: "List app files",
|
|
53937
|
+
description: `Every file in an app folder with its size (skips ${[...RESERVED].join(", ")}; at most ${MAX_LISTED}).`,
|
|
53938
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53939
|
+
inputSchema: z.object({ dir: DIR }),
|
|
53940
|
+
handler: async (a, d) => {
|
|
53941
|
+
const app = await confinedAppDir(a, d);
|
|
53942
|
+
if (typeof app !== "string") return app;
|
|
53943
|
+
if (!existsSync54(app) || !statSync13(app).isDirectory()) return refuse4("no_app", `no folder at ${app}`);
|
|
53944
|
+
return ok({ ok: true, dir: app, ...listFiles(app) });
|
|
53945
|
+
}
|
|
53946
|
+
},
|
|
53947
|
+
{
|
|
53948
|
+
name: "himi_read_file",
|
|
53949
|
+
title: "Read an app file",
|
|
53950
|
+
description: `One file of an app folder, as UTF-8 text (at most ${MAX_FILE_BYTES / 1024} KiB).`,
|
|
53951
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53952
|
+
inputSchema: z.object({ dir: DIR, path: z.string().min(1).describe('Path inside the app folder, e.g. "screens/home.ts".') }),
|
|
53953
|
+
handler: async (a, d) => {
|
|
53954
|
+
const app = await confinedAppDir(a, d);
|
|
53955
|
+
if (typeof app !== "string") return app;
|
|
53956
|
+
const p = confinedPath(app, a.path);
|
|
53957
|
+
if (typeof p !== "string") return refuse4("bad_path", p.error);
|
|
53958
|
+
if (!existsSync54(p) || !lstatSync12(p).isFile()) return refuse4("not_found", `no file "${String(a.path)}"`);
|
|
53959
|
+
const size = statSync13(p).size;
|
|
53960
|
+
if (size > MAX_FILE_BYTES) return refuse4("too_large", `"${String(a.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
|
|
53961
|
+
return ok({ ok: true, path: a.path, bytes: size, content: readFileSync59(p, "utf8") });
|
|
53962
|
+
}
|
|
53963
|
+
},
|
|
53964
|
+
{
|
|
53965
|
+
name: "himi_write_files",
|
|
53966
|
+
title: "Write app files",
|
|
53967
|
+
description: `Create or REPLACE files in an app folder (parent folders are created). At most ${MAX_FILES_PER_WRITE} files and ${MAX_FILE_BYTES / 1024} KiB each per call. Nothing is written if any path is refused.`,
|
|
53968
|
+
annotations: WRITE_ANN,
|
|
53969
|
+
inputSchema: z.object({
|
|
53970
|
+
dir: DIR,
|
|
53971
|
+
files: z.array(z.object({ path: z.string().min(1), content: z.string() })).min(1).max(MAX_FILES_PER_WRITE)
|
|
53972
|
+
}),
|
|
53973
|
+
handler: async (a, d) => {
|
|
53974
|
+
const app = await confinedAppDir(a, d);
|
|
53975
|
+
if (typeof app !== "string") return app;
|
|
53976
|
+
const files = Array.isArray(a.files) ? a.files : [];
|
|
53977
|
+
if (!files.length || files.length > MAX_FILES_PER_WRITE) return refuse4("bad_request", `between 1 and ${MAX_FILES_PER_WRITE} files per call`);
|
|
53978
|
+
const planned = [];
|
|
53979
|
+
const refused2 = [];
|
|
53980
|
+
for (const f of files) {
|
|
53981
|
+
const p = confinedPath(app, f.path);
|
|
53982
|
+
if (typeof p !== "string") refused2.push({ path: f.path, error: p.error });
|
|
53983
|
+
else if (typeof f.content !== "string") refused2.push({ path: f.path, error: "content must be text" });
|
|
53984
|
+
else if (Buffer.byteLength(f.content) > MAX_FILE_BYTES) refused2.push({ path: f.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
|
|
53985
|
+
else if (existsSync54(p) && !lstatSync12(p).isFile()) refused2.push({ path: f.path, error: "not a regular file" });
|
|
53986
|
+
else planned.push({ abs: p, rel: String(f.path), content: f.content });
|
|
53987
|
+
}
|
|
53988
|
+
if (refused2.length) return { ...ok({ ok: false, error: "refused", written: [], refused: refused2 }), isError: true };
|
|
53989
|
+
for (const f of planned) {
|
|
53990
|
+
mkdirSync26(dirname30(f.abs), { recursive: true });
|
|
53991
|
+
writeFileSync21(f.abs, f.content);
|
|
53992
|
+
}
|
|
53993
|
+
return ok({ ok: true, dir: app, written: planned.map((f) => f.rel) });
|
|
53994
|
+
}
|
|
53995
|
+
},
|
|
53996
|
+
{
|
|
53997
|
+
name: "himi_delete_files",
|
|
53998
|
+
title: "Delete app files",
|
|
53999
|
+
description: "Delete files (not folders) from an app folder. Nothing is deleted if any path is refused.",
|
|
54000
|
+
annotations: { ...WRITE_ANN, idempotentHint: false },
|
|
54001
|
+
inputSchema: z.object({ dir: DIR, paths: z.array(z.string().min(1)).min(1).max(MAX_FILES_PER_WRITE) }),
|
|
54002
|
+
handler: async (a, d) => {
|
|
54003
|
+
const app = await confinedAppDir(a, d);
|
|
54004
|
+
if (typeof app !== "string") return app;
|
|
54005
|
+
const paths = Array.isArray(a.paths) ? a.paths : [];
|
|
54006
|
+
const planned = [];
|
|
54007
|
+
const refused2 = [];
|
|
54008
|
+
for (const rel of paths) {
|
|
54009
|
+
const p = confinedPath(app, rel);
|
|
54010
|
+
if (typeof p !== "string") refused2.push({ path: rel, error: p.error });
|
|
54011
|
+
else if (!existsSync54(p)) refused2.push({ path: rel, error: "no such file" });
|
|
54012
|
+
else if (!lstatSync12(p).isFile()) refused2.push({ path: rel, error: "not a regular file" });
|
|
54013
|
+
else planned.push(p);
|
|
54014
|
+
}
|
|
54015
|
+
if (refused2.length) return { ...ok({ ok: false, error: "refused", deleted: [], refused: refused2 }), isError: true };
|
|
54016
|
+
for (const p of planned) rmSync12(p);
|
|
54017
|
+
return ok({ ok: true, dir: app, deleted: paths });
|
|
54018
|
+
}
|
|
54019
|
+
}
|
|
54020
|
+
];
|
|
54021
|
+
}
|
|
54022
|
+
var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED, RESERVED, CONTENT_MARKER, ok, refuse4, DIR, WRITE_ANN;
|
|
54023
|
+
var init_file_tools = __esm({
|
|
54024
|
+
"src/mcp/file-tools.ts"() {
|
|
54025
|
+
MAX_FILE_BYTES = 1024 * 1024;
|
|
54026
|
+
MAX_FILES_PER_WRITE = 100;
|
|
54027
|
+
MAX_LISTED = 2e3;
|
|
54028
|
+
RESERVED = /* @__PURE__ */ new Set([".git", "node_modules", "dist"]);
|
|
54029
|
+
CONTENT_MARKER = "himalaya.content.json";
|
|
54030
|
+
ok = (o) => ({ content: [{ type: "text", text: JSON.stringify(o, null, 2) }] });
|
|
54031
|
+
refuse4 = (error, message) => ({ content: [{ type: "text", text: JSON.stringify({ ok: false, error, message }, null, 2) }], isError: true });
|
|
54032
|
+
DIR = z.string().optional().describe("The app folder, relative to the workspace folder. Default: the workspace folder itself.");
|
|
54033
|
+
WRITE_ANN = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
|
|
54034
|
+
}
|
|
54035
|
+
});
|
|
54036
|
+
|
|
54037
|
+
// src/mcp/tools.ts
|
|
54038
|
+
import * as z2 from "zod";
|
|
54039
|
+
import { resolve as resolve46 } from "node:path";
|
|
53861
54040
|
function fromCli(r, extra = []) {
|
|
53862
54041
|
const body = r.json !== void 0 ? JSON.stringify(r.json, null, 2) : r.text.trim();
|
|
53863
54042
|
const content = [];
|
|
@@ -53869,10 +54048,27 @@ ${r.stderr.trim()}`) });
|
|
|
53869
54048
|
}
|
|
53870
54049
|
async function appDir2(args, deps) {
|
|
53871
54050
|
const base = await deps.defaultDir();
|
|
53872
|
-
return typeof args.dir === "string" && args.dir ?
|
|
54051
|
+
return typeof args.dir === "string" && args.dir ? resolve46(base, args.dir) : base;
|
|
54052
|
+
}
|
|
54053
|
+
function loginResult(s) {
|
|
54054
|
+
switch (s.state) {
|
|
54055
|
+
case "pending":
|
|
54056
|
+
return json3({
|
|
54057
|
+
ok: true,
|
|
54058
|
+
state: "pending",
|
|
54059
|
+
...s.loginUrl ? { loginUrl: s.loginUrl } : {},
|
|
54060
|
+
message: "A browser window opened for the user to sign in to Wix. If it did not open, give them `loginUrl`. Once they have signed in, call himi_login again to confirm, or just retry the push."
|
|
54061
|
+
});
|
|
54062
|
+
case "signed_in":
|
|
54063
|
+
return json3({ ok: true, state: "signed_in", account: s.account, scope: s.scope, expiresAt: s.expiresAt });
|
|
54064
|
+
case "failed":
|
|
54065
|
+
return { ...json3({ ok: false, state: "failed", error: s.error, hint: "Call himi_login again to retry, or ask the user to run `himi login --browser` in a terminal." }), isError: true };
|
|
54066
|
+
default:
|
|
54067
|
+
return json3({ ok: true, state: "idle" });
|
|
54068
|
+
}
|
|
53873
54069
|
}
|
|
53874
54070
|
async function requireLogin(deps) {
|
|
53875
|
-
const who = await deps.runCli(["whoami"]);
|
|
54071
|
+
const who = await deps.runCli(["whoami", ...opt("--target", deps.login.target())]);
|
|
53876
54072
|
if (who.code === 0) return null;
|
|
53877
54073
|
return { content: [{ type: "text", text: LOGIN_HINT }, ...who.stderr.trim() ? [{ type: "text", text: who.stderr.trim() }] : []], isError: true };
|
|
53878
54074
|
}
|
|
@@ -53891,8 +54087,8 @@ function guarded(h) {
|
|
|
53891
54087
|
return h(args, deps);
|
|
53892
54088
|
};
|
|
53893
54089
|
}
|
|
53894
|
-
function himiTools() {
|
|
53895
|
-
return rawTools().map((t) => ({ ...t, handler: guarded(t.handler) }));
|
|
54090
|
+
function himiTools(opts = {}) {
|
|
54091
|
+
return [...rawTools(), ...opts.withFiles ? fileTools() : []].map((t) => ({ ...t, handler: guarded(t.handler) }));
|
|
53896
54092
|
}
|
|
53897
54093
|
function rawTools() {
|
|
53898
54094
|
return [
|
|
@@ -53901,7 +54097,7 @@ function rawTools() {
|
|
|
53901
54097
|
title: "Read a himi authoring guide",
|
|
53902
54098
|
description: "List the Himalaya authoring guides, or read one by topic id. Offline \u2014 the guides ship with this CLI. Start here before authoring.",
|
|
53903
54099
|
annotations: LEARN,
|
|
53904
|
-
inputSchema:
|
|
54100
|
+
inputSchema: z2.object({ topic: z2.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
|
|
53905
54101
|
handler: async (a, d) => fromCli(await d.runCli(["docs", ...typeof a.topic === "string" && a.topic ? [a.topic] : [], "--json"]))
|
|
53906
54102
|
},
|
|
53907
54103
|
{
|
|
@@ -53909,7 +54105,7 @@ function rawTools() {
|
|
|
53909
54105
|
title: "SDUI component vocabulary",
|
|
53910
54106
|
description: "The SDUI component vocabulary and props a descriptor may use; a name returns that one component. Offline.",
|
|
53911
54107
|
annotations: LEARN,
|
|
53912
|
-
inputSchema:
|
|
54108
|
+
inputSchema: z2.object({ name: z2.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
|
|
53913
54109
|
handler: async (a, d) => fromCli(await d.runCli(["components", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
|
|
53914
54110
|
},
|
|
53915
54111
|
{
|
|
@@ -53917,7 +54113,7 @@ function rawTools() {
|
|
|
53917
54113
|
title: "Importable @himalaya SDKs",
|
|
53918
54114
|
description: "The @himalaya/* SDKs a Tier-5 worker may import; a name returns that SDK's typed API. Offline.",
|
|
53919
54115
|
annotations: LEARN,
|
|
53920
|
-
inputSchema:
|
|
54116
|
+
inputSchema: z2.object({ name: z2.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
|
|
53921
54117
|
handler: async (a, d) => fromCli(await d.runCli(["sdk", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
|
|
53922
54118
|
},
|
|
53923
54119
|
{
|
|
@@ -53925,7 +54121,7 @@ function rawTools() {
|
|
|
53925
54121
|
title: "Icon name vocabulary",
|
|
53926
54122
|
description: "The valid Icon.name values. An unknown name renders a fallback glyph and `himi_validate` warns. Offline.",
|
|
53927
54123
|
annotations: LEARN,
|
|
53928
|
-
inputSchema:
|
|
54124
|
+
inputSchema: z2.object({}),
|
|
53929
54125
|
handler: async (_a, d) => fromCli(await d.runCli(["icons", "--json"]))
|
|
53930
54126
|
},
|
|
53931
54127
|
{
|
|
@@ -53933,14 +54129,14 @@ function rawTools() {
|
|
|
53933
54129
|
title: "Create a new himi app",
|
|
53934
54130
|
description: "Scaffold a new content package `<parentDir>/<name>` (optionally from a reference template), with its agent files and this MCP server already configured for Claude Code, Cursor, Codex and VS Code. Refuses a directory that already exists.",
|
|
53935
54131
|
annotations: LOCAL_WRITE,
|
|
53936
|
-
inputSchema:
|
|
53937
|
-
name:
|
|
53938
|
-
parentDir:
|
|
53939
|
-
template:
|
|
54132
|
+
inputSchema: z2.object({
|
|
54133
|
+
name: z2.string().min(1).describe("The app name \u2014 also its folder name."),
|
|
54134
|
+
parentDir: z2.string().optional().describe("Where to create the folder. Default: the workspace root."),
|
|
54135
|
+
template: z2.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
|
|
53940
54136
|
}),
|
|
53941
54137
|
handler: async (a, d) => {
|
|
53942
54138
|
const base = await d.defaultDir();
|
|
53943
|
-
const parent = typeof a.parentDir === "string" && a.parentDir ?
|
|
54139
|
+
const parent = typeof a.parentDir === "string" && a.parentDir ? resolve46(base, a.parentDir) : base;
|
|
53944
54140
|
return fromCli(await d.runCli(["init", String(a.name), "--dir", parent, ...opt("--template", a.template)]));
|
|
53945
54141
|
}
|
|
53946
54142
|
},
|
|
@@ -53949,7 +54145,7 @@ function rawTools() {
|
|
|
53949
54145
|
title: "Build the app's worker bundles",
|
|
53950
54146
|
description: "Compile every tier5-src/<name>/index.ts to dist/bundles/<name>.bundle.js with esbuild. Writes dist/ only.",
|
|
53951
54147
|
annotations: LOCAL_WRITE,
|
|
53952
|
-
inputSchema:
|
|
54148
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
53953
54149
|
handler: async (a, d) => fromCli(await d.runCli(["build", "--content", await appDir2(a, d)]))
|
|
53954
54150
|
},
|
|
53955
54151
|
{
|
|
@@ -53957,7 +54153,7 @@ function rawTools() {
|
|
|
53957
54153
|
title: "Validate the app",
|
|
53958
54154
|
description: "Lint the content package without publishing: worker type-checking, schema/proto, token refs, the component allowlist, $service bindings. Run before every preview or push.",
|
|
53959
54155
|
annotations: CHECK,
|
|
53960
|
-
inputSchema:
|
|
54156
|
+
inputSchema: z2.object({ dir: DIR2, strict: z2.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
|
|
53961
54157
|
handler: async (a, d) => fromCli(await d.runCli(["validate", "--content", await appDir2(a, d), ...sw("--strict", a.strict)]))
|
|
53962
54158
|
},
|
|
53963
54159
|
{
|
|
@@ -53965,10 +54161,10 @@ function rawTools() {
|
|
|
53965
54161
|
title: "Behavioral crawl",
|
|
53966
54162
|
description: "The derived behavioral crawl: boots each screen's real worker and dispatches every action its descriptor declares, against the app's mocked network (dev/net-mocks.json). Hermetic \u2014 never reaches live Wix. Catches the wrong-reducer class validate and render pass clean.",
|
|
53967
54163
|
annotations: CHECK,
|
|
53968
|
-
inputSchema:
|
|
53969
|
-
dir:
|
|
53970
|
-
screens:
|
|
53971
|
-
deep:
|
|
54164
|
+
inputSchema: z2.object({
|
|
54165
|
+
dir: DIR2,
|
|
54166
|
+
screens: z2.array(z2.string()).optional().describe("Only these screen ids. Omit for all."),
|
|
54167
|
+
deep: z2.boolean().optional().describe("Also follow navigation into the screens actions open.")
|
|
53972
54168
|
}),
|
|
53973
54169
|
handler: async (a, d) => {
|
|
53974
54170
|
const screens = Array.isArray(a.screens) ? a.screens.filter((s) => typeof s === "string") : [];
|
|
@@ -53980,13 +54176,13 @@ function rawTools() {
|
|
|
53980
54176
|
title: "Render a screen to PNG",
|
|
53981
54177
|
description: "Headless-render one screen with the web renderer and return the PNG plus the render diagnostics. The PNG is also written to .himi/shots/<screen>.png, which the build board shows. Needs Playwright's Chromium; without it the result says how to install it and still returns the diagnostics.",
|
|
53982
54178
|
annotations: CHECK,
|
|
53983
|
-
inputSchema:
|
|
53984
|
-
screen:
|
|
53985
|
-
dir:
|
|
53986
|
-
scheme:
|
|
53987
|
-
width:
|
|
53988
|
-
device:
|
|
53989
|
-
rtl:
|
|
54179
|
+
inputSchema: z2.object({
|
|
54180
|
+
screen: z2.string().min(1).describe("The screen id."),
|
|
54181
|
+
dir: DIR2,
|
|
54182
|
+
scheme: z2.enum(["light", "dark"]).optional(),
|
|
54183
|
+
width: z2.number().int().positive().optional().describe("Viewport width in px."),
|
|
54184
|
+
device: z2.string().optional().describe("A named device (overrides width)."),
|
|
54185
|
+
rtl: z2.boolean().optional()
|
|
53990
54186
|
}),
|
|
53991
54187
|
handler: async (a, d) => {
|
|
53992
54188
|
const r = await d.runCli([
|
|
@@ -54016,12 +54212,12 @@ function rawTools() {
|
|
|
54016
54212
|
title: "Build journal",
|
|
54017
54213
|
description: "Read or append the owner-facing build journal (.himi/progress.jsonl). With `message`, append one postcard for a journey step; without, print the journal \u2014 `brief` gives the short session-start summary (current step, open approvals).",
|
|
54018
54214
|
annotations: { ...LOCAL_WRITE, idempotentHint: false },
|
|
54019
|
-
inputSchema:
|
|
54020
|
-
dir:
|
|
54021
|
-
message:
|
|
54022
|
-
step:
|
|
54023
|
-
noImage:
|
|
54024
|
-
brief:
|
|
54215
|
+
inputSchema: z2.object({
|
|
54216
|
+
dir: DIR2,
|
|
54217
|
+
message: z2.string().optional().describe("What changed, one or two lines, for the owner."),
|
|
54218
|
+
step: z2.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
|
|
54219
|
+
noImage: z2.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
|
|
54220
|
+
brief: z2.boolean().optional()
|
|
54025
54221
|
}),
|
|
54026
54222
|
handler: async (a, d) => {
|
|
54027
54223
|
const dir = await appDir2(a, d);
|
|
@@ -54034,7 +54230,7 @@ function rawTools() {
|
|
|
54034
54230
|
title: "Start the live preview",
|
|
54035
54231
|
description: "Serve the app on localhost and keep it live (`himi run --watch`): every save rebuilds and repaints the open tab. Returns the URL. Reuses a preview that is already running for this app. " + PREVIEW_HINT,
|
|
54036
54232
|
annotations: LOCAL_WRITE,
|
|
54037
|
-
inputSchema:
|
|
54233
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54038
54234
|
handler: async (a, d) => {
|
|
54039
54235
|
try {
|
|
54040
54236
|
return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
|
|
@@ -54051,7 +54247,7 @@ ${log}` : ""}`, true);
|
|
|
54051
54247
|
title: "Live preview status",
|
|
54052
54248
|
description: "Whether this app's live preview is running, and its URL and last build result.",
|
|
54053
54249
|
annotations: CHECK,
|
|
54054
|
-
inputSchema:
|
|
54250
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54055
54251
|
handler: async (a, d) => json3(await d.preview.status(await appDir2(a, d)))
|
|
54056
54252
|
},
|
|
54057
54253
|
{
|
|
@@ -54059,7 +54255,7 @@ ${log}` : ""}`, true);
|
|
|
54059
54255
|
title: "Stop the live preview",
|
|
54060
54256
|
description: "Stop this app's live preview (the `himi run --watch` a `himi_preview_start` started).",
|
|
54061
54257
|
annotations: { ...LOCAL_WRITE, destructiveHint: false },
|
|
54062
|
-
inputSchema:
|
|
54258
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54063
54259
|
handler: async (a, d) => json3(await d.preview.stop(await appDir2(a, d)))
|
|
54064
54260
|
},
|
|
54065
54261
|
{
|
|
@@ -54067,38 +54263,60 @@ ${log}` : ""}`, true);
|
|
|
54067
54263
|
title: "Signed-in identity",
|
|
54068
54264
|
description: "The identity the stored serve-plane credential carries (account, scope, expiry). Local \u2014 decodes the stored token, no network.",
|
|
54069
54265
|
annotations: LEARN,
|
|
54070
|
-
inputSchema:
|
|
54071
|
-
handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target)]))
|
|
54266
|
+
inputSchema: z2.object({ target: z2.string().optional().describe("Serve target. Default: the CLI's default.") }),
|
|
54267
|
+
handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target ?? d.login.target())]))
|
|
54268
|
+
},
|
|
54269
|
+
{
|
|
54270
|
+
name: "himi_login",
|
|
54271
|
+
title: "Sign in to Wix",
|
|
54272
|
+
description: "Open a browser window where the USER signs in to Wix, so himi_push and himi_share can publish. Returns at once with the sign-in link; call again to see whether the sign-in finished. Already signed in: says who, and opens nothing unless `switchAccount` is true. This server never sees the credential \u2014 the sign-in stores a scoped token on this machine.",
|
|
54273
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
54274
|
+
inputSchema: z2.object({
|
|
54275
|
+
target: z2.string().optional().describe("Serve target. Default: the CLI's default."),
|
|
54276
|
+
switchAccount: z2.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
|
|
54277
|
+
}),
|
|
54278
|
+
handler: async (a, d) => {
|
|
54279
|
+
const s = d.login.status();
|
|
54280
|
+
if (s.state === "pending") return loginResult(s);
|
|
54281
|
+
if (!a.switchAccount) {
|
|
54282
|
+
const who = await d.runCli(["whoami", ...opt("--target", a.target)]);
|
|
54283
|
+
if (who.code === 0) {
|
|
54284
|
+
d.login.adopt(typeof a.target === "string" && a.target ? a.target : void 0);
|
|
54285
|
+
return json3({ ok: true, state: "signed_in", ...who.json && typeof who.json === "object" ? who.json : {} });
|
|
54286
|
+
}
|
|
54287
|
+
}
|
|
54288
|
+
return loginResult(await d.login.start(typeof a.target === "string" && a.target ? a.target : void 0));
|
|
54289
|
+
}
|
|
54072
54290
|
},
|
|
54073
54291
|
{
|
|
54074
54292
|
name: "himi_push",
|
|
54075
54293
|
title: "Publish a draft",
|
|
54076
|
-
description: "Lint, build and publish the app as a DRAFT release: owner-private, servable by preview link and in Himi Player, NOT live. Returns the preview links and the universal link that opens it in Himi Player. Never promotes \u2014 going live is a human command. Refuses on any validation error. Needs
|
|
54294
|
+
description: "Lint, build and publish the app as a DRAFT release: owner-private, servable by preview link and in Himi Player, NOT live. Returns the preview links and the universal link that opens it in Himi Player. Never promotes \u2014 going live is a human command. Refuses on any validation error. Needs a sign-in first (himi_login).",
|
|
54077
54295
|
annotations: PUBLISH,
|
|
54078
|
-
inputSchema:
|
|
54079
|
-
dir:
|
|
54080
|
-
label:
|
|
54081
|
-
notes:
|
|
54296
|
+
inputSchema: z2.object({
|
|
54297
|
+
dir: DIR2,
|
|
54298
|
+
label: z2.string().optional().describe("A short label for this draft."),
|
|
54299
|
+
notes: z2.string().optional().describe("Release notes for this draft.")
|
|
54082
54300
|
}),
|
|
54083
54301
|
handler: async (a, d) => {
|
|
54084
54302
|
const gate = await requireLogin(d);
|
|
54085
54303
|
if (gate) return gate;
|
|
54086
|
-
return fromCli(await d.runCli(["push", "--content", await appDir2(a, d), "--draft", ...opt("--label", a.label), ...opt("--notes", a.notes)]));
|
|
54304
|
+
return fromCli(await d.runCli(["push", "--content", await appDir2(a, d), "--draft", ...opt("--label", a.label), ...opt("--notes", a.notes), ...opt("--target", d.login.target())]));
|
|
54087
54305
|
}
|
|
54088
54306
|
},
|
|
54089
54307
|
{
|
|
54090
54308
|
name: "himi_share",
|
|
54091
54309
|
title: "Share a .himi package link",
|
|
54092
|
-
description: "Publish a content-addressed share link for a validated `.himi` package of an already-published release. Needs
|
|
54310
|
+
description: "Publish a content-addressed share link for a validated `.himi` package of an already-published release. Needs a sign-in first (himi_login).",
|
|
54093
54311
|
annotations: PUBLISH,
|
|
54094
|
-
inputSchema:
|
|
54095
|
-
file:
|
|
54096
|
-
expiresAt:
|
|
54312
|
+
inputSchema: z2.object({
|
|
54313
|
+
file: z2.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
|
|
54314
|
+
expiresAt: z2.string().optional().describe("ISO timestamp the link stops working.")
|
|
54097
54315
|
}),
|
|
54098
54316
|
handler: async (a, d) => {
|
|
54099
54317
|
const gate = await requireLogin(d);
|
|
54100
54318
|
if (gate) return gate;
|
|
54101
|
-
return fromCli(await d.runCli(["share", "--file",
|
|
54319
|
+
return fromCli(await d.runCli(["share", "--file", resolve46(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt), ...opt("--target", d.login.target())]));
|
|
54102
54320
|
}
|
|
54103
54321
|
},
|
|
54104
54322
|
{
|
|
@@ -54108,19 +54326,20 @@ ${log}` : ""}`, true);
|
|
|
54108
54326
|
// Not idempotent: with credentials, each `himi preview` mints a fresh single-use handover —
|
|
54109
54327
|
// the same reason the hosted connector's tool of this name says false (RFC 0064 §5).
|
|
54110
54328
|
annotations: { ...PUBLISH, readOnlyHint: true, idempotentHint: false },
|
|
54111
|
-
inputSchema:
|
|
54112
|
-
app:
|
|
54113
|
-
release:
|
|
54114
|
-
screen:
|
|
54115
|
-
surface:
|
|
54329
|
+
inputSchema: z2.object({
|
|
54330
|
+
app: z2.string().min(1),
|
|
54331
|
+
release: z2.string().min(1),
|
|
54332
|
+
screen: z2.string().optional(),
|
|
54333
|
+
surface: z2.string().optional()
|
|
54116
54334
|
}),
|
|
54117
|
-
handler: async (a, d) => fromCli(await d.runCli(["preview", "--app", String(a.app), "--release", String(a.release), ...opt("--screen", a.screen), ...opt("--surface", a.surface)]))
|
|
54335
|
+
handler: async (a, d) => fromCli(await d.runCli(["preview", "--app", String(a.app), "--release", String(a.release), ...opt("--screen", a.screen), ...opt("--surface", a.surface), ...opt("--target", d.login.target())]))
|
|
54118
54336
|
}
|
|
54119
54337
|
];
|
|
54120
54338
|
}
|
|
54121
|
-
var MAX_TEXT2, clip, text6, json3, opt, sw,
|
|
54339
|
+
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
|
|
54122
54340
|
var init_tools = __esm({
|
|
54123
54341
|
"src/mcp/tools.ts"() {
|
|
54342
|
+
init_file_tools();
|
|
54124
54343
|
MAX_TEXT2 = 8e4;
|
|
54125
54344
|
clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
|
|
54126
54345
|
\u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
|
|
@@ -54128,13 +54347,88 @@ var init_tools = __esm({
|
|
|
54128
54347
|
json3 = (o) => text6(JSON.stringify(o, null, 2));
|
|
54129
54348
|
opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
|
|
54130
54349
|
sw = (flag, v) => v === true ? [flag] : [];
|
|
54131
|
-
|
|
54350
|
+
DIR2 = z2.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
|
|
54132
54351
|
LEARN = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54133
54352
|
CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54134
54353
|
LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54135
54354
|
PUBLISH = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
54136
54355
|
PREVIEW_HINT = "The preview is already running: open `url` in your built-in browser \u2014 Claude Code desktop's browser pane, Cursor's Browser tool, the Browser in Codex inside the ChatGPT desktop app, VS Code's integrated browser. Do not also start the `himi-preview` launch configuration: it serves the same port, and is the way to start a preview only when none is running. A terminal-only agent should show the owner `himi_render` PNGs instead. `board` (when present) is the build board on the same origin.";
|
|
54137
|
-
LOGIN_HINT = "Not signed in to the himi serve plane.
|
|
54356
|
+
LOGIN_HINT = "Not signed in to the himi serve plane. Call himi_login: it opens a browser window where the user signs in to Wix (this server never sees the credential). A user with a terminal can run `himi login --browser` instead. Then retry.";
|
|
54357
|
+
}
|
|
54358
|
+
});
|
|
54359
|
+
|
|
54360
|
+
// src/mcp/login.ts
|
|
54361
|
+
import { spawn as nodeSpawn2 } from "node:child_process";
|
|
54362
|
+
function createLoginSession(deps) {
|
|
54363
|
+
let current = { state: "idle" };
|
|
54364
|
+
let signedInTarget;
|
|
54365
|
+
return {
|
|
54366
|
+
status: () => current,
|
|
54367
|
+
target: () => signedInTarget,
|
|
54368
|
+
adopt: (target) => {
|
|
54369
|
+
signedInTarget = target;
|
|
54370
|
+
},
|
|
54371
|
+
start(target) {
|
|
54372
|
+
if (current.state === "pending") return Promise.resolve(current);
|
|
54373
|
+
const self = deps.selfCommand();
|
|
54374
|
+
const args = [...self.args, "login", "--browser", "--skip-version-check", ...target ? ["--target", target] : []];
|
|
54375
|
+
const pending = { state: "pending", startedAt: deps.now() };
|
|
54376
|
+
current = pending;
|
|
54377
|
+
const out2 = [];
|
|
54378
|
+
const err = [];
|
|
54379
|
+
return new Promise((resolve54) => {
|
|
54380
|
+
let answered = false;
|
|
54381
|
+
const answer = () => {
|
|
54382
|
+
if (answered) return;
|
|
54383
|
+
answered = true;
|
|
54384
|
+
resolve54(current);
|
|
54385
|
+
};
|
|
54386
|
+
let child;
|
|
54387
|
+
try {
|
|
54388
|
+
child = deps.spawn(self.cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, HIMI_NO_UPDATE_CHECK: "1" } });
|
|
54389
|
+
} catch (e) {
|
|
54390
|
+
current = { state: "failed", error: `could not start himi login: ${e.message}` };
|
|
54391
|
+
answer();
|
|
54392
|
+
return;
|
|
54393
|
+
}
|
|
54394
|
+
child.stdout?.on("data", (c) => out2.push(String(c)));
|
|
54395
|
+
child.stderr?.on("data", (c) => {
|
|
54396
|
+
err.push(String(c));
|
|
54397
|
+
const link = LINK2.exec(err.join(""))?.[0];
|
|
54398
|
+
if (link && !pending.loginUrl && current === pending) {
|
|
54399
|
+
pending.loginUrl = link;
|
|
54400
|
+
answer();
|
|
54401
|
+
}
|
|
54402
|
+
});
|
|
54403
|
+
child.once("error", (e) => {
|
|
54404
|
+
current = { state: "failed", error: `could not start himi login: ${e.message}` };
|
|
54405
|
+
answer();
|
|
54406
|
+
});
|
|
54407
|
+
child.once("exit", (code) => {
|
|
54408
|
+
if (code === 0) {
|
|
54409
|
+
const r = lastJson([out2.join("")]) ?? {};
|
|
54410
|
+
current = { state: "signed_in", account: r.sub, scope: r.scope, expiresAt: r.exp };
|
|
54411
|
+
signedInTarget = target;
|
|
54412
|
+
} else {
|
|
54413
|
+
const e = lastJson(err.join("").split("\n"));
|
|
54414
|
+
current = { state: "failed", error: e?.error ?? (err.join("").trim().slice(-500) || `himi login exited ${code}`) };
|
|
54415
|
+
}
|
|
54416
|
+
answer();
|
|
54417
|
+
});
|
|
54418
|
+
setTimeout(answer, deps.linkWaitMs ?? 5e3).unref?.();
|
|
54419
|
+
});
|
|
54420
|
+
}
|
|
54421
|
+
};
|
|
54422
|
+
}
|
|
54423
|
+
var defaultLoginDeps, LINK2;
|
|
54424
|
+
var init_login = __esm({
|
|
54425
|
+
"src/mcp/login.ts"() {
|
|
54426
|
+
init_cli_bridge();
|
|
54427
|
+
defaultLoginDeps = {
|
|
54428
|
+
spawn: (cmd, args, opts) => nodeSpawn2(cmd, args, opts),
|
|
54429
|
+
now: () => Date.now()
|
|
54430
|
+
};
|
|
54431
|
+
LINK2 = /https?:\/\/[^\s)]+/;
|
|
54138
54432
|
}
|
|
54139
54433
|
});
|
|
54140
54434
|
|
|
@@ -54146,7 +54440,7 @@ __export(server_exports, {
|
|
|
54146
54440
|
protectStdout: () => protectStdout,
|
|
54147
54441
|
startMcpServer: () => startMcpServer
|
|
54148
54442
|
});
|
|
54149
|
-
import { readFileSync as
|
|
54443
|
+
import { readFileSync as readFileSync60 } from "node:fs";
|
|
54150
54444
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
54151
54445
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
54152
54446
|
import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
@@ -54156,9 +54450,9 @@ function protectStdout() {
|
|
|
54156
54450
|
console.info = toErr;
|
|
54157
54451
|
console.debug = toErr;
|
|
54158
54452
|
}
|
|
54159
|
-
function buildServer(deps, version2) {
|
|
54453
|
+
function buildServer(deps, version2, tools = {}) {
|
|
54160
54454
|
const server = new McpServer({ name: "himi", version: version2 }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
|
|
54161
|
-
for (const tool of himiTools()) {
|
|
54455
|
+
for (const tool of himiTools(tools)) {
|
|
54162
54456
|
server.registerTool(
|
|
54163
54457
|
tool.name,
|
|
54164
54458
|
{ title: tool.title, description: tool.description, inputSchema: tool.inputSchema, annotations: { title: tool.title, ...tool.annotations } },
|
|
@@ -54192,22 +54486,23 @@ async function startMcpServer(opts) {
|
|
|
54192
54486
|
// next call rather than pinning every later tool to the server's cwd (often $HOME for a GUI host).
|
|
54193
54487
|
defaultDir: async () => {
|
|
54194
54488
|
if (!rootDir && pinned) rootDir = await firstRoot(pinned);
|
|
54195
|
-
return rootDir || process.cwd();
|
|
54489
|
+
return rootDir || opts.workspace || process.cwd();
|
|
54196
54490
|
},
|
|
54197
54491
|
preview: {
|
|
54198
54492
|
start: (dir) => startPreview(dir, { port: previewPortForDir(dir) }, previewDeps),
|
|
54199
54493
|
status: (dir) => previewStatus(dir, previewDeps),
|
|
54200
54494
|
stop: (dir) => stopPreview(dir, previewDeps)
|
|
54201
54495
|
},
|
|
54202
|
-
readFile: (p) =>
|
|
54496
|
+
readFile: (p) => readFileSync60(p),
|
|
54497
|
+
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
|
|
54203
54498
|
};
|
|
54204
|
-
const closed = new Promise((
|
|
54205
|
-
stdin.once("end",
|
|
54206
|
-
stdin.once("close",
|
|
54499
|
+
const closed = new Promise((resolve54) => {
|
|
54500
|
+
stdin.once("end", resolve54);
|
|
54501
|
+
stdin.once("close", resolve54);
|
|
54207
54502
|
});
|
|
54208
54503
|
const handle = serveStdio(
|
|
54209
54504
|
() => {
|
|
54210
|
-
pinned = buildServer(deps, opts.version);
|
|
54505
|
+
pinned = buildServer(deps, opts.version, { withFiles: opts.withFiles });
|
|
54211
54506
|
return pinned;
|
|
54212
54507
|
},
|
|
54213
54508
|
{ transport: new StdioServerTransport(stdin, stdout), onerror: (e) => console.error(`[himi mcp] ${e.message}`) }
|
|
@@ -54221,6 +54516,7 @@ var init_server = __esm({
|
|
|
54221
54516
|
init_cli_bridge();
|
|
54222
54517
|
init_tools();
|
|
54223
54518
|
init_preview();
|
|
54519
|
+
init_login();
|
|
54224
54520
|
SERVER_INSTRUCTIONS = "himi builds native mobile apps (iOS + Android + web) from a content package: SDUI descriptors plus Tier-5 JS workers. The loop: himi_docs (read `headless-loop` first) \u2192 edit files \u2192 himi_validate \u2192 himi_test \u2192 himi_render (show the owner the PNG) \u2192 himi_preview_start (live preview in your IDE's browser) \u2192 himi_push (a DRAFT the owner opens in Himi Player; never live). Tools act on the workspace root unless given `dir`.";
|
|
54225
54521
|
}
|
|
54226
54522
|
});
|
|
@@ -54240,9 +54536,9 @@ __export(native_decode_exports, {
|
|
|
54240
54536
|
runNativeDecode: () => runNativeDecode
|
|
54241
54537
|
});
|
|
54242
54538
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
54243
|
-
import { existsSync as
|
|
54539
|
+
import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync22 } from "node:fs";
|
|
54244
54540
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
54245
|
-
import { join as
|
|
54541
|
+
import { join as join54 } from "node:path";
|
|
54246
54542
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
54247
54543
|
function nativeDecodePackageDir() {
|
|
54248
54544
|
return fileURLToPath22(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -54252,8 +54548,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
54252
54548
|
}
|
|
54253
54549
|
function nativeOracleShipped() {
|
|
54254
54550
|
return {
|
|
54255
|
-
ios:
|
|
54256
|
-
android:
|
|
54551
|
+
ios: existsSync55(join54(nativeDecodePackageDir(), "Package.swift")),
|
|
54552
|
+
android: existsSync55(join54(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
54257
54553
|
};
|
|
54258
54554
|
}
|
|
54259
54555
|
function detectNativeDecode(options = {}) {
|
|
@@ -54264,7 +54560,7 @@ function detectNativeDecode(options = {}) {
|
|
|
54264
54560
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
54265
54561
|
}
|
|
54266
54562
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
54267
|
-
const packageAvailable = options.packageAvailable ??
|
|
54563
|
+
const packageAvailable = options.packageAvailable ?? existsSync55(join54(packageDir, "Package.swift"));
|
|
54268
54564
|
if (!packageAvailable) {
|
|
54269
54565
|
return {
|
|
54270
54566
|
platform: "ios",
|
|
@@ -54276,7 +54572,7 @@ function detectNativeDecode(options = {}) {
|
|
|
54276
54572
|
}
|
|
54277
54573
|
function localPropertiesSdk(harnessDir) {
|
|
54278
54574
|
try {
|
|
54279
|
-
const match =
|
|
54575
|
+
const match = readFileSync61(join54(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
54280
54576
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
54281
54577
|
} catch {
|
|
54282
54578
|
return null;
|
|
@@ -54284,8 +54580,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
54284
54580
|
}
|
|
54285
54581
|
function detectAndroidNativeDecode(options = {}) {
|
|
54286
54582
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
54287
|
-
const gradlew =
|
|
54288
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
54583
|
+
const gradlew = join54(harnessDir, "gradlew");
|
|
54584
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync55(gradlew);
|
|
54289
54585
|
if (!gradlewAvailable) {
|
|
54290
54586
|
return {
|
|
54291
54587
|
platform: "android",
|
|
@@ -54295,7 +54591,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
54295
54591
|
}
|
|
54296
54592
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
54297
54593
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
54298
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
54594
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync55(sdk));
|
|
54299
54595
|
if (!sdkAvailable) {
|
|
54300
54596
|
return {
|
|
54301
54597
|
platform: "android",
|
|
@@ -54367,14 +54663,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
54367
54663
|
return verdicts;
|
|
54368
54664
|
}
|
|
54369
54665
|
function runNativeDecode(options) {
|
|
54370
|
-
const descriptorDir = mkdtempSync2(
|
|
54666
|
+
const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-"));
|
|
54371
54667
|
const startedAt = Date.now();
|
|
54372
54668
|
try {
|
|
54373
54669
|
for (const descriptor of options.descriptors) {
|
|
54374
54670
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54375
54671
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54376
54672
|
}
|
|
54377
|
-
|
|
54673
|
+
writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54378
54674
|
}
|
|
54379
54675
|
options.progress?.("building cached Swift oracle");
|
|
54380
54676
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -54386,7 +54682,7 @@ function runNativeDecode(options) {
|
|
|
54386
54682
|
encoding: "utf8"
|
|
54387
54683
|
}).trim();
|
|
54388
54684
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54389
|
-
const stdout = execFileSync5(
|
|
54685
|
+
const stdout = execFileSync5(join54(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
54390
54686
|
stdio: ["ignore", "pipe", "pipe"],
|
|
54391
54687
|
encoding: "utf8"
|
|
54392
54688
|
});
|
|
@@ -54400,19 +54696,19 @@ function runNativeDecode(options) {
|
|
|
54400
54696
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
54401
54697
|
throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
|
|
54402
54698
|
} finally {
|
|
54403
|
-
|
|
54699
|
+
rmSync13(descriptorDir, { recursive: true, force: true });
|
|
54404
54700
|
}
|
|
54405
54701
|
}
|
|
54406
54702
|
function runAndroidNativeDecode(options) {
|
|
54407
|
-
const descriptorDir = mkdtempSync2(
|
|
54408
|
-
const outputPath =
|
|
54703
|
+
const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-android-"));
|
|
54704
|
+
const outputPath = join54(descriptorDir, "verdicts.ndjson");
|
|
54409
54705
|
const startedAt = Date.now();
|
|
54410
54706
|
try {
|
|
54411
54707
|
for (const descriptor of options.descriptors) {
|
|
54412
54708
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54413
54709
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54414
54710
|
}
|
|
54415
|
-
|
|
54711
|
+
writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54416
54712
|
}
|
|
54417
54713
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54418
54714
|
execFileSync5(options.gradlew, [
|
|
@@ -54427,7 +54723,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54427
54723
|
stdio: ["ignore", "ignore", "pipe"],
|
|
54428
54724
|
encoding: "utf8"
|
|
54429
54725
|
});
|
|
54430
|
-
const stdout =
|
|
54726
|
+
const stdout = readFileSync61(outputPath, "utf8");
|
|
54431
54727
|
return {
|
|
54432
54728
|
platform: "android",
|
|
54433
54729
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -54438,7 +54734,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54438
54734
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
54439
54735
|
throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
|
|
54440
54736
|
} finally {
|
|
54441
|
-
|
|
54737
|
+
rmSync13(descriptorDir, { recursive: true, force: true });
|
|
54442
54738
|
}
|
|
54443
54739
|
}
|
|
54444
54740
|
function fieldAt(path2) {
|
|
@@ -54497,30 +54793,30 @@ __export(browser_authoring_exports, {
|
|
|
54497
54793
|
});
|
|
54498
54794
|
import { createServer as createServer5 } from "node:http";
|
|
54499
54795
|
import { createHash as createHash29, randomBytes as randomBytes4 } from "node:crypto";
|
|
54500
|
-
import { existsSync as
|
|
54501
|
-
import { join as
|
|
54796
|
+
import { existsSync as existsSync56, readdirSync as readdirSync28, readFileSync as readFileSync62, realpathSync as realpathSync8, statSync as statSync14 } from "node:fs";
|
|
54797
|
+
import { join as join55, posix as posix2, relative as relative12, sep as sep15 } from "node:path";
|
|
54502
54798
|
function humanMs(ms) {
|
|
54503
54799
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
54504
54800
|
}
|
|
54505
54801
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
54506
|
-
const root =
|
|
54802
|
+
const root = join55(tier5SrcDir, bundleName);
|
|
54507
54803
|
const files = {};
|
|
54508
54804
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
54509
54805
|
const walk2 = (abs, rel) => {
|
|
54510
|
-
const real =
|
|
54806
|
+
const real = realpathSync8(abs);
|
|
54511
54807
|
if (visitedDirs.has(real)) return;
|
|
54512
54808
|
visitedDirs.add(real);
|
|
54513
|
-
for (const name of
|
|
54514
|
-
const childAbs =
|
|
54809
|
+
for (const name of readdirSync28(abs).sort()) {
|
|
54810
|
+
const childAbs = join55(abs, name);
|
|
54515
54811
|
const childRel = posix2.join(rel, name);
|
|
54516
|
-
if (
|
|
54812
|
+
if (statSync14(childAbs).isDirectory()) {
|
|
54517
54813
|
walk2(childAbs, childRel);
|
|
54518
54814
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
54519
|
-
files[childRel] =
|
|
54815
|
+
files[childRel] = readFileSync62(childAbs, "utf8");
|
|
54520
54816
|
}
|
|
54521
54817
|
}
|
|
54522
54818
|
};
|
|
54523
|
-
if (!
|
|
54819
|
+
if (!existsSync56(root)) return null;
|
|
54524
54820
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
54525
54821
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
54526
54822
|
if (!entry) return null;
|
|
@@ -54537,20 +54833,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
54537
54833
|
const spec = m[1];
|
|
54538
54834
|
const virtual = posix2.normalize(posix2.join(dir, spec));
|
|
54539
54835
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
54540
|
-
const onDisk =
|
|
54836
|
+
const onDisk = join55(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
54541
54837
|
const candidates = [
|
|
54542
54838
|
onDisk,
|
|
54543
54839
|
`${onDisk}.ts`,
|
|
54544
54840
|
`${onDisk}.js`,
|
|
54545
54841
|
onDisk.replace(/\.js$/, ".ts"),
|
|
54546
|
-
|
|
54547
|
-
|
|
54842
|
+
join55(onDisk, "index.ts"),
|
|
54843
|
+
join55(onDisk, "index.js")
|
|
54548
54844
|
];
|
|
54549
54845
|
for (const abs of candidates) {
|
|
54550
|
-
if (!
|
|
54551
|
-
const key2 = `/tier5-src/${
|
|
54846
|
+
if (!existsSync56(abs) || statSync14(abs).isDirectory()) continue;
|
|
54847
|
+
const key2 = `/tier5-src/${relative12(tier5SrcDir, abs).split(sep15).join(posix2.sep)}`;
|
|
54552
54848
|
if (key2 in files) break;
|
|
54553
|
-
files[key2] =
|
|
54849
|
+
files[key2] = readFileSync62(abs, "utf8");
|
|
54554
54850
|
queue.push(key2);
|
|
54555
54851
|
break;
|
|
54556
54852
|
}
|
|
@@ -54582,10 +54878,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
54582
54878
|
for (const source of Object.values(files)) visit(source);
|
|
54583
54879
|
return { modules, unsupported };
|
|
54584
54880
|
}
|
|
54585
|
-
function sdkSubpathReader(
|
|
54881
|
+
function sdkSubpathReader(resolve54) {
|
|
54586
54882
|
return (sub) => {
|
|
54587
54883
|
try {
|
|
54588
|
-
return
|
|
54884
|
+
return readFileSync62(resolve54(`@wix/himalaya/${sub}`), "utf8");
|
|
54589
54885
|
} catch {
|
|
54590
54886
|
return null;
|
|
54591
54887
|
}
|
|
@@ -54663,7 +54959,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
54663
54959
|
const token = mintToken2(payload);
|
|
54664
54960
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
54665
54961
|
if (unusable) throw new Error(unusable);
|
|
54666
|
-
return await new Promise((
|
|
54962
|
+
return await new Promise((resolve54, reject) => {
|
|
54667
54963
|
let settled = false;
|
|
54668
54964
|
let url = "";
|
|
54669
54965
|
const server = createServer5();
|
|
@@ -54715,7 +55011,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
54715
55011
|
}
|
|
54716
55012
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
54717
55013
|
const report3 = body.result;
|
|
54718
|
-
finish2(() =>
|
|
55014
|
+
finish2(() => resolve54({ report: report3, url }));
|
|
54719
55015
|
})();
|
|
54720
55016
|
});
|
|
54721
55017
|
server.on("error", (e) => finish2(() => reject(e)));
|
|
@@ -54757,8 +55053,8 @@ __export(coverage_exports, {
|
|
|
54757
55053
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
54758
55054
|
trendAndStore: () => trendAndStore
|
|
54759
55055
|
});
|
|
54760
|
-
import { existsSync as
|
|
54761
|
-
import { dirname as
|
|
55056
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as writeFileSync23 } from "node:fs";
|
|
55057
|
+
import { dirname as dirname31, join as join56 } from "node:path";
|
|
54762
55058
|
function suppressedNativeKeys(oracle) {
|
|
54763
55059
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
54764
55060
|
}
|
|
@@ -54938,11 +55234,11 @@ function assembleLedger(r, options = {}) {
|
|
|
54938
55234
|
return out2;
|
|
54939
55235
|
}
|
|
54940
55236
|
function trendAndStore(dir, entries, suppressed) {
|
|
54941
|
-
const p =
|
|
55237
|
+
const p = join56(dir, LEDGER_FILE);
|
|
54942
55238
|
let previous = null;
|
|
54943
55239
|
try {
|
|
54944
|
-
if (
|
|
54945
|
-
const parsed = JSON.parse(
|
|
55240
|
+
if (existsSync57(p)) {
|
|
55241
|
+
const parsed = JSON.parse(readFileSync63(p, "utf8"));
|
|
54946
55242
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
54947
55243
|
}
|
|
54948
55244
|
} catch {
|
|
@@ -54950,8 +55246,8 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
54950
55246
|
const current = entries.map((e) => e.key);
|
|
54951
55247
|
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
54952
55248
|
try {
|
|
54953
|
-
|
|
54954
|
-
|
|
55249
|
+
mkdirSync27(dirname31(p), { recursive: true });
|
|
55250
|
+
writeFileSync23(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
54955
55251
|
} catch {
|
|
54956
55252
|
return null;
|
|
54957
55253
|
}
|
|
@@ -54981,11 +55277,11 @@ function formatLedger(entries, trend) {
|
|
|
54981
55277
|
return out2.join("\n");
|
|
54982
55278
|
}
|
|
54983
55279
|
function diffAndStoreObservations(dir, current) {
|
|
54984
|
-
const p =
|
|
55280
|
+
const p = join56(dir, OBS_FILE);
|
|
54985
55281
|
let previous = null;
|
|
54986
55282
|
try {
|
|
54987
|
-
if (
|
|
54988
|
-
const parsed = JSON.parse(
|
|
55283
|
+
if (existsSync57(p)) {
|
|
55284
|
+
const parsed = JSON.parse(readFileSync63(p, "utf8"));
|
|
54989
55285
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
54990
55286
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
54991
55287
|
)) {
|
|
@@ -54995,8 +55291,8 @@ function diffAndStoreObservations(dir, current) {
|
|
|
54995
55291
|
} catch {
|
|
54996
55292
|
}
|
|
54997
55293
|
try {
|
|
54998
|
-
|
|
54999
|
-
|
|
55294
|
+
mkdirSync27(dirname31(p), { recursive: true });
|
|
55295
|
+
writeFileSync23(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55000
55296
|
} catch {
|
|
55001
55297
|
return null;
|
|
55002
55298
|
}
|
|
@@ -55034,8 +55330,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
55034
55330
|
var init_coverage = __esm({
|
|
55035
55331
|
"src/coverage.ts"() {
|
|
55036
55332
|
init_native_decode();
|
|
55037
|
-
LEDGER_FILE =
|
|
55038
|
-
OBS_FILE =
|
|
55333
|
+
LEDGER_FILE = join56(".himi", "test-ledger.json");
|
|
55334
|
+
OBS_FILE = join56(".himi", "test-observations.json");
|
|
55039
55335
|
}
|
|
55040
55336
|
});
|
|
55041
55337
|
|
|
@@ -55046,16 +55342,16 @@ __export(design_kits_exports, {
|
|
|
55046
55342
|
kitsDir: () => kitsDir,
|
|
55047
55343
|
listKits: () => listKits2
|
|
55048
55344
|
});
|
|
55049
|
-
import { existsSync as
|
|
55050
|
-
import { join as
|
|
55345
|
+
import { existsSync as existsSync58, readFileSync as readFileSync64, readdirSync as readdirSync29 } from "node:fs";
|
|
55346
|
+
import { join as join57, basename as basename15 } from "node:path";
|
|
55051
55347
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
55052
55348
|
function kitsDir() {
|
|
55053
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
55349
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync58(p));
|
|
55054
55350
|
}
|
|
55055
55351
|
function listKits2() {
|
|
55056
55352
|
const dir = kitsDir();
|
|
55057
55353
|
if (!dir) return [];
|
|
55058
|
-
return
|
|
55354
|
+
return readdirSync29(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
|
|
55059
55355
|
}
|
|
55060
55356
|
function kitReport(name) {
|
|
55061
55357
|
const dir = kitsDir();
|
|
@@ -55074,7 +55370,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
55074
55370
|
if (!kits.includes(name)) {
|
|
55075
55371
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
55076
55372
|
}
|
|
55077
|
-
const raw =
|
|
55373
|
+
const raw = readFileSync64(join57(dir, `${name}.json`), "utf8");
|
|
55078
55374
|
let parsed;
|
|
55079
55375
|
try {
|
|
55080
55376
|
parsed = JSON.parse(raw);
|
|
@@ -55098,9 +55394,9 @@ var init_design_kits = __esm({
|
|
|
55098
55394
|
"src/design-kits.ts"() {
|
|
55099
55395
|
KIT_DIR_CANDIDATES = [
|
|
55100
55396
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
55101
|
-
|
|
55397
|
+
join57(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
55102
55398
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
55103
|
-
|
|
55399
|
+
join57(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
55104
55400
|
];
|
|
55105
55401
|
}
|
|
55106
55402
|
});
|
|
@@ -55114,11 +55410,11 @@ __export(assets_exports, {
|
|
|
55114
55410
|
removeAssetPayload: () => removeAssetPayload,
|
|
55115
55411
|
verifyReport: () => verifyReport
|
|
55116
55412
|
});
|
|
55117
|
-
import { readFileSync as
|
|
55413
|
+
import { readFileSync as readFileSync65 } from "node:fs";
|
|
55118
55414
|
import { basename as basename16 } from "node:path";
|
|
55119
55415
|
function declaredAssets(dir) {
|
|
55120
55416
|
return collectAssets(dir).map((a) => {
|
|
55121
|
-
const bytes2 =
|
|
55417
|
+
const bytes2 = readFileSync65(a.path);
|
|
55122
55418
|
return {
|
|
55123
55419
|
name: a.name,
|
|
55124
55420
|
sha256: assetSha256(bytes2),
|
|
@@ -55195,7 +55491,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
55195
55491
|
};
|
|
55196
55492
|
}
|
|
55197
55493
|
function addAssetPayload(manifest, filePath, opts) {
|
|
55198
|
-
const bytes2 =
|
|
55494
|
+
const bytes2 = readFileSync65(filePath);
|
|
55199
55495
|
const name = opts.name ?? basename16(filePath);
|
|
55200
55496
|
const sha2565 = assetSha256(bytes2);
|
|
55201
55497
|
const record2 = {
|
|
@@ -56919,9 +57215,9 @@ __export(run_exports, {
|
|
|
56919
57215
|
runPackage: () => runPackage,
|
|
56920
57216
|
withoutProdServe: () => withoutProdServe
|
|
56921
57217
|
});
|
|
56922
|
-
import { cpSync as cpSync2, existsSync as
|
|
57218
|
+
import { cpSync as cpSync2, existsSync as existsSync59, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, readFileSync as readFileSync66, rmSync as rmSync14, statSync as statSync15 } from "node:fs";
|
|
56923
57219
|
import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
|
|
56924
|
-
import { dirname as
|
|
57220
|
+
import { dirname as dirname32, join as join58 } from "node:path";
|
|
56925
57221
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
56926
57222
|
function makePackageRunHandler(opts) {
|
|
56927
57223
|
const store = new FileReleaseStore(opts.releaseRoot);
|
|
@@ -56949,9 +57245,9 @@ async function fetchBytes(url) {
|
|
|
56949
57245
|
}
|
|
56950
57246
|
async function resolvePackage(source, workDir) {
|
|
56951
57247
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
56952
|
-
if (!isUrl2 &&
|
|
56953
|
-
const appDirManifest =
|
|
56954
|
-
if (
|
|
57248
|
+
if (!isUrl2 && existsSync59(source) && statSync15(source).isDirectory()) {
|
|
57249
|
+
const appDirManifest = join58(source, "release-manifest.json");
|
|
57250
|
+
if (existsSync59(appDirManifest)) {
|
|
56955
57251
|
const opened2 = openPackageDir(source);
|
|
56956
57252
|
if (!opened2.validation.ok) {
|
|
56957
57253
|
throw new Error(`package is not valid:
|
|
@@ -56960,11 +57256,11 @@ async function resolvePackage(source, workDir) {
|
|
|
56960
57256
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
56961
57257
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
56962
57258
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
56963
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
56964
|
-
const target =
|
|
56965
|
-
if (
|
|
56966
|
-
|
|
56967
|
-
|
|
57259
|
+
const root2 = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
|
|
57260
|
+
const target = join58(root2, app2);
|
|
57261
|
+
if (join58(source) !== target) {
|
|
57262
|
+
mkdirSync28(root2, { recursive: true });
|
|
57263
|
+
rmSync14(target, { recursive: true, force: true });
|
|
56968
57264
|
cpSync2(source, target, { recursive: true });
|
|
56969
57265
|
}
|
|
56970
57266
|
return {
|
|
@@ -56979,12 +57275,12 @@ async function resolvePackage(source, workDir) {
|
|
|
56979
57275
|
}
|
|
56980
57276
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
56981
57277
|
}
|
|
56982
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
56983
|
-
const root = workDir ?? mkdtempSync3(
|
|
57278
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync66(source);
|
|
57279
|
+
const root = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
|
|
56984
57280
|
const { app, appDir: appDir3 } = unpackTo(bytes2, root);
|
|
56985
57281
|
const opened = openPackageDir(appDir3);
|
|
56986
57282
|
if (!opened.validation.ok) {
|
|
56987
|
-
|
|
57283
|
+
rmSync14(workDir ? appDir3 : root, { recursive: true, force: true });
|
|
56988
57284
|
throw new Error(`package is not valid:
|
|
56989
57285
|
${opened.validation.errors.join("\n ")}`);
|
|
56990
57286
|
}
|
|
@@ -57001,16 +57297,16 @@ async function resolvePackage(source, workDir) {
|
|
|
57001
57297
|
async function loadPreviewAssets() {
|
|
57002
57298
|
try {
|
|
57003
57299
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
57004
|
-
const here =
|
|
57300
|
+
const here = dirname32(fileURLToPath24(import.meta.url));
|
|
57005
57301
|
const candidates = [
|
|
57006
|
-
|
|
57302
|
+
join58(here, "preview-assets.generated.bin"),
|
|
57007
57303
|
// published: copied next to the bundled CLI
|
|
57008
|
-
|
|
57304
|
+
join58(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
57009
57305
|
// in-repo checkout
|
|
57010
57306
|
];
|
|
57011
57307
|
for (const path2 of candidates) {
|
|
57012
|
-
if (!
|
|
57013
|
-
const blob =
|
|
57308
|
+
if (!existsSync59(path2)) continue;
|
|
57309
|
+
const blob = readFileSync66(path2);
|
|
57014
57310
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
57015
57311
|
}
|
|
57016
57312
|
return /* @__PURE__ */ new Map();
|
|
@@ -57058,7 +57354,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57058
57354
|
const resolved2 = await resolvePackage(source, opts.workDir);
|
|
57059
57355
|
const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
|
|
57060
57356
|
if (!opts.spa && assets.size === 0) {
|
|
57061
|
-
if (resolved2.temp)
|
|
57357
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57062
57358
|
throw new Error(NO_SPA_MESSAGE);
|
|
57063
57359
|
}
|
|
57064
57360
|
const plane = makePackageRunHandler({
|
|
@@ -57096,7 +57392,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57096
57392
|
lanBound = (await listen(lanServer, port, lanHost)).address;
|
|
57097
57393
|
} catch (e) {
|
|
57098
57394
|
await closeServer(server);
|
|
57099
|
-
if (resolved2.temp)
|
|
57395
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57100
57396
|
throw new Error(`himi run --lan could not listen on ${lanHost}:${port} (${e.message}); drop --lan, or pass --port for a free one`);
|
|
57101
57397
|
}
|
|
57102
57398
|
bound.push(lanBound);
|
|
@@ -57118,7 +57414,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57118
57414
|
warnings: resolved2.warnings,
|
|
57119
57415
|
close: async () => {
|
|
57120
57416
|
await Promise.all(servers.map(closeServer));
|
|
57121
|
-
if (resolved2.temp)
|
|
57417
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57122
57418
|
}
|
|
57123
57419
|
};
|
|
57124
57420
|
}
|
|
@@ -57157,9 +57453,9 @@ __export(run_watch_exports, {
|
|
|
57157
57453
|
watchedContentDir: () => watchedContentDir,
|
|
57158
57454
|
writeRunRecord: () => writeRunRecord
|
|
57159
57455
|
});
|
|
57160
|
-
import { closeSync as closeSync4, constants, existsSync as
|
|
57456
|
+
import { closeSync as closeSync4, constants, existsSync as existsSync60, fstatSync, lstatSync as lstatSync13, statSync as statSync16, mkdirSync as mkdirSync29, openSync as openSync3, readFileSync as readFileSync67, realpathSync as realpathSync9, renameSync as renameSync6, rmSync as rmSync15, writeFileSync as writeFileSync24, watch as fsWatch } from "node:fs";
|
|
57161
57457
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
57162
|
-
import { extname as extname4, join as
|
|
57458
|
+
import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
|
|
57163
57459
|
function diffReleases(prev, next) {
|
|
57164
57460
|
const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
|
|
57165
57461
|
const changedBundles = new Set(bundles);
|
|
@@ -57200,7 +57496,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
57200
57496
|
let timer = null;
|
|
57201
57497
|
const pending = /* @__PURE__ */ new Set();
|
|
57202
57498
|
const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
|
|
57203
|
-
if (!file || ignoredChange(file, (rel) => isDir(
|
|
57499
|
+
if (!file || ignoredChange(file, (rel) => isDir(join59(dir, rel)))) return;
|
|
57204
57500
|
pending.add(file);
|
|
57205
57501
|
if (timer) clearTimeout(timer);
|
|
57206
57502
|
timer = setTimeout(() => {
|
|
@@ -57219,9 +57515,9 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
57219
57515
|
}
|
|
57220
57516
|
function watchedContentDir(source) {
|
|
57221
57517
|
if (!source || /^https?:\/\//i.test(source)) return null;
|
|
57222
|
-
const dir =
|
|
57518
|
+
const dir = resolve47(source);
|
|
57223
57519
|
try {
|
|
57224
|
-
return
|
|
57520
|
+
return statSync16(dir).isDirectory() && existsSync60(join59(dir, "himalaya.content.json")) ? dir : null;
|
|
57225
57521
|
} catch {
|
|
57226
57522
|
return null;
|
|
57227
57523
|
}
|
|
@@ -57278,33 +57574,33 @@ function serialize(task) {
|
|
|
57278
57574
|
});
|
|
57279
57575
|
}
|
|
57280
57576
|
function himiDir(dir) {
|
|
57281
|
-
const root =
|
|
57577
|
+
const root = join59(dir, ".himi");
|
|
57282
57578
|
try {
|
|
57283
|
-
return
|
|
57579
|
+
return lstatSync13(root).isDirectory() ? root : null;
|
|
57284
57580
|
} catch (e) {
|
|
57285
57581
|
if (e.code !== "ENOENT") return null;
|
|
57286
|
-
|
|
57287
|
-
return
|
|
57582
|
+
mkdirSync29(root, { recursive: true });
|
|
57583
|
+
return lstatSync13(root).isDirectory() ? root : null;
|
|
57288
57584
|
}
|
|
57289
57585
|
}
|
|
57290
57586
|
function writeRunRecord(dir, record2) {
|
|
57291
57587
|
const root = himiDir(dir);
|
|
57292
57588
|
if (!root) return false;
|
|
57293
|
-
const tmp =
|
|
57589
|
+
const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
|
|
57294
57590
|
try {
|
|
57295
|
-
|
|
57591
|
+
writeFileSync24(tmp, `${JSON.stringify(record2, null, 2)}
|
|
57296
57592
|
`, { flag: "wx" });
|
|
57297
|
-
renameSync6(tmp,
|
|
57593
|
+
renameSync6(tmp, join59(root, "run.json"));
|
|
57298
57594
|
} catch (e) {
|
|
57299
|
-
|
|
57595
|
+
rmSync15(tmp, { force: true });
|
|
57300
57596
|
throw e;
|
|
57301
57597
|
}
|
|
57302
57598
|
return true;
|
|
57303
57599
|
}
|
|
57304
57600
|
function removeRunRecord(dir, owner) {
|
|
57305
|
-
const root =
|
|
57601
|
+
const root = join59(dir, ".himi");
|
|
57306
57602
|
try {
|
|
57307
|
-
if (!
|
|
57603
|
+
if (!lstatSync13(root).isDirectory()) return;
|
|
57308
57604
|
} catch {
|
|
57309
57605
|
return;
|
|
57310
57606
|
}
|
|
@@ -57317,22 +57613,22 @@ function removeRunRecord(dir, owner) {
|
|
|
57317
57613
|
}
|
|
57318
57614
|
if (typeof pid === "number" && pid !== owner) return;
|
|
57319
57615
|
}
|
|
57320
|
-
|
|
57616
|
+
rmSync15(join59(root, "run.json"), { force: true });
|
|
57321
57617
|
}
|
|
57322
57618
|
function boardFile(dir, pathname) {
|
|
57323
57619
|
if (pathname === RUN_IDENTITY_PATH) {
|
|
57324
57620
|
return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
|
|
57325
57621
|
}
|
|
57326
57622
|
let rel = null;
|
|
57327
|
-
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel =
|
|
57328
|
-
else if (pathname === "/__himi/studio/state.js") rel =
|
|
57329
|
-
else if (pathname === "/__himi/studio/timeline.js") rel =
|
|
57623
|
+
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join59("studio", "index.html");
|
|
57624
|
+
else if (pathname === "/__himi/studio/state.js") rel = join59("studio", "state.js");
|
|
57625
|
+
else if (pathname === "/__himi/studio/timeline.js") rel = join59("studio", "timeline.js");
|
|
57330
57626
|
else {
|
|
57331
57627
|
const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
|
|
57332
|
-
if (m) rel =
|
|
57628
|
+
if (m) rel = join59("history", m[1]);
|
|
57333
57629
|
}
|
|
57334
57630
|
if (!rel) return null;
|
|
57335
|
-
const bytes2 = readConfined(
|
|
57631
|
+
const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
|
|
57336
57632
|
if (!bytes2) return new Response("not found", { status: 404 });
|
|
57337
57633
|
return new Response(bytes2, {
|
|
57338
57634
|
status: 200,
|
|
@@ -57341,20 +57637,20 @@ function boardFile(dir, pathname) {
|
|
|
57341
57637
|
}
|
|
57342
57638
|
function readConfined(root, rel) {
|
|
57343
57639
|
try {
|
|
57344
|
-
if (!
|
|
57345
|
-
const parts = rel.split(
|
|
57640
|
+
if (!lstatSync13(root).isDirectory()) return null;
|
|
57641
|
+
const parts = rel.split(sep16);
|
|
57346
57642
|
let at2 = root;
|
|
57347
57643
|
for (let i = 0; i < parts.length; i++) {
|
|
57348
|
-
at2 =
|
|
57349
|
-
const st =
|
|
57644
|
+
at2 = join59(at2, parts[i]);
|
|
57645
|
+
const st = lstatSync13(at2);
|
|
57350
57646
|
if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
|
|
57351
57647
|
}
|
|
57352
|
-
const canonicalRoot =
|
|
57353
|
-
if (!
|
|
57648
|
+
const canonicalRoot = realpathSync9(root);
|
|
57649
|
+
if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
|
|
57354
57650
|
const fd = openSync3(at2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
57355
57651
|
try {
|
|
57356
57652
|
if (!fstatSync(fd).isFile()) return null;
|
|
57357
|
-
return
|
|
57653
|
+
return readFileSync67(fd);
|
|
57358
57654
|
} finally {
|
|
57359
57655
|
closeSync4(fd);
|
|
57360
57656
|
}
|
|
@@ -57383,7 +57679,7 @@ var init_run_watch = __esm({
|
|
|
57383
57679
|
};
|
|
57384
57680
|
isDir = (path2) => {
|
|
57385
57681
|
try {
|
|
57386
|
-
return
|
|
57682
|
+
return statSync16(path2).isDirectory();
|
|
57387
57683
|
} catch {
|
|
57388
57684
|
return false;
|
|
57389
57685
|
}
|
|
@@ -57407,19 +57703,19 @@ __export(run_browser_exports, {
|
|
|
57407
57703
|
runInBrowser: () => runInBrowser
|
|
57408
57704
|
});
|
|
57409
57705
|
import { createServer as createServer7 } from "node:http";
|
|
57410
|
-
import { existsSync as
|
|
57706
|
+
import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
|
|
57411
57707
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
57412
|
-
import { dirname as
|
|
57708
|
+
import { dirname as dirname33, resolve as resolve48 } from "node:path";
|
|
57413
57709
|
import { fileURLToPath as fileURLToPath25 } from "node:url";
|
|
57414
57710
|
function stagedDir() {
|
|
57415
|
-
return process.env.HIMI_BROWSER_PLANE_OUT ?
|
|
57711
|
+
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve48(process.env.HIMI_BROWSER_PLANE_OUT) : resolve48(REPO, "packages", "serve", "dist", "browser-plane");
|
|
57416
57712
|
}
|
|
57417
57713
|
function missingStaged() {
|
|
57418
|
-
return [...SERVED].filter((f) => !
|
|
57714
|
+
return [...SERVED].filter((f) => !existsSync61(resolve48(stagedDir(), f))).sort();
|
|
57419
57715
|
}
|
|
57420
57716
|
function ensureBrowserPlaneStaged() {
|
|
57421
57717
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
57422
|
-
const r = spawnSync3(process.execPath, [
|
|
57718
|
+
const r = spawnSync3(process.execPath, [resolve48(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
|
|
57423
57719
|
cwd: REPO,
|
|
57424
57720
|
encoding: "utf8"
|
|
57425
57721
|
});
|
|
@@ -57505,7 +57801,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
57505
57801
|
}
|
|
57506
57802
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
57507
57803
|
if (SERVED.has(name)) {
|
|
57508
|
-
if (!
|
|
57804
|
+
if (!existsSync61(resolve48(stagedDir(), name))) {
|
|
57509
57805
|
const restaged = ensureBrowserPlaneStaged();
|
|
57510
57806
|
if (!restaged.ok) {
|
|
57511
57807
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -57515,7 +57811,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
57515
57811
|
}
|
|
57516
57812
|
let bytes2;
|
|
57517
57813
|
try {
|
|
57518
|
-
bytes2 =
|
|
57814
|
+
bytes2 = readFileSync68(resolve48(stagedDir(), name));
|
|
57519
57815
|
} catch (e) {
|
|
57520
57816
|
res.writeHead(503, { "content-type": "application/json" });
|
|
57521
57817
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -57557,8 +57853,8 @@ var init_run_browser = __esm({
|
|
|
57557
57853
|
init_open_url();
|
|
57558
57854
|
init_file_store();
|
|
57559
57855
|
init_wix_client_id();
|
|
57560
|
-
HERE2 =
|
|
57561
|
-
REPO =
|
|
57856
|
+
HERE2 = dirname33(fileURLToPath25(import.meta.url));
|
|
57857
|
+
REPO = resolve48(HERE2, "..", "..", "..");
|
|
57562
57858
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
57563
57859
|
}
|
|
57564
57860
|
});
|
|
@@ -57977,11 +58273,11 @@ __export(preflight_exports, {
|
|
|
57977
58273
|
parseStoreConfig: () => parseStoreConfig,
|
|
57978
58274
|
requireEnv: () => requireEnv
|
|
57979
58275
|
});
|
|
57980
|
-
import { existsSync as
|
|
57981
|
-
import { isAbsolute as
|
|
58276
|
+
import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
|
|
58277
|
+
import { isAbsolute as isAbsolute6, relative as relative13, resolve as resolve49 } from "node:path";
|
|
57982
58278
|
function isInsideRepo(p) {
|
|
57983
|
-
const rel =
|
|
57984
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
58279
|
+
const rel = relative13(REPO_ROOT3, resolve49(p));
|
|
58280
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute6(rel);
|
|
57985
58281
|
}
|
|
57986
58282
|
function assertCredentialOutsideRepo(label2, p) {
|
|
57987
58283
|
if (isInsideRepo(p)) {
|
|
@@ -58034,10 +58330,10 @@ function parseStoreConfig(text8) {
|
|
|
58034
58330
|
}
|
|
58035
58331
|
function loadStoreConfig(app) {
|
|
58036
58332
|
const p = storeConfigPath(app);
|
|
58037
|
-
if (!
|
|
58333
|
+
if (!existsSync62(p)) {
|
|
58038
58334
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
58039
58335
|
}
|
|
58040
|
-
return parseStoreConfig(
|
|
58336
|
+
return parseStoreConfig(readFileSync69(p, "utf8"));
|
|
58041
58337
|
}
|
|
58042
58338
|
var init_preflight = __esm({
|
|
58043
58339
|
"../store-release/preflight.ts"() {
|
|
@@ -58056,19 +58352,19 @@ __export(credential_profile_exports, {
|
|
|
58056
58352
|
profilePath: () => profilePath,
|
|
58057
58353
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
58058
58354
|
});
|
|
58059
|
-
import { existsSync as
|
|
58355
|
+
import { existsSync as existsSync63, readFileSync as readFileSync70 } from "node:fs";
|
|
58060
58356
|
import { homedir as homedir5 } from "node:os";
|
|
58061
|
-
import { join as
|
|
58357
|
+
import { join as join60 } from "node:path";
|
|
58062
58358
|
function credentialsDir(home = homedir5()) {
|
|
58063
|
-
return
|
|
58359
|
+
return join60(home, ".himalaya", "store-credentials");
|
|
58064
58360
|
}
|
|
58065
58361
|
function profilePath(name, home = homedir5()) {
|
|
58066
58362
|
if (!PROFILE_NAME.test(name)) {
|
|
58067
58363
|
throw new Error(
|
|
58068
|
-
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${
|
|
58364
|
+
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join60(credentialsDir(home), "<name>.json")}; it is never a path.`
|
|
58069
58365
|
);
|
|
58070
58366
|
}
|
|
58071
|
-
return
|
|
58367
|
+
return join60(credentialsDir(home), `${name}.json`);
|
|
58072
58368
|
}
|
|
58073
58369
|
function parseProfile(text8, label2) {
|
|
58074
58370
|
let doc;
|
|
@@ -58099,8 +58395,8 @@ function resolveStoreCredentials(opts) {
|
|
|
58099
58395
|
const { app, cfg } = opts;
|
|
58100
58396
|
const env = opts.env ?? process.env;
|
|
58101
58397
|
const home = opts.home ?? homedir5();
|
|
58102
|
-
const read = opts.readProfile ?? ((p) =>
|
|
58103
|
-
const exists = opts.profileExists ??
|
|
58398
|
+
const read = opts.readProfile ?? ((p) => readFileSync70(p, "utf8"));
|
|
58399
|
+
const exists = opts.profileExists ?? existsSync63;
|
|
58104
58400
|
const ios = cfg.ios ?? {};
|
|
58105
58401
|
const flagName = opts.profileFlag?.trim();
|
|
58106
58402
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -58180,9 +58476,9 @@ __export(preflight_app_exports, {
|
|
|
58180
58476
|
preflightApp: () => preflightApp,
|
|
58181
58477
|
profileAccount: () => profileAccount
|
|
58182
58478
|
});
|
|
58183
|
-
import { readFileSync as
|
|
58479
|
+
import { readFileSync as readFileSync71, existsSync as existsSync64, readdirSync as readdirSync30, statSync as statSync17 } from "node:fs";
|
|
58184
58480
|
import { createHash as createHash30 } from "node:crypto";
|
|
58185
|
-
import { join as
|
|
58481
|
+
import { join as join61 } from "node:path";
|
|
58186
58482
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
58187
58483
|
const f = [];
|
|
58188
58484
|
const has = (re, s) => re.test(s);
|
|
@@ -58246,13 +58542,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
58246
58542
|
}
|
|
58247
58543
|
}
|
|
58248
58544
|
async function preflightApp(app, opts = {}) {
|
|
58249
|
-
const projectYml =
|
|
58250
|
-
const storeConfig =
|
|
58545
|
+
const projectYml = existsSync64(iosProjectYml(app)) ? readFileSync71(iosProjectYml(app), "utf8") : "";
|
|
58546
|
+
const storeConfig = existsSync64(storeConfigPath(app)) ? readFileSync71(storeConfigPath(app), "utf8") : "";
|
|
58251
58547
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
58252
58548
|
const findings = analyze(
|
|
58253
58549
|
projectYml,
|
|
58254
58550
|
storeConfig,
|
|
58255
|
-
await appIconState(
|
|
58551
|
+
await appIconState(join61(appDir(app), "ios")),
|
|
58256
58552
|
profileAccount(app, storeConfig, opts)
|
|
58257
58553
|
);
|
|
58258
58554
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -58281,18 +58577,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
58281
58577
|
return f;
|
|
58282
58578
|
}
|
|
58283
58579
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
58284
|
-
const root =
|
|
58580
|
+
const root = join61(storeDir(app), "metadata");
|
|
58285
58581
|
const out2 = /* @__PURE__ */ new Set();
|
|
58286
|
-
if (
|
|
58287
|
-
for (const n of
|
|
58582
|
+
if (existsSync64(root)) {
|
|
58583
|
+
for (const n of readdirSync30(root)) if (n.endsWith(".txt")) out2.add(n);
|
|
58288
58584
|
}
|
|
58289
|
-
if (
|
|
58585
|
+
if (existsSync64(join61(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
|
|
58290
58586
|
return out2;
|
|
58291
58587
|
}
|
|
58292
58588
|
function reviewInfoFiles(app) {
|
|
58293
|
-
const dir =
|
|
58294
|
-
if (!
|
|
58295
|
-
return new Set(
|
|
58589
|
+
const dir = join61(storeDir(app), "review_information");
|
|
58590
|
+
if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
|
|
58591
|
+
return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
|
|
58296
58592
|
}
|
|
58297
58593
|
function isValidAppStoreSize(w, h) {
|
|
58298
58594
|
return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
|
|
@@ -58401,12 +58697,12 @@ function analyzePlayListing(assets) {
|
|
|
58401
58697
|
return f;
|
|
58402
58698
|
}
|
|
58403
58699
|
function playListingAssets(app, locale = "en-US") {
|
|
58404
|
-
const dir =
|
|
58700
|
+
const dir = join61(storeDir(app), "play", locale, "images");
|
|
58405
58701
|
const read = (names) => {
|
|
58406
58702
|
for (const name of names) {
|
|
58407
|
-
const p =
|
|
58703
|
+
const p = join61(dir, name);
|
|
58408
58704
|
try {
|
|
58409
|
-
if (
|
|
58705
|
+
if (statSync17(p).isFile()) return { name, bytes: readFileSync71(p) };
|
|
58410
58706
|
} catch {
|
|
58411
58707
|
}
|
|
58412
58708
|
}
|
|
@@ -58437,26 +58733,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
58437
58733
|
return f;
|
|
58438
58734
|
}
|
|
58439
58735
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
58440
|
-
const dir =
|
|
58441
|
-
if (!
|
|
58442
|
-
return new Set(
|
|
58736
|
+
const dir = join61(storeDir(app), "metadata", locale);
|
|
58737
|
+
if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
|
|
58738
|
+
return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
|
|
58443
58739
|
}
|
|
58444
58740
|
function listScreenshots(app, locale = "en-US") {
|
|
58445
58741
|
const out2 = [];
|
|
58446
|
-
const flat =
|
|
58447
|
-
if (
|
|
58448
|
-
for (const png of
|
|
58449
|
-
const sz = pngSize(
|
|
58742
|
+
const flat = join61(storeDir(app), "screenshots", locale);
|
|
58743
|
+
if (existsSync64(flat)) {
|
|
58744
|
+
for (const png of readdirSync30(flat).filter((n) => n.endsWith(".png"))) {
|
|
58745
|
+
const sz = pngSize(readFileSync71(join61(flat, png)));
|
|
58450
58746
|
if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
|
|
58451
58747
|
}
|
|
58452
58748
|
}
|
|
58453
|
-
const legacy =
|
|
58454
|
-
if (
|
|
58455
|
-
for (const deviceDir of
|
|
58456
|
-
const d =
|
|
58457
|
-
if (!
|
|
58458
|
-
for (const png of
|
|
58459
|
-
const sz = pngSize(
|
|
58749
|
+
const legacy = join61(storeDir(app), "metadata", locale, "screenshots");
|
|
58750
|
+
if (existsSync64(legacy)) {
|
|
58751
|
+
for (const deviceDir of readdirSync30(legacy)) {
|
|
58752
|
+
const d = join61(legacy, deviceDir);
|
|
58753
|
+
if (!statSync17(d).isDirectory()) continue;
|
|
58754
|
+
for (const png of readdirSync30(d).filter((n) => n.endsWith(".png"))) {
|
|
58755
|
+
const sz = pngSize(readFileSync71(join61(d, png)));
|
|
58460
58756
|
if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
58461
58757
|
}
|
|
58462
58758
|
}
|
|
@@ -58464,13 +58760,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
58464
58760
|
return out2;
|
|
58465
58761
|
}
|
|
58466
58762
|
function placeholderHashes2() {
|
|
58467
|
-
const templateIos =
|
|
58468
|
-
if (!
|
|
58469
|
-
for (const target of
|
|
58470
|
-
const p =
|
|
58763
|
+
const templateIos = join61(appDir("_template"), "ios");
|
|
58764
|
+
if (!existsSync64(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
58765
|
+
for (const target of readdirSync30(templateIos)) {
|
|
58766
|
+
const p = join61(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
58471
58767
|
try {
|
|
58472
|
-
if (!
|
|
58473
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(
|
|
58768
|
+
if (!statSync17(p).isFile()) continue;
|
|
58769
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync71(p)).digest("hex")];
|
|
58474
58770
|
} catch {
|
|
58475
58771
|
}
|
|
58476
58772
|
}
|
|
@@ -58501,12 +58797,12 @@ async function pixelIssues(bytes2) {
|
|
|
58501
58797
|
}
|
|
58502
58798
|
}
|
|
58503
58799
|
async function appIconState(iosDir) {
|
|
58504
|
-
if (!
|
|
58505
|
-
for (const target of
|
|
58506
|
-
const p =
|
|
58800
|
+
if (!existsSync64(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
58801
|
+
for (const target of readdirSync30(iosDir)) {
|
|
58802
|
+
const p = join61(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
58507
58803
|
try {
|
|
58508
|
-
if (!
|
|
58509
|
-
const bytes2 =
|
|
58804
|
+
if (!statSync17(p).isFile()) continue;
|
|
58805
|
+
const bytes2 = readFileSync71(p);
|
|
58510
58806
|
const hash = createHash30("sha256").update(bytes2).digest("hex");
|
|
58511
58807
|
const pixels = await pixelIssues(bytes2);
|
|
58512
58808
|
return {
|
|
@@ -58578,7 +58874,7 @@ __export(version_exports, {
|
|
|
58578
58874
|
setAndroidVersion: () => setAndroidVersion,
|
|
58579
58875
|
setIosVersion: () => setIosVersion
|
|
58580
58876
|
});
|
|
58581
|
-
import { readFileSync as
|
|
58877
|
+
import { readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
|
|
58582
58878
|
function readIosVersion(projectYml) {
|
|
58583
58879
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
58584
58880
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -58636,15 +58932,15 @@ function setAndroidVersion(gradle, v) {
|
|
|
58636
58932
|
function bumpVersion(app, opts) {
|
|
58637
58933
|
const iosPath = iosProjectYml(app);
|
|
58638
58934
|
const gradlePath = androidGradle(app);
|
|
58639
|
-
const iosYml =
|
|
58640
|
-
const gradle =
|
|
58935
|
+
const iosYml = readFileSync72(iosPath, "utf8");
|
|
58936
|
+
const gradle = readFileSync72(gradlePath, "utf8");
|
|
58641
58937
|
const current = readIosVersion(iosYml);
|
|
58642
58938
|
const next = {
|
|
58643
58939
|
marketing: opts.marketing ?? current.marketing,
|
|
58644
58940
|
build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
|
|
58645
58941
|
};
|
|
58646
|
-
|
|
58647
|
-
|
|
58942
|
+
writeFileSync25(iosPath, setIosVersion(iosYml, next));
|
|
58943
|
+
writeFileSync25(gradlePath, setAndroidVersion(gradle, next));
|
|
58648
58944
|
return next;
|
|
58649
58945
|
}
|
|
58650
58946
|
var init_version = __esm({
|
|
@@ -58654,7 +58950,7 @@ var init_version = __esm({
|
|
|
58654
58950
|
});
|
|
58655
58951
|
|
|
58656
58952
|
// ../store-release/register-bundle.ts
|
|
58657
|
-
import { readFileSync as
|
|
58953
|
+
import { readFileSync as readFileSync73 } from "node:fs";
|
|
58658
58954
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
58659
58955
|
function b64url2(b) {
|
|
58660
58956
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -58672,7 +58968,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
58672
58968
|
async function registerBundleId(opts) {
|
|
58673
58969
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
58674
58970
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
58675
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
58971
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
58676
58972
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
58677
58973
|
method: "POST",
|
|
58678
58974
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -58726,7 +59022,7 @@ __export(asc_status_exports, {
|
|
|
58726
59022
|
ascStatus: () => ascStatus,
|
|
58727
59023
|
buildVerdict: () => buildVerdict
|
|
58728
59024
|
});
|
|
58729
|
-
import { readFileSync as
|
|
59025
|
+
import { readFileSync as readFileSync74 } from "node:fs";
|
|
58730
59026
|
function buildVerdict(builds) {
|
|
58731
59027
|
if (!builds.length) {
|
|
58732
59028
|
return "NO builds registered \u2014 if you uploaded recently and it's been >15 min, the binary was REJECTED IN PROCESSING (reason is email-only; run validate-binary.ts / scan-purpose-strings.ts to reproduce it).";
|
|
@@ -58740,7 +59036,7 @@ function buildVerdict(builds) {
|
|
|
58740
59036
|
function client(creds) {
|
|
58741
59037
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
58742
59038
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
58743
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
59039
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync74(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
58744
59040
|
return async (path2) => {
|
|
58745
59041
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
58746
59042
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -58789,7 +59085,7 @@ var init_asc_status = __esm({
|
|
|
58789
59085
|
// ../../core/functions-secrets/src/vault.ts
|
|
58790
59086
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
|
|
58791
59087
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
58792
|
-
import { dirname as
|
|
59088
|
+
import { dirname as dirname34 } from "node:path";
|
|
58793
59089
|
function createJsonSecretStore(filePath) {
|
|
58794
59090
|
const read = async () => {
|
|
58795
59091
|
try {
|
|
@@ -58802,7 +59098,7 @@ function createJsonSecretStore(filePath) {
|
|
|
58802
59098
|
}
|
|
58803
59099
|
};
|
|
58804
59100
|
const write2 = async (records) => {
|
|
58805
|
-
await mkdir(
|
|
59101
|
+
await mkdir(dirname34(filePath), { recursive: true });
|
|
58806
59102
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
58807
59103
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
58808
59104
|
`, { mode: 384 });
|
|
@@ -58900,7 +59196,7 @@ __export(secrets_exports, {
|
|
|
58900
59196
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
58901
59197
|
runSecretsCommand: () => runSecretsCommand
|
|
58902
59198
|
});
|
|
58903
|
-
import { readFileSync as
|
|
59199
|
+
import { readFileSync as readFileSync75 } from "node:fs";
|
|
58904
59200
|
function environment(value) {
|
|
58905
59201
|
if (value === "preview" || value === "production") return value;
|
|
58906
59202
|
throw new Error("--environment must be preview or production");
|
|
@@ -58931,7 +59227,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
58931
59227
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
58932
59228
|
return 0;
|
|
58933
59229
|
}
|
|
58934
|
-
const value = options.readValue ? options.readValue() :
|
|
59230
|
+
const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
|
|
58935
59231
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
58936
59232
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
58937
59233
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -58960,7 +59256,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
58960
59256
|
}
|
|
58961
59257
|
let body;
|
|
58962
59258
|
if (operation !== "list") {
|
|
58963
|
-
const value = options.readValue ? options.readValue() :
|
|
59259
|
+
const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
|
|
58964
59260
|
body = JSON.stringify({ value });
|
|
58965
59261
|
}
|
|
58966
59262
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -59097,29 +59393,29 @@ __export(notify_ping_exports, {
|
|
|
59097
59393
|
runNotifyPing: () => runNotifyPing
|
|
59098
59394
|
});
|
|
59099
59395
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
59100
|
-
import { resolve as
|
|
59101
|
-
function
|
|
59396
|
+
import { resolve as resolve50 } from "node:path";
|
|
59397
|
+
function refuse5(io, error, hint, exit = 2, extra = {}) {
|
|
59102
59398
|
io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
|
|
59103
59399
|
return exit;
|
|
59104
59400
|
}
|
|
59105
59401
|
async function runNotifyPing(flags, io, deps = {}) {
|
|
59106
59402
|
const flagError = flagRefusal(flags);
|
|
59107
|
-
if (flagError) return
|
|
59108
|
-
const input = mergePushInputs(pushInputsFromContent(
|
|
59403
|
+
if (flagError) return refuse5(io, flagError);
|
|
59404
|
+
const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
|
|
59109
59405
|
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
|
|
59110
|
-
if (missing.length) return
|
|
59406
|
+
if (missing.length) return refuse5(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
|
|
59111
59407
|
const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
|
|
59112
|
-
if (!UUID_RE.test(requestId2)) return
|
|
59408
|
+
if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
|
|
59113
59409
|
const owner = await hostedOwnerSession(flags, deps);
|
|
59114
|
-
if (!owner.ok) return
|
|
59410
|
+
if (!owner.ok) return refuse5(io, owner.error, owner.hint, owner.exit);
|
|
59115
59411
|
const { session } = owner;
|
|
59116
59412
|
const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
|
|
59117
|
-
if (ownership.state !== "owned") return
|
|
59413
|
+
if (ownership.state !== "owned") return refuse5(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
|
|
59118
59414
|
let siteToken2;
|
|
59119
59415
|
try {
|
|
59120
59416
|
siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
|
|
59121
59417
|
} catch {
|
|
59122
|
-
return
|
|
59418
|
+
return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
|
|
59123
59419
|
}
|
|
59124
59420
|
const body = {
|
|
59125
59421
|
app: ownership.slug,
|
|
@@ -59142,12 +59438,12 @@ function flagRefusal(flags) {
|
|
|
59142
59438
|
function report2(http, sent, flags, io) {
|
|
59143
59439
|
const code = refusalCode(http);
|
|
59144
59440
|
if (code === "send_outcome_unknown") {
|
|
59145
|
-
return
|
|
59441
|
+
return refuse5(io, code, `Ping may have accepted it. Re-run the same command with --request-id ${sent.requestId}: Ping runs one request at most once per site for 24 hours.`, 1, { requestId: sent.requestId });
|
|
59146
59442
|
}
|
|
59147
59443
|
if (code === "rate_limited" && http.retryAfterSec) {
|
|
59148
|
-
return
|
|
59444
|
+
return refuse5(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
|
|
59149
59445
|
}
|
|
59150
|
-
if (code) return
|
|
59446
|
+
if (code) return refuse5(io, code, HINTS[code], 1);
|
|
59151
59447
|
if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
|
|
59152
59448
|
else io.log(summary(http.body ?? {}, sent));
|
|
59153
59449
|
return 0;
|
|
@@ -59207,15 +59503,15 @@ __export(notify_exports, {
|
|
|
59207
59503
|
runNotify: () => runNotify,
|
|
59208
59504
|
saveAdminSession: () => saveAdminSession
|
|
59209
59505
|
});
|
|
59210
|
-
import { chmodSync as chmodSync3, mkdirSync as
|
|
59506
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync26 } from "node:fs";
|
|
59211
59507
|
import { homedir as homedir6 } from "node:os";
|
|
59212
|
-
import { dirname as
|
|
59508
|
+
import { dirname as dirname35, join as join62 } from "node:path";
|
|
59213
59509
|
function defaultSessionsPath() {
|
|
59214
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
59510
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join62(homedir6(), ".himalaya", "admin-sessions.json");
|
|
59215
59511
|
}
|
|
59216
59512
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
59217
59513
|
try {
|
|
59218
|
-
return JSON.parse(
|
|
59514
|
+
return JSON.parse(readFileSync76(path2, "utf8"));
|
|
59219
59515
|
} catch {
|
|
59220
59516
|
return {};
|
|
59221
59517
|
}
|
|
@@ -59223,10 +59519,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
59223
59519
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
59224
59520
|
const file = loadSessionsFile(path2);
|
|
59225
59521
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
59226
|
-
|
|
59227
|
-
|
|
59522
|
+
mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
|
|
59523
|
+
writeFileSync26(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
59228
59524
|
try {
|
|
59229
|
-
chmodSync3(
|
|
59525
|
+
chmodSync3(dirname35(path2), 448);
|
|
59230
59526
|
chmodSync3(path2, 384);
|
|
59231
59527
|
} catch {
|
|
59232
59528
|
}
|
|
@@ -61826,10 +62122,10 @@ function assertPublicSiteUrl(raw) {
|
|
|
61826
62122
|
if (refusal) throw new Error(refusal);
|
|
61827
62123
|
}
|
|
61828
62124
|
function resolveAll(hostname2) {
|
|
61829
|
-
return new Promise((
|
|
62125
|
+
return new Promise((resolve54, reject) => {
|
|
61830
62126
|
dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
|
|
61831
62127
|
if (err) reject(err);
|
|
61832
|
-
else
|
|
62128
|
+
else resolve54(addresses);
|
|
61833
62129
|
});
|
|
61834
62130
|
});
|
|
61835
62131
|
}
|
|
@@ -61837,13 +62133,13 @@ function withAbort(start, signal, what) {
|
|
|
61837
62133
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
61838
62134
|
const work = start();
|
|
61839
62135
|
if (!signal) return work;
|
|
61840
|
-
return new Promise((
|
|
62136
|
+
return new Promise((resolve54, reject) => {
|
|
61841
62137
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
61842
62138
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
61843
|
-
work.then(
|
|
62139
|
+
work.then(resolve54, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
61844
62140
|
});
|
|
61845
62141
|
}
|
|
61846
|
-
async function pinAddress(url,
|
|
62142
|
+
async function pinAddress(url, resolve54 = resolveAll, signal) {
|
|
61847
62143
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
61848
62144
|
if (ipv4Octets(host)) {
|
|
61849
62145
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -61853,7 +62149,7 @@ async function pinAddress(url, resolve53 = resolveAll, signal) {
|
|
|
61853
62149
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
61854
62150
|
return { address: host, family: 6 };
|
|
61855
62151
|
}
|
|
61856
|
-
const addresses = await withAbort(() =>
|
|
62152
|
+
const addresses = await withAbort(() => resolve54(host), signal, `${host} lookup`);
|
|
61857
62153
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
61858
62154
|
const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
|
|
61859
62155
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -61893,7 +62189,7 @@ function copyIncomingHeaders(headers2) {
|
|
|
61893
62189
|
return out2;
|
|
61894
62190
|
}
|
|
61895
62191
|
function requestOnce(url, pinned, init) {
|
|
61896
|
-
return new Promise((
|
|
62192
|
+
return new Promise((resolve54, reject) => {
|
|
61897
62193
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
61898
62194
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
61899
62195
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -61923,7 +62219,7 @@ function requestOnce(url, pinned, init) {
|
|
|
61923
62219
|
reject(err);
|
|
61924
62220
|
return;
|
|
61925
62221
|
}
|
|
61926
|
-
|
|
62222
|
+
resolve54(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
|
|
61927
62223
|
}
|
|
61928
62224
|
);
|
|
61929
62225
|
req.on("error", reject);
|
|
@@ -62983,8 +63279,8 @@ var init_brand_font = __esm({
|
|
|
62983
63279
|
});
|
|
62984
63280
|
|
|
62985
63281
|
// src/site-analyze/write-artifacts.ts
|
|
62986
|
-
import { mkdirSync as
|
|
62987
|
-
import { join as
|
|
63282
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
|
|
63283
|
+
import { join as join63 } from "node:path";
|
|
62988
63284
|
function attachVeloSources(book, sources, put) {
|
|
62989
63285
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
62990
63286
|
for (const f of book.velo.files) {
|
|
@@ -63139,13 +63435,13 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
63139
63435
|
}
|
|
63140
63436
|
async function writeBusinessBook(result, opts) {
|
|
63141
63437
|
const out2 = opts.outDir;
|
|
63142
|
-
|
|
63143
|
-
|
|
63438
|
+
mkdirSync31(join63(out2, "evidence/pages"), { recursive: true });
|
|
63439
|
+
mkdirSync31(join63(out2, "media/catalog"), { recursive: true });
|
|
63144
63440
|
const files = [];
|
|
63145
63441
|
const put = (rel, body) => {
|
|
63146
|
-
const p =
|
|
63147
|
-
|
|
63148
|
-
|
|
63442
|
+
const p = join63(out2, rel);
|
|
63443
|
+
mkdirSync31(join63(p, ".."), { recursive: true });
|
|
63444
|
+
writeFileSync27(p, body);
|
|
63149
63445
|
files.push(rel);
|
|
63150
63446
|
};
|
|
63151
63447
|
const book = result.book;
|
|
@@ -63238,15 +63534,15 @@ var init_customer_build = __esm({
|
|
|
63238
63534
|
});
|
|
63239
63535
|
|
|
63240
63536
|
// src/site-analyze/apply.ts
|
|
63241
|
-
import { existsSync as
|
|
63242
|
-
import { dirname as
|
|
63537
|
+
import { existsSync as existsSync65, readFileSync as readFileSync77, writeFileSync as writeFileSync28, copyFileSync as copyFileSync3, mkdirSync as mkdirSync32, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
|
|
63538
|
+
import { dirname as dirname36, isAbsolute as isAbsolute7, join as join64, resolve as resolve51, sep as sep17 } from "node:path";
|
|
63243
63539
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
63244
63540
|
function unpairedRedirectNote(overlay) {
|
|
63245
63541
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
63246
63542
|
return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
|
|
63247
63543
|
}
|
|
63248
63544
|
function posix3(p) {
|
|
63249
|
-
return
|
|
63545
|
+
return resolve51(p).replace(/\\/g, "/");
|
|
63250
63546
|
}
|
|
63251
63547
|
function committedShellProvisioning(path2) {
|
|
63252
63548
|
return committedShellFor(posix3(path2));
|
|
@@ -63254,8 +63550,8 @@ function committedShellProvisioning(path2) {
|
|
|
63254
63550
|
function findRepoRoot(cwd) {
|
|
63255
63551
|
let dir = cwd;
|
|
63256
63552
|
for (let i = 0; i < 8; i++) {
|
|
63257
|
-
if (SHELL_NAMES2.some((name) =>
|
|
63258
|
-
const next =
|
|
63553
|
+
if (SHELL_NAMES2.some((name) => existsSync65(join64(dir, shellAppDir(name), "package.json")))) return dir;
|
|
63554
|
+
const next = dirname36(dir);
|
|
63259
63555
|
if (next === dir) break;
|
|
63260
63556
|
dir = next;
|
|
63261
63557
|
}
|
|
@@ -63280,7 +63576,7 @@ function assertNotCommitted(path2, forbidden) {
|
|
|
63280
63576
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
63281
63577
|
);
|
|
63282
63578
|
}
|
|
63283
|
-
if (forbidden &&
|
|
63579
|
+
if (forbidden && resolve51(path2) === resolve51(forbidden)) {
|
|
63284
63580
|
const named = committedShellProvisioning(forbidden);
|
|
63285
63581
|
throw new Error(
|
|
63286
63582
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -63325,36 +63621,36 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
63325
63621
|
}
|
|
63326
63622
|
function buildMergedContract(options) {
|
|
63327
63623
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
63328
|
-
const committedPath =
|
|
63329
|
-
if (!
|
|
63624
|
+
const committedPath = join64(appDir3, "provisioning.json");
|
|
63625
|
+
if (!existsSync65(committedPath)) {
|
|
63330
63626
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
63331
63627
|
}
|
|
63332
|
-
const committed = JSON.parse(
|
|
63628
|
+
const committed = JSON.parse(readFileSync77(committedPath, "utf8"));
|
|
63333
63629
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
63334
63630
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
63335
63631
|
const branding = merged.branding ?? {};
|
|
63336
63632
|
const staged = [];
|
|
63337
63633
|
const contained = (root, rel) => {
|
|
63338
|
-
if (
|
|
63339
|
-
const full =
|
|
63340
|
-
return full.startsWith(
|
|
63634
|
+
if (isAbsolute7(rel)) return void 0;
|
|
63635
|
+
const full = resolve51(root, rel);
|
|
63636
|
+
return full.startsWith(resolve51(root) + sep17) ? full : void 0;
|
|
63341
63637
|
};
|
|
63342
63638
|
const stage = (fromRel, toRel) => {
|
|
63343
63639
|
const from = contained(packageDir, fromRel);
|
|
63344
|
-
const to = contained(
|
|
63345
|
-
if (!from || !to || !
|
|
63640
|
+
const to = contained(join64(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
63641
|
+
if (!from || !to || !existsSync65(from)) return void 0;
|
|
63346
63642
|
let real;
|
|
63347
63643
|
let realRoot;
|
|
63348
63644
|
try {
|
|
63349
|
-
real =
|
|
63350
|
-
realRoot =
|
|
63645
|
+
real = realpathSync10(from);
|
|
63646
|
+
realRoot = realpathSync10(packageDir);
|
|
63351
63647
|
} catch {
|
|
63352
63648
|
return void 0;
|
|
63353
63649
|
}
|
|
63354
|
-
if (!real.startsWith(realRoot +
|
|
63650
|
+
if (!real.startsWith(realRoot + sep17)) return void 0;
|
|
63355
63651
|
try {
|
|
63356
|
-
if (!
|
|
63357
|
-
|
|
63652
|
+
if (!statSync18(real).isFile()) return void 0;
|
|
63653
|
+
mkdirSync32(dirname36(to), { recursive: true });
|
|
63358
63654
|
copyFileSync3(real, to);
|
|
63359
63655
|
} catch {
|
|
63360
63656
|
return void 0;
|
|
@@ -63364,11 +63660,11 @@ function buildMergedContract(options) {
|
|
|
63364
63660
|
};
|
|
63365
63661
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
63366
63662
|
if (icon) branding.appIconPath = icon;
|
|
63367
|
-
const facesPath =
|
|
63368
|
-
if (
|
|
63663
|
+
const facesPath = join64(packageDir, "media/fonts/faces.json");
|
|
63664
|
+
if (existsSync65(facesPath)) {
|
|
63369
63665
|
let faces = [];
|
|
63370
63666
|
try {
|
|
63371
|
-
const parsed = JSON.parse(
|
|
63667
|
+
const parsed = JSON.parse(readFileSync77(facesPath, "utf8"));
|
|
63372
63668
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
63373
63669
|
} catch {
|
|
63374
63670
|
faces = [];
|
|
@@ -63389,11 +63685,11 @@ function buildMergedContract(options) {
|
|
|
63389
63685
|
merged.branding = branding;
|
|
63390
63686
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
63391
63687
|
`;
|
|
63392
|
-
const path2 =
|
|
63393
|
-
|
|
63394
|
-
const localPath =
|
|
63395
|
-
|
|
63396
|
-
|
|
63688
|
+
const path2 = join64(packageDir, "provisioning.contract.json");
|
|
63689
|
+
writeFileSync28(path2, body);
|
|
63690
|
+
const localPath = join64(appDir3, LOCAL_CONTRACT_REL);
|
|
63691
|
+
mkdirSync32(dirname36(localPath), { recursive: true });
|
|
63692
|
+
writeFileSync28(localPath, body);
|
|
63397
63693
|
staged.push(localPath);
|
|
63398
63694
|
return { path: path2, staged };
|
|
63399
63695
|
}
|
|
@@ -63426,10 +63722,10 @@ function catalogTypography(overlay, template) {
|
|
|
63426
63722
|
function staticFaqFor(overlay, overlayPath) {
|
|
63427
63723
|
const own3 = overlay.faq;
|
|
63428
63724
|
if (own3 !== void 0) return deriveStaticFaq(own3);
|
|
63429
|
-
const bookPath =
|
|
63430
|
-
if (!
|
|
63725
|
+
const bookPath = join64(dirname36(resolve51(overlayPath)), "book.json");
|
|
63726
|
+
if (!existsSync65(bookPath)) return void 0;
|
|
63431
63727
|
try {
|
|
63432
|
-
const book = JSON.parse(
|
|
63728
|
+
const book = JSON.parse(readFileSync77(bookPath, "utf8"));
|
|
63433
63729
|
const copy = book?.copy;
|
|
63434
63730
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
63435
63731
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -63440,11 +63736,11 @@ function staticFaqFor(overlay, overlayPath) {
|
|
|
63440
63736
|
}
|
|
63441
63737
|
}
|
|
63442
63738
|
async function applyOverlays(input) {
|
|
63443
|
-
const cwd =
|
|
63739
|
+
const cwd = resolve51(input.cwd);
|
|
63444
63740
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
63445
63741
|
assertKnownShell(shell);
|
|
63446
|
-
const overlay = JSON.parse(
|
|
63447
|
-
const tokens = JSON.parse(
|
|
63742
|
+
const overlay = JSON.parse(readFileSync77(input.overlayPath, "utf8"));
|
|
63743
|
+
const tokens = JSON.parse(readFileSync77(input.tokensPath, "utf8"));
|
|
63448
63744
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
63449
63745
|
if (faq !== void 0) overlay.faq = faq;
|
|
63450
63746
|
const wrote = [];
|
|
@@ -63456,15 +63752,15 @@ async function applyOverlays(input) {
|
|
|
63456
63752
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
63457
63753
|
);
|
|
63458
63754
|
}
|
|
63459
|
-
const appDir3 =
|
|
63460
|
-
const committedPath =
|
|
63461
|
-
const committedSite =
|
|
63755
|
+
const appDir3 = join64(repoRoot2, shellAppDir(shell));
|
|
63756
|
+
const committedPath = join64(appDir3, "provisioning.json");
|
|
63757
|
+
const committedSite = existsSync65(committedPath) ? JSON.parse(readFileSync77(committedPath, "utf8")).site : void 0;
|
|
63462
63758
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
63463
63759
|
throw new Error(
|
|
63464
63760
|
`shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
|
|
63465
63761
|
);
|
|
63466
63762
|
}
|
|
63467
|
-
const packageDir =
|
|
63763
|
+
const packageDir = dirname36(resolve51(input.overlayPath));
|
|
63468
63764
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
|
|
63469
63765
|
wrote.push(...staged);
|
|
63470
63766
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -63485,22 +63781,22 @@ async function applyOverlays(input) {
|
|
|
63485
63781
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
63486
63782
|
};
|
|
63487
63783
|
}
|
|
63488
|
-
const pkgProv =
|
|
63784
|
+
const pkgProv = join64(cwd, "provisioning.json");
|
|
63489
63785
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
63490
63786
|
let packageFaq = faq;
|
|
63491
|
-
if (
|
|
63492
|
-
const cur = JSON.parse(
|
|
63787
|
+
if (existsSync65(pkgProv)) {
|
|
63788
|
+
const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
|
|
63493
63789
|
const merged = deepMerge4(cur, overlay);
|
|
63494
63790
|
packageFaq = merged.faq;
|
|
63495
|
-
|
|
63791
|
+
writeFileSync28(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
63496
63792
|
wrote.push(pkgProv);
|
|
63497
63793
|
} else {
|
|
63498
|
-
|
|
63794
|
+
writeFileSync28(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
63499
63795
|
wrote.push(pkgProv);
|
|
63500
63796
|
}
|
|
63501
|
-
const pkgTokens =
|
|
63502
|
-
if (
|
|
63503
|
-
const cur = JSON.parse(
|
|
63797
|
+
const pkgTokens = join64(cwd, "tokens.json");
|
|
63798
|
+
if (existsSync65(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
63799
|
+
const cur = JSON.parse(readFileSync77(pkgTokens, "utf8"));
|
|
63504
63800
|
let tokensIn = tokens;
|
|
63505
63801
|
if (tokens.typography) {
|
|
63506
63802
|
const fonts = catalogTypography(tokens.typography, cur.typography);
|
|
@@ -63521,13 +63817,13 @@ async function applyOverlays(input) {
|
|
|
63521
63817
|
if (primary && glow && typeof glow.color === "string") glow.color = primary;
|
|
63522
63818
|
stripBrandFromIdiom(merged);
|
|
63523
63819
|
}
|
|
63524
|
-
|
|
63820
|
+
writeFileSync28(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
63525
63821
|
wrote.push(pkgTokens);
|
|
63526
63822
|
}
|
|
63527
63823
|
const homeAction = homeRefreshActionId(shell);
|
|
63528
|
-
const homeSrc =
|
|
63529
|
-
if (homeAction &&
|
|
63530
|
-
const prev =
|
|
63824
|
+
const homeSrc = join64(cwd, "dev/index.ts");
|
|
63825
|
+
if (homeAction && existsSync65(homeSrc)) {
|
|
63826
|
+
const prev = readFileSync77(homeSrc, "utf8");
|
|
63531
63827
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
63532
63828
|
let next = patched.src;
|
|
63533
63829
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -63551,20 +63847,20 @@ async function applyOverlays(input) {
|
|
|
63551
63847
|
}
|
|
63552
63848
|
}
|
|
63553
63849
|
if (next !== prev) {
|
|
63554
|
-
|
|
63850
|
+
writeFileSync28(homeSrc, next);
|
|
63555
63851
|
wrote.push(homeSrc);
|
|
63556
63852
|
}
|
|
63557
63853
|
if (patched.unparsed) {
|
|
63558
63854
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
63559
63855
|
}
|
|
63560
63856
|
}
|
|
63561
|
-
if (!input.iconPath || !
|
|
63562
|
-
const book = input.iconPath ?
|
|
63857
|
+
if (!input.iconPath || !existsSync65(input.iconPath)) {
|
|
63858
|
+
const book = input.iconPath ? dirname36(dirname36(resolve51(input.iconPath))) : void 0;
|
|
63563
63859
|
notes.push(
|
|
63564
63860
|
book ? `no icon installed \u2014 ${siteLogoAbsence(book).hint}` : "no icon installed and no business book to say why \u2014 `himi icon generate` draws one from the accent, or `himi icon set <file.png>` installs the customer's own mark"
|
|
63565
63861
|
);
|
|
63566
63862
|
}
|
|
63567
|
-
if (input.iconPath &&
|
|
63863
|
+
if (input.iconPath && existsSync65(input.iconPath)) {
|
|
63568
63864
|
try {
|
|
63569
63865
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
63570
63866
|
wrote.push(...installed.wrote);
|
|
@@ -64678,10 +64974,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
|
|
|
64678
64974
|
}
|
|
64679
64975
|
function createPromiseCallback(cb) {
|
|
64680
64976
|
let callback;
|
|
64681
|
-
let
|
|
64977
|
+
let resolve54;
|
|
64682
64978
|
let reject;
|
|
64683
64979
|
const promise = new Promise((_resolve, _reject) => {
|
|
64684
|
-
|
|
64980
|
+
resolve54 = _resolve;
|
|
64685
64981
|
reject = _reject;
|
|
64686
64982
|
});
|
|
64687
64983
|
if (typeof cb === "function") {
|
|
@@ -64697,7 +64993,7 @@ function createPromiseCallback(cb) {
|
|
|
64697
64993
|
callback = (err, result) => {
|
|
64698
64994
|
try {
|
|
64699
64995
|
if (err) reject(err);
|
|
64700
|
-
else
|
|
64996
|
+
else resolve54(result);
|
|
64701
64997
|
} catch (e) {
|
|
64702
64998
|
reject(e instanceof Error ? e : new Error());
|
|
64703
64999
|
}
|
|
@@ -67785,14 +68081,14 @@ async function runSiteFunction(opts) {
|
|
|
67785
68081
|
}
|
|
67786
68082
|
if (opts.op === "publish") {
|
|
67787
68083
|
const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
|
|
67788
|
-
const
|
|
68084
|
+
const ok2 = httpOk(snap.rev) && httpOk(snap.live);
|
|
67789
68085
|
return {
|
|
67790
68086
|
...base,
|
|
67791
|
-
ok,
|
|
68087
|
+
ok: ok2,
|
|
67792
68088
|
revision: snap.revision,
|
|
67793
68089
|
codeAppId: snap.codeAppId,
|
|
67794
68090
|
publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
|
|
67795
|
-
error:
|
|
68091
|
+
error: ok2 ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
|
|
67796
68092
|
};
|
|
67797
68093
|
}
|
|
67798
68094
|
const { id, listed } = await withGrid(fetchImpl, opts.token, opts.msid, opts.siteUrl);
|
|
@@ -67887,12 +68183,12 @@ async function invokeAndReport(fetchImpl, opts, base, name, method) {
|
|
|
67887
68183
|
await new Promise((res) => setTimeout(res, 2500));
|
|
67888
68184
|
hit = await tryInvoke();
|
|
67889
68185
|
}
|
|
67890
|
-
const
|
|
68186
|
+
const ok2 = httpOk(hit.r);
|
|
67891
68187
|
return {
|
|
67892
68188
|
...base,
|
|
67893
|
-
ok,
|
|
68189
|
+
ok: ok2,
|
|
67894
68190
|
invoke: { url: hit.url, status: hit.r.status, body: hit.r.json ?? snippet2(hit.r.text) },
|
|
67895
|
-
error:
|
|
68191
|
+
error: ok2 ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
|
|
67896
68192
|
};
|
|
67897
68193
|
}
|
|
67898
68194
|
var HTTP_METHODS2, WRITE_LAYOUTS, VELO_PROVISION_URL, SITE_PUBLISH_URL, PUBLISH_RC_URL, SITE_FUNCTION_USAGE, NAME_RE, EXPORT_HEAD, WIX_HTTP_IMPORT_LINE;
|
|
@@ -67926,8 +68222,8 @@ __export(cli_exports, {
|
|
|
67926
68222
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
67927
68223
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
67928
68224
|
});
|
|
67929
|
-
import { readFileSync as
|
|
67930
|
-
import { resolve as
|
|
68225
|
+
import { readFileSync as readFileSync78 } from "node:fs";
|
|
68226
|
+
import { resolve as resolve52 } from "node:path";
|
|
67931
68227
|
function assetFetchFor(_opts) {
|
|
67932
68228
|
return pinnedFetch2;
|
|
67933
68229
|
}
|
|
@@ -67947,7 +68243,7 @@ async function runSiteAnalyze(opts) {
|
|
|
67947
68243
|
const assetFetch = assetFetchFor(opts);
|
|
67948
68244
|
const siteFetch = guardedSiteFetch;
|
|
67949
68245
|
const cwd = opts.cwd ?? process.cwd();
|
|
67950
|
-
const outDir =
|
|
68246
|
+
const outDir = resolve52(cwd, opts.outDir ?? ".himi/business-book");
|
|
67951
68247
|
let ownerAuth;
|
|
67952
68248
|
let msid;
|
|
67953
68249
|
const ownerSite = ownerSiteFor(opts);
|
|
@@ -67999,9 +68295,9 @@ async function runSiteAnalyze(opts) {
|
|
|
67999
68295
|
if (opts.apply) {
|
|
68000
68296
|
applied = await applyOverlays({
|
|
68001
68297
|
cwd,
|
|
68002
|
-
overlayPath:
|
|
68003
|
-
tokensPath:
|
|
68004
|
-
iconPath:
|
|
68298
|
+
overlayPath: resolve52(outDir, "provisioning.overlay.json"),
|
|
68299
|
+
tokensPath: resolve52(outDir, "tokens.overlay.json"),
|
|
68300
|
+
iconPath: resolve52(outDir, "media/icon.png"),
|
|
68005
68301
|
shell: opts.shell
|
|
68006
68302
|
});
|
|
68007
68303
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -68037,8 +68333,8 @@ async function runSiteFunctionCli(opts) {
|
|
|
68037
68333
|
const token = opts.token ?? await siteToken(msid);
|
|
68038
68334
|
let source;
|
|
68039
68335
|
if (opts.sourcePath) {
|
|
68040
|
-
const p =
|
|
68041
|
-
source =
|
|
68336
|
+
const p = resolve52(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
68337
|
+
source = readFileSync78(p, "utf8");
|
|
68042
68338
|
}
|
|
68043
68339
|
let body;
|
|
68044
68340
|
if (opts.bodyRaw != null) {
|
|
@@ -68093,7 +68389,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
68093
68389
|
cached2 = fromEnv;
|
|
68094
68390
|
return fromEnv;
|
|
68095
68391
|
}
|
|
68096
|
-
const token = await new Promise((
|
|
68392
|
+
const token = await new Promise((resolve54, reject) => {
|
|
68097
68393
|
let child;
|
|
68098
68394
|
try {
|
|
68099
68395
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -68122,7 +68418,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
68122
68418
|
const scan = (d) => {
|
|
68123
68419
|
out2 += String(d);
|
|
68124
68420
|
const m = out2.match(TOKEN_RE2);
|
|
68125
|
-
if (m) done(() =>
|
|
68421
|
+
if (m) done(() => resolve54(m[0]));
|
|
68126
68422
|
};
|
|
68127
68423
|
child.stdout?.on("data", scan);
|
|
68128
68424
|
child.stderr?.on("data", scan);
|
|
@@ -68299,7 +68595,7 @@ __export(site_create_exports, {
|
|
|
68299
68595
|
runSiteList: () => runSiteList,
|
|
68300
68596
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
68301
68597
|
});
|
|
68302
|
-
import { existsSync as
|
|
68598
|
+
import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync29 } from "node:fs";
|
|
68303
68599
|
import { resolve as resolvePath2 } from "node:path";
|
|
68304
68600
|
function oauthClientName(projectName) {
|
|
68305
68601
|
return `${projectName} client`;
|
|
@@ -68448,7 +68744,7 @@ async function runSiteCreate(opts) {
|
|
|
68448
68744
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
68449
68745
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
68450
68746
|
}
|
|
68451
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
68747
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync29 }) {
|
|
68452
68748
|
const msid = binding2.siteId;
|
|
68453
68749
|
const path2 = resolvePath2(target);
|
|
68454
68750
|
const committed = committedShellProvisioning(path2);
|
|
@@ -69121,12 +69417,12 @@ var init_context = __esm({
|
|
|
69121
69417
|
});
|
|
69122
69418
|
|
|
69123
69419
|
// src/cli.ts
|
|
69124
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
69420
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync80, mkdirSync as mkdirSync33, writeFileSync as writeFileSync30, existsSync as existsSync67, rmSync as rmSync16, readdirSync as readdirSync31, statSync as statSync19, lstatSync as lstatSync14, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
|
|
69125
69421
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
69126
69422
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
69127
69423
|
import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
|
|
69128
69424
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
69129
|
-
import { join as
|
|
69425
|
+
import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
|
|
69130
69426
|
import { fileURLToPath as fileURLToPath26 } from "node:url";
|
|
69131
69427
|
|
|
69132
69428
|
// ../serve-cli/src/client.ts
|
|
@@ -69867,7 +70163,7 @@ async function browserLogin(opts) {
|
|
|
69867
70163
|
const log = opts.log ?? (() => {
|
|
69868
70164
|
});
|
|
69869
70165
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
69870
|
-
return await new Promise((
|
|
70166
|
+
return await new Promise((resolve54, reject) => {
|
|
69871
70167
|
let settled = false;
|
|
69872
70168
|
let loginUrl = "";
|
|
69873
70169
|
const server = createServer();
|
|
@@ -69931,7 +70227,7 @@ async function browserLogin(opts) {
|
|
|
69931
70227
|
return;
|
|
69932
70228
|
}
|
|
69933
70229
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
|
|
69934
|
-
finish2(() =>
|
|
70230
|
+
finish2(() => resolve54({ token, loginUrl }));
|
|
69935
70231
|
});
|
|
69936
70232
|
});
|
|
69937
70233
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -71261,8 +71557,8 @@ var str8 = (v) => typeof v === "string" ? v : void 0;
|
|
|
71261
71557
|
var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
71262
71558
|
function embeddedTemplateCatalog() {
|
|
71263
71559
|
return availableTemplates().map((name) => {
|
|
71264
|
-
const path2 =
|
|
71265
|
-
const meta = JSON.parse(
|
|
71560
|
+
const path2 = join65(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
71561
|
+
const meta = JSON.parse(readFileSync80(path2, "utf8"));
|
|
71266
71562
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
71267
71563
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
71268
71564
|
}
|
|
@@ -71944,7 +72240,7 @@ var COMMANDS = [
|
|
|
71944
72240
|
{ name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone. A NON-EMPTY destination is refused unless you say which you mean: `--force` merges and reports \u2014 it writes the archive over what is there, keeps files the release does not carry, and NAMES every one of them as `left: [...]` so a tree that matches no release is never silent (#2437); `--replace` restores exactly what was archived, removing those files first (`removed: [...]`) and implying `--force`. `--replace` refuses a directory holding no `himalaya.content.json`, so a mistyped `--out` cannot clear an unrelated tree, and the only paths it can remove are the ones a push would have archived \u2014 `.git/`, `node_modules/`, `dist/`, `.env*` and key material are out of its reach by construction.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]" },
|
|
71945
72241
|
{ name: "share", summary: "publish or revoke a content-addressed `.himi` share link. The package must be a validated archive for an already-published release; the resulting https URL is safe to QR, copy, or open in Himi Player.", required: "--file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>" },
|
|
71946
72242
|
{ name: "run", summary: "serve a .himi package on localhost and open it in a browser \u2014 no serve plane, no dev-server, no setup. Given no argument it builds the current content package first, so `himi run` is the inner loop: edit, run, look at it. The SPA and /v1 are served from ONE origin because Tier-5 bundle fetches on web are same-origin-only. --chrome preview frames the app in a device chassis; --chrome app serves it as a plain web app. Blocks until Ctrl-C, like any dev server. --browser runs the whole plane INSIDE the tab (service worker + in-memory store) so no app code executes in this process or on any pod. --lan also serves it to the local network and prints a QR, so a phone on the same Wi-Fi opens it as the real app, full screen. --watch keeps the preview LIVE: every save in the content package rebuilds it and repaints the open tab with only what changed (the dev-server's hot-reload events); a build that fails keeps the last good preview on screen and says why. --idle-exit <min> (with --watch only) stops the watch once that many minutes pass with no source save, printing `{\"watch\":\"idle_exit\"}` and removing its .himi/run.json on the way out \u2014 the watch `himi init` starts passes 30; one started by hand runs until Ctrl-C. Stopping (Ctrl-C, SIGTERM, SIGHUP or the idle exit) removes the run's own .himi/run.json. Any `himi run` of a content package (plain, --watch or --browser) frames its preview on the build board (`himi studio`) while it serves, and all but --browser also serve that board at /__himi/studio/ on the preview's own origin. Its .himi/run.json (pid, watching) is also how `himi render` and `himi test` tell a live --watch is running: while none is, they add a `reminder` naming `himi run --watch --content <dir> &`, and while one is (the one `himi init` started, usually, whose .himi/watch.json vouches for it until it serves) the reminder names its url and board instead (either at most once every ten minutes per app) \u2014 first in `next[]` and again as the envelope's LAST key (the last line of `himi test`'s plain report), so an output read with `tail` still carries it.", required: "[<package.himi|dir|url>] [--browser] [--watch] [--idle-exit <min>] [--lan] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
|
|
71947
|
-
{ name: "mcp", summary: "run the himi tools as a local Model Context Protocol server over stdio, for coding agents \u2014 Claude Code, Cursor, Codex, VS Code. Tools: docs/components/sdk/icons, init, build, validate, test (hermetic), render (returns the PNG), progress, a live preview (start/status/stop a `himi run --watch`), whoami, and DRAFT-only push/share/preview links \u2014 never promote,
|
|
72243
|
+
{ name: "mcp", summary: "run the himi tools as a local Model Context Protocol server over stdio, for coding agents \u2014 Claude Code, Cursor, Codex, VS Code. Tools: docs/components/sdk/icons, init, build, validate, test (hermetic), render (returns the PNG), progress, a live preview (start/status/stop a `himi run --watch`), whoami, login (opens the browser sign-in for the user; the credential goes to a child `himi login` and onto disk, never through the server), and DRAFT-only push/share/preview links \u2014 never promote, dist or secrets. A sign-in's target is the one push/share then use. Each tool runs the same command in-process on the content package on disk (default: the host's workspace root). `himi init` and `himi agent-init` write the config for every host (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, .codex/config.toml when absent) plus a `himi-preview` launch configuration (.claude/launch.json) that opens the live preview in Claude Code desktop's browser pane. Never self-updates (npx already runs the current CLI). Blocks until the host closes stdin. `himi mcp plugin --out <dir>` writes the Claude Code plugin (the customer skill + this server) as a folder \u2014 the same plugin the serve plane's marketplace hands out at /.claude-plugin/marketplace.json. `--with-files` adds list/read/write/delete file tools confined to the workspace folder, for a host that cannot edit files (Claude Desktop chat, via the Desktop Extension); `HIMI_WORKSPACE` names that folder when the host names none.", required: "[plugin --out <dir>] [--with-files]" },
|
|
71948
72244
|
{ name: "preview", summary: "print the shareable web URL + himi:// deep link + agent /v1/preview JSON URLs for an app+release; --surface frames the web preview as any catalog surface (?surface=)", required: "--app --release [--screen] [--surface]" },
|
|
71949
72245
|
{ name: "surfaces", summary: "the surface catalog vs this app's envelope (platforms.json): targeted surfaces, the opt-in key for the rest, per-surface preview links with --app --release, and which widget families the package produces with --measure-widgets (which runs its built bundles)", required: "[--content <dir>] [--app --release] [--measure-widgets]" },
|
|
71950
72246
|
{ name: "context", summary: "fetch the agent preview envelope (GET /v1/preview/a/<app>) \u2014 ok/issues/screens/links; exit 1 if ok:false", required: "--app --release [--screen] [--include telemetry]" },
|
|
@@ -71976,7 +72272,7 @@ var COMMANDS = [
|
|
|
71976
72272
|
];
|
|
71977
72273
|
function cliVersion() {
|
|
71978
72274
|
try {
|
|
71979
|
-
return JSON.parse(
|
|
72275
|
+
return JSON.parse(readFileSync80(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
71980
72276
|
} catch {
|
|
71981
72277
|
return "unknown";
|
|
71982
72278
|
}
|
|
@@ -72027,16 +72323,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
|
|
|
72027
72323
|
}
|
|
72028
72324
|
var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
|
|
72029
72325
|
function execNpmConfig(file, args, options) {
|
|
72030
|
-
return new Promise((
|
|
72031
|
-
execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) :
|
|
72326
|
+
return new Promise((resolve54, reject) => {
|
|
72327
|
+
execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve54(String(stdout)));
|
|
72032
72328
|
});
|
|
72033
72329
|
}
|
|
72034
72330
|
var npmScopedWixRegistry = createScopedRegistryResolver();
|
|
72035
72331
|
async function scopedRegistryBefore(lookup2, deadline) {
|
|
72036
72332
|
let cancel = () => {
|
|
72037
72333
|
};
|
|
72038
|
-
const expired = new Promise((
|
|
72039
|
-
const timer = setTimeout(() =>
|
|
72334
|
+
const expired = new Promise((resolve54) => {
|
|
72335
|
+
const timer = setTimeout(() => resolve54(void 0), Math.max(0, deadline - Date.now()));
|
|
72040
72336
|
cancel = () => clearTimeout(timer);
|
|
72041
72337
|
});
|
|
72042
72338
|
try {
|
|
@@ -72094,18 +72390,18 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
72094
72390
|
}
|
|
72095
72391
|
function packageVersion(path2) {
|
|
72096
72392
|
try {
|
|
72097
|
-
const version2 = JSON.parse(
|
|
72393
|
+
const version2 = JSON.parse(readFileSync80(path2, "utf8")).version;
|
|
72098
72394
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
72099
72395
|
} catch {
|
|
72100
72396
|
return void 0;
|
|
72101
72397
|
}
|
|
72102
72398
|
}
|
|
72103
72399
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
72104
|
-
let dir =
|
|
72400
|
+
let dir = resolve53(fromDir);
|
|
72105
72401
|
for (; ; ) {
|
|
72106
|
-
const version2 = packageVersion(
|
|
72402
|
+
const version2 = packageVersion(join65(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
72107
72403
|
if (version2) return { version: version2, source: "local" };
|
|
72108
|
-
const parent =
|
|
72404
|
+
const parent = dirname37(dir);
|
|
72109
72405
|
if (parent === dir) break;
|
|
72110
72406
|
dir = parent;
|
|
72111
72407
|
}
|
|
@@ -72113,7 +72409,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
72113
72409
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
72114
72410
|
try {
|
|
72115
72411
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
72116
|
-
const version2 = root ? packageVersion(
|
|
72412
|
+
const version2 = root ? packageVersion(join65(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
72117
72413
|
return version2 ? { version: version2, source: "global" } : {};
|
|
72118
72414
|
} catch {
|
|
72119
72415
|
return {};
|
|
@@ -72160,11 +72456,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
72160
72456
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
72161
72457
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
72162
72458
|
function updateCachePath(env = process.env) {
|
|
72163
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
72459
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join65(homedir7(), ".himalaya", "update-check.json");
|
|
72164
72460
|
}
|
|
72165
72461
|
function readUpdateCache(path2) {
|
|
72166
72462
|
try {
|
|
72167
|
-
const parsed = JSON.parse(
|
|
72463
|
+
const parsed = JSON.parse(readFileSync80(path2, "utf8"));
|
|
72168
72464
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
72169
72465
|
} catch {
|
|
72170
72466
|
return {};
|
|
@@ -72172,8 +72468,8 @@ function readUpdateCache(path2) {
|
|
|
72172
72468
|
}
|
|
72173
72469
|
function writeUpdateCache(path2, cache) {
|
|
72174
72470
|
try {
|
|
72175
|
-
|
|
72176
|
-
|
|
72471
|
+
mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
|
|
72472
|
+
writeFileSync30(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
72177
72473
|
} catch {
|
|
72178
72474
|
}
|
|
72179
72475
|
}
|
|
@@ -72233,12 +72529,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
|
|
|
72233
72529
|
},
|
|
72234
72530
|
installedVersion: () => {
|
|
72235
72531
|
const root = globalNodeModulesRoot();
|
|
72236
|
-
return root ? packageVersion(
|
|
72532
|
+
return root ? packageVersion(join65(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
72237
72533
|
},
|
|
72238
72534
|
reexec: (argv) => {
|
|
72239
72535
|
const root = globalNodeModulesRoot();
|
|
72240
|
-
const entry = root ?
|
|
72241
|
-
if (!entry || !
|
|
72536
|
+
const entry = root ? join65(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
72537
|
+
if (!entry || !existsSync67(entry)) return void 0;
|
|
72242
72538
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
72243
72539
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
72244
72540
|
stdio: "inherit",
|
|
@@ -72285,7 +72581,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
72285
72581
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
72286
72582
|
let content;
|
|
72287
72583
|
try {
|
|
72288
|
-
content =
|
|
72584
|
+
content = readFileSync80(path2, "utf8");
|
|
72289
72585
|
} catch {
|
|
72290
72586
|
continue;
|
|
72291
72587
|
}
|
|
@@ -72293,7 +72589,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
72293
72589
|
let since = stamped;
|
|
72294
72590
|
if (!Number.isFinite(since)) {
|
|
72295
72591
|
try {
|
|
72296
|
-
since =
|
|
72592
|
+
since = statSync19(path2).mtimeMs;
|
|
72297
72593
|
} catch {
|
|
72298
72594
|
continue;
|
|
72299
72595
|
}
|
|
@@ -72308,14 +72604,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72308
72604
|
const mine = lockStamp(now);
|
|
72309
72605
|
const readLock = (path2) => {
|
|
72310
72606
|
try {
|
|
72311
|
-
return
|
|
72607
|
+
return readFileSync80(path2, "utf8");
|
|
72312
72608
|
} catch {
|
|
72313
72609
|
return void 0;
|
|
72314
72610
|
}
|
|
72315
72611
|
};
|
|
72316
72612
|
const tryCreate = (path2) => {
|
|
72317
72613
|
try {
|
|
72318
|
-
|
|
72614
|
+
writeFileSync30(path2, mine, { flag: "wx", mode: 384 });
|
|
72319
72615
|
return true;
|
|
72320
72616
|
} catch {
|
|
72321
72617
|
return false;
|
|
@@ -72323,13 +72619,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72323
72619
|
};
|
|
72324
72620
|
const removeIfMine = (path2) => {
|
|
72325
72621
|
try {
|
|
72326
|
-
if (readLock(path2) === mine)
|
|
72622
|
+
if (readLock(path2) === mine) rmSync16(path2, { force: true });
|
|
72327
72623
|
} catch {
|
|
72328
72624
|
}
|
|
72329
72625
|
};
|
|
72330
72626
|
const release = () => removeIfMine(lockPath);
|
|
72331
72627
|
try {
|
|
72332
|
-
|
|
72628
|
+
mkdirSync33(dirname37(lockPath), { recursive: true, mode: 448 });
|
|
72333
72629
|
} catch {
|
|
72334
72630
|
return () => {
|
|
72335
72631
|
};
|
|
@@ -72346,7 +72642,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72346
72642
|
hooks.underBreakLock?.();
|
|
72347
72643
|
if (current === void 0) return tryCreate(lockPath) ? release : void 0;
|
|
72348
72644
|
if (!isAbandoned(current)) return void 0;
|
|
72349
|
-
|
|
72645
|
+
rmSync16(lockPath, { force: true });
|
|
72350
72646
|
return tryCreate(lockPath) ? release : void 0;
|
|
72351
72647
|
} finally {
|
|
72352
72648
|
removeIfMine(breakPath);
|
|
@@ -72442,7 +72738,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
|
|
|
72442
72738
|
return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
|
|
72443
72739
|
};
|
|
72444
72740
|
return async (dir, opts = {}) => {
|
|
72445
|
-
const argv = ["validate", "--content",
|
|
72741
|
+
const argv = ["validate", "--content", resolve53(dir), "--strict", "--skip-version-check"];
|
|
72446
72742
|
if (!opts.fresh) {
|
|
72447
72743
|
const out2 = [];
|
|
72448
72744
|
const err = [];
|
|
@@ -72900,9 +73196,9 @@ function executableOnPath(name, env = process.env) {
|
|
|
72900
73196
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
72901
73197
|
for (const dir of entries) {
|
|
72902
73198
|
for (const suffix of suffixes) {
|
|
72903
|
-
const candidate =
|
|
73199
|
+
const candidate = join65(dir, `${name}${suffix}`);
|
|
72904
73200
|
try {
|
|
72905
|
-
if (!
|
|
73201
|
+
if (!statSync19(candidate).isFile()) continue;
|
|
72906
73202
|
if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
|
|
72907
73203
|
return true;
|
|
72908
73204
|
} catch {
|
|
@@ -72949,9 +73245,9 @@ function buildDoctorReport(input) {
|
|
|
72949
73245
|
const versionSkew = versions?.cli.status === "outdated" || sdkSkew;
|
|
72950
73246
|
const hostRefused = auth.controlTokenStatus === "refused";
|
|
72951
73247
|
const staleToken = auth.controlTokenPresent === true && auth.controlToken === false && !hostRefused;
|
|
72952
|
-
const
|
|
73248
|
+
const ok2 = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
|
|
72953
73249
|
return {
|
|
72954
|
-
ok,
|
|
73250
|
+
ok: ok2,
|
|
72955
73251
|
target,
|
|
72956
73252
|
version: version2,
|
|
72957
73253
|
dataPlane: { ...data, note: "public Wix APIs \u2014 reachable off-VPN" },
|
|
@@ -73009,7 +73305,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
73009
73305
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
73010
73306
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
73011
73307
|
const iosYmlPath = iosProjectYml2(app);
|
|
73012
|
-
const iosYml =
|
|
73308
|
+
const iosYml = existsSync67(iosYmlPath) ? readFileSync80(iosYmlPath, "utf8") : "";
|
|
73013
73309
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
73014
73310
|
if (!optedIn) {
|
|
73015
73311
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -73023,14 +73319,14 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
73023
73319
|
}
|
|
73024
73320
|
function readConfigSource(dir) {
|
|
73025
73321
|
try {
|
|
73026
|
-
return
|
|
73322
|
+
return readFileSync80(join65(dir, "config.ts"), "utf8");
|
|
73027
73323
|
} catch {
|
|
73028
73324
|
return null;
|
|
73029
73325
|
}
|
|
73030
73326
|
}
|
|
73031
73327
|
function writePngFile(path2, base64) {
|
|
73032
|
-
|
|
73033
|
-
|
|
73328
|
+
mkdirSync33(dirname37(path2), { recursive: true });
|
|
73329
|
+
writeFileSync30(path2, Buffer.from(base64, "base64"));
|
|
73034
73330
|
return path2;
|
|
73035
73331
|
}
|
|
73036
73332
|
async function seedAgentFilesFor(dir, flags, mode = "init") {
|
|
@@ -73058,8 +73354,8 @@ function keptPlan(kept) {
|
|
|
73058
73354
|
return note ? { kept, note } : {};
|
|
73059
73355
|
}
|
|
73060
73356
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
73061
|
-
const dir =
|
|
73062
|
-
if (
|
|
73357
|
+
const dir = resolve53(parentDir, name);
|
|
73358
|
+
if (existsSync67(join65(dir, "himalaya.content.json"))) {
|
|
73063
73359
|
throw new Error(`content package already exists at ${dir}`);
|
|
73064
73360
|
}
|
|
73065
73361
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -73071,7 +73367,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
|
73071
73367
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
73072
73368
|
}
|
|
73073
73369
|
function contentDir(flags) {
|
|
73074
|
-
return
|
|
73370
|
+
return resolve53(str8(flags.content) ?? process.cwd());
|
|
73075
73371
|
}
|
|
73076
73372
|
function renameRestoredSource(restored, declaredApp, renamed) {
|
|
73077
73373
|
const text8 = {};
|
|
@@ -73089,7 +73385,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
|
|
|
73089
73385
|
function symlinkDestinationIssue(dest) {
|
|
73090
73386
|
let kind;
|
|
73091
73387
|
try {
|
|
73092
|
-
kind =
|
|
73388
|
+
kind = lstatSync14(dest);
|
|
73093
73389
|
} catch {
|
|
73094
73390
|
return null;
|
|
73095
73391
|
}
|
|
@@ -73102,11 +73398,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
73102
73398
|
function restoreDestinationIssue(dest, force) {
|
|
73103
73399
|
const link = symlinkDestinationIssue(dest);
|
|
73104
73400
|
if (link) return link;
|
|
73105
|
-
if (!
|
|
73106
|
-
if (!
|
|
73401
|
+
if (!existsSync67(dest)) return null;
|
|
73402
|
+
if (!statSync19(dest).isDirectory()) {
|
|
73107
73403
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
73108
73404
|
}
|
|
73109
|
-
if (
|
|
73405
|
+
if (readdirSync31(dest).length > 0 && !force) {
|
|
73110
73406
|
return {
|
|
73111
73407
|
error: `${dest} already exists and is not empty`,
|
|
73112
73408
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -73115,10 +73411,10 @@ function restoreDestinationIssue(dest, force) {
|
|
|
73115
73411
|
return null;
|
|
73116
73412
|
}
|
|
73117
73413
|
function isHimalayaMonorepoCheckout(start) {
|
|
73118
|
-
let dir =
|
|
73414
|
+
let dir = resolve53(start);
|
|
73119
73415
|
for (; ; ) {
|
|
73120
|
-
if (
|
|
73121
|
-
const parent =
|
|
73416
|
+
if (existsSync67(join65(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync67(join65(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
73417
|
+
const parent = dirname37(dir);
|
|
73122
73418
|
if (parent === dir) return false;
|
|
73123
73419
|
dir = parent;
|
|
73124
73420
|
}
|
|
@@ -73177,8 +73473,8 @@ function materializeForPreview(appDir3, slug, displayName) {
|
|
|
73177
73473
|
const forBuild = Object.fromEntries(
|
|
73178
73474
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
73179
73475
|
);
|
|
73180
|
-
const repoRoot2 =
|
|
73181
|
-
const root =
|
|
73476
|
+
const repoRoot2 = resolve53(fileURLToPath26(new URL("../../..", import.meta.url)));
|
|
73477
|
+
const root = join65(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
73182
73478
|
const stillRunning = (pid) => {
|
|
73183
73479
|
try {
|
|
73184
73480
|
process.kill(pid, 0);
|
|
@@ -73188,30 +73484,30 @@ function materializeForPreview(appDir3, slug, displayName) {
|
|
|
73188
73484
|
}
|
|
73189
73485
|
};
|
|
73190
73486
|
try {
|
|
73191
|
-
for (const entry of
|
|
73487
|
+
for (const entry of readdirSync31(root, { withFileTypes: true })) {
|
|
73192
73488
|
if (!entry.isDirectory()) continue;
|
|
73193
73489
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
73194
73490
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
73195
|
-
|
|
73491
|
+
rmSync16(join65(root, entry.name), { recursive: true, force: true });
|
|
73196
73492
|
}
|
|
73197
73493
|
}
|
|
73198
73494
|
} catch {
|
|
73199
73495
|
}
|
|
73200
|
-
const dest =
|
|
73201
|
-
|
|
73202
|
-
|
|
73496
|
+
const dest = join65(root, `${slug}-${process.pid}`);
|
|
73497
|
+
rmSync16(dest, { recursive: true, force: true });
|
|
73498
|
+
mkdirSync33(dest, { recursive: true });
|
|
73203
73499
|
try {
|
|
73204
73500
|
materializeSource(forBuild, displayName, dest, slug);
|
|
73205
73501
|
} catch (e) {
|
|
73206
|
-
|
|
73502
|
+
rmSync16(dest, { recursive: true, force: true });
|
|
73207
73503
|
throw e;
|
|
73208
73504
|
}
|
|
73209
73505
|
return dest;
|
|
73210
73506
|
}
|
|
73211
73507
|
async function appId(dir) {
|
|
73212
73508
|
try {
|
|
73213
|
-
const { readFileSync:
|
|
73214
|
-
const m = JSON.parse(
|
|
73509
|
+
const { readFileSync: readFileSync81 } = await import("node:fs");
|
|
73510
|
+
const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
|
|
73215
73511
|
if (m.name) return m.name;
|
|
73216
73512
|
} catch {
|
|
73217
73513
|
}
|
|
@@ -73219,8 +73515,8 @@ async function appId(dir) {
|
|
|
73219
73515
|
}
|
|
73220
73516
|
async function contentVisibility(dir) {
|
|
73221
73517
|
try {
|
|
73222
|
-
const { readFileSync:
|
|
73223
|
-
const m = JSON.parse(
|
|
73518
|
+
const { readFileSync: readFileSync81 } = await import("node:fs");
|
|
73519
|
+
const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
|
|
73224
73520
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
73225
73521
|
} catch {
|
|
73226
73522
|
}
|
|
@@ -73423,7 +73719,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
73423
73719
|
return 0;
|
|
73424
73720
|
}
|
|
73425
73721
|
case "agent-init": {
|
|
73426
|
-
const dir =
|
|
73722
|
+
const dir = resolve53(str8(flags.dir) ?? process.cwd());
|
|
73427
73723
|
const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
|
|
73428
73724
|
let res;
|
|
73429
73725
|
try {
|
|
@@ -73445,7 +73741,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
73445
73741
|
...res.removed.length ? { removed: res.removed, note: "older copies at the app root, moved to .himi/legacy-agent-files/ (a backup, in case one became app code) \u2014 the current ones live in .agents/skills/himalaya/" } : {},
|
|
73446
73742
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
73447
73743
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
73448
|
-
...
|
|
73744
|
+
...existsSync67(join65(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
|
|
73449
73745
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
73450
73746
|
portalUrl: idx.portalUrl
|
|
73451
73747
|
});
|
|
@@ -73468,7 +73764,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
73468
73764
|
try {
|
|
73469
73765
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
73470
73766
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
73471
|
-
out2 = mkdtempSync4(
|
|
73767
|
+
out2 = mkdtempSync4(join65(tmpdir5(), "himi-ux-record-"));
|
|
73472
73768
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
73473
73769
|
const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
73474
73770
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -73481,7 +73777,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
73481
73777
|
return null;
|
|
73482
73778
|
} finally {
|
|
73483
73779
|
if (out2 !== void 0) try {
|
|
73484
|
-
|
|
73780
|
+
rmSync16(out2, { recursive: true, force: true });
|
|
73485
73781
|
} catch {
|
|
73486
73782
|
}
|
|
73487
73783
|
}
|
|
@@ -73635,7 +73931,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73635
73931
|
}
|
|
73636
73932
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
73637
73933
|
try {
|
|
73638
|
-
|
|
73934
|
+
readdirSync31(outDir);
|
|
73639
73935
|
} catch {
|
|
73640
73936
|
return { families: void 0, source: "unbuilt" };
|
|
73641
73937
|
}
|
|
@@ -73646,7 +73942,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73646
73942
|
let js;
|
|
73647
73943
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
73648
73944
|
try {
|
|
73649
|
-
js =
|
|
73945
|
+
js = readFileSync80(join65(outDir, candidate), "utf8");
|
|
73650
73946
|
break;
|
|
73651
73947
|
} catch {
|
|
73652
73948
|
}
|
|
@@ -73677,7 +73973,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73677
73973
|
}
|
|
73678
73974
|
return { families, source: "dist/bundles" };
|
|
73679
73975
|
}
|
|
73680
|
-
var boardOpen = (dir) =>
|
|
73976
|
+
var boardOpen = (dir) => existsSync67(join65(dir, ".himi", "studio", "index.html"));
|
|
73681
73977
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
73682
73978
|
async function leaveForBoard(dir, record2, value) {
|
|
73683
73979
|
if (!boardOpen(dir)) return;
|
|
@@ -73701,7 +73997,7 @@ async function liveMapFor(dir) {
|
|
|
73701
73997
|
}
|
|
73702
73998
|
var commandScratch = new AsyncLocalStorage();
|
|
73703
73999
|
function commandScratchDir(prefix) {
|
|
73704
|
-
const dir = mkdtempSync4(
|
|
74000
|
+
const dir = mkdtempSync4(join65(tmpdir5(), prefix));
|
|
73705
74001
|
commandScratch.getStore()?.push(dir);
|
|
73706
74002
|
return dir;
|
|
73707
74003
|
}
|
|
@@ -73712,7 +74008,7 @@ async function run(argv, io = defaultIO, deps = {}) {
|
|
|
73712
74008
|
code = await commandScratch.run(scratch, () => runCommand(argv, io, deps));
|
|
73713
74009
|
} finally {
|
|
73714
74010
|
for (const dir of scratch) try {
|
|
73715
|
-
|
|
74011
|
+
rmSync16(dir, { recursive: true, force: true });
|
|
73716
74012
|
} catch {
|
|
73717
74013
|
}
|
|
73718
74014
|
}
|
|
@@ -73980,7 +74276,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
73980
74276
|
return 2;
|
|
73981
74277
|
}
|
|
73982
74278
|
const template = str8(flags.template);
|
|
73983
|
-
const parentDir =
|
|
74279
|
+
const parentDir = resolve53(str8(flags.dir) ?? process.cwd());
|
|
73984
74280
|
const withAgentFiles = async (dir) => {
|
|
73985
74281
|
const seeded = await seedAgentFilesFor(dir, flags);
|
|
73986
74282
|
if (!seeded.agent || "error" in seeded.agent) return seeded;
|
|
@@ -73993,7 +74289,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
73993
74289
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
73994
74290
|
next.push(`carried the planning journal into the app (${carried.join(", ")}${owed ? `; ${owed} approval${owed === 1 ? "" : "s"} still owed` : ""}) \u2014 \`himi progress --brief\` there shows it`);
|
|
73995
74291
|
}
|
|
73996
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) =>
|
|
74292
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync67(join65(parentDir, f)));
|
|
73997
74293
|
if (planInParent.length) {
|
|
73998
74294
|
next.push(`${planInParent.join(" and ")} in ${parentDir} ${planInParent.length > 1 ? "are" : "is"} not the app's \u2014 if that is the approved plan, move it over the template's boilerplate in ${dir}`);
|
|
73999
74295
|
}
|
|
@@ -74141,11 +74437,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74141
74437
|
return 2;
|
|
74142
74438
|
}
|
|
74143
74439
|
}
|
|
74144
|
-
const appDir3 =
|
|
74145
|
-
const sourceDir =
|
|
74440
|
+
const appDir3 = resolve53(str8(flags.dir) ?? process.cwd());
|
|
74441
|
+
const sourceDir = resolve53(str8(flags["source-dir"]) ?? appDir3);
|
|
74146
74442
|
let meta;
|
|
74147
74443
|
try {
|
|
74148
|
-
meta = JSON.parse(
|
|
74444
|
+
meta = JSON.parse(readFileSync80(join65(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
74149
74445
|
} catch {
|
|
74150
74446
|
io.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
|
|
74151
74447
|
return 2;
|
|
@@ -74155,7 +74451,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74155
74451
|
return 2;
|
|
74156
74452
|
}
|
|
74157
74453
|
try {
|
|
74158
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
74454
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync80(join65(sourceDir, "tokens.json"), "utf8")));
|
|
74159
74455
|
meta = { ...appearance, ...meta };
|
|
74160
74456
|
} catch {
|
|
74161
74457
|
}
|
|
@@ -74177,14 +74473,14 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74177
74473
|
const force = flags.force === true;
|
|
74178
74474
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
74179
74475
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
74180
|
-
const out2 = mkdtempSync4(
|
|
74476
|
+
const out2 = mkdtempSync4(join65(tmpdir5(), "himi-template-"));
|
|
74181
74477
|
publishScratch.push(out2);
|
|
74182
74478
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
74183
74479
|
const outcome = await buildReleaseFromContent2(buildDir, out2, {
|
|
74184
74480
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
74185
74481
|
collect: { lint: true, strict }
|
|
74186
74482
|
});
|
|
74187
|
-
const scaffoldSourceFindings =
|
|
74483
|
+
const scaffoldSourceFindings = resolve53(sourceDir) === resolve53(appDir3) ? [] : [
|
|
74188
74484
|
...tokenColorIssues(sourceDir),
|
|
74189
74485
|
...surfaceIssues(sourceDir, void 0, strict),
|
|
74190
74486
|
...await fontIssues(sourceDir, strict),
|
|
@@ -74227,11 +74523,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74227
74523
|
}));
|
|
74228
74524
|
return 1;
|
|
74229
74525
|
}
|
|
74230
|
-
const iconPath = str8(flags.icon) ?
|
|
74526
|
+
const iconPath = str8(flags.icon) ? resolve53(str8(flags.icon)) : templateIconPath(name);
|
|
74231
74527
|
let iconHash;
|
|
74232
74528
|
if (iconPath) {
|
|
74233
74529
|
try {
|
|
74234
|
-
const bytes2 =
|
|
74530
|
+
const bytes2 = readFileSync80(iconPath);
|
|
74235
74531
|
payload.icon = bytes2.toString("base64");
|
|
74236
74532
|
iconHash = createHash31("sha256").update(bytes2).digest("hex");
|
|
74237
74533
|
} catch {
|
|
@@ -74404,7 +74700,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74404
74700
|
} finally {
|
|
74405
74701
|
for (const dir of publishScratch) {
|
|
74406
74702
|
try {
|
|
74407
|
-
|
|
74703
|
+
rmSync16(dir, { recursive: true, force: true });
|
|
74408
74704
|
} catch (e) {
|
|
74409
74705
|
io.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e.message}` }));
|
|
74410
74706
|
}
|
|
@@ -74438,12 +74734,12 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74438
74734
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
74439
74735
|
return 2;
|
|
74440
74736
|
}
|
|
74441
|
-
const { readdirSync:
|
|
74737
|
+
const { readdirSync: readdirSync32, existsSync: fileExists } = await import("node:fs");
|
|
74442
74738
|
const { join: pathJoin } = await import("node:path");
|
|
74443
74739
|
const targets = [];
|
|
74444
74740
|
const t5 = pathJoin(dir, "tier5-src");
|
|
74445
74741
|
if (fileExists(t5)) {
|
|
74446
|
-
for (const d of
|
|
74742
|
+
for (const d of readdirSync32(t5, { withFileTypes: true })) {
|
|
74447
74743
|
if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
|
|
74448
74744
|
}
|
|
74449
74745
|
}
|
|
@@ -74518,7 +74814,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74518
74814
|
const path2 = dpxSessionTokenPath();
|
|
74519
74815
|
let raw;
|
|
74520
74816
|
try {
|
|
74521
|
-
raw =
|
|
74817
|
+
raw = readFileSync80(path2, "utf8");
|
|
74522
74818
|
} catch {
|
|
74523
74819
|
throw new Error(`no DPX BO session at ${path2}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
|
|
74524
74820
|
}
|
|
@@ -74649,32 +74945,37 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74649
74945
|
return 1;
|
|
74650
74946
|
}
|
|
74651
74947
|
const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
|
|
74652
|
-
const dir =
|
|
74948
|
+
const dir = resolve53(out2);
|
|
74653
74949
|
const files = himiPluginFiles2(skills.skillMd);
|
|
74654
74950
|
for (const f of files) {
|
|
74655
|
-
|
|
74656
|
-
|
|
74951
|
+
mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
|
|
74952
|
+
writeFileSync30(join65(dir, f.path), f.text);
|
|
74657
74953
|
}
|
|
74658
74954
|
print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
74659
74955
|
return 0;
|
|
74660
74956
|
}
|
|
74661
74957
|
const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
74662
|
-
await startMcpServer2({
|
|
74958
|
+
await startMcpServer2({
|
|
74959
|
+
run,
|
|
74960
|
+
version: cliVersion(),
|
|
74961
|
+
withFiles: flags["with-files"] === true,
|
|
74962
|
+
...process.env.HIMI_WORKSPACE ? { workspace: resolve53(process.env.HIMI_WORKSPACE) } : {}
|
|
74963
|
+
});
|
|
74663
74964
|
return 0;
|
|
74664
74965
|
}
|
|
74665
74966
|
case "studio": {
|
|
74666
74967
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
74667
74968
|
const dir = contentDir(flags);
|
|
74668
|
-
if (!
|
|
74969
|
+
if (!existsSync67(join65(dir, "himalaya.content.json"))) {
|
|
74669
74970
|
io.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
|
|
74670
74971
|
return 2;
|
|
74671
74972
|
}
|
|
74672
74973
|
if (pos[1] === "reel") {
|
|
74673
74974
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
74674
|
-
const out2 =
|
|
74975
|
+
const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
|
|
74675
74976
|
const { html, plan } = buildReel2(dir);
|
|
74676
|
-
|
|
74677
|
-
|
|
74977
|
+
mkdirSync33(dirname37(out2), { recursive: true });
|
|
74978
|
+
writeFileSync30(out2, html);
|
|
74678
74979
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
74679
74980
|
const url2 = pathToFileURL9(out2).href;
|
|
74680
74981
|
const open2 = flags["no-open"] !== true;
|
|
@@ -74743,7 +75044,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
74743
75044
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
74744
75045
|
const dir = contentDir(flags);
|
|
74745
75046
|
const journal2 = journalPath2(dir);
|
|
74746
|
-
const isContentPackage =
|
|
75047
|
+
const isContentPackage = existsSync67(join65(dir, "himalaya.content.json"));
|
|
74747
75048
|
const hint = isContentPackage ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
|
|
74748
75049
|
const message = pos.slice(1).join(" ").trim();
|
|
74749
75050
|
const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
|
|
@@ -74892,7 +75193,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
74892
75193
|
case "test": {
|
|
74893
75194
|
const dir = contentDir(flags);
|
|
74894
75195
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
74895
|
-
if (
|
|
75196
|
+
if (existsSync67(join65(dir, "functions"))) {
|
|
74896
75197
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
74897
75198
|
const loaded = await loadFunctionsApp2(dir);
|
|
74898
75199
|
const results = [];
|
|
@@ -75024,7 +75325,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75024
75325
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
75025
75326
|
return 2;
|
|
75026
75327
|
}
|
|
75027
|
-
const sources = collectWorkerSources2(
|
|
75328
|
+
const sources = collectWorkerSources2(join65(dir, "tier5-src"), screen.bundleName);
|
|
75028
75329
|
if (!sources) {
|
|
75029
75330
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
75030
75331
|
return 2;
|
|
@@ -75201,7 +75502,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75201
75502
|
const sp = await runShotsPass2({
|
|
75202
75503
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
75203
75504
|
tokens: outcome.tokens,
|
|
75204
|
-
outDir:
|
|
75505
|
+
outDir: join65(dir, ".himi", "shots"),
|
|
75205
75506
|
width: 390,
|
|
75206
75507
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
75207
75508
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -75211,7 +75512,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75211
75512
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
75212
75513
|
renderPngBatch: renderPngBatch2,
|
|
75213
75514
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
75214
|
-
clearDir: (d) =>
|
|
75515
|
+
clearDir: (d) => rmSync16(d, { recursive: true, force: true })
|
|
75215
75516
|
}
|
|
75216
75517
|
});
|
|
75217
75518
|
writtenShots = sp.written;
|
|
@@ -75239,7 +75540,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75239
75540
|
releaseId: result.releaseId,
|
|
75240
75541
|
releasePayload: release,
|
|
75241
75542
|
descriptors: attestedDescriptors,
|
|
75242
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
75543
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join65(dir, ".himi", "shots", name)])),
|
|
75243
75544
|
coverage: {
|
|
75244
75545
|
screens: crawledScreens.size,
|
|
75245
75546
|
actionsDispatched: result.actions.exercised,
|
|
@@ -75350,7 +75651,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75350
75651
|
return 2;
|
|
75351
75652
|
}
|
|
75352
75653
|
try {
|
|
75353
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
75654
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync80(stateArg.replace(/^@/, ""), "utf8");
|
|
75354
75655
|
injectedState = JSON.parse(raw);
|
|
75355
75656
|
} catch (e) {
|
|
75356
75657
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -75365,7 +75666,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75365
75666
|
return 2;
|
|
75366
75667
|
}
|
|
75367
75668
|
try {
|
|
75368
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
75669
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync80(inputArg.replace(/^@/, ""), "utf8");
|
|
75369
75670
|
const parsed = JSON.parse(raw);
|
|
75370
75671
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
75371
75672
|
injectedInput = parsed;
|
|
@@ -75428,11 +75729,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75428
75729
|
const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
|
|
75429
75730
|
let pngFile;
|
|
75430
75731
|
let attestationPngFile;
|
|
75431
|
-
const shotPath =
|
|
75732
|
+
const shotPath = join65(dir, ".himi", "shots", `${screenId}.png`);
|
|
75432
75733
|
const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
|
|
75433
75734
|
if (pngTarget && r.pngBase64) {
|
|
75434
75735
|
pngFile = writePngFile(pngTarget, r.pngBase64);
|
|
75435
|
-
attestationPngFile =
|
|
75736
|
+
attestationPngFile = resolve53(pngTarget) === resolve53(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
|
|
75436
75737
|
}
|
|
75437
75738
|
if (renderWidth !== void 0 && r.renderable) {
|
|
75438
75739
|
recordRenderWidth(dir, {
|
|
@@ -75768,7 +76069,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75768
76069
|
return 2;
|
|
75769
76070
|
}
|
|
75770
76071
|
const renamed = str8(flags.name);
|
|
75771
|
-
const dest =
|
|
76072
|
+
const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
75772
76073
|
const replace = flags.replace === true;
|
|
75773
76074
|
const force = replace || flags.force === true;
|
|
75774
76075
|
const linked = symlinkDestinationIssue(dest);
|
|
@@ -75776,20 +76077,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75776
76077
|
io.error(JSON.stringify(linked));
|
|
75777
76078
|
return 1;
|
|
75778
76079
|
}
|
|
75779
|
-
if (
|
|
75780
|
-
if (!
|
|
76080
|
+
if (existsSync67(dest)) {
|
|
76081
|
+
if (!statSync19(dest).isDirectory()) {
|
|
75781
76082
|
io.error(JSON.stringify({
|
|
75782
76083
|
error: `${dest} exists and is not a directory`,
|
|
75783
76084
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
75784
76085
|
}));
|
|
75785
76086
|
return 1;
|
|
75786
76087
|
}
|
|
75787
|
-
const occupied =
|
|
76088
|
+
const occupied = readdirSync31(dest).length > 0;
|
|
75788
76089
|
if (occupied && !force) {
|
|
75789
76090
|
io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
|
|
75790
76091
|
return 1;
|
|
75791
76092
|
}
|
|
75792
|
-
if (replace && occupied && !
|
|
76093
|
+
if (replace && occupied && !existsSync67(join65(dest, "himalaya.content.json"))) {
|
|
75793
76094
|
io.error(JSON.stringify({
|
|
75794
76095
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
75795
76096
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -75956,7 +76257,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75956
76257
|
const manifest = outcome.manifest;
|
|
75957
76258
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
75958
76259
|
const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
|
|
75959
|
-
const contentRel =
|
|
76260
|
+
const contentRel = relative14(process.cwd(), dir) || ".";
|
|
75960
76261
|
const contentArg2 = shellQuote3(contentRel);
|
|
75961
76262
|
if (onlyRaw !== void 0) {
|
|
75962
76263
|
const onlyDraft = flags.draft === true;
|
|
@@ -76427,7 +76728,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76427
76728
|
return 2;
|
|
76428
76729
|
}
|
|
76429
76730
|
try {
|
|
76430
|
-
const res = writePack(
|
|
76731
|
+
const res = writePack(resolve53(releaseDir), only, resolve53(str8(flags.out) ?? process.cwd()));
|
|
76431
76732
|
print({
|
|
76432
76733
|
ok: true,
|
|
76433
76734
|
app: res.app,
|
|
@@ -76476,7 +76777,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76476
76777
|
}
|
|
76477
76778
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76478
76779
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
76479
|
-
const built = mkdtempSync4(
|
|
76780
|
+
const built = mkdtempSync4(join65(tmpdir5(), "himi-pack-"));
|
|
76480
76781
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
76481
76782
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
76482
76783
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -76493,12 +76794,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76493
76794
|
...await navIssues2(dir, strict)
|
|
76494
76795
|
]);
|
|
76495
76796
|
if (hasErrors && !force) {
|
|
76496
|
-
|
|
76797
|
+
rmSync16(built, { recursive: true, force: true });
|
|
76497
76798
|
print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
76498
76799
|
return 1;
|
|
76499
76800
|
}
|
|
76500
76801
|
try {
|
|
76501
|
-
const res = writePack(built, app,
|
|
76802
|
+
const res = writePack(built, app, resolve53(str8(flags.out) ?? dir), sourceArchive);
|
|
76502
76803
|
print({
|
|
76503
76804
|
ok: true,
|
|
76504
76805
|
app: res.app,
|
|
@@ -76529,7 +76830,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76529
76830
|
io.error(JSON.stringify({ error: e.message }));
|
|
76530
76831
|
return 1;
|
|
76531
76832
|
} finally {
|
|
76532
|
-
|
|
76833
|
+
rmSync16(built, { recursive: true, force: true });
|
|
76533
76834
|
}
|
|
76534
76835
|
}
|
|
76535
76836
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -76543,7 +76844,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76543
76844
|
const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
|
|
76544
76845
|
let opened;
|
|
76545
76846
|
try {
|
|
76546
|
-
opened = openPackageFile2(
|
|
76847
|
+
opened = openPackageFile2(resolve53(file));
|
|
76547
76848
|
} catch (e) {
|
|
76548
76849
|
io.error(JSON.stringify({ error: e.message }));
|
|
76549
76850
|
return 1;
|
|
@@ -76556,7 +76857,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76556
76857
|
io.error(JSON.stringify({
|
|
76557
76858
|
ok: false,
|
|
76558
76859
|
error: "app_source_not_in_package",
|
|
76559
|
-
detail: `${
|
|
76860
|
+
detail: `${resolve53(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
|
|
76560
76861
|
hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
|
|
76561
76862
|
}));
|
|
76562
76863
|
return 1;
|
|
@@ -76579,7 +76880,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76579
76880
|
return 1;
|
|
76580
76881
|
}
|
|
76581
76882
|
}
|
|
76582
|
-
const dest =
|
|
76883
|
+
const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
|
|
76583
76884
|
const issue2 = restoreDestinationIssue(dest, flags.force === true);
|
|
76584
76885
|
if (issue2) {
|
|
76585
76886
|
io.error(JSON.stringify(issue2));
|
|
@@ -76666,7 +76967,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76666
76967
|
}
|
|
76667
76968
|
try {
|
|
76668
76969
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
76669
|
-
const opened = openPackageFile2(
|
|
76970
|
+
const opened = openPackageFile2(resolve53(file));
|
|
76670
76971
|
if (!opened.validation.ok || !opened.header) {
|
|
76671
76972
|
io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
76672
76973
|
return 1;
|
|
@@ -76676,12 +76977,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76676
76977
|
io.error(JSON.stringify({
|
|
76677
76978
|
ok: false,
|
|
76678
76979
|
error: "refusing to share a package that carries the app's source",
|
|
76679
|
-
detail: `${
|
|
76980
|
+
detail: `${resolve53(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
|
|
76680
76981
|
hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
|
|
76681
76982
|
}));
|
|
76682
76983
|
return 1;
|
|
76683
76984
|
}
|
|
76684
|
-
const archive =
|
|
76985
|
+
const archive = readFileSync80(resolve53(file));
|
|
76685
76986
|
const result = await client2().createPackageShare({
|
|
76686
76987
|
app: opened.header.app,
|
|
76687
76988
|
releaseId: opened.header.releaseId,
|
|
@@ -76757,11 +77058,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76757
77058
|
const app = await appId(dir2);
|
|
76758
77059
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76759
77060
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
76760
|
-
temp = mkdtempSync4(
|
|
77061
|
+
temp = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
|
|
76761
77062
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
76762
77063
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
76763
77064
|
servedMissing = initial.missingBundles;
|
|
76764
|
-
source =
|
|
77065
|
+
source = join65(temp, app);
|
|
76765
77066
|
}
|
|
76766
77067
|
const chromeArg = str8(flags.chrome) ?? "preview";
|
|
76767
77068
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -76797,7 +77098,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76797
77098
|
if (!recordKit) return;
|
|
76798
77099
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
76799
77100
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
76800
|
-
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
77101
|
+
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join65(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
|
|
76801
77102
|
await refreshBoard();
|
|
76802
77103
|
};
|
|
76803
77104
|
const retract = async () => {
|
|
@@ -76820,9 +77121,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76820
77121
|
});
|
|
76821
77122
|
await announce(run2);
|
|
76822
77123
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
76823
|
-
await new Promise((
|
|
77124
|
+
await new Promise((resolve54) => {
|
|
76824
77125
|
const stop = () => {
|
|
76825
|
-
void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() =>
|
|
77126
|
+
void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
|
|
76826
77127
|
};
|
|
76827
77128
|
process.once("SIGINT", stop);
|
|
76828
77129
|
process.once("SIGTERM", stop);
|
|
@@ -76831,7 +77132,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76831
77132
|
}
|
|
76832
77133
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
76833
77134
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
76834
|
-
if (watch2) served = mkdtempSync4(
|
|
77135
|
+
if (watch2) served = mkdtempSync4(join65(tmpdir5(), "himi-run-served-"));
|
|
76835
77136
|
const running = await runPackage2(source, {
|
|
76836
77137
|
port,
|
|
76837
77138
|
chrome: chromeArg,
|
|
@@ -76860,8 +77161,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76860
77161
|
await announce(running);
|
|
76861
77162
|
if (watchKit && bus) {
|
|
76862
77163
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76863
|
-
const live2 =
|
|
76864
|
-
const manifestOf = (tree) => JSON.parse(
|
|
77164
|
+
const live2 = join65(running.releaseRoot, running.app);
|
|
77165
|
+
const manifestOf = (tree) => JSON.parse(readFileSync80(join65(tree, "release-manifest.json"), "utf8"));
|
|
76865
77166
|
let current = manifestOf(live2);
|
|
76866
77167
|
const failed2 = async (message) => {
|
|
76867
77168
|
if (stopping) return;
|
|
@@ -76872,7 +77173,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76872
77173
|
};
|
|
76873
77174
|
rebuild = watchKit.serialize(async () => {
|
|
76874
77175
|
const t0 = Date.now();
|
|
76875
|
-
const next = mkdtempSync4(
|
|
77176
|
+
const next = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
|
|
76876
77177
|
try {
|
|
76877
77178
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
76878
77179
|
if (bres.compileErrors.length) {
|
|
@@ -76889,18 +77190,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76889
77190
|
return;
|
|
76890
77191
|
}
|
|
76891
77192
|
if (stopping) return;
|
|
76892
|
-
const fresh = manifestOf(
|
|
77193
|
+
const fresh = manifestOf(join65(next, running.app));
|
|
76893
77194
|
const diff = watchKit.diffReleases(current, fresh);
|
|
76894
77195
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
76895
|
-
const changes = describeChanges2(live2,
|
|
77196
|
+
const changes = describeChanges2(live2, join65(next, running.app), diff);
|
|
76896
77197
|
const retired = `${live2}.retired-${Date.now()}`;
|
|
76897
77198
|
renameSync7(live2, retired);
|
|
76898
77199
|
try {
|
|
76899
|
-
renameSync7(
|
|
77200
|
+
renameSync7(join65(next, running.app), live2);
|
|
76900
77201
|
} catch {
|
|
76901
|
-
cpSync3(
|
|
77202
|
+
cpSync3(join65(next, running.app), live2, { recursive: true });
|
|
76902
77203
|
}
|
|
76903
|
-
|
|
77204
|
+
rmSync16(retired, { recursive: true, force: true });
|
|
76904
77205
|
current = fresh;
|
|
76905
77206
|
servedMissing = outcome.missingBundles;
|
|
76906
77207
|
for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
|
|
@@ -76910,7 +77211,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76910
77211
|
} catch (e) {
|
|
76911
77212
|
await failed2(e.message.split("\n")[0]);
|
|
76912
77213
|
} finally {
|
|
76913
|
-
|
|
77214
|
+
rmSync16(next, { recursive: true, force: true });
|
|
76914
77215
|
}
|
|
76915
77216
|
});
|
|
76916
77217
|
watcher2 = watchKit.watchContent(dir, () => {
|
|
@@ -76978,9 +77279,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76978
77279
|
io.error(JSON.stringify({ error: e.message }));
|
|
76979
77280
|
return 1;
|
|
76980
77281
|
} finally {
|
|
76981
|
-
if (temp)
|
|
76982
|
-
if (served)
|
|
76983
|
-
if (browserCopy)
|
|
77282
|
+
if (temp) rmSync16(temp, { recursive: true, force: true });
|
|
77283
|
+
if (served) rmSync16(served, { recursive: true, force: true });
|
|
77284
|
+
if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
|
|
76984
77285
|
}
|
|
76985
77286
|
}
|
|
76986
77287
|
case "preview": {
|
|
@@ -77522,7 +77823,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77522
77823
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
77523
77824
|
return 2;
|
|
77524
77825
|
}
|
|
77525
|
-
if (!
|
|
77826
|
+
if (!existsSync67(file)) {
|
|
77526
77827
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
77527
77828
|
return 2;
|
|
77528
77829
|
}
|
|
@@ -77578,7 +77879,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77578
77879
|
lintNote: "`himi patch` sends a raw file. Nothing here built or linted your app \u2014 `himi push --only <selector>` is the same edit with the full lint gate in front of it."
|
|
77579
77880
|
};
|
|
77580
77881
|
if (kind === "tokens" || kind === "app-config") {
|
|
77581
|
-
const body =
|
|
77882
|
+
const body = readFileSync80(file, "utf8");
|
|
77582
77883
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
77583
77884
|
return runReleasePatch({
|
|
77584
77885
|
...common,
|
|
@@ -77593,7 +77894,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77593
77894
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
77594
77895
|
return 2;
|
|
77595
77896
|
}
|
|
77596
|
-
const descriptor =
|
|
77897
|
+
const descriptor = readFileSync80(file, "utf8");
|
|
77597
77898
|
try {
|
|
77598
77899
|
JSON.parse(descriptor);
|
|
77599
77900
|
} catch (e) {
|
|
@@ -77633,7 +77934,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77633
77934
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
77634
77935
|
});
|
|
77635
77936
|
}
|
|
77636
|
-
const bytes2 =
|
|
77937
|
+
const bytes2 = readFileSync80(file);
|
|
77637
77938
|
const sha = createHash31("sha256").update(bytes2).digest("hex");
|
|
77638
77939
|
const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
77639
77940
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -77777,7 +78078,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77777
78078
|
}
|
|
77778
78079
|
let def;
|
|
77779
78080
|
try {
|
|
77780
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
78081
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync80(arg.slice(1), "utf8") : arg);
|
|
77781
78082
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
77782
78083
|
io.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
|
|
77783
78084
|
return 2;
|
|
@@ -78241,7 +78542,7 @@ ${label2}`);
|
|
|
78241
78542
|
const platform = str8(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
78242
78543
|
{
|
|
78243
78544
|
const distDir = contentDir(flags);
|
|
78244
|
-
if (
|
|
78545
|
+
if (existsSync67(join65(distDir, "himalaya.content.json"))) {
|
|
78245
78546
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
78246
78547
|
const errors = issues.filter((i) => i.severity === "error");
|
|
78247
78548
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -78527,7 +78828,7 @@ ${label2}`);
|
|
|
78527
78828
|
const dpxPath = dpxSessionTokenPath();
|
|
78528
78829
|
let dpx;
|
|
78529
78830
|
try {
|
|
78530
|
-
dpx =
|
|
78831
|
+
dpx = readFileSync80(dpxPath, "utf8").trim();
|
|
78531
78832
|
} catch {
|
|
78532
78833
|
io.error(JSON.stringify({ error: `no dpx session at ${dpxPath} \u2014 run \`dpx auth login\` then \`dpx auth token > ${dpxPath}\` (dpx 2.x keeps its own state in ~/.dpx/auth.json and does NOT write the legacy session file), or omit --dpx` }));
|
|
78533
78834
|
return 1;
|
|
@@ -78935,7 +79236,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
78935
79236
|
const path2 = dpxSessionTokenPath();
|
|
78936
79237
|
let raw;
|
|
78937
79238
|
try {
|
|
78938
|
-
raw =
|
|
79239
|
+
raw = readFileSync80(path2, "utf8");
|
|
78939
79240
|
} catch {
|
|
78940
79241
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
78941
79242
|
return 1;
|