@wix/himalaya-cli 0.1114.0 → 0.1116.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 +847 -653
- package/guides/himi-mcp.md +8 -0
- package/guides/wix-business-context.md +4 -2
- package/package.json +2 -2
- package/template-icons/brandy.png +0 -0
- package/templates/brandy/README.md +60 -0
- package/templates/brandy/config.ts +76 -0
- package/templates/brandy/dev/index.ts +25 -0
- package/templates/brandy/himalaya.content.json +5 -0
- package/templates/brandy/himalaya.template.json +6 -0
- package/templates/brandy/icon.png +0 -0
- package/templates/brandy/platforms.json +1 -0
- package/templates/brandy/provisioning.json +12 -0
- package/templates/brandy/tokens.json +128 -0
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) {
|
|
@@ -14806,8 +14806,8 @@ function matchWeightCss(available, desired) {
|
|
|
14806
14806
|
const upFrom = (n) => sorted2.find((w) => w >= n);
|
|
14807
14807
|
const downFrom = (n) => [...sorted2].reverse().find((w) => w <= n);
|
|
14808
14808
|
if (desired >= 400 && desired <= 500) {
|
|
14809
|
-
const
|
|
14810
|
-
return
|
|
14809
|
+
const within2 = sorted2.find((w) => w >= desired && w <= 500);
|
|
14810
|
+
return within2 ?? downFrom(desired) ?? upFrom(desired);
|
|
14811
14811
|
}
|
|
14812
14812
|
if (desired < 400) return downFrom(desired) ?? upFrom(desired);
|
|
14813
14813
|
return upFrom(desired) ?? downFrom(desired);
|
|
@@ -15930,29 +15930,29 @@ function matchRuleEx(rules, method, path2, ctx = {}) {
|
|
|
15930
15930
|
}
|
|
15931
15931
|
if (m.query) {
|
|
15932
15932
|
const q = ctx.query ?? {};
|
|
15933
|
-
let
|
|
15933
|
+
let ok2 = true;
|
|
15934
15934
|
for (const [k, v] of Object.entries(m.query)) {
|
|
15935
15935
|
if (q[k] !== v) {
|
|
15936
|
-
|
|
15936
|
+
ok2 = false;
|
|
15937
15937
|
break;
|
|
15938
15938
|
}
|
|
15939
15939
|
captures[`query.${k}`] = q[k];
|
|
15940
15940
|
}
|
|
15941
|
-
if (!
|
|
15941
|
+
if (!ok2) continue;
|
|
15942
15942
|
for (const [k, v] of Object.entries(q)) captures[`query.${k}`] = v;
|
|
15943
15943
|
} else if (ctx.query) {
|
|
15944
15944
|
for (const [k, v] of Object.entries(ctx.query)) captures[`query.${k}`] = v;
|
|
15945
15945
|
}
|
|
15946
15946
|
if (m.headers) {
|
|
15947
15947
|
const hh = lc(ctx.headers);
|
|
15948
|
-
let
|
|
15948
|
+
let ok2 = true;
|
|
15949
15949
|
for (const [k, v] of Object.entries(m.headers)) {
|
|
15950
15950
|
if (hh[k.toLowerCase()] !== v) {
|
|
15951
|
-
|
|
15951
|
+
ok2 = false;
|
|
15952
15952
|
break;
|
|
15953
15953
|
}
|
|
15954
15954
|
}
|
|
15955
|
-
if (!
|
|
15955
|
+
if (!ok2) continue;
|
|
15956
15956
|
}
|
|
15957
15957
|
if (m.bodyContains && !(ctx.body ?? "").includes(m.bodyContains)) continue;
|
|
15958
15958
|
return { rule: r, captures };
|
|
@@ -18574,11 +18574,11 @@ function appleScriptString(s) {
|
|
|
18574
18574
|
function runNotifier(cmd, args) {
|
|
18575
18575
|
return new Promise((done) => {
|
|
18576
18576
|
let settled = false;
|
|
18577
|
-
const finish2 = (
|
|
18577
|
+
const finish2 = (ok2) => {
|
|
18578
18578
|
if (!settled) {
|
|
18579
18579
|
settled = true;
|
|
18580
18580
|
clearTimeout(timer);
|
|
18581
|
-
done(
|
|
18581
|
+
done(ok2);
|
|
18582
18582
|
}
|
|
18583
18583
|
};
|
|
18584
18584
|
const child = spawn3(cmd, args, { stdio: "ignore" });
|
|
@@ -19465,10 +19465,10 @@ var init_preview = __esm({
|
|
|
19465
19465
|
}
|
|
19466
19466
|
},
|
|
19467
19467
|
kill: (pid, signal) => process.kill(pid, signal),
|
|
19468
|
-
portFree: (port) => new Promise((
|
|
19468
|
+
portFree: (port) => new Promise((resolve54) => {
|
|
19469
19469
|
const s = createServer2();
|
|
19470
|
-
s.once("error", () =>
|
|
19471
|
-
s.listen(port, "127.0.0.1", () => s.close(() =>
|
|
19470
|
+
s.once("error", () => resolve54(false));
|
|
19471
|
+
s.listen(port, "127.0.0.1", () => s.close(() => resolve54(true)));
|
|
19472
19472
|
}),
|
|
19473
19473
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
19474
19474
|
servingIdentity: async (origin) => {
|
|
@@ -20612,7 +20612,7 @@ async function injectRequest(listener, request) {
|
|
|
20612
20612
|
req.headers.host ??= url.host;
|
|
20613
20613
|
if (body && body.length > 0) req.push(body);
|
|
20614
20614
|
req.push(null);
|
|
20615
|
-
return await new Promise((
|
|
20615
|
+
return await new Promise((resolve54, reject) => {
|
|
20616
20616
|
const streamed = () => {
|
|
20617
20617
|
queueMicrotask(() => {
|
|
20618
20618
|
req.emit("close");
|
|
@@ -20628,7 +20628,7 @@ async function injectRequest(listener, request) {
|
|
|
20628
20628
|
else headers2.set(name, value);
|
|
20629
20629
|
}
|
|
20630
20630
|
const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
|
|
20631
|
-
|
|
20631
|
+
resolve54(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
|
|
20632
20632
|
}, streamed);
|
|
20633
20633
|
res.on("inject-error", reject);
|
|
20634
20634
|
try {
|
|
@@ -21334,7 +21334,7 @@ function redactBodyString(body) {
|
|
|
21334
21334
|
} catch {
|
|
21335
21335
|
}
|
|
21336
21336
|
}
|
|
21337
|
-
return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name,
|
|
21337
|
+
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
21338
|
}
|
|
21339
21339
|
function createWixGatewayState() {
|
|
21340
21340
|
return { mode: "record", rules: [], traffic: [], clients: /* @__PURE__ */ new Set(), seq: 0, ruleSeq: 0 };
|
|
@@ -23080,10 +23080,10 @@ function recordDeviceLayout(payload) {
|
|
|
23080
23080
|
}
|
|
23081
23081
|
async function handleDeviceLayoutReport(res, payload) {
|
|
23082
23082
|
const screenId = recordDeviceLayout(payload);
|
|
23083
|
-
const
|
|
23084
|
-
res.statusCode =
|
|
23083
|
+
const ok2 = screenId !== null;
|
|
23084
|
+
res.statusCode = ok2 ? 200 : 400;
|
|
23085
23085
|
res.setHeader("content-type", "application/json");
|
|
23086
|
-
res.end(JSON.stringify(
|
|
23086
|
+
res.end(JSON.stringify(ok2 ? { status: "ok", screenId } : { error: "invalid_layout" }));
|
|
23087
23087
|
return screenId;
|
|
23088
23088
|
}
|
|
23089
23089
|
async function handlePreviewHitTest(res, payload) {
|
|
@@ -23162,12 +23162,12 @@ function finalizeRecording(key2, rec) {
|
|
|
23162
23162
|
if (rec.finalize) return rec.finalize;
|
|
23163
23163
|
rec.finalize = (async () => {
|
|
23164
23164
|
clearTimeout(rec.autoStop);
|
|
23165
|
-
await new Promise((
|
|
23165
|
+
await new Promise((resolve54) => {
|
|
23166
23166
|
let done = false;
|
|
23167
23167
|
const finish2 = () => {
|
|
23168
23168
|
if (!done) {
|
|
23169
23169
|
done = true;
|
|
23170
|
-
|
|
23170
|
+
resolve54();
|
|
23171
23171
|
}
|
|
23172
23172
|
};
|
|
23173
23173
|
rec.child.once("close", finish2);
|
|
@@ -23278,7 +23278,7 @@ var init_preview2 = __esm({
|
|
|
23278
23278
|
DEVICE_LIST_TIMEOUT_MS = 5e3;
|
|
23279
23279
|
defaultRunner2 = {
|
|
23280
23280
|
capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
|
|
23281
|
-
return new Promise((
|
|
23281
|
+
return new Promise((resolve54, reject) => {
|
|
23282
23282
|
const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
23283
23283
|
const out2 = [];
|
|
23284
23284
|
const err = [];
|
|
@@ -23300,7 +23300,7 @@ var init_preview2 = __esm({
|
|
|
23300
23300
|
child.stderr.on("data", (b) => err.push(b));
|
|
23301
23301
|
child.on("error", (e) => settle(reject, e));
|
|
23302
23302
|
child.on("close", (code) => {
|
|
23303
|
-
if (code === 0) settle(
|
|
23303
|
+
if (code === 0) settle(resolve54, Buffer.concat(out2));
|
|
23304
23304
|
else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
23305
23305
|
});
|
|
23306
23306
|
});
|
|
@@ -24632,13 +24632,13 @@ function validate(rule, rawValue) {
|
|
|
24632
24632
|
return { rule: "type", type: rule.type };
|
|
24633
24633
|
}
|
|
24634
24634
|
if (rule.regex) {
|
|
24635
|
-
let
|
|
24635
|
+
let ok2;
|
|
24636
24636
|
try {
|
|
24637
|
-
|
|
24637
|
+
ok2 = new RegExp(`^(?:${rule.regex})$`).test(value);
|
|
24638
24638
|
} catch {
|
|
24639
|
-
|
|
24639
|
+
ok2 = true;
|
|
24640
24640
|
}
|
|
24641
|
-
if (!
|
|
24641
|
+
if (!ok2) return { rule: "regex" };
|
|
24642
24642
|
}
|
|
24643
24643
|
if (typeof rule.minLength === "number" && rule.minLength > 0 && value.length < rule.minLength) {
|
|
24644
24644
|
return { rule: "minLength", limit: rule.minLength };
|
|
@@ -27552,12 +27552,12 @@ function createRicosHostSession(o) {
|
|
|
27552
27552
|
flush() {
|
|
27553
27553
|
if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
|
|
27554
27554
|
const requestId2 = newId();
|
|
27555
|
-
return new Promise((
|
|
27555
|
+
return new Promise((resolve54) => {
|
|
27556
27556
|
const timer = t.setTimeout(() => {
|
|
27557
27557
|
flushes.delete(requestId2);
|
|
27558
|
-
|
|
27558
|
+
resolve54(null);
|
|
27559
27559
|
}, flushMs);
|
|
27560
|
-
flushes.set(requestId2, { resolve:
|
|
27560
|
+
flushes.set(requestId2, { resolve: resolve54, timer });
|
|
27561
27561
|
o.send({ v: 1, type: "requestContent", requestId: requestId2 });
|
|
27562
27562
|
});
|
|
27563
27563
|
},
|
|
@@ -27610,7 +27610,7 @@ async function runRicosImageUpload(o) {
|
|
|
27610
27610
|
};
|
|
27611
27611
|
session.insertMediaPlaceholder(requestId2);
|
|
27612
27612
|
try {
|
|
27613
|
-
const entry = await new Promise((
|
|
27613
|
+
const entry = await new Promise((resolve54) => {
|
|
27614
27614
|
let done = false;
|
|
27615
27615
|
let unsub = () => {
|
|
27616
27616
|
};
|
|
@@ -27619,7 +27619,7 @@ async function runRicosImageUpload(o) {
|
|
|
27619
27619
|
done = true;
|
|
27620
27620
|
t.clearTimeout(timer);
|
|
27621
27621
|
queueMicrotask(() => unsub());
|
|
27622
|
-
|
|
27622
|
+
resolve54(v);
|
|
27623
27623
|
};
|
|
27624
27624
|
const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
|
|
27625
27625
|
unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
|
|
@@ -27638,10 +27638,10 @@ async function runRicosImageUpload(o) {
|
|
|
27638
27638
|
} catch {
|
|
27639
27639
|
return fail2("read");
|
|
27640
27640
|
}
|
|
27641
|
-
const
|
|
27641
|
+
const sep18 = entry.uploadUrl.includes("?") ? "&" : "?";
|
|
27642
27642
|
let res;
|
|
27643
27643
|
try {
|
|
27644
|
-
res = await deps.fetch(`${entry.uploadUrl}${
|
|
27644
|
+
res = await deps.fetch(`${entry.uploadUrl}${sep18}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
|
|
27645
27645
|
} catch {
|
|
27646
27646
|
return fail2("put");
|
|
27647
27647
|
}
|
|
@@ -27656,14 +27656,14 @@ async function runRicosImageUpload(o) {
|
|
|
27656
27656
|
const d = root.file && typeof root.file === "object" ? root.file : root;
|
|
27657
27657
|
const id = typeof d.id === "string" ? d.id : "";
|
|
27658
27658
|
if (!id) return fail2("bad_descriptor");
|
|
27659
|
-
const
|
|
27659
|
+
const ok2 = session.resolveMedia(requestId2, {
|
|
27660
27660
|
id,
|
|
27661
27661
|
url: typeof d.url === "string" ? d.url : "",
|
|
27662
27662
|
...typeof d.width === "number" ? { width: d.width } : {},
|
|
27663
27663
|
...typeof d.height === "number" ? { height: d.height } : {},
|
|
27664
27664
|
mimeType: file.mimeType
|
|
27665
27665
|
});
|
|
27666
|
-
return
|
|
27666
|
+
return ok2 ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
|
|
27667
27667
|
} finally {
|
|
27668
27668
|
deps.dispatch({ actionId: `tier5.${svc}.clearUpload`, args: { requestId: requestId2 } });
|
|
27669
27669
|
}
|
|
@@ -29550,8 +29550,8 @@ function ensureCountUpRuntime() {
|
|
|
29550
29550
|
const neg = fixed.startsWith("-");
|
|
29551
29551
|
const body = neg ? fixed.slice(1) : fixed;
|
|
29552
29552
|
const [int2, frac] = body.split(".");
|
|
29553
|
-
const
|
|
29554
|
-
return (neg ? "-" : "") +
|
|
29553
|
+
const sep18 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
29554
|
+
return (neg ? "-" : "") + sep18 + (frac ? "." + frac : "");
|
|
29555
29555
|
};
|
|
29556
29556
|
const animateEl = (el) => {
|
|
29557
29557
|
const node = el;
|
|
@@ -30372,24 +30372,24 @@ function usesSchematicRoute(props) {
|
|
|
30372
30372
|
const hasRouteFeed = typeof props.routePath === "string" && props.routePath !== "";
|
|
30373
30373
|
return hasFeed && !hasRoute && !hasRouteFeed;
|
|
30374
30374
|
}
|
|
30375
|
-
function longitudeAt(x,
|
|
30376
|
-
return x / (TILE_PX * Math.pow(2,
|
|
30375
|
+
function longitudeAt(x, z3) {
|
|
30376
|
+
return x / (TILE_PX * Math.pow(2, z3)) * 360 - 180;
|
|
30377
30377
|
}
|
|
30378
|
-
function latitudeAt(y,
|
|
30379
|
-
const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2,
|
|
30378
|
+
function latitudeAt(y, z3) {
|
|
30379
|
+
const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z3));
|
|
30380
30380
|
return 180 / Math.PI * Math.atan(Math.sinh(n));
|
|
30381
30381
|
}
|
|
30382
|
-
function regionArgs(centerLat, centerLng,
|
|
30383
|
-
const cx = mercatorX(centerLng,
|
|
30384
|
-
const cy = mercatorY(centerLat,
|
|
30382
|
+
function regionArgs(centerLat, centerLng, z3, w, h) {
|
|
30383
|
+
const cx = mercatorX(centerLng, z3);
|
|
30384
|
+
const cy = mercatorY(centerLat, z3);
|
|
30385
30385
|
return {
|
|
30386
30386
|
latitude: centerLat,
|
|
30387
30387
|
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,
|
|
30388
|
+
zoom: z3,
|
|
30389
|
+
north: latitudeAt(cy - h / 2, z3),
|
|
30390
|
+
south: latitudeAt(cy + h / 2, z3),
|
|
30391
|
+
east: longitudeAt(cx + w / 2, z3),
|
|
30392
|
+
west: longitudeAt(cx - w / 2, z3)
|
|
30393
30393
|
};
|
|
30394
30394
|
}
|
|
30395
30395
|
function decodeCamera(v) {
|
|
@@ -30419,9 +30419,9 @@ function resolveTileSource(source) {
|
|
|
30419
30419
|
const maxZoom = typeof s.maxZoom === "number" && s.maxZoom > 0 ? s.maxZoom : DEFAULT_TILE_MAX_ZOOM;
|
|
30420
30420
|
return { urlTemplate, attribution, maxZoom };
|
|
30421
30421
|
}
|
|
30422
|
-
function tileUrl(source,
|
|
30423
|
-
if (!source) return `https://tile.openstreetmap.org/${
|
|
30424
|
-
return source.urlTemplate.replace("{z}", String(
|
|
30422
|
+
function tileUrl(source, z3, x, y) {
|
|
30423
|
+
if (!source) return `https://tile.openstreetmap.org/${z3}/${x}/${y}.png`;
|
|
30424
|
+
return source.urlTemplate.replace("{z}", String(z3)).replace("{x}", String(x)).replace("{y}", String(y));
|
|
30425
30425
|
}
|
|
30426
30426
|
function parseShapeKind(raw) {
|
|
30427
30427
|
const k = typeof raw === "string" ? raw.toLowerCase() : "";
|
|
@@ -30438,12 +30438,12 @@ function circleRing(centreLat, centreLng, radiusM, segments = CIRCLE_SEGMENTS) {
|
|
|
30438
30438
|
return { latitude: centreLat + dLat * Math.sin(theta), longitude: centreLng + dLng * Math.cos(theta) };
|
|
30439
30439
|
});
|
|
30440
30440
|
}
|
|
30441
|
-
function distanceToPolylinePx(px, py, points,
|
|
30441
|
+
function distanceToPolylinePx(px, py, points, z3, originX, originY) {
|
|
30442
30442
|
if (points.length < 2) return null;
|
|
30443
30443
|
let best = Infinity;
|
|
30444
30444
|
for (let i = 0; i < points.length - 1; i++) {
|
|
30445
|
-
const ax = mercatorX(points[i].longitude,
|
|
30446
|
-
const bx = mercatorX(points[i + 1].longitude,
|
|
30445
|
+
const ax = mercatorX(points[i].longitude, z3) - originX, ay = mercatorY(points[i].latitude, z3) - originY;
|
|
30446
|
+
const bx = mercatorX(points[i + 1].longitude, z3) - originX, by = mercatorY(points[i + 1].latitude, z3) - originY;
|
|
30447
30447
|
const dx = bx - ax, dy = by - ay;
|
|
30448
30448
|
const lenSq = dx * dx + dy * dy;
|
|
30449
30449
|
const t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
|
|
@@ -30453,22 +30453,22 @@ function distanceToPolylinePx(px, py, points, z2, originX, originY) {
|
|
|
30453
30453
|
}
|
|
30454
30454
|
return best;
|
|
30455
30455
|
}
|
|
30456
|
-
function polygonContainsPx(px, py, points,
|
|
30456
|
+
function polygonContainsPx(px, py, points, z3, originX, originY) {
|
|
30457
30457
|
if (points.length < 3) return false;
|
|
30458
30458
|
let inside2 = false;
|
|
30459
30459
|
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,
|
|
30460
|
+
const xi = mercatorX(points[i].longitude, z3) - originX, yi = mercatorY(points[i].latitude, z3) - originY;
|
|
30461
|
+
const xj = mercatorX(points[j].longitude, z3) - originX, yj = mercatorY(points[j].latitude, z3) - originY;
|
|
30462
30462
|
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) inside2 = !inside2;
|
|
30463
30463
|
}
|
|
30464
30464
|
return inside2;
|
|
30465
30465
|
}
|
|
30466
|
-
function markerHit(px, py, markers,
|
|
30466
|
+
function markerHit(px, py, markers, z3, originX, originY) {
|
|
30467
30467
|
let best = null;
|
|
30468
30468
|
let bestDistance = MARKER_HIT_RADIUS;
|
|
30469
30469
|
markers.forEach((m, i) => {
|
|
30470
|
-
const dx = mercatorX(m.longitude,
|
|
30471
|
-
const dy = mercatorY(m.latitude,
|
|
30470
|
+
const dx = mercatorX(m.longitude, z3) - originX - px;
|
|
30471
|
+
const dy = mercatorY(m.latitude, z3) - originY - py;
|
|
30472
30472
|
const d = Math.sqrt(dx * dx + dy * dy);
|
|
30473
30473
|
if (d <= bestDistance) {
|
|
30474
30474
|
bestDistance = d;
|
|
@@ -30477,22 +30477,22 @@ function markerHit(px, py, markers, z2, originX, originY) {
|
|
|
30477
30477
|
});
|
|
30478
30478
|
return best;
|
|
30479
30479
|
}
|
|
30480
|
-
function mercatorX(lng,
|
|
30481
|
-
return (lng + 180) / 360 * TILE_PX * Math.pow(2,
|
|
30480
|
+
function mercatorX(lng, z3) {
|
|
30481
|
+
return (lng + 180) / 360 * TILE_PX * Math.pow(2, z3);
|
|
30482
30482
|
}
|
|
30483
|
-
function mercatorY(lat,
|
|
30483
|
+
function mercatorY(lat, z3) {
|
|
30484
30484
|
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,
|
|
30485
|
+
return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z3);
|
|
30486
30486
|
}
|
|
30487
30487
|
function fitZoom(pts, w, h, fallback) {
|
|
30488
30488
|
if (pts.length < 2 || w <= 0 || h <= 0) return fallback;
|
|
30489
30489
|
const lats = pts.map((p) => p.latitude), lngs = pts.map((p) => p.longitude);
|
|
30490
30490
|
const minLa = Math.min(...lats), maxLa = Math.max(...lats);
|
|
30491
30491
|
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
|
|
30492
|
+
for (let z3 = 19; z3 >= 1; z3--) {
|
|
30493
|
+
const dx = Math.abs(mercatorX(maxLo, z3) - mercatorX(minLo, z3));
|
|
30494
|
+
const dy = Math.abs(mercatorY(maxLa, z3) - mercatorY(minLa, z3));
|
|
30495
|
+
if (dx <= w && dy <= h) return z3;
|
|
30496
30496
|
}
|
|
30497
30497
|
return 1;
|
|
30498
30498
|
}
|
|
@@ -34611,20 +34611,20 @@ var init_renderNode = __esm({
|
|
|
34611
34611
|
const fitted = shouldFit ? fitZoom(all, W - 48, H - 48, declared) : declared;
|
|
34612
34612
|
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
34613
|
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
|
|
34614
|
+
const z3 = userCam?.z ?? fitted;
|
|
34615
34615
|
const cLat = userCam?.lat ?? baseLat;
|
|
34616
34616
|
const cLng = userCam?.lng ?? baseLng;
|
|
34617
34617
|
React7.useEffect(() => {
|
|
34618
|
-
const resolved2 = resolveCamera(commandedCamera, cLat, cLng,
|
|
34618
|
+
const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z3);
|
|
34619
34619
|
if (!resolved2) return;
|
|
34620
34620
|
setUserCam({
|
|
34621
34621
|
lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
|
|
34622
34622
|
lng: resolved2.longitude,
|
|
34623
|
-
z: Math.max(1, Math.min(19, resolved2.zoom ??
|
|
34623
|
+
z: Math.max(1, Math.min(19, resolved2.zoom ?? z3))
|
|
34624
34624
|
});
|
|
34625
34625
|
}, [commandedCamera]);
|
|
34626
|
-
const originX = mercatorX(cLng,
|
|
34627
|
-
const originY = mercatorY(cLat,
|
|
34626
|
+
const originX = mercatorX(cLng, z3) - W / 2;
|
|
34627
|
+
const originY = mercatorY(cLat, z3) - H / 2;
|
|
34628
34628
|
const interactive = pinsOnly ? props.interactive === true : props.interactive !== false;
|
|
34629
34629
|
const resolvedTileSource = resolveTileSource(props.tileSource);
|
|
34630
34630
|
const fireMapEvent = (action, payload) => {
|
|
@@ -34642,7 +34642,7 @@ var init_renderNode = __esm({
|
|
|
34642
34642
|
const { kx, ky } = layoutScale(el);
|
|
34643
34643
|
const px = (e.clientX - r.left) * kx - el.clientLeft;
|
|
34644
34644
|
const py = (e.clientY - r.top) * ky - el.clientTop;
|
|
34645
|
-
const hit = markerHit(px, py, markers,
|
|
34645
|
+
const hit = markerHit(px, py, markers, z3, originX, originY);
|
|
34646
34646
|
if (hit !== null) {
|
|
34647
34647
|
const m = markers[hit];
|
|
34648
34648
|
const payload = { index: hit, latitude: m.latitude, longitude: m.longitude };
|
|
@@ -34653,10 +34653,10 @@ var init_renderNode = __esm({
|
|
|
34653
34653
|
const shapeIndex = shapes.findIndex((sh) => {
|
|
34654
34654
|
if (sh.kind === "unknown" || sh.points.length < 2) return false;
|
|
34655
34655
|
if (sh.kind === "line") {
|
|
34656
|
-
const d2 = distanceToPolylinePx(px, py, sh.points,
|
|
34656
|
+
const d2 = distanceToPolylinePx(px, py, sh.points, z3, originX, originY);
|
|
34657
34657
|
return d2 !== null && d2 <= SHAPE_HIT_RADIUS;
|
|
34658
34658
|
}
|
|
34659
|
-
return polygonContainsPx(px, py, sh.points,
|
|
34659
|
+
return polygonContainsPx(px, py, sh.points, z3, originX, originY);
|
|
34660
34660
|
});
|
|
34661
34661
|
if (shapeIndex >= 0 && props.onShapeTap) {
|
|
34662
34662
|
const sh = shapes[shapeIndex];
|
|
@@ -34665,15 +34665,15 @@ var init_renderNode = __esm({
|
|
|
34665
34665
|
fireMapEvent(props.onShapeTap, payload);
|
|
34666
34666
|
} else {
|
|
34667
34667
|
fireMapEvent(props.onMapTap, {
|
|
34668
|
-
latitude: latitudeAt(originY + py,
|
|
34669
|
-
longitude: longitudeAt(originX + px,
|
|
34668
|
+
latitude: latitudeAt(originY + py, z3),
|
|
34669
|
+
longitude: longitudeAt(originX + px, z3)
|
|
34670
34670
|
});
|
|
34671
34671
|
}
|
|
34672
34672
|
}
|
|
34673
34673
|
};
|
|
34674
34674
|
const onPointerDown = (e) => {
|
|
34675
34675
|
if (!interactive) return;
|
|
34676
|
-
dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z:
|
|
34676
|
+
dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z3, ...layoutScale(e.currentTarget) };
|
|
34677
34677
|
dragMovedRef.current = false;
|
|
34678
34678
|
};
|
|
34679
34679
|
const onPointerMove = (e) => {
|
|
@@ -34697,8 +34697,8 @@ var init_renderNode = __esm({
|
|
|
34697
34697
|
const onWheel = (e) => {
|
|
34698
34698
|
if (!interactive) return;
|
|
34699
34699
|
e.preventDefault();
|
|
34700
|
-
const next = Math.max(1, Math.min(19,
|
|
34701
|
-
if (next !==
|
|
34700
|
+
const next = Math.max(1, Math.min(19, z3 + (e.deltaY < 0 ? 1 : -1)));
|
|
34701
|
+
if (next !== z3) setUserCam({ lat: cLat, lng: cLng, z: next });
|
|
34702
34702
|
};
|
|
34703
34703
|
React7.useEffect(() => {
|
|
34704
34704
|
const action = props.onRegionChange;
|
|
@@ -34709,22 +34709,22 @@ var init_renderNode = __esm({
|
|
|
34709
34709
|
regionReportedRef.current = true;
|
|
34710
34710
|
return;
|
|
34711
34711
|
}
|
|
34712
|
-
fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng,
|
|
34712
|
+
fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z3, W, H) } });
|
|
34713
34713
|
}, 250);
|
|
34714
34714
|
return () => clearTimeout(t);
|
|
34715
|
-
}, [cLat, cLng,
|
|
34716
|
-
const sx = (p) => mercatorX(p.longitude,
|
|
34717
|
-
const sy = (p) => mercatorY(p.latitude,
|
|
34715
|
+
}, [cLat, cLng, z3, W, H, props.onRegionChange]);
|
|
34716
|
+
const sx = (p) => mercatorX(p.longitude, z3) - originX;
|
|
34717
|
+
const sy = (p) => mercatorY(p.latitude, z3) - originY;
|
|
34718
34718
|
const accent = C("accentPrimary", "#116DFF");
|
|
34719
|
-
const n = Math.pow(2,
|
|
34719
|
+
const n = Math.pow(2, z3);
|
|
34720
34720
|
const tiles = [];
|
|
34721
34721
|
for (let tx = Math.floor(originX / TILE_PX); tx <= Math.floor((originX + W) / TILE_PX); tx++) {
|
|
34722
34722
|
for (let ty = Math.floor(originY / TILE_PX); ty <= Math.floor((originY + H) / TILE_PX); ty++) {
|
|
34723
34723
|
if (ty < 0 || ty >= n) continue;
|
|
34724
34724
|
const wrapX = (tx % n + n) % n;
|
|
34725
34725
|
tiles.push({
|
|
34726
|
-
key: `${
|
|
34727
|
-
src: tileUrl(resolvedTileSource,
|
|
34726
|
+
key: `${z3}/${wrapX}/${ty}`,
|
|
34727
|
+
src: tileUrl(resolvedTileSource, z3, wrapX, ty),
|
|
34728
34728
|
left: tx * TILE_PX - originX,
|
|
34729
34729
|
top: ty * TILE_PX - originY
|
|
34730
34730
|
});
|
|
@@ -34736,7 +34736,7 @@ var init_renderNode = __esm({
|
|
|
34736
34736
|
ref: attachBox,
|
|
34737
34737
|
"data-map-mode": "tile",
|
|
34738
34738
|
"data-route-points": route.length,
|
|
34739
|
-
"data-map-zoom":
|
|
34739
|
+
"data-map-zoom": z3,
|
|
34740
34740
|
onClick: onSurfaceClick,
|
|
34741
34741
|
onPointerDown,
|
|
34742
34742
|
onPointerMove,
|
|
@@ -35902,7 +35902,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
35902
35902
|
const browser = globalThis;
|
|
35903
35903
|
browser.document.documentElement.style.colorScheme = selected;
|
|
35904
35904
|
await browser.document.fonts?.ready;
|
|
35905
|
-
await new Promise((
|
|
35905
|
+
await new Promise((resolve54) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve54())));
|
|
35906
35906
|
}, scheme);
|
|
35907
35907
|
}
|
|
35908
35908
|
async function renderPngBatch(items) {
|
|
@@ -39543,7 +39543,7 @@ async function handleWebWix(req, res, state) {
|
|
|
39543
39543
|
}
|
|
39544
39544
|
if (match) {
|
|
39545
39545
|
const mocked = match.rule.response;
|
|
39546
|
-
if (mocked.delayMs) await new Promise((
|
|
39546
|
+
if (mocked.delayMs) await new Promise((resolve54) => setTimeout(resolve54, mocked.delayMs));
|
|
39547
39547
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
39548
39548
|
record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
|
|
39549
39549
|
return reply(200, { status: mocked.status, body: responseBody ?? "" });
|
|
@@ -40537,8 +40537,8 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
40537
40537
|
}
|
|
40538
40538
|
async function serveStatic(req, res, root, prefix) {
|
|
40539
40539
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
40540
|
-
const
|
|
40541
|
-
const safe = normalize3(
|
|
40540
|
+
const relative15 = requested.replace(prefix, "").replace(/^\//, "");
|
|
40541
|
+
const safe = normalize3(relative15).replace(/^(\.\.[\/\\])+/, "");
|
|
40542
40542
|
const fullPath = resolve33(root, safe);
|
|
40543
40543
|
if (!fullPath.startsWith(root)) {
|
|
40544
40544
|
return send(res, 403, "forbidden");
|
|
@@ -41269,8 +41269,8 @@ function sha256hex(b) {
|
|
|
41269
41269
|
function stableStringify(value) {
|
|
41270
41270
|
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
41271
41271
|
if (Array.isArray(value)) return "[" + value.map(stableStringify).join(",") + "]";
|
|
41272
|
-
const
|
|
41273
|
-
return "{" + Object.keys(
|
|
41272
|
+
const object3 = value;
|
|
41273
|
+
return "{" + Object.keys(object3).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object3[key2])).join(",") + "}";
|
|
41274
41274
|
}
|
|
41275
41275
|
function manifestContent(m) {
|
|
41276
41276
|
const {
|
|
@@ -41642,12 +41642,12 @@ var init_query = __esm({
|
|
|
41642
41642
|
});
|
|
41643
41643
|
|
|
41644
41644
|
// ../../core/dev-server/src/crawl-input.ts
|
|
41645
|
-
function resolved(v,
|
|
41646
|
-
if (typeof v === "string") return v.startsWith("$service:") ?
|
|
41645
|
+
function resolved(v, resolve54) {
|
|
41646
|
+
if (typeof v === "string") return v.startsWith("$service:") ? resolve54(v) : v;
|
|
41647
41647
|
if (Array.isArray(v)) {
|
|
41648
41648
|
const out2 = v.flatMap((el) => {
|
|
41649
41649
|
if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
|
|
41650
|
-
const r =
|
|
41650
|
+
const r = resolve54(el);
|
|
41651
41651
|
return Array.isArray(r) ? r : [r];
|
|
41652
41652
|
});
|
|
41653
41653
|
return out2;
|
|
@@ -41661,9 +41661,9 @@ function hasRowBinding(props) {
|
|
|
41661
41661
|
return itemToken(v) || Array.isArray(v) && v.some(itemToken);
|
|
41662
41662
|
});
|
|
41663
41663
|
}
|
|
41664
|
-
function declaredOptionIds(props,
|
|
41664
|
+
function declaredOptionIds(props, resolve54) {
|
|
41665
41665
|
const literal = props.options ?? props.tabs ?? props.chips;
|
|
41666
|
-
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath,
|
|
41666
|
+
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve54) : void 0;
|
|
41667
41667
|
const raw = Array.isArray(bound) ? bound : literal;
|
|
41668
41668
|
if (!Array.isArray(raw)) return [];
|
|
41669
41669
|
const out2 = [];
|
|
@@ -41706,24 +41706,24 @@ function seedTokens(state, limit = 48) {
|
|
|
41706
41706
|
walk2(state, 0);
|
|
41707
41707
|
return out2;
|
|
41708
41708
|
}
|
|
41709
|
-
function synthesizeInput(control,
|
|
41709
|
+
function synthesizeInput(control, resolve54, tokens) {
|
|
41710
41710
|
const id = `${control.type}.${control.callback}`;
|
|
41711
41711
|
const row = SYNTHESIZED_CONTROLS[id];
|
|
41712
41712
|
if (!row) return null;
|
|
41713
41713
|
const props = control.props;
|
|
41714
41714
|
if (hasRowBinding(props)) return null;
|
|
41715
41715
|
if (row.from === "declared-options") {
|
|
41716
|
-
const ids = declaredOptionIds(props,
|
|
41716
|
+
const ids = declaredOptionIds(props, resolve54);
|
|
41717
41717
|
if (!ids.length) return null;
|
|
41718
41718
|
if (row.encoding === "string-array") {
|
|
41719
|
-
const currentRaw2 = resolved(props.selectedIds,
|
|
41719
|
+
const currentRaw2 = resolved(props.selectedIds, resolve54);
|
|
41720
41720
|
const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
|
|
41721
41721
|
const pick4 = ids.find((o) => !current3.includes(o));
|
|
41722
41722
|
if (pick4 === void 0) return null;
|
|
41723
41723
|
const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
|
|
41724
41724
|
return { key: row.key, value, from: row.from, current: current3, control: id };
|
|
41725
41725
|
}
|
|
41726
|
-
const currentRaw = resolved(props.selectedId,
|
|
41726
|
+
const currentRaw = resolved(props.selectedId, resolve54);
|
|
41727
41727
|
const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
|
|
41728
41728
|
const pick3 = ids.find((o) => o !== current2);
|
|
41729
41729
|
if (pick3 === void 0) return null;
|
|
@@ -41731,7 +41731,7 @@ function synthesizeInput(control, resolve53, tokens) {
|
|
|
41731
41731
|
}
|
|
41732
41732
|
if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
|
|
41733
41733
|
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 :
|
|
41734
|
+
const bound = binding2 === void 0 ? void 0 : resolve54(binding2);
|
|
41735
41735
|
const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
|
|
41736
41736
|
const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
|
|
41737
41737
|
const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
|
|
@@ -43216,8 +43216,8 @@ async function crawlScreenInner(opts) {
|
|
|
43216
43216
|
if (linkable.has(target)) return true;
|
|
43217
43217
|
for (const base of linkable) {
|
|
43218
43218
|
if (target.length > base.length + 1 && target.startsWith(base)) {
|
|
43219
|
-
const
|
|
43220
|
-
if (
|
|
43219
|
+
const sep18 = target[base.length];
|
|
43220
|
+
if (sep18 === "_" || sep18 === "/") return true;
|
|
43221
43221
|
}
|
|
43222
43222
|
}
|
|
43223
43223
|
return false;
|
|
@@ -46244,7 +46244,7 @@ var init_studio_timeline = __esm({
|
|
|
46244
46244
|
isStr = (x) => typeof x === "string";
|
|
46245
46245
|
isObj2 = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
|
|
46246
46246
|
strs = (x) => Array.isArray(x) && x.every(isStr);
|
|
46247
|
-
nullOr = (x,
|
|
46247
|
+
nullOr = (x, ok2) => x === null || isObj2(x) && ok2(x);
|
|
46248
46248
|
accentOf = (palette2) => {
|
|
46249
46249
|
for (const p of palette2 ?? []) {
|
|
46250
46250
|
const [name, hex2] = Array.isArray(p) ? p : [p.name, p.hex];
|
|
@@ -47194,16 +47194,16 @@ function pushSetupBodyBytes(body) {
|
|
|
47194
47194
|
return Buffer.byteLength(JSON.stringify(body), "utf8");
|
|
47195
47195
|
}
|
|
47196
47196
|
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
|
|
47197
|
+
const refuse6 = (error) => ({ ok: false, status: 0, body: null, error });
|
|
47198
|
+
if (!options.target.controlToken) return refuse6("control_token_required");
|
|
47199
|
+
if (!options.wixToken) return refuse6("wix_account_token_required");
|
|
47200
|
+
if (credentialHostRefusal(options.target.control)) return refuse6("insecure_target");
|
|
47201
|
+
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse6("invalid_preview_tag");
|
|
47202
47202
|
const setup = options.operation === "setup";
|
|
47203
|
-
if (setup && !options.body) return
|
|
47204
|
-
if (!setup && (!options.query?.app || !options.query?.site)) return
|
|
47203
|
+
if (setup && !options.body) return refuse6("push_setup_body_required");
|
|
47204
|
+
if (!setup && (!options.query?.app || !options.query?.site)) return refuse6("push_setup_query_required");
|
|
47205
47205
|
if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
|
|
47206
|
-
return
|
|
47206
|
+
return refuse6("push_setup_body_too_large");
|
|
47207
47207
|
}
|
|
47208
47208
|
const base = options.target.control.replace(/\/+$/, "");
|
|
47209
47209
|
let path2 = "/v1/admin/push/setup";
|
|
@@ -51021,8 +51021,8 @@ function baseOf(target, linkable, known) {
|
|
|
51021
51021
|
let best = null;
|
|
51022
51022
|
for (const base of linkable ?? []) {
|
|
51023
51023
|
if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
|
|
51024
|
-
const
|
|
51025
|
-
if ((
|
|
51024
|
+
const sep18 = target[base.length];
|
|
51025
|
+
if ((sep18 === "_" || sep18 === "/") && (!best || base.length > best.length)) best = base;
|
|
51026
51026
|
}
|
|
51027
51027
|
return best;
|
|
51028
51028
|
}
|
|
@@ -52263,7 +52263,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
52263
52263
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
52264
52264
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
52265
52265
|
const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
|
|
52266
|
-
return await new Promise((
|
|
52266
|
+
return await new Promise((resolve54, reject) => {
|
|
52267
52267
|
let settled = false;
|
|
52268
52268
|
const finish2 = (fn) => {
|
|
52269
52269
|
if (settled) return;
|
|
@@ -52300,7 +52300,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
52300
52300
|
}
|
|
52301
52301
|
const responseHeaders = new Headers();
|
|
52302
52302
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
52303
|
-
|
|
52303
|
+
resolve54(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
52304
52304
|
}));
|
|
52305
52305
|
});
|
|
52306
52306
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -52600,7 +52600,7 @@ function createLocalTestSandbox() {
|
|
|
52600
52600
|
}
|
|
52601
52601
|
})();
|
|
52602
52602
|
`;
|
|
52603
|
-
return await new Promise((
|
|
52603
|
+
return await new Promise((resolve54, reject) => {
|
|
52604
52604
|
const { port1, port2 } = new MessageChannel();
|
|
52605
52605
|
const serializableContext = {
|
|
52606
52606
|
auth: context.auth,
|
|
@@ -52676,7 +52676,7 @@ function createLocalTestSandbox() {
|
|
|
52676
52676
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
52677
52677
|
return;
|
|
52678
52678
|
}
|
|
52679
|
-
if (message.ok) finish2(() =>
|
|
52679
|
+
if (message.ok) finish2(() => resolve54({ value: message.value, durationMs: Date.now() - started }));
|
|
52680
52680
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
52681
52681
|
});
|
|
52682
52682
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -53853,9 +53853,187 @@ var init_cli_bridge = __esm({
|
|
|
53853
53853
|
}
|
|
53854
53854
|
});
|
|
53855
53855
|
|
|
53856
|
-
// src/mcp/tools.ts
|
|
53856
|
+
// src/mcp/file-tools.ts
|
|
53857
|
+
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";
|
|
53858
|
+
import { dirname as dirname30, isAbsolute as isAbsolute5, join as join53, relative as relative11, resolve as resolve45, sep as sep14 } from "node:path";
|
|
53857
53859
|
import * as z from "zod";
|
|
53858
|
-
|
|
53860
|
+
function within(root, p) {
|
|
53861
|
+
return p === root || p.startsWith(root.endsWith(sep14) ? root : root + sep14);
|
|
53862
|
+
}
|
|
53863
|
+
function realish(p) {
|
|
53864
|
+
let cur = p;
|
|
53865
|
+
const tail = [];
|
|
53866
|
+
while (!existsSync54(cur)) {
|
|
53867
|
+
const up = dirname30(cur);
|
|
53868
|
+
if (up === cur) break;
|
|
53869
|
+
tail.unshift(cur.slice(up.length + (up.endsWith(sep14) ? 0 : 1)));
|
|
53870
|
+
cur = up;
|
|
53871
|
+
}
|
|
53872
|
+
return join53(realpathSync7(cur), ...tail);
|
|
53873
|
+
}
|
|
53874
|
+
async function confinedAppDir(args, deps) {
|
|
53875
|
+
const root = resolve45(await deps.defaultDir());
|
|
53876
|
+
const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
|
|
53877
|
+
if (!existsSync54(root)) return refuse4("no_workspace", `the workspace folder ${root} does not exist`);
|
|
53878
|
+
if (!within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
|
|
53879
|
+
return dir;
|
|
53880
|
+
}
|
|
53881
|
+
function confinedPath(appDir3, rel) {
|
|
53882
|
+
if (typeof rel !== "string" || !rel.trim()) return { error: "a path is required" };
|
|
53883
|
+
if (rel.includes("\0")) return { error: "a path may not contain NUL" };
|
|
53884
|
+
if (isAbsolute5(rel)) return { error: `"${rel}" is absolute \u2014 give a path inside the app folder` };
|
|
53885
|
+
const abs = resolve45(appDir3, rel);
|
|
53886
|
+
const real = realish(abs);
|
|
53887
|
+
const base = existsSync54(appDir3) ? realpathSync7(appDir3) : realish(appDir3);
|
|
53888
|
+
if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
|
|
53889
|
+
const first = relative11(base, real).split(sep14)[0];
|
|
53890
|
+
if (RESERVED.has(first)) return { error: `"${rel}" is inside ${first}/, which this tool does not touch` };
|
|
53891
|
+
return abs;
|
|
53892
|
+
}
|
|
53893
|
+
function listFiles(appDir3) {
|
|
53894
|
+
const files = [];
|
|
53895
|
+
const walk2 = (d) => {
|
|
53896
|
+
for (const e of readdirSync27(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
53897
|
+
if (RESERVED.has(e.name)) continue;
|
|
53898
|
+
if (e.isSymbolicLink()) continue;
|
|
53899
|
+
const p = join53(d, e.name);
|
|
53900
|
+
if (e.isDirectory()) {
|
|
53901
|
+
if (!walk2(p)) return false;
|
|
53902
|
+
} else if (e.isFile()) {
|
|
53903
|
+
if (files.length >= MAX_LISTED) return false;
|
|
53904
|
+
files.push({ path: relative11(appDir3, p).split(sep14).join("/"), bytes: statSync13(p).size });
|
|
53905
|
+
}
|
|
53906
|
+
}
|
|
53907
|
+
return true;
|
|
53908
|
+
};
|
|
53909
|
+
const complete = walk2(appDir3);
|
|
53910
|
+
return { files, truncated: !complete };
|
|
53911
|
+
}
|
|
53912
|
+
function fileTools() {
|
|
53913
|
+
return [
|
|
53914
|
+
{
|
|
53915
|
+
name: "himi_list_apps",
|
|
53916
|
+
title: "List apps in the workspace",
|
|
53917
|
+
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.",
|
|
53918
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53919
|
+
inputSchema: z.object({}),
|
|
53920
|
+
handler: async (_a, d) => {
|
|
53921
|
+
const root = resolve45(await d.defaultDir());
|
|
53922
|
+
if (!existsSync54(root)) return ok({ ok: true, workspace: root, apps: [] });
|
|
53923
|
+
const apps = [];
|
|
53924
|
+
if (existsSync54(join53(root, CONTENT_MARKER))) apps.push(".");
|
|
53925
|
+
for (const e of readdirSync27(root, { withFileTypes: true })) {
|
|
53926
|
+
if (e.isDirectory() && !e.name.startsWith(".") && existsSync54(join53(root, e.name, CONTENT_MARKER))) apps.push(e.name);
|
|
53927
|
+
}
|
|
53928
|
+
return ok({ ok: true, workspace: root, apps: apps.sort() });
|
|
53929
|
+
}
|
|
53930
|
+
},
|
|
53931
|
+
{
|
|
53932
|
+
name: "himi_list_files",
|
|
53933
|
+
title: "List app files",
|
|
53934
|
+
description: `Every file in an app folder with its size (skips ${[...RESERVED].join(", ")}; at most ${MAX_LISTED}).`,
|
|
53935
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53936
|
+
inputSchema: z.object({ dir: DIR }),
|
|
53937
|
+
handler: async (a, d) => {
|
|
53938
|
+
const app = await confinedAppDir(a, d);
|
|
53939
|
+
if (typeof app !== "string") return app;
|
|
53940
|
+
if (!existsSync54(app) || !statSync13(app).isDirectory()) return refuse4("no_app", `no folder at ${app}`);
|
|
53941
|
+
return ok({ ok: true, dir: app, ...listFiles(app) });
|
|
53942
|
+
}
|
|
53943
|
+
},
|
|
53944
|
+
{
|
|
53945
|
+
name: "himi_read_file",
|
|
53946
|
+
title: "Read an app file",
|
|
53947
|
+
description: `One file of an app folder, as UTF-8 text (at most ${MAX_FILE_BYTES / 1024} KiB).`,
|
|
53948
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53949
|
+
inputSchema: z.object({ dir: DIR, path: z.string().min(1).describe('Path inside the app folder, e.g. "screens/home.ts".') }),
|
|
53950
|
+
handler: async (a, d) => {
|
|
53951
|
+
const app = await confinedAppDir(a, d);
|
|
53952
|
+
if (typeof app !== "string") return app;
|
|
53953
|
+
const p = confinedPath(app, a.path);
|
|
53954
|
+
if (typeof p !== "string") return refuse4("bad_path", p.error);
|
|
53955
|
+
if (!existsSync54(p) || !lstatSync12(p).isFile()) return refuse4("not_found", `no file "${String(a.path)}"`);
|
|
53956
|
+
const size = statSync13(p).size;
|
|
53957
|
+
if (size > MAX_FILE_BYTES) return refuse4("too_large", `"${String(a.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
|
|
53958
|
+
return ok({ ok: true, path: a.path, bytes: size, content: readFileSync59(p, "utf8") });
|
|
53959
|
+
}
|
|
53960
|
+
},
|
|
53961
|
+
{
|
|
53962
|
+
name: "himi_write_files",
|
|
53963
|
+
title: "Write app files",
|
|
53964
|
+
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.`,
|
|
53965
|
+
annotations: WRITE_ANN,
|
|
53966
|
+
inputSchema: z.object({
|
|
53967
|
+
dir: DIR,
|
|
53968
|
+
files: z.array(z.object({ path: z.string().min(1), content: z.string() })).min(1).max(MAX_FILES_PER_WRITE)
|
|
53969
|
+
}),
|
|
53970
|
+
handler: async (a, d) => {
|
|
53971
|
+
const app = await confinedAppDir(a, d);
|
|
53972
|
+
if (typeof app !== "string") return app;
|
|
53973
|
+
const files = Array.isArray(a.files) ? a.files : [];
|
|
53974
|
+
if (!files.length || files.length > MAX_FILES_PER_WRITE) return refuse4("bad_request", `between 1 and ${MAX_FILES_PER_WRITE} files per call`);
|
|
53975
|
+
const planned = [];
|
|
53976
|
+
const refused2 = [];
|
|
53977
|
+
for (const f of files) {
|
|
53978
|
+
const p = confinedPath(app, f.path);
|
|
53979
|
+
if (typeof p !== "string") refused2.push({ path: f.path, error: p.error });
|
|
53980
|
+
else if (typeof f.content !== "string") refused2.push({ path: f.path, error: "content must be text" });
|
|
53981
|
+
else if (Buffer.byteLength(f.content) > MAX_FILE_BYTES) refused2.push({ path: f.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
|
|
53982
|
+
else if (existsSync54(p) && !lstatSync12(p).isFile()) refused2.push({ path: f.path, error: "not a regular file" });
|
|
53983
|
+
else planned.push({ abs: p, rel: String(f.path), content: f.content });
|
|
53984
|
+
}
|
|
53985
|
+
if (refused2.length) return { ...ok({ ok: false, error: "refused", written: [], refused: refused2 }), isError: true };
|
|
53986
|
+
for (const f of planned) {
|
|
53987
|
+
mkdirSync26(dirname30(f.abs), { recursive: true });
|
|
53988
|
+
writeFileSync21(f.abs, f.content);
|
|
53989
|
+
}
|
|
53990
|
+
return ok({ ok: true, dir: app, written: planned.map((f) => f.rel) });
|
|
53991
|
+
}
|
|
53992
|
+
},
|
|
53993
|
+
{
|
|
53994
|
+
name: "himi_delete_files",
|
|
53995
|
+
title: "Delete app files",
|
|
53996
|
+
description: "Delete files (not folders) from an app folder. Nothing is deleted if any path is refused.",
|
|
53997
|
+
annotations: { ...WRITE_ANN, idempotentHint: false },
|
|
53998
|
+
inputSchema: z.object({ dir: DIR, paths: z.array(z.string().min(1)).min(1).max(MAX_FILES_PER_WRITE) }),
|
|
53999
|
+
handler: async (a, d) => {
|
|
54000
|
+
const app = await confinedAppDir(a, d);
|
|
54001
|
+
if (typeof app !== "string") return app;
|
|
54002
|
+
const paths = Array.isArray(a.paths) ? a.paths : [];
|
|
54003
|
+
const planned = [];
|
|
54004
|
+
const refused2 = [];
|
|
54005
|
+
for (const rel of paths) {
|
|
54006
|
+
const p = confinedPath(app, rel);
|
|
54007
|
+
if (typeof p !== "string") refused2.push({ path: rel, error: p.error });
|
|
54008
|
+
else if (!existsSync54(p)) refused2.push({ path: rel, error: "no such file" });
|
|
54009
|
+
else if (!lstatSync12(p).isFile()) refused2.push({ path: rel, error: "not a regular file" });
|
|
54010
|
+
else planned.push(p);
|
|
54011
|
+
}
|
|
54012
|
+
if (refused2.length) return { ...ok({ ok: false, error: "refused", deleted: [], refused: refused2 }), isError: true };
|
|
54013
|
+
for (const p of planned) rmSync12(p);
|
|
54014
|
+
return ok({ ok: true, dir: app, deleted: paths });
|
|
54015
|
+
}
|
|
54016
|
+
}
|
|
54017
|
+
];
|
|
54018
|
+
}
|
|
54019
|
+
var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED, RESERVED, CONTENT_MARKER, ok, refuse4, DIR, WRITE_ANN;
|
|
54020
|
+
var init_file_tools = __esm({
|
|
54021
|
+
"src/mcp/file-tools.ts"() {
|
|
54022
|
+
MAX_FILE_BYTES = 1024 * 1024;
|
|
54023
|
+
MAX_FILES_PER_WRITE = 100;
|
|
54024
|
+
MAX_LISTED = 2e3;
|
|
54025
|
+
RESERVED = /* @__PURE__ */ new Set([".git", "node_modules", "dist"]);
|
|
54026
|
+
CONTENT_MARKER = "himalaya.content.json";
|
|
54027
|
+
ok = (o) => ({ content: [{ type: "text", text: JSON.stringify(o, null, 2) }] });
|
|
54028
|
+
refuse4 = (error, message) => ({ content: [{ type: "text", text: JSON.stringify({ ok: false, error, message }, null, 2) }], isError: true });
|
|
54029
|
+
DIR = z.string().optional().describe("The app folder, relative to the workspace folder. Default: the workspace folder itself.");
|
|
54030
|
+
WRITE_ANN = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
|
|
54031
|
+
}
|
|
54032
|
+
});
|
|
54033
|
+
|
|
54034
|
+
// src/mcp/tools.ts
|
|
54035
|
+
import * as z2 from "zod";
|
|
54036
|
+
import { resolve as resolve46 } from "node:path";
|
|
53859
54037
|
function fromCli(r, extra = []) {
|
|
53860
54038
|
const body = r.json !== void 0 ? JSON.stringify(r.json, null, 2) : r.text.trim();
|
|
53861
54039
|
const content = [];
|
|
@@ -53867,7 +54045,7 @@ ${r.stderr.trim()}`) });
|
|
|
53867
54045
|
}
|
|
53868
54046
|
async function appDir2(args, deps) {
|
|
53869
54047
|
const base = await deps.defaultDir();
|
|
53870
|
-
return typeof args.dir === "string" && args.dir ?
|
|
54048
|
+
return typeof args.dir === "string" && args.dir ? resolve46(base, args.dir) : base;
|
|
53871
54049
|
}
|
|
53872
54050
|
function loginResult(s) {
|
|
53873
54051
|
switch (s.state) {
|
|
@@ -53906,8 +54084,8 @@ function guarded(h) {
|
|
|
53906
54084
|
return h(args, deps);
|
|
53907
54085
|
};
|
|
53908
54086
|
}
|
|
53909
|
-
function himiTools() {
|
|
53910
|
-
return rawTools().map((t) => ({ ...t, handler: guarded(t.handler) }));
|
|
54087
|
+
function himiTools(opts = {}) {
|
|
54088
|
+
return [...rawTools(), ...opts.withFiles ? fileTools() : []].map((t) => ({ ...t, handler: guarded(t.handler) }));
|
|
53911
54089
|
}
|
|
53912
54090
|
function rawTools() {
|
|
53913
54091
|
return [
|
|
@@ -53916,7 +54094,7 @@ function rawTools() {
|
|
|
53916
54094
|
title: "Read a himi authoring guide",
|
|
53917
54095
|
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
54096
|
annotations: LEARN,
|
|
53919
|
-
inputSchema:
|
|
54097
|
+
inputSchema: z2.object({ topic: z2.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
|
|
53920
54098
|
handler: async (a, d) => fromCli(await d.runCli(["docs", ...typeof a.topic === "string" && a.topic ? [a.topic] : [], "--json"]))
|
|
53921
54099
|
},
|
|
53922
54100
|
{
|
|
@@ -53924,7 +54102,7 @@ function rawTools() {
|
|
|
53924
54102
|
title: "SDUI component vocabulary",
|
|
53925
54103
|
description: "The SDUI component vocabulary and props a descriptor may use; a name returns that one component. Offline.",
|
|
53926
54104
|
annotations: LEARN,
|
|
53927
|
-
inputSchema:
|
|
54105
|
+
inputSchema: z2.object({ name: z2.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
|
|
53928
54106
|
handler: async (a, d) => fromCli(await d.runCli(["components", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
|
|
53929
54107
|
},
|
|
53930
54108
|
{
|
|
@@ -53932,7 +54110,7 @@ function rawTools() {
|
|
|
53932
54110
|
title: "Importable @himalaya SDKs",
|
|
53933
54111
|
description: "The @himalaya/* SDKs a Tier-5 worker may import; a name returns that SDK's typed API. Offline.",
|
|
53934
54112
|
annotations: LEARN,
|
|
53935
|
-
inputSchema:
|
|
54113
|
+
inputSchema: z2.object({ name: z2.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
|
|
53936
54114
|
handler: async (a, d) => fromCli(await d.runCli(["sdk", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
|
|
53937
54115
|
},
|
|
53938
54116
|
{
|
|
@@ -53940,7 +54118,7 @@ function rawTools() {
|
|
|
53940
54118
|
title: "Icon name vocabulary",
|
|
53941
54119
|
description: "The valid Icon.name values. An unknown name renders a fallback glyph and `himi_validate` warns. Offline.",
|
|
53942
54120
|
annotations: LEARN,
|
|
53943
|
-
inputSchema:
|
|
54121
|
+
inputSchema: z2.object({}),
|
|
53944
54122
|
handler: async (_a, d) => fromCli(await d.runCli(["icons", "--json"]))
|
|
53945
54123
|
},
|
|
53946
54124
|
{
|
|
@@ -53948,14 +54126,14 @@ function rawTools() {
|
|
|
53948
54126
|
title: "Create a new himi app",
|
|
53949
54127
|
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
54128
|
annotations: LOCAL_WRITE,
|
|
53951
|
-
inputSchema:
|
|
53952
|
-
name:
|
|
53953
|
-
parentDir:
|
|
53954
|
-
template:
|
|
54129
|
+
inputSchema: z2.object({
|
|
54130
|
+
name: z2.string().min(1).describe("The app name \u2014 also its folder name."),
|
|
54131
|
+
parentDir: z2.string().optional().describe("Where to create the folder. Default: the workspace root."),
|
|
54132
|
+
template: z2.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
|
|
53955
54133
|
}),
|
|
53956
54134
|
handler: async (a, d) => {
|
|
53957
54135
|
const base = await d.defaultDir();
|
|
53958
|
-
const parent = typeof a.parentDir === "string" && a.parentDir ?
|
|
54136
|
+
const parent = typeof a.parentDir === "string" && a.parentDir ? resolve46(base, a.parentDir) : base;
|
|
53959
54137
|
return fromCli(await d.runCli(["init", String(a.name), "--dir", parent, ...opt("--template", a.template)]));
|
|
53960
54138
|
}
|
|
53961
54139
|
},
|
|
@@ -53964,7 +54142,7 @@ function rawTools() {
|
|
|
53964
54142
|
title: "Build the app's worker bundles",
|
|
53965
54143
|
description: "Compile every tier5-src/<name>/index.ts to dist/bundles/<name>.bundle.js with esbuild. Writes dist/ only.",
|
|
53966
54144
|
annotations: LOCAL_WRITE,
|
|
53967
|
-
inputSchema:
|
|
54145
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
53968
54146
|
handler: async (a, d) => fromCli(await d.runCli(["build", "--content", await appDir2(a, d)]))
|
|
53969
54147
|
},
|
|
53970
54148
|
{
|
|
@@ -53972,7 +54150,7 @@ function rawTools() {
|
|
|
53972
54150
|
title: "Validate the app",
|
|
53973
54151
|
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
54152
|
annotations: CHECK,
|
|
53975
|
-
inputSchema:
|
|
54153
|
+
inputSchema: z2.object({ dir: DIR2, strict: z2.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
|
|
53976
54154
|
handler: async (a, d) => fromCli(await d.runCli(["validate", "--content", await appDir2(a, d), ...sw("--strict", a.strict)]))
|
|
53977
54155
|
},
|
|
53978
54156
|
{
|
|
@@ -53980,10 +54158,10 @@ function rawTools() {
|
|
|
53980
54158
|
title: "Behavioral crawl",
|
|
53981
54159
|
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
54160
|
annotations: CHECK,
|
|
53983
|
-
inputSchema:
|
|
53984
|
-
dir:
|
|
53985
|
-
screens:
|
|
53986
|
-
deep:
|
|
54161
|
+
inputSchema: z2.object({
|
|
54162
|
+
dir: DIR2,
|
|
54163
|
+
screens: z2.array(z2.string()).optional().describe("Only these screen ids. Omit for all."),
|
|
54164
|
+
deep: z2.boolean().optional().describe("Also follow navigation into the screens actions open.")
|
|
53987
54165
|
}),
|
|
53988
54166
|
handler: async (a, d) => {
|
|
53989
54167
|
const screens = Array.isArray(a.screens) ? a.screens.filter((s) => typeof s === "string") : [];
|
|
@@ -53995,13 +54173,13 @@ function rawTools() {
|
|
|
53995
54173
|
title: "Render a screen to PNG",
|
|
53996
54174
|
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
54175
|
annotations: CHECK,
|
|
53998
|
-
inputSchema:
|
|
53999
|
-
screen:
|
|
54000
|
-
dir:
|
|
54001
|
-
scheme:
|
|
54002
|
-
width:
|
|
54003
|
-
device:
|
|
54004
|
-
rtl:
|
|
54176
|
+
inputSchema: z2.object({
|
|
54177
|
+
screen: z2.string().min(1).describe("The screen id."),
|
|
54178
|
+
dir: DIR2,
|
|
54179
|
+
scheme: z2.enum(["light", "dark"]).optional(),
|
|
54180
|
+
width: z2.number().int().positive().optional().describe("Viewport width in px."),
|
|
54181
|
+
device: z2.string().optional().describe("A named device (overrides width)."),
|
|
54182
|
+
rtl: z2.boolean().optional()
|
|
54005
54183
|
}),
|
|
54006
54184
|
handler: async (a, d) => {
|
|
54007
54185
|
const r = await d.runCli([
|
|
@@ -54031,12 +54209,12 @@ function rawTools() {
|
|
|
54031
54209
|
title: "Build journal",
|
|
54032
54210
|
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
54211
|
annotations: { ...LOCAL_WRITE, idempotentHint: false },
|
|
54034
|
-
inputSchema:
|
|
54035
|
-
dir:
|
|
54036
|
-
message:
|
|
54037
|
-
step:
|
|
54038
|
-
noImage:
|
|
54039
|
-
brief:
|
|
54212
|
+
inputSchema: z2.object({
|
|
54213
|
+
dir: DIR2,
|
|
54214
|
+
message: z2.string().optional().describe("What changed, one or two lines, for the owner."),
|
|
54215
|
+
step: z2.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
|
|
54216
|
+
noImage: z2.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
|
|
54217
|
+
brief: z2.boolean().optional()
|
|
54040
54218
|
}),
|
|
54041
54219
|
handler: async (a, d) => {
|
|
54042
54220
|
const dir = await appDir2(a, d);
|
|
@@ -54049,7 +54227,7 @@ function rawTools() {
|
|
|
54049
54227
|
title: "Start the live preview",
|
|
54050
54228
|
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
54229
|
annotations: LOCAL_WRITE,
|
|
54052
|
-
inputSchema:
|
|
54230
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54053
54231
|
handler: async (a, d) => {
|
|
54054
54232
|
try {
|
|
54055
54233
|
return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
|
|
@@ -54066,7 +54244,7 @@ ${log}` : ""}`, true);
|
|
|
54066
54244
|
title: "Live preview status",
|
|
54067
54245
|
description: "Whether this app's live preview is running, and its URL and last build result.",
|
|
54068
54246
|
annotations: CHECK,
|
|
54069
|
-
inputSchema:
|
|
54247
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54070
54248
|
handler: async (a, d) => json3(await d.preview.status(await appDir2(a, d)))
|
|
54071
54249
|
},
|
|
54072
54250
|
{
|
|
@@ -54074,7 +54252,7 @@ ${log}` : ""}`, true);
|
|
|
54074
54252
|
title: "Stop the live preview",
|
|
54075
54253
|
description: "Stop this app's live preview (the `himi run --watch` a `himi_preview_start` started).",
|
|
54076
54254
|
annotations: { ...LOCAL_WRITE, destructiveHint: false },
|
|
54077
|
-
inputSchema:
|
|
54255
|
+
inputSchema: z2.object({ dir: DIR2 }),
|
|
54078
54256
|
handler: async (a, d) => json3(await d.preview.stop(await appDir2(a, d)))
|
|
54079
54257
|
},
|
|
54080
54258
|
{
|
|
@@ -54082,7 +54260,7 @@ ${log}` : ""}`, true);
|
|
|
54082
54260
|
title: "Signed-in identity",
|
|
54083
54261
|
description: "The identity the stored serve-plane credential carries (account, scope, expiry). Local \u2014 decodes the stored token, no network.",
|
|
54084
54262
|
annotations: LEARN,
|
|
54085
|
-
inputSchema:
|
|
54263
|
+
inputSchema: z2.object({ target: z2.string().optional().describe("Serve target. Default: the CLI's default.") }),
|
|
54086
54264
|
handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target ?? d.login.target())]))
|
|
54087
54265
|
},
|
|
54088
54266
|
{
|
|
@@ -54090,9 +54268,9 @@ ${log}` : ""}`, true);
|
|
|
54090
54268
|
title: "Sign in to Wix",
|
|
54091
54269
|
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
54270
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
54093
|
-
inputSchema:
|
|
54094
|
-
target:
|
|
54095
|
-
switchAccount:
|
|
54271
|
+
inputSchema: z2.object({
|
|
54272
|
+
target: z2.string().optional().describe("Serve target. Default: the CLI's default."),
|
|
54273
|
+
switchAccount: z2.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
|
|
54096
54274
|
}),
|
|
54097
54275
|
handler: async (a, d) => {
|
|
54098
54276
|
const s = d.login.status();
|
|
@@ -54112,10 +54290,10 @@ ${log}` : ""}`, true);
|
|
|
54112
54290
|
title: "Publish a draft",
|
|
54113
54291
|
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
54292
|
annotations: PUBLISH,
|
|
54115
|
-
inputSchema:
|
|
54116
|
-
dir:
|
|
54117
|
-
label:
|
|
54118
|
-
notes:
|
|
54293
|
+
inputSchema: z2.object({
|
|
54294
|
+
dir: DIR2,
|
|
54295
|
+
label: z2.string().optional().describe("A short label for this draft."),
|
|
54296
|
+
notes: z2.string().optional().describe("Release notes for this draft.")
|
|
54119
54297
|
}),
|
|
54120
54298
|
handler: async (a, d) => {
|
|
54121
54299
|
const gate = await requireLogin(d);
|
|
@@ -54128,14 +54306,14 @@ ${log}` : ""}`, true);
|
|
|
54128
54306
|
title: "Share a .himi package link",
|
|
54129
54307
|
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
54308
|
annotations: PUBLISH,
|
|
54131
|
-
inputSchema:
|
|
54132
|
-
file:
|
|
54133
|
-
expiresAt:
|
|
54309
|
+
inputSchema: z2.object({
|
|
54310
|
+
file: z2.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
|
|
54311
|
+
expiresAt: z2.string().optional().describe("ISO timestamp the link stops working.")
|
|
54134
54312
|
}),
|
|
54135
54313
|
handler: async (a, d) => {
|
|
54136
54314
|
const gate = await requireLogin(d);
|
|
54137
54315
|
if (gate) return gate;
|
|
54138
|
-
return fromCli(await d.runCli(["share", "--file",
|
|
54316
|
+
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
54317
|
}
|
|
54140
54318
|
},
|
|
54141
54319
|
{
|
|
@@ -54145,19 +54323,20 @@ ${log}` : ""}`, true);
|
|
|
54145
54323
|
// Not idempotent: with credentials, each `himi preview` mints a fresh single-use handover —
|
|
54146
54324
|
// the same reason the hosted connector's tool of this name says false (RFC 0064 §5).
|
|
54147
54325
|
annotations: { ...PUBLISH, readOnlyHint: true, idempotentHint: false },
|
|
54148
|
-
inputSchema:
|
|
54149
|
-
app:
|
|
54150
|
-
release:
|
|
54151
|
-
screen:
|
|
54152
|
-
surface:
|
|
54326
|
+
inputSchema: z2.object({
|
|
54327
|
+
app: z2.string().min(1),
|
|
54328
|
+
release: z2.string().min(1),
|
|
54329
|
+
screen: z2.string().optional(),
|
|
54330
|
+
surface: z2.string().optional()
|
|
54153
54331
|
}),
|
|
54154
54332
|
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
54333
|
}
|
|
54156
54334
|
];
|
|
54157
54335
|
}
|
|
54158
|
-
var MAX_TEXT2, clip, text6, json3, opt, sw,
|
|
54336
|
+
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
|
|
54159
54337
|
var init_tools = __esm({
|
|
54160
54338
|
"src/mcp/tools.ts"() {
|
|
54339
|
+
init_file_tools();
|
|
54161
54340
|
MAX_TEXT2 = 8e4;
|
|
54162
54341
|
clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
|
|
54163
54342
|
\u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
|
|
@@ -54165,7 +54344,7 @@ var init_tools = __esm({
|
|
|
54165
54344
|
json3 = (o) => text6(JSON.stringify(o, null, 2));
|
|
54166
54345
|
opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
|
|
54167
54346
|
sw = (flag, v) => v === true ? [flag] : [];
|
|
54168
|
-
|
|
54347
|
+
DIR2 = z2.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
|
|
54169
54348
|
LEARN = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54170
54349
|
CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
54171
54350
|
LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
@@ -54194,12 +54373,12 @@ function createLoginSession(deps) {
|
|
|
54194
54373
|
current = pending;
|
|
54195
54374
|
const out2 = [];
|
|
54196
54375
|
const err = [];
|
|
54197
|
-
return new Promise((
|
|
54376
|
+
return new Promise((resolve54) => {
|
|
54198
54377
|
let answered = false;
|
|
54199
54378
|
const answer = () => {
|
|
54200
54379
|
if (answered) return;
|
|
54201
54380
|
answered = true;
|
|
54202
|
-
|
|
54381
|
+
resolve54(current);
|
|
54203
54382
|
};
|
|
54204
54383
|
let child;
|
|
54205
54384
|
try {
|
|
@@ -54258,7 +54437,7 @@ __export(server_exports, {
|
|
|
54258
54437
|
protectStdout: () => protectStdout,
|
|
54259
54438
|
startMcpServer: () => startMcpServer
|
|
54260
54439
|
});
|
|
54261
|
-
import { readFileSync as
|
|
54440
|
+
import { readFileSync as readFileSync60 } from "node:fs";
|
|
54262
54441
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
54263
54442
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
54264
54443
|
import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
@@ -54268,9 +54447,9 @@ function protectStdout() {
|
|
|
54268
54447
|
console.info = toErr;
|
|
54269
54448
|
console.debug = toErr;
|
|
54270
54449
|
}
|
|
54271
|
-
function buildServer(deps, version2) {
|
|
54450
|
+
function buildServer(deps, version2, tools = {}) {
|
|
54272
54451
|
const server = new McpServer({ name: "himi", version: version2 }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
|
|
54273
|
-
for (const tool of himiTools()) {
|
|
54452
|
+
for (const tool of himiTools(tools)) {
|
|
54274
54453
|
server.registerTool(
|
|
54275
54454
|
tool.name,
|
|
54276
54455
|
{ title: tool.title, description: tool.description, inputSchema: tool.inputSchema, annotations: { title: tool.title, ...tool.annotations } },
|
|
@@ -54304,23 +54483,23 @@ async function startMcpServer(opts) {
|
|
|
54304
54483
|
// next call rather than pinning every later tool to the server's cwd (often $HOME for a GUI host).
|
|
54305
54484
|
defaultDir: async () => {
|
|
54306
54485
|
if (!rootDir && pinned) rootDir = await firstRoot(pinned);
|
|
54307
|
-
return rootDir || process.cwd();
|
|
54486
|
+
return rootDir || opts.workspace || process.cwd();
|
|
54308
54487
|
},
|
|
54309
54488
|
preview: {
|
|
54310
54489
|
start: (dir) => startPreview(dir, { port: previewPortForDir(dir) }, previewDeps),
|
|
54311
54490
|
status: (dir) => previewStatus(dir, previewDeps),
|
|
54312
54491
|
stop: (dir) => stopPreview(dir, previewDeps)
|
|
54313
54492
|
},
|
|
54314
|
-
readFile: (p) =>
|
|
54493
|
+
readFile: (p) => readFileSync60(p),
|
|
54315
54494
|
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
|
|
54316
54495
|
};
|
|
54317
|
-
const closed = new Promise((
|
|
54318
|
-
stdin.once("end",
|
|
54319
|
-
stdin.once("close",
|
|
54496
|
+
const closed = new Promise((resolve54) => {
|
|
54497
|
+
stdin.once("end", resolve54);
|
|
54498
|
+
stdin.once("close", resolve54);
|
|
54320
54499
|
});
|
|
54321
54500
|
const handle = serveStdio(
|
|
54322
54501
|
() => {
|
|
54323
|
-
pinned = buildServer(deps, opts.version);
|
|
54502
|
+
pinned = buildServer(deps, opts.version, { withFiles: opts.withFiles });
|
|
54324
54503
|
return pinned;
|
|
54325
54504
|
},
|
|
54326
54505
|
{ transport: new StdioServerTransport(stdin, stdout), onerror: (e) => console.error(`[himi mcp] ${e.message}`) }
|
|
@@ -54354,9 +54533,9 @@ __export(native_decode_exports, {
|
|
|
54354
54533
|
runNativeDecode: () => runNativeDecode
|
|
54355
54534
|
});
|
|
54356
54535
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
54357
|
-
import { existsSync as
|
|
54536
|
+
import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync22 } from "node:fs";
|
|
54358
54537
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
54359
|
-
import { join as
|
|
54538
|
+
import { join as join54 } from "node:path";
|
|
54360
54539
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
54361
54540
|
function nativeDecodePackageDir() {
|
|
54362
54541
|
return fileURLToPath22(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -54366,8 +54545,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
54366
54545
|
}
|
|
54367
54546
|
function nativeOracleShipped() {
|
|
54368
54547
|
return {
|
|
54369
|
-
ios:
|
|
54370
|
-
android:
|
|
54548
|
+
ios: existsSync55(join54(nativeDecodePackageDir(), "Package.swift")),
|
|
54549
|
+
android: existsSync55(join54(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
54371
54550
|
};
|
|
54372
54551
|
}
|
|
54373
54552
|
function detectNativeDecode(options = {}) {
|
|
@@ -54378,7 +54557,7 @@ function detectNativeDecode(options = {}) {
|
|
|
54378
54557
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
54379
54558
|
}
|
|
54380
54559
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
54381
|
-
const packageAvailable = options.packageAvailable ??
|
|
54560
|
+
const packageAvailable = options.packageAvailable ?? existsSync55(join54(packageDir, "Package.swift"));
|
|
54382
54561
|
if (!packageAvailable) {
|
|
54383
54562
|
return {
|
|
54384
54563
|
platform: "ios",
|
|
@@ -54390,7 +54569,7 @@ function detectNativeDecode(options = {}) {
|
|
|
54390
54569
|
}
|
|
54391
54570
|
function localPropertiesSdk(harnessDir) {
|
|
54392
54571
|
try {
|
|
54393
|
-
const match =
|
|
54572
|
+
const match = readFileSync61(join54(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
54394
54573
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
54395
54574
|
} catch {
|
|
54396
54575
|
return null;
|
|
@@ -54398,8 +54577,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
54398
54577
|
}
|
|
54399
54578
|
function detectAndroidNativeDecode(options = {}) {
|
|
54400
54579
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
54401
|
-
const gradlew =
|
|
54402
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
54580
|
+
const gradlew = join54(harnessDir, "gradlew");
|
|
54581
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync55(gradlew);
|
|
54403
54582
|
if (!gradlewAvailable) {
|
|
54404
54583
|
return {
|
|
54405
54584
|
platform: "android",
|
|
@@ -54409,7 +54588,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
54409
54588
|
}
|
|
54410
54589
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
54411
54590
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
54412
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
54591
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync55(sdk));
|
|
54413
54592
|
if (!sdkAvailable) {
|
|
54414
54593
|
return {
|
|
54415
54594
|
platform: "android",
|
|
@@ -54481,14 +54660,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
54481
54660
|
return verdicts;
|
|
54482
54661
|
}
|
|
54483
54662
|
function runNativeDecode(options) {
|
|
54484
|
-
const descriptorDir = mkdtempSync2(
|
|
54663
|
+
const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-"));
|
|
54485
54664
|
const startedAt = Date.now();
|
|
54486
54665
|
try {
|
|
54487
54666
|
for (const descriptor of options.descriptors) {
|
|
54488
54667
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54489
54668
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54490
54669
|
}
|
|
54491
|
-
|
|
54670
|
+
writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54492
54671
|
}
|
|
54493
54672
|
options.progress?.("building cached Swift oracle");
|
|
54494
54673
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -54500,7 +54679,7 @@ function runNativeDecode(options) {
|
|
|
54500
54679
|
encoding: "utf8"
|
|
54501
54680
|
}).trim();
|
|
54502
54681
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54503
|
-
const stdout = execFileSync5(
|
|
54682
|
+
const stdout = execFileSync5(join54(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
54504
54683
|
stdio: ["ignore", "pipe", "pipe"],
|
|
54505
54684
|
encoding: "utf8"
|
|
54506
54685
|
});
|
|
@@ -54514,19 +54693,19 @@ function runNativeDecode(options) {
|
|
|
54514
54693
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
54515
54694
|
throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
|
|
54516
54695
|
} finally {
|
|
54517
|
-
|
|
54696
|
+
rmSync13(descriptorDir, { recursive: true, force: true });
|
|
54518
54697
|
}
|
|
54519
54698
|
}
|
|
54520
54699
|
function runAndroidNativeDecode(options) {
|
|
54521
|
-
const descriptorDir = mkdtempSync2(
|
|
54522
|
-
const outputPath =
|
|
54700
|
+
const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-android-"));
|
|
54701
|
+
const outputPath = join54(descriptorDir, "verdicts.ndjson");
|
|
54523
54702
|
const startedAt = Date.now();
|
|
54524
54703
|
try {
|
|
54525
54704
|
for (const descriptor of options.descriptors) {
|
|
54526
54705
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54527
54706
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54528
54707
|
}
|
|
54529
|
-
|
|
54708
|
+
writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54530
54709
|
}
|
|
54531
54710
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54532
54711
|
execFileSync5(options.gradlew, [
|
|
@@ -54541,7 +54720,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54541
54720
|
stdio: ["ignore", "ignore", "pipe"],
|
|
54542
54721
|
encoding: "utf8"
|
|
54543
54722
|
});
|
|
54544
|
-
const stdout =
|
|
54723
|
+
const stdout = readFileSync61(outputPath, "utf8");
|
|
54545
54724
|
return {
|
|
54546
54725
|
platform: "android",
|
|
54547
54726
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -54552,7 +54731,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54552
54731
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
54553
54732
|
throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
|
|
54554
54733
|
} finally {
|
|
54555
|
-
|
|
54734
|
+
rmSync13(descriptorDir, { recursive: true, force: true });
|
|
54556
54735
|
}
|
|
54557
54736
|
}
|
|
54558
54737
|
function fieldAt(path2) {
|
|
@@ -54611,30 +54790,30 @@ __export(browser_authoring_exports, {
|
|
|
54611
54790
|
});
|
|
54612
54791
|
import { createServer as createServer5 } from "node:http";
|
|
54613
54792
|
import { createHash as createHash29, randomBytes as randomBytes4 } from "node:crypto";
|
|
54614
|
-
import { existsSync as
|
|
54615
|
-
import { join as
|
|
54793
|
+
import { existsSync as existsSync56, readdirSync as readdirSync28, readFileSync as readFileSync62, realpathSync as realpathSync8, statSync as statSync14 } from "node:fs";
|
|
54794
|
+
import { join as join55, posix as posix2, relative as relative12, sep as sep15 } from "node:path";
|
|
54616
54795
|
function humanMs(ms) {
|
|
54617
54796
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
54618
54797
|
}
|
|
54619
54798
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
54620
|
-
const root =
|
|
54799
|
+
const root = join55(tier5SrcDir, bundleName);
|
|
54621
54800
|
const files = {};
|
|
54622
54801
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
54623
54802
|
const walk2 = (abs, rel) => {
|
|
54624
|
-
const real =
|
|
54803
|
+
const real = realpathSync8(abs);
|
|
54625
54804
|
if (visitedDirs.has(real)) return;
|
|
54626
54805
|
visitedDirs.add(real);
|
|
54627
|
-
for (const name of
|
|
54628
|
-
const childAbs =
|
|
54806
|
+
for (const name of readdirSync28(abs).sort()) {
|
|
54807
|
+
const childAbs = join55(abs, name);
|
|
54629
54808
|
const childRel = posix2.join(rel, name);
|
|
54630
|
-
if (
|
|
54809
|
+
if (statSync14(childAbs).isDirectory()) {
|
|
54631
54810
|
walk2(childAbs, childRel);
|
|
54632
54811
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
54633
|
-
files[childRel] =
|
|
54812
|
+
files[childRel] = readFileSync62(childAbs, "utf8");
|
|
54634
54813
|
}
|
|
54635
54814
|
}
|
|
54636
54815
|
};
|
|
54637
|
-
if (!
|
|
54816
|
+
if (!existsSync56(root)) return null;
|
|
54638
54817
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
54639
54818
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
54640
54819
|
if (!entry) return null;
|
|
@@ -54651,20 +54830,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
54651
54830
|
const spec = m[1];
|
|
54652
54831
|
const virtual = posix2.normalize(posix2.join(dir, spec));
|
|
54653
54832
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
54654
|
-
const onDisk =
|
|
54833
|
+
const onDisk = join55(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
54655
54834
|
const candidates = [
|
|
54656
54835
|
onDisk,
|
|
54657
54836
|
`${onDisk}.ts`,
|
|
54658
54837
|
`${onDisk}.js`,
|
|
54659
54838
|
onDisk.replace(/\.js$/, ".ts"),
|
|
54660
|
-
|
|
54661
|
-
|
|
54839
|
+
join55(onDisk, "index.ts"),
|
|
54840
|
+
join55(onDisk, "index.js")
|
|
54662
54841
|
];
|
|
54663
54842
|
for (const abs of candidates) {
|
|
54664
|
-
if (!
|
|
54665
|
-
const key2 = `/tier5-src/${
|
|
54843
|
+
if (!existsSync56(abs) || statSync14(abs).isDirectory()) continue;
|
|
54844
|
+
const key2 = `/tier5-src/${relative12(tier5SrcDir, abs).split(sep15).join(posix2.sep)}`;
|
|
54666
54845
|
if (key2 in files) break;
|
|
54667
|
-
files[key2] =
|
|
54846
|
+
files[key2] = readFileSync62(abs, "utf8");
|
|
54668
54847
|
queue.push(key2);
|
|
54669
54848
|
break;
|
|
54670
54849
|
}
|
|
@@ -54696,10 +54875,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
54696
54875
|
for (const source of Object.values(files)) visit(source);
|
|
54697
54876
|
return { modules, unsupported };
|
|
54698
54877
|
}
|
|
54699
|
-
function sdkSubpathReader(
|
|
54878
|
+
function sdkSubpathReader(resolve54) {
|
|
54700
54879
|
return (sub) => {
|
|
54701
54880
|
try {
|
|
54702
|
-
return
|
|
54881
|
+
return readFileSync62(resolve54(`@wix/himalaya/${sub}`), "utf8");
|
|
54703
54882
|
} catch {
|
|
54704
54883
|
return null;
|
|
54705
54884
|
}
|
|
@@ -54777,7 +54956,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
54777
54956
|
const token = mintToken2(payload);
|
|
54778
54957
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
54779
54958
|
if (unusable) throw new Error(unusable);
|
|
54780
|
-
return await new Promise((
|
|
54959
|
+
return await new Promise((resolve54, reject) => {
|
|
54781
54960
|
let settled = false;
|
|
54782
54961
|
let url = "";
|
|
54783
54962
|
const server = createServer5();
|
|
@@ -54829,7 +55008,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
54829
55008
|
}
|
|
54830
55009
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
54831
55010
|
const report3 = body.result;
|
|
54832
|
-
finish2(() =>
|
|
55011
|
+
finish2(() => resolve54({ report: report3, url }));
|
|
54833
55012
|
})();
|
|
54834
55013
|
});
|
|
54835
55014
|
server.on("error", (e) => finish2(() => reject(e)));
|
|
@@ -54871,8 +55050,8 @@ __export(coverage_exports, {
|
|
|
54871
55050
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
54872
55051
|
trendAndStore: () => trendAndStore
|
|
54873
55052
|
});
|
|
54874
|
-
import { existsSync as
|
|
54875
|
-
import { dirname as
|
|
55053
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as writeFileSync23 } from "node:fs";
|
|
55054
|
+
import { dirname as dirname31, join as join56 } from "node:path";
|
|
54876
55055
|
function suppressedNativeKeys(oracle) {
|
|
54877
55056
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
54878
55057
|
}
|
|
@@ -55052,11 +55231,11 @@ function assembleLedger(r, options = {}) {
|
|
|
55052
55231
|
return out2;
|
|
55053
55232
|
}
|
|
55054
55233
|
function trendAndStore(dir, entries, suppressed) {
|
|
55055
|
-
const p =
|
|
55234
|
+
const p = join56(dir, LEDGER_FILE);
|
|
55056
55235
|
let previous = null;
|
|
55057
55236
|
try {
|
|
55058
|
-
if (
|
|
55059
|
-
const parsed = JSON.parse(
|
|
55237
|
+
if (existsSync57(p)) {
|
|
55238
|
+
const parsed = JSON.parse(readFileSync63(p, "utf8"));
|
|
55060
55239
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
55061
55240
|
}
|
|
55062
55241
|
} catch {
|
|
@@ -55064,8 +55243,8 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
55064
55243
|
const current = entries.map((e) => e.key);
|
|
55065
55244
|
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
55066
55245
|
try {
|
|
55067
|
-
|
|
55068
|
-
|
|
55246
|
+
mkdirSync27(dirname31(p), { recursive: true });
|
|
55247
|
+
writeFileSync23(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55069
55248
|
} catch {
|
|
55070
55249
|
return null;
|
|
55071
55250
|
}
|
|
@@ -55095,11 +55274,11 @@ function formatLedger(entries, trend) {
|
|
|
55095
55274
|
return out2.join("\n");
|
|
55096
55275
|
}
|
|
55097
55276
|
function diffAndStoreObservations(dir, current) {
|
|
55098
|
-
const p =
|
|
55277
|
+
const p = join56(dir, OBS_FILE);
|
|
55099
55278
|
let previous = null;
|
|
55100
55279
|
try {
|
|
55101
|
-
if (
|
|
55102
|
-
const parsed = JSON.parse(
|
|
55280
|
+
if (existsSync57(p)) {
|
|
55281
|
+
const parsed = JSON.parse(readFileSync63(p, "utf8"));
|
|
55103
55282
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
55104
55283
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
55105
55284
|
)) {
|
|
@@ -55109,8 +55288,8 @@ function diffAndStoreObservations(dir, current) {
|
|
|
55109
55288
|
} catch {
|
|
55110
55289
|
}
|
|
55111
55290
|
try {
|
|
55112
|
-
|
|
55113
|
-
|
|
55291
|
+
mkdirSync27(dirname31(p), { recursive: true });
|
|
55292
|
+
writeFileSync23(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55114
55293
|
} catch {
|
|
55115
55294
|
return null;
|
|
55116
55295
|
}
|
|
@@ -55148,8 +55327,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
55148
55327
|
var init_coverage = __esm({
|
|
55149
55328
|
"src/coverage.ts"() {
|
|
55150
55329
|
init_native_decode();
|
|
55151
|
-
LEDGER_FILE =
|
|
55152
|
-
OBS_FILE =
|
|
55330
|
+
LEDGER_FILE = join56(".himi", "test-ledger.json");
|
|
55331
|
+
OBS_FILE = join56(".himi", "test-observations.json");
|
|
55153
55332
|
}
|
|
55154
55333
|
});
|
|
55155
55334
|
|
|
@@ -55160,16 +55339,16 @@ __export(design_kits_exports, {
|
|
|
55160
55339
|
kitsDir: () => kitsDir,
|
|
55161
55340
|
listKits: () => listKits2
|
|
55162
55341
|
});
|
|
55163
|
-
import { existsSync as
|
|
55164
|
-
import { join as
|
|
55342
|
+
import { existsSync as existsSync58, readFileSync as readFileSync64, readdirSync as readdirSync29 } from "node:fs";
|
|
55343
|
+
import { join as join57, basename as basename15 } from "node:path";
|
|
55165
55344
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
55166
55345
|
function kitsDir() {
|
|
55167
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
55346
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync58(p));
|
|
55168
55347
|
}
|
|
55169
55348
|
function listKits2() {
|
|
55170
55349
|
const dir = kitsDir();
|
|
55171
55350
|
if (!dir) return [];
|
|
55172
|
-
return
|
|
55351
|
+
return readdirSync29(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
|
|
55173
55352
|
}
|
|
55174
55353
|
function kitReport(name) {
|
|
55175
55354
|
const dir = kitsDir();
|
|
@@ -55188,7 +55367,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
55188
55367
|
if (!kits.includes(name)) {
|
|
55189
55368
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
55190
55369
|
}
|
|
55191
|
-
const raw =
|
|
55370
|
+
const raw = readFileSync64(join57(dir, `${name}.json`), "utf8");
|
|
55192
55371
|
let parsed;
|
|
55193
55372
|
try {
|
|
55194
55373
|
parsed = JSON.parse(raw);
|
|
@@ -55212,9 +55391,9 @@ var init_design_kits = __esm({
|
|
|
55212
55391
|
"src/design-kits.ts"() {
|
|
55213
55392
|
KIT_DIR_CANDIDATES = [
|
|
55214
55393
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
55215
|
-
|
|
55394
|
+
join57(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
55216
55395
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
55217
|
-
|
|
55396
|
+
join57(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
55218
55397
|
];
|
|
55219
55398
|
}
|
|
55220
55399
|
});
|
|
@@ -55228,11 +55407,11 @@ __export(assets_exports, {
|
|
|
55228
55407
|
removeAssetPayload: () => removeAssetPayload,
|
|
55229
55408
|
verifyReport: () => verifyReport
|
|
55230
55409
|
});
|
|
55231
|
-
import { readFileSync as
|
|
55410
|
+
import { readFileSync as readFileSync65 } from "node:fs";
|
|
55232
55411
|
import { basename as basename16 } from "node:path";
|
|
55233
55412
|
function declaredAssets(dir) {
|
|
55234
55413
|
return collectAssets(dir).map((a) => {
|
|
55235
|
-
const bytes2 =
|
|
55414
|
+
const bytes2 = readFileSync65(a.path);
|
|
55236
55415
|
return {
|
|
55237
55416
|
name: a.name,
|
|
55238
55417
|
sha256: assetSha256(bytes2),
|
|
@@ -55309,7 +55488,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
55309
55488
|
};
|
|
55310
55489
|
}
|
|
55311
55490
|
function addAssetPayload(manifest, filePath, opts) {
|
|
55312
|
-
const bytes2 =
|
|
55491
|
+
const bytes2 = readFileSync65(filePath);
|
|
55313
55492
|
const name = opts.name ?? basename16(filePath);
|
|
55314
55493
|
const sha2565 = assetSha256(bytes2);
|
|
55315
55494
|
const record2 = {
|
|
@@ -57033,9 +57212,9 @@ __export(run_exports, {
|
|
|
57033
57212
|
runPackage: () => runPackage,
|
|
57034
57213
|
withoutProdServe: () => withoutProdServe
|
|
57035
57214
|
});
|
|
57036
|
-
import { cpSync as cpSync2, existsSync as
|
|
57215
|
+
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
57216
|
import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
|
|
57038
|
-
import { dirname as
|
|
57217
|
+
import { dirname as dirname32, join as join58 } from "node:path";
|
|
57039
57218
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
57040
57219
|
function makePackageRunHandler(opts) {
|
|
57041
57220
|
const store = new FileReleaseStore(opts.releaseRoot);
|
|
@@ -57063,9 +57242,9 @@ async function fetchBytes(url) {
|
|
|
57063
57242
|
}
|
|
57064
57243
|
async function resolvePackage(source, workDir) {
|
|
57065
57244
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
57066
|
-
if (!isUrl2 &&
|
|
57067
|
-
const appDirManifest =
|
|
57068
|
-
if (
|
|
57245
|
+
if (!isUrl2 && existsSync59(source) && statSync15(source).isDirectory()) {
|
|
57246
|
+
const appDirManifest = join58(source, "release-manifest.json");
|
|
57247
|
+
if (existsSync59(appDirManifest)) {
|
|
57069
57248
|
const opened2 = openPackageDir(source);
|
|
57070
57249
|
if (!opened2.validation.ok) {
|
|
57071
57250
|
throw new Error(`package is not valid:
|
|
@@ -57074,11 +57253,11 @@ async function resolvePackage(source, workDir) {
|
|
|
57074
57253
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
57075
57254
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
57076
57255
|
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
|
-
|
|
57256
|
+
const root2 = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
|
|
57257
|
+
const target = join58(root2, app2);
|
|
57258
|
+
if (join58(source) !== target) {
|
|
57259
|
+
mkdirSync28(root2, { recursive: true });
|
|
57260
|
+
rmSync14(target, { recursive: true, force: true });
|
|
57082
57261
|
cpSync2(source, target, { recursive: true });
|
|
57083
57262
|
}
|
|
57084
57263
|
return {
|
|
@@ -57093,12 +57272,12 @@ async function resolvePackage(source, workDir) {
|
|
|
57093
57272
|
}
|
|
57094
57273
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
57095
57274
|
}
|
|
57096
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
57097
|
-
const root = workDir ?? mkdtempSync3(
|
|
57275
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync66(source);
|
|
57276
|
+
const root = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
|
|
57098
57277
|
const { app, appDir: appDir3 } = unpackTo(bytes2, root);
|
|
57099
57278
|
const opened = openPackageDir(appDir3);
|
|
57100
57279
|
if (!opened.validation.ok) {
|
|
57101
|
-
|
|
57280
|
+
rmSync14(workDir ? appDir3 : root, { recursive: true, force: true });
|
|
57102
57281
|
throw new Error(`package is not valid:
|
|
57103
57282
|
${opened.validation.errors.join("\n ")}`);
|
|
57104
57283
|
}
|
|
@@ -57115,16 +57294,16 @@ async function resolvePackage(source, workDir) {
|
|
|
57115
57294
|
async function loadPreviewAssets() {
|
|
57116
57295
|
try {
|
|
57117
57296
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
57118
|
-
const here =
|
|
57297
|
+
const here = dirname32(fileURLToPath24(import.meta.url));
|
|
57119
57298
|
const candidates = [
|
|
57120
|
-
|
|
57299
|
+
join58(here, "preview-assets.generated.bin"),
|
|
57121
57300
|
// published: copied next to the bundled CLI
|
|
57122
|
-
|
|
57301
|
+
join58(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
57123
57302
|
// in-repo checkout
|
|
57124
57303
|
];
|
|
57125
57304
|
for (const path2 of candidates) {
|
|
57126
|
-
if (!
|
|
57127
|
-
const blob =
|
|
57305
|
+
if (!existsSync59(path2)) continue;
|
|
57306
|
+
const blob = readFileSync66(path2);
|
|
57128
57307
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
57129
57308
|
}
|
|
57130
57309
|
return /* @__PURE__ */ new Map();
|
|
@@ -57172,7 +57351,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57172
57351
|
const resolved2 = await resolvePackage(source, opts.workDir);
|
|
57173
57352
|
const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
|
|
57174
57353
|
if (!opts.spa && assets.size === 0) {
|
|
57175
|
-
if (resolved2.temp)
|
|
57354
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57176
57355
|
throw new Error(NO_SPA_MESSAGE);
|
|
57177
57356
|
}
|
|
57178
57357
|
const plane = makePackageRunHandler({
|
|
@@ -57210,7 +57389,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57210
57389
|
lanBound = (await listen(lanServer, port, lanHost)).address;
|
|
57211
57390
|
} catch (e) {
|
|
57212
57391
|
await closeServer(server);
|
|
57213
|
-
if (resolved2.temp)
|
|
57392
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57214
57393
|
throw new Error(`himi run --lan could not listen on ${lanHost}:${port} (${e.message}); drop --lan, or pass --port for a free one`);
|
|
57215
57394
|
}
|
|
57216
57395
|
bound.push(lanBound);
|
|
@@ -57232,7 +57411,7 @@ async function runPackage(source, opts = {}) {
|
|
|
57232
57411
|
warnings: resolved2.warnings,
|
|
57233
57412
|
close: async () => {
|
|
57234
57413
|
await Promise.all(servers.map(closeServer));
|
|
57235
|
-
if (resolved2.temp)
|
|
57414
|
+
if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
|
|
57236
57415
|
}
|
|
57237
57416
|
};
|
|
57238
57417
|
}
|
|
@@ -57271,9 +57450,9 @@ __export(run_watch_exports, {
|
|
|
57271
57450
|
watchedContentDir: () => watchedContentDir,
|
|
57272
57451
|
writeRunRecord: () => writeRunRecord
|
|
57273
57452
|
});
|
|
57274
|
-
import { closeSync as closeSync4, constants, existsSync as
|
|
57453
|
+
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
57454
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
57276
|
-
import { extname as extname4, join as
|
|
57455
|
+
import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
|
|
57277
57456
|
function diffReleases(prev, next) {
|
|
57278
57457
|
const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
|
|
57279
57458
|
const changedBundles = new Set(bundles);
|
|
@@ -57314,7 +57493,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
57314
57493
|
let timer = null;
|
|
57315
57494
|
const pending = /* @__PURE__ */ new Set();
|
|
57316
57495
|
const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
|
|
57317
|
-
if (!file || ignoredChange(file, (rel) => isDir(
|
|
57496
|
+
if (!file || ignoredChange(file, (rel) => isDir(join59(dir, rel)))) return;
|
|
57318
57497
|
pending.add(file);
|
|
57319
57498
|
if (timer) clearTimeout(timer);
|
|
57320
57499
|
timer = setTimeout(() => {
|
|
@@ -57333,9 +57512,9 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
57333
57512
|
}
|
|
57334
57513
|
function watchedContentDir(source) {
|
|
57335
57514
|
if (!source || /^https?:\/\//i.test(source)) return null;
|
|
57336
|
-
const dir =
|
|
57515
|
+
const dir = resolve47(source);
|
|
57337
57516
|
try {
|
|
57338
|
-
return
|
|
57517
|
+
return statSync16(dir).isDirectory() && existsSync60(join59(dir, "himalaya.content.json")) ? dir : null;
|
|
57339
57518
|
} catch {
|
|
57340
57519
|
return null;
|
|
57341
57520
|
}
|
|
@@ -57392,33 +57571,33 @@ function serialize(task) {
|
|
|
57392
57571
|
});
|
|
57393
57572
|
}
|
|
57394
57573
|
function himiDir(dir) {
|
|
57395
|
-
const root =
|
|
57574
|
+
const root = join59(dir, ".himi");
|
|
57396
57575
|
try {
|
|
57397
|
-
return
|
|
57576
|
+
return lstatSync13(root).isDirectory() ? root : null;
|
|
57398
57577
|
} catch (e) {
|
|
57399
57578
|
if (e.code !== "ENOENT") return null;
|
|
57400
|
-
|
|
57401
|
-
return
|
|
57579
|
+
mkdirSync29(root, { recursive: true });
|
|
57580
|
+
return lstatSync13(root).isDirectory() ? root : null;
|
|
57402
57581
|
}
|
|
57403
57582
|
}
|
|
57404
57583
|
function writeRunRecord(dir, record2) {
|
|
57405
57584
|
const root = himiDir(dir);
|
|
57406
57585
|
if (!root) return false;
|
|
57407
|
-
const tmp =
|
|
57586
|
+
const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
|
|
57408
57587
|
try {
|
|
57409
|
-
|
|
57588
|
+
writeFileSync24(tmp, `${JSON.stringify(record2, null, 2)}
|
|
57410
57589
|
`, { flag: "wx" });
|
|
57411
|
-
renameSync6(tmp,
|
|
57590
|
+
renameSync6(tmp, join59(root, "run.json"));
|
|
57412
57591
|
} catch (e) {
|
|
57413
|
-
|
|
57592
|
+
rmSync15(tmp, { force: true });
|
|
57414
57593
|
throw e;
|
|
57415
57594
|
}
|
|
57416
57595
|
return true;
|
|
57417
57596
|
}
|
|
57418
57597
|
function removeRunRecord(dir, owner) {
|
|
57419
|
-
const root =
|
|
57598
|
+
const root = join59(dir, ".himi");
|
|
57420
57599
|
try {
|
|
57421
|
-
if (!
|
|
57600
|
+
if (!lstatSync13(root).isDirectory()) return;
|
|
57422
57601
|
} catch {
|
|
57423
57602
|
return;
|
|
57424
57603
|
}
|
|
@@ -57431,22 +57610,22 @@ function removeRunRecord(dir, owner) {
|
|
|
57431
57610
|
}
|
|
57432
57611
|
if (typeof pid === "number" && pid !== owner) return;
|
|
57433
57612
|
}
|
|
57434
|
-
|
|
57613
|
+
rmSync15(join59(root, "run.json"), { force: true });
|
|
57435
57614
|
}
|
|
57436
57615
|
function boardFile(dir, pathname) {
|
|
57437
57616
|
if (pathname === RUN_IDENTITY_PATH) {
|
|
57438
57617
|
return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
|
|
57439
57618
|
}
|
|
57440
57619
|
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 =
|
|
57620
|
+
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join59("studio", "index.html");
|
|
57621
|
+
else if (pathname === "/__himi/studio/state.js") rel = join59("studio", "state.js");
|
|
57622
|
+
else if (pathname === "/__himi/studio/timeline.js") rel = join59("studio", "timeline.js");
|
|
57444
57623
|
else {
|
|
57445
57624
|
const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
|
|
57446
|
-
if (m) rel =
|
|
57625
|
+
if (m) rel = join59("history", m[1]);
|
|
57447
57626
|
}
|
|
57448
57627
|
if (!rel) return null;
|
|
57449
|
-
const bytes2 = readConfined(
|
|
57628
|
+
const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
|
|
57450
57629
|
if (!bytes2) return new Response("not found", { status: 404 });
|
|
57451
57630
|
return new Response(bytes2, {
|
|
57452
57631
|
status: 200,
|
|
@@ -57455,20 +57634,20 @@ function boardFile(dir, pathname) {
|
|
|
57455
57634
|
}
|
|
57456
57635
|
function readConfined(root, rel) {
|
|
57457
57636
|
try {
|
|
57458
|
-
if (!
|
|
57459
|
-
const parts = rel.split(
|
|
57637
|
+
if (!lstatSync13(root).isDirectory()) return null;
|
|
57638
|
+
const parts = rel.split(sep16);
|
|
57460
57639
|
let at2 = root;
|
|
57461
57640
|
for (let i = 0; i < parts.length; i++) {
|
|
57462
|
-
at2 =
|
|
57463
|
-
const st =
|
|
57641
|
+
at2 = join59(at2, parts[i]);
|
|
57642
|
+
const st = lstatSync13(at2);
|
|
57464
57643
|
if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
|
|
57465
57644
|
}
|
|
57466
|
-
const canonicalRoot =
|
|
57467
|
-
if (!
|
|
57645
|
+
const canonicalRoot = realpathSync9(root);
|
|
57646
|
+
if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
|
|
57468
57647
|
const fd = openSync3(at2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
57469
57648
|
try {
|
|
57470
57649
|
if (!fstatSync(fd).isFile()) return null;
|
|
57471
|
-
return
|
|
57650
|
+
return readFileSync67(fd);
|
|
57472
57651
|
} finally {
|
|
57473
57652
|
closeSync4(fd);
|
|
57474
57653
|
}
|
|
@@ -57497,7 +57676,7 @@ var init_run_watch = __esm({
|
|
|
57497
57676
|
};
|
|
57498
57677
|
isDir = (path2) => {
|
|
57499
57678
|
try {
|
|
57500
|
-
return
|
|
57679
|
+
return statSync16(path2).isDirectory();
|
|
57501
57680
|
} catch {
|
|
57502
57681
|
return false;
|
|
57503
57682
|
}
|
|
@@ -57521,19 +57700,19 @@ __export(run_browser_exports, {
|
|
|
57521
57700
|
runInBrowser: () => runInBrowser
|
|
57522
57701
|
});
|
|
57523
57702
|
import { createServer as createServer7 } from "node:http";
|
|
57524
|
-
import { existsSync as
|
|
57703
|
+
import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
|
|
57525
57704
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
57526
|
-
import { dirname as
|
|
57705
|
+
import { dirname as dirname33, resolve as resolve48 } from "node:path";
|
|
57527
57706
|
import { fileURLToPath as fileURLToPath25 } from "node:url";
|
|
57528
57707
|
function stagedDir() {
|
|
57529
|
-
return process.env.HIMI_BROWSER_PLANE_OUT ?
|
|
57708
|
+
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve48(process.env.HIMI_BROWSER_PLANE_OUT) : resolve48(REPO, "packages", "serve", "dist", "browser-plane");
|
|
57530
57709
|
}
|
|
57531
57710
|
function missingStaged() {
|
|
57532
|
-
return [...SERVED].filter((f) => !
|
|
57711
|
+
return [...SERVED].filter((f) => !existsSync61(resolve48(stagedDir(), f))).sort();
|
|
57533
57712
|
}
|
|
57534
57713
|
function ensureBrowserPlaneStaged() {
|
|
57535
57714
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
57536
|
-
const r = spawnSync3(process.execPath, [
|
|
57715
|
+
const r = spawnSync3(process.execPath, [resolve48(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
|
|
57537
57716
|
cwd: REPO,
|
|
57538
57717
|
encoding: "utf8"
|
|
57539
57718
|
});
|
|
@@ -57619,7 +57798,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
57619
57798
|
}
|
|
57620
57799
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
57621
57800
|
if (SERVED.has(name)) {
|
|
57622
|
-
if (!
|
|
57801
|
+
if (!existsSync61(resolve48(stagedDir(), name))) {
|
|
57623
57802
|
const restaged = ensureBrowserPlaneStaged();
|
|
57624
57803
|
if (!restaged.ok) {
|
|
57625
57804
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -57629,7 +57808,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
57629
57808
|
}
|
|
57630
57809
|
let bytes2;
|
|
57631
57810
|
try {
|
|
57632
|
-
bytes2 =
|
|
57811
|
+
bytes2 = readFileSync68(resolve48(stagedDir(), name));
|
|
57633
57812
|
} catch (e) {
|
|
57634
57813
|
res.writeHead(503, { "content-type": "application/json" });
|
|
57635
57814
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -57671,8 +57850,8 @@ var init_run_browser = __esm({
|
|
|
57671
57850
|
init_open_url();
|
|
57672
57851
|
init_file_store();
|
|
57673
57852
|
init_wix_client_id();
|
|
57674
|
-
HERE2 =
|
|
57675
|
-
REPO =
|
|
57853
|
+
HERE2 = dirname33(fileURLToPath25(import.meta.url));
|
|
57854
|
+
REPO = resolve48(HERE2, "..", "..", "..");
|
|
57676
57855
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
57677
57856
|
}
|
|
57678
57857
|
});
|
|
@@ -58091,11 +58270,11 @@ __export(preflight_exports, {
|
|
|
58091
58270
|
parseStoreConfig: () => parseStoreConfig,
|
|
58092
58271
|
requireEnv: () => requireEnv
|
|
58093
58272
|
});
|
|
58094
|
-
import { existsSync as
|
|
58095
|
-
import { isAbsolute as
|
|
58273
|
+
import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
|
|
58274
|
+
import { isAbsolute as isAbsolute6, relative as relative13, resolve as resolve49 } from "node:path";
|
|
58096
58275
|
function isInsideRepo(p) {
|
|
58097
|
-
const rel =
|
|
58098
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
58276
|
+
const rel = relative13(REPO_ROOT3, resolve49(p));
|
|
58277
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute6(rel);
|
|
58099
58278
|
}
|
|
58100
58279
|
function assertCredentialOutsideRepo(label2, p) {
|
|
58101
58280
|
if (isInsideRepo(p)) {
|
|
@@ -58148,10 +58327,10 @@ function parseStoreConfig(text8) {
|
|
|
58148
58327
|
}
|
|
58149
58328
|
function loadStoreConfig(app) {
|
|
58150
58329
|
const p = storeConfigPath(app);
|
|
58151
|
-
if (!
|
|
58330
|
+
if (!existsSync62(p)) {
|
|
58152
58331
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
58153
58332
|
}
|
|
58154
|
-
return parseStoreConfig(
|
|
58333
|
+
return parseStoreConfig(readFileSync69(p, "utf8"));
|
|
58155
58334
|
}
|
|
58156
58335
|
var init_preflight = __esm({
|
|
58157
58336
|
"../store-release/preflight.ts"() {
|
|
@@ -58170,19 +58349,19 @@ __export(credential_profile_exports, {
|
|
|
58170
58349
|
profilePath: () => profilePath,
|
|
58171
58350
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
58172
58351
|
});
|
|
58173
|
-
import { existsSync as
|
|
58352
|
+
import { existsSync as existsSync63, readFileSync as readFileSync70 } from "node:fs";
|
|
58174
58353
|
import { homedir as homedir5 } from "node:os";
|
|
58175
|
-
import { join as
|
|
58354
|
+
import { join as join60 } from "node:path";
|
|
58176
58355
|
function credentialsDir(home = homedir5()) {
|
|
58177
|
-
return
|
|
58356
|
+
return join60(home, ".himalaya", "store-credentials");
|
|
58178
58357
|
}
|
|
58179
58358
|
function profilePath(name, home = homedir5()) {
|
|
58180
58359
|
if (!PROFILE_NAME.test(name)) {
|
|
58181
58360
|
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 ${
|
|
58361
|
+
`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
58362
|
);
|
|
58184
58363
|
}
|
|
58185
|
-
return
|
|
58364
|
+
return join60(credentialsDir(home), `${name}.json`);
|
|
58186
58365
|
}
|
|
58187
58366
|
function parseProfile(text8, label2) {
|
|
58188
58367
|
let doc;
|
|
@@ -58213,8 +58392,8 @@ function resolveStoreCredentials(opts) {
|
|
|
58213
58392
|
const { app, cfg } = opts;
|
|
58214
58393
|
const env = opts.env ?? process.env;
|
|
58215
58394
|
const home = opts.home ?? homedir5();
|
|
58216
|
-
const read = opts.readProfile ?? ((p) =>
|
|
58217
|
-
const exists = opts.profileExists ??
|
|
58395
|
+
const read = opts.readProfile ?? ((p) => readFileSync70(p, "utf8"));
|
|
58396
|
+
const exists = opts.profileExists ?? existsSync63;
|
|
58218
58397
|
const ios = cfg.ios ?? {};
|
|
58219
58398
|
const flagName = opts.profileFlag?.trim();
|
|
58220
58399
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -58294,9 +58473,9 @@ __export(preflight_app_exports, {
|
|
|
58294
58473
|
preflightApp: () => preflightApp,
|
|
58295
58474
|
profileAccount: () => profileAccount
|
|
58296
58475
|
});
|
|
58297
|
-
import { readFileSync as
|
|
58476
|
+
import { readFileSync as readFileSync71, existsSync as existsSync64, readdirSync as readdirSync30, statSync as statSync17 } from "node:fs";
|
|
58298
58477
|
import { createHash as createHash30 } from "node:crypto";
|
|
58299
|
-
import { join as
|
|
58478
|
+
import { join as join61 } from "node:path";
|
|
58300
58479
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
58301
58480
|
const f = [];
|
|
58302
58481
|
const has = (re, s) => re.test(s);
|
|
@@ -58360,13 +58539,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
58360
58539
|
}
|
|
58361
58540
|
}
|
|
58362
58541
|
async function preflightApp(app, opts = {}) {
|
|
58363
|
-
const projectYml =
|
|
58364
|
-
const storeConfig =
|
|
58542
|
+
const projectYml = existsSync64(iosProjectYml(app)) ? readFileSync71(iosProjectYml(app), "utf8") : "";
|
|
58543
|
+
const storeConfig = existsSync64(storeConfigPath(app)) ? readFileSync71(storeConfigPath(app), "utf8") : "";
|
|
58365
58544
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
58366
58545
|
const findings = analyze(
|
|
58367
58546
|
projectYml,
|
|
58368
58547
|
storeConfig,
|
|
58369
|
-
await appIconState(
|
|
58548
|
+
await appIconState(join61(appDir(app), "ios")),
|
|
58370
58549
|
profileAccount(app, storeConfig, opts)
|
|
58371
58550
|
);
|
|
58372
58551
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -58395,18 +58574,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
58395
58574
|
return f;
|
|
58396
58575
|
}
|
|
58397
58576
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
58398
|
-
const root =
|
|
58577
|
+
const root = join61(storeDir(app), "metadata");
|
|
58399
58578
|
const out2 = /* @__PURE__ */ new Set();
|
|
58400
|
-
if (
|
|
58401
|
-
for (const n of
|
|
58579
|
+
if (existsSync64(root)) {
|
|
58580
|
+
for (const n of readdirSync30(root)) if (n.endsWith(".txt")) out2.add(n);
|
|
58402
58581
|
}
|
|
58403
|
-
if (
|
|
58582
|
+
if (existsSync64(join61(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
|
|
58404
58583
|
return out2;
|
|
58405
58584
|
}
|
|
58406
58585
|
function reviewInfoFiles(app) {
|
|
58407
|
-
const dir =
|
|
58408
|
-
if (!
|
|
58409
|
-
return new Set(
|
|
58586
|
+
const dir = join61(storeDir(app), "review_information");
|
|
58587
|
+
if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
|
|
58588
|
+
return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
|
|
58410
58589
|
}
|
|
58411
58590
|
function isValidAppStoreSize(w, h) {
|
|
58412
58591
|
return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
|
|
@@ -58515,12 +58694,12 @@ function analyzePlayListing(assets) {
|
|
|
58515
58694
|
return f;
|
|
58516
58695
|
}
|
|
58517
58696
|
function playListingAssets(app, locale = "en-US") {
|
|
58518
|
-
const dir =
|
|
58697
|
+
const dir = join61(storeDir(app), "play", locale, "images");
|
|
58519
58698
|
const read = (names) => {
|
|
58520
58699
|
for (const name of names) {
|
|
58521
|
-
const p =
|
|
58700
|
+
const p = join61(dir, name);
|
|
58522
58701
|
try {
|
|
58523
|
-
if (
|
|
58702
|
+
if (statSync17(p).isFile()) return { name, bytes: readFileSync71(p) };
|
|
58524
58703
|
} catch {
|
|
58525
58704
|
}
|
|
58526
58705
|
}
|
|
@@ -58551,26 +58730,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
58551
58730
|
return f;
|
|
58552
58731
|
}
|
|
58553
58732
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
58554
|
-
const dir =
|
|
58555
|
-
if (!
|
|
58556
|
-
return new Set(
|
|
58733
|
+
const dir = join61(storeDir(app), "metadata", locale);
|
|
58734
|
+
if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
|
|
58735
|
+
return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
|
|
58557
58736
|
}
|
|
58558
58737
|
function listScreenshots(app, locale = "en-US") {
|
|
58559
58738
|
const out2 = [];
|
|
58560
|
-
const flat =
|
|
58561
|
-
if (
|
|
58562
|
-
for (const png of
|
|
58563
|
-
const sz = pngSize(
|
|
58739
|
+
const flat = join61(storeDir(app), "screenshots", locale);
|
|
58740
|
+
if (existsSync64(flat)) {
|
|
58741
|
+
for (const png of readdirSync30(flat).filter((n) => n.endsWith(".png"))) {
|
|
58742
|
+
const sz = pngSize(readFileSync71(join61(flat, png)));
|
|
58564
58743
|
if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
|
|
58565
58744
|
}
|
|
58566
58745
|
}
|
|
58567
|
-
const legacy =
|
|
58568
|
-
if (
|
|
58569
|
-
for (const deviceDir of
|
|
58570
|
-
const d =
|
|
58571
|
-
if (!
|
|
58572
|
-
for (const png of
|
|
58573
|
-
const sz = pngSize(
|
|
58746
|
+
const legacy = join61(storeDir(app), "metadata", locale, "screenshots");
|
|
58747
|
+
if (existsSync64(legacy)) {
|
|
58748
|
+
for (const deviceDir of readdirSync30(legacy)) {
|
|
58749
|
+
const d = join61(legacy, deviceDir);
|
|
58750
|
+
if (!statSync17(d).isDirectory()) continue;
|
|
58751
|
+
for (const png of readdirSync30(d).filter((n) => n.endsWith(".png"))) {
|
|
58752
|
+
const sz = pngSize(readFileSync71(join61(d, png)));
|
|
58574
58753
|
if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
58575
58754
|
}
|
|
58576
58755
|
}
|
|
@@ -58578,13 +58757,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
58578
58757
|
return out2;
|
|
58579
58758
|
}
|
|
58580
58759
|
function placeholderHashes2() {
|
|
58581
|
-
const templateIos =
|
|
58582
|
-
if (!
|
|
58583
|
-
for (const target of
|
|
58584
|
-
const p =
|
|
58760
|
+
const templateIos = join61(appDir("_template"), "ios");
|
|
58761
|
+
if (!existsSync64(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
58762
|
+
for (const target of readdirSync30(templateIos)) {
|
|
58763
|
+
const p = join61(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
58585
58764
|
try {
|
|
58586
|
-
if (!
|
|
58587
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(
|
|
58765
|
+
if (!statSync17(p).isFile()) continue;
|
|
58766
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync71(p)).digest("hex")];
|
|
58588
58767
|
} catch {
|
|
58589
58768
|
}
|
|
58590
58769
|
}
|
|
@@ -58615,12 +58794,12 @@ async function pixelIssues(bytes2) {
|
|
|
58615
58794
|
}
|
|
58616
58795
|
}
|
|
58617
58796
|
async function appIconState(iosDir) {
|
|
58618
|
-
if (!
|
|
58619
|
-
for (const target of
|
|
58620
|
-
const p =
|
|
58797
|
+
if (!existsSync64(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
58798
|
+
for (const target of readdirSync30(iosDir)) {
|
|
58799
|
+
const p = join61(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
58621
58800
|
try {
|
|
58622
|
-
if (!
|
|
58623
|
-
const bytes2 =
|
|
58801
|
+
if (!statSync17(p).isFile()) continue;
|
|
58802
|
+
const bytes2 = readFileSync71(p);
|
|
58624
58803
|
const hash = createHash30("sha256").update(bytes2).digest("hex");
|
|
58625
58804
|
const pixels = await pixelIssues(bytes2);
|
|
58626
58805
|
return {
|
|
@@ -58692,7 +58871,7 @@ __export(version_exports, {
|
|
|
58692
58871
|
setAndroidVersion: () => setAndroidVersion,
|
|
58693
58872
|
setIosVersion: () => setIosVersion
|
|
58694
58873
|
});
|
|
58695
|
-
import { readFileSync as
|
|
58874
|
+
import { readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
|
|
58696
58875
|
function readIosVersion(projectYml) {
|
|
58697
58876
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
58698
58877
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -58750,15 +58929,15 @@ function setAndroidVersion(gradle, v) {
|
|
|
58750
58929
|
function bumpVersion(app, opts) {
|
|
58751
58930
|
const iosPath = iosProjectYml(app);
|
|
58752
58931
|
const gradlePath = androidGradle(app);
|
|
58753
|
-
const iosYml =
|
|
58754
|
-
const gradle =
|
|
58932
|
+
const iosYml = readFileSync72(iosPath, "utf8");
|
|
58933
|
+
const gradle = readFileSync72(gradlePath, "utf8");
|
|
58755
58934
|
const current = readIosVersion(iosYml);
|
|
58756
58935
|
const next = {
|
|
58757
58936
|
marketing: opts.marketing ?? current.marketing,
|
|
58758
58937
|
build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
|
|
58759
58938
|
};
|
|
58760
|
-
|
|
58761
|
-
|
|
58939
|
+
writeFileSync25(iosPath, setIosVersion(iosYml, next));
|
|
58940
|
+
writeFileSync25(gradlePath, setAndroidVersion(gradle, next));
|
|
58762
58941
|
return next;
|
|
58763
58942
|
}
|
|
58764
58943
|
var init_version = __esm({
|
|
@@ -58768,7 +58947,7 @@ var init_version = __esm({
|
|
|
58768
58947
|
});
|
|
58769
58948
|
|
|
58770
58949
|
// ../store-release/register-bundle.ts
|
|
58771
|
-
import { readFileSync as
|
|
58950
|
+
import { readFileSync as readFileSync73 } from "node:fs";
|
|
58772
58951
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
58773
58952
|
function b64url2(b) {
|
|
58774
58953
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -58786,7 +58965,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
58786
58965
|
async function registerBundleId(opts) {
|
|
58787
58966
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
58788
58967
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
58789
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
58968
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
58790
58969
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
58791
58970
|
method: "POST",
|
|
58792
58971
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -58840,7 +59019,7 @@ __export(asc_status_exports, {
|
|
|
58840
59019
|
ascStatus: () => ascStatus,
|
|
58841
59020
|
buildVerdict: () => buildVerdict
|
|
58842
59021
|
});
|
|
58843
|
-
import { readFileSync as
|
|
59022
|
+
import { readFileSync as readFileSync74 } from "node:fs";
|
|
58844
59023
|
function buildVerdict(builds) {
|
|
58845
59024
|
if (!builds.length) {
|
|
58846
59025
|
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 +59033,7 @@ function buildVerdict(builds) {
|
|
|
58854
59033
|
function client(creds) {
|
|
58855
59034
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
58856
59035
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
58857
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
59036
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync74(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
58858
59037
|
return async (path2) => {
|
|
58859
59038
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
58860
59039
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -58903,7 +59082,7 @@ var init_asc_status = __esm({
|
|
|
58903
59082
|
// ../../core/functions-secrets/src/vault.ts
|
|
58904
59083
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
|
|
58905
59084
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
58906
|
-
import { dirname as
|
|
59085
|
+
import { dirname as dirname34 } from "node:path";
|
|
58907
59086
|
function createJsonSecretStore(filePath) {
|
|
58908
59087
|
const read = async () => {
|
|
58909
59088
|
try {
|
|
@@ -58916,7 +59095,7 @@ function createJsonSecretStore(filePath) {
|
|
|
58916
59095
|
}
|
|
58917
59096
|
};
|
|
58918
59097
|
const write2 = async (records) => {
|
|
58919
|
-
await mkdir(
|
|
59098
|
+
await mkdir(dirname34(filePath), { recursive: true });
|
|
58920
59099
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
58921
59100
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
58922
59101
|
`, { mode: 384 });
|
|
@@ -59014,7 +59193,7 @@ __export(secrets_exports, {
|
|
|
59014
59193
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
59015
59194
|
runSecretsCommand: () => runSecretsCommand
|
|
59016
59195
|
});
|
|
59017
|
-
import { readFileSync as
|
|
59196
|
+
import { readFileSync as readFileSync75 } from "node:fs";
|
|
59018
59197
|
function environment(value) {
|
|
59019
59198
|
if (value === "preview" || value === "production") return value;
|
|
59020
59199
|
throw new Error("--environment must be preview or production");
|
|
@@ -59045,7 +59224,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
59045
59224
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
59046
59225
|
return 0;
|
|
59047
59226
|
}
|
|
59048
|
-
const value = options.readValue ? options.readValue() :
|
|
59227
|
+
const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
|
|
59049
59228
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
59050
59229
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
59051
59230
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -59074,7 +59253,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
59074
59253
|
}
|
|
59075
59254
|
let body;
|
|
59076
59255
|
if (operation !== "list") {
|
|
59077
|
-
const value = options.readValue ? options.readValue() :
|
|
59256
|
+
const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
|
|
59078
59257
|
body = JSON.stringify({ value });
|
|
59079
59258
|
}
|
|
59080
59259
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -59211,29 +59390,29 @@ __export(notify_ping_exports, {
|
|
|
59211
59390
|
runNotifyPing: () => runNotifyPing
|
|
59212
59391
|
});
|
|
59213
59392
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
59214
|
-
import { resolve as
|
|
59215
|
-
function
|
|
59393
|
+
import { resolve as resolve50 } from "node:path";
|
|
59394
|
+
function refuse5(io, error, hint, exit = 2, extra = {}) {
|
|
59216
59395
|
io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
|
|
59217
59396
|
return exit;
|
|
59218
59397
|
}
|
|
59219
59398
|
async function runNotifyPing(flags, io, deps = {}) {
|
|
59220
59399
|
const flagError = flagRefusal(flags);
|
|
59221
|
-
if (flagError) return
|
|
59222
|
-
const input = mergePushInputs(pushInputsFromContent(
|
|
59400
|
+
if (flagError) return refuse5(io, flagError);
|
|
59401
|
+
const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
|
|
59223
59402
|
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
|
|
59224
|
-
if (missing.length) return
|
|
59403
|
+
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
59404
|
const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
|
|
59226
|
-
if (!UUID_RE.test(requestId2)) return
|
|
59405
|
+
if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
|
|
59227
59406
|
const owner = await hostedOwnerSession(flags, deps);
|
|
59228
|
-
if (!owner.ok) return
|
|
59407
|
+
if (!owner.ok) return refuse5(io, owner.error, owner.hint, owner.exit);
|
|
59229
59408
|
const { session } = owner;
|
|
59230
59409
|
const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
|
|
59231
|
-
if (ownership.state !== "owned") return
|
|
59410
|
+
if (ownership.state !== "owned") return refuse5(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
|
|
59232
59411
|
let siteToken2;
|
|
59233
59412
|
try {
|
|
59234
59413
|
siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
|
|
59235
59414
|
} catch {
|
|
59236
|
-
return
|
|
59415
|
+
return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
|
|
59237
59416
|
}
|
|
59238
59417
|
const body = {
|
|
59239
59418
|
app: ownership.slug,
|
|
@@ -59256,12 +59435,12 @@ function flagRefusal(flags) {
|
|
|
59256
59435
|
function report2(http, sent, flags, io) {
|
|
59257
59436
|
const code = refusalCode(http);
|
|
59258
59437
|
if (code === "send_outcome_unknown") {
|
|
59259
|
-
return
|
|
59438
|
+
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
59439
|
}
|
|
59261
59440
|
if (code === "rate_limited" && http.retryAfterSec) {
|
|
59262
|
-
return
|
|
59441
|
+
return refuse5(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
|
|
59263
59442
|
}
|
|
59264
|
-
if (code) return
|
|
59443
|
+
if (code) return refuse5(io, code, HINTS[code], 1);
|
|
59265
59444
|
if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
|
|
59266
59445
|
else io.log(summary(http.body ?? {}, sent));
|
|
59267
59446
|
return 0;
|
|
@@ -59321,15 +59500,15 @@ __export(notify_exports, {
|
|
|
59321
59500
|
runNotify: () => runNotify,
|
|
59322
59501
|
saveAdminSession: () => saveAdminSession
|
|
59323
59502
|
});
|
|
59324
|
-
import { chmodSync as chmodSync3, mkdirSync as
|
|
59503
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync26 } from "node:fs";
|
|
59325
59504
|
import { homedir as homedir6 } from "node:os";
|
|
59326
|
-
import { dirname as
|
|
59505
|
+
import { dirname as dirname35, join as join62 } from "node:path";
|
|
59327
59506
|
function defaultSessionsPath() {
|
|
59328
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
59507
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join62(homedir6(), ".himalaya", "admin-sessions.json");
|
|
59329
59508
|
}
|
|
59330
59509
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
59331
59510
|
try {
|
|
59332
|
-
return JSON.parse(
|
|
59511
|
+
return JSON.parse(readFileSync76(path2, "utf8"));
|
|
59333
59512
|
} catch {
|
|
59334
59513
|
return {};
|
|
59335
59514
|
}
|
|
@@ -59337,10 +59516,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
59337
59516
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
59338
59517
|
const file = loadSessionsFile(path2);
|
|
59339
59518
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
59340
|
-
|
|
59341
|
-
|
|
59519
|
+
mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
|
|
59520
|
+
writeFileSync26(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
59342
59521
|
try {
|
|
59343
|
-
chmodSync3(
|
|
59522
|
+
chmodSync3(dirname35(path2), 448);
|
|
59344
59523
|
chmodSync3(path2, 384);
|
|
59345
59524
|
} catch {
|
|
59346
59525
|
}
|
|
@@ -61940,10 +62119,10 @@ function assertPublicSiteUrl(raw) {
|
|
|
61940
62119
|
if (refusal) throw new Error(refusal);
|
|
61941
62120
|
}
|
|
61942
62121
|
function resolveAll(hostname2) {
|
|
61943
|
-
return new Promise((
|
|
62122
|
+
return new Promise((resolve54, reject) => {
|
|
61944
62123
|
dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
|
|
61945
62124
|
if (err) reject(err);
|
|
61946
|
-
else
|
|
62125
|
+
else resolve54(addresses);
|
|
61947
62126
|
});
|
|
61948
62127
|
});
|
|
61949
62128
|
}
|
|
@@ -61951,13 +62130,13 @@ function withAbort(start, signal, what) {
|
|
|
61951
62130
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
61952
62131
|
const work = start();
|
|
61953
62132
|
if (!signal) return work;
|
|
61954
|
-
return new Promise((
|
|
62133
|
+
return new Promise((resolve54, reject) => {
|
|
61955
62134
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
61956
62135
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
61957
|
-
work.then(
|
|
62136
|
+
work.then(resolve54, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
61958
62137
|
});
|
|
61959
62138
|
}
|
|
61960
|
-
async function pinAddress(url,
|
|
62139
|
+
async function pinAddress(url, resolve54 = resolveAll, signal) {
|
|
61961
62140
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
61962
62141
|
if (ipv4Octets(host)) {
|
|
61963
62142
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -61967,7 +62146,7 @@ async function pinAddress(url, resolve53 = resolveAll, signal) {
|
|
|
61967
62146
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
61968
62147
|
return { address: host, family: 6 };
|
|
61969
62148
|
}
|
|
61970
|
-
const addresses = await withAbort(() =>
|
|
62149
|
+
const addresses = await withAbort(() => resolve54(host), signal, `${host} lookup`);
|
|
61971
62150
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
61972
62151
|
const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
|
|
61973
62152
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -62007,7 +62186,7 @@ function copyIncomingHeaders(headers2) {
|
|
|
62007
62186
|
return out2;
|
|
62008
62187
|
}
|
|
62009
62188
|
function requestOnce(url, pinned, init) {
|
|
62010
|
-
return new Promise((
|
|
62189
|
+
return new Promise((resolve54, reject) => {
|
|
62011
62190
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
62012
62191
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
62013
62192
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -62037,7 +62216,7 @@ function requestOnce(url, pinned, init) {
|
|
|
62037
62216
|
reject(err);
|
|
62038
62217
|
return;
|
|
62039
62218
|
}
|
|
62040
|
-
|
|
62219
|
+
resolve54(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
|
|
62041
62220
|
}
|
|
62042
62221
|
);
|
|
62043
62222
|
req.on("error", reject);
|
|
@@ -63097,8 +63276,8 @@ var init_brand_font = __esm({
|
|
|
63097
63276
|
});
|
|
63098
63277
|
|
|
63099
63278
|
// src/site-analyze/write-artifacts.ts
|
|
63100
|
-
import { mkdirSync as
|
|
63101
|
-
import { join as
|
|
63279
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
|
|
63280
|
+
import { join as join63 } from "node:path";
|
|
63102
63281
|
function attachVeloSources(book, sources, put) {
|
|
63103
63282
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
63104
63283
|
for (const f of book.velo.files) {
|
|
@@ -63253,13 +63432,13 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
63253
63432
|
}
|
|
63254
63433
|
async function writeBusinessBook(result, opts) {
|
|
63255
63434
|
const out2 = opts.outDir;
|
|
63256
|
-
|
|
63257
|
-
|
|
63435
|
+
mkdirSync31(join63(out2, "evidence/pages"), { recursive: true });
|
|
63436
|
+
mkdirSync31(join63(out2, "media/catalog"), { recursive: true });
|
|
63258
63437
|
const files = [];
|
|
63259
63438
|
const put = (rel, body) => {
|
|
63260
|
-
const p =
|
|
63261
|
-
|
|
63262
|
-
|
|
63439
|
+
const p = join63(out2, rel);
|
|
63440
|
+
mkdirSync31(join63(p, ".."), { recursive: true });
|
|
63441
|
+
writeFileSync27(p, body);
|
|
63263
63442
|
files.push(rel);
|
|
63264
63443
|
};
|
|
63265
63444
|
const book = result.book;
|
|
@@ -63352,15 +63531,15 @@ var init_customer_build = __esm({
|
|
|
63352
63531
|
});
|
|
63353
63532
|
|
|
63354
63533
|
// src/site-analyze/apply.ts
|
|
63355
|
-
import { existsSync as
|
|
63356
|
-
import { dirname as
|
|
63534
|
+
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";
|
|
63535
|
+
import { dirname as dirname36, isAbsolute as isAbsolute7, join as join64, resolve as resolve51, sep as sep17 } from "node:path";
|
|
63357
63536
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
63358
63537
|
function unpairedRedirectNote(overlay) {
|
|
63359
63538
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
63360
63539
|
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
63540
|
}
|
|
63362
63541
|
function posix3(p) {
|
|
63363
|
-
return
|
|
63542
|
+
return resolve51(p).replace(/\\/g, "/");
|
|
63364
63543
|
}
|
|
63365
63544
|
function committedShellProvisioning(path2) {
|
|
63366
63545
|
return committedShellFor(posix3(path2));
|
|
@@ -63368,8 +63547,8 @@ function committedShellProvisioning(path2) {
|
|
|
63368
63547
|
function findRepoRoot(cwd) {
|
|
63369
63548
|
let dir = cwd;
|
|
63370
63549
|
for (let i = 0; i < 8; i++) {
|
|
63371
|
-
if (SHELL_NAMES2.some((name) =>
|
|
63372
|
-
const next =
|
|
63550
|
+
if (SHELL_NAMES2.some((name) => existsSync65(join64(dir, shellAppDir(name), "package.json")))) return dir;
|
|
63551
|
+
const next = dirname36(dir);
|
|
63373
63552
|
if (next === dir) break;
|
|
63374
63553
|
dir = next;
|
|
63375
63554
|
}
|
|
@@ -63394,7 +63573,7 @@ function assertNotCommitted(path2, forbidden) {
|
|
|
63394
63573
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
63395
63574
|
);
|
|
63396
63575
|
}
|
|
63397
|
-
if (forbidden &&
|
|
63576
|
+
if (forbidden && resolve51(path2) === resolve51(forbidden)) {
|
|
63398
63577
|
const named = committedShellProvisioning(forbidden);
|
|
63399
63578
|
throw new Error(
|
|
63400
63579
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -63439,36 +63618,36 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
63439
63618
|
}
|
|
63440
63619
|
function buildMergedContract(options) {
|
|
63441
63620
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
63442
|
-
const committedPath =
|
|
63443
|
-
if (!
|
|
63621
|
+
const committedPath = join64(appDir3, "provisioning.json");
|
|
63622
|
+
if (!existsSync65(committedPath)) {
|
|
63444
63623
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
63445
63624
|
}
|
|
63446
|
-
const committed = JSON.parse(
|
|
63625
|
+
const committed = JSON.parse(readFileSync77(committedPath, "utf8"));
|
|
63447
63626
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
63448
63627
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
63449
63628
|
const branding = merged.branding ?? {};
|
|
63450
63629
|
const staged = [];
|
|
63451
63630
|
const contained = (root, rel) => {
|
|
63452
|
-
if (
|
|
63453
|
-
const full =
|
|
63454
|
-
return full.startsWith(
|
|
63631
|
+
if (isAbsolute7(rel)) return void 0;
|
|
63632
|
+
const full = resolve51(root, rel);
|
|
63633
|
+
return full.startsWith(resolve51(root) + sep17) ? full : void 0;
|
|
63455
63634
|
};
|
|
63456
63635
|
const stage = (fromRel, toRel) => {
|
|
63457
63636
|
const from = contained(packageDir, fromRel);
|
|
63458
|
-
const to = contained(
|
|
63459
|
-
if (!from || !to || !
|
|
63637
|
+
const to = contained(join64(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
63638
|
+
if (!from || !to || !existsSync65(from)) return void 0;
|
|
63460
63639
|
let real;
|
|
63461
63640
|
let realRoot;
|
|
63462
63641
|
try {
|
|
63463
|
-
real =
|
|
63464
|
-
realRoot =
|
|
63642
|
+
real = realpathSync10(from);
|
|
63643
|
+
realRoot = realpathSync10(packageDir);
|
|
63465
63644
|
} catch {
|
|
63466
63645
|
return void 0;
|
|
63467
63646
|
}
|
|
63468
|
-
if (!real.startsWith(realRoot +
|
|
63647
|
+
if (!real.startsWith(realRoot + sep17)) return void 0;
|
|
63469
63648
|
try {
|
|
63470
|
-
if (!
|
|
63471
|
-
|
|
63649
|
+
if (!statSync18(real).isFile()) return void 0;
|
|
63650
|
+
mkdirSync32(dirname36(to), { recursive: true });
|
|
63472
63651
|
copyFileSync3(real, to);
|
|
63473
63652
|
} catch {
|
|
63474
63653
|
return void 0;
|
|
@@ -63478,11 +63657,11 @@ function buildMergedContract(options) {
|
|
|
63478
63657
|
};
|
|
63479
63658
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
63480
63659
|
if (icon) branding.appIconPath = icon;
|
|
63481
|
-
const facesPath =
|
|
63482
|
-
if (
|
|
63660
|
+
const facesPath = join64(packageDir, "media/fonts/faces.json");
|
|
63661
|
+
if (existsSync65(facesPath)) {
|
|
63483
63662
|
let faces = [];
|
|
63484
63663
|
try {
|
|
63485
|
-
const parsed = JSON.parse(
|
|
63664
|
+
const parsed = JSON.parse(readFileSync77(facesPath, "utf8"));
|
|
63486
63665
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
63487
63666
|
} catch {
|
|
63488
63667
|
faces = [];
|
|
@@ -63503,11 +63682,11 @@ function buildMergedContract(options) {
|
|
|
63503
63682
|
merged.branding = branding;
|
|
63504
63683
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
63505
63684
|
`;
|
|
63506
|
-
const path2 =
|
|
63507
|
-
|
|
63508
|
-
const localPath =
|
|
63509
|
-
|
|
63510
|
-
|
|
63685
|
+
const path2 = join64(packageDir, "provisioning.contract.json");
|
|
63686
|
+
writeFileSync28(path2, body);
|
|
63687
|
+
const localPath = join64(appDir3, LOCAL_CONTRACT_REL);
|
|
63688
|
+
mkdirSync32(dirname36(localPath), { recursive: true });
|
|
63689
|
+
writeFileSync28(localPath, body);
|
|
63511
63690
|
staged.push(localPath);
|
|
63512
63691
|
return { path: path2, staged };
|
|
63513
63692
|
}
|
|
@@ -63540,10 +63719,10 @@ function catalogTypography(overlay, template) {
|
|
|
63540
63719
|
function staticFaqFor(overlay, overlayPath) {
|
|
63541
63720
|
const own3 = overlay.faq;
|
|
63542
63721
|
if (own3 !== void 0) return deriveStaticFaq(own3);
|
|
63543
|
-
const bookPath =
|
|
63544
|
-
if (!
|
|
63722
|
+
const bookPath = join64(dirname36(resolve51(overlayPath)), "book.json");
|
|
63723
|
+
if (!existsSync65(bookPath)) return void 0;
|
|
63545
63724
|
try {
|
|
63546
|
-
const book = JSON.parse(
|
|
63725
|
+
const book = JSON.parse(readFileSync77(bookPath, "utf8"));
|
|
63547
63726
|
const copy = book?.copy;
|
|
63548
63727
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
63549
63728
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -63554,11 +63733,11 @@ function staticFaqFor(overlay, overlayPath) {
|
|
|
63554
63733
|
}
|
|
63555
63734
|
}
|
|
63556
63735
|
async function applyOverlays(input) {
|
|
63557
|
-
const cwd =
|
|
63736
|
+
const cwd = resolve51(input.cwd);
|
|
63558
63737
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
63559
63738
|
assertKnownShell(shell);
|
|
63560
|
-
const overlay = JSON.parse(
|
|
63561
|
-
const tokens = JSON.parse(
|
|
63739
|
+
const overlay = JSON.parse(readFileSync77(input.overlayPath, "utf8"));
|
|
63740
|
+
const tokens = JSON.parse(readFileSync77(input.tokensPath, "utf8"));
|
|
63562
63741
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
63563
63742
|
if (faq !== void 0) overlay.faq = faq;
|
|
63564
63743
|
const wrote = [];
|
|
@@ -63570,15 +63749,15 @@ async function applyOverlays(input) {
|
|
|
63570
63749
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
63571
63750
|
);
|
|
63572
63751
|
}
|
|
63573
|
-
const appDir3 =
|
|
63574
|
-
const committedPath =
|
|
63575
|
-
const committedSite =
|
|
63752
|
+
const appDir3 = join64(repoRoot2, shellAppDir(shell));
|
|
63753
|
+
const committedPath = join64(appDir3, "provisioning.json");
|
|
63754
|
+
const committedSite = existsSync65(committedPath) ? JSON.parse(readFileSync77(committedPath, "utf8")).site : void 0;
|
|
63576
63755
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
63577
63756
|
throw new Error(
|
|
63578
63757
|
`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
63758
|
);
|
|
63580
63759
|
}
|
|
63581
|
-
const packageDir =
|
|
63760
|
+
const packageDir = dirname36(resolve51(input.overlayPath));
|
|
63582
63761
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
|
|
63583
63762
|
wrote.push(...staged);
|
|
63584
63763
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -63599,22 +63778,22 @@ async function applyOverlays(input) {
|
|
|
63599
63778
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
63600
63779
|
};
|
|
63601
63780
|
}
|
|
63602
|
-
const pkgProv =
|
|
63781
|
+
const pkgProv = join64(cwd, "provisioning.json");
|
|
63603
63782
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
63604
63783
|
let packageFaq = faq;
|
|
63605
|
-
if (
|
|
63606
|
-
const cur = JSON.parse(
|
|
63784
|
+
if (existsSync65(pkgProv)) {
|
|
63785
|
+
const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
|
|
63607
63786
|
const merged = deepMerge4(cur, overlay);
|
|
63608
63787
|
packageFaq = merged.faq;
|
|
63609
|
-
|
|
63788
|
+
writeFileSync28(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
63610
63789
|
wrote.push(pkgProv);
|
|
63611
63790
|
} else {
|
|
63612
|
-
|
|
63791
|
+
writeFileSync28(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
63613
63792
|
wrote.push(pkgProv);
|
|
63614
63793
|
}
|
|
63615
|
-
const pkgTokens =
|
|
63616
|
-
if (
|
|
63617
|
-
const cur = JSON.parse(
|
|
63794
|
+
const pkgTokens = join64(cwd, "tokens.json");
|
|
63795
|
+
if (existsSync65(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
63796
|
+
const cur = JSON.parse(readFileSync77(pkgTokens, "utf8"));
|
|
63618
63797
|
let tokensIn = tokens;
|
|
63619
63798
|
if (tokens.typography) {
|
|
63620
63799
|
const fonts = catalogTypography(tokens.typography, cur.typography);
|
|
@@ -63635,13 +63814,13 @@ async function applyOverlays(input) {
|
|
|
63635
63814
|
if (primary && glow && typeof glow.color === "string") glow.color = primary;
|
|
63636
63815
|
stripBrandFromIdiom(merged);
|
|
63637
63816
|
}
|
|
63638
|
-
|
|
63817
|
+
writeFileSync28(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
63639
63818
|
wrote.push(pkgTokens);
|
|
63640
63819
|
}
|
|
63641
63820
|
const homeAction = homeRefreshActionId(shell);
|
|
63642
|
-
const homeSrc =
|
|
63643
|
-
if (homeAction &&
|
|
63644
|
-
const prev =
|
|
63821
|
+
const homeSrc = join64(cwd, "dev/index.ts");
|
|
63822
|
+
if (homeAction && existsSync65(homeSrc)) {
|
|
63823
|
+
const prev = readFileSync77(homeSrc, "utf8");
|
|
63645
63824
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
63646
63825
|
let next = patched.src;
|
|
63647
63826
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -63665,20 +63844,20 @@ async function applyOverlays(input) {
|
|
|
63665
63844
|
}
|
|
63666
63845
|
}
|
|
63667
63846
|
if (next !== prev) {
|
|
63668
|
-
|
|
63847
|
+
writeFileSync28(homeSrc, next);
|
|
63669
63848
|
wrote.push(homeSrc);
|
|
63670
63849
|
}
|
|
63671
63850
|
if (patched.unparsed) {
|
|
63672
63851
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
63673
63852
|
}
|
|
63674
63853
|
}
|
|
63675
|
-
if (!input.iconPath || !
|
|
63676
|
-
const book = input.iconPath ?
|
|
63854
|
+
if (!input.iconPath || !existsSync65(input.iconPath)) {
|
|
63855
|
+
const book = input.iconPath ? dirname36(dirname36(resolve51(input.iconPath))) : void 0;
|
|
63677
63856
|
notes.push(
|
|
63678
63857
|
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
63858
|
);
|
|
63680
63859
|
}
|
|
63681
|
-
if (input.iconPath &&
|
|
63860
|
+
if (input.iconPath && existsSync65(input.iconPath)) {
|
|
63682
63861
|
try {
|
|
63683
63862
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
63684
63863
|
wrote.push(...installed.wrote);
|
|
@@ -64792,10 +64971,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
|
|
|
64792
64971
|
}
|
|
64793
64972
|
function createPromiseCallback(cb) {
|
|
64794
64973
|
let callback;
|
|
64795
|
-
let
|
|
64974
|
+
let resolve54;
|
|
64796
64975
|
let reject;
|
|
64797
64976
|
const promise = new Promise((_resolve, _reject) => {
|
|
64798
|
-
|
|
64977
|
+
resolve54 = _resolve;
|
|
64799
64978
|
reject = _reject;
|
|
64800
64979
|
});
|
|
64801
64980
|
if (typeof cb === "function") {
|
|
@@ -64811,7 +64990,7 @@ function createPromiseCallback(cb) {
|
|
|
64811
64990
|
callback = (err, result) => {
|
|
64812
64991
|
try {
|
|
64813
64992
|
if (err) reject(err);
|
|
64814
|
-
else
|
|
64993
|
+
else resolve54(result);
|
|
64815
64994
|
} catch (e) {
|
|
64816
64995
|
reject(e instanceof Error ? e : new Error());
|
|
64817
64996
|
}
|
|
@@ -67899,14 +68078,14 @@ async function runSiteFunction(opts) {
|
|
|
67899
68078
|
}
|
|
67900
68079
|
if (opts.op === "publish") {
|
|
67901
68080
|
const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
|
|
67902
|
-
const
|
|
68081
|
+
const ok2 = httpOk(snap.rev) && httpOk(snap.live);
|
|
67903
68082
|
return {
|
|
67904
68083
|
...base,
|
|
67905
|
-
ok,
|
|
68084
|
+
ok: ok2,
|
|
67906
68085
|
revision: snap.revision,
|
|
67907
68086
|
codeAppId: snap.codeAppId,
|
|
67908
68087
|
publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
|
|
67909
|
-
error:
|
|
68088
|
+
error: ok2 ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
|
|
67910
68089
|
};
|
|
67911
68090
|
}
|
|
67912
68091
|
const { id, listed } = await withGrid(fetchImpl, opts.token, opts.msid, opts.siteUrl);
|
|
@@ -68001,12 +68180,12 @@ async function invokeAndReport(fetchImpl, opts, base, name, method) {
|
|
|
68001
68180
|
await new Promise((res) => setTimeout(res, 2500));
|
|
68002
68181
|
hit = await tryInvoke();
|
|
68003
68182
|
}
|
|
68004
|
-
const
|
|
68183
|
+
const ok2 = httpOk(hit.r);
|
|
68005
68184
|
return {
|
|
68006
68185
|
...base,
|
|
68007
|
-
ok,
|
|
68186
|
+
ok: ok2,
|
|
68008
68187
|
invoke: { url: hit.url, status: hit.r.status, body: hit.r.json ?? snippet2(hit.r.text) },
|
|
68009
|
-
error:
|
|
68188
|
+
error: ok2 ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
|
|
68010
68189
|
};
|
|
68011
68190
|
}
|
|
68012
68191
|
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;
|
|
@@ -68034,14 +68213,19 @@ __export(cli_exports, {
|
|
|
68034
68213
|
APPLY_NEEDS_CLIENT: () => APPLY_NEEDS_CLIENT,
|
|
68035
68214
|
REDIRECT_NEEDS_CLIENT: () => REDIRECT_NEEDS_CLIENT,
|
|
68036
68215
|
SITE_FUNCTION_USAGE: () => SITE_FUNCTION_USAGE,
|
|
68216
|
+
applyNeedsClient: () => applyNeedsClient,
|
|
68037
68217
|
assetFetchFor: () => assetFetchFor,
|
|
68038
68218
|
noteWithWarnings: () => noteWithWarnings,
|
|
68039
68219
|
ownerSiteFor: () => ownerSiteFor,
|
|
68040
68220
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
68041
68221
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
68042
68222
|
});
|
|
68043
|
-
import { readFileSync as
|
|
68044
|
-
import { resolve as
|
|
68223
|
+
import { readFileSync as readFileSync78 } from "node:fs";
|
|
68224
|
+
import { resolve as resolve52 } from "node:path";
|
|
68225
|
+
function applyNeedsClient(shell) {
|
|
68226
|
+
if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
|
|
68227
|
+
return !isSiteShell(shell);
|
|
68228
|
+
}
|
|
68045
68229
|
function assetFetchFor(_opts) {
|
|
68046
68230
|
return pinnedFetch2;
|
|
68047
68231
|
}
|
|
@@ -68054,14 +68238,14 @@ function ownerSiteFor(opts, env = process.env) {
|
|
|
68054
68238
|
async function runSiteAnalyze(opts) {
|
|
68055
68239
|
if (opts.shell !== void 0) assertKnownShell(opts.shell);
|
|
68056
68240
|
if (!opts.clientId?.trim()) {
|
|
68057
|
-
if (opts.apply) throw Object.assign(new Error(APPLY_NEEDS_CLIENT), { exit: 2 });
|
|
68241
|
+
if (opts.apply && applyNeedsClient(opts.shell)) throw Object.assign(new Error(APPLY_NEEDS_CLIENT), { exit: 2 });
|
|
68058
68242
|
if (opts.redirectUri?.trim()) throw Object.assign(new Error(REDIRECT_NEEDS_CLIENT), { exit: 2 });
|
|
68059
68243
|
}
|
|
68060
68244
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
68061
68245
|
const assetFetch = assetFetchFor(opts);
|
|
68062
68246
|
const siteFetch = guardedSiteFetch;
|
|
68063
68247
|
const cwd = opts.cwd ?? process.cwd();
|
|
68064
|
-
const outDir =
|
|
68248
|
+
const outDir = resolve52(cwd, opts.outDir ?? ".himi/business-book");
|
|
68065
68249
|
let ownerAuth;
|
|
68066
68250
|
let msid;
|
|
68067
68251
|
const ownerSite = ownerSiteFor(opts);
|
|
@@ -68089,7 +68273,10 @@ async function runSiteAnalyze(opts) {
|
|
|
68089
68273
|
try {
|
|
68090
68274
|
const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look });
|
|
68091
68275
|
result.provisioningOverlay.site = derived.site;
|
|
68092
|
-
|
|
68276
|
+
const warnings2 = (result.warnings ?? []).map(
|
|
68277
|
+
(w) => !opts.clientId?.trim() && w.startsWith("no --client-id:") ? `no --client-id: fine for --shell ${opts.shell} \u2014 a site shell binds no client, so --apply works without one. Only the vertical probes were skipped, so the catalog has no counts.` : w
|
|
68278
|
+
);
|
|
68279
|
+
result.warnings = [...warnings2, ...derived.notes];
|
|
68093
68280
|
} catch (e) {
|
|
68094
68281
|
result.warnings = [
|
|
68095
68282
|
...result.warnings ?? [],
|
|
@@ -68113,9 +68300,9 @@ async function runSiteAnalyze(opts) {
|
|
|
68113
68300
|
if (opts.apply) {
|
|
68114
68301
|
applied = await applyOverlays({
|
|
68115
68302
|
cwd,
|
|
68116
|
-
overlayPath:
|
|
68117
|
-
tokensPath:
|
|
68118
|
-
iconPath:
|
|
68303
|
+
overlayPath: resolve52(outDir, "provisioning.overlay.json"),
|
|
68304
|
+
tokensPath: resolve52(outDir, "tokens.overlay.json"),
|
|
68305
|
+
iconPath: resolve52(outDir, "media/icon.png"),
|
|
68119
68306
|
shell: opts.shell
|
|
68120
68307
|
});
|
|
68121
68308
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -68151,8 +68338,8 @@ async function runSiteFunctionCli(opts) {
|
|
|
68151
68338
|
const token = opts.token ?? await siteToken(msid);
|
|
68152
68339
|
let source;
|
|
68153
68340
|
if (opts.sourcePath) {
|
|
68154
|
-
const p =
|
|
68155
|
-
source =
|
|
68341
|
+
const p = resolve52(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
68342
|
+
source = readFileSync78(p, "utf8");
|
|
68156
68343
|
}
|
|
68157
68344
|
let body;
|
|
68158
68345
|
if (opts.bodyRaw != null) {
|
|
@@ -68207,7 +68394,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
68207
68394
|
cached2 = fromEnv;
|
|
68208
68395
|
return fromEnv;
|
|
68209
68396
|
}
|
|
68210
|
-
const token = await new Promise((
|
|
68397
|
+
const token = await new Promise((resolve54, reject) => {
|
|
68211
68398
|
let child;
|
|
68212
68399
|
try {
|
|
68213
68400
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -68236,7 +68423,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
68236
68423
|
const scan = (d) => {
|
|
68237
68424
|
out2 += String(d);
|
|
68238
68425
|
const m = out2.match(TOKEN_RE2);
|
|
68239
|
-
if (m) done(() =>
|
|
68426
|
+
if (m) done(() => resolve54(m[0]));
|
|
68240
68427
|
};
|
|
68241
68428
|
child.stdout?.on("data", scan);
|
|
68242
68429
|
child.stderr?.on("data", scan);
|
|
@@ -68413,7 +68600,7 @@ __export(site_create_exports, {
|
|
|
68413
68600
|
runSiteList: () => runSiteList,
|
|
68414
68601
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
68415
68602
|
});
|
|
68416
|
-
import { existsSync as
|
|
68603
|
+
import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync29 } from "node:fs";
|
|
68417
68604
|
import { resolve as resolvePath2 } from "node:path";
|
|
68418
68605
|
function oauthClientName(projectName) {
|
|
68419
68606
|
return `${projectName} client`;
|
|
@@ -68562,7 +68749,7 @@ async function runSiteCreate(opts) {
|
|
|
68562
68749
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
68563
68750
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
68564
68751
|
}
|
|
68565
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
68752
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync29 }) {
|
|
68566
68753
|
const msid = binding2.siteId;
|
|
68567
68754
|
const path2 = resolvePath2(target);
|
|
68568
68755
|
const committed = committedShellProvisioning(path2);
|
|
@@ -69235,12 +69422,12 @@ var init_context = __esm({
|
|
|
69235
69422
|
});
|
|
69236
69423
|
|
|
69237
69424
|
// src/cli.ts
|
|
69238
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
69425
|
+
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
69426
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
69240
69427
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
69241
69428
|
import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
|
|
69242
69429
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
69243
|
-
import { join as
|
|
69430
|
+
import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
|
|
69244
69431
|
import { fileURLToPath as fileURLToPath26 } from "node:url";
|
|
69245
69432
|
|
|
69246
69433
|
// ../serve-cli/src/client.ts
|
|
@@ -69981,7 +70168,7 @@ async function browserLogin(opts) {
|
|
|
69981
70168
|
const log = opts.log ?? (() => {
|
|
69982
70169
|
});
|
|
69983
70170
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
69984
|
-
return await new Promise((
|
|
70171
|
+
return await new Promise((resolve54, reject) => {
|
|
69985
70172
|
let settled = false;
|
|
69986
70173
|
let loginUrl = "";
|
|
69987
70174
|
const server = createServer();
|
|
@@ -70045,7 +70232,7 @@ async function browserLogin(opts) {
|
|
|
70045
70232
|
return;
|
|
70046
70233
|
}
|
|
70047
70234
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
|
|
70048
|
-
finish2(() =>
|
|
70235
|
+
finish2(() => resolve54({ token, loginUrl }));
|
|
70049
70236
|
});
|
|
70050
70237
|
});
|
|
70051
70238
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -71375,8 +71562,8 @@ var str8 = (v) => typeof v === "string" ? v : void 0;
|
|
|
71375
71562
|
var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
71376
71563
|
function embeddedTemplateCatalog() {
|
|
71377
71564
|
return availableTemplates().map((name) => {
|
|
71378
|
-
const path2 =
|
|
71379
|
-
const meta = JSON.parse(
|
|
71565
|
+
const path2 = join65(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
71566
|
+
const meta = JSON.parse(readFileSync80(path2, "utf8"));
|
|
71380
71567
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
71381
71568
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
71382
71569
|
}
|
|
@@ -71934,7 +72121,8 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
71934
72121
|
a brandable shell's content package. --url alone is the
|
|
71935
72122
|
visitor-only pass (published pages, look, copy); --client-id
|
|
71936
72123
|
adds the vertical catalog counts and the app binding, and
|
|
71937
|
-
--apply requires it
|
|
72124
|
+
--apply requires it (not for a site shell, which binds no
|
|
72125
|
+
client). --shell takes the same
|
|
71938
72126
|
names 'himi dist --shell' does; default branded-lite.
|
|
71939
72127
|
A SITE shell (brandy) also derives the site's page map
|
|
71940
72128
|
(tabs/drawer from its menu) into the overlay's \`site\`
|
|
@@ -72049,7 +72237,7 @@ var COMMANDS = [
|
|
|
72049
72237
|
{ name: "login", summary: "obtain a scoped serve-control token from Wix identity and store it in ~/.himalaya/serve-targets.json (so push/promote need no hand-pasted token). Three modes: --browser (your own Wix account, no VPN/BO), --wix (HEADLESS \u2014 the machine's own Wix CLI credential; the mode a CI pod or agent container can satisfy), --dpx (Wix employee, reads ~/.dpx/session/token). RFC 0026 WS3.", required: "[--browser|--wix|--dpx] [--target <t>] [--issue-url <url>]" },
|
|
72050
72238
|
{ name: "logout", summary: "remove the stored control token for a target", required: "[--target <t>]" },
|
|
72051
72239
|
{ name: "notify", summary: "`setup` optionally configures Branded/Ping from local customer key files; `status --refresh` reads live backend readiness. Setup may be deferred while building. These use serve-control and require owner plus Wix account authentication. `send`, `tokens`, `doctor`: send a REAL push notification to registered devices (RFC 0036 WS5) \u2014 APNs .p8 over HTTP/2 for iOS, FCM v1 for Android. `send` targets one device (--token / --device <registry id>) or fans out to the whole app (--all), reporting a per-device result; a token the provider says is uninstalled (APNs 410 Unregistered / FCM UNREGISTERED) is auto-disabled, while a merely wrong one (BadDeviceToken \u2014 usually a sandbox/production mismatch) is recorded and left enabled. `tokens` lists the registry. `doctor` reports which credentials resolve and which sender each platform picks. Talks to the admin-server via --admin-url/HIMALAYA_ADMIN_URL, authenticated with --admin-session/HIMALAYA_ADMIN_SESSION. `send --provider ping` is the hosted alternative: the serve plane sends one test notification to one site member through Ping as Himalaya, with owner login instead of provider keys, and reports acceptance, never delivery. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send --provider ping [--content <dir>] [--app <a>] [--site <msid>] --member-email <email> --title <s> [--body <s>] --link <url> [--request-id <uuid>] [--dry-run] [--json] | send|tokens|doctor [--app <a>] [--token <t> | --device <id> | --all] [--title <s>] [--body <s>] [--link <url>] [--platform ios|android] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]" },
|
|
72052
|
-
{ name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no URL/browser and never uploads or applies anything. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell; `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--json] | analyze --url <https> [--client-id <id>] [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
|
|
72240
|
+
{ name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no URL/browser and never uploads or applies anything. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell (a site shell needs no `--client-id`: it is visitor-only and binds no client); `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--json] | analyze --url <https> [--client-id <id>] [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
|
|
72053
72241
|
{ name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
|
|
72054
72242
|
{ name: "upgrade", summary: "install the newest published CLI (`npm i -g @wix/himalaya-cli@latest`) and report what moved. This is the explicit door: himi also updates itself when the running build is more than a week old \u2014 unattended it just does it and re-runs your command, at a terminal it asks first \u2014 and `HIMI_NO_UPDATE_CHECK=1` turns that off, leaving this command as the way to catch up. Reports `unchanged` rather than claiming success when npm exits 0 without moving the version, which is what a registry mirror serving its own pinned copy looks like.", required: "[--json]" },
|
|
72055
72243
|
{ name: "push", summary: "lint + build + publish a release (default --draft: servable via ?release= but NOT live). REFUSES to publish on any error unless --force; --strict promotes warnings. Prints preview + agent-context links. A successful draft push also rebuilds the making-of (.himi/making-of.html, local and offline) and names it as `reel` \u2014 the file to hand the owner beside the preview link. Its postcard carries the home shot only when that shot is newer than the last source edit; otherwise the postcard says why and names `himi render <home> --png`, and the envelope's `postcardPicture: {skipped, render}` leads next[] with that render (the push never renders it itself). The published slug is NAMESPACED per owner \u2014 `<ownerPrefix>.<name>`, composed offline from the control token's ownerPrefix claim, so the CLI and the server derive the identical string and himalaya.content.json is NOT rewritten (a legacy token with no ownerPrefix publishes the declared name unchanged). An app claimed BEFORE namespacing is stored under its FLAT slug, so the claim route answers `alreadyYours` naming that slug and the push adopts it \u2014 reported as `adoptedSlug`, since it is the one case where the published `app` differs from what the declared name composes to. `--no-claim` skips the route that knows this, so a pre-namespacing app pushed with it still fails 403. --visibility public|unlisted decides whether /v1/apps + the Himi Player picker LIST the app (also declarable as `visibility` in himalaya.content.json; omitted, a brand-new app defaults to unlisted \u2014 share by link \u2014 and an existing setting is kept). --account-id names which account owns the app when your Wix session resolves to several (the auto-claim of a brand-new slug cannot guess \u2014 without it a multi-account caller is told to name one). An unforced push of a release that carries SCREENS also refuses when `.himi/ux-audit.json` holds no mobile-UX drive recorded against that release id, or holds one that FAILED (#2955) \u2014 a published draft IS the owner-private preview a customer is handed; `himi ux record` clears it and `--force` overrides it, which the success envelope then says out loud. `--only <selector>` publishes ONLY the named items as a release derived from the app's live release (or `--from-release <id>`), running the identical build + lint gate and simply publishing less; it requires an explicit `--draft` or `--live` because a partial publish has no safe default, never claims a slug, and carries neither attestation nor a source archive (both named in the output). Selectors are comma-separated in ONE `--only`: `changed` (every item whose bytes differ from the base), `screen:<id|glob>`, `bundle:<name>`, `tokens`, `app-config` \u2014 a selected screen drags its logic bundle and a selected bundle drags the screens that reference it, or the bytes land under a key nothing reads.", required: "[--content <dir>] [--draft] [--live] [--force] [--strict] [--label] [--notes] [--visibility public|unlisted] [--no-claim] [--account-id <id>] [--only <selector>] [--from-release <id>] [--accept-regressions] [--accept-partial] [--app <slug>] (--control-token)" },
|
|
@@ -72058,7 +72246,7 @@ var COMMANDS = [
|
|
|
72058
72246
|
{ 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
72247
|
{ 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
72248
|
{ 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>]" },
|
|
72249
|
+
{ 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
72250
|
{ 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
72251
|
{ 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
72252
|
{ 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 +72278,7 @@ var COMMANDS = [
|
|
|
72090
72278
|
];
|
|
72091
72279
|
function cliVersion() {
|
|
72092
72280
|
try {
|
|
72093
|
-
return JSON.parse(
|
|
72281
|
+
return JSON.parse(readFileSync80(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
72094
72282
|
} catch {
|
|
72095
72283
|
return "unknown";
|
|
72096
72284
|
}
|
|
@@ -72141,16 +72329,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
|
|
|
72141
72329
|
}
|
|
72142
72330
|
var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
|
|
72143
72331
|
function execNpmConfig(file, args, options) {
|
|
72144
|
-
return new Promise((
|
|
72145
|
-
execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) :
|
|
72332
|
+
return new Promise((resolve54, reject) => {
|
|
72333
|
+
execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve54(String(stdout)));
|
|
72146
72334
|
});
|
|
72147
72335
|
}
|
|
72148
72336
|
var npmScopedWixRegistry = createScopedRegistryResolver();
|
|
72149
72337
|
async function scopedRegistryBefore(lookup2, deadline) {
|
|
72150
72338
|
let cancel = () => {
|
|
72151
72339
|
};
|
|
72152
|
-
const expired = new Promise((
|
|
72153
|
-
const timer = setTimeout(() =>
|
|
72340
|
+
const expired = new Promise((resolve54) => {
|
|
72341
|
+
const timer = setTimeout(() => resolve54(void 0), Math.max(0, deadline - Date.now()));
|
|
72154
72342
|
cancel = () => clearTimeout(timer);
|
|
72155
72343
|
});
|
|
72156
72344
|
try {
|
|
@@ -72208,18 +72396,18 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
72208
72396
|
}
|
|
72209
72397
|
function packageVersion(path2) {
|
|
72210
72398
|
try {
|
|
72211
|
-
const version2 = JSON.parse(
|
|
72399
|
+
const version2 = JSON.parse(readFileSync80(path2, "utf8")).version;
|
|
72212
72400
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
72213
72401
|
} catch {
|
|
72214
72402
|
return void 0;
|
|
72215
72403
|
}
|
|
72216
72404
|
}
|
|
72217
72405
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
72218
|
-
let dir =
|
|
72406
|
+
let dir = resolve53(fromDir);
|
|
72219
72407
|
for (; ; ) {
|
|
72220
|
-
const version2 = packageVersion(
|
|
72408
|
+
const version2 = packageVersion(join65(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
72221
72409
|
if (version2) return { version: version2, source: "local" };
|
|
72222
|
-
const parent =
|
|
72410
|
+
const parent = dirname37(dir);
|
|
72223
72411
|
if (parent === dir) break;
|
|
72224
72412
|
dir = parent;
|
|
72225
72413
|
}
|
|
@@ -72227,7 +72415,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
72227
72415
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
72228
72416
|
try {
|
|
72229
72417
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
72230
|
-
const version2 = root ? packageVersion(
|
|
72418
|
+
const version2 = root ? packageVersion(join65(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
72231
72419
|
return version2 ? { version: version2, source: "global" } : {};
|
|
72232
72420
|
} catch {
|
|
72233
72421
|
return {};
|
|
@@ -72274,11 +72462,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
72274
72462
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
72275
72463
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
72276
72464
|
function updateCachePath(env = process.env) {
|
|
72277
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
72465
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join65(homedir7(), ".himalaya", "update-check.json");
|
|
72278
72466
|
}
|
|
72279
72467
|
function readUpdateCache(path2) {
|
|
72280
72468
|
try {
|
|
72281
|
-
const parsed = JSON.parse(
|
|
72469
|
+
const parsed = JSON.parse(readFileSync80(path2, "utf8"));
|
|
72282
72470
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
72283
72471
|
} catch {
|
|
72284
72472
|
return {};
|
|
@@ -72286,8 +72474,8 @@ function readUpdateCache(path2) {
|
|
|
72286
72474
|
}
|
|
72287
72475
|
function writeUpdateCache(path2, cache) {
|
|
72288
72476
|
try {
|
|
72289
|
-
|
|
72290
|
-
|
|
72477
|
+
mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
|
|
72478
|
+
writeFileSync30(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
72291
72479
|
} catch {
|
|
72292
72480
|
}
|
|
72293
72481
|
}
|
|
@@ -72347,12 +72535,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
|
|
|
72347
72535
|
},
|
|
72348
72536
|
installedVersion: () => {
|
|
72349
72537
|
const root = globalNodeModulesRoot();
|
|
72350
|
-
return root ? packageVersion(
|
|
72538
|
+
return root ? packageVersion(join65(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
72351
72539
|
},
|
|
72352
72540
|
reexec: (argv) => {
|
|
72353
72541
|
const root = globalNodeModulesRoot();
|
|
72354
|
-
const entry = root ?
|
|
72355
|
-
if (!entry || !
|
|
72542
|
+
const entry = root ? join65(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
72543
|
+
if (!entry || !existsSync67(entry)) return void 0;
|
|
72356
72544
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
72357
72545
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
72358
72546
|
stdio: "inherit",
|
|
@@ -72399,7 +72587,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
72399
72587
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
72400
72588
|
let content;
|
|
72401
72589
|
try {
|
|
72402
|
-
content =
|
|
72590
|
+
content = readFileSync80(path2, "utf8");
|
|
72403
72591
|
} catch {
|
|
72404
72592
|
continue;
|
|
72405
72593
|
}
|
|
@@ -72407,7 +72595,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
72407
72595
|
let since = stamped;
|
|
72408
72596
|
if (!Number.isFinite(since)) {
|
|
72409
72597
|
try {
|
|
72410
|
-
since =
|
|
72598
|
+
since = statSync19(path2).mtimeMs;
|
|
72411
72599
|
} catch {
|
|
72412
72600
|
continue;
|
|
72413
72601
|
}
|
|
@@ -72422,14 +72610,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72422
72610
|
const mine = lockStamp(now);
|
|
72423
72611
|
const readLock = (path2) => {
|
|
72424
72612
|
try {
|
|
72425
|
-
return
|
|
72613
|
+
return readFileSync80(path2, "utf8");
|
|
72426
72614
|
} catch {
|
|
72427
72615
|
return void 0;
|
|
72428
72616
|
}
|
|
72429
72617
|
};
|
|
72430
72618
|
const tryCreate = (path2) => {
|
|
72431
72619
|
try {
|
|
72432
|
-
|
|
72620
|
+
writeFileSync30(path2, mine, { flag: "wx", mode: 384 });
|
|
72433
72621
|
return true;
|
|
72434
72622
|
} catch {
|
|
72435
72623
|
return false;
|
|
@@ -72437,13 +72625,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72437
72625
|
};
|
|
72438
72626
|
const removeIfMine = (path2) => {
|
|
72439
72627
|
try {
|
|
72440
|
-
if (readLock(path2) === mine)
|
|
72628
|
+
if (readLock(path2) === mine) rmSync16(path2, { force: true });
|
|
72441
72629
|
} catch {
|
|
72442
72630
|
}
|
|
72443
72631
|
};
|
|
72444
72632
|
const release = () => removeIfMine(lockPath);
|
|
72445
72633
|
try {
|
|
72446
|
-
|
|
72634
|
+
mkdirSync33(dirname37(lockPath), { recursive: true, mode: 448 });
|
|
72447
72635
|
} catch {
|
|
72448
72636
|
return () => {
|
|
72449
72637
|
};
|
|
@@ -72460,7 +72648,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72460
72648
|
hooks.underBreakLock?.();
|
|
72461
72649
|
if (current === void 0) return tryCreate(lockPath) ? release : void 0;
|
|
72462
72650
|
if (!isAbandoned(current)) return void 0;
|
|
72463
|
-
|
|
72651
|
+
rmSync16(lockPath, { force: true });
|
|
72464
72652
|
return tryCreate(lockPath) ? release : void 0;
|
|
72465
72653
|
} finally {
|
|
72466
72654
|
removeIfMine(breakPath);
|
|
@@ -72556,7 +72744,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
|
|
|
72556
72744
|
return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
|
|
72557
72745
|
};
|
|
72558
72746
|
return async (dir, opts = {}) => {
|
|
72559
|
-
const argv = ["validate", "--content",
|
|
72747
|
+
const argv = ["validate", "--content", resolve53(dir), "--strict", "--skip-version-check"];
|
|
72560
72748
|
if (!opts.fresh) {
|
|
72561
72749
|
const out2 = [];
|
|
72562
72750
|
const err = [];
|
|
@@ -73014,9 +73202,9 @@ function executableOnPath(name, env = process.env) {
|
|
|
73014
73202
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
73015
73203
|
for (const dir of entries) {
|
|
73016
73204
|
for (const suffix of suffixes) {
|
|
73017
|
-
const candidate =
|
|
73205
|
+
const candidate = join65(dir, `${name}${suffix}`);
|
|
73018
73206
|
try {
|
|
73019
|
-
if (!
|
|
73207
|
+
if (!statSync19(candidate).isFile()) continue;
|
|
73020
73208
|
if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
|
|
73021
73209
|
return true;
|
|
73022
73210
|
} catch {
|
|
@@ -73063,9 +73251,9 @@ function buildDoctorReport(input) {
|
|
|
73063
73251
|
const versionSkew = versions?.cli.status === "outdated" || sdkSkew;
|
|
73064
73252
|
const hostRefused = auth.controlTokenStatus === "refused";
|
|
73065
73253
|
const staleToken = auth.controlTokenPresent === true && auth.controlToken === false && !hostRefused;
|
|
73066
|
-
const
|
|
73254
|
+
const ok2 = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
|
|
73067
73255
|
return {
|
|
73068
|
-
ok,
|
|
73256
|
+
ok: ok2,
|
|
73069
73257
|
target,
|
|
73070
73258
|
version: version2,
|
|
73071
73259
|
dataPlane: { ...data, note: "public Wix APIs \u2014 reachable off-VPN" },
|
|
@@ -73123,7 +73311,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
73123
73311
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
73124
73312
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
73125
73313
|
const iosYmlPath = iosProjectYml2(app);
|
|
73126
|
-
const iosYml =
|
|
73314
|
+
const iosYml = existsSync67(iosYmlPath) ? readFileSync80(iosYmlPath, "utf8") : "";
|
|
73127
73315
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
73128
73316
|
if (!optedIn) {
|
|
73129
73317
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -73137,14 +73325,14 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
73137
73325
|
}
|
|
73138
73326
|
function readConfigSource(dir) {
|
|
73139
73327
|
try {
|
|
73140
|
-
return
|
|
73328
|
+
return readFileSync80(join65(dir, "config.ts"), "utf8");
|
|
73141
73329
|
} catch {
|
|
73142
73330
|
return null;
|
|
73143
73331
|
}
|
|
73144
73332
|
}
|
|
73145
73333
|
function writePngFile(path2, base64) {
|
|
73146
|
-
|
|
73147
|
-
|
|
73334
|
+
mkdirSync33(dirname37(path2), { recursive: true });
|
|
73335
|
+
writeFileSync30(path2, Buffer.from(base64, "base64"));
|
|
73148
73336
|
return path2;
|
|
73149
73337
|
}
|
|
73150
73338
|
async function seedAgentFilesFor(dir, flags, mode = "init") {
|
|
@@ -73172,8 +73360,8 @@ function keptPlan(kept) {
|
|
|
73172
73360
|
return note ? { kept, note } : {};
|
|
73173
73361
|
}
|
|
73174
73362
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
73175
|
-
const dir =
|
|
73176
|
-
if (
|
|
73363
|
+
const dir = resolve53(parentDir, name);
|
|
73364
|
+
if (existsSync67(join65(dir, "himalaya.content.json"))) {
|
|
73177
73365
|
throw new Error(`content package already exists at ${dir}`);
|
|
73178
73366
|
}
|
|
73179
73367
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -73185,7 +73373,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
|
73185
73373
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
73186
73374
|
}
|
|
73187
73375
|
function contentDir(flags) {
|
|
73188
|
-
return
|
|
73376
|
+
return resolve53(str8(flags.content) ?? process.cwd());
|
|
73189
73377
|
}
|
|
73190
73378
|
function renameRestoredSource(restored, declaredApp, renamed) {
|
|
73191
73379
|
const text8 = {};
|
|
@@ -73203,7 +73391,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
|
|
|
73203
73391
|
function symlinkDestinationIssue(dest) {
|
|
73204
73392
|
let kind;
|
|
73205
73393
|
try {
|
|
73206
|
-
kind =
|
|
73394
|
+
kind = lstatSync14(dest);
|
|
73207
73395
|
} catch {
|
|
73208
73396
|
return null;
|
|
73209
73397
|
}
|
|
@@ -73216,11 +73404,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
73216
73404
|
function restoreDestinationIssue(dest, force) {
|
|
73217
73405
|
const link = symlinkDestinationIssue(dest);
|
|
73218
73406
|
if (link) return link;
|
|
73219
|
-
if (!
|
|
73220
|
-
if (!
|
|
73407
|
+
if (!existsSync67(dest)) return null;
|
|
73408
|
+
if (!statSync19(dest).isDirectory()) {
|
|
73221
73409
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
73222
73410
|
}
|
|
73223
|
-
if (
|
|
73411
|
+
if (readdirSync31(dest).length > 0 && !force) {
|
|
73224
73412
|
return {
|
|
73225
73413
|
error: `${dest} already exists and is not empty`,
|
|
73226
73414
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -73229,10 +73417,10 @@ function restoreDestinationIssue(dest, force) {
|
|
|
73229
73417
|
return null;
|
|
73230
73418
|
}
|
|
73231
73419
|
function isHimalayaMonorepoCheckout(start) {
|
|
73232
|
-
let dir =
|
|
73420
|
+
let dir = resolve53(start);
|
|
73233
73421
|
for (; ; ) {
|
|
73234
|
-
if (
|
|
73235
|
-
const parent =
|
|
73422
|
+
if (existsSync67(join65(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync67(join65(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
73423
|
+
const parent = dirname37(dir);
|
|
73236
73424
|
if (parent === dir) return false;
|
|
73237
73425
|
dir = parent;
|
|
73238
73426
|
}
|
|
@@ -73291,8 +73479,8 @@ function materializeForPreview(appDir3, slug, displayName) {
|
|
|
73291
73479
|
const forBuild = Object.fromEntries(
|
|
73292
73480
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
73293
73481
|
);
|
|
73294
|
-
const repoRoot2 =
|
|
73295
|
-
const root =
|
|
73482
|
+
const repoRoot2 = resolve53(fileURLToPath26(new URL("../../..", import.meta.url)));
|
|
73483
|
+
const root = join65(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
73296
73484
|
const stillRunning = (pid) => {
|
|
73297
73485
|
try {
|
|
73298
73486
|
process.kill(pid, 0);
|
|
@@ -73302,30 +73490,30 @@ function materializeForPreview(appDir3, slug, displayName) {
|
|
|
73302
73490
|
}
|
|
73303
73491
|
};
|
|
73304
73492
|
try {
|
|
73305
|
-
for (const entry of
|
|
73493
|
+
for (const entry of readdirSync31(root, { withFileTypes: true })) {
|
|
73306
73494
|
if (!entry.isDirectory()) continue;
|
|
73307
73495
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
73308
73496
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
73309
|
-
|
|
73497
|
+
rmSync16(join65(root, entry.name), { recursive: true, force: true });
|
|
73310
73498
|
}
|
|
73311
73499
|
}
|
|
73312
73500
|
} catch {
|
|
73313
73501
|
}
|
|
73314
|
-
const dest =
|
|
73315
|
-
|
|
73316
|
-
|
|
73502
|
+
const dest = join65(root, `${slug}-${process.pid}`);
|
|
73503
|
+
rmSync16(dest, { recursive: true, force: true });
|
|
73504
|
+
mkdirSync33(dest, { recursive: true });
|
|
73317
73505
|
try {
|
|
73318
73506
|
materializeSource(forBuild, displayName, dest, slug);
|
|
73319
73507
|
} catch (e) {
|
|
73320
|
-
|
|
73508
|
+
rmSync16(dest, { recursive: true, force: true });
|
|
73321
73509
|
throw e;
|
|
73322
73510
|
}
|
|
73323
73511
|
return dest;
|
|
73324
73512
|
}
|
|
73325
73513
|
async function appId(dir) {
|
|
73326
73514
|
try {
|
|
73327
|
-
const { readFileSync:
|
|
73328
|
-
const m = JSON.parse(
|
|
73515
|
+
const { readFileSync: readFileSync81 } = await import("node:fs");
|
|
73516
|
+
const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
|
|
73329
73517
|
if (m.name) return m.name;
|
|
73330
73518
|
} catch {
|
|
73331
73519
|
}
|
|
@@ -73333,8 +73521,8 @@ async function appId(dir) {
|
|
|
73333
73521
|
}
|
|
73334
73522
|
async function contentVisibility(dir) {
|
|
73335
73523
|
try {
|
|
73336
|
-
const { readFileSync:
|
|
73337
|
-
const m = JSON.parse(
|
|
73524
|
+
const { readFileSync: readFileSync81 } = await import("node:fs");
|
|
73525
|
+
const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
|
|
73338
73526
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
73339
73527
|
} catch {
|
|
73340
73528
|
}
|
|
@@ -73537,7 +73725,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
73537
73725
|
return 0;
|
|
73538
73726
|
}
|
|
73539
73727
|
case "agent-init": {
|
|
73540
|
-
const dir =
|
|
73728
|
+
const dir = resolve53(str8(flags.dir) ?? process.cwd());
|
|
73541
73729
|
const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
|
|
73542
73730
|
let res;
|
|
73543
73731
|
try {
|
|
@@ -73559,7 +73747,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
73559
73747
|
...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
73748
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
73561
73749
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
73562
|
-
...
|
|
73750
|
+
...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
73751
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
73564
73752
|
portalUrl: idx.portalUrl
|
|
73565
73753
|
});
|
|
@@ -73582,7 +73770,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
73582
73770
|
try {
|
|
73583
73771
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
73584
73772
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
73585
|
-
out2 = mkdtempSync4(
|
|
73773
|
+
out2 = mkdtempSync4(join65(tmpdir5(), "himi-ux-record-"));
|
|
73586
73774
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
73587
73775
|
const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
73588
73776
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -73595,7 +73783,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
73595
73783
|
return null;
|
|
73596
73784
|
} finally {
|
|
73597
73785
|
if (out2 !== void 0) try {
|
|
73598
|
-
|
|
73786
|
+
rmSync16(out2, { recursive: true, force: true });
|
|
73599
73787
|
} catch {
|
|
73600
73788
|
}
|
|
73601
73789
|
}
|
|
@@ -73749,7 +73937,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73749
73937
|
}
|
|
73750
73938
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
73751
73939
|
try {
|
|
73752
|
-
|
|
73940
|
+
readdirSync31(outDir);
|
|
73753
73941
|
} catch {
|
|
73754
73942
|
return { families: void 0, source: "unbuilt" };
|
|
73755
73943
|
}
|
|
@@ -73760,7 +73948,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73760
73948
|
let js;
|
|
73761
73949
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
73762
73950
|
try {
|
|
73763
|
-
js =
|
|
73951
|
+
js = readFileSync80(join65(outDir, candidate), "utf8");
|
|
73764
73952
|
break;
|
|
73765
73953
|
} catch {
|
|
73766
73954
|
}
|
|
@@ -73791,7 +73979,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
73791
73979
|
}
|
|
73792
73980
|
return { families, source: "dist/bundles" };
|
|
73793
73981
|
}
|
|
73794
|
-
var boardOpen = (dir) =>
|
|
73982
|
+
var boardOpen = (dir) => existsSync67(join65(dir, ".himi", "studio", "index.html"));
|
|
73795
73983
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
73796
73984
|
async function leaveForBoard(dir, record2, value) {
|
|
73797
73985
|
if (!boardOpen(dir)) return;
|
|
@@ -73815,7 +74003,7 @@ async function liveMapFor(dir) {
|
|
|
73815
74003
|
}
|
|
73816
74004
|
var commandScratch = new AsyncLocalStorage();
|
|
73817
74005
|
function commandScratchDir(prefix) {
|
|
73818
|
-
const dir = mkdtempSync4(
|
|
74006
|
+
const dir = mkdtempSync4(join65(tmpdir5(), prefix));
|
|
73819
74007
|
commandScratch.getStore()?.push(dir);
|
|
73820
74008
|
return dir;
|
|
73821
74009
|
}
|
|
@@ -73826,7 +74014,7 @@ async function run(argv, io = defaultIO, deps = {}) {
|
|
|
73826
74014
|
code = await commandScratch.run(scratch, () => runCommand(argv, io, deps));
|
|
73827
74015
|
} finally {
|
|
73828
74016
|
for (const dir of scratch) try {
|
|
73829
|
-
|
|
74017
|
+
rmSync16(dir, { recursive: true, force: true });
|
|
73830
74018
|
} catch {
|
|
73831
74019
|
}
|
|
73832
74020
|
}
|
|
@@ -74094,7 +74282,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
74094
74282
|
return 2;
|
|
74095
74283
|
}
|
|
74096
74284
|
const template = str8(flags.template);
|
|
74097
|
-
const parentDir =
|
|
74285
|
+
const parentDir = resolve53(str8(flags.dir) ?? process.cwd());
|
|
74098
74286
|
const withAgentFiles = async (dir) => {
|
|
74099
74287
|
const seeded = await seedAgentFilesFor(dir, flags);
|
|
74100
74288
|
if (!seeded.agent || "error" in seeded.agent) return seeded;
|
|
@@ -74107,7 +74295,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
74107
74295
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
74108
74296
|
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
74297
|
}
|
|
74110
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) =>
|
|
74298
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync67(join65(parentDir, f)));
|
|
74111
74299
|
if (planInParent.length) {
|
|
74112
74300
|
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
74301
|
}
|
|
@@ -74255,11 +74443,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74255
74443
|
return 2;
|
|
74256
74444
|
}
|
|
74257
74445
|
}
|
|
74258
|
-
const appDir3 =
|
|
74259
|
-
const sourceDir =
|
|
74446
|
+
const appDir3 = resolve53(str8(flags.dir) ?? process.cwd());
|
|
74447
|
+
const sourceDir = resolve53(str8(flags["source-dir"]) ?? appDir3);
|
|
74260
74448
|
let meta;
|
|
74261
74449
|
try {
|
|
74262
|
-
meta = JSON.parse(
|
|
74450
|
+
meta = JSON.parse(readFileSync80(join65(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
74263
74451
|
} catch {
|
|
74264
74452
|
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
74453
|
return 2;
|
|
@@ -74269,7 +74457,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74269
74457
|
return 2;
|
|
74270
74458
|
}
|
|
74271
74459
|
try {
|
|
74272
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
74460
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync80(join65(sourceDir, "tokens.json"), "utf8")));
|
|
74273
74461
|
meta = { ...appearance, ...meta };
|
|
74274
74462
|
} catch {
|
|
74275
74463
|
}
|
|
@@ -74291,14 +74479,14 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74291
74479
|
const force = flags.force === true;
|
|
74292
74480
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
74293
74481
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
74294
|
-
const out2 = mkdtempSync4(
|
|
74482
|
+
const out2 = mkdtempSync4(join65(tmpdir5(), "himi-template-"));
|
|
74295
74483
|
publishScratch.push(out2);
|
|
74296
74484
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
74297
74485
|
const outcome = await buildReleaseFromContent2(buildDir, out2, {
|
|
74298
74486
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
74299
74487
|
collect: { lint: true, strict }
|
|
74300
74488
|
});
|
|
74301
|
-
const scaffoldSourceFindings =
|
|
74489
|
+
const scaffoldSourceFindings = resolve53(sourceDir) === resolve53(appDir3) ? [] : [
|
|
74302
74490
|
...tokenColorIssues(sourceDir),
|
|
74303
74491
|
...surfaceIssues(sourceDir, void 0, strict),
|
|
74304
74492
|
...await fontIssues(sourceDir, strict),
|
|
@@ -74341,11 +74529,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74341
74529
|
}));
|
|
74342
74530
|
return 1;
|
|
74343
74531
|
}
|
|
74344
|
-
const iconPath = str8(flags.icon) ?
|
|
74532
|
+
const iconPath = str8(flags.icon) ? resolve53(str8(flags.icon)) : templateIconPath(name);
|
|
74345
74533
|
let iconHash;
|
|
74346
74534
|
if (iconPath) {
|
|
74347
74535
|
try {
|
|
74348
|
-
const bytes2 =
|
|
74536
|
+
const bytes2 = readFileSync80(iconPath);
|
|
74349
74537
|
payload.icon = bytes2.toString("base64");
|
|
74350
74538
|
iconHash = createHash31("sha256").update(bytes2).digest("hex");
|
|
74351
74539
|
} catch {
|
|
@@ -74518,7 +74706,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74518
74706
|
} finally {
|
|
74519
74707
|
for (const dir of publishScratch) {
|
|
74520
74708
|
try {
|
|
74521
|
-
|
|
74709
|
+
rmSync16(dir, { recursive: true, force: true });
|
|
74522
74710
|
} catch (e) {
|
|
74523
74711
|
io.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e.message}` }));
|
|
74524
74712
|
}
|
|
@@ -74552,12 +74740,12 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74552
74740
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
74553
74741
|
return 2;
|
|
74554
74742
|
}
|
|
74555
|
-
const { readdirSync:
|
|
74743
|
+
const { readdirSync: readdirSync32, existsSync: fileExists } = await import("node:fs");
|
|
74556
74744
|
const { join: pathJoin } = await import("node:path");
|
|
74557
74745
|
const targets = [];
|
|
74558
74746
|
const t5 = pathJoin(dir, "tier5-src");
|
|
74559
74747
|
if (fileExists(t5)) {
|
|
74560
|
-
for (const d of
|
|
74748
|
+
for (const d of readdirSync32(t5, { withFileTypes: true })) {
|
|
74561
74749
|
if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
|
|
74562
74750
|
}
|
|
74563
74751
|
}
|
|
@@ -74632,7 +74820,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74632
74820
|
const path2 = dpxSessionTokenPath();
|
|
74633
74821
|
let raw;
|
|
74634
74822
|
try {
|
|
74635
|
-
raw =
|
|
74823
|
+
raw = readFileSync80(path2, "utf8");
|
|
74636
74824
|
} catch {
|
|
74637
74825
|
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
74826
|
}
|
|
@@ -74763,32 +74951,37 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74763
74951
|
return 1;
|
|
74764
74952
|
}
|
|
74765
74953
|
const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
|
|
74766
|
-
const dir =
|
|
74954
|
+
const dir = resolve53(out2);
|
|
74767
74955
|
const files = himiPluginFiles2(skills.skillMd);
|
|
74768
74956
|
for (const f of files) {
|
|
74769
|
-
|
|
74770
|
-
|
|
74957
|
+
mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
|
|
74958
|
+
writeFileSync30(join65(dir, f.path), f.text);
|
|
74771
74959
|
}
|
|
74772
74960
|
print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
74773
74961
|
return 0;
|
|
74774
74962
|
}
|
|
74775
74963
|
const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
74776
|
-
await startMcpServer2({
|
|
74964
|
+
await startMcpServer2({
|
|
74965
|
+
run,
|
|
74966
|
+
version: cliVersion(),
|
|
74967
|
+
withFiles: flags["with-files"] === true,
|
|
74968
|
+
...process.env.HIMI_WORKSPACE ? { workspace: resolve53(process.env.HIMI_WORKSPACE) } : {}
|
|
74969
|
+
});
|
|
74777
74970
|
return 0;
|
|
74778
74971
|
}
|
|
74779
74972
|
case "studio": {
|
|
74780
74973
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
74781
74974
|
const dir = contentDir(flags);
|
|
74782
|
-
if (!
|
|
74975
|
+
if (!existsSync67(join65(dir, "himalaya.content.json"))) {
|
|
74783
74976
|
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
74977
|
return 2;
|
|
74785
74978
|
}
|
|
74786
74979
|
if (pos[1] === "reel") {
|
|
74787
74980
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
74788
|
-
const out2 =
|
|
74981
|
+
const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
|
|
74789
74982
|
const { html, plan } = buildReel2(dir);
|
|
74790
|
-
|
|
74791
|
-
|
|
74983
|
+
mkdirSync33(dirname37(out2), { recursive: true });
|
|
74984
|
+
writeFileSync30(out2, html);
|
|
74792
74985
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
74793
74986
|
const url2 = pathToFileURL9(out2).href;
|
|
74794
74987
|
const open2 = flags["no-open"] !== true;
|
|
@@ -74857,7 +75050,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
74857
75050
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
74858
75051
|
const dir = contentDir(flags);
|
|
74859
75052
|
const journal2 = journalPath2(dir);
|
|
74860
|
-
const isContentPackage =
|
|
75053
|
+
const isContentPackage = existsSync67(join65(dir, "himalaya.content.json"));
|
|
74861
75054
|
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
75055
|
const message = pos.slice(1).join(" ").trim();
|
|
74863
75056
|
const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
|
|
@@ -75006,7 +75199,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75006
75199
|
case "test": {
|
|
75007
75200
|
const dir = contentDir(flags);
|
|
75008
75201
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
75009
|
-
if (
|
|
75202
|
+
if (existsSync67(join65(dir, "functions"))) {
|
|
75010
75203
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
75011
75204
|
const loaded = await loadFunctionsApp2(dir);
|
|
75012
75205
|
const results = [];
|
|
@@ -75138,7 +75331,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75138
75331
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
75139
75332
|
return 2;
|
|
75140
75333
|
}
|
|
75141
|
-
const sources = collectWorkerSources2(
|
|
75334
|
+
const sources = collectWorkerSources2(join65(dir, "tier5-src"), screen.bundleName);
|
|
75142
75335
|
if (!sources) {
|
|
75143
75336
|
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
75337
|
return 2;
|
|
@@ -75315,7 +75508,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75315
75508
|
const sp = await runShotsPass2({
|
|
75316
75509
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
75317
75510
|
tokens: outcome.tokens,
|
|
75318
|
-
outDir:
|
|
75511
|
+
outDir: join65(dir, ".himi", "shots"),
|
|
75319
75512
|
width: 390,
|
|
75320
75513
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
75321
75514
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -75325,7 +75518,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75325
75518
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
75326
75519
|
renderPngBatch: renderPngBatch2,
|
|
75327
75520
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
75328
|
-
clearDir: (d) =>
|
|
75521
|
+
clearDir: (d) => rmSync16(d, { recursive: true, force: true })
|
|
75329
75522
|
}
|
|
75330
75523
|
});
|
|
75331
75524
|
writtenShots = sp.written;
|
|
@@ -75353,7 +75546,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
75353
75546
|
releaseId: result.releaseId,
|
|
75354
75547
|
releasePayload: release,
|
|
75355
75548
|
descriptors: attestedDescriptors,
|
|
75356
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
75549
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join65(dir, ".himi", "shots", name)])),
|
|
75357
75550
|
coverage: {
|
|
75358
75551
|
screens: crawledScreens.size,
|
|
75359
75552
|
actionsDispatched: result.actions.exercised,
|
|
@@ -75464,7 +75657,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75464
75657
|
return 2;
|
|
75465
75658
|
}
|
|
75466
75659
|
try {
|
|
75467
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
75660
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync80(stateArg.replace(/^@/, ""), "utf8");
|
|
75468
75661
|
injectedState = JSON.parse(raw);
|
|
75469
75662
|
} catch (e) {
|
|
75470
75663
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -75479,7 +75672,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75479
75672
|
return 2;
|
|
75480
75673
|
}
|
|
75481
75674
|
try {
|
|
75482
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
75675
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync80(inputArg.replace(/^@/, ""), "utf8");
|
|
75483
75676
|
const parsed = JSON.parse(raw);
|
|
75484
75677
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
75485
75678
|
injectedInput = parsed;
|
|
@@ -75542,11 +75735,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
75542
75735
|
const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
|
|
75543
75736
|
let pngFile;
|
|
75544
75737
|
let attestationPngFile;
|
|
75545
|
-
const shotPath =
|
|
75738
|
+
const shotPath = join65(dir, ".himi", "shots", `${screenId}.png`);
|
|
75546
75739
|
const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
|
|
75547
75740
|
if (pngTarget && r.pngBase64) {
|
|
75548
75741
|
pngFile = writePngFile(pngTarget, r.pngBase64);
|
|
75549
|
-
attestationPngFile =
|
|
75742
|
+
attestationPngFile = resolve53(pngTarget) === resolve53(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
|
|
75550
75743
|
}
|
|
75551
75744
|
if (renderWidth !== void 0 && r.renderable) {
|
|
75552
75745
|
recordRenderWidth(dir, {
|
|
@@ -75882,7 +76075,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75882
76075
|
return 2;
|
|
75883
76076
|
}
|
|
75884
76077
|
const renamed = str8(flags.name);
|
|
75885
|
-
const dest =
|
|
76078
|
+
const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
75886
76079
|
const replace = flags.replace === true;
|
|
75887
76080
|
const force = replace || flags.force === true;
|
|
75888
76081
|
const linked = symlinkDestinationIssue(dest);
|
|
@@ -75890,20 +76083,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
75890
76083
|
io.error(JSON.stringify(linked));
|
|
75891
76084
|
return 1;
|
|
75892
76085
|
}
|
|
75893
|
-
if (
|
|
75894
|
-
if (!
|
|
76086
|
+
if (existsSync67(dest)) {
|
|
76087
|
+
if (!statSync19(dest).isDirectory()) {
|
|
75895
76088
|
io.error(JSON.stringify({
|
|
75896
76089
|
error: `${dest} exists and is not a directory`,
|
|
75897
76090
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
75898
76091
|
}));
|
|
75899
76092
|
return 1;
|
|
75900
76093
|
}
|
|
75901
|
-
const occupied =
|
|
76094
|
+
const occupied = readdirSync31(dest).length > 0;
|
|
75902
76095
|
if (occupied && !force) {
|
|
75903
76096
|
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
76097
|
return 1;
|
|
75905
76098
|
}
|
|
75906
|
-
if (replace && occupied && !
|
|
76099
|
+
if (replace && occupied && !existsSync67(join65(dest, "himalaya.content.json"))) {
|
|
75907
76100
|
io.error(JSON.stringify({
|
|
75908
76101
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
75909
76102
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -76070,7 +76263,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76070
76263
|
const manifest = outcome.manifest;
|
|
76071
76264
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
76072
76265
|
const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
|
|
76073
|
-
const contentRel =
|
|
76266
|
+
const contentRel = relative14(process.cwd(), dir) || ".";
|
|
76074
76267
|
const contentArg2 = shellQuote3(contentRel);
|
|
76075
76268
|
if (onlyRaw !== void 0) {
|
|
76076
76269
|
const onlyDraft = flags.draft === true;
|
|
@@ -76541,7 +76734,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76541
76734
|
return 2;
|
|
76542
76735
|
}
|
|
76543
76736
|
try {
|
|
76544
|
-
const res = writePack(
|
|
76737
|
+
const res = writePack(resolve53(releaseDir), only, resolve53(str8(flags.out) ?? process.cwd()));
|
|
76545
76738
|
print({
|
|
76546
76739
|
ok: true,
|
|
76547
76740
|
app: res.app,
|
|
@@ -76590,7 +76783,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76590
76783
|
}
|
|
76591
76784
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76592
76785
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
76593
|
-
const built = mkdtempSync4(
|
|
76786
|
+
const built = mkdtempSync4(join65(tmpdir5(), "himi-pack-"));
|
|
76594
76787
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
76595
76788
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
76596
76789
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -76607,12 +76800,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76607
76800
|
...await navIssues2(dir, strict)
|
|
76608
76801
|
]);
|
|
76609
76802
|
if (hasErrors && !force) {
|
|
76610
|
-
|
|
76803
|
+
rmSync16(built, { recursive: true, force: true });
|
|
76611
76804
|
print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
76612
76805
|
return 1;
|
|
76613
76806
|
}
|
|
76614
76807
|
try {
|
|
76615
|
-
const res = writePack(built, app,
|
|
76808
|
+
const res = writePack(built, app, resolve53(str8(flags.out) ?? dir), sourceArchive);
|
|
76616
76809
|
print({
|
|
76617
76810
|
ok: true,
|
|
76618
76811
|
app: res.app,
|
|
@@ -76643,7 +76836,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76643
76836
|
io.error(JSON.stringify({ error: e.message }));
|
|
76644
76837
|
return 1;
|
|
76645
76838
|
} finally {
|
|
76646
|
-
|
|
76839
|
+
rmSync16(built, { recursive: true, force: true });
|
|
76647
76840
|
}
|
|
76648
76841
|
}
|
|
76649
76842
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -76657,7 +76850,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76657
76850
|
const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
|
|
76658
76851
|
let opened;
|
|
76659
76852
|
try {
|
|
76660
|
-
opened = openPackageFile2(
|
|
76853
|
+
opened = openPackageFile2(resolve53(file));
|
|
76661
76854
|
} catch (e) {
|
|
76662
76855
|
io.error(JSON.stringify({ error: e.message }));
|
|
76663
76856
|
return 1;
|
|
@@ -76670,7 +76863,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76670
76863
|
io.error(JSON.stringify({
|
|
76671
76864
|
ok: false,
|
|
76672
76865
|
error: "app_source_not_in_package",
|
|
76673
|
-
detail: `${
|
|
76866
|
+
detail: `${resolve53(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
|
|
76674
76867
|
hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
|
|
76675
76868
|
}));
|
|
76676
76869
|
return 1;
|
|
@@ -76693,7 +76886,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76693
76886
|
return 1;
|
|
76694
76887
|
}
|
|
76695
76888
|
}
|
|
76696
|
-
const dest =
|
|
76889
|
+
const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
|
|
76697
76890
|
const issue2 = restoreDestinationIssue(dest, flags.force === true);
|
|
76698
76891
|
if (issue2) {
|
|
76699
76892
|
io.error(JSON.stringify(issue2));
|
|
@@ -76780,7 +76973,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76780
76973
|
}
|
|
76781
76974
|
try {
|
|
76782
76975
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
76783
|
-
const opened = openPackageFile2(
|
|
76976
|
+
const opened = openPackageFile2(resolve53(file));
|
|
76784
76977
|
if (!opened.validation.ok || !opened.header) {
|
|
76785
76978
|
io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
76786
76979
|
return 1;
|
|
@@ -76790,12 +76983,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76790
76983
|
io.error(JSON.stringify({
|
|
76791
76984
|
ok: false,
|
|
76792
76985
|
error: "refusing to share a package that carries the app's source",
|
|
76793
|
-
detail: `${
|
|
76986
|
+
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
76987
|
hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
|
|
76795
76988
|
}));
|
|
76796
76989
|
return 1;
|
|
76797
76990
|
}
|
|
76798
|
-
const archive =
|
|
76991
|
+
const archive = readFileSync80(resolve53(file));
|
|
76799
76992
|
const result = await client2().createPackageShare({
|
|
76800
76993
|
app: opened.header.app,
|
|
76801
76994
|
releaseId: opened.header.releaseId,
|
|
@@ -76871,11 +77064,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76871
77064
|
const app = await appId(dir2);
|
|
76872
77065
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76873
77066
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
76874
|
-
temp = mkdtempSync4(
|
|
77067
|
+
temp = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
|
|
76875
77068
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
76876
77069
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
76877
77070
|
servedMissing = initial.missingBundles;
|
|
76878
|
-
source =
|
|
77071
|
+
source = join65(temp, app);
|
|
76879
77072
|
}
|
|
76880
77073
|
const chromeArg = str8(flags.chrome) ?? "preview";
|
|
76881
77074
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -76911,7 +77104,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76911
77104
|
if (!recordKit) return;
|
|
76912
77105
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
76913
77106
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
76914
|
-
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
77107
|
+
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
77108
|
await refreshBoard();
|
|
76916
77109
|
};
|
|
76917
77110
|
const retract = async () => {
|
|
@@ -76934,9 +77127,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76934
77127
|
});
|
|
76935
77128
|
await announce(run2);
|
|
76936
77129
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
76937
|
-
await new Promise((
|
|
77130
|
+
await new Promise((resolve54) => {
|
|
76938
77131
|
const stop = () => {
|
|
76939
|
-
void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() =>
|
|
77132
|
+
void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
|
|
76940
77133
|
};
|
|
76941
77134
|
process.once("SIGINT", stop);
|
|
76942
77135
|
process.once("SIGTERM", stop);
|
|
@@ -76945,7 +77138,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76945
77138
|
}
|
|
76946
77139
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
76947
77140
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
76948
|
-
if (watch2) served = mkdtempSync4(
|
|
77141
|
+
if (watch2) served = mkdtempSync4(join65(tmpdir5(), "himi-run-served-"));
|
|
76949
77142
|
const running = await runPackage2(source, {
|
|
76950
77143
|
port,
|
|
76951
77144
|
chrome: chromeArg,
|
|
@@ -76974,8 +77167,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76974
77167
|
await announce(running);
|
|
76975
77168
|
if (watchKit && bus) {
|
|
76976
77169
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
76977
|
-
const live2 =
|
|
76978
|
-
const manifestOf = (tree) => JSON.parse(
|
|
77170
|
+
const live2 = join65(running.releaseRoot, running.app);
|
|
77171
|
+
const manifestOf = (tree) => JSON.parse(readFileSync80(join65(tree, "release-manifest.json"), "utf8"));
|
|
76979
77172
|
let current = manifestOf(live2);
|
|
76980
77173
|
const failed2 = async (message) => {
|
|
76981
77174
|
if (stopping) return;
|
|
@@ -76986,7 +77179,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76986
77179
|
};
|
|
76987
77180
|
rebuild = watchKit.serialize(async () => {
|
|
76988
77181
|
const t0 = Date.now();
|
|
76989
|
-
const next = mkdtempSync4(
|
|
77182
|
+
const next = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
|
|
76990
77183
|
try {
|
|
76991
77184
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
76992
77185
|
if (bres.compileErrors.length) {
|
|
@@ -77003,18 +77196,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77003
77196
|
return;
|
|
77004
77197
|
}
|
|
77005
77198
|
if (stopping) return;
|
|
77006
|
-
const fresh = manifestOf(
|
|
77199
|
+
const fresh = manifestOf(join65(next, running.app));
|
|
77007
77200
|
const diff = watchKit.diffReleases(current, fresh);
|
|
77008
77201
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
77009
|
-
const changes = describeChanges2(live2,
|
|
77202
|
+
const changes = describeChanges2(live2, join65(next, running.app), diff);
|
|
77010
77203
|
const retired = `${live2}.retired-${Date.now()}`;
|
|
77011
77204
|
renameSync7(live2, retired);
|
|
77012
77205
|
try {
|
|
77013
|
-
renameSync7(
|
|
77206
|
+
renameSync7(join65(next, running.app), live2);
|
|
77014
77207
|
} catch {
|
|
77015
|
-
cpSync3(
|
|
77208
|
+
cpSync3(join65(next, running.app), live2, { recursive: true });
|
|
77016
77209
|
}
|
|
77017
|
-
|
|
77210
|
+
rmSync16(retired, { recursive: true, force: true });
|
|
77018
77211
|
current = fresh;
|
|
77019
77212
|
servedMissing = outcome.missingBundles;
|
|
77020
77213
|
for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
|
|
@@ -77024,7 +77217,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77024
77217
|
} catch (e) {
|
|
77025
77218
|
await failed2(e.message.split("\n")[0]);
|
|
77026
77219
|
} finally {
|
|
77027
|
-
|
|
77220
|
+
rmSync16(next, { recursive: true, force: true });
|
|
77028
77221
|
}
|
|
77029
77222
|
});
|
|
77030
77223
|
watcher2 = watchKit.watchContent(dir, () => {
|
|
@@ -77092,9 +77285,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77092
77285
|
io.error(JSON.stringify({ error: e.message }));
|
|
77093
77286
|
return 1;
|
|
77094
77287
|
} finally {
|
|
77095
|
-
if (temp)
|
|
77096
|
-
if (served)
|
|
77097
|
-
if (browserCopy)
|
|
77288
|
+
if (temp) rmSync16(temp, { recursive: true, force: true });
|
|
77289
|
+
if (served) rmSync16(served, { recursive: true, force: true });
|
|
77290
|
+
if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
|
|
77098
77291
|
}
|
|
77099
77292
|
}
|
|
77100
77293
|
case "preview": {
|
|
@@ -77636,7 +77829,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77636
77829
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
77637
77830
|
return 2;
|
|
77638
77831
|
}
|
|
77639
|
-
if (!
|
|
77832
|
+
if (!existsSync67(file)) {
|
|
77640
77833
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
77641
77834
|
return 2;
|
|
77642
77835
|
}
|
|
@@ -77692,7 +77885,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77692
77885
|
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
77886
|
};
|
|
77694
77887
|
if (kind === "tokens" || kind === "app-config") {
|
|
77695
|
-
const body =
|
|
77888
|
+
const body = readFileSync80(file, "utf8");
|
|
77696
77889
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
77697
77890
|
return runReleasePatch({
|
|
77698
77891
|
...common,
|
|
@@ -77707,7 +77900,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77707
77900
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
77708
77901
|
return 2;
|
|
77709
77902
|
}
|
|
77710
|
-
const descriptor =
|
|
77903
|
+
const descriptor = readFileSync80(file, "utf8");
|
|
77711
77904
|
try {
|
|
77712
77905
|
JSON.parse(descriptor);
|
|
77713
77906
|
} catch (e) {
|
|
@@ -77747,7 +77940,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77747
77940
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
77748
77941
|
});
|
|
77749
77942
|
}
|
|
77750
|
-
const bytes2 =
|
|
77943
|
+
const bytes2 = readFileSync80(file);
|
|
77751
77944
|
const sha = createHash31("sha256").update(bytes2).digest("hex");
|
|
77752
77945
|
const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
77753
77946
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -77891,7 +78084,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77891
78084
|
}
|
|
77892
78085
|
let def;
|
|
77893
78086
|
try {
|
|
77894
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
78087
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync80(arg.slice(1), "utf8") : arg);
|
|
77895
78088
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
77896
78089
|
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
78090
|
return 2;
|
|
@@ -78355,7 +78548,7 @@ ${label2}`);
|
|
|
78355
78548
|
const platform = str8(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
78356
78549
|
{
|
|
78357
78550
|
const distDir = contentDir(flags);
|
|
78358
|
-
if (
|
|
78551
|
+
if (existsSync67(join65(distDir, "himalaya.content.json"))) {
|
|
78359
78552
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
78360
78553
|
const errors = issues.filter((i) => i.severity === "error");
|
|
78361
78554
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -78641,7 +78834,7 @@ ${label2}`);
|
|
|
78641
78834
|
const dpxPath = dpxSessionTokenPath();
|
|
78642
78835
|
let dpx;
|
|
78643
78836
|
try {
|
|
78644
|
-
dpx =
|
|
78837
|
+
dpx = readFileSync80(dpxPath, "utf8").trim();
|
|
78645
78838
|
} catch {
|
|
78646
78839
|
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
78840
|
return 1;
|
|
@@ -79049,7 +79242,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
79049
79242
|
const path2 = dpxSessionTokenPath();
|
|
79050
79243
|
let raw;
|
|
79051
79244
|
try {
|
|
79052
|
-
raw =
|
|
79245
|
+
raw = readFileSync80(path2, "utf8");
|
|
79053
79246
|
} catch {
|
|
79054
79247
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
79055
79248
|
return 1;
|
|
@@ -79365,10 +79558,11 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
79365
79558
|
return 2;
|
|
79366
79559
|
}
|
|
79367
79560
|
const redirectFlag = str8(flags["redirect-uri"]);
|
|
79368
|
-
|
|
79369
|
-
|
|
79561
|
+
const { APPLY_NEEDS_CLIENT: APPLY_NEEDS_CLIENT2, REDIRECT_NEEDS_CLIENT: REDIRECT_NEEDS_CLIENT2, applyNeedsClient: applyNeedsClient2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
79562
|
+
const applyWantsClient = flags.apply === true && applyNeedsClient2(str8(flags.shell));
|
|
79563
|
+
if (!clientId && (applyWantsClient || redirectFlag)) {
|
|
79370
79564
|
io.error(JSON.stringify({
|
|
79371
|
-
error:
|
|
79565
|
+
error: applyWantsClient ? APPLY_NEEDS_CLIENT2 : REDIRECT_NEEDS_CLIENT2,
|
|
79372
79566
|
usage: analyzeUsage
|
|
79373
79567
|
}));
|
|
79374
79568
|
return 2;
|