@wix/himalaya-cli 0.1114.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 +833 -646
- package/guides/himi-mcp.md +8 -0
- 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 };
|
|
@@ -24718,6 +24719,7 @@ function shouldRevealError(args) {
|
|
|
24718
24719
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
24719
24720
|
var init_validation = __esm({
|
|
24720
24721
|
"../../core/ts/src/validation.ts"() {
|
|
24722
|
+
"use strict";
|
|
24721
24723
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
24722
24724
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
24723
24725
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -27552,12 +27554,12 @@ function createRicosHostSession(o) {
|
|
|
27552
27554
|
flush() {
|
|
27553
27555
|
if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
|
|
27554
27556
|
const requestId2 = newId();
|
|
27555
|
-
return new Promise((
|
|
27557
|
+
return new Promise((resolve54) => {
|
|
27556
27558
|
const timer = t.setTimeout(() => {
|
|
27557
27559
|
flushes.delete(requestId2);
|
|
27558
|
-
|
|
27560
|
+
resolve54(null);
|
|
27559
27561
|
}, flushMs);
|
|
27560
|
-
flushes.set(requestId2, { resolve:
|
|
27562
|
+
flushes.set(requestId2, { resolve: resolve54, timer });
|
|
27561
27563
|
o.send({ v: 1, type: "requestContent", requestId: requestId2 });
|
|
27562
27564
|
});
|
|
27563
27565
|
},
|
|
@@ -27610,7 +27612,7 @@ async function runRicosImageUpload(o) {
|
|
|
27610
27612
|
};
|
|
27611
27613
|
session.insertMediaPlaceholder(requestId2);
|
|
27612
27614
|
try {
|
|
27613
|
-
const entry = await new Promise((
|
|
27615
|
+
const entry = await new Promise((resolve54) => {
|
|
27614
27616
|
let done = false;
|
|
27615
27617
|
let unsub = () => {
|
|
27616
27618
|
};
|
|
@@ -27619,7 +27621,7 @@ async function runRicosImageUpload(o) {
|
|
|
27619
27621
|
done = true;
|
|
27620
27622
|
t.clearTimeout(timer);
|
|
27621
27623
|
queueMicrotask(() => unsub());
|
|
27622
|
-
|
|
27624
|
+
resolve54(v);
|
|
27623
27625
|
};
|
|
27624
27626
|
const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
|
|
27625
27627
|
unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
|
|
@@ -27638,10 +27640,10 @@ async function runRicosImageUpload(o) {
|
|
|
27638
27640
|
} catch {
|
|
27639
27641
|
return fail2("read");
|
|
27640
27642
|
}
|
|
27641
|
-
const
|
|
27643
|
+
const sep18 = entry.uploadUrl.includes("?") ? "&" : "?";
|
|
27642
27644
|
let res;
|
|
27643
27645
|
try {
|
|
27644
|
-
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 });
|
|
27645
27647
|
} catch {
|
|
27646
27648
|
return fail2("put");
|
|
27647
27649
|
}
|
|
@@ -27656,14 +27658,14 @@ async function runRicosImageUpload(o) {
|
|
|
27656
27658
|
const d = root.file && typeof root.file === "object" ? root.file : root;
|
|
27657
27659
|
const id = typeof d.id === "string" ? d.id : "";
|
|
27658
27660
|
if (!id) return fail2("bad_descriptor");
|
|
27659
|
-
const
|
|
27661
|
+
const ok2 = session.resolveMedia(requestId2, {
|
|
27660
27662
|
id,
|
|
27661
27663
|
url: typeof d.url === "string" ? d.url : "",
|
|
27662
27664
|
...typeof d.width === "number" ? { width: d.width } : {},
|
|
27663
27665
|
...typeof d.height === "number" ? { height: d.height } : {},
|
|
27664
27666
|
mimeType: file.mimeType
|
|
27665
27667
|
});
|
|
27666
|
-
return
|
|
27668
|
+
return ok2 ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
|
|
27667
27669
|
} finally {
|
|
27668
27670
|
deps.dispatch({ actionId: `tier5.${svc}.clearUpload`, args: { requestId: requestId2 } });
|
|
27669
27671
|
}
|
|
@@ -29118,6 +29120,7 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
29118
29120
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
29119
29121
|
var init_worker_subtree = __esm({
|
|
29120
29122
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
29123
|
+
"use strict";
|
|
29121
29124
|
init_worker_subtree_safe_types_generated();
|
|
29122
29125
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
29123
29126
|
maxEncodedBytes: 65536,
|
|
@@ -29550,8 +29553,8 @@ function ensureCountUpRuntime() {
|
|
|
29550
29553
|
const neg = fixed.startsWith("-");
|
|
29551
29554
|
const body = neg ? fixed.slice(1) : fixed;
|
|
29552
29555
|
const [int2, frac] = body.split(".");
|
|
29553
|
-
const
|
|
29554
|
-
return (neg ? "-" : "") +
|
|
29556
|
+
const sep18 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
29557
|
+
return (neg ? "-" : "") + sep18 + (frac ? "." + frac : "");
|
|
29555
29558
|
};
|
|
29556
29559
|
const animateEl = (el) => {
|
|
29557
29560
|
const node = el;
|
|
@@ -30372,24 +30375,24 @@ function usesSchematicRoute(props) {
|
|
|
30372
30375
|
const hasRouteFeed = typeof props.routePath === "string" && props.routePath !== "";
|
|
30373
30376
|
return hasFeed && !hasRoute && !hasRouteFeed;
|
|
30374
30377
|
}
|
|
30375
|
-
function longitudeAt(x,
|
|
30376
|
-
return x / (TILE_PX * Math.pow(2,
|
|
30378
|
+
function longitudeAt(x, z3) {
|
|
30379
|
+
return x / (TILE_PX * Math.pow(2, z3)) * 360 - 180;
|
|
30377
30380
|
}
|
|
30378
|
-
function latitudeAt(y,
|
|
30379
|
-
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));
|
|
30380
30383
|
return 180 / Math.PI * Math.atan(Math.sinh(n));
|
|
30381
30384
|
}
|
|
30382
|
-
function regionArgs(centerLat, centerLng,
|
|
30383
|
-
const cx = mercatorX(centerLng,
|
|
30384
|
-
const cy = mercatorY(centerLat,
|
|
30385
|
+
function regionArgs(centerLat, centerLng, z3, w, h) {
|
|
30386
|
+
const cx = mercatorX(centerLng, z3);
|
|
30387
|
+
const cy = mercatorY(centerLat, z3);
|
|
30385
30388
|
return {
|
|
30386
30389
|
latitude: centerLat,
|
|
30387
30390
|
longitude: centerLng,
|
|
30388
|
-
zoom:
|
|
30389
|
-
north: latitudeAt(cy - h / 2,
|
|
30390
|
-
south: latitudeAt(cy + h / 2,
|
|
30391
|
-
east: longitudeAt(cx + w / 2,
|
|
30392
|
-
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)
|
|
30393
30396
|
};
|
|
30394
30397
|
}
|
|
30395
30398
|
function decodeCamera(v) {
|
|
@@ -30419,9 +30422,9 @@ function resolveTileSource(source) {
|
|
|
30419
30422
|
const maxZoom = typeof s.maxZoom === "number" && s.maxZoom > 0 ? s.maxZoom : DEFAULT_TILE_MAX_ZOOM;
|
|
30420
30423
|
return { urlTemplate, attribution, maxZoom };
|
|
30421
30424
|
}
|
|
30422
|
-
function tileUrl(source,
|
|
30423
|
-
if (!source) return `https://tile.openstreetmap.org/${
|
|
30424
|
-
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));
|
|
30425
30428
|
}
|
|
30426
30429
|
function parseShapeKind(raw) {
|
|
30427
30430
|
const k = typeof raw === "string" ? raw.toLowerCase() : "";
|
|
@@ -30438,12 +30441,12 @@ function circleRing(centreLat, centreLng, radiusM, segments = CIRCLE_SEGMENTS) {
|
|
|
30438
30441
|
return { latitude: centreLat + dLat * Math.sin(theta), longitude: centreLng + dLng * Math.cos(theta) };
|
|
30439
30442
|
});
|
|
30440
30443
|
}
|
|
30441
|
-
function distanceToPolylinePx(px, py, points,
|
|
30444
|
+
function distanceToPolylinePx(px, py, points, z3, originX, originY) {
|
|
30442
30445
|
if (points.length < 2) return null;
|
|
30443
30446
|
let best = Infinity;
|
|
30444
30447
|
for (let i = 0; i < points.length - 1; i++) {
|
|
30445
|
-
const ax = mercatorX(points[i].longitude,
|
|
30446
|
-
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;
|
|
30447
30450
|
const dx = bx - ax, dy = by - ay;
|
|
30448
30451
|
const lenSq = dx * dx + dy * dy;
|
|
30449
30452
|
const t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
|
|
@@ -30453,22 +30456,22 @@ function distanceToPolylinePx(px, py, points, z2, originX, originY) {
|
|
|
30453
30456
|
}
|
|
30454
30457
|
return best;
|
|
30455
30458
|
}
|
|
30456
|
-
function polygonContainsPx(px, py, points,
|
|
30459
|
+
function polygonContainsPx(px, py, points, z3, originX, originY) {
|
|
30457
30460
|
if (points.length < 3) return false;
|
|
30458
30461
|
let inside2 = false;
|
|
30459
30462
|
for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
|
|
30460
|
-
const xi = mercatorX(points[i].longitude,
|
|
30461
|
-
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;
|
|
30462
30465
|
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) inside2 = !inside2;
|
|
30463
30466
|
}
|
|
30464
30467
|
return inside2;
|
|
30465
30468
|
}
|
|
30466
|
-
function markerHit(px, py, markers,
|
|
30469
|
+
function markerHit(px, py, markers, z3, originX, originY) {
|
|
30467
30470
|
let best = null;
|
|
30468
30471
|
let bestDistance = MARKER_HIT_RADIUS;
|
|
30469
30472
|
markers.forEach((m, i) => {
|
|
30470
|
-
const dx = mercatorX(m.longitude,
|
|
30471
|
-
const dy = mercatorY(m.latitude,
|
|
30473
|
+
const dx = mercatorX(m.longitude, z3) - originX - px;
|
|
30474
|
+
const dy = mercatorY(m.latitude, z3) - originY - py;
|
|
30472
30475
|
const d = Math.sqrt(dx * dx + dy * dy);
|
|
30473
30476
|
if (d <= bestDistance) {
|
|
30474
30477
|
bestDistance = d;
|
|
@@ -30477,22 +30480,22 @@ function markerHit(px, py, markers, z2, originX, originY) {
|
|
|
30477
30480
|
});
|
|
30478
30481
|
return best;
|
|
30479
30482
|
}
|
|
30480
|
-
function mercatorX(lng,
|
|
30481
|
-
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);
|
|
30482
30485
|
}
|
|
30483
|
-
function mercatorY(lat,
|
|
30486
|
+
function mercatorY(lat, z3) {
|
|
30484
30487
|
const s = Math.max(-85.05112878, Math.min(85.05112878, lat)) * Math.PI / 180;
|
|
30485
|
-
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);
|
|
30486
30489
|
}
|
|
30487
30490
|
function fitZoom(pts, w, h, fallback) {
|
|
30488
30491
|
if (pts.length < 2 || w <= 0 || h <= 0) return fallback;
|
|
30489
30492
|
const lats = pts.map((p) => p.latitude), lngs = pts.map((p) => p.longitude);
|
|
30490
30493
|
const minLa = Math.min(...lats), maxLa = Math.max(...lats);
|
|
30491
30494
|
const minLo = Math.min(...lngs), maxLo = Math.max(...lngs);
|
|
30492
|
-
for (let
|
|
30493
|
-
const dx = Math.abs(mercatorX(maxLo,
|
|
30494
|
-
const dy = Math.abs(mercatorY(maxLa,
|
|
30495
|
-
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;
|
|
30496
30499
|
}
|
|
30497
30500
|
return 1;
|
|
30498
30501
|
}
|
|
@@ -34611,20 +34614,20 @@ var init_renderNode = __esm({
|
|
|
34611
34614
|
const fitted = shouldFit ? fitZoom(all, W - 48, H - 48, declared) : declared;
|
|
34612
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;
|
|
34613
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;
|
|
34614
|
-
const
|
|
34617
|
+
const z3 = userCam?.z ?? fitted;
|
|
34615
34618
|
const cLat = userCam?.lat ?? baseLat;
|
|
34616
34619
|
const cLng = userCam?.lng ?? baseLng;
|
|
34617
34620
|
React7.useEffect(() => {
|
|
34618
|
-
const resolved2 = resolveCamera(commandedCamera, cLat, cLng,
|
|
34621
|
+
const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z3);
|
|
34619
34622
|
if (!resolved2) return;
|
|
34620
34623
|
setUserCam({
|
|
34621
34624
|
lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
|
|
34622
34625
|
lng: resolved2.longitude,
|
|
34623
|
-
z: Math.max(1, Math.min(19, resolved2.zoom ??
|
|
34626
|
+
z: Math.max(1, Math.min(19, resolved2.zoom ?? z3))
|
|
34624
34627
|
});
|
|
34625
34628
|
}, [commandedCamera]);
|
|
34626
|
-
const originX = mercatorX(cLng,
|
|
34627
|
-
const originY = mercatorY(cLat,
|
|
34629
|
+
const originX = mercatorX(cLng, z3) - W / 2;
|
|
34630
|
+
const originY = mercatorY(cLat, z3) - H / 2;
|
|
34628
34631
|
const interactive = pinsOnly ? props.interactive === true : props.interactive !== false;
|
|
34629
34632
|
const resolvedTileSource = resolveTileSource(props.tileSource);
|
|
34630
34633
|
const fireMapEvent = (action, payload) => {
|
|
@@ -34642,7 +34645,7 @@ var init_renderNode = __esm({
|
|
|
34642
34645
|
const { kx, ky } = layoutScale(el);
|
|
34643
34646
|
const px = (e.clientX - r.left) * kx - el.clientLeft;
|
|
34644
34647
|
const py = (e.clientY - r.top) * ky - el.clientTop;
|
|
34645
|
-
const hit = markerHit(px, py, markers,
|
|
34648
|
+
const hit = markerHit(px, py, markers, z3, originX, originY);
|
|
34646
34649
|
if (hit !== null) {
|
|
34647
34650
|
const m = markers[hit];
|
|
34648
34651
|
const payload = { index: hit, latitude: m.latitude, longitude: m.longitude };
|
|
@@ -34653,10 +34656,10 @@ var init_renderNode = __esm({
|
|
|
34653
34656
|
const shapeIndex = shapes.findIndex((sh) => {
|
|
34654
34657
|
if (sh.kind === "unknown" || sh.points.length < 2) return false;
|
|
34655
34658
|
if (sh.kind === "line") {
|
|
34656
|
-
const d2 = distanceToPolylinePx(px, py, sh.points,
|
|
34659
|
+
const d2 = distanceToPolylinePx(px, py, sh.points, z3, originX, originY);
|
|
34657
34660
|
return d2 !== null && d2 <= SHAPE_HIT_RADIUS;
|
|
34658
34661
|
}
|
|
34659
|
-
return polygonContainsPx(px, py, sh.points,
|
|
34662
|
+
return polygonContainsPx(px, py, sh.points, z3, originX, originY);
|
|
34660
34663
|
});
|
|
34661
34664
|
if (shapeIndex >= 0 && props.onShapeTap) {
|
|
34662
34665
|
const sh = shapes[shapeIndex];
|
|
@@ -34665,15 +34668,15 @@ var init_renderNode = __esm({
|
|
|
34665
34668
|
fireMapEvent(props.onShapeTap, payload);
|
|
34666
34669
|
} else {
|
|
34667
34670
|
fireMapEvent(props.onMapTap, {
|
|
34668
|
-
latitude: latitudeAt(originY + py,
|
|
34669
|
-
longitude: longitudeAt(originX + px,
|
|
34671
|
+
latitude: latitudeAt(originY + py, z3),
|
|
34672
|
+
longitude: longitudeAt(originX + px, z3)
|
|
34670
34673
|
});
|
|
34671
34674
|
}
|
|
34672
34675
|
}
|
|
34673
34676
|
};
|
|
34674
34677
|
const onPointerDown = (e) => {
|
|
34675
34678
|
if (!interactive) return;
|
|
34676
|
-
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) };
|
|
34677
34680
|
dragMovedRef.current = false;
|
|
34678
34681
|
};
|
|
34679
34682
|
const onPointerMove = (e) => {
|
|
@@ -34697,8 +34700,8 @@ var init_renderNode = __esm({
|
|
|
34697
34700
|
const onWheel = (e) => {
|
|
34698
34701
|
if (!interactive) return;
|
|
34699
34702
|
e.preventDefault();
|
|
34700
|
-
const next = Math.max(1, Math.min(19,
|
|
34701
|
-
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 });
|
|
34702
34705
|
};
|
|
34703
34706
|
React7.useEffect(() => {
|
|
34704
34707
|
const action = props.onRegionChange;
|
|
@@ -34709,22 +34712,22 @@ var init_renderNode = __esm({
|
|
|
34709
34712
|
regionReportedRef.current = true;
|
|
34710
34713
|
return;
|
|
34711
34714
|
}
|
|
34712
|
-
fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng,
|
|
34715
|
+
fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z3, W, H) } });
|
|
34713
34716
|
}, 250);
|
|
34714
34717
|
return () => clearTimeout(t);
|
|
34715
|
-
}, [cLat, cLng,
|
|
34716
|
-
const sx = (p) => mercatorX(p.longitude,
|
|
34717
|
-
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;
|
|
34718
34721
|
const accent = C("accentPrimary", "#116DFF");
|
|
34719
|
-
const n = Math.pow(2,
|
|
34722
|
+
const n = Math.pow(2, z3);
|
|
34720
34723
|
const tiles = [];
|
|
34721
34724
|
for (let tx = Math.floor(originX / TILE_PX); tx <= Math.floor((originX + W) / TILE_PX); tx++) {
|
|
34722
34725
|
for (let ty = Math.floor(originY / TILE_PX); ty <= Math.floor((originY + H) / TILE_PX); ty++) {
|
|
34723
34726
|
if (ty < 0 || ty >= n) continue;
|
|
34724
34727
|
const wrapX = (tx % n + n) % n;
|
|
34725
34728
|
tiles.push({
|
|
34726
|
-
key: `${
|
|
34727
|
-
src: tileUrl(resolvedTileSource,
|
|
34729
|
+
key: `${z3}/${wrapX}/${ty}`,
|
|
34730
|
+
src: tileUrl(resolvedTileSource, z3, wrapX, ty),
|
|
34728
34731
|
left: tx * TILE_PX - originX,
|
|
34729
34732
|
top: ty * TILE_PX - originY
|
|
34730
34733
|
});
|
|
@@ -34736,7 +34739,7 @@ var init_renderNode = __esm({
|
|
|
34736
34739
|
ref: attachBox,
|
|
34737
34740
|
"data-map-mode": "tile",
|
|
34738
34741
|
"data-route-points": route.length,
|
|
34739
|
-
"data-map-zoom":
|
|
34742
|
+
"data-map-zoom": z3,
|
|
34740
34743
|
onClick: onSurfaceClick,
|
|
34741
34744
|
onPointerDown,
|
|
34742
34745
|
onPointerMove,
|
|
@@ -35902,7 +35905,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
35902
35905
|
const browser = globalThis;
|
|
35903
35906
|
browser.document.documentElement.style.colorScheme = selected;
|
|
35904
35907
|
await browser.document.fonts?.ready;
|
|
35905
|
-
await new Promise((
|
|
35908
|
+
await new Promise((resolve54) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve54())));
|
|
35906
35909
|
}, scheme);
|
|
35907
35910
|
}
|
|
35908
35911
|
async function renderPngBatch(items) {
|
|
@@ -39543,7 +39546,7 @@ async function handleWebWix(req, res, state) {
|
|
|
39543
39546
|
}
|
|
39544
39547
|
if (match) {
|
|
39545
39548
|
const mocked = match.rule.response;
|
|
39546
|
-
if (mocked.delayMs) await new Promise((
|
|
39549
|
+
if (mocked.delayMs) await new Promise((resolve54) => setTimeout(resolve54, mocked.delayMs));
|
|
39547
39550
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
39548
39551
|
record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
|
|
39549
39552
|
return reply(200, { status: mocked.status, body: responseBody ?? "" });
|
|
@@ -40537,8 +40540,8 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
40537
40540
|
}
|
|
40538
40541
|
async function serveStatic(req, res, root, prefix) {
|
|
40539
40542
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
40540
|
-
const
|
|
40541
|
-
const safe = normalize3(
|
|
40543
|
+
const relative15 = requested.replace(prefix, "").replace(/^\//, "");
|
|
40544
|
+
const safe = normalize3(relative15).replace(/^(\.\.[\/\\])+/, "");
|
|
40542
40545
|
const fullPath = resolve33(root, safe);
|
|
40543
40546
|
if (!fullPath.startsWith(root)) {
|
|
40544
40547
|
return send(res, 403, "forbidden");
|
|
@@ -41269,8 +41272,8 @@ function sha256hex(b) {
|
|
|
41269
41272
|
function stableStringify(value) {
|
|
41270
41273
|
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
41271
41274
|
if (Array.isArray(value)) return "[" + value.map(stableStringify).join(",") + "]";
|
|
41272
|
-
const
|
|
41273
|
-
return "{" + Object.keys(
|
|
41275
|
+
const object3 = value;
|
|
41276
|
+
return "{" + Object.keys(object3).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object3[key2])).join(",") + "}";
|
|
41274
41277
|
}
|
|
41275
41278
|
function manifestContent(m) {
|
|
41276
41279
|
const {
|
|
@@ -41642,12 +41645,12 @@ var init_query = __esm({
|
|
|
41642
41645
|
});
|
|
41643
41646
|
|
|
41644
41647
|
// ../../core/dev-server/src/crawl-input.ts
|
|
41645
|
-
function resolved(v,
|
|
41646
|
-
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;
|
|
41647
41650
|
if (Array.isArray(v)) {
|
|
41648
41651
|
const out2 = v.flatMap((el) => {
|
|
41649
41652
|
if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
|
|
41650
|
-
const r =
|
|
41653
|
+
const r = resolve54(el);
|
|
41651
41654
|
return Array.isArray(r) ? r : [r];
|
|
41652
41655
|
});
|
|
41653
41656
|
return out2;
|
|
@@ -41661,9 +41664,9 @@ function hasRowBinding(props) {
|
|
|
41661
41664
|
return itemToken(v) || Array.isArray(v) && v.some(itemToken);
|
|
41662
41665
|
});
|
|
41663
41666
|
}
|
|
41664
|
-
function declaredOptionIds(props,
|
|
41667
|
+
function declaredOptionIds(props, resolve54) {
|
|
41665
41668
|
const literal = props.options ?? props.tabs ?? props.chips;
|
|
41666
|
-
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath,
|
|
41669
|
+
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve54) : void 0;
|
|
41667
41670
|
const raw = Array.isArray(bound) ? bound : literal;
|
|
41668
41671
|
if (!Array.isArray(raw)) return [];
|
|
41669
41672
|
const out2 = [];
|
|
@@ -41706,24 +41709,24 @@ function seedTokens(state, limit = 48) {
|
|
|
41706
41709
|
walk2(state, 0);
|
|
41707
41710
|
return out2;
|
|
41708
41711
|
}
|
|
41709
|
-
function synthesizeInput(control,
|
|
41712
|
+
function synthesizeInput(control, resolve54, tokens) {
|
|
41710
41713
|
const id = `${control.type}.${control.callback}`;
|
|
41711
41714
|
const row = SYNTHESIZED_CONTROLS[id];
|
|
41712
41715
|
if (!row) return null;
|
|
41713
41716
|
const props = control.props;
|
|
41714
41717
|
if (hasRowBinding(props)) return null;
|
|
41715
41718
|
if (row.from === "declared-options") {
|
|
41716
|
-
const ids = declaredOptionIds(props,
|
|
41719
|
+
const ids = declaredOptionIds(props, resolve54);
|
|
41717
41720
|
if (!ids.length) return null;
|
|
41718
41721
|
if (row.encoding === "string-array") {
|
|
41719
|
-
const currentRaw2 = resolved(props.selectedIds,
|
|
41722
|
+
const currentRaw2 = resolved(props.selectedIds, resolve54);
|
|
41720
41723
|
const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
|
|
41721
41724
|
const pick4 = ids.find((o) => !current3.includes(o));
|
|
41722
41725
|
if (pick4 === void 0) return null;
|
|
41723
41726
|
const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
|
|
41724
41727
|
return { key: row.key, value, from: row.from, current: current3, control: id };
|
|
41725
41728
|
}
|
|
41726
|
-
const currentRaw = resolved(props.selectedId,
|
|
41729
|
+
const currentRaw = resolved(props.selectedId, resolve54);
|
|
41727
41730
|
const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
|
|
41728
41731
|
const pick3 = ids.find((o) => o !== current2);
|
|
41729
41732
|
if (pick3 === void 0) return null;
|
|
@@ -41731,7 +41734,7 @@ function synthesizeInput(control, resolve53, tokens) {
|
|
|
41731
41734
|
}
|
|
41732
41735
|
if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
|
|
41733
41736
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
|
|
41734
|
-
const bound = binding2 === void 0 ? void 0 :
|
|
41737
|
+
const bound = binding2 === void 0 ? void 0 : resolve54(binding2);
|
|
41735
41738
|
const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
|
|
41736
41739
|
const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
|
|
41737
41740
|
const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
|
|
@@ -43216,8 +43219,8 @@ async function crawlScreenInner(opts) {
|
|
|
43216
43219
|
if (linkable.has(target)) return true;
|
|
43217
43220
|
for (const base of linkable) {
|
|
43218
43221
|
if (target.length > base.length + 1 && target.startsWith(base)) {
|
|
43219
|
-
const
|
|
43220
|
-
if (
|
|
43222
|
+
const sep18 = target[base.length];
|
|
43223
|
+
if (sep18 === "_" || sep18 === "/") return true;
|
|
43221
43224
|
}
|
|
43222
43225
|
}
|
|
43223
43226
|
return false;
|
|
@@ -46244,7 +46247,7 @@ var init_studio_timeline = __esm({
|
|
|
46244
46247
|
isStr = (x) => typeof x === "string";
|
|
46245
46248
|
isObj2 = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
|
|
46246
46249
|
strs = (x) => Array.isArray(x) && x.every(isStr);
|
|
46247
|
-
nullOr = (x,
|
|
46250
|
+
nullOr = (x, ok2) => x === null || isObj2(x) && ok2(x);
|
|
46248
46251
|
accentOf = (palette2) => {
|
|
46249
46252
|
for (const p of palette2 ?? []) {
|
|
46250
46253
|
const [name, hex2] = Array.isArray(p) ? p : [p.name, p.hex];
|
|
@@ -47194,16 +47197,16 @@ function pushSetupBodyBytes(body) {
|
|
|
47194
47197
|
return Buffer.byteLength(JSON.stringify(body), "utf8");
|
|
47195
47198
|
}
|
|
47196
47199
|
async function pushSetupRequest(options) {
|
|
47197
|
-
const
|
|
47198
|
-
if (!options.target.controlToken) return
|
|
47199
|
-
if (!options.wixToken) return
|
|
47200
|
-
if (credentialHostRefusal(options.target.control)) return
|
|
47201
|
-
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");
|
|
47202
47205
|
const setup = options.operation === "setup";
|
|
47203
|
-
if (setup && !options.body) return
|
|
47204
|
-
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");
|
|
47205
47208
|
if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
|
|
47206
|
-
return
|
|
47209
|
+
return refuse6("push_setup_body_too_large");
|
|
47207
47210
|
}
|
|
47208
47211
|
const base = options.target.control.replace(/\/+$/, "");
|
|
47209
47212
|
let path2 = "/v1/admin/push/setup";
|
|
@@ -51021,8 +51024,8 @@ function baseOf(target, linkable, known) {
|
|
|
51021
51024
|
let best = null;
|
|
51022
51025
|
for (const base of linkable ?? []) {
|
|
51023
51026
|
if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
|
|
51024
|
-
const
|
|
51025
|
-
if ((
|
|
51027
|
+
const sep18 = target[base.length];
|
|
51028
|
+
if ((sep18 === "_" || sep18 === "/") && (!best || base.length > best.length)) best = base;
|
|
51026
51029
|
}
|
|
51027
51030
|
return best;
|
|
51028
51031
|
}
|
|
@@ -52263,7 +52266,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
52263
52266
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
52264
52267
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
52265
52268
|
const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
|
|
52266
|
-
return await new Promise((
|
|
52269
|
+
return await new Promise((resolve54, reject) => {
|
|
52267
52270
|
let settled = false;
|
|
52268
52271
|
const finish2 = (fn) => {
|
|
52269
52272
|
if (settled) return;
|
|
@@ -52300,7 +52303,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
52300
52303
|
}
|
|
52301
52304
|
const responseHeaders = new Headers();
|
|
52302
52305
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
52303
|
-
|
|
52306
|
+
resolve54(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
52304
52307
|
}));
|
|
52305
52308
|
});
|
|
52306
52309
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -52600,7 +52603,7 @@ function createLocalTestSandbox() {
|
|
|
52600
52603
|
}
|
|
52601
52604
|
})();
|
|
52602
52605
|
`;
|
|
52603
|
-
return await new Promise((
|
|
52606
|
+
return await new Promise((resolve54, reject) => {
|
|
52604
52607
|
const { port1, port2 } = new MessageChannel();
|
|
52605
52608
|
const serializableContext = {
|
|
52606
52609
|
auth: context.auth,
|
|
@@ -52676,7 +52679,7 @@ function createLocalTestSandbox() {
|
|
|
52676
52679
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
52677
52680
|
return;
|
|
52678
52681
|
}
|
|
52679
|
-
if (message.ok) finish2(() =>
|
|
52682
|
+
if (message.ok) finish2(() => resolve54({ value: message.value, durationMs: Date.now() - started }));
|
|
52680
52683
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
52681
52684
|
});
|
|
52682
52685
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -53853,9 +53856,187 @@ var init_cli_bridge = __esm({
|
|
|
53853
53856
|
}
|
|
53854
53857
|
});
|
|
53855
53858
|
|
|
53856
|
-
// 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";
|
|
53857
53862
|
import * as z from "zod";
|
|
53858
|
-
|
|
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";
|
|
53859
54040
|
function fromCli(r, extra = []) {
|
|
53860
54041
|
const body = r.json !== void 0 ? JSON.stringify(r.json, null, 2) : r.text.trim();
|
|
53861
54042
|
const content = [];
|
|
@@ -53867,7 +54048,7 @@ ${r.stderr.trim()}`) });
|
|
|
53867
54048
|
}
|
|
53868
54049
|
async function appDir2(args, deps) {
|
|
53869
54050
|
const base = await deps.defaultDir();
|
|
53870
|
-
return typeof args.dir === "string" && args.dir ?
|
|
54051
|
+
return typeof args.dir === "string" && args.dir ? resolve46(base, args.dir) : base;
|
|
53871
54052
|
}
|
|
53872
54053
|
function loginResult(s) {
|
|
53873
54054
|
switch (s.state) {
|
|
@@ -53906,8 +54087,8 @@ function guarded(h) {
|
|
|
53906
54087
|
return h(args, deps);
|
|
53907
54088
|
};
|
|
53908
54089
|
}
|
|
53909
|
-
function himiTools() {
|
|
53910
|
-
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) }));
|
|
53911
54092
|
}
|
|
53912
54093
|
function rawTools() {
|
|
53913
54094
|
return [
|
|
@@ -53916,7 +54097,7 @@ function rawTools() {
|
|
|
53916
54097
|
title: "Read a himi authoring guide",
|
|
53917
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.",
|
|
53918
54099
|
annotations: LEARN,
|
|
53919
|
-
inputSchema:
|
|
54100
|
+
inputSchema: z2.object({ topic: z2.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
|
|
53920
54101
|
handler: async (a, d) => fromCli(await d.runCli(["docs", ...typeof a.topic === "string" && a.topic ? [a.topic] : [], "--json"]))
|
|
53921
54102
|
},
|
|
53922
54103
|
{
|
|
@@ -53924,7 +54105,7 @@ function rawTools() {
|
|
|
53924
54105
|
title: "SDUI component vocabulary",
|
|
53925
54106
|
description: "The SDUI component vocabulary and props a descriptor may use; a name returns that one component. Offline.",
|
|
53926
54107
|
annotations: LEARN,
|
|
53927
|
-
inputSchema:
|
|
54108
|
+
inputSchema: z2.object({ name: z2.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
|
|
53928
54109
|
handler: async (a, d) => fromCli(await d.runCli(["components", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
|
|
53929
54110
|
},
|
|
53930
54111
|
{
|
|
@@ -53932,7 +54113,7 @@ function rawTools() {
|
|
|
53932
54113
|
title: "Importable @himalaya SDKs",
|
|
53933
54114
|
description: "The @himalaya/* SDKs a Tier-5 worker may import; a name returns that SDK's typed API. Offline.",
|
|
53934
54115
|
annotations: LEARN,
|
|
53935
|
-
inputSchema:
|
|
54116
|
+
inputSchema: z2.object({ name: z2.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
|
|
53936
54117
|
handler: async (a, d) => fromCli(await d.runCli(["sdk", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
|
|
53937
54118
|
},
|
|
53938
54119
|
{
|
|
@@ -53940,7 +54121,7 @@ function rawTools() {
|
|
|
53940
54121
|
title: "Icon name vocabulary",
|
|
53941
54122
|
description: "The valid Icon.name values. An unknown name renders a fallback glyph and `himi_validate` warns. Offline.",
|
|
53942
54123
|
annotations: LEARN,
|
|
53943
|
-
inputSchema:
|
|
54124
|
+
inputSchema: z2.object({}),
|
|
53944
54125
|
handler: async (_a, d) => fromCli(await d.runCli(["icons", "--json"]))
|
|
53945
54126
|
},
|
|
53946
54127
|
{
|
|
@@ -53948,14 +54129,14 @@ function rawTools() {
|
|
|
53948
54129
|
title: "Create a new himi app",
|
|
53949
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.",
|
|
53950
54131
|
annotations: LOCAL_WRITE,
|
|
53951
|
-
inputSchema:
|
|
53952
|
-
name:
|
|
53953
|
-
parentDir:
|
|
53954
|
-
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).")
|
|
53955
54136
|
}),
|
|
53956
54137
|
handler: async (a, d) => {
|
|
53957
54138
|
const base = await d.defaultDir();
|
|
53958
|
-
const parent = typeof a.parentDir === "string" && a.parentDir ?
|
|
54139
|
+
const parent = typeof a.parentDir === "string" && a.parentDir ? resolve46(base, a.parentDir) : base;
|
|
53959
54140
|
return fromCli(await d.runCli(["init", String(a.name), "--dir", parent, ...opt("--template", a.template)]));
|
|
53960
54141
|
}
|
|
53961
54142
|
},
|
|
@@ -53964,7 +54145,7 @@ function rawTools() {
|
|
|
53964
54145
|
title: "Build the app's worker bundles",
|
|
53965
54146
|
description: "Compile every tier5-src/<name>/index.ts to dist/bundles/<name>.bundle.js with esbuild. Writes dist/ only.",
|
|
53966
54147
|
annotations: LOCAL_WRITE,
|
|
53967
|
-
inputSchema:
|
|
54148
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
53968
54149
|
handler: async (a, d) => fromCli(await d.runCli(["build", "--content", await appDir2(a, d)]))
|
|
53969
54150
|
},
|
|
53970
54151
|
{
|
|
@@ -53972,7 +54153,7 @@ function rawTools() {
|
|
|
53972
54153
|
title: "Validate the app",
|
|
53973
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.",
|
|
53974
54155
|
annotations: CHECK,
|
|
53975
|
-
inputSchema:
|
|
54156
|
+
inputSchema: z2.object({ dir: DIR2, strict: z2.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
|
|
53976
54157
|
handler: async (a, d) => fromCli(await d.runCli(["validate", "--content", await appDir2(a, d), ...sw("--strict", a.strict)]))
|
|
53977
54158
|
},
|
|
53978
54159
|
{
|
|
@@ -53980,10 +54161,10 @@ function rawTools() {
|
|
|
53980
54161
|
title: "Behavioral crawl",
|
|
53981
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.",
|
|
53982
54163
|
annotations: CHECK,
|
|
53983
|
-
inputSchema:
|
|
53984
|
-
dir:
|
|
53985
|
-
screens:
|
|
53986
|
-
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.")
|
|
53987
54168
|
}),
|
|
53988
54169
|
handler: async (a, d) => {
|
|
53989
54170
|
const screens = Array.isArray(a.screens) ? a.screens.filter((s) => typeof s === "string") : [];
|
|
@@ -53995,13 +54176,13 @@ function rawTools() {
|
|
|
53995
54176
|
title: "Render a screen to PNG",
|
|
53996
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.",
|
|
53997
54178
|
annotations: CHECK,
|
|
53998
|
-
inputSchema:
|
|
53999
|
-
screen:
|
|
54000
|
-
dir:
|
|
54001
|
-
scheme:
|
|
54002
|
-
width:
|
|
54003
|
-
device:
|
|
54004
|
-
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()
|
|
54005
54186
|
}),
|
|
54006
54187
|
handler: async (a, d) => {
|
|
54007
54188
|
const r = await d.runCli([
|
|
@@ -54031,12 +54212,12 @@ function rawTools() {
|
|
|
54031
54212
|
title: "Build journal",
|
|
54032
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).",
|
|
54033
54214
|
annotations: { ...LOCAL_WRITE, idempotentHint: false },
|
|
54034
|
-
inputSchema:
|
|
54035
|
-
dir:
|
|
54036
|
-
message:
|
|
54037
|
-
step:
|
|
54038
|
-
noImage:
|
|
54039
|
-
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()
|
|
54040
54221
|
}),
|
|
54041
54222
|
handler: async (a, d) => {
|
|
54042
54223
|
const dir = await appDir2(a, d);
|
|
@@ -54049,7 +54230,7 @@ function rawTools() {
|
|
|
54049
54230
|
title: "Start the live preview",
|
|
54050
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,
|
|
54051
54232
|
annotations: LOCAL_WRITE,
|
|
54052
|
-
inputSchema:
|
|
54233
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54053
54234
|
handler: async (a, d) => {
|
|
54054
54235
|
try {
|
|
54055
54236
|
return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
|
|
@@ -54066,7 +54247,7 @@ ${log}` : ""}`, true);
|
|
|
54066
54247
|
title: "Live preview status",
|
|
54067
54248
|
description: "Whether this app's live preview is running, and its URL and last build result.",
|
|
54068
54249
|
annotations: CHECK,
|
|
54069
|
-
inputSchema:
|
|
54250
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54070
54251
|
handler: async (a, d) => json3(await d.preview.status(await appDir2(a, d)))
|
|
54071
54252
|
},
|
|
54072
54253
|
{
|
|
@@ -54074,7 +54255,7 @@ ${log}` : ""}`, true);
|
|
|
54074
54255
|
title: "Stop the live preview",
|
|
54075
54256
|
description: "Stop this app's live preview (the `himi run --watch` a `himi_preview_start` started).",
|
|
54076
54257
|
annotations: { ...LOCAL_WRITE, destructiveHint: false },
|
|
54077
|
-
inputSchema:
|
|
54258
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54078
54259
|
handler: async (a, d) => json3(await d.preview.stop(await appDir2(a, d)))
|
|
54079
54260
|
},
|
|
54080
54261
|
{
|
|
@@ -54082,7 +54263,7 @@ ${log}` : ""}`, true);
|
|
|
54082
54263
|
title: "Signed-in identity",
|
|
54083
54264
|
description: "The identity the stored serve-plane credential carries (account, scope, expiry). Local \u2014 decodes the stored token, no network.",
|
|
54084
54265
|
annotations: LEARN,
|
|
54085
|
-
inputSchema:
|
|
54266
|
+
inputSchema: z2.object({ target: z2.string().optional().describe("Serve target. Default: the CLI's default.") }),
|
|
54086
54267
|
handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target ?? d.login.target())]))
|
|
54087
54268
|
},
|
|
54088
54269
|
{
|
|
@@ -54090,9 +54271,9 @@ ${log}` : ""}`, true);
|
|
|
54090
54271
|
title: "Sign in to Wix",
|
|
54091
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.",
|
|
54092
54273
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
54093
|
-
inputSchema:
|
|
54094
|
-
target:
|
|
54095
|
-
switchAccount:
|
|
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).")
|
|
54096
54277
|
}),
|
|
54097
54278
|
handler: async (a, d) => {
|
|
54098
54279
|
const s = d.login.status();
|
|
@@ -54112,10 +54293,10 @@ ${log}` : ""}`, true);
|
|
|
54112
54293
|
title: "Publish a draft",
|
|
54113
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).",
|
|
54114
54295
|
annotations: PUBLISH,
|
|
54115
|
-
inputSchema:
|
|
54116
|
-
dir:
|
|
54117
|
-
label:
|
|
54118
|
-
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.")
|
|
54119
54300
|
}),
|
|
54120
54301
|
handler: async (a, d) => {
|
|
54121
54302
|
const gate = await requireLogin(d);
|
|
@@ -54128,14 +54309,14 @@ ${log}` : ""}`, true);
|
|
|
54128
54309
|
title: "Share a .himi package link",
|
|
54129
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).",
|
|
54130
54311
|
annotations: PUBLISH,
|
|
54131
|
-
inputSchema:
|
|
54132
|
-
file:
|
|
54133
|
-
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.")
|
|
54134
54315
|
}),
|
|
54135
54316
|
handler: async (a, d) => {
|
|
54136
54317
|
const gate = await requireLogin(d);
|
|
54137
54318
|
if (gate) return gate;
|
|
54138
|
-
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())]));
|
|
54139
54320
|
}
|
|
54140
54321
|
},
|
|
54141
54322
|
{
|
|
@@ -54145,19 +54326,20 @@ ${log}` : ""}`, true);
|
|
|
54145
54326
|
// Not idempotent: with credentials, each `himi preview` mints a fresh single-use handover —
|
|
54146
54327
|
// the same reason the hosted connector's tool of this name says false (RFC 0064 §5).
|
|
54147
54328
|
annotations: { ...PUBLISH, readOnlyHint: true, idempotentHint: false },
|
|
54148
|
-
inputSchema:
|
|
54149
|
-
app:
|
|
54150
|
-
release:
|
|
54151
|
-
screen:
|
|
54152
|
-
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()
|
|
54153
54334
|
}),
|
|
54154
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())]))
|
|
54155
54336
|
}
|
|
54156
54337
|
];
|
|
54157
54338
|
}
|
|
54158
|
-
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;
|
|
54159
54340
|
var init_tools = __esm({
|
|
54160
54341
|
"src/mcp/tools.ts"() {
|
|
54342
|
+
init_file_tools();
|
|
54161
54343
|
MAX_TEXT2 = 8e4;
|
|
54162
54344
|
clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
|
|
54163
54345
|
\u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
|
|
@@ -54165,7 +54347,7 @@ var init_tools = __esm({
|
|
|
54165
54347
|
json3 = (o) => text6(JSON.stringify(o, null, 2));
|
|
54166
54348
|
opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
|
|
54167
54349
|
sw = (flag, v) => v === true ? [flag] : [];
|
|
54168
|
-
|
|
54350
|
+
DIR2 = z2.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
|
|
54169
54351
|
LEARN = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54170
54352
|
CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54171
54353
|
LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
@@ -54194,12 +54376,12 @@ function createLoginSession(deps) {
|
|
|
54194
54376
|
current = pending;
|
|
54195
54377
|
const out2 = [];
|
|
54196
54378
|
const err = [];
|
|
54197
|
-
return new Promise((
|
|
54379
|
+
return new Promise((resolve54) => {
|
|
54198
54380
|
let answered = false;
|
|
54199
54381
|
const answer = () => {
|
|
54200
54382
|
if (answered) return;
|
|
54201
54383
|
answered = true;
|
|
54202
|
-
|
|
54384
|
+
resolve54(current);
|
|
54203
54385
|
};
|
|
54204
54386
|
let child;
|
|
54205
54387
|
try {
|
|
@@ -54258,7 +54440,7 @@ __export(server_exports, {
|
|
|
54258
54440
|
protectStdout: () => protectStdout,
|
|
54259
54441
|
startMcpServer: () => startMcpServer
|
|
54260
54442
|
});
|
|
54261
|
-
import { readFileSync as
|
|
54443
|
+
import { readFileSync as readFileSync60 } from "node:fs";
|
|
54262
54444
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
54263
54445
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
54264
54446
|
import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
@@ -54268,9 +54450,9 @@ function protectStdout() {
|
|
|
54268
54450
|
console.info = toErr;
|
|
54269
54451
|
console.debug = toErr;
|
|
54270
54452
|
}
|
|
54271
|
-
function buildServer(deps, version2) {
|
|
54453
|
+
function buildServer(deps, version2, tools = {}) {
|
|
54272
54454
|
const server = new McpServer({ name: "himi", version: version2 }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
|
|
54273
|
-
for (const tool of himiTools()) {
|
|
54455
|
+
for (const tool of himiTools(tools)) {
|
|
54274
54456
|
server.registerTool(
|
|
54275
54457
|
tool.name,
|
|
54276
54458
|
{ title: tool.title, description: tool.description, inputSchema: tool.inputSchema, annotations: { title: tool.title, ...tool.annotations } },
|
|
@@ -54304,23 +54486,23 @@ async function startMcpServer(opts) {
|
|
|
54304
54486
|
// next call rather than pinning every later tool to the server's cwd (often $HOME for a GUI host).
|
|
54305
54487
|
defaultDir: async () => {
|
|
54306
54488
|
if (!rootDir && pinned) rootDir = await firstRoot(pinned);
|
|
54307
|
-
return rootDir || process.cwd();
|
|
54489
|
+
return rootDir || opts.workspace || process.cwd();
|
|
54308
54490
|
},
|
|
54309
54491
|
preview: {
|
|
54310
54492
|
start: (dir) => startPreview(dir, { port: previewPortForDir(dir) }, previewDeps),
|
|
54311
54493
|
status: (dir) => previewStatus(dir, previewDeps),
|
|
54312
54494
|
stop: (dir) => stopPreview(dir, previewDeps)
|
|
54313
54495
|
},
|
|
54314
|
-
readFile: (p) =>
|
|
54496
|
+
readFile: (p) => readFileSync60(p),
|
|
54315
54497
|
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
|
|
54316
54498
|
};
|
|
54317
|
-
const closed = new Promise((
|
|
54318
|
-
stdin.once("end",
|
|
54319
|
-
stdin.once("close",
|
|
54499
|
+
const closed = new Promise((resolve54) => {
|
|
54500
|
+
stdin.once("end", resolve54);
|
|
54501
|
+
stdin.once("close", resolve54);
|
|
54320
54502
|
});
|
|
54321
54503
|
const handle = serveStdio(
|
|
54322
54504
|
() => {
|
|
54323
|
-
pinned = buildServer(deps, opts.version);
|
|
54505
|
+
pinned = buildServer(deps, opts.version, { withFiles: opts.withFiles });
|
|
54324
54506
|
return pinned;
|
|
54325
54507
|
},
|
|
54326
54508
|
{ transport: new StdioServerTransport(stdin, stdout), onerror: (e) => console.error(`[himi mcp] ${e.message}`) }
|
|
@@ -54354,9 +54536,9 @@ __export(native_decode_exports, {
|
|
|
54354
54536
|
runNativeDecode: () => runNativeDecode
|
|
54355
54537
|
});
|
|
54356
54538
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
54357
|
-
import { existsSync as
|
|
54539
|
+
import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync22 } from "node:fs";
|
|
54358
54540
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
54359
|
-
import { join as
|
|
54541
|
+
import { join as join54 } from "node:path";
|
|
54360
54542
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
54361
54543
|
function nativeDecodePackageDir() {
|
|
54362
54544
|
return fileURLToPath22(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -54366,8 +54548,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
54366
54548
|
}
|
|
54367
54549
|
function nativeOracleShipped() {
|
|
54368
54550
|
return {
|
|
54369
|
-
ios:
|
|
54370
|
-
android:
|
|
54551
|
+
ios: existsSync55(join54(nativeDecodePackageDir(), "Package.swift")),
|
|
54552
|
+
android: existsSync55(join54(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
54371
54553
|
};
|
|
54372
54554
|
}
|
|
54373
54555
|
function detectNativeDecode(options = {}) {
|
|
@@ -54378,7 +54560,7 @@ function detectNativeDecode(options = {}) {
|
|
|
54378
54560
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
54379
54561
|
}
|
|
54380
54562
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
54381
|
-
const packageAvailable = options.packageAvailable ??
|
|
54563
|
+
const packageAvailable = options.packageAvailable ?? existsSync55(join54(packageDir, "Package.swift"));
|
|
54382
54564
|
if (!packageAvailable) {
|
|
54383
54565
|
return {
|
|
54384
54566
|
platform: "ios",
|
|
@@ -54390,7 +54572,7 @@ function detectNativeDecode(options = {}) {
|
|
|
54390
54572
|
}
|
|
54391
54573
|
function localPropertiesSdk(harnessDir) {
|
|
54392
54574
|
try {
|
|
54393
|
-
const match =
|
|
54575
|
+
const match = readFileSync61(join54(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
54394
54576
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
54395
54577
|
} catch {
|
|
54396
54578
|
return null;
|
|
@@ -54398,8 +54580,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
54398
54580
|
}
|
|
54399
54581
|
function detectAndroidNativeDecode(options = {}) {
|
|
54400
54582
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
54401
|
-
const gradlew =
|
|
54402
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
54583
|
+
const gradlew = join54(harnessDir, "gradlew");
|
|
54584
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync55(gradlew);
|
|
54403
54585
|
if (!gradlewAvailable) {
|
|
54404
54586
|
return {
|
|
54405
54587
|
platform: "android",
|
|
@@ -54409,7 +54591,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
54409
54591
|
}
|
|
54410
54592
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
54411
54593
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
54412
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
54594
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync55(sdk));
|
|
54413
54595
|
if (!sdkAvailable) {
|
|
54414
54596
|
return {
|
|
54415
54597
|
platform: "android",
|
|
@@ -54481,14 +54663,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
54481
54663
|
return verdicts;
|
|
54482
54664
|
}
|
|
54483
54665
|
function runNativeDecode(options) {
|
|
54484
|
-
const descriptorDir = mkdtempSync2(
|
|
54666
|
+
const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-"));
|
|
54485
54667
|
const startedAt = Date.now();
|
|
54486
54668
|
try {
|
|
54487
54669
|
for (const descriptor of options.descriptors) {
|
|
54488
54670
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54489
54671
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54490
54672
|
}
|
|
54491
|
-
|
|
54673
|
+
writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54492
54674
|
}
|
|
54493
54675
|
options.progress?.("building cached Swift oracle");
|
|
54494
54676
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -54500,7 +54682,7 @@ function runNativeDecode(options) {
|
|
|
54500
54682
|
encoding: "utf8"
|
|
54501
54683
|
}).trim();
|
|
54502
54684
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54503
|
-
const stdout = execFileSync5(
|
|
54685
|
+
const stdout = execFileSync5(join54(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
54504
54686
|
stdio: ["ignore", "pipe", "pipe"],
|
|
54505
54687
|
encoding: "utf8"
|
|
54506
54688
|
});
|
|
@@ -54514,19 +54696,19 @@ function runNativeDecode(options) {
|
|
|
54514
54696
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
54515
54697
|
throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
|
|
54516
54698
|
} finally {
|
|
54517
|
-
|
|
54699
|
+
rmSync13(descriptorDir, { recursive: true, force: true });
|
|
54518
54700
|
}
|
|
54519
54701
|
}
|
|
54520
54702
|
function runAndroidNativeDecode(options) {
|
|
54521
|
-
const descriptorDir = mkdtempSync2(
|
|
54522
|
-
const outputPath =
|
|
54703
|
+
const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-android-"));
|
|
54704
|
+
const outputPath = join54(descriptorDir, "verdicts.ndjson");
|
|
54523
54705
|
const startedAt = Date.now();
|
|
54524
54706
|
try {
|
|
54525
54707
|
for (const descriptor of options.descriptors) {
|
|
54526
54708
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54527
54709
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54528
54710
|
}
|
|
54529
|
-
|
|
54711
|
+
writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54530
54712
|
}
|
|
54531
54713
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54532
54714
|
execFileSync5(options.gradlew, [
|
|
@@ -54541,7 +54723,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54541
54723
|
stdio: ["ignore", "ignore", "pipe"],
|
|
54542
54724
|
encoding: "utf8"
|
|
54543
54725
|
});
|
|
54544
|
-
const stdout =
|
|
54726
|
+
const stdout = readFileSync61(outputPath, "utf8");
|
|
54545
54727
|
return {
|
|
54546
54728
|
platform: "android",
|
|
54547
54729
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -54552,7 +54734,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54552
54734
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
54553
54735
|
throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
|
|
54554
54736
|
} finally {
|
|
54555
|
-
|
|
54737
|
+
rmSync13(descriptorDir, { recursive: true, force: true });
|
|
54556
54738
|
}
|
|
54557
54739
|
}
|
|
54558
54740
|
function fieldAt(path2) {
|
|
@@ -54611,30 +54793,30 @@ __export(browser_authoring_exports, {
|
|
|
54611
54793
|
});
|
|
54612
54794
|
import { createServer as createServer5 } from "node:http";
|
|
54613
54795
|
import { createHash as createHash29, randomBytes as randomBytes4 } from "node:crypto";
|
|
54614
|
-
import { existsSync as
|
|
54615
|
-
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";
|
|
54616
54798
|
function humanMs(ms) {
|
|
54617
54799
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
54618
54800
|
}
|
|
54619
54801
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
54620
|
-
const root =
|
|
54802
|
+
const root = join55(tier5SrcDir, bundleName);
|
|
54621
54803
|
const files = {};
|
|
54622
54804
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
54623
54805
|
const walk2 = (abs, rel) => {
|
|
54624
|
-
const real =
|
|
54806
|
+
const real = realpathSync8(abs);
|
|
54625
54807
|
if (visitedDirs.has(real)) return;
|
|
54626
54808
|
visitedDirs.add(real);
|
|
54627
|
-
for (const name of
|
|
54628
|
-
const childAbs =
|
|
54809
|
+
for (const name of readdirSync28(abs).sort()) {
|
|
54810
|
+
const childAbs = join55(abs, name);
|
|
54629
54811
|
const childRel = posix2.join(rel, name);
|
|
54630
|
-
if (
|
|
54812
|
+
if (statSync14(childAbs).isDirectory()) {
|
|
54631
54813
|
walk2(childAbs, childRel);
|
|
54632
54814
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
54633
|
-
files[childRel] =
|
|
54815
|
+
files[childRel] = readFileSync62(childAbs, "utf8");
|
|
54634
54816
|
}
|
|
54635
54817
|
}
|
|
54636
54818
|
};
|
|
54637
|
-
if (!
|
|
54819
|
+
if (!existsSync56(root)) return null;
|
|
54638
54820
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
54639
54821
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
54640
54822
|
if (!entry) return null;
|
|
@@ -54651,20 +54833,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
54651
54833
|
const spec = m[1];
|
|
54652
54834
|
const virtual = posix2.normalize(posix2.join(dir, spec));
|
|
54653
54835
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
54654
|
-
const onDisk =
|
|
54836
|
+
const onDisk = join55(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
54655
54837
|
const candidates = [
|
|
54656
54838
|
onDisk,
|
|
54657
54839
|
`${onDisk}.ts`,
|
|
54658
54840
|
`${onDisk}.js`,
|
|
54659
54841
|
onDisk.replace(/\.js$/, ".ts"),
|
|
54660
|
-
|
|
54661
|
-
|
|
54842
|
+
join55(onDisk, "index.ts"),
|
|
54843
|
+
join55(onDisk, "index.js")
|
|
54662
54844
|
];
|
|
54663
54845
|
for (const abs of candidates) {
|
|
54664
|
-
if (!
|
|
54665
|
-
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)}`;
|
|
54666
54848
|
if (key2 in files) break;
|
|
54667
|
-
files[key2] =
|
|
54849
|
+
files[key2] = readFileSync62(abs, "utf8");
|
|
54668
54850
|
queue.push(key2);
|
|
54669
54851
|
break;
|
|
54670
54852
|
}
|
|
@@ -54696,10 +54878,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
54696
54878
|
for (const source of Object.values(files)) visit(source);
|
|
54697
54879
|
return { modules, unsupported };
|
|
54698
54880
|
}
|
|
54699
|
-
function sdkSubpathReader(
|
|
54881
|
+
function sdkSubpathReader(resolve54) {
|
|
54700
54882
|
return (sub) => {
|
|
54701
54883
|
try {
|
|
54702
|
-
return
|
|
54884
|
+
return readFileSync62(resolve54(`@wix/himalaya/${sub}`), "utf8");
|
|
54703
54885
|
} catch {
|
|
54704
54886
|
return null;
|
|
54705
54887
|
}
|
|
@@ -54777,7 +54959,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
54777
54959
|
const token = mintToken2(payload);
|
|
54778
54960
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
54779
54961
|
if (unusable) throw new Error(unusable);
|
|
54780
|
-
return await new Promise((
|
|
54962
|
+
return await new Promise((resolve54, reject) => {
|
|
54781
54963
|
let settled = false;
|
|
54782
54964
|
let url = "";
|
|
54783
54965
|
const server = createServer5();
|
|
@@ -54829,7 +55011,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
54829
55011
|
}
|
|
54830
55012
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
54831
55013
|
const report3 = body.result;
|
|
54832
|
-
finish2(() =>
|
|
55014
|
+
finish2(() => resolve54({ report: report3, url }));
|
|
54833
55015
|
})();
|
|
54834
55016
|
});
|
|
54835
55017
|
server.on("error", (e) => finish2(() => reject(e)));
|
|
@@ -54871,8 +55053,8 @@ __export(coverage_exports, {
|
|
|
54871
55053
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
54872
55054
|
trendAndStore: () => trendAndStore
|
|
54873
55055
|
});
|
|
54874
|
-
import { existsSync as
|
|
54875
|
-
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";
|
|
54876
55058
|
function suppressedNativeKeys(oracle) {
|
|
54877
55059
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
54878
55060
|
}
|
|
@@ -55052,11 +55234,11 @@ function assembleLedger(r, options = {}) {
|
|
|
55052
55234
|
return out2;
|
|
55053
55235
|
}
|
|
55054
55236
|
function trendAndStore(dir, entries, suppressed) {
|
|
55055
|
-
const p =
|
|
55237
|
+
const p = join56(dir, LEDGER_FILE);
|
|
55056
55238
|
let previous = null;
|
|
55057
55239
|
try {
|
|
55058
|
-
if (
|
|
55059
|
-
const parsed = JSON.parse(
|
|
55240
|
+
if (existsSync57(p)) {
|
|
55241
|
+
const parsed = JSON.parse(readFileSync63(p, "utf8"));
|
|
55060
55242
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
55061
55243
|
}
|
|
55062
55244
|
} catch {
|
|
@@ -55064,8 +55246,8 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
55064
55246
|
const current = entries.map((e) => e.key);
|
|
55065
55247
|
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
55066
55248
|
try {
|
|
55067
|
-
|
|
55068
|
-
|
|
55249
|
+
mkdirSync27(dirname31(p), { recursive: true });
|
|
55250
|
+
writeFileSync23(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55069
55251
|
} catch {
|
|
55070
55252
|
return null;
|
|
55071
55253
|
}
|
|
@@ -55095,11 +55277,11 @@ function formatLedger(entries, trend) {
|
|
|
55095
55277
|
return out2.join("\n");
|
|
55096
55278
|
}
|
|
55097
55279
|
function diffAndStoreObservations(dir, current) {
|
|
55098
|
-
const p =
|
|
55280
|
+
const p = join56(dir, OBS_FILE);
|
|
55099
55281
|
let previous = null;
|
|
55100
55282
|
try {
|
|
55101
|
-
if (
|
|
55102
|
-
const parsed = JSON.parse(
|
|
55283
|
+
if (existsSync57(p)) {
|
|
55284
|
+
const parsed = JSON.parse(readFileSync63(p, "utf8"));
|
|
55103
55285
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
55104
55286
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
55105
55287
|
)) {
|
|
@@ -55109,8 +55291,8 @@ function diffAndStoreObservations(dir, current) {
|
|
|
55109
55291
|
} catch {
|
|
55110
55292
|
}
|
|
55111
55293
|
try {
|
|
55112
|
-
|
|
55113
|
-
|
|
55294
|
+
mkdirSync27(dirname31(p), { recursive: true });
|
|
55295
|
+
writeFileSync23(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55114
55296
|
} catch {
|
|
55115
55297
|
return null;
|
|
55116
55298
|
}
|
|
@@ -55148,8 +55330,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
55148
55330
|
var init_coverage = __esm({
|
|
55149
55331
|
"src/coverage.ts"() {
|
|
55150
55332
|
init_native_decode();
|
|
55151
|
-
LEDGER_FILE =
|
|
55152
|
-
OBS_FILE =
|
|
55333
|
+
LEDGER_FILE = join56(".himi", "test-ledger.json");
|
|
55334
|
+
OBS_FILE = join56(".himi", "test-observations.json");
|
|
55153
55335
|
}
|
|
55154
55336
|
});
|
|
55155
55337
|
|
|
@@ -55160,16 +55342,16 @@ __export(design_kits_exports, {
|
|
|
55160
55342
|
kitsDir: () => kitsDir,
|
|
55161
55343
|
listKits: () => listKits2
|
|
55162
55344
|
});
|
|
55163
|
-
import { existsSync as
|
|
55164
|
-
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";
|
|
55165
55347
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
55166
55348
|
function kitsDir() {
|
|
55167
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
55349
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync58(p));
|
|
55168
55350
|
}
|
|
55169
55351
|
function listKits2() {
|
|
55170
55352
|
const dir = kitsDir();
|
|
55171
55353
|
if (!dir) return [];
|
|
55172
|
-
return
|
|
55354
|
+
return readdirSync29(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
|
|
55173
55355
|
}
|
|
55174
55356
|
function kitReport(name) {
|
|
55175
55357
|
const dir = kitsDir();
|
|
@@ -55188,7 +55370,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
55188
55370
|
if (!kits.includes(name)) {
|
|
55189
55371
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
55190
55372
|
}
|
|
55191
|
-
const raw =
|
|
55373
|
+
const raw = readFileSync64(join57(dir, `${name}.json`), "utf8");
|
|
55192
55374
|
let parsed;
|
|
55193
55375
|
try {
|
|
55194
55376
|
parsed = JSON.parse(raw);
|
|
@@ -55212,9 +55394,9 @@ var init_design_kits = __esm({
|
|
|
55212
55394
|
"src/design-kits.ts"() {
|
|
55213
55395
|
KIT_DIR_CANDIDATES = [
|
|
55214
55396
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
55215
|
-
|
|
55397
|
+
join57(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
55216
55398
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
55217
|
-
|
|
55399
|
+
join57(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
55218
55400
|
];
|
|
55219
55401
|
}
|
|
55220
55402
|
});
|
|
@@ -55228,11 +55410,11 @@ __export(assets_exports, {
|
|
|
55228
55410
|
removeAssetPayload: () => removeAssetPayload,
|
|
55229
55411
|
verifyReport: () => verifyReport
|
|
55230
55412
|
});
|
|
55231
|
-
import { readFileSync as
|
|
55413
|
+
import { readFileSync as readFileSync65 } from "node:fs";
|
|
55232
55414
|
import { basename as basename16 } from "node:path";
|
|
55233
55415
|
function declaredAssets(dir) {
|
|
55234
55416
|
return collectAssets(dir).map((a) => {
|
|
55235
|
-
const bytes2 =
|
|
55417
|
+
const bytes2 = readFileSync65(a.path);
|
|
55236
55418
|
return {
|
|
55237
55419
|
name: a.name,
|
|
55238
55420
|
sha256: assetSha256(bytes2),
|
|
@@ -55309,7 +55491,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
55309
55491
|
};
|
|
55310
55492
|
}
|
|
55311
55493
|
function addAssetPayload(manifest, filePath, opts) {
|
|
55312
|
-
const bytes2 =
|
|
55494
|
+
const bytes2 = readFileSync65(filePath);
|
|
55313
55495
|
const name = opts.name ?? basename16(filePath);
|
|
55314
55496
|
const sha2565 = assetSha256(bytes2);
|
|
55315
55497
|
const record2 = {
|
|
@@ -57033,9 +57215,9 @@ __export(run_exports, {
|
|
|
57033
57215
|
runPackage: () => runPackage,
|
|
57034
57216
|
withoutProdServe: () => withoutProdServe
|
|
57035
57217
|
});
|
|
57036
|
-
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";
|
|
57037
57219
|
import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
|
|
57038
|
-
import { dirname as
|
|
57220
|
+
import { dirname as dirname32, join as join58 } from "node:path";
|
|
57039
57221
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
57040
57222
|
function makePackageRunHandler(opts) {
|
|
57041
57223
|
const store = new FileReleaseStore(opts.releaseRoot);
|
|
@@ -57063,9 +57245,9 @@ async function fetchBytes(url) {
|
|
|
57063
57245
|
}
|
|
57064
57246
|
async function resolvePackage(source, workDir) {
|
|
57065
57247
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
57066
|
-
if (!isUrl2 &&
|
|
57067
|
-
const appDirManifest =
|
|
57068
|
-
if (
|
|
57248
|
+
if (!isUrl2 && existsSync59(source) && statSync15(source).isDirectory()) {
|
|
57249
|
+
const appDirManifest = join58(source, "release-manifest.json");
|
|
57250
|
+
if (existsSync59(appDirManifest)) {
|
|
57069
57251
|
const opened2 = openPackageDir(source);
|
|
57070
57252
|
if (!opened2.validation.ok) {
|
|
57071
57253
|
throw new Error(`package is not valid:
|
|
@@ -57074,11 +57256,11 @@ async function resolvePackage(source, workDir) {
|
|
|
57074
57256
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
57075
57257
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
57076
57258
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
57077
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
57078
|
-
const target =
|
|
57079
|
-
if (
|
|
57080
|
-
|
|
57081
|
-
|
|
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 });
|
|
57082
57264
|
cpSync2(source, target, { recursive: true });
|
|
57083
57265
|
}
|
|
57084
57266
|
return {
|
|
@@ -57093,12 +57275,12 @@ async function resolvePackage(source, workDir) {
|
|
|
57093
57275
|
}
|
|
57094
57276
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
57095
57277
|
}
|
|
57096
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
57097
|
-
const root = workDir ?? mkdtempSync3(
|
|
57278
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync66(source);
|
|
57279
|
+
const root = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
|
|
57098
57280
|
const { app, appDir: appDir3 } = unpackTo(bytes2, root);
|
|
57099
57281
|
const opened = openPackageDir(appDir3);
|
|
57100
57282
|
if (!opened.validation.ok) {
|
|
57101
|
-
|
|
57283
|
+
rmSync14(workDir ? appDir3 : root, { recursive: true, force: true });
|
|
57102
57284
|
throw new Error(`package is not valid:
|
|
57103
57285
|
${opened.validation.errors.join("\n ")}`);
|
|
57104
57286
|
}
|
|
@@ -57115,16 +57297,16 @@ async function resolvePackage(source, workDir) {
|
|
|
57115
57297
|
async function loadPreviewAssets() {
|
|
57116
57298
|
try {
|
|
57117
57299
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
57118
|
-
const here =
|
|
57300
|
+
const here = dirname32(fileURLToPath24(import.meta.url));
|
|
57119
57301
|
const candidates = [
|
|
57120
|
-
|
|
57302
|
+
join58(here, "preview-assets.generated.bin"),
|
|
57121
57303
|
// published: copied next to the bundled CLI
|
|
57122
|
-
|
|
57304
|
+
join58(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
57123
57305
|
// in-repo checkout
|
|
57124
57306
|
];
|
|
57125
57307
|
for (const path2 of candidates) {
|
|
57126
|
-
if (!
|
|
57127
|
-
const blob =
|
|
57308
|
+
if (!existsSync59(path2)) continue;
|
|
57309
|
+
const blob = readFileSync66(path2);
|
|
57128
57310
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
57129
57311
|
}
|
|
57130
57312
|
return /* @__PURE__ */ new Map();
|
|
@@ -57172,7 +57354,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57172
57354
|
const resolved2 = await resolvePackage(source, opts.workDir);
|
|
57173
57355
|
const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
|
|
57174
57356
|
if (!opts.spa && assets.size === 0) {
|
|
57175
|
-
if (resolved2.temp)
|
|
57357
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57176
57358
|
throw new Error(NO_SPA_MESSAGE);
|
|
57177
57359
|
}
|
|
57178
57360
|
const plane = makePackageRunHandler({
|
|
@@ -57210,7 +57392,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57210
57392
|
lanBound = (await listen(lanServer, port, lanHost)).address;
|
|
57211
57393
|
} catch (e) {
|
|
57212
57394
|
await closeServer(server);
|
|
57213
|
-
if (resolved2.temp)
|
|
57395
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57214
57396
|
throw new Error(`himi run --lan could not listen on ${lanHost}:${port} (${e.message}); drop --lan, or pass --port for a free one`);
|
|
57215
57397
|
}
|
|
57216
57398
|
bound.push(lanBound);
|
|
@@ -57232,7 +57414,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57232
57414
|
warnings: resolved2.warnings,
|
|
57233
57415
|
close: async () => {
|
|
57234
57416
|
await Promise.all(servers.map(closeServer));
|
|
57235
|
-
if (resolved2.temp)
|
|
57417
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57236
57418
|
}
|
|
57237
57419
|
};
|
|
57238
57420
|
}
|
|
@@ -57271,9 +57453,9 @@ __export(run_watch_exports, {
|
|
|
57271
57453
|
watchedContentDir: () => watchedContentDir,
|
|
57272
57454
|
writeRunRecord: () => writeRunRecord
|
|
57273
57455
|
});
|
|
57274
|
-
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";
|
|
57275
57457
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
57276
|
-
import { extname as extname4, join as
|
|
57458
|
+
import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
|
|
57277
57459
|
function diffReleases(prev, next) {
|
|
57278
57460
|
const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
|
|
57279
57461
|
const changedBundles = new Set(bundles);
|
|
@@ -57314,7 +57496,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
57314
57496
|
let timer = null;
|
|
57315
57497
|
const pending = /* @__PURE__ */ new Set();
|
|
57316
57498
|
const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
|
|
57317
|
-
if (!file || ignoredChange(file, (rel) => isDir(
|
|
57499
|
+
if (!file || ignoredChange(file, (rel) => isDir(join59(dir, rel)))) return;
|
|
57318
57500
|
pending.add(file);
|
|
57319
57501
|
if (timer) clearTimeout(timer);
|
|
57320
57502
|
timer = setTimeout(() => {
|
|
@@ -57333,9 +57515,9 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
57333
57515
|
}
|
|
57334
57516
|
function watchedContentDir(source) {
|
|
57335
57517
|
if (!source || /^https?:\/\//i.test(source)) return null;
|
|
57336
|
-
const dir =
|
|
57518
|
+
const dir = resolve47(source);
|
|
57337
57519
|
try {
|
|
57338
|
-
return
|
|
57520
|
+
return statSync16(dir).isDirectory() && existsSync60(join59(dir, "himalaya.content.json")) ? dir : null;
|
|
57339
57521
|
} catch {
|
|
57340
57522
|
return null;
|
|
57341
57523
|
}
|
|
@@ -57392,33 +57574,33 @@ function serialize(task) {
|
|
|
57392
57574
|
});
|
|
57393
57575
|
}
|
|
57394
57576
|
function himiDir(dir) {
|
|
57395
|
-
const root =
|
|
57577
|
+
const root = join59(dir, ".himi");
|
|
57396
57578
|
try {
|
|
57397
|
-
return
|
|
57579
|
+
return lstatSync13(root).isDirectory() ? root : null;
|
|
57398
57580
|
} catch (e) {
|
|
57399
57581
|
if (e.code !== "ENOENT") return null;
|
|
57400
|
-
|
|
57401
|
-
return
|
|
57582
|
+
mkdirSync29(root, { recursive: true });
|
|
57583
|
+
return lstatSync13(root).isDirectory() ? root : null;
|
|
57402
57584
|
}
|
|
57403
57585
|
}
|
|
57404
57586
|
function writeRunRecord(dir, record2) {
|
|
57405
57587
|
const root = himiDir(dir);
|
|
57406
57588
|
if (!root) return false;
|
|
57407
|
-
const tmp =
|
|
57589
|
+
const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
|
|
57408
57590
|
try {
|
|
57409
|
-
|
|
57591
|
+
writeFileSync24(tmp, `${JSON.stringify(record2, null, 2)}
|
|
57410
57592
|
`, { flag: "wx" });
|
|
57411
|
-
renameSync6(tmp,
|
|
57593
|
+
renameSync6(tmp, join59(root, "run.json"));
|
|
57412
57594
|
} catch (e) {
|
|
57413
|
-
|
|
57595
|
+
rmSync15(tmp, { force: true });
|
|
57414
57596
|
throw e;
|
|
57415
57597
|
}
|
|
57416
57598
|
return true;
|
|
57417
57599
|
}
|
|
57418
57600
|
function removeRunRecord(dir, owner) {
|
|
57419
|
-
const root =
|
|
57601
|
+
const root = join59(dir, ".himi");
|
|
57420
57602
|
try {
|
|
57421
|
-
if (!
|
|
57603
|
+
if (!lstatSync13(root).isDirectory()) return;
|
|
57422
57604
|
} catch {
|
|
57423
57605
|
return;
|
|
57424
57606
|
}
|
|
@@ -57431,22 +57613,22 @@ function removeRunRecord(dir, owner) {
|
|
|
57431
57613
|
}
|
|
57432
57614
|
if (typeof pid === "number" && pid !== owner) return;
|
|
57433
57615
|
}
|
|
57434
|
-
|
|
57616
|
+
rmSync15(join59(root, "run.json"), { force: true });
|
|
57435
57617
|
}
|
|
57436
57618
|
function boardFile(dir, pathname) {
|
|
57437
57619
|
if (pathname === RUN_IDENTITY_PATH) {
|
|
57438
57620
|
return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
|
|
57439
57621
|
}
|
|
57440
57622
|
let rel = null;
|
|
57441
|
-
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel =
|
|
57442
|
-
else if (pathname === "/__himi/studio/state.js") rel =
|
|
57443
|
-
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");
|
|
57444
57626
|
else {
|
|
57445
57627
|
const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
|
|
57446
|
-
if (m) rel =
|
|
57628
|
+
if (m) rel = join59("history", m[1]);
|
|
57447
57629
|
}
|
|
57448
57630
|
if (!rel) return null;
|
|
57449
|
-
const bytes2 = readConfined(
|
|
57631
|
+
const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
|
|
57450
57632
|
if (!bytes2) return new Response("not found", { status: 404 });
|
|
57451
57633
|
return new Response(bytes2, {
|
|
57452
57634
|
status: 200,
|
|
@@ -57455,20 +57637,20 @@ function boardFile(dir, pathname) {
|
|
|
57455
57637
|
}
|
|
57456
57638
|
function readConfined(root, rel) {
|
|
57457
57639
|
try {
|
|
57458
|
-
if (!
|
|
57459
|
-
const parts = rel.split(
|
|
57640
|
+
if (!lstatSync13(root).isDirectory()) return null;
|
|
57641
|
+
const parts = rel.split(sep16);
|
|
57460
57642
|
let at2 = root;
|
|
57461
57643
|
for (let i = 0; i < parts.length; i++) {
|
|
57462
|
-
at2 =
|
|
57463
|
-
const st =
|
|
57644
|
+
at2 = join59(at2, parts[i]);
|
|
57645
|
+
const st = lstatSync13(at2);
|
|
57464
57646
|
if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
|
|
57465
57647
|
}
|
|
57466
|
-
const canonicalRoot =
|
|
57467
|
-
if (!
|
|
57648
|
+
const canonicalRoot = realpathSync9(root);
|
|
57649
|
+
if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
|
|
57468
57650
|
const fd = openSync3(at2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
57469
57651
|
try {
|
|
57470
57652
|
if (!fstatSync(fd).isFile()) return null;
|
|
57471
|
-
return
|
|
57653
|
+
return readFileSync67(fd);
|
|
57472
57654
|
} finally {
|
|
57473
57655
|
closeSync4(fd);
|
|
57474
57656
|
}
|
|
@@ -57497,7 +57679,7 @@ var init_run_watch = __esm({
|
|
|
57497
57679
|
};
|
|
57498
57680
|
isDir = (path2) => {
|
|
57499
57681
|
try {
|
|
57500
|
-
return
|
|
57682
|
+
return statSync16(path2).isDirectory();
|
|
57501
57683
|
} catch {
|
|
57502
57684
|
return false;
|
|
57503
57685
|
}
|
|
@@ -57521,19 +57703,19 @@ __export(run_browser_exports, {
|
|
|
57521
57703
|
runInBrowser: () => runInBrowser
|
|
57522
57704
|
});
|
|
57523
57705
|
import { createServer as createServer7 } from "node:http";
|
|
57524
|
-
import { existsSync as
|
|
57706
|
+
import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
|
|
57525
57707
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
57526
|
-
import { dirname as
|
|
57708
|
+
import { dirname as dirname33, resolve as resolve48 } from "node:path";
|
|
57527
57709
|
import { fileURLToPath as fileURLToPath25 } from "node:url";
|
|
57528
57710
|
function stagedDir() {
|
|
57529
|
-
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");
|
|
57530
57712
|
}
|
|
57531
57713
|
function missingStaged() {
|
|
57532
|
-
return [...SERVED].filter((f) => !
|
|
57714
|
+
return [...SERVED].filter((f) => !existsSync61(resolve48(stagedDir(), f))).sort();
|
|
57533
57715
|
}
|
|
57534
57716
|
function ensureBrowserPlaneStaged() {
|
|
57535
57717
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
57536
|
-
const r = spawnSync3(process.execPath, [
|
|
57718
|
+
const r = spawnSync3(process.execPath, [resolve48(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
|
|
57537
57719
|
cwd: REPO,
|
|
57538
57720
|
encoding: "utf8"
|
|
57539
57721
|
});
|
|
@@ -57619,7 +57801,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
57619
57801
|
}
|
|
57620
57802
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
57621
57803
|
if (SERVED.has(name)) {
|
|
57622
|
-
if (!
|
|
57804
|
+
if (!existsSync61(resolve48(stagedDir(), name))) {
|
|
57623
57805
|
const restaged = ensureBrowserPlaneStaged();
|
|
57624
57806
|
if (!restaged.ok) {
|
|
57625
57807
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -57629,7 +57811,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
57629
57811
|
}
|
|
57630
57812
|
let bytes2;
|
|
57631
57813
|
try {
|
|
57632
|
-
bytes2 =
|
|
57814
|
+
bytes2 = readFileSync68(resolve48(stagedDir(), name));
|
|
57633
57815
|
} catch (e) {
|
|
57634
57816
|
res.writeHead(503, { "content-type": "application/json" });
|
|
57635
57817
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -57671,8 +57853,8 @@ var init_run_browser = __esm({
|
|
|
57671
57853
|
init_open_url();
|
|
57672
57854
|
init_file_store();
|
|
57673
57855
|
init_wix_client_id();
|
|
57674
|
-
HERE2 =
|
|
57675
|
-
REPO =
|
|
57856
|
+
HERE2 = dirname33(fileURLToPath25(import.meta.url));
|
|
57857
|
+
REPO = resolve48(HERE2, "..", "..", "..");
|
|
57676
57858
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
57677
57859
|
}
|
|
57678
57860
|
});
|
|
@@ -58091,11 +58273,11 @@ __export(preflight_exports, {
|
|
|
58091
58273
|
parseStoreConfig: () => parseStoreConfig,
|
|
58092
58274
|
requireEnv: () => requireEnv
|
|
58093
58275
|
});
|
|
58094
|
-
import { existsSync as
|
|
58095
|
-
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";
|
|
58096
58278
|
function isInsideRepo(p) {
|
|
58097
|
-
const rel =
|
|
58098
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
58279
|
+
const rel = relative13(REPO_ROOT3, resolve49(p));
|
|
58280
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute6(rel);
|
|
58099
58281
|
}
|
|
58100
58282
|
function assertCredentialOutsideRepo(label2, p) {
|
|
58101
58283
|
if (isInsideRepo(p)) {
|
|
@@ -58148,10 +58330,10 @@ function parseStoreConfig(text8) {
|
|
|
58148
58330
|
}
|
|
58149
58331
|
function loadStoreConfig(app) {
|
|
58150
58332
|
const p = storeConfigPath(app);
|
|
58151
|
-
if (!
|
|
58333
|
+
if (!existsSync62(p)) {
|
|
58152
58334
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
58153
58335
|
}
|
|
58154
|
-
return parseStoreConfig(
|
|
58336
|
+
return parseStoreConfig(readFileSync69(p, "utf8"));
|
|
58155
58337
|
}
|
|
58156
58338
|
var init_preflight = __esm({
|
|
58157
58339
|
"../store-release/preflight.ts"() {
|
|
@@ -58170,19 +58352,19 @@ __export(credential_profile_exports, {
|
|
|
58170
58352
|
profilePath: () => profilePath,
|
|
58171
58353
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
58172
58354
|
});
|
|
58173
|
-
import { existsSync as
|
|
58355
|
+
import { existsSync as existsSync63, readFileSync as readFileSync70 } from "node:fs";
|
|
58174
58356
|
import { homedir as homedir5 } from "node:os";
|
|
58175
|
-
import { join as
|
|
58357
|
+
import { join as join60 } from "node:path";
|
|
58176
58358
|
function credentialsDir(home = homedir5()) {
|
|
58177
|
-
return
|
|
58359
|
+
return join60(home, ".himalaya", "store-credentials");
|
|
58178
58360
|
}
|
|
58179
58361
|
function profilePath(name, home = homedir5()) {
|
|
58180
58362
|
if (!PROFILE_NAME.test(name)) {
|
|
58181
58363
|
throw new Error(
|
|
58182
|
-
`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.`
|
|
58183
58365
|
);
|
|
58184
58366
|
}
|
|
58185
|
-
return
|
|
58367
|
+
return join60(credentialsDir(home), `${name}.json`);
|
|
58186
58368
|
}
|
|
58187
58369
|
function parseProfile(text8, label2) {
|
|
58188
58370
|
let doc;
|
|
@@ -58213,8 +58395,8 @@ function resolveStoreCredentials(opts) {
|
|
|
58213
58395
|
const { app, cfg } = opts;
|
|
58214
58396
|
const env = opts.env ?? process.env;
|
|
58215
58397
|
const home = opts.home ?? homedir5();
|
|
58216
|
-
const read = opts.readProfile ?? ((p) =>
|
|
58217
|
-
const exists = opts.profileExists ??
|
|
58398
|
+
const read = opts.readProfile ?? ((p) => readFileSync70(p, "utf8"));
|
|
58399
|
+
const exists = opts.profileExists ?? existsSync63;
|
|
58218
58400
|
const ios = cfg.ios ?? {};
|
|
58219
58401
|
const flagName = opts.profileFlag?.trim();
|
|
58220
58402
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -58294,9 +58476,9 @@ __export(preflight_app_exports, {
|
|
|
58294
58476
|
preflightApp: () => preflightApp,
|
|
58295
58477
|
profileAccount: () => profileAccount
|
|
58296
58478
|
});
|
|
58297
|
-
import { readFileSync as
|
|
58479
|
+
import { readFileSync as readFileSync71, existsSync as existsSync64, readdirSync as readdirSync30, statSync as statSync17 } from "node:fs";
|
|
58298
58480
|
import { createHash as createHash30 } from "node:crypto";
|
|
58299
|
-
import { join as
|
|
58481
|
+
import { join as join61 } from "node:path";
|
|
58300
58482
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
58301
58483
|
const f = [];
|
|
58302
58484
|
const has = (re, s) => re.test(s);
|
|
@@ -58360,13 +58542,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
58360
58542
|
}
|
|
58361
58543
|
}
|
|
58362
58544
|
async function preflightApp(app, opts = {}) {
|
|
58363
|
-
const projectYml =
|
|
58364
|
-
const storeConfig =
|
|
58545
|
+
const projectYml = existsSync64(iosProjectYml(app)) ? readFileSync71(iosProjectYml(app), "utf8") : "";
|
|
58546
|
+
const storeConfig = existsSync64(storeConfigPath(app)) ? readFileSync71(storeConfigPath(app), "utf8") : "";
|
|
58365
58547
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
58366
58548
|
const findings = analyze(
|
|
58367
58549
|
projectYml,
|
|
58368
58550
|
storeConfig,
|
|
58369
|
-
await appIconState(
|
|
58551
|
+
await appIconState(join61(appDir(app), "ios")),
|
|
58370
58552
|
profileAccount(app, storeConfig, opts)
|
|
58371
58553
|
);
|
|
58372
58554
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -58395,18 +58577,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
58395
58577
|
return f;
|
|
58396
58578
|
}
|
|
58397
58579
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
58398
|
-
const root =
|
|
58580
|
+
const root = join61(storeDir(app), "metadata");
|
|
58399
58581
|
const out2 = /* @__PURE__ */ new Set();
|
|
58400
|
-
if (
|
|
58401
|
-
for (const n of
|
|
58582
|
+
if (existsSync64(root)) {
|
|
58583
|
+
for (const n of readdirSync30(root)) if (n.endsWith(".txt")) out2.add(n);
|
|
58402
58584
|
}
|
|
58403
|
-
if (
|
|
58585
|
+
if (existsSync64(join61(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
|
|
58404
58586
|
return out2;
|
|
58405
58587
|
}
|
|
58406
58588
|
function reviewInfoFiles(app) {
|
|
58407
|
-
const dir =
|
|
58408
|
-
if (!
|
|
58409
|
-
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")));
|
|
58410
58592
|
}
|
|
58411
58593
|
function isValidAppStoreSize(w, h) {
|
|
58412
58594
|
return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
|
|
@@ -58515,12 +58697,12 @@ function analyzePlayListing(assets) {
|
|
|
58515
58697
|
return f;
|
|
58516
58698
|
}
|
|
58517
58699
|
function playListingAssets(app, locale = "en-US") {
|
|
58518
|
-
const dir =
|
|
58700
|
+
const dir = join61(storeDir(app), "play", locale, "images");
|
|
58519
58701
|
const read = (names) => {
|
|
58520
58702
|
for (const name of names) {
|
|
58521
|
-
const p =
|
|
58703
|
+
const p = join61(dir, name);
|
|
58522
58704
|
try {
|
|
58523
|
-
if (
|
|
58705
|
+
if (statSync17(p).isFile()) return { name, bytes: readFileSync71(p) };
|
|
58524
58706
|
} catch {
|
|
58525
58707
|
}
|
|
58526
58708
|
}
|
|
@@ -58551,26 +58733,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
58551
58733
|
return f;
|
|
58552
58734
|
}
|
|
58553
58735
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
58554
|
-
const dir =
|
|
58555
|
-
if (!
|
|
58556
|
-
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")));
|
|
58557
58739
|
}
|
|
58558
58740
|
function listScreenshots(app, locale = "en-US") {
|
|
58559
58741
|
const out2 = [];
|
|
58560
|
-
const flat =
|
|
58561
|
-
if (
|
|
58562
|
-
for (const png of
|
|
58563
|
-
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)));
|
|
58564
58746
|
if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
|
|
58565
58747
|
}
|
|
58566
58748
|
}
|
|
58567
|
-
const legacy =
|
|
58568
|
-
if (
|
|
58569
|
-
for (const deviceDir of
|
|
58570
|
-
const d =
|
|
58571
|
-
if (!
|
|
58572
|
-
for (const png of
|
|
58573
|
-
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)));
|
|
58574
58756
|
if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
58575
58757
|
}
|
|
58576
58758
|
}
|
|
@@ -58578,13 +58760,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
58578
58760
|
return out2;
|
|
58579
58761
|
}
|
|
58580
58762
|
function placeholderHashes2() {
|
|
58581
|
-
const templateIos =
|
|
58582
|
-
if (!
|
|
58583
|
-
for (const target of
|
|
58584
|
-
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");
|
|
58585
58767
|
try {
|
|
58586
|
-
if (!
|
|
58587
|
-
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")];
|
|
58588
58770
|
} catch {
|
|
58589
58771
|
}
|
|
58590
58772
|
}
|
|
@@ -58615,12 +58797,12 @@ async function pixelIssues(bytes2) {
|
|
|
58615
58797
|
}
|
|
58616
58798
|
}
|
|
58617
58799
|
async function appIconState(iosDir) {
|
|
58618
|
-
if (!
|
|
58619
|
-
for (const target of
|
|
58620
|
-
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");
|
|
58621
58803
|
try {
|
|
58622
|
-
if (!
|
|
58623
|
-
const bytes2 =
|
|
58804
|
+
if (!statSync17(p).isFile()) continue;
|
|
58805
|
+
const bytes2 = readFileSync71(p);
|
|
58624
58806
|
const hash = createHash30("sha256").update(bytes2).digest("hex");
|
|
58625
58807
|
const pixels = await pixelIssues(bytes2);
|
|
58626
58808
|
return {
|
|
@@ -58692,7 +58874,7 @@ __export(version_exports, {
|
|
|
58692
58874
|
setAndroidVersion: () => setAndroidVersion,
|
|
58693
58875
|
setIosVersion: () => setIosVersion
|
|
58694
58876
|
});
|
|
58695
|
-
import { readFileSync as
|
|
58877
|
+
import { readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
|
|
58696
58878
|
function readIosVersion(projectYml) {
|
|
58697
58879
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
58698
58880
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -58750,15 +58932,15 @@ function setAndroidVersion(gradle, v) {
|
|
|
58750
58932
|
function bumpVersion(app, opts) {
|
|
58751
58933
|
const iosPath = iosProjectYml(app);
|
|
58752
58934
|
const gradlePath = androidGradle(app);
|
|
58753
|
-
const iosYml =
|
|
58754
|
-
const gradle =
|
|
58935
|
+
const iosYml = readFileSync72(iosPath, "utf8");
|
|
58936
|
+
const gradle = readFileSync72(gradlePath, "utf8");
|
|
58755
58937
|
const current = readIosVersion(iosYml);
|
|
58756
58938
|
const next = {
|
|
58757
58939
|
marketing: opts.marketing ?? current.marketing,
|
|
58758
58940
|
build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
|
|
58759
58941
|
};
|
|
58760
|
-
|
|
58761
|
-
|
|
58942
|
+
writeFileSync25(iosPath, setIosVersion(iosYml, next));
|
|
58943
|
+
writeFileSync25(gradlePath, setAndroidVersion(gradle, next));
|
|
58762
58944
|
return next;
|
|
58763
58945
|
}
|
|
58764
58946
|
var init_version = __esm({
|
|
@@ -58768,7 +58950,7 @@ var init_version = __esm({
|
|
|
58768
58950
|
});
|
|
58769
58951
|
|
|
58770
58952
|
// ../store-release/register-bundle.ts
|
|
58771
|
-
import { readFileSync as
|
|
58953
|
+
import { readFileSync as readFileSync73 } from "node:fs";
|
|
58772
58954
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
58773
58955
|
function b64url2(b) {
|
|
58774
58956
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -58786,7 +58968,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
58786
58968
|
async function registerBundleId(opts) {
|
|
58787
58969
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
58788
58970
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
58789
|
-
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));
|
|
58790
58972
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
58791
58973
|
method: "POST",
|
|
58792
58974
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -58840,7 +59022,7 @@ __export(asc_status_exports, {
|
|
|
58840
59022
|
ascStatus: () => ascStatus,
|
|
58841
59023
|
buildVerdict: () => buildVerdict
|
|
58842
59024
|
});
|
|
58843
|
-
import { readFileSync as
|
|
59025
|
+
import { readFileSync as readFileSync74 } from "node:fs";
|
|
58844
59026
|
function buildVerdict(builds) {
|
|
58845
59027
|
if (!builds.length) {
|
|
58846
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).";
|
|
@@ -58854,7 +59036,7 @@ function buildVerdict(builds) {
|
|
|
58854
59036
|
function client(creds) {
|
|
58855
59037
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
58856
59038
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
58857
|
-
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));
|
|
58858
59040
|
return async (path2) => {
|
|
58859
59041
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
58860
59042
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -58903,7 +59085,7 @@ var init_asc_status = __esm({
|
|
|
58903
59085
|
// ../../core/functions-secrets/src/vault.ts
|
|
58904
59086
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
|
|
58905
59087
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
58906
|
-
import { dirname as
|
|
59088
|
+
import { dirname as dirname34 } from "node:path";
|
|
58907
59089
|
function createJsonSecretStore(filePath) {
|
|
58908
59090
|
const read = async () => {
|
|
58909
59091
|
try {
|
|
@@ -58916,7 +59098,7 @@ function createJsonSecretStore(filePath) {
|
|
|
58916
59098
|
}
|
|
58917
59099
|
};
|
|
58918
59100
|
const write2 = async (records) => {
|
|
58919
|
-
await mkdir(
|
|
59101
|
+
await mkdir(dirname34(filePath), { recursive: true });
|
|
58920
59102
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
58921
59103
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
58922
59104
|
`, { mode: 384 });
|
|
@@ -59014,7 +59196,7 @@ __export(secrets_exports, {
|
|
|
59014
59196
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
59015
59197
|
runSecretsCommand: () => runSecretsCommand
|
|
59016
59198
|
});
|
|
59017
|
-
import { readFileSync as
|
|
59199
|
+
import { readFileSync as readFileSync75 } from "node:fs";
|
|
59018
59200
|
function environment(value) {
|
|
59019
59201
|
if (value === "preview" || value === "production") return value;
|
|
59020
59202
|
throw new Error("--environment must be preview or production");
|
|
@@ -59045,7 +59227,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
59045
59227
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
59046
59228
|
return 0;
|
|
59047
59229
|
}
|
|
59048
|
-
const value = options.readValue ? options.readValue() :
|
|
59230
|
+
const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
|
|
59049
59231
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
59050
59232
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
59051
59233
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -59074,7 +59256,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
59074
59256
|
}
|
|
59075
59257
|
let body;
|
|
59076
59258
|
if (operation !== "list") {
|
|
59077
|
-
const value = options.readValue ? options.readValue() :
|
|
59259
|
+
const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
|
|
59078
59260
|
body = JSON.stringify({ value });
|
|
59079
59261
|
}
|
|
59080
59262
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -59211,29 +59393,29 @@ __export(notify_ping_exports, {
|
|
|
59211
59393
|
runNotifyPing: () => runNotifyPing
|
|
59212
59394
|
});
|
|
59213
59395
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
59214
|
-
import { resolve as
|
|
59215
|
-
function
|
|
59396
|
+
import { resolve as resolve50 } from "node:path";
|
|
59397
|
+
function refuse5(io, error, hint, exit = 2, extra = {}) {
|
|
59216
59398
|
io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
|
|
59217
59399
|
return exit;
|
|
59218
59400
|
}
|
|
59219
59401
|
async function runNotifyPing(flags, io, deps = {}) {
|
|
59220
59402
|
const flagError = flagRefusal(flags);
|
|
59221
|
-
if (flagError) return
|
|
59222
|
-
const input = mergePushInputs(pushInputsFromContent(
|
|
59403
|
+
if (flagError) return refuse5(io, flagError);
|
|
59404
|
+
const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
|
|
59223
59405
|
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
|
|
59224
|
-
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 });
|
|
59225
59407
|
const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
|
|
59226
|
-
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.");
|
|
59227
59409
|
const owner = await hostedOwnerSession(flags, deps);
|
|
59228
|
-
if (!owner.ok) return
|
|
59410
|
+
if (!owner.ok) return refuse5(io, owner.error, owner.hint, owner.exit);
|
|
59229
59411
|
const { session } = owner;
|
|
59230
59412
|
const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
|
|
59231
|
-
if (ownership.state !== "owned") return
|
|
59413
|
+
if (ownership.state !== "owned") return refuse5(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
|
|
59232
59414
|
let siteToken2;
|
|
59233
59415
|
try {
|
|
59234
59416
|
siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
|
|
59235
59417
|
} catch {
|
|
59236
|
-
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);
|
|
59237
59419
|
}
|
|
59238
59420
|
const body = {
|
|
59239
59421
|
app: ownership.slug,
|
|
@@ -59256,12 +59438,12 @@ function flagRefusal(flags) {
|
|
|
59256
59438
|
function report2(http, sent, flags, io) {
|
|
59257
59439
|
const code = refusalCode(http);
|
|
59258
59440
|
if (code === "send_outcome_unknown") {
|
|
59259
|
-
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 });
|
|
59260
59442
|
}
|
|
59261
59443
|
if (code === "rate_limited" && http.retryAfterSec) {
|
|
59262
|
-
return
|
|
59444
|
+
return refuse5(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
|
|
59263
59445
|
}
|
|
59264
|
-
if (code) return
|
|
59446
|
+
if (code) return refuse5(io, code, HINTS[code], 1);
|
|
59265
59447
|
if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
|
|
59266
59448
|
else io.log(summary(http.body ?? {}, sent));
|
|
59267
59449
|
return 0;
|
|
@@ -59321,15 +59503,15 @@ __export(notify_exports, {
|
|
|
59321
59503
|
runNotify: () => runNotify,
|
|
59322
59504
|
saveAdminSession: () => saveAdminSession
|
|
59323
59505
|
});
|
|
59324
|
-
import { chmodSync as chmodSync3, mkdirSync as
|
|
59506
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync26 } from "node:fs";
|
|
59325
59507
|
import { homedir as homedir6 } from "node:os";
|
|
59326
|
-
import { dirname as
|
|
59508
|
+
import { dirname as dirname35, join as join62 } from "node:path";
|
|
59327
59509
|
function defaultSessionsPath() {
|
|
59328
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
59510
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join62(homedir6(), ".himalaya", "admin-sessions.json");
|
|
59329
59511
|
}
|
|
59330
59512
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
59331
59513
|
try {
|
|
59332
|
-
return JSON.parse(
|
|
59514
|
+
return JSON.parse(readFileSync76(path2, "utf8"));
|
|
59333
59515
|
} catch {
|
|
59334
59516
|
return {};
|
|
59335
59517
|
}
|
|
@@ -59337,10 +59519,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
59337
59519
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
59338
59520
|
const file = loadSessionsFile(path2);
|
|
59339
59521
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
59340
|
-
|
|
59341
|
-
|
|
59522
|
+
mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
|
|
59523
|
+
writeFileSync26(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
59342
59524
|
try {
|
|
59343
|
-
chmodSync3(
|
|
59525
|
+
chmodSync3(dirname35(path2), 448);
|
|
59344
59526
|
chmodSync3(path2, 384);
|
|
59345
59527
|
} catch {
|
|
59346
59528
|
}
|
|
@@ -61940,10 +62122,10 @@ function assertPublicSiteUrl(raw) {
|
|
|
61940
62122
|
if (refusal) throw new Error(refusal);
|
|
61941
62123
|
}
|
|
61942
62124
|
function resolveAll(hostname2) {
|
|
61943
|
-
return new Promise((
|
|
62125
|
+
return new Promise((resolve54, reject) => {
|
|
61944
62126
|
dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
|
|
61945
62127
|
if (err) reject(err);
|
|
61946
|
-
else
|
|
62128
|
+
else resolve54(addresses);
|
|
61947
62129
|
});
|
|
61948
62130
|
});
|
|
61949
62131
|
}
|
|
@@ -61951,13 +62133,13 @@ function withAbort(start, signal, what) {
|
|
|
61951
62133
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
61952
62134
|
const work = start();
|
|
61953
62135
|
if (!signal) return work;
|
|
61954
|
-
return new Promise((
|
|
62136
|
+
return new Promise((resolve54, reject) => {
|
|
61955
62137
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
61956
62138
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
61957
|
-
work.then(
|
|
62139
|
+
work.then(resolve54, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
61958
62140
|
});
|
|
61959
62141
|
}
|
|
61960
|
-
async function pinAddress(url,
|
|
62142
|
+
async function pinAddress(url, resolve54 = resolveAll, signal) {
|
|
61961
62143
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
61962
62144
|
if (ipv4Octets(host)) {
|
|
61963
62145
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -61967,7 +62149,7 @@ async function pinAddress(url, resolve53 = resolveAll, signal) {
|
|
|
61967
62149
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
61968
62150
|
return { address: host, family: 6 };
|
|
61969
62151
|
}
|
|
61970
|
-
const addresses = await withAbort(() =>
|
|
62152
|
+
const addresses = await withAbort(() => resolve54(host), signal, `${host} lookup`);
|
|
61971
62153
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
61972
62154
|
const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
|
|
61973
62155
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -62007,7 +62189,7 @@ function copyIncomingHeaders(headers2) {
|
|
|
62007
62189
|
return out2;
|
|
62008
62190
|
}
|
|
62009
62191
|
function requestOnce(url, pinned, init) {
|
|
62010
|
-
return new Promise((
|
|
62192
|
+
return new Promise((resolve54, reject) => {
|
|
62011
62193
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
62012
62194
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
62013
62195
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -62037,7 +62219,7 @@ function requestOnce(url, pinned, init) {
|
|
|
62037
62219
|
reject(err);
|
|
62038
62220
|
return;
|
|
62039
62221
|
}
|
|
62040
|
-
|
|
62222
|
+
resolve54(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
|
|
62041
62223
|
}
|
|
62042
62224
|
);
|
|
62043
62225
|
req.on("error", reject);
|
|
@@ -63097,8 +63279,8 @@ var init_brand_font = __esm({
|
|
|
63097
63279
|
});
|
|
63098
63280
|
|
|
63099
63281
|
// src/site-analyze/write-artifacts.ts
|
|
63100
|
-
import { mkdirSync as
|
|
63101
|
-
import { join as
|
|
63282
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
|
|
63283
|
+
import { join as join63 } from "node:path";
|
|
63102
63284
|
function attachVeloSources(book, sources, put) {
|
|
63103
63285
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
63104
63286
|
for (const f of book.velo.files) {
|
|
@@ -63253,13 +63435,13 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
63253
63435
|
}
|
|
63254
63436
|
async function writeBusinessBook(result, opts) {
|
|
63255
63437
|
const out2 = opts.outDir;
|
|
63256
|
-
|
|
63257
|
-
|
|
63438
|
+
mkdirSync31(join63(out2, "evidence/pages"), { recursive: true });
|
|
63439
|
+
mkdirSync31(join63(out2, "media/catalog"), { recursive: true });
|
|
63258
63440
|
const files = [];
|
|
63259
63441
|
const put = (rel, body) => {
|
|
63260
|
-
const p =
|
|
63261
|
-
|
|
63262
|
-
|
|
63442
|
+
const p = join63(out2, rel);
|
|
63443
|
+
mkdirSync31(join63(p, ".."), { recursive: true });
|
|
63444
|
+
writeFileSync27(p, body);
|
|
63263
63445
|
files.push(rel);
|
|
63264
63446
|
};
|
|
63265
63447
|
const book = result.book;
|
|
@@ -63352,15 +63534,15 @@ var init_customer_build = __esm({
|
|
|
63352
63534
|
});
|
|
63353
63535
|
|
|
63354
63536
|
// src/site-analyze/apply.ts
|
|
63355
|
-
import { existsSync as
|
|
63356
|
-
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";
|
|
63357
63539
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
63358
63540
|
function unpairedRedirectNote(overlay) {
|
|
63359
63541
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
63360
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)`;
|
|
63361
63543
|
}
|
|
63362
63544
|
function posix3(p) {
|
|
63363
|
-
return
|
|
63545
|
+
return resolve51(p).replace(/\\/g, "/");
|
|
63364
63546
|
}
|
|
63365
63547
|
function committedShellProvisioning(path2) {
|
|
63366
63548
|
return committedShellFor(posix3(path2));
|
|
@@ -63368,8 +63550,8 @@ function committedShellProvisioning(path2) {
|
|
|
63368
63550
|
function findRepoRoot(cwd) {
|
|
63369
63551
|
let dir = cwd;
|
|
63370
63552
|
for (let i = 0; i < 8; i++) {
|
|
63371
|
-
if (SHELL_NAMES2.some((name) =>
|
|
63372
|
-
const next =
|
|
63553
|
+
if (SHELL_NAMES2.some((name) => existsSync65(join64(dir, shellAppDir(name), "package.json")))) return dir;
|
|
63554
|
+
const next = dirname36(dir);
|
|
63373
63555
|
if (next === dir) break;
|
|
63374
63556
|
dir = next;
|
|
63375
63557
|
}
|
|
@@ -63394,7 +63576,7 @@ function assertNotCommitted(path2, forbidden) {
|
|
|
63394
63576
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
63395
63577
|
);
|
|
63396
63578
|
}
|
|
63397
|
-
if (forbidden &&
|
|
63579
|
+
if (forbidden && resolve51(path2) === resolve51(forbidden)) {
|
|
63398
63580
|
const named = committedShellProvisioning(forbidden);
|
|
63399
63581
|
throw new Error(
|
|
63400
63582
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -63439,36 +63621,36 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
63439
63621
|
}
|
|
63440
63622
|
function buildMergedContract(options) {
|
|
63441
63623
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
63442
|
-
const committedPath =
|
|
63443
|
-
if (!
|
|
63624
|
+
const committedPath = join64(appDir3, "provisioning.json");
|
|
63625
|
+
if (!existsSync65(committedPath)) {
|
|
63444
63626
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
63445
63627
|
}
|
|
63446
|
-
const committed = JSON.parse(
|
|
63628
|
+
const committed = JSON.parse(readFileSync77(committedPath, "utf8"));
|
|
63447
63629
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
63448
63630
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
63449
63631
|
const branding = merged.branding ?? {};
|
|
63450
63632
|
const staged = [];
|
|
63451
63633
|
const contained = (root, rel) => {
|
|
63452
|
-
if (
|
|
63453
|
-
const full =
|
|
63454
|
-
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;
|
|
63455
63637
|
};
|
|
63456
63638
|
const stage = (fromRel, toRel) => {
|
|
63457
63639
|
const from = contained(packageDir, fromRel);
|
|
63458
|
-
const to = contained(
|
|
63459
|
-
if (!from || !to || !
|
|
63640
|
+
const to = contained(join64(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
63641
|
+
if (!from || !to || !existsSync65(from)) return void 0;
|
|
63460
63642
|
let real;
|
|
63461
63643
|
let realRoot;
|
|
63462
63644
|
try {
|
|
63463
|
-
real =
|
|
63464
|
-
realRoot =
|
|
63645
|
+
real = realpathSync10(from);
|
|
63646
|
+
realRoot = realpathSync10(packageDir);
|
|
63465
63647
|
} catch {
|
|
63466
63648
|
return void 0;
|
|
63467
63649
|
}
|
|
63468
|
-
if (!real.startsWith(realRoot +
|
|
63650
|
+
if (!real.startsWith(realRoot + sep17)) return void 0;
|
|
63469
63651
|
try {
|
|
63470
|
-
if (!
|
|
63471
|
-
|
|
63652
|
+
if (!statSync18(real).isFile()) return void 0;
|
|
63653
|
+
mkdirSync32(dirname36(to), { recursive: true });
|
|
63472
63654
|
copyFileSync3(real, to);
|
|
63473
63655
|
} catch {
|
|
63474
63656
|
return void 0;
|
|
@@ -63478,11 +63660,11 @@ function buildMergedContract(options) {
|
|
|
63478
63660
|
};
|
|
63479
63661
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
63480
63662
|
if (icon) branding.appIconPath = icon;
|
|
63481
|
-
const facesPath =
|
|
63482
|
-
if (
|
|
63663
|
+
const facesPath = join64(packageDir, "media/fonts/faces.json");
|
|
63664
|
+
if (existsSync65(facesPath)) {
|
|
63483
63665
|
let faces = [];
|
|
63484
63666
|
try {
|
|
63485
|
-
const parsed = JSON.parse(
|
|
63667
|
+
const parsed = JSON.parse(readFileSync77(facesPath, "utf8"));
|
|
63486
63668
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
63487
63669
|
} catch {
|
|
63488
63670
|
faces = [];
|
|
@@ -63503,11 +63685,11 @@ function buildMergedContract(options) {
|
|
|
63503
63685
|
merged.branding = branding;
|
|
63504
63686
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
63505
63687
|
`;
|
|
63506
|
-
const path2 =
|
|
63507
|
-
|
|
63508
|
-
const localPath =
|
|
63509
|
-
|
|
63510
|
-
|
|
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);
|
|
63511
63693
|
staged.push(localPath);
|
|
63512
63694
|
return { path: path2, staged };
|
|
63513
63695
|
}
|
|
@@ -63540,10 +63722,10 @@ function catalogTypography(overlay, template) {
|
|
|
63540
63722
|
function staticFaqFor(overlay, overlayPath) {
|
|
63541
63723
|
const own3 = overlay.faq;
|
|
63542
63724
|
if (own3 !== void 0) return deriveStaticFaq(own3);
|
|
63543
|
-
const bookPath =
|
|
63544
|
-
if (!
|
|
63725
|
+
const bookPath = join64(dirname36(resolve51(overlayPath)), "book.json");
|
|
63726
|
+
if (!existsSync65(bookPath)) return void 0;
|
|
63545
63727
|
try {
|
|
63546
|
-
const book = JSON.parse(
|
|
63728
|
+
const book = JSON.parse(readFileSync77(bookPath, "utf8"));
|
|
63547
63729
|
const copy = book?.copy;
|
|
63548
63730
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
63549
63731
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -63554,11 +63736,11 @@ function staticFaqFor(overlay, overlayPath) {
|
|
|
63554
63736
|
}
|
|
63555
63737
|
}
|
|
63556
63738
|
async function applyOverlays(input) {
|
|
63557
|
-
const cwd =
|
|
63739
|
+
const cwd = resolve51(input.cwd);
|
|
63558
63740
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
63559
63741
|
assertKnownShell(shell);
|
|
63560
|
-
const overlay = JSON.parse(
|
|
63561
|
-
const tokens = JSON.parse(
|
|
63742
|
+
const overlay = JSON.parse(readFileSync77(input.overlayPath, "utf8"));
|
|
63743
|
+
const tokens = JSON.parse(readFileSync77(input.tokensPath, "utf8"));
|
|
63562
63744
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
63563
63745
|
if (faq !== void 0) overlay.faq = faq;
|
|
63564
63746
|
const wrote = [];
|
|
@@ -63570,15 +63752,15 @@ async function applyOverlays(input) {
|
|
|
63570
63752
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
63571
63753
|
);
|
|
63572
63754
|
}
|
|
63573
|
-
const appDir3 =
|
|
63574
|
-
const committedPath =
|
|
63575
|
-
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;
|
|
63576
63758
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
63577
63759
|
throw new Error(
|
|
63578
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.`
|
|
63579
63761
|
);
|
|
63580
63762
|
}
|
|
63581
|
-
const packageDir =
|
|
63763
|
+
const packageDir = dirname36(resolve51(input.overlayPath));
|
|
63582
63764
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
|
|
63583
63765
|
wrote.push(...staged);
|
|
63584
63766
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -63599,22 +63781,22 @@ async function applyOverlays(input) {
|
|
|
63599
63781
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
63600
63782
|
};
|
|
63601
63783
|
}
|
|
63602
|
-
const pkgProv =
|
|
63784
|
+
const pkgProv = join64(cwd, "provisioning.json");
|
|
63603
63785
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
63604
63786
|
let packageFaq = faq;
|
|
63605
|
-
if (
|
|
63606
|
-
const cur = JSON.parse(
|
|
63787
|
+
if (existsSync65(pkgProv)) {
|
|
63788
|
+
const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
|
|
63607
63789
|
const merged = deepMerge4(cur, overlay);
|
|
63608
63790
|
packageFaq = merged.faq;
|
|
63609
|
-
|
|
63791
|
+
writeFileSync28(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
63610
63792
|
wrote.push(pkgProv);
|
|
63611
63793
|
} else {
|
|
63612
|
-
|
|
63794
|
+
writeFileSync28(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
63613
63795
|
wrote.push(pkgProv);
|
|
63614
63796
|
}
|
|
63615
|
-
const pkgTokens =
|
|
63616
|
-
if (
|
|
63617
|
-
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"));
|
|
63618
63800
|
let tokensIn = tokens;
|
|
63619
63801
|
if (tokens.typography) {
|
|
63620
63802
|
const fonts = catalogTypography(tokens.typography, cur.typography);
|
|
@@ -63635,13 +63817,13 @@ async function applyOverlays(input) {
|
|
|
63635
63817
|
if (primary && glow && typeof glow.color === "string") glow.color = primary;
|
|
63636
63818
|
stripBrandFromIdiom(merged);
|
|
63637
63819
|
}
|
|
63638
|
-
|
|
63820
|
+
writeFileSync28(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
63639
63821
|
wrote.push(pkgTokens);
|
|
63640
63822
|
}
|
|
63641
63823
|
const homeAction = homeRefreshActionId(shell);
|
|
63642
|
-
const homeSrc =
|
|
63643
|
-
if (homeAction &&
|
|
63644
|
-
const prev =
|
|
63824
|
+
const homeSrc = join64(cwd, "dev/index.ts");
|
|
63825
|
+
if (homeAction && existsSync65(homeSrc)) {
|
|
63826
|
+
const prev = readFileSync77(homeSrc, "utf8");
|
|
63645
63827
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
63646
63828
|
let next = patched.src;
|
|
63647
63829
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -63665,20 +63847,20 @@ async function applyOverlays(input) {
|
|
|
63665
63847
|
}
|
|
63666
63848
|
}
|
|
63667
63849
|
if (next !== prev) {
|
|
63668
|
-
|
|
63850
|
+
writeFileSync28(homeSrc, next);
|
|
63669
63851
|
wrote.push(homeSrc);
|
|
63670
63852
|
}
|
|
63671
63853
|
if (patched.unparsed) {
|
|
63672
63854
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
63673
63855
|
}
|
|
63674
63856
|
}
|
|
63675
|
-
if (!input.iconPath || !
|
|
63676
|
-
const book = input.iconPath ?
|
|
63857
|
+
if (!input.iconPath || !existsSync65(input.iconPath)) {
|
|
63858
|
+
const book = input.iconPath ? dirname36(dirname36(resolve51(input.iconPath))) : void 0;
|
|
63677
63859
|
notes.push(
|
|
63678
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"
|
|
63679
63861
|
);
|
|
63680
63862
|
}
|
|
63681
|
-
if (input.iconPath &&
|
|
63863
|
+
if (input.iconPath && existsSync65(input.iconPath)) {
|
|
63682
63864
|
try {
|
|
63683
63865
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
63684
63866
|
wrote.push(...installed.wrote);
|
|
@@ -64792,10 +64974,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
|
|
|
64792
64974
|
}
|
|
64793
64975
|
function createPromiseCallback(cb) {
|
|
64794
64976
|
let callback;
|
|
64795
|
-
let
|
|
64977
|
+
let resolve54;
|
|
64796
64978
|
let reject;
|
|
64797
64979
|
const promise = new Promise((_resolve, _reject) => {
|
|
64798
|
-
|
|
64980
|
+
resolve54 = _resolve;
|
|
64799
64981
|
reject = _reject;
|
|
64800
64982
|
});
|
|
64801
64983
|
if (typeof cb === "function") {
|
|
@@ -64811,7 +64993,7 @@ function createPromiseCallback(cb) {
|
|
|
64811
64993
|
callback = (err, result) => {
|
|
64812
64994
|
try {
|
|
64813
64995
|
if (err) reject(err);
|
|
64814
|
-
else
|
|
64996
|
+
else resolve54(result);
|
|
64815
64997
|
} catch (e) {
|
|
64816
64998
|
reject(e instanceof Error ? e : new Error());
|
|
64817
64999
|
}
|
|
@@ -67899,14 +68081,14 @@ async function runSiteFunction(opts) {
|
|
|
67899
68081
|
}
|
|
67900
68082
|
if (opts.op === "publish") {
|
|
67901
68083
|
const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
|
|
67902
|
-
const
|
|
68084
|
+
const ok2 = httpOk(snap.rev) && httpOk(snap.live);
|
|
67903
68085
|
return {
|
|
67904
68086
|
...base,
|
|
67905
|
-
ok,
|
|
68087
|
+
ok: ok2,
|
|
67906
68088
|
revision: snap.revision,
|
|
67907
68089
|
codeAppId: snap.codeAppId,
|
|
67908
68090
|
publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
|
|
67909
|
-
error:
|
|
68091
|
+
error: ok2 ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
|
|
67910
68092
|
};
|
|
67911
68093
|
}
|
|
67912
68094
|
const { id, listed } = await withGrid(fetchImpl, opts.token, opts.msid, opts.siteUrl);
|
|
@@ -68001,12 +68183,12 @@ async function invokeAndReport(fetchImpl, opts, base, name, method) {
|
|
|
68001
68183
|
await new Promise((res) => setTimeout(res, 2500));
|
|
68002
68184
|
hit = await tryInvoke();
|
|
68003
68185
|
}
|
|
68004
|
-
const
|
|
68186
|
+
const ok2 = httpOk(hit.r);
|
|
68005
68187
|
return {
|
|
68006
68188
|
...base,
|
|
68007
|
-
ok,
|
|
68189
|
+
ok: ok2,
|
|
68008
68190
|
invoke: { url: hit.url, status: hit.r.status, body: hit.r.json ?? snippet2(hit.r.text) },
|
|
68009
|
-
error:
|
|
68191
|
+
error: ok2 ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
|
|
68010
68192
|
};
|
|
68011
68193
|
}
|
|
68012
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;
|
|
@@ -68040,8 +68222,8 @@ __export(cli_exports, {
|
|
|
68040
68222
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
68041
68223
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
68042
68224
|
});
|
|
68043
|
-
import { readFileSync as
|
|
68044
|
-
import { resolve as
|
|
68225
|
+
import { readFileSync as readFileSync78 } from "node:fs";
|
|
68226
|
+
import { resolve as resolve52 } from "node:path";
|
|
68045
68227
|
function assetFetchFor(_opts) {
|
|
68046
68228
|
return pinnedFetch2;
|
|
68047
68229
|
}
|
|
@@ -68061,7 +68243,7 @@ async function runSiteAnalyze(opts) {
|
|
|
68061
68243
|
const assetFetch = assetFetchFor(opts);
|
|
68062
68244
|
const siteFetch = guardedSiteFetch;
|
|
68063
68245
|
const cwd = opts.cwd ?? process.cwd();
|
|
68064
|
-
const outDir =
|
|
68246
|
+
const outDir = resolve52(cwd, opts.outDir ?? ".himi/business-book");
|
|
68065
68247
|
let ownerAuth;
|
|
68066
68248
|
let msid;
|
|
68067
68249
|
const ownerSite = ownerSiteFor(opts);
|
|
@@ -68113,9 +68295,9 @@ async function runSiteAnalyze(opts) {
|
|
|
68113
68295
|
if (opts.apply) {
|
|
68114
68296
|
applied = await applyOverlays({
|
|
68115
68297
|
cwd,
|
|
68116
|
-
overlayPath:
|
|
68117
|
-
tokensPath:
|
|
68118
|
-
iconPath:
|
|
68298
|
+
overlayPath: resolve52(outDir, "provisioning.overlay.json"),
|
|
68299
|
+
tokensPath: resolve52(outDir, "tokens.overlay.json"),
|
|
68300
|
+
iconPath: resolve52(outDir, "media/icon.png"),
|
|
68119
68301
|
shell: opts.shell
|
|
68120
68302
|
});
|
|
68121
68303
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -68151,8 +68333,8 @@ async function runSiteFunctionCli(opts) {
|
|
|
68151
68333
|
const token = opts.token ?? await siteToken(msid);
|
|
68152
68334
|
let source;
|
|
68153
68335
|
if (opts.sourcePath) {
|
|
68154
|
-
const p =
|
|
68155
|
-
source =
|
|
68336
|
+
const p = resolve52(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
68337
|
+
source = readFileSync78(p, "utf8");
|
|
68156
68338
|
}
|
|
68157
68339
|
let body;
|
|
68158
68340
|
if (opts.bodyRaw != null) {
|
|
@@ -68207,7 +68389,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
68207
68389
|
cached2 = fromEnv;
|
|
68208
68390
|
return fromEnv;
|
|
68209
68391
|
}
|
|
68210
|
-
const token = await new Promise((
|
|
68392
|
+
const token = await new Promise((resolve54, reject) => {
|
|
68211
68393
|
let child;
|
|
68212
68394
|
try {
|
|
68213
68395
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -68236,7 +68418,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
68236
68418
|
const scan = (d) => {
|
|
68237
68419
|
out2 += String(d);
|
|
68238
68420
|
const m = out2.match(TOKEN_RE2);
|
|
68239
|
-
if (m) done(() =>
|
|
68421
|
+
if (m) done(() => resolve54(m[0]));
|
|
68240
68422
|
};
|
|
68241
68423
|
child.stdout?.on("data", scan);
|
|
68242
68424
|
child.stderr?.on("data", scan);
|
|
@@ -68413,7 +68595,7 @@ __export(site_create_exports, {
|
|
|
68413
68595
|
runSiteList: () => runSiteList,
|
|
68414
68596
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
68415
68597
|
});
|
|
68416
|
-
import { existsSync as
|
|
68598
|
+
import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync29 } from "node:fs";
|
|
68417
68599
|
import { resolve as resolvePath2 } from "node:path";
|
|
68418
68600
|
function oauthClientName(projectName) {
|
|
68419
68601
|
return `${projectName} client`;
|
|
@@ -68562,7 +68744,7 @@ async function runSiteCreate(opts) {
|
|
|
68562
68744
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
68563
68745
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
68564
68746
|
}
|
|
68565
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
68747
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync29 }) {
|
|
68566
68748
|
const msid = binding2.siteId;
|
|
68567
68749
|
const path2 = resolvePath2(target);
|
|
68568
68750
|
const committed = committedShellProvisioning(path2);
|
|
@@ -69235,12 +69417,12 @@ var init_context = __esm({
|
|
|
69235
69417
|
});
|
|
69236
69418
|
|
|
69237
69419
|
// src/cli.ts
|
|
69238
|
-
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";
|
|
69239
69421
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
69240
69422
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
69241
69423
|
import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
|
|
69242
69424
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
69243
|
-
import { join as
|
|
69425
|
+
import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
|
|
69244
69426
|
import { fileURLToPath as fileURLToPath26 } from "node:url";
|
|
69245
69427
|
|
|
69246
69428
|
// ../serve-cli/src/client.ts
|
|
@@ -69981,7 +70163,7 @@ async function browserLogin(opts) {
|
|
|
69981
70163
|
const log = opts.log ?? (() => {
|
|
69982
70164
|
});
|
|
69983
70165
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
69984
|
-
return await new Promise((
|
|
70166
|
+
return await new Promise((resolve54, reject) => {
|
|
69985
70167
|
let settled = false;
|
|
69986
70168
|
let loginUrl = "";
|
|
69987
70169
|
const server = createServer();
|
|
@@ -70045,7 +70227,7 @@ async function browserLogin(opts) {
|
|
|
70045
70227
|
return;
|
|
70046
70228
|
}
|
|
70047
70229
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
|
|
70048
|
-
finish2(() =>
|
|
70230
|
+
finish2(() => resolve54({ token, loginUrl }));
|
|
70049
70231
|
});
|
|
70050
70232
|
});
|
|
70051
70233
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -71375,8 +71557,8 @@ var str8 = (v) => typeof v === "string" ? v : void 0;
|
|
|
71375
71557
|
var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
71376
71558
|
function embeddedTemplateCatalog() {
|
|
71377
71559
|
return availableTemplates().map((name) => {
|
|
71378
|
-
const path2 =
|
|
71379
|
-
const meta = JSON.parse(
|
|
71560
|
+
const path2 = join65(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
71561
|
+
const meta = JSON.parse(readFileSync80(path2, "utf8"));
|
|
71380
71562
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
71381
71563
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
71382
71564
|
}
|
|
@@ -72058,7 +72240,7 @@ var COMMANDS = [
|
|
|
72058
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>]" },
|
|
72059
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>" },
|
|
72060
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>]" },
|
|
72061
|
-
{ 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.", required: "[plugin --out <dir>]" },
|
|
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]" },
|
|
72062
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]" },
|
|
72063
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]" },
|
|
72064
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]" },
|
|
@@ -72090,7 +72272,7 @@ var COMMANDS = [
|
|
|
72090
72272
|
];
|
|
72091
72273
|
function cliVersion() {
|
|
72092
72274
|
try {
|
|
72093
|
-
return JSON.parse(
|
|
72275
|
+
return JSON.parse(readFileSync80(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
72094
72276
|
} catch {
|
|
72095
72277
|
return "unknown";
|
|
72096
72278
|
}
|
|
@@ -72141,16 +72323,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
|
|
|
72141
72323
|
}
|
|
72142
72324
|
var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
|
|
72143
72325
|
function execNpmConfig(file, args, options) {
|
|
72144
|
-
return new Promise((
|
|
72145
|
-
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)));
|
|
72146
72328
|
});
|
|
72147
72329
|
}
|
|
72148
72330
|
var npmScopedWixRegistry = createScopedRegistryResolver();
|
|
72149
72331
|
async function scopedRegistryBefore(lookup2, deadline) {
|
|
72150
72332
|
let cancel = () => {
|
|
72151
72333
|
};
|
|
72152
|
-
const expired = new Promise((
|
|
72153
|
-
const timer = setTimeout(() =>
|
|
72334
|
+
const expired = new Promise((resolve54) => {
|
|
72335
|
+
const timer = setTimeout(() => resolve54(void 0), Math.max(0, deadline - Date.now()));
|
|
72154
72336
|
cancel = () => clearTimeout(timer);
|
|
72155
72337
|
});
|
|
72156
72338
|
try {
|
|
@@ -72208,18 +72390,18 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
72208
72390
|
}
|
|
72209
72391
|
function packageVersion(path2) {
|
|
72210
72392
|
try {
|
|
72211
|
-
const version2 = JSON.parse(
|
|
72393
|
+
const version2 = JSON.parse(readFileSync80(path2, "utf8")).version;
|
|
72212
72394
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
72213
72395
|
} catch {
|
|
72214
72396
|
return void 0;
|
|
72215
72397
|
}
|
|
72216
72398
|
}
|
|
72217
72399
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
72218
|
-
let dir =
|
|
72400
|
+
let dir = resolve53(fromDir);
|
|
72219
72401
|
for (; ; ) {
|
|
72220
|
-
const version2 = packageVersion(
|
|
72402
|
+
const version2 = packageVersion(join65(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
72221
72403
|
if (version2) return { version: version2, source: "local" };
|
|
72222
|
-
const parent =
|
|
72404
|
+
const parent = dirname37(dir);
|
|
72223
72405
|
if (parent === dir) break;
|
|
72224
72406
|
dir = parent;
|
|
72225
72407
|
}
|
|
@@ -72227,7 +72409,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
72227
72409
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
72228
72410
|
try {
|
|
72229
72411
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
72230
|
-
const version2 = root ? packageVersion(
|
|
72412
|
+
const version2 = root ? packageVersion(join65(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
72231
72413
|
return version2 ? { version: version2, source: "global" } : {};
|
|
72232
72414
|
} catch {
|
|
72233
72415
|
return {};
|
|
@@ -72274,11 +72456,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
72274
72456
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
72275
72457
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
72276
72458
|
function updateCachePath(env = process.env) {
|
|
72277
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
72459
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join65(homedir7(), ".himalaya", "update-check.json");
|
|
72278
72460
|
}
|
|
72279
72461
|
function readUpdateCache(path2) {
|
|
72280
72462
|
try {
|
|
72281
|
-
const parsed = JSON.parse(
|
|
72463
|
+
const parsed = JSON.parse(readFileSync80(path2, "utf8"));
|
|
72282
72464
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
72283
72465
|
} catch {
|
|
72284
72466
|
return {};
|
|
@@ -72286,8 +72468,8 @@ function readUpdateCache(path2) {
|
|
|
72286
72468
|
}
|
|
72287
72469
|
function writeUpdateCache(path2, cache) {
|
|
72288
72470
|
try {
|
|
72289
|
-
|
|
72290
|
-
|
|
72471
|
+
mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
|
|
72472
|
+
writeFileSync30(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
72291
72473
|
} catch {
|
|
72292
72474
|
}
|
|
72293
72475
|
}
|
|
@@ -72347,12 +72529,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
|
|
|
72347
72529
|
},
|
|
72348
72530
|
installedVersion: () => {
|
|
72349
72531
|
const root = globalNodeModulesRoot();
|
|
72350
|
-
return root ? packageVersion(
|
|
72532
|
+
return root ? packageVersion(join65(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
72351
72533
|
},
|
|
72352
72534
|
reexec: (argv) => {
|
|
72353
72535
|
const root = globalNodeModulesRoot();
|
|
72354
|
-
const entry = root ?
|
|
72355
|
-
if (!entry || !
|
|
72536
|
+
const entry = root ? join65(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
72537
|
+
if (!entry || !existsSync67(entry)) return void 0;
|
|
72356
72538
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
72357
72539
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
72358
72540
|
stdio: "inherit",
|
|
@@ -72399,7 +72581,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
72399
72581
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
72400
72582
|
let content;
|
|
72401
72583
|
try {
|
|
72402
|
-
content =
|
|
72584
|
+
content = readFileSync80(path2, "utf8");
|
|
72403
72585
|
} catch {
|
|
72404
72586
|
continue;
|
|
72405
72587
|
}
|
|
@@ -72407,7 +72589,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
72407
72589
|
let since = stamped;
|
|
72408
72590
|
if (!Number.isFinite(since)) {
|
|
72409
72591
|
try {
|
|
72410
|
-
since =
|
|
72592
|
+
since = statSync19(path2).mtimeMs;
|
|
72411
72593
|
} catch {
|
|
72412
72594
|
continue;
|
|
72413
72595
|
}
|
|
@@ -72422,14 +72604,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72422
72604
|
const mine = lockStamp(now);
|
|
72423
72605
|
const readLock = (path2) => {
|
|
72424
72606
|
try {
|
|
72425
|
-
return
|
|
72607
|
+
return readFileSync80(path2, "utf8");
|
|
72426
72608
|
} catch {
|
|
72427
72609
|
return void 0;
|
|
72428
72610
|
}
|
|
72429
72611
|
};
|
|
72430
72612
|
const tryCreate = (path2) => {
|
|
72431
72613
|
try {
|
|
72432
|
-
|
|
72614
|
+
writeFileSync30(path2, mine, { flag: "wx", mode: 384 });
|
|
72433
72615
|
return true;
|
|
72434
72616
|
} catch {
|
|
72435
72617
|
return false;
|
|
@@ -72437,13 +72619,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72437
72619
|
};
|
|
72438
72620
|
const removeIfMine = (path2) => {
|
|
72439
72621
|
try {
|
|
72440
|
-
if (readLock(path2) === mine)
|
|
72622
|
+
if (readLock(path2) === mine) rmSync16(path2, { force: true });
|
|
72441
72623
|
} catch {
|
|
72442
72624
|
}
|
|
72443
72625
|
};
|
|
72444
72626
|
const release = () => removeIfMine(lockPath);
|
|
72445
72627
|
try {
|
|
72446
|
-
|
|
72628
|
+
mkdirSync33(dirname37(lockPath), { recursive: true, mode: 448 });
|
|
72447
72629
|
} catch {
|
|
72448
72630
|
return () => {
|
|
72449
72631
|
};
|
|
@@ -72460,7 +72642,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72460
72642
|
hooks.underBreakLock?.();
|
|
72461
72643
|
if (current === void 0) return tryCreate(lockPath) ? release : void 0;
|
|
72462
72644
|
if (!isAbandoned(current)) return void 0;
|
|
72463
|
-
|
|
72645
|
+
rmSync16(lockPath, { force: true });
|
|
72464
72646
|
return tryCreate(lockPath) ? release : void 0;
|
|
72465
72647
|
} finally {
|
|
72466
72648
|
removeIfMine(breakPath);
|
|
@@ -72556,7 +72738,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
|
|
|
72556
72738
|
return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
|
|
72557
72739
|
};
|
|
72558
72740
|
return async (dir, opts = {}) => {
|
|
72559
|
-
const argv = ["validate", "--content",
|
|
72741
|
+
const argv = ["validate", "--content", resolve53(dir), "--strict", "--skip-version-check"];
|
|
72560
72742
|
if (!opts.fresh) {
|
|
72561
72743
|
const out2 = [];
|
|
72562
72744
|
const err = [];
|
|
@@ -73014,9 +73196,9 @@ function executableOnPath(name, env = process.env) {
|
|
|
73014
73196
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
73015
73197
|
for (const dir of entries) {
|
|
73016
73198
|
for (const suffix of suffixes) {
|
|
73017
|
-
const candidate =
|
|
73199
|
+
const candidate = join65(dir, `${name}${suffix}`);
|
|
73018
73200
|
try {
|
|
73019
|
-
if (!
|
|
73201
|
+
if (!statSync19(candidate).isFile()) continue;
|
|
73020
73202
|
if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
|
|
73021
73203
|
return true;
|
|
73022
73204
|
} catch {
|
|
@@ -73063,9 +73245,9 @@ function buildDoctorReport(input) {
|
|
|
73063
73245
|
const versionSkew = versions?.cli.status === "outdated" || sdkSkew;
|
|
73064
73246
|
const hostRefused = auth.controlTokenStatus === "refused";
|
|
73065
73247
|
const staleToken = auth.controlTokenPresent === true && auth.controlToken === false && !hostRefused;
|
|
73066
|
-
const
|
|
73248
|
+
const ok2 = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
|
|
73067
73249
|
return {
|
|
73068
|
-
ok,
|
|
73250
|
+
ok: ok2,
|
|
73069
73251
|
target,
|
|
73070
73252
|
version: version2,
|
|
73071
73253
|
dataPlane: { ...data, note: "public Wix APIs \u2014 reachable off-VPN" },
|
|
@@ -73123,7 +73305,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
73123
73305
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
73124
73306
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
73125
73307
|
const iosYmlPath = iosProjectYml2(app);
|
|
73126
|
-
const iosYml =
|
|
73308
|
+
const iosYml = existsSync67(iosYmlPath) ? readFileSync80(iosYmlPath, "utf8") : "";
|
|
73127
73309
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
73128
73310
|
if (!optedIn) {
|
|
73129
73311
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -73137,14 +73319,14 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
73137
73319
|
}
|
|
73138
73320
|
function readConfigSource(dir) {
|
|
73139
73321
|
try {
|
|
73140
|
-
return
|
|
73322
|
+
return readFileSync80(join65(dir, "config.ts"), "utf8");
|
|
73141
73323
|
} catch {
|
|
73142
73324
|
return null;
|
|
73143
73325
|
}
|
|
73144
73326
|
}
|
|
73145
73327
|
function writePngFile(path2, base64) {
|
|
73146
|
-
|
|
73147
|
-
|
|
73328
|
+
mkdirSync33(dirname37(path2), { recursive: true });
|
|
73329
|
+
writeFileSync30(path2, Buffer.from(base64, "base64"));
|
|
73148
73330
|
return path2;
|
|
73149
73331
|
}
|
|
73150
73332
|
async function seedAgentFilesFor(dir, flags, mode = "init") {
|
|
@@ -73172,8 +73354,8 @@ function keptPlan(kept) {
|
|
|
73172
73354
|
return note ? { kept, note } : {};
|
|
73173
73355
|
}
|
|
73174
73356
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
73175
|
-
const dir =
|
|
73176
|
-
if (
|
|
73357
|
+
const dir = resolve53(parentDir, name);
|
|
73358
|
+
if (existsSync67(join65(dir, "himalaya.content.json"))) {
|
|
73177
73359
|
throw new Error(`content package already exists at ${dir}`);
|
|
73178
73360
|
}
|
|
73179
73361
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -73185,7 +73367,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
|
73185
73367
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
73186
73368
|
}
|
|
73187
73369
|
function contentDir(flags) {
|
|
73188
|
-
return
|
|
73370
|
+
return resolve53(str8(flags.content) ?? process.cwd());
|
|
73189
73371
|
}
|
|
73190
73372
|
function renameRestoredSource(restored, declaredApp, renamed) {
|
|
73191
73373
|
const text8 = {};
|
|
@@ -73203,7 +73385,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
|
|
|
73203
73385
|
function symlinkDestinationIssue(dest) {
|
|
73204
73386
|
let kind;
|
|
73205
73387
|
try {
|
|
73206
|
-
kind =
|
|
73388
|
+
kind = lstatSync14(dest);
|
|
73207
73389
|
} catch {
|
|
73208
73390
|
return null;
|
|
73209
73391
|
}
|
|
@@ -73216,11 +73398,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
73216
73398
|
function restoreDestinationIssue(dest, force) {
|
|
73217
73399
|
const link = symlinkDestinationIssue(dest);
|
|
73218
73400
|
if (link) return link;
|
|
73219
|
-
if (!
|
|
73220
|
-
if (!
|
|
73401
|
+
if (!existsSync67(dest)) return null;
|
|
73402
|
+
if (!statSync19(dest).isDirectory()) {
|
|
73221
73403
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
73222
73404
|
}
|
|
73223
|
-
if (
|
|
73405
|
+
if (readdirSync31(dest).length > 0 && !force) {
|
|
73224
73406
|
return {
|
|
73225
73407
|
error: `${dest} already exists and is not empty`,
|
|
73226
73408
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -73229,10 +73411,10 @@ function restoreDestinationIssue(dest, force) {
|
|
|
73229
73411
|
return null;
|
|
73230
73412
|
}
|
|
73231
73413
|
function isHimalayaMonorepoCheckout(start) {
|
|
73232
|
-
let dir =
|
|
73414
|
+
let dir = resolve53(start);
|
|
73233
73415
|
for (; ; ) {
|
|
73234
|
-
if (
|
|
73235
|
-
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);
|
|
73236
73418
|
if (parent === dir) return false;
|
|
73237
73419
|
dir = parent;
|
|
73238
73420
|
}
|
|
@@ -73291,8 +73473,8 @@ function materializeForPreview(appDir3, slug, displayName) {
|
|
|
73291
73473
|
const forBuild = Object.fromEntries(
|
|
73292
73474
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
73293
73475
|
);
|
|
73294
|
-
const repoRoot2 =
|
|
73295
|
-
const root =
|
|
73476
|
+
const repoRoot2 = resolve53(fileURLToPath26(new URL("../../..", import.meta.url)));
|
|
73477
|
+
const root = join65(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
73296
73478
|
const stillRunning = (pid) => {
|
|
73297
73479
|
try {
|
|
73298
73480
|
process.kill(pid, 0);
|
|
@@ -73302,30 +73484,30 @@ function materializeForPreview(appDir3, slug, displayName) {
|
|
|
73302
73484
|
}
|
|
73303
73485
|
};
|
|
73304
73486
|
try {
|
|
73305
|
-
for (const entry of
|
|
73487
|
+
for (const entry of readdirSync31(root, { withFileTypes: true })) {
|
|
73306
73488
|
if (!entry.isDirectory()) continue;
|
|
73307
73489
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
73308
73490
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
73309
|
-
|
|
73491
|
+
rmSync16(join65(root, entry.name), { recursive: true, force: true });
|
|
73310
73492
|
}
|
|
73311
73493
|
}
|
|
73312
73494
|
} catch {
|
|
73313
73495
|
}
|
|
73314
|
-
const dest =
|
|
73315
|
-
|
|
73316
|
-
|
|
73496
|
+
const dest = join65(root, `${slug}-${process.pid}`);
|
|
73497
|
+
rmSync16(dest, { recursive: true, force: true });
|
|
73498
|
+
mkdirSync33(dest, { recursive: true });
|
|
73317
73499
|
try {
|
|
73318
73500
|
materializeSource(forBuild, displayName, dest, slug);
|
|
73319
73501
|
} catch (e) {
|
|
73320
|
-
|
|
73502
|
+
rmSync16(dest, { recursive: true, force: true });
|
|
73321
73503
|
throw e;
|
|
73322
73504
|
}
|
|
73323
73505
|
return dest;
|
|
73324
73506
|
}
|
|
73325
73507
|
async function appId(dir) {
|
|
73326
73508
|
try {
|
|
73327
|
-
const { readFileSync:
|
|
73328
|
-
const m = JSON.parse(
|
|
73509
|
+
const { readFileSync: readFileSync81 } = await import("node:fs");
|
|
73510
|
+
const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
|
|
73329
73511
|
if (m.name) return m.name;
|
|
73330
73512
|
} catch {
|
|
73331
73513
|
}
|
|
@@ -73333,8 +73515,8 @@ async function appId(dir) {
|
|
|
73333
73515
|
}
|
|
73334
73516
|
async function contentVisibility(dir) {
|
|
73335
73517
|
try {
|
|
73336
|
-
const { readFileSync:
|
|
73337
|
-
const m = JSON.parse(
|
|
73518
|
+
const { readFileSync: readFileSync81 } = await import("node:fs");
|
|
73519
|
+
const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
|
|
73338
73520
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
73339
73521
|
} catch {
|
|
73340
73522
|
}
|
|
@@ -73537,7 +73719,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
73537
73719
|
return 0;
|
|
73538
73720
|
}
|
|
73539
73721
|
case "agent-init": {
|
|
73540
|
-
const dir =
|
|
73722
|
+
const dir = resolve53(str8(flags.dir) ?? process.cwd());
|
|
73541
73723
|
const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
|
|
73542
73724
|
let res;
|
|
73543
73725
|
try {
|
|
@@ -73559,7 +73741,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
73559
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/" } : {},
|
|
73560
73742
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
73561
73743
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
73562
|
-
...
|
|
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" } : {},
|
|
73563
73745
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
73564
73746
|
portalUrl: idx.portalUrl
|
|
73565
73747
|
});
|
|
@@ -73582,7 +73764,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
73582
73764
|
try {
|
|
73583
73765
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
73584
73766
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
73585
|
-
out2 = mkdtempSync4(
|
|
73767
|
+
out2 = mkdtempSync4(join65(tmpdir5(), "himi-ux-record-"));
|
|
73586
73768
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
73587
73769
|
const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
73588
73770
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -73595,7 +73777,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
73595
73777
|
return null;
|
|
73596
73778
|
} finally {
|
|
73597
73779
|
if (out2 !== void 0) try {
|
|
73598
|
-
|
|
73780
|
+
rmSync16(out2, { recursive: true, force: true });
|
|
73599
73781
|
} catch {
|
|
73600
73782
|
}
|
|
73601
73783
|
}
|
|
@@ -73749,7 +73931,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73749
73931
|
}
|
|
73750
73932
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
73751
73933
|
try {
|
|
73752
|
-
|
|
73934
|
+
readdirSync31(outDir);
|
|
73753
73935
|
} catch {
|
|
73754
73936
|
return { families: void 0, source: "unbuilt" };
|
|
73755
73937
|
}
|
|
@@ -73760,7 +73942,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73760
73942
|
let js;
|
|
73761
73943
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
73762
73944
|
try {
|
|
73763
|
-
js =
|
|
73945
|
+
js = readFileSync80(join65(outDir, candidate), "utf8");
|
|
73764
73946
|
break;
|
|
73765
73947
|
} catch {
|
|
73766
73948
|
}
|
|
@@ -73791,7 +73973,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73791
73973
|
}
|
|
73792
73974
|
return { families, source: "dist/bundles" };
|
|
73793
73975
|
}
|
|
73794
|
-
var boardOpen = (dir) =>
|
|
73976
|
+
var boardOpen = (dir) => existsSync67(join65(dir, ".himi", "studio", "index.html"));
|
|
73795
73977
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
73796
73978
|
async function leaveForBoard(dir, record2, value) {
|
|
73797
73979
|
if (!boardOpen(dir)) return;
|
|
@@ -73815,7 +73997,7 @@ async function liveMapFor(dir) {
|
|
|
73815
73997
|
}
|
|
73816
73998
|
var commandScratch = new AsyncLocalStorage();
|
|
73817
73999
|
function commandScratchDir(prefix) {
|
|
73818
|
-
const dir = mkdtempSync4(
|
|
74000
|
+
const dir = mkdtempSync4(join65(tmpdir5(), prefix));
|
|
73819
74001
|
commandScratch.getStore()?.push(dir);
|
|
73820
74002
|
return dir;
|
|
73821
74003
|
}
|
|
@@ -73826,7 +74008,7 @@ async function run(argv, io = defaultIO, deps = {}) {
|
|
|
73826
74008
|
code = await commandScratch.run(scratch, () => runCommand(argv, io, deps));
|
|
73827
74009
|
} finally {
|
|
73828
74010
|
for (const dir of scratch) try {
|
|
73829
|
-
|
|
74011
|
+
rmSync16(dir, { recursive: true, force: true });
|
|
73830
74012
|
} catch {
|
|
73831
74013
|
}
|
|
73832
74014
|
}
|
|
@@ -74094,7 +74276,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
74094
74276
|
return 2;
|
|
74095
74277
|
}
|
|
74096
74278
|
const template = str8(flags.template);
|
|
74097
|
-
const parentDir =
|
|
74279
|
+
const parentDir = resolve53(str8(flags.dir) ?? process.cwd());
|
|
74098
74280
|
const withAgentFiles = async (dir) => {
|
|
74099
74281
|
const seeded = await seedAgentFilesFor(dir, flags);
|
|
74100
74282
|
if (!seeded.agent || "error" in seeded.agent) return seeded;
|
|
@@ -74107,7 +74289,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
74107
74289
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
74108
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`);
|
|
74109
74291
|
}
|
|
74110
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) =>
|
|
74292
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync67(join65(parentDir, f)));
|
|
74111
74293
|
if (planInParent.length) {
|
|
74112
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}`);
|
|
74113
74295
|
}
|
|
@@ -74255,11 +74437,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74255
74437
|
return 2;
|
|
74256
74438
|
}
|
|
74257
74439
|
}
|
|
74258
|
-
const appDir3 =
|
|
74259
|
-
const sourceDir =
|
|
74440
|
+
const appDir3 = resolve53(str8(flags.dir) ?? process.cwd());
|
|
74441
|
+
const sourceDir = resolve53(str8(flags["source-dir"]) ?? appDir3);
|
|
74260
74442
|
let meta;
|
|
74261
74443
|
try {
|
|
74262
|
-
meta = JSON.parse(
|
|
74444
|
+
meta = JSON.parse(readFileSync80(join65(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
74263
74445
|
} catch {
|
|
74264
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>)` }));
|
|
74265
74447
|
return 2;
|
|
@@ -74269,7 +74451,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74269
74451
|
return 2;
|
|
74270
74452
|
}
|
|
74271
74453
|
try {
|
|
74272
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
74454
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync80(join65(sourceDir, "tokens.json"), "utf8")));
|
|
74273
74455
|
meta = { ...appearance, ...meta };
|
|
74274
74456
|
} catch {
|
|
74275
74457
|
}
|
|
@@ -74291,14 +74473,14 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74291
74473
|
const force = flags.force === true;
|
|
74292
74474
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
74293
74475
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
74294
|
-
const out2 = mkdtempSync4(
|
|
74476
|
+
const out2 = mkdtempSync4(join65(tmpdir5(), "himi-template-"));
|
|
74295
74477
|
publishScratch.push(out2);
|
|
74296
74478
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
74297
74479
|
const outcome = await buildReleaseFromContent2(buildDir, out2, {
|
|
74298
74480
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
74299
74481
|
collect: { lint: true, strict }
|
|
74300
74482
|
});
|
|
74301
|
-
const scaffoldSourceFindings =
|
|
74483
|
+
const scaffoldSourceFindings = resolve53(sourceDir) === resolve53(appDir3) ? [] : [
|
|
74302
74484
|
...tokenColorIssues(sourceDir),
|
|
74303
74485
|
...surfaceIssues(sourceDir, void 0, strict),
|
|
74304
74486
|
...await fontIssues(sourceDir, strict),
|
|
@@ -74341,11 +74523,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74341
74523
|
}));
|
|
74342
74524
|
return 1;
|
|
74343
74525
|
}
|
|
74344
|
-
const iconPath = str8(flags.icon) ?
|
|
74526
|
+
const iconPath = str8(flags.icon) ? resolve53(str8(flags.icon)) : templateIconPath(name);
|
|
74345
74527
|
let iconHash;
|
|
74346
74528
|
if (iconPath) {
|
|
74347
74529
|
try {
|
|
74348
|
-
const bytes2 =
|
|
74530
|
+
const bytes2 = readFileSync80(iconPath);
|
|
74349
74531
|
payload.icon = bytes2.toString("base64");
|
|
74350
74532
|
iconHash = createHash31("sha256").update(bytes2).digest("hex");
|
|
74351
74533
|
} catch {
|
|
@@ -74518,7 +74700,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74518
74700
|
} finally {
|
|
74519
74701
|
for (const dir of publishScratch) {
|
|
74520
74702
|
try {
|
|
74521
|
-
|
|
74703
|
+
rmSync16(dir, { recursive: true, force: true });
|
|
74522
74704
|
} catch (e) {
|
|
74523
74705
|
io.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e.message}` }));
|
|
74524
74706
|
}
|
|
@@ -74552,12 +74734,12 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74552
74734
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
74553
74735
|
return 2;
|
|
74554
74736
|
}
|
|
74555
|
-
const { readdirSync:
|
|
74737
|
+
const { readdirSync: readdirSync32, existsSync: fileExists } = await import("node:fs");
|
|
74556
74738
|
const { join: pathJoin } = await import("node:path");
|
|
74557
74739
|
const targets = [];
|
|
74558
74740
|
const t5 = pathJoin(dir, "tier5-src");
|
|
74559
74741
|
if (fileExists(t5)) {
|
|
74560
|
-
for (const d of
|
|
74742
|
+
for (const d of readdirSync32(t5, { withFileTypes: true })) {
|
|
74561
74743
|
if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
|
|
74562
74744
|
}
|
|
74563
74745
|
}
|
|
@@ -74632,7 +74814,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74632
74814
|
const path2 = dpxSessionTokenPath();
|
|
74633
74815
|
let raw;
|
|
74634
74816
|
try {
|
|
74635
|
-
raw =
|
|
74817
|
+
raw = readFileSync80(path2, "utf8");
|
|
74636
74818
|
} catch {
|
|
74637
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`);
|
|
74638
74820
|
}
|
|
@@ -74763,32 +74945,37 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74763
74945
|
return 1;
|
|
74764
74946
|
}
|
|
74765
74947
|
const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
|
|
74766
|
-
const dir =
|
|
74948
|
+
const dir = resolve53(out2);
|
|
74767
74949
|
const files = himiPluginFiles2(skills.skillMd);
|
|
74768
74950
|
for (const f of files) {
|
|
74769
|
-
|
|
74770
|
-
|
|
74951
|
+
mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
|
|
74952
|
+
writeFileSync30(join65(dir, f.path), f.text);
|
|
74771
74953
|
}
|
|
74772
74954
|
print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
74773
74955
|
return 0;
|
|
74774
74956
|
}
|
|
74775
74957
|
const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
74776
|
-
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
|
+
});
|
|
74777
74964
|
return 0;
|
|
74778
74965
|
}
|
|
74779
74966
|
case "studio": {
|
|
74780
74967
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
74781
74968
|
const dir = contentDir(flags);
|
|
74782
|
-
if (!
|
|
74969
|
+
if (!existsSync67(join65(dir, "himalaya.content.json"))) {
|
|
74783
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/" }));
|
|
74784
74971
|
return 2;
|
|
74785
74972
|
}
|
|
74786
74973
|
if (pos[1] === "reel") {
|
|
74787
74974
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
74788
|
-
const out2 =
|
|
74975
|
+
const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
|
|
74789
74976
|
const { html, plan } = buildReel2(dir);
|
|
74790
|
-
|
|
74791
|
-
|
|
74977
|
+
mkdirSync33(dirname37(out2), { recursive: true });
|
|
74978
|
+
writeFileSync30(out2, html);
|
|
74792
74979
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
74793
74980
|
const url2 = pathToFileURL9(out2).href;
|
|
74794
74981
|
const open2 = flags["no-open"] !== true;
|
|
@@ -74857,7 +75044,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
74857
75044
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
74858
75045
|
const dir = contentDir(flags);
|
|
74859
75046
|
const journal2 = journalPath2(dir);
|
|
74860
|
-
const isContentPackage =
|
|
75047
|
+
const isContentPackage = existsSync67(join65(dir, "himalaya.content.json"));
|
|
74861
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" };
|
|
74862
75049
|
const message = pos.slice(1).join(" ").trim();
|
|
74863
75050
|
const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
|
|
@@ -75006,7 +75193,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75006
75193
|
case "test": {
|
|
75007
75194
|
const dir = contentDir(flags);
|
|
75008
75195
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
75009
|
-
if (
|
|
75196
|
+
if (existsSync67(join65(dir, "functions"))) {
|
|
75010
75197
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
75011
75198
|
const loaded = await loadFunctionsApp2(dir);
|
|
75012
75199
|
const results = [];
|
|
@@ -75138,7 +75325,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75138
75325
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
75139
75326
|
return 2;
|
|
75140
75327
|
}
|
|
75141
|
-
const sources = collectWorkerSources2(
|
|
75328
|
+
const sources = collectWorkerSources2(join65(dir, "tier5-src"), screen.bundleName);
|
|
75142
75329
|
if (!sources) {
|
|
75143
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` }));
|
|
75144
75331
|
return 2;
|
|
@@ -75315,7 +75502,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75315
75502
|
const sp = await runShotsPass2({
|
|
75316
75503
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
75317
75504
|
tokens: outcome.tokens,
|
|
75318
|
-
outDir:
|
|
75505
|
+
outDir: join65(dir, ".himi", "shots"),
|
|
75319
75506
|
width: 390,
|
|
75320
75507
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
75321
75508
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -75325,7 +75512,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75325
75512
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
75326
75513
|
renderPngBatch: renderPngBatch2,
|
|
75327
75514
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
75328
|
-
clearDir: (d) =>
|
|
75515
|
+
clearDir: (d) => rmSync16(d, { recursive: true, force: true })
|
|
75329
75516
|
}
|
|
75330
75517
|
});
|
|
75331
75518
|
writtenShots = sp.written;
|
|
@@ -75353,7 +75540,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75353
75540
|
releaseId: result.releaseId,
|
|
75354
75541
|
releasePayload: release,
|
|
75355
75542
|
descriptors: attestedDescriptors,
|
|
75356
|
-
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)])),
|
|
75357
75544
|
coverage: {
|
|
75358
75545
|
screens: crawledScreens.size,
|
|
75359
75546
|
actionsDispatched: result.actions.exercised,
|
|
@@ -75464,7 +75651,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75464
75651
|
return 2;
|
|
75465
75652
|
}
|
|
75466
75653
|
try {
|
|
75467
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
75654
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync80(stateArg.replace(/^@/, ""), "utf8");
|
|
75468
75655
|
injectedState = JSON.parse(raw);
|
|
75469
75656
|
} catch (e) {
|
|
75470
75657
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -75479,7 +75666,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75479
75666
|
return 2;
|
|
75480
75667
|
}
|
|
75481
75668
|
try {
|
|
75482
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
75669
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync80(inputArg.replace(/^@/, ""), "utf8");
|
|
75483
75670
|
const parsed = JSON.parse(raw);
|
|
75484
75671
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
75485
75672
|
injectedInput = parsed;
|
|
@@ -75542,11 +75729,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75542
75729
|
const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
|
|
75543
75730
|
let pngFile;
|
|
75544
75731
|
let attestationPngFile;
|
|
75545
|
-
const shotPath =
|
|
75732
|
+
const shotPath = join65(dir, ".himi", "shots", `${screenId}.png`);
|
|
75546
75733
|
const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
|
|
75547
75734
|
if (pngTarget && r.pngBase64) {
|
|
75548
75735
|
pngFile = writePngFile(pngTarget, r.pngBase64);
|
|
75549
|
-
attestationPngFile =
|
|
75736
|
+
attestationPngFile = resolve53(pngTarget) === resolve53(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
|
|
75550
75737
|
}
|
|
75551
75738
|
if (renderWidth !== void 0 && r.renderable) {
|
|
75552
75739
|
recordRenderWidth(dir, {
|
|
@@ -75882,7 +76069,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75882
76069
|
return 2;
|
|
75883
76070
|
}
|
|
75884
76071
|
const renamed = str8(flags.name);
|
|
75885
|
-
const dest =
|
|
76072
|
+
const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
75886
76073
|
const replace = flags.replace === true;
|
|
75887
76074
|
const force = replace || flags.force === true;
|
|
75888
76075
|
const linked = symlinkDestinationIssue(dest);
|
|
@@ -75890,20 +76077,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75890
76077
|
io.error(JSON.stringify(linked));
|
|
75891
76078
|
return 1;
|
|
75892
76079
|
}
|
|
75893
|
-
if (
|
|
75894
|
-
if (!
|
|
76080
|
+
if (existsSync67(dest)) {
|
|
76081
|
+
if (!statSync19(dest).isDirectory()) {
|
|
75895
76082
|
io.error(JSON.stringify({
|
|
75896
76083
|
error: `${dest} exists and is not a directory`,
|
|
75897
76084
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
75898
76085
|
}));
|
|
75899
76086
|
return 1;
|
|
75900
76087
|
}
|
|
75901
|
-
const occupied =
|
|
76088
|
+
const occupied = readdirSync31(dest).length > 0;
|
|
75902
76089
|
if (occupied && !force) {
|
|
75903
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" }));
|
|
75904
76091
|
return 1;
|
|
75905
76092
|
}
|
|
75906
|
-
if (replace && occupied && !
|
|
76093
|
+
if (replace && occupied && !existsSync67(join65(dest, "himalaya.content.json"))) {
|
|
75907
76094
|
io.error(JSON.stringify({
|
|
75908
76095
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
75909
76096
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -76070,7 +76257,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76070
76257
|
const manifest = outcome.manifest;
|
|
76071
76258
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
76072
76259
|
const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
|
|
76073
|
-
const contentRel =
|
|
76260
|
+
const contentRel = relative14(process.cwd(), dir) || ".";
|
|
76074
76261
|
const contentArg2 = shellQuote3(contentRel);
|
|
76075
76262
|
if (onlyRaw !== void 0) {
|
|
76076
76263
|
const onlyDraft = flags.draft === true;
|
|
@@ -76541,7 +76728,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76541
76728
|
return 2;
|
|
76542
76729
|
}
|
|
76543
76730
|
try {
|
|
76544
|
-
const res = writePack(
|
|
76731
|
+
const res = writePack(resolve53(releaseDir), only, resolve53(str8(flags.out) ?? process.cwd()));
|
|
76545
76732
|
print({
|
|
76546
76733
|
ok: true,
|
|
76547
76734
|
app: res.app,
|
|
@@ -76590,7 +76777,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76590
76777
|
}
|
|
76591
76778
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76592
76779
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
76593
|
-
const built = mkdtempSync4(
|
|
76780
|
+
const built = mkdtempSync4(join65(tmpdir5(), "himi-pack-"));
|
|
76594
76781
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
76595
76782
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
76596
76783
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -76607,12 +76794,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76607
76794
|
...await navIssues2(dir, strict)
|
|
76608
76795
|
]);
|
|
76609
76796
|
if (hasErrors && !force) {
|
|
76610
|
-
|
|
76797
|
+
rmSync16(built, { recursive: true, force: true });
|
|
76611
76798
|
print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
76612
76799
|
return 1;
|
|
76613
76800
|
}
|
|
76614
76801
|
try {
|
|
76615
|
-
const res = writePack(built, app,
|
|
76802
|
+
const res = writePack(built, app, resolve53(str8(flags.out) ?? dir), sourceArchive);
|
|
76616
76803
|
print({
|
|
76617
76804
|
ok: true,
|
|
76618
76805
|
app: res.app,
|
|
@@ -76643,7 +76830,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76643
76830
|
io.error(JSON.stringify({ error: e.message }));
|
|
76644
76831
|
return 1;
|
|
76645
76832
|
} finally {
|
|
76646
|
-
|
|
76833
|
+
rmSync16(built, { recursive: true, force: true });
|
|
76647
76834
|
}
|
|
76648
76835
|
}
|
|
76649
76836
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -76657,7 +76844,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76657
76844
|
const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
|
|
76658
76845
|
let opened;
|
|
76659
76846
|
try {
|
|
76660
|
-
opened = openPackageFile2(
|
|
76847
|
+
opened = openPackageFile2(resolve53(file));
|
|
76661
76848
|
} catch (e) {
|
|
76662
76849
|
io.error(JSON.stringify({ error: e.message }));
|
|
76663
76850
|
return 1;
|
|
@@ -76670,7 +76857,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76670
76857
|
io.error(JSON.stringify({
|
|
76671
76858
|
ok: false,
|
|
76672
76859
|
error: "app_source_not_in_package",
|
|
76673
|
-
detail: `${
|
|
76860
|
+
detail: `${resolve53(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
|
|
76674
76861
|
hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
|
|
76675
76862
|
}));
|
|
76676
76863
|
return 1;
|
|
@@ -76693,7 +76880,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76693
76880
|
return 1;
|
|
76694
76881
|
}
|
|
76695
76882
|
}
|
|
76696
|
-
const dest =
|
|
76883
|
+
const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
|
|
76697
76884
|
const issue2 = restoreDestinationIssue(dest, flags.force === true);
|
|
76698
76885
|
if (issue2) {
|
|
76699
76886
|
io.error(JSON.stringify(issue2));
|
|
@@ -76780,7 +76967,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76780
76967
|
}
|
|
76781
76968
|
try {
|
|
76782
76969
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
76783
|
-
const opened = openPackageFile2(
|
|
76970
|
+
const opened = openPackageFile2(resolve53(file));
|
|
76784
76971
|
if (!opened.validation.ok || !opened.header) {
|
|
76785
76972
|
io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
76786
76973
|
return 1;
|
|
@@ -76790,12 +76977,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76790
76977
|
io.error(JSON.stringify({
|
|
76791
76978
|
ok: false,
|
|
76792
76979
|
error: "refusing to share a package that carries the app's source",
|
|
76793
|
-
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`,
|
|
76794
76981
|
hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
|
|
76795
76982
|
}));
|
|
76796
76983
|
return 1;
|
|
76797
76984
|
}
|
|
76798
|
-
const archive =
|
|
76985
|
+
const archive = readFileSync80(resolve53(file));
|
|
76799
76986
|
const result = await client2().createPackageShare({
|
|
76800
76987
|
app: opened.header.app,
|
|
76801
76988
|
releaseId: opened.header.releaseId,
|
|
@@ -76871,11 +77058,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76871
77058
|
const app = await appId(dir2);
|
|
76872
77059
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76873
77060
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
76874
|
-
temp = mkdtempSync4(
|
|
77061
|
+
temp = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
|
|
76875
77062
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
76876
77063
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
76877
77064
|
servedMissing = initial.missingBundles;
|
|
76878
|
-
source =
|
|
77065
|
+
source = join65(temp, app);
|
|
76879
77066
|
}
|
|
76880
77067
|
const chromeArg = str8(flags.chrome) ?? "preview";
|
|
76881
77068
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -76911,7 +77098,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76911
77098
|
if (!recordKit) return;
|
|
76912
77099
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
76913
77100
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
76914
|
-
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.` }));
|
|
76915
77102
|
await refreshBoard();
|
|
76916
77103
|
};
|
|
76917
77104
|
const retract = async () => {
|
|
@@ -76934,9 +77121,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76934
77121
|
});
|
|
76935
77122
|
await announce(run2);
|
|
76936
77123
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
76937
|
-
await new Promise((
|
|
77124
|
+
await new Promise((resolve54) => {
|
|
76938
77125
|
const stop = () => {
|
|
76939
|
-
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()));
|
|
76940
77127
|
};
|
|
76941
77128
|
process.once("SIGINT", stop);
|
|
76942
77129
|
process.once("SIGTERM", stop);
|
|
@@ -76945,7 +77132,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76945
77132
|
}
|
|
76946
77133
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
76947
77134
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
76948
|
-
if (watch2) served = mkdtempSync4(
|
|
77135
|
+
if (watch2) served = mkdtempSync4(join65(tmpdir5(), "himi-run-served-"));
|
|
76949
77136
|
const running = await runPackage2(source, {
|
|
76950
77137
|
port,
|
|
76951
77138
|
chrome: chromeArg,
|
|
@@ -76974,8 +77161,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76974
77161
|
await announce(running);
|
|
76975
77162
|
if (watchKit && bus) {
|
|
76976
77163
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76977
|
-
const live2 =
|
|
76978
|
-
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"));
|
|
76979
77166
|
let current = manifestOf(live2);
|
|
76980
77167
|
const failed2 = async (message) => {
|
|
76981
77168
|
if (stopping) return;
|
|
@@ -76986,7 +77173,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76986
77173
|
};
|
|
76987
77174
|
rebuild = watchKit.serialize(async () => {
|
|
76988
77175
|
const t0 = Date.now();
|
|
76989
|
-
const next = mkdtempSync4(
|
|
77176
|
+
const next = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
|
|
76990
77177
|
try {
|
|
76991
77178
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
76992
77179
|
if (bres.compileErrors.length) {
|
|
@@ -77003,18 +77190,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77003
77190
|
return;
|
|
77004
77191
|
}
|
|
77005
77192
|
if (stopping) return;
|
|
77006
|
-
const fresh = manifestOf(
|
|
77193
|
+
const fresh = manifestOf(join65(next, running.app));
|
|
77007
77194
|
const diff = watchKit.diffReleases(current, fresh);
|
|
77008
77195
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
77009
|
-
const changes = describeChanges2(live2,
|
|
77196
|
+
const changes = describeChanges2(live2, join65(next, running.app), diff);
|
|
77010
77197
|
const retired = `${live2}.retired-${Date.now()}`;
|
|
77011
77198
|
renameSync7(live2, retired);
|
|
77012
77199
|
try {
|
|
77013
|
-
renameSync7(
|
|
77200
|
+
renameSync7(join65(next, running.app), live2);
|
|
77014
77201
|
} catch {
|
|
77015
|
-
cpSync3(
|
|
77202
|
+
cpSync3(join65(next, running.app), live2, { recursive: true });
|
|
77016
77203
|
}
|
|
77017
|
-
|
|
77204
|
+
rmSync16(retired, { recursive: true, force: true });
|
|
77018
77205
|
current = fresh;
|
|
77019
77206
|
servedMissing = outcome.missingBundles;
|
|
77020
77207
|
for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
|
|
@@ -77024,7 +77211,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77024
77211
|
} catch (e) {
|
|
77025
77212
|
await failed2(e.message.split("\n")[0]);
|
|
77026
77213
|
} finally {
|
|
77027
|
-
|
|
77214
|
+
rmSync16(next, { recursive: true, force: true });
|
|
77028
77215
|
}
|
|
77029
77216
|
});
|
|
77030
77217
|
watcher2 = watchKit.watchContent(dir, () => {
|
|
@@ -77092,9 +77279,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77092
77279
|
io.error(JSON.stringify({ error: e.message }));
|
|
77093
77280
|
return 1;
|
|
77094
77281
|
} finally {
|
|
77095
|
-
if (temp)
|
|
77096
|
-
if (served)
|
|
77097
|
-
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 });
|
|
77098
77285
|
}
|
|
77099
77286
|
}
|
|
77100
77287
|
case "preview": {
|
|
@@ -77636,7 +77823,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77636
77823
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
77637
77824
|
return 2;
|
|
77638
77825
|
}
|
|
77639
|
-
if (!
|
|
77826
|
+
if (!existsSync67(file)) {
|
|
77640
77827
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
77641
77828
|
return 2;
|
|
77642
77829
|
}
|
|
@@ -77692,7 +77879,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77692
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."
|
|
77693
77880
|
};
|
|
77694
77881
|
if (kind === "tokens" || kind === "app-config") {
|
|
77695
|
-
const body =
|
|
77882
|
+
const body = readFileSync80(file, "utf8");
|
|
77696
77883
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
77697
77884
|
return runReleasePatch({
|
|
77698
77885
|
...common,
|
|
@@ -77707,7 +77894,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77707
77894
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
77708
77895
|
return 2;
|
|
77709
77896
|
}
|
|
77710
|
-
const descriptor =
|
|
77897
|
+
const descriptor = readFileSync80(file, "utf8");
|
|
77711
77898
|
try {
|
|
77712
77899
|
JSON.parse(descriptor);
|
|
77713
77900
|
} catch (e) {
|
|
@@ -77747,7 +77934,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77747
77934
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
77748
77935
|
});
|
|
77749
77936
|
}
|
|
77750
|
-
const bytes2 =
|
|
77937
|
+
const bytes2 = readFileSync80(file);
|
|
77751
77938
|
const sha = createHash31("sha256").update(bytes2).digest("hex");
|
|
77752
77939
|
const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
77753
77940
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -77891,7 +78078,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77891
78078
|
}
|
|
77892
78079
|
let def;
|
|
77893
78080
|
try {
|
|
77894
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
78081
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync80(arg.slice(1), "utf8") : arg);
|
|
77895
78082
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
77896
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}`] }));
|
|
77897
78084
|
return 2;
|
|
@@ -78355,7 +78542,7 @@ ${label2}`);
|
|
|
78355
78542
|
const platform = str8(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
78356
78543
|
{
|
|
78357
78544
|
const distDir = contentDir(flags);
|
|
78358
|
-
if (
|
|
78545
|
+
if (existsSync67(join65(distDir, "himalaya.content.json"))) {
|
|
78359
78546
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
78360
78547
|
const errors = issues.filter((i) => i.severity === "error");
|
|
78361
78548
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -78641,7 +78828,7 @@ ${label2}`);
|
|
|
78641
78828
|
const dpxPath = dpxSessionTokenPath();
|
|
78642
78829
|
let dpx;
|
|
78643
78830
|
try {
|
|
78644
|
-
dpx =
|
|
78831
|
+
dpx = readFileSync80(dpxPath, "utf8").trim();
|
|
78645
78832
|
} catch {
|
|
78646
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` }));
|
|
78647
78834
|
return 1;
|
|
@@ -79049,7 +79236,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
79049
79236
|
const path2 = dpxSessionTokenPath();
|
|
79050
79237
|
let raw;
|
|
79051
79238
|
try {
|
|
79052
|
-
raw =
|
|
79239
|
+
raw = readFileSync80(path2, "utf8");
|
|
79053
79240
|
} catch {
|
|
79054
79241
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
79055
79242
|
return 1;
|