@wix/himalaya-cli 0.1058.0 → 0.1060.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 +1089 -602
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/headless-loop.md +6 -1
- package/guides/himi-test.md +17 -0
- package/package.json +2 -2
- package/templates/surface-showcase/dev/index.ts +3 -1
package/dist/cli.mjs
CHANGED
|
@@ -2699,7 +2699,7 @@ function isAttestationV2(value) {
|
|
|
2699
2699
|
const a = value;
|
|
2700
2700
|
const coverage = a.coverage;
|
|
2701
2701
|
const report2 = a.report;
|
|
2702
|
-
return a.attestation === 2 && typeof a.runId === "string" && ["himi-test", "himi-render", "himi-shots"].includes(a.tool) && [a.app, a.contentDir, a.gitDiffHash, a.gitUntrackedHash, a.releaseId, a.releaseHash, a.selfHash].every((item) => typeof item === "string" && item.length > 0) && stringRecord(a.descriptorHashes) && stringRecord(a.screenshots) && !!coverage && [coverage.screens, coverage.actionsDispatched, coverage.uncoveredFns, coverage.gaps].every((
|
|
2702
|
+
return a.attestation === 2 && typeof a.runId === "string" && ["himi-test", "himi-render", "himi-shots"].includes(a.tool) && [a.app, a.contentDir, a.gitDiffHash, a.gitUntrackedHash, a.releaseId, a.releaseHash, a.selfHash].every((item) => typeof item === "string" && item.length > 0) && stringRecord(a.descriptorHashes) && stringRecord(a.screenshots) && !!coverage && [coverage.screens, coverage.actionsDispatched, coverage.uncoveredFns, coverage.gaps].every((count2) => typeof count2 === "number" && Number.isFinite(count2) && count2 >= 0) && typeof report2?.ok === "boolean" && !!report2.counts && [report2.counts.errors, report2.counts.warnings, report2.counts.gaps].every((count2) => typeof count2 === "number" && Number.isFinite(count2) && count2 >= 0) && (a.prev === null || typeof a.prev === "string");
|
|
2703
2703
|
}
|
|
2704
2704
|
function readLatestAttestation(contentDir2) {
|
|
2705
2705
|
try {
|
|
@@ -6684,7 +6684,6 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
6684
6684
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
6685
6685
|
var init_bindings = __esm({
|
|
6686
6686
|
"../../core/ts/src/bindings.ts"() {
|
|
6687
|
-
"use strict";
|
|
6688
6687
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
6689
6688
|
BINDING_SIGIL_RE = new RegExp(
|
|
6690
6689
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -12327,8 +12326,8 @@ function canonicalHex(value) {
|
|
|
12327
12326
|
function tokenColorProblems(colors) {
|
|
12328
12327
|
const problems = [];
|
|
12329
12328
|
for (const [name, value] of Object.entries(colors ?? {})) {
|
|
12330
|
-
const
|
|
12331
|
-
for (const [path2, raw] of
|
|
12329
|
+
const leaves2 = typeof value === "object" && value !== null && !Array.isArray(value) ? Object.entries(value).map(([variant, raw]) => [`${name}.${variant}`, raw]) : [[name, value]];
|
|
12330
|
+
for (const [path2, raw] of leaves2) {
|
|
12332
12331
|
if (typeof raw !== "string") {
|
|
12333
12332
|
problems.push({ path: path2, value: JSON.stringify(raw) ?? String(raw) });
|
|
12334
12333
|
continue;
|
|
@@ -15100,6 +15099,20 @@ async function tabRootScreens(dir) {
|
|
|
15100
15099
|
(nav?.tabBar?.items ?? []).map((i) => i?.screenId).filter((s) => typeof s === "string" && !!s)
|
|
15101
15100
|
);
|
|
15102
15101
|
}
|
|
15102
|
+
async function navEntryScreens(dir, homeScreenId) {
|
|
15103
|
+
const nav = (await loadContentConfigQuietly(dir))?.navigation;
|
|
15104
|
+
const out = /* @__PURE__ */ new Set();
|
|
15105
|
+
if (homeScreenId) out.add(homeScreenId);
|
|
15106
|
+
const walk2 = (v, depth) => {
|
|
15107
|
+
if (depth > 6 || typeof v !== "object" || v === null) return;
|
|
15108
|
+
for (const [k, x] of Object.entries(v)) {
|
|
15109
|
+
if ((k === "screenId" || k === "contentScreenId") && typeof x === "string" && x) out.add(x);
|
|
15110
|
+
else walk2(x, depth + 1);
|
|
15111
|
+
}
|
|
15112
|
+
};
|
|
15113
|
+
for (const chrome of ["tabBar", "drawer", "sidebar", "topBarDefault"]) walk2(nav?.[chrome], 0);
|
|
15114
|
+
return out;
|
|
15115
|
+
}
|
|
15103
15116
|
async function localDbEntities(dir) {
|
|
15104
15117
|
const schema = (await loadContentConfigQuietly(dir))?.dataSchema;
|
|
15105
15118
|
const names = (schema?.entities ?? []).map((e) => e?.name).filter((n) => typeof n === "string" && n.length > 0);
|
|
@@ -16835,9 +16848,9 @@ function hostFromProject(project) {
|
|
|
16835
16848
|
const blocks = project.split(/(?=^ [A-Za-z0-9_]+:\s*$)/m);
|
|
16836
16849
|
const host = blocks.find((block) => /^ type: application\s*$/m.test(block));
|
|
16837
16850
|
if (!host) throw new Error("Live Activity generation requires an iOS application target");
|
|
16838
|
-
const
|
|
16851
|
+
const scalar4 = (key2, indent) => new RegExp(`^ {${indent}}${key2}:\\s*(.+)$`, "m").exec(host)?.[1]?.trim().replace(/^['"]|['"]$/g, "");
|
|
16839
16852
|
const name = /^ ([A-Za-z0-9_]+):/m.exec(host)?.[1];
|
|
16840
|
-
const bundleId =
|
|
16853
|
+
const bundleId = scalar4("PRODUCT_BUNDLE_IDENTIFIER", 8) ?? scalar4("bundleId", 4);
|
|
16841
16854
|
const scheme = /CFBundleURLSchemes:\s*\n\s*-\s*(.+)/.exec(host)?.[1]?.trim().replace(/^['"]|['"]$/g, "");
|
|
16842
16855
|
if (!name || !bundleId || !scheme) throw new Error("Live Activity generation requires host name, bundleId and URL scheme");
|
|
16843
16856
|
const configs = /^ configFiles:\s*\n((?: .+\n)+)/m.exec(host)?.[1]?.trimEnd().split("\n").map((line) => line.trim()) ?? [];
|
|
@@ -16846,9 +16859,9 @@ function hostFromProject(project) {
|
|
|
16846
16859
|
bundleId,
|
|
16847
16860
|
scheme,
|
|
16848
16861
|
configs,
|
|
16849
|
-
displayName:
|
|
16850
|
-
version:
|
|
16851
|
-
build:
|
|
16862
|
+
displayName: scalar4("CFBundleDisplayName", 8) ?? name,
|
|
16863
|
+
version: scalar4("CFBundleShortVersionString", 8) ?? scalar4("MARKETING_VERSION", 8) ?? "1.0",
|
|
16864
|
+
build: scalar4("CFBundleVersion", 8) ?? scalar4("CURRENT_PROJECT_VERSION", 8) ?? "1"
|
|
16852
16865
|
};
|
|
16853
16866
|
}
|
|
16854
16867
|
function liveActivityPlan(project, enabled, deferredActions = false) {
|
|
@@ -18942,8 +18955,8 @@ var init_store2 = __esm({
|
|
|
18942
18955
|
`);
|
|
18943
18956
|
}
|
|
18944
18957
|
seedNotesIfEmpty() {
|
|
18945
|
-
const
|
|
18946
|
-
if (
|
|
18958
|
+
const count2 = this.db.prepare("SELECT COUNT(*) as c FROM notes").get();
|
|
18959
|
+
if (count2.c > 0) return;
|
|
18947
18960
|
const seedNotes = [
|
|
18948
18961
|
{
|
|
18949
18962
|
id: "n_001",
|
|
@@ -18983,8 +18996,8 @@ var init_store2 = __esm({
|
|
|
18983
18996
|
}
|
|
18984
18997
|
}
|
|
18985
18998
|
seedProductsIfEmpty() {
|
|
18986
|
-
const
|
|
18987
|
-
if (
|
|
18999
|
+
const count2 = this.db.prepare("SELECT COUNT(*) as c FROM products").get();
|
|
19000
|
+
if (count2.c > 0) return;
|
|
18988
19001
|
const now = Math.floor(Date.now() / 1e3);
|
|
18989
19002
|
const seed2 = [
|
|
18990
19003
|
{ id: "p_001", sku: "MNT-CAP-01", title: "Summit cap", description: "Wool-blend beanie. Charcoal. One size, packs flat.", price_cents: 2900, currency: "USD", category: "apparel", inventory: 28, status: "active" },
|
|
@@ -20561,6 +20574,23 @@ function forEachChildComponent(node, cb) {
|
|
|
20561
20574
|
};
|
|
20562
20575
|
visit(node.body.props);
|
|
20563
20576
|
}
|
|
20577
|
+
function visitComponents(root, cb) {
|
|
20578
|
+
const visit = (value) => {
|
|
20579
|
+
if (isNode(value)) {
|
|
20580
|
+
cb(value);
|
|
20581
|
+
visit(value.body.props);
|
|
20582
|
+
return;
|
|
20583
|
+
}
|
|
20584
|
+
if (Array.isArray(value)) {
|
|
20585
|
+
for (const entry of value) visit(entry);
|
|
20586
|
+
return;
|
|
20587
|
+
}
|
|
20588
|
+
if (typeof value === "object" && value !== null) {
|
|
20589
|
+
for (const entry of Object.values(value)) visit(entry);
|
|
20590
|
+
}
|
|
20591
|
+
};
|
|
20592
|
+
visit(root);
|
|
20593
|
+
}
|
|
20564
20594
|
function assignStableIds(descriptor) {
|
|
20565
20595
|
const used = /* @__PURE__ */ new Set();
|
|
20566
20596
|
const uniquify = (base) => {
|
|
@@ -22812,7 +22842,6 @@ function shouldRevealError(args) {
|
|
|
22812
22842
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
22813
22843
|
var init_validation = __esm({
|
|
22814
22844
|
"../../core/ts/src/validation.ts"() {
|
|
22815
|
-
"use strict";
|
|
22816
22845
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
22817
22846
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
22818
22847
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -26173,8 +26202,8 @@ function componentShape(value) {
|
|
|
26173
26202
|
if (!isRecord(value) || typeof value.id !== "string" || !isRecord(value.body)) return false;
|
|
26174
26203
|
return typeof value.body.package === "string" && typeof value.body.type === "string" && isRecord(value.body.props);
|
|
26175
26204
|
}
|
|
26176
|
-
function rotateRight(value,
|
|
26177
|
-
return value >>>
|
|
26205
|
+
function rotateRight(value, count2) {
|
|
26206
|
+
return value >>> count2 | value << 32 - count2;
|
|
26178
26207
|
}
|
|
26179
26208
|
function workerSubtreeSha256(raw) {
|
|
26180
26209
|
const input = new TextEncoder().encode(raw);
|
|
@@ -26413,7 +26442,6 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
26413
26442
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
26414
26443
|
var init_worker_subtree = __esm({
|
|
26415
26444
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
26416
|
-
"use strict";
|
|
26417
26445
|
init_worker_subtree_safe_types_generated();
|
|
26418
26446
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
26419
26447
|
maxEncodedBytes: 65536,
|
|
@@ -27276,6 +27304,11 @@ function withExtras(name, render) {
|
|
|
27276
27304
|
Wrapped.displayName = name;
|
|
27277
27305
|
return Wrapped;
|
|
27278
27306
|
}
|
|
27307
|
+
function sheetTabStops(root) {
|
|
27308
|
+
const all = Array.from(root.querySelectorAll(NATIVELY_TABBABLE)).filter((el) => el.tabIndex >= 0 && !el.disabled && !el.closest('[inert], [hidden], [aria-hidden="true"]'));
|
|
27309
|
+
const ordered = all.filter((el) => el.tabIndex > 0).sort((a, b) => a.tabIndex - b.tabIndex);
|
|
27310
|
+
return [...ordered, ...all.filter((el) => el.tabIndex === 0)];
|
|
27311
|
+
}
|
|
27279
27312
|
function chartNumbers(raw) {
|
|
27280
27313
|
if (!Array.isArray(raw)) return [];
|
|
27281
27314
|
return raw.map((v) => v && typeof v === "object" && !Array.isArray(v) ? v.value : v).map(Number).filter((n) => Number.isFinite(n));
|
|
@@ -27335,14 +27368,14 @@ function dataTableCells(row, columns) {
|
|
|
27335
27368
|
if (Array.isArray(o.cells)) return columns.map((_, i) => o.cells[i] == null ? "" : String(o.cells[i]));
|
|
27336
27369
|
return columns.map((c) => c.key && o[c.key] != null ? String(o[c.key]) : "");
|
|
27337
27370
|
}
|
|
27338
|
-
function resampleWaveform(samples,
|
|
27371
|
+
function resampleWaveform(samples, count2) {
|
|
27339
27372
|
const clean2 = samples.map((n) => Number.isFinite(n) ? Math.min(Math.max(n, 0), 1) : 0);
|
|
27340
|
-
if (
|
|
27341
|
-
if (clean2.length <=
|
|
27373
|
+
if (count2 <= 0 || clean2.length === 0) return [];
|
|
27374
|
+
if (clean2.length <= count2) return clean2;
|
|
27342
27375
|
const out = [];
|
|
27343
|
-
for (let i = 0; i <
|
|
27344
|
-
const lo = Math.floor(i * clean2.length /
|
|
27345
|
-
const hi = Math.min(Math.max(lo + 1, Math.floor((i + 1) * clean2.length /
|
|
27376
|
+
for (let i = 0; i < count2; i++) {
|
|
27377
|
+
const lo = Math.floor(i * clean2.length / count2);
|
|
27378
|
+
const hi = Math.min(Math.max(lo + 1, Math.floor((i + 1) * clean2.length / count2)), clean2.length);
|
|
27346
27379
|
let sum = 0;
|
|
27347
27380
|
for (let j = lo; j < hi; j++) sum += clean2[j];
|
|
27348
27381
|
out.push(sum / (hi - lo));
|
|
@@ -28539,10 +28572,10 @@ function renderInner(node, ctx) {
|
|
|
28539
28572
|
case "Agenda":
|
|
28540
28573
|
return /* @__PURE__ */ jsx6(AgendaNode, { props, ctx, wrap });
|
|
28541
28574
|
case "PageControl": {
|
|
28542
|
-
const
|
|
28575
|
+
const count2 = props.count ?? 0;
|
|
28543
28576
|
const cur = props.currentIndex ?? 0;
|
|
28544
28577
|
const accent = C("accentPrimary", "#116DFF");
|
|
28545
|
-
return /* @__PURE__ */ jsx6("div", { style: { display: "inline-flex", alignItems: "center", gap: 8, ...wrap }, children: Array.from({ length:
|
|
28578
|
+
return /* @__PURE__ */ jsx6("div", { style: { display: "inline-flex", alignItems: "center", gap: 8, ...wrap }, children: Array.from({ length: count2 }).map((_, i) => /* @__PURE__ */ jsx6("span", { style: { width: i === cur ? 22 : 9, height: 9, borderRadius: 999, background: i === cur ? accent : C("textTertiary", "#aab2bd"), transition: "width .2s" } }, i)) });
|
|
28546
28579
|
}
|
|
28547
28580
|
// ───────────── pickers & inputs (RFC 0033) ─────────────
|
|
28548
28581
|
case "WheelPicker":
|
|
@@ -28574,45 +28607,11 @@ function renderInner(node, ctx) {
|
|
|
28574
28607
|
return /* @__PURE__ */ jsx6(PdfViewNode, { props, ctx, wrap });
|
|
28575
28608
|
case "MediaPlayer":
|
|
28576
28609
|
return /* @__PURE__ */ jsx6(MediaPlayerView, { nodeId: node.id, props, ctx, wrap });
|
|
28577
|
-
// Motion grammar (Batch 4) — Lottie
|
|
28578
|
-
|
|
28579
|
-
|
|
28580
|
-
case "
|
|
28581
|
-
|
|
28582
|
-
const lh = typeof props.height === "number" && props.height > 0 ? props.height : 160;
|
|
28583
|
-
return /* @__PURE__ */ jsx6(
|
|
28584
|
-
"div",
|
|
28585
|
-
{
|
|
28586
|
-
"data-himalaya-lottie": props.source ? String(props.source) : "",
|
|
28587
|
-
"data-himalaya-lottie-loop": props.loop === false ? "0" : "1",
|
|
28588
|
-
"data-himalaya-lottie-autoplay": props.autoplay === false ? "0" : "1",
|
|
28589
|
-
"data-himalaya-lottie-speed": typeof props.speed === "number" ? String(props.speed) : "1",
|
|
28590
|
-
"data-himalaya-lottie-reduce": ctx.reduceMotion() ? "1" : "0",
|
|
28591
|
-
role: "img",
|
|
28592
|
-
"aria-label": "animation",
|
|
28593
|
-
style: { width: "100%", height: lh, display: "block", ...wrap }
|
|
28594
|
-
}
|
|
28595
|
-
);
|
|
28596
|
-
}
|
|
28597
|
-
// Motion grammar (Phase-2) — Rive. @rive-app/canvas mounts to the <canvas>
|
|
28598
|
-
// browser-side via ensureRiveRuntime (dynamic import). Reduced motion → no autoplay.
|
|
28599
|
-
case "Rive": {
|
|
28600
|
-
ensureRiveRuntime();
|
|
28601
|
-
const rh = typeof props.height === "number" && props.height > 0 ? props.height : 160;
|
|
28602
|
-
return /* @__PURE__ */ jsx6(
|
|
28603
|
-
"canvas",
|
|
28604
|
-
{
|
|
28605
|
-
"data-himalaya-rive": props.source ? String(props.source) : "",
|
|
28606
|
-
"data-himalaya-rive-artboard": props.artboard ? String(props.artboard) : "",
|
|
28607
|
-
"data-himalaya-rive-sm": props.stateMachine ? String(props.stateMachine) : "",
|
|
28608
|
-
"data-himalaya-rive-autoplay": props.autoplay === false ? "0" : "1",
|
|
28609
|
-
"data-himalaya-rive-reduce": ctx.reduceMotion() ? "1" : "0",
|
|
28610
|
-
role: "img",
|
|
28611
|
-
"aria-label": "animation",
|
|
28612
|
-
style: { width: "100%", height: rh, display: "block", ...wrap }
|
|
28613
|
-
}
|
|
28614
|
-
);
|
|
28615
|
-
}
|
|
28610
|
+
// Motion grammar (Batch 4 / Phase-2) — Lottie and Rive; see LottieNode / RiveNode.
|
|
28611
|
+
case "Lottie":
|
|
28612
|
+
return /* @__PURE__ */ jsx6(LottieNode, { props, ctx, wrap });
|
|
28613
|
+
case "Rive":
|
|
28614
|
+
return /* @__PURE__ */ jsx6(RiveNode, { props, ctx, wrap });
|
|
28616
28615
|
// ───────────── forms ─────────────
|
|
28617
28616
|
case "Form":
|
|
28618
28617
|
return /* @__PURE__ */ jsx6(FormView, { props, ctx, wrap });
|
|
@@ -28681,9 +28680,9 @@ function renderInner(node, ctx) {
|
|
|
28681
28680
|
case "WorkerSubtree":
|
|
28682
28681
|
return /* @__PURE__ */ jsx6(WorkerSubtreeNode, { props, ctx, wrap, nodeId: node.id });
|
|
28683
28682
|
case "Skeleton": {
|
|
28684
|
-
const
|
|
28685
|
-
if (
|
|
28686
|
-
return /* @__PURE__ */ jsx6("div", { style: { display: "flex", flexDirection: "column", gap: 10, width: "100%", ...wrap }, children: Array.from({ length:
|
|
28683
|
+
const count2 = typeof props.count === "number" ? props.count : 1;
|
|
28684
|
+
if (count2 <= 1) return /* @__PURE__ */ jsx6("div", { style: { width: props.width ?? "100%", height: props.height ?? 14, borderRadius: props.cornerRadius ?? 6, background: C("surfaceTertiary", "#f0f0f3"), flex: "none", ...wrap } });
|
|
28685
|
+
return /* @__PURE__ */ jsx6("div", { style: { display: "flex", flexDirection: "column", gap: 10, width: "100%", ...wrap }, children: Array.from({ length: count2 }).map((_, i) => /* @__PURE__ */ jsx6("div", { style: { height: props.height ?? 22, width: `${100 - i * 8}%`, borderRadius: props.cornerRadius ?? 8, background: C("surfaceTertiary", "#f0f0f3") } }, i)) });
|
|
28687
28686
|
}
|
|
28688
28687
|
// ───────────── search & filter ─────────────
|
|
28689
28688
|
case "SearchField":
|
|
@@ -28762,7 +28761,7 @@ function renderInner(node, ctx) {
|
|
|
28762
28761
|
}
|
|
28763
28762
|
}
|
|
28764
28763
|
}
|
|
28765
|
-
var useIsomorphicLayoutEffect, ResponsiveGrid, SPLIT_EXPANDED_MIN_WIDTH, SPLIT_COLUMN_GAP, ResponsiveSplitView, ABSOLUTE_URL_RE, appearKeyframesInjected, pressStylesInjected, FOCUS_RING_CSS, focusStylesInjected, HLIST_CHILD_CSS, hListStylesInjected, listAnimateRuntimeInstalled, transitionKeyframesInjected, countUpRuntimeInjected, MEASURE_PREFIX, measureRuntimeInjected, revealRuntimeInjected, vectorAnimStylesInjected, scrollProgressRuntimeInjected, confettiRuntimeInjected, lottieRuntimeInjected, riveRuntimeInjected, gradientKeyframesInjected, parallaxRuntimeInjected, spinKeyframesInjected, marqueeKeyframesInjected, alignItems, zJustifyItems, hAlignItems, bodyFont, kids, rowKids, staggeredKids, asTextL10n, asBoundText, useBoundString, InterpolatedTextView, txt, selectFragmentCase, fragmentValueHash, fragmentSlotContent, FragmentSlotNode, WorkerSubtreeNode, resolveItemDeep2, resolveSwipeActions, resolveModBindings, resolvedComponentId, directServiceBindings, ReactiveDirectScalars, HiddenGate, KEYBOARD_INPUT_MODES, AUTOCAPITALIZE_VALUES, ENTER_KEY_HINTS, AUTOGROW_CEILING, EditableField, MenuNode, LoadMoreSentinel, FieldErrorNode, FormView, MediaSlotProvider, MEDIA_ITEM_BINDABLE, MediaPlayerView, VideoNode, PdfViewNode, WebViewNode, InteractivePicker, InteractiveDatePicker, InteractiveSearchField, InteractiveStepper, SYNTHETIC_TAP_ROLE, SYNTHETIC_TABINDEX, INFERRED_DECORATIVE, SELF_RENDERED_LEAF, ROLE_WHEN_NAMED, AUTHORED_ROLE, PENDING_RANGE, RANGE_ROLES, INTERACTIVE_ROLES, ALWAYS_INTERACTIVE_COMPONENT_TYPES, controlNode, ToggleNode, SliderNode, SelectionControlNode, TabsNode, SegmentedControlNode, DisclosureGroupNode, GridNode, SplitViewNode, TextNode, ImageNode, AvatarNode, IconNode, ButtonNode, OtpInputNode, ProgressBarNode, ActivityIndicatorNode, BottomSheetNode, ChipsInputNode, ChipNode, TableNode, GaugeRing, GaugeNode, RATING_METRICS, ratingMetrics, RatingNode, AvatarStripNode, CHART_STROKE_CYCLE, chartStrokeAt, chartBarCenter, ChartNode, donutSliceOpacity, DonutChartNode, LegendMarker, LegendNode, cellAlign, DataTableNode, voiceNoteState, voiceNoteDelivery, VOICE_NOTE_DEFAULT_BARS, clampBarCount, VoiceNoteNode, TimelineNode, WheelPickerNode, ColorPickerNode, FilterChipsNode, TILE_PX, MAX_MERCATOR_LAT, DEFAULT_TILE_MAX_ZOOM, CIRCLE_SEGMENTS, METRES_PER_DEG_LAT, MARKER_HIT_RADIUS, SHAPE_HIT_RADIUS, MapNode, CollapsingHeaderNode, UnsupportedOnSurface, CALENDAR_DATE_ONLY_RE, CAL_DEFAULT_MAX_DOTS, CAL_AGENDA_INITIAL_DAYS, CAL_AGENDA_PAGE_DAYS, CAL_DEFAULT_SNAP_MINUTES, CAL_UNASSIGNED_LANE_ID, MonthCalendarNode, TimeGridNode, AgendaNode, ARIA_ROLE, initialFocusScheduled, initialFocusSeen, PRESENTED_SCOPE, presentedOpeners, presentedObserver, A11yHintDescription, WebRenderer;
|
|
28764
|
+
var useIsomorphicLayoutEffect, ResponsiveGrid, SPLIT_EXPANDED_MIN_WIDTH, SPLIT_COLUMN_GAP, ResponsiveSplitView, ABSOLUTE_URL_RE, appearKeyframesInjected, pressStylesInjected, FOCUS_RING_CSS, focusStylesInjected, HLIST_CHILD_CSS, hListStylesInjected, listAnimateRuntimeInstalled, transitionKeyframesInjected, countUpRuntimeInjected, MEASURE_PREFIX, measureRuntimeInjected, revealRuntimeInjected, vectorAnimStylesInjected, scrollProgressRuntimeInjected, confettiRuntimeInjected, lottieRuntimeInjected, riveRuntimeInjected, gradientKeyframesInjected, parallaxRuntimeInjected, spinKeyframesInjected, marqueeKeyframesInjected, alignItems, zJustifyItems, hAlignItems, bodyFont, kids, rowKids, staggeredKids, asTextL10n, asBoundText, useBoundString, InterpolatedTextView, txt, selectFragmentCase, fragmentValueHash, fragmentSlotContent, FragmentSlotNode, WorkerSubtreeNode, resolveItemDeep2, resolveSwipeActions, resolveModBindings, resolvedComponentId, directServiceBindings, ReactiveDirectScalars, HiddenGate, KEYBOARD_INPUT_MODES, AUTOCAPITALIZE_VALUES, ENTER_KEY_HINTS, AUTOGROW_CEILING, EditableField, MenuNode, LoadMoreSentinel, FieldErrorNode, FormView, MediaSlotProvider, MEDIA_ITEM_BINDABLE, MediaPlayerView, VideoNode, PdfViewNode, WebViewNode, InteractivePicker, InteractiveDatePicker, InteractiveSearchField, InteractiveStepper, SYNTHETIC_TAP_ROLE, SYNTHETIC_TABINDEX, INFERRED_DECORATIVE, SELF_RENDERED_LEAF, ROLE_WHEN_NAMED, AUTHORED_ROLE, PENDING_RANGE, RANGE_ROLES, INTERACTIVE_ROLES, ALWAYS_INTERACTIVE_COMPONENT_TYPES, controlNode, ToggleNode, SliderNode, SelectionControlNode, TabsNode, SegmentedControlNode, DisclosureGroupNode, GridNode, SplitViewNode, TextNode, ImageNode, ANIMATION_LEAF, LottieNode, RiveNode, AvatarNode, IconNode, ButtonNode, OtpInputNode, ProgressBarNode, ActivityIndicatorNode, NATIVELY_TABBABLE, BottomSheetNode, ChipsInputNode, ChipNode, TableNode, GaugeRing, GaugeNode, RATING_METRICS, ratingMetrics, RatingNode, AvatarStripNode, CHART_STROKE_CYCLE, chartStrokeAt, chartBarCenter, ChartNode, donutSliceOpacity, DonutChartNode, LegendMarker, LegendNode, cellAlign, DataTableNode, voiceNoteState, voiceNoteDelivery, VOICE_NOTE_DEFAULT_BARS, clampBarCount, VoiceNoteNode, TimelineNode, WheelPickerNode, ColorPickerNode, FilterChipsNode, TILE_PX, MAX_MERCATOR_LAT, DEFAULT_TILE_MAX_ZOOM, CIRCLE_SEGMENTS, METRES_PER_DEG_LAT, MARKER_HIT_RADIUS, SHAPE_HIT_RADIUS, MapNode, CollapsingHeaderNode, UnsupportedOnSurface, CALENDAR_DATE_ONLY_RE, CAL_DEFAULT_MAX_DOTS, CAL_AGENDA_INITIAL_DAYS, CAL_AGENDA_PAGE_DAYS, CAL_DEFAULT_SNAP_MINUTES, CAL_UNASSIGNED_LANE_ID, MonthCalendarNode, TimeGridNode, AgendaNode, ARIA_ROLE, initialFocusScheduled, initialFocusSeen, PRESENTED_SCOPE, presentedOpeners, presentedObserver, A11yHintDescription, WebRenderer;
|
|
28766
28765
|
var init_renderNode = __esm({
|
|
28767
28766
|
"../../core/web-renderer/src/renderNode.tsx"() {
|
|
28768
28767
|
"use strict";
|
|
@@ -30524,6 +30523,39 @@ var init_renderNode = __esm({
|
|
|
30524
30523
|
}
|
|
30525
30524
|
return /* @__PURE__ */ jsx6("div", { style: { width: w, height: boxHeight, aspectRatio: ar, borderRadius: r, background: ph ?? (hasSource ? `linear-gradient(135deg, ${C("surfaceTertiary", "#e6e6e6")}, ${C("surfaceSecondary", "#f2f2f2")})` : "transparent"), color: C("textSecondary", "#999"), display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "ui-monospace, monospace", fontSize: 11, flex: "none", ...wrap }, children: banner || !hasSource ? "" : "\u2022" });
|
|
30526
30525
|
});
|
|
30526
|
+
ANIMATION_LEAF = { "aria-hidden": "true", [INFERRED_DECORATIVE]: true, [SELF_RENDERED_LEAF]: true, [ROLE_WHEN_NAMED]: "img" };
|
|
30527
|
+
LottieNode = withExtras("LottieNode", ({ props, ctx, wrap }) => {
|
|
30528
|
+
ensureLottieRuntime();
|
|
30529
|
+
const lh = typeof props.height === "number" && props.height > 0 ? props.height : 160;
|
|
30530
|
+
return /* @__PURE__ */ jsx6(
|
|
30531
|
+
"div",
|
|
30532
|
+
{
|
|
30533
|
+
"data-himalaya-lottie": props.source ? String(props.source) : "",
|
|
30534
|
+
"data-himalaya-lottie-loop": props.loop === false ? "0" : "1",
|
|
30535
|
+
"data-himalaya-lottie-autoplay": props.autoplay === false ? "0" : "1",
|
|
30536
|
+
"data-himalaya-lottie-speed": typeof props.speed === "number" ? String(props.speed) : "1",
|
|
30537
|
+
"data-himalaya-lottie-reduce": ctx.reduceMotion() ? "1" : "0",
|
|
30538
|
+
...ANIMATION_LEAF,
|
|
30539
|
+
style: { width: "100%", height: lh, display: "block", ...wrap }
|
|
30540
|
+
}
|
|
30541
|
+
);
|
|
30542
|
+
});
|
|
30543
|
+
RiveNode = withExtras("RiveNode", ({ props, ctx, wrap }) => {
|
|
30544
|
+
ensureRiveRuntime();
|
|
30545
|
+
const rh = typeof props.height === "number" && props.height > 0 ? props.height : 160;
|
|
30546
|
+
return /* @__PURE__ */ jsx6(
|
|
30547
|
+
"canvas",
|
|
30548
|
+
{
|
|
30549
|
+
"data-himalaya-rive": props.source ? String(props.source) : "",
|
|
30550
|
+
"data-himalaya-rive-artboard": props.artboard ? String(props.artboard) : "",
|
|
30551
|
+
"data-himalaya-rive-sm": props.stateMachine ? String(props.stateMachine) : "",
|
|
30552
|
+
"data-himalaya-rive-autoplay": props.autoplay === false ? "0" : "1",
|
|
30553
|
+
"data-himalaya-rive-reduce": ctx.reduceMotion() ? "1" : "0",
|
|
30554
|
+
...ANIMATION_LEAF,
|
|
30555
|
+
style: { width: "100%", height: rh, display: "block", ...wrap }
|
|
30556
|
+
}
|
|
30557
|
+
);
|
|
30558
|
+
});
|
|
30527
30559
|
AvatarNode = withExtras("AvatarNode", ({ props, ctx, wrap }) => {
|
|
30528
30560
|
const C = ctx.color;
|
|
30529
30561
|
const boundUrl = useResolvedScalar(isBinding(props.imageUrl) ? props.imageUrl : void 0, ctx);
|
|
@@ -30703,16 +30735,53 @@ var init_renderNode = __esm({
|
|
|
30703
30735
|
ensureSpinKeyframes();
|
|
30704
30736
|
return /* @__PURE__ */ jsx6("div", { role: "progressbar", style: { width: size, height: size, borderRadius: "50%", border: `${thick}px solid ${track}`, borderTopColor: tint, boxSizing: "border-box", flex: "none", animation: ctx.empty ? void 0 : "himalaya-spin 0.8s linear infinite", ...wrap } });
|
|
30705
30737
|
});
|
|
30738
|
+
NATIVELY_TABBABLE = 'a[href], area[href], button, input:not([type="hidden"]), select, textarea, iframe, object, embed, audio[controls], video[controls], summary, [contenteditable]:not([contenteditable="false"]), [tabindex]';
|
|
30706
30739
|
BottomSheetNode = withExtras("BottomSheetNode", ({ props, ctx, wrap }) => {
|
|
30707
30740
|
const sheetTitle = useBoundString(props.title, ctx);
|
|
30708
30741
|
const C = ctx.color;
|
|
30709
30742
|
const bound = useResolvedScalar(props.presentedPath, ctx);
|
|
30710
30743
|
const gated = props.presentedPath != null || props.presented != null;
|
|
30711
30744
|
const presented = props.presentedPath != null ? bound : props.presented;
|
|
30712
|
-
|
|
30745
|
+
const shown2 = !gated || presented === true || presented === "true";
|
|
30746
|
+
const modal = ariaModal(props.modal, true) === "true";
|
|
30747
|
+
const dialogRef = React5.useRef(null);
|
|
30748
|
+
useIsomorphicLayoutEffect(() => {
|
|
30749
|
+
if (!shown2 || !modal) return;
|
|
30750
|
+
const dialog = dialogRef.current;
|
|
30751
|
+
const active = dialog?.ownerDocument.activeElement;
|
|
30752
|
+
if (dialog && active instanceof HTMLElement && active !== dialog.ownerDocument.body && !dialog.contains(active)) {
|
|
30753
|
+
restoreFocusOnDismiss(dialog, active);
|
|
30754
|
+
}
|
|
30755
|
+
const layer = pushModalLayer(() => dialogRef.current);
|
|
30756
|
+
const enter = setTimeout(() => {
|
|
30757
|
+
const d = dialogRef.current;
|
|
30758
|
+
if (!d || d.contains(d.ownerDocument.activeElement)) return;
|
|
30759
|
+
if (d.querySelector("[data-himalaya-initial-focus]")) return;
|
|
30760
|
+
d.focus();
|
|
30761
|
+
}, 0);
|
|
30762
|
+
return () => {
|
|
30763
|
+
clearTimeout(enter);
|
|
30764
|
+
layer.release();
|
|
30765
|
+
};
|
|
30766
|
+
}, [shown2, modal]);
|
|
30767
|
+
const trapTab = (e) => {
|
|
30768
|
+
if (!modal || e.key !== "Tab" || e.defaultPrevented || e.nativeEvent.defaultPrevented) return;
|
|
30769
|
+
const d = dialogRef.current;
|
|
30770
|
+
if (!d) return;
|
|
30771
|
+
e.preventDefault();
|
|
30772
|
+
const stops = sheetTabStops(d);
|
|
30773
|
+
if (!stops.length) {
|
|
30774
|
+
d.focus();
|
|
30775
|
+
return;
|
|
30776
|
+
}
|
|
30777
|
+
const at = stops.indexOf(d.ownerDocument.activeElement);
|
|
30778
|
+
const next = e.shiftKey ? at <= 0 ? stops.length - 1 : at - 1 : at === -1 || at === stops.length - 1 ? 0 : at + 1;
|
|
30779
|
+
stops[next].focus();
|
|
30780
|
+
};
|
|
30781
|
+
if (!shown2) return null;
|
|
30713
30782
|
const grabber = props.showGrabber !== false;
|
|
30714
30783
|
const sheet = idiomControls(ctx.idiom).sheet;
|
|
30715
|
-
return /* @__PURE__ */ jsx6("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,.35)", zIndex: 50, display: "flex", flexDirection: "column", justifyContent: "flex-end", ...wrap }, children: /* @__PURE__ */ jsxs3("div", { role: "dialog", "aria-modal":
|
|
30784
|
+
return /* @__PURE__ */ jsx6("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,.35)", zIndex: 50, display: "flex", flexDirection: "column", justifyContent: "flex-end", ...wrap }, children: /* @__PURE__ */ jsxs3("div", { ref: dialogRef, role: "dialog", "aria-modal": modal ? "true" : void 0, tabIndex: modal ? -1 : void 0, onKeyDown: modal ? trapTab : void 0, "aria-label": props.title != null ? sheetTitle : "Sheet", style: { width: "100%", background: C("surfacePrimary", "#fff"), borderRadius: `${sheet.cornerRadius}px ${sheet.cornerRadius}px 0 0`, boxShadow: "0 -4px 24px rgba(0,0,0,.12)", overflow: "hidden" }, children: [
|
|
30716
30785
|
grabber && /* @__PURE__ */ jsx6("div", { style: { display: "flex", justifyContent: "center", padding: "8px 0 4px" }, children: /* @__PURE__ */ jsx6("div", { style: { width: sheet.grabberWidth, height: sheet.grabberHeight, borderRadius: 999, background: C("surfaceTertiary", "#d8dce2") } }) }),
|
|
30717
30786
|
/* @__PURE__ */ jsx6("div", { style: { padding: "8px 16px 16px" }, children: props.content ? renderNode(props.content, ctx) : null })
|
|
30718
30787
|
] }) });
|
|
@@ -30841,8 +30910,8 @@ var init_renderNode = __esm({
|
|
|
30841
30910
|
const overflow = props.overflowCount || Math.max(0, avatars.length - maxVisible);
|
|
30842
30911
|
const shift = Math.round(size * (1 - (props.overlapRatio ?? 0.67)));
|
|
30843
30912
|
const caption = useBoundString(props.caption, ctx).trim();
|
|
30844
|
-
const
|
|
30845
|
-
const countText =
|
|
30913
|
+
const count2 = shown2.length + overflow;
|
|
30914
|
+
const countText = count2 > 0 ? `${count2} ${count2 === 1 ? "person" : "people"}` : "";
|
|
30846
30915
|
const groupName = [caption, countText].filter(Boolean).join(", ");
|
|
30847
30916
|
return /* @__PURE__ */ jsxs3("div", { role: "group", "aria-label": groupName || void 0, "data-a11y-value": countText || void 0, ...{ [SELF_RENDERED_LEAF]: true }, style: { width: "100%", ...wrap }, children: [
|
|
30848
30917
|
/* @__PURE__ */ jsxs3("div", { style: { display: "flex" }, children: [
|
|
@@ -31157,7 +31226,7 @@ var init_renderNode = __esm({
|
|
|
31157
31226
|
const W = 100, H = 100;
|
|
31158
31227
|
const slot = bars.length > 0 ? W / bars.length : W;
|
|
31159
31228
|
const barW = Math.max(0.6, slot * 0.58);
|
|
31160
|
-
const
|
|
31229
|
+
const cut2 = progress * W;
|
|
31161
31230
|
const rates = Array.isArray(props.rates) ? props.rates.map(Number).filter((n) => n > 0) : [];
|
|
31162
31231
|
const [pickedRate, setPickedRate] = React5.useState(null);
|
|
31163
31232
|
React5.useEffect(() => {
|
|
@@ -31268,7 +31337,7 @@ var init_renderNode = __esm({
|
|
|
31268
31337
|
height: bh,
|
|
31269
31338
|
rx: barW / 2,
|
|
31270
31339
|
fill: accent,
|
|
31271
|
-
opacity: cx <=
|
|
31340
|
+
opacity: cx <= cut2 ? isPlayable ? 1 : 0.45 : isPlayable ? 0.28 : 0.16
|
|
31272
31341
|
},
|
|
31273
31342
|
i
|
|
31274
31343
|
);
|
|
@@ -36184,7 +36253,7 @@ async function handleWebWix(req, res, state) {
|
|
|
36184
36253
|
const session = webWixSession(req, res, state);
|
|
36185
36254
|
const auth = resolveWebWixAuth(state.app);
|
|
36186
36255
|
const path2 = new URL(req.url ?? "", "http://localhost").pathname;
|
|
36187
|
-
const
|
|
36256
|
+
const readJson6 = async () => {
|
|
36188
36257
|
const chunks = [];
|
|
36189
36258
|
for await (const c of req) chunks.push(c);
|
|
36190
36259
|
const t = Buffer.concat(chunks).toString("utf8");
|
|
@@ -36201,7 +36270,7 @@ async function handleWebWix(req, res, state) {
|
|
|
36201
36270
|
res.end(JSON.stringify(obj3));
|
|
36202
36271
|
};
|
|
36203
36272
|
if (path2 === "/v1/__webwix/login" && req.method === "POST") {
|
|
36204
|
-
const b = await
|
|
36273
|
+
const b = await readJson6();
|
|
36205
36274
|
try {
|
|
36206
36275
|
const { memberToken, visitorToken } = await memberDirectLogin(
|
|
36207
36276
|
auth.clientId,
|
|
@@ -36218,7 +36287,7 @@ async function handleWebWix(req, res, state) {
|
|
|
36218
36287
|
}
|
|
36219
36288
|
}
|
|
36220
36289
|
if (path2 === "/v1/__webwix/call" && req.method === "POST") {
|
|
36221
|
-
const b = await
|
|
36290
|
+
const b = await readJson6();
|
|
36222
36291
|
const ownerRung = b.ownerMsid !== void 0 || b.checkOwnerSession === true;
|
|
36223
36292
|
const msid = String(b.ownerMsid ?? "");
|
|
36224
36293
|
const cookie = req.headers.cookie ?? "";
|
|
@@ -36366,7 +36435,7 @@ async function handleWebWix(req, res, state) {
|
|
|
36366
36435
|
});
|
|
36367
36436
|
}
|
|
36368
36437
|
if (path2 === "/v1/__webwix/register" && req.method === "POST") {
|
|
36369
|
-
const b = await
|
|
36438
|
+
const b = await readJson6();
|
|
36370
36439
|
try {
|
|
36371
36440
|
const { memberToken, visitorToken } = await memberDirectRegister(
|
|
36372
36441
|
auth.clientId,
|
|
@@ -39365,10 +39434,10 @@ function effectSince(w, mark, action, componentId) {
|
|
|
39365
39434
|
}
|
|
39366
39435
|
function resolveSiteRows(itemsPath, valueOf) {
|
|
39367
39436
|
if (!itemsPath || itemsPath === UNTRACKED_ITEMS) return void 0;
|
|
39368
|
-
const
|
|
39369
|
-
if (
|
|
39370
|
-
const outer = valueOf(itemsPath.slice(0,
|
|
39371
|
-
const field = itemsPath.slice(
|
|
39437
|
+
const cut2 = itemsPath.indexOf(NESTED_ITEMS_SEP);
|
|
39438
|
+
if (cut2 < 0) return valueOf(itemsPath);
|
|
39439
|
+
const outer = valueOf(itemsPath.slice(0, cut2));
|
|
39440
|
+
const field = itemsPath.slice(cut2 + NESTED_ITEMS_SEP.length);
|
|
39372
39441
|
const first = Array.isArray(outer) ? outer[0] : void 0;
|
|
39373
39442
|
return first && typeof first === "object" ? first[field] : void 0;
|
|
39374
39443
|
}
|
|
@@ -39523,6 +39592,7 @@ async function crawlScreenInner(opts) {
|
|
|
39523
39592
|
const findings = [];
|
|
39524
39593
|
const actionsSkipped = [];
|
|
39525
39594
|
const navEdges = [];
|
|
39595
|
+
const navUnfollowed = /* @__PURE__ */ new Set();
|
|
39526
39596
|
const unobservedActions = [];
|
|
39527
39597
|
const effects = [];
|
|
39528
39598
|
let observations;
|
|
@@ -39545,7 +39615,10 @@ async function crawlScreenInner(opts) {
|
|
|
39545
39615
|
return pathValue(row0, path2);
|
|
39546
39616
|
};
|
|
39547
39617
|
const target = resolveItem(merged.screenId);
|
|
39548
|
-
if (typeof target !== "string" || !target || target.includes("$"))
|
|
39618
|
+
if (typeof target !== "string" || !target || target.includes("$")) {
|
|
39619
|
+
navUnfollowed.add(`tap:${site.componentId ?? JSON.stringify(site.params ?? {})}`);
|
|
39620
|
+
continue;
|
|
39621
|
+
}
|
|
39549
39622
|
const params = {};
|
|
39550
39623
|
for (const [k, v] of Object.entries(merged)) {
|
|
39551
39624
|
if (k === "screenId" || k === "presentation") continue;
|
|
@@ -39558,7 +39631,10 @@ async function crawlScreenInner(opts) {
|
|
|
39558
39631
|
};
|
|
39559
39632
|
const drainWorkerEdges = (w, via) => {
|
|
39560
39633
|
for (const d of w.navDirectives.splice(0)) {
|
|
39561
|
-
if (!d.screenId || d.screenId.includes("$"))
|
|
39634
|
+
if (!d.screenId || d.screenId.includes("$")) {
|
|
39635
|
+
navUnfollowed.add(`${via}:${d.screenId ?? ""}`);
|
|
39636
|
+
continue;
|
|
39637
|
+
}
|
|
39562
39638
|
const params = {};
|
|
39563
39639
|
for (const [k, v] of Object.entries(d.args)) if (!v.includes("$")) params[k] = v;
|
|
39564
39640
|
navEdges.push({ target: d.screenId, params, via });
|
|
@@ -39939,7 +40015,7 @@ async function crawlScreenInner(opts) {
|
|
|
39939
40015
|
const edges = dedupeEdges(navEdges);
|
|
39940
40016
|
if (linkableScreenIds?.size && !opts.capabilitySuccess) {
|
|
39941
40017
|
const linkable = linkableScreenIds;
|
|
39942
|
-
const
|
|
40018
|
+
const resolvesToLinkable2 = (target) => {
|
|
39943
40019
|
if (linkable.has(target)) return true;
|
|
39944
40020
|
for (const base of linkable) {
|
|
39945
40021
|
if (target.length > base.length + 1 && target.startsWith(base)) {
|
|
@@ -39953,7 +40029,7 @@ async function crawlScreenInner(opts) {
|
|
|
39953
40029
|
for (const e of edges) {
|
|
39954
40030
|
if (e.target === screenId) continue;
|
|
39955
40031
|
if (reported.has(e.target)) continue;
|
|
39956
|
-
if (knownScreenIds.has(e.target) ||
|
|
40032
|
+
if (knownScreenIds.has(e.target) || resolvesToLinkable2(e.target)) continue;
|
|
39957
40033
|
reported.add(e.target);
|
|
39958
40034
|
findings.push({
|
|
39959
40035
|
screen: screenId,
|
|
@@ -39974,6 +40050,7 @@ async function crawlScreenInner(opts) {
|
|
|
39974
40050
|
actionsExercised: exercised,
|
|
39975
40051
|
actionsSkipped,
|
|
39976
40052
|
navEdges: edges,
|
|
40053
|
+
...navUnfollowed.size ? { navUnfollowed: navUnfollowed.size } : {},
|
|
39977
40054
|
...effects.length ? { effects } : {},
|
|
39978
40055
|
...observations ? { observations } : {},
|
|
39979
40056
|
...unobservedActions.length ? { unobservedActions } : {},
|
|
@@ -42029,6 +42106,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
42029
42106
|
...collect2?.lint ? { lint, workers } : {},
|
|
42030
42107
|
...collect2?.render ? { renders } : {},
|
|
42031
42108
|
...collect2?.descriptors ? { descriptors: baked, linkableScreenIds: [...linkable] } : {},
|
|
42109
|
+
...collect2?.descriptors && typeof preloaded.meta.homeScreenId === "string" && preloaded.meta.homeScreenId ? { homeScreenId: preloaded.meta.homeScreenId } : {},
|
|
42032
42110
|
...renderTokens !== void 0 ? { tokens: renderTokens } : {},
|
|
42033
42111
|
...preloaded.meta.surfaces ? { surfaceNav: preloaded.meta.surfaces } : {},
|
|
42034
42112
|
auth: (() => {
|
|
@@ -42294,6 +42372,27 @@ h2{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;le
|
|
|
42294
42372
|
.lant{font-weight:600}
|
|
42295
42373
|
.lanu{font-size:12px;word-break:break-all}
|
|
42296
42374
|
.lanh{color:var(--muted);font-size:12px;margin-top:4px}
|
|
42375
|
+
.mbox{overflow-x:auto}
|
|
42376
|
+
.msum{color:var(--muted);font-size:12px;margin-bottom:8px}
|
|
42377
|
+
.mnode rect{fill:var(--card);stroke:var(--line);stroke-width:1.2}
|
|
42378
|
+
.mnode text{font-size:11px;fill:var(--ink)}
|
|
42379
|
+
.mnode.ok rect{fill:var(--okbg);stroke:var(--ok)}
|
|
42380
|
+
.mnode.failed rect{fill:var(--badbg);stroke:var(--bad)}
|
|
42381
|
+
.mnode.pending rect{stroke-dasharray:4 3}
|
|
42382
|
+
.mnode.skipped text{fill:var(--muted)}
|
|
42383
|
+
.mnode.entry rect{stroke-width:2.4}
|
|
42384
|
+
.mnode.unreached rect{fill:var(--warnbg);stroke:var(--warn);stroke-dasharray:4 3}
|
|
42385
|
+
.medge{fill:none;stroke:var(--faint);stroke-width:1.2}
|
|
42386
|
+
.mbroken{font-size:11px;fill:var(--bad)}
|
|
42387
|
+
.mrow{font-size:11px;fill:var(--warn)}
|
|
42388
|
+
.mfollow{font-size:9px;fill:var(--warn)}
|
|
42389
|
+
.mnode.unfollowed rect{stroke:var(--warn)}
|
|
42390
|
+
.changes{margin-top:12px;padding:10px 12px;border:1px solid var(--line);border-radius:12px;font-size:12px}
|
|
42391
|
+
.changes .cht{font-weight:600;margin-bottom:4px}
|
|
42392
|
+
.changes ul{margin:0;padding-left:16px}
|
|
42393
|
+
.changes li{margin:2px 0;word-break:break-word}
|
|
42394
|
+
.changes .sw{display:inline-block;width:10px;height:10px;border-radius:3px;margin-left:6px;vertical-align:middle;border:1px solid var(--line)}
|
|
42395
|
+
.changes .chm{color:var(--muted);margin-top:2px}
|
|
42297
42396
|
.film{display:flex;gap:6px;overflow-x:auto;margin-top:12px;padding-bottom:4px}.film img{width:48px;aspect-ratio:390/844;object-fit:cover;object-position:top;border-radius:8px;border:1px solid var(--line);cursor:zoom-in}
|
|
42298
42397
|
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}.chip{font-size:12px;padding:5px 10px;border-radius:999px;background:var(--card);border:1px solid var(--line);color:var(--muted)}
|
|
42299
42398
|
.chip.ok{background:var(--okbg);color:var(--ok);border-color:transparent}.chip.warn{background:var(--warnbg);color:var(--warn);border-color:transparent}.chip.bad{background:var(--badbg);color:var(--bad);border-color:transparent}
|
|
@@ -42351,6 +42450,7 @@ h2{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;le
|
|
|
42351
42450
|
<div class="card section"><h2>Screens</h2><div class="wall" id="wall"></div></div>
|
|
42352
42451
|
<div class="card section" id="brandcard"><h2>Brand</h2><div class="brand" id="brand"></div></div>
|
|
42353
42452
|
<div class="card section" id="navcard"><h2>Navigation the test crawl followed</h2><div class="nav" id="nav"></div></div>
|
|
42453
|
+
<div class="card section" id="appmap" hidden><h2>App map</h2><div class="msum" id="msum"></div><div class="mbox" id="mapbox"></div></div>
|
|
42354
42454
|
<div class="card section"><h2>Postcards</h2><ul class="log" id="log"></ul></div>
|
|
42355
42455
|
</div></div></div>
|
|
42356
42456
|
<div id="lb"><img alt=""></div>
|
|
@@ -42362,6 +42462,48 @@ h2{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;le
|
|
|
42362
42462
|
var cur=null, lastSeen=Date.now();
|
|
42363
42463
|
function $(id){return document.getElementById(id)}
|
|
42364
42464
|
function el(tag,cls,txt){var e=document.createElement(tag);if(cls)e.className=cls;if(txt!=null)e.textContent=txt;return e}
|
|
42465
|
+
/* #3342 \u2014 the app map. Layers are the distance from an entry (tab roots, or the first screen), the
|
|
42466
|
+
screens nothing leads to sit in their own last row, a link to a screen that does not exist is a red
|
|
42467
|
+
stub naming it. Built with DOM calls: a screen id is SVG text, never markup. Past 60 screens only
|
|
42468
|
+
the ones worth looking at are drawn (unreached, failed) and the summary carries the rest. */
|
|
42469
|
+
function drawMap(m){var card=$("appmap"),box=$("mapbox");clear(box);if(!m){card.hidden=true;return}card.hidden=false;
|
|
42470
|
+
var un=m.screens.filter(function(x){return !x.reached});
|
|
42471
|
+
/* "Nothing leads here" only when the crawl saw every link: a link built from list data (a feed's rows,
|
|
42472
|
+
a home grid) has a target it cannot resolve, and one of those may well open the screen. */
|
|
42473
|
+
var gone=!m.done?" not reached yet \xB7 ":m.unfollowed?" not seen linked \xB7 ":" unreached \xB7 ";
|
|
42474
|
+
$("msum").textContent=m.screens.length+" screens \xB7 "+un.length+gone+m.broken.length+" broken link"+(m.broken.length===1?"":"s")+(m.unfollowed?" \xB7 "+m.unfollowed+" link"+(m.unfollowed===1?"":"s")+" the crawl could not follow":"")+(m.edgesDropped?" \xB7 "+m.edgesDropped+" more link"+(m.edgesDropped===1?"":"s")+" not drawn":"")+(m.done?"":" \xB7 crawling");
|
|
42475
|
+
var show=m.screens.length>60?m.screens.filter(function(x){return !x.reached||x.status==="failed"}):m.screens,on={};show.forEach(function(x){on[x.id]=1});
|
|
42476
|
+
var out={},depth={},q=[];m.edges.forEach(function(e){if(on[e.from]&&on[e.to])(out[e.from]=out[e.from]||[]).push(e.to)});
|
|
42477
|
+
show.forEach(function(x){if(x.entry){depth[x.id]=0;q.push(x.id)}});
|
|
42478
|
+
while(q.length){var c=q.shift();(out[c]||[]).forEach(function(t){if(depth[t]==null){depth[t]=depth[c]+1;q.push(t)}})}
|
|
42479
|
+
var maxd=0;show.forEach(function(x){if(depth[x.id]>maxd)maxd=depth[x.id]});
|
|
42480
|
+
var rows=[];show.forEach(function(x){var r=!x.reached?maxd+2:depth[x.id]!=null?depth[x.id]:maxd+1;(rows[r]=rows[r]||[]).push(x)});
|
|
42481
|
+
/* Nodes are as wide as the longest id drawn needs (up to 300px): an id cut to its first letters
|
|
42482
|
+
cannot be told from its template siblings, which differ only at the end. Past that, the middle
|
|
42483
|
+
goes and both ends stay; the full id is always in the node's title. */
|
|
42484
|
+
var CW=6.5,longest=0;show.forEach(function(x){longest=Math.max(longest,x.id.length)});
|
|
42485
|
+
var W=Math.round(Math.min(300,Math.max(124,longest*CW+20))),H=28,HG=12,VG=36,P=10,ns="http://www.w3.org/2000/svg",pos={},y=P,width=0,unRow=maxd+2;
|
|
42486
|
+
function lab(id){var k=Math.floor((W-20)/CW);if(id.length<=k)return id;var a=Math.ceil((k-1)/2),b=Math.floor((k-1)/2);return id.slice(0,a)+"\u2026"+id.slice(id.length-b)}
|
|
42487
|
+
var svg=document.createElementNS(ns,"svg"),edgesG=document.createElementNS(ns,"g"),nodesG=document.createElementNS(ns,"g");svg.appendChild(edgesG);svg.appendChild(nodesG);
|
|
42488
|
+
function sv(tag,attrs,txt){var e=document.createElementNS(ns,tag);for(var k in attrs)e.setAttribute(k,String(attrs[k]));if(txt!=null)e.textContent=txt;return e}
|
|
42489
|
+
for(var r=0;r<rows.length;r++){var row=rows[r];if(!row)continue;
|
|
42490
|
+
if(r===unRow){nodesG.appendChild(sv("text",{x:P,y:y+10,"class":"mrow"},!m.done?"Not reached yet \u2014 no link to these seen so far":m.unfollowed?"Not seen linked \u2014 "+m.unfollowed+" link"+(m.unfollowed===1?"":"s")+" built from list data could not be followed":"Unreached \u2014 nothing leads here"));y+=16}
|
|
42491
|
+
row.forEach(function(x,i){var nx=P+i*(W+HG);pos[x.id]={x:nx,y:y};width=Math.max(width,nx+W+P);
|
|
42492
|
+
var g=sv("g",{"class":"mnode "+x.status+(x.entry?" entry":"")+(x.reached?"":" unreached")+(x.unfollowed?" unfollowed":""),"data-id":x.id});
|
|
42493
|
+
g.appendChild(sv("rect",{x:nx,y:y,width:W,height:H,rx:7}));g.appendChild(sv("text",{x:nx+W/2,y:y+H/2+4,"text-anchor":"middle"},lab(x.id)));
|
|
42494
|
+
g.appendChild(sv("title",{},x.id+" \xB7 "+x.status+(x.entry?" \xB7 entry":"")+(x.reached?"":" \xB7 unreached")+(x.unfollowed?" \xB7 "+x.unfollowed+" links the crawl could not follow":"")));
|
|
42495
|
+
if(x.unfollowed)g.appendChild(sv("text",{x:nx+W-6,y:y+10,"text-anchor":"end","class":"mfollow"},"+"+x.unfollowed+"?"));nodesG.appendChild(g)});
|
|
42496
|
+
y+=H+VG}
|
|
42497
|
+
m.edges.forEach(function(e){var a=pos[e.from],b=pos[e.to];if(!a||!b)return;var x1=a.x+W/2,y1=a.y+H,x2=b.x+W/2,y2=b.y,my=(y1+y2)/2;
|
|
42498
|
+
edgesG.appendChild(sv("path",{"class":"medge",d:"M"+x1+" "+y1+" C"+x1+" "+my+" "+x2+" "+my+" "+x2+" "+y2}))});
|
|
42499
|
+
var by=y;m.broken.forEach(function(e,i){var a=pos[e.from];if(!a)return;var bx=a.x+W+4,yy=a.y+H/2+4+i%2*10;
|
|
42500
|
+
nodesG.appendChild(sv("text",{x:bx,y:yy,"class":"mbroken"},"\u2192 missing: "+e.to));width=Math.max(width,bx+170)});
|
|
42501
|
+
svg.setAttribute("width",String(Math.max(width,200)));svg.setAttribute("height",String(Math.max(by,40)));svg.setAttribute("role","img");svg.setAttribute("aria-label","App map: "+$("msum").textContent);box.appendChild(svg)}
|
|
42502
|
+
/* #3342 \u2014 what the last rebuild changed, one line each, already text (studio.ts formats it); a hex
|
|
42503
|
+
token gets old/new swatches, painted through style, never markup. */
|
|
42504
|
+
function changesCard(b){var d=el("div","changes");d.appendChild(el("div","cht","What changed \xB7 "+hhmm(b.at)));var ul=document.createElement("ul");
|
|
42505
|
+
b.changes.lines.forEach(function(l){var li=el("li",null,l.text);if(l.from){var a=el("span","sw");a.style.background=l.from;li.appendChild(a)}if(l.to){var z=el("span","sw");z.style.background=l.to;li.appendChild(z)}ul.appendChild(li)});
|
|
42506
|
+
d.appendChild(ul);if(b.changes.more)d.appendChild(el("div","chm","+"+b.changes.more+" more"));return d}
|
|
42365
42507
|
/* #3250 \u2014 a --lan run's way onto the owner's phone. The QR arrives as rows of 1/0 modules and is drawn
|
|
42366
42508
|
as ONE path of unit squares: built with DOM calls, so nothing in the URL can become markup. */
|
|
42367
42509
|
function lanCard(lan){var d=el("div","lan");d.appendChild(el("div","lant","Open on your phone"));
|
|
@@ -42397,7 +42539,7 @@ function render(s){
|
|
|
42397
42539
|
if(pip){paintStrip(s)}else{
|
|
42398
42540
|
var kept=s.live?focus.querySelector("iframe"):null;if(kept&&(kept.getAttribute("src")!==s.live.url||kept.getAttribute("data-run")!==s.live.runId))kept=null;
|
|
42399
42541
|
if(kept){while(focus.lastChild&&focus.lastChild!==kept.parentNode)focus.removeChild(focus.lastChild)}else clear(focus);
|
|
42400
|
-
if(s.live){$("focuslbl").textContent="Live preview";if(!kept){var f=el("div","phone vpf");var fr=document.createElement("iframe");fr.className="vp";fr.setAttribute("width","390");fr.setAttribute("height","844");fr.setAttribute("data-run",s.live.runId);fr.src=s.live.url;fr.title="Live preview";f.appendChild(fr);focus.appendChild(f)}fit();if(s.live.buildError){var be=el("div","chip bad",null);be.style.display="block";be.style.marginTop="8px";be.textContent="Last edit did not build, still showing the last good version: "+s.live.buildError;focus.appendChild(be)}focus.appendChild(el("div","cap",(s.live.watching?"Repaints as the app is edited \xB7 ":"The build this run started with; himi run --watch repaints on every edit \xB7 ")+s.live.url));if(s.live.lan)focus.appendChild(lanCard(s.live.lan))}
|
|
42542
|
+
if(s.live){$("focuslbl").textContent="Live preview";if(!kept){var f=el("div","phone vpf");var fr=document.createElement("iframe");fr.className="vp";fr.setAttribute("width","390");fr.setAttribute("height","844");fr.setAttribute("data-run",s.live.runId);fr.src=s.live.url;fr.title="Live preview";f.appendChild(fr);focus.appendChild(f)}fit();if(s.live.buildError){var be=el("div","chip bad",null);be.style.display="block";be.style.marginTop="8px";be.textContent="Last edit did not build, still showing the last good version: "+s.live.buildError;focus.appendChild(be)}focus.appendChild(el("div","cap",(s.live.watching?"Repaints as the app is edited \xB7 ":"The build this run started with; himi run --watch repaints on every edit \xB7 ")+s.live.url));if(s.live.lan)focus.appendChild(lanCard(s.live.lan));if(s.live.lastBuild&&s.live.lastBuild.changes)focus.appendChild(changesCard(s.live.lastBuild))}
|
|
42401
42543
|
else if(s.focus&&s.focus.frames.length){var fl=s.focus.frames;$("focuslbl").textContent="Latest \xB7 "+s.focus.id;var p=el("div","phone");p.appendChild(img(fl[fl.length-1].img));focus.appendChild(p);focus.appendChild(el("div","cap",fl.length+(fl.length===1?" version":" versions")+" so far"))}
|
|
42402
42544
|
else{$("focuslbl").textContent="Latest";focus.appendChild(el("div","empty","The first render appears here."))}
|
|
42403
42545
|
if(s.focus&&s.focus.frames.length>1)s.focus.frames.forEach(function(fm){film.appendChild(img(fm.img))});}}
|
|
@@ -42415,7 +42557,7 @@ function render(s){
|
|
|
42415
42557
|
if(s.brand.site){var si=img(s.brand.site,"site");brand.appendChild(si)}
|
|
42416
42558
|
if(s.brand.site&&s.focus&&s.focus.frames.length){brand.appendChild(el("span","sub","\u2192"));var pf=el("div","shot");pf.style.width="90px";var ff=el("div","frame");ff.appendChild(img(s.focus.frames[s.focus.frames.length-1].img));pf.appendChild(ff);brand.appendChild(pf)}
|
|
42417
42559
|
if(s.app.palette.length){var sw=el("div","sw");s.app.palette.forEach(function(c){var d=el("span");d.style.background=c.hex;d.title=c.name+" "+c.hex;sw.appendChild(d)});brand.appendChild(sw)}
|
|
42418
|
-
var nav=$("nav");clear(nav);$("navcard").style.display=s.nav.length?"":"none";s.nav.forEach(function(e){nav.appendChild(el("span",null,e.from+" \u2192 "+e.to))});
|
|
42560
|
+
var nav=$("nav");clear(nav);$("navcard").style.display=s.nav.length&&!s.map?"":"none";drawMap(s.map);s.nav.forEach(function(e){nav.appendChild(el("span",null,e.from+" \u2192 "+e.to))});
|
|
42419
42561
|
var log=$("log");clear(log);if(!s.journal.length)log.appendChild(el("li","empty","Postcards the agent journals appear here."));
|
|
42420
42562
|
s.journal.forEach(function(j){var li=el("li");li.appendChild(el("div","t",hhmm(j.ts)));var body=el("div");body.appendChild(el("div",null,j.message));if(j.step)body.appendChild(el("div","s","step "+j.stepNumber+" \xB7 "+j.step));
|
|
42421
42563
|
if(j.images.length){var row=el("div","imgs");j.images.forEach(function(u){row.appendChild(img(u))});body.appendChild(row)}li.appendChild(body);log.appendChild(li)});
|
|
@@ -42535,7 +42677,7 @@ function favicon(n,bad){try{var c=document.createElement("canvas");c.width=c.hei
|
|
|
42535
42677
|
function burst(){var c=$("fx");c.setAttribute("data-bursts",String((+c.getAttribute("data-bursts")||0)+1));if(reduced())return;var x=c.getContext&&c.getContext("2d");if(!x)return;var W=c.width=innerWidth,H=c.height=innerHeight,cols=["#1f7a4d","#3b6fd8","#e0a030","#d4537e",accentNow()],P=[];for(var i=0;i<120;i++)P.push({x:W/2,y:H*.35,vx:(Math.random()-.5)*14,vy:-Math.random()*12-4,c:cols[i%cols.length],r:Math.random()*6.28});var t0=now();(function f(){x.clearRect(0,0,W,H);P.forEach(function(p){p.x+=p.vx;p.y+=p.vy;p.vy+=.35;p.r+=.2;x.save();x.translate(p.x,p.y);x.rotate(p.r);x.fillStyle=p.c;x.fillRect(-4,-2,8,4);x.restore()});if(now()-t0<2200)raf(f);else x.clearRect(0,0,W,H)})()}
|
|
42536
42678
|
function countTo(e,a,b){if(!e)return;if(reduced()){e.textContent=String(b);return}var t0=now();(function f(){var k=Math.min(1,(now()-t0)/900);e.textContent=String(Math.round(a+(b-a)*k));if(k<1)raf(f)})()}
|
|
42537
42679
|
function snap(s){var sc={},acc=null;s.screens.forEach(function(x){sc[x.id]=x.img});s.app.palette.forEach(function(p){if(p.name==="accentPrimary")acc=p.hex});return{screens:sc,step:s.current?s.current.stepNumber:0,top:s.journal[0]?s.journal[0].ts:null,build:s.live&&s.live.lastBuild?s.live.lastBuild.at:s.pastBuild?s.pastBuild.at:null,run:s.live?s.live.runId:s.pastBuild?s.pastBuild.run:null,push:s.health.push?s.health.push.releaseId:null,gaps:s.health.test?s.health.test.gaps:null,accent:acc,reveal:s.reveal?s.reveal.at:null}}
|
|
42538
|
-
function buildLine(b){if(!b.ok)return "Build failed \xB7 still showing the last good version";var what=b.screens.length?b.screens.slice(0,3).join(", ")+(b.screens.length>3?" +"+(b.screens.length-3):""):b.tokens?"design tokens":b.config?"app config":"no visible change";return "Rebuilt"+(b.ms!=null?" in "+(b.ms/1000).toFixed(1)+" s":"")+" \xB7 "+what}
|
|
42680
|
+
function buildLine(b){if(!b.ok)return "Build failed \xB7 still showing the last good version";var what=b.headline?b.headline:b.screens.length?b.screens.slice(0,3).join(", ")+(b.screens.length>3?" +"+(b.screens.length-3):""):b.tokens?"design tokens":b.config?"app config":"no visible change";return "Rebuilt"+(b.ms!=null?" in "+(b.ms/1000).toFixed(1)+" s":"")+" \xB7 "+what}
|
|
42539
42681
|
function effects(s){var is=snap(s),was=seen;seen=is;if(is.accent)document.documentElement.style.setProperty("--accent",is.accent);
|
|
42540
42682
|
/* The phone (kept across renders) and the Now line outlive a render: clear what they played last. */
|
|
42541
42683
|
var stage=rewinding?$("still"):$("focus"),ph=stage.querySelector(".phone"),nm=$("nowmsg");if(ph)ph.classList.remove("pulse","bad");nm.classList.remove("slidein");if(!was)return;
|
|
@@ -42598,9 +42740,174 @@ var init_studio_page = __esm({
|
|
|
42598
42740
|
}
|
|
42599
42741
|
});
|
|
42600
42742
|
|
|
42601
|
-
// src/
|
|
42602
|
-
|
|
42743
|
+
// src/build-changes.ts
|
|
42744
|
+
var build_changes_exports = {};
|
|
42745
|
+
__export(build_changes_exports, {
|
|
42746
|
+
boardLines: () => boardLines,
|
|
42747
|
+
describeChanges: () => describeChanges,
|
|
42748
|
+
diffDescriptors: () => diffDescriptors,
|
|
42749
|
+
diffTokens: () => diffTokens,
|
|
42750
|
+
headline: () => headline
|
|
42751
|
+
});
|
|
42752
|
+
import { existsSync as existsSync40, readdirSync as readdirSync22, readFileSync as readFileSync43 } from "node:fs";
|
|
42603
42753
|
import { join as join38 } from "node:path";
|
|
42754
|
+
function componentsOf(descriptor) {
|
|
42755
|
+
const out = /* @__PURE__ */ new Map();
|
|
42756
|
+
visitComponents(descriptor, (n) => {
|
|
42757
|
+
if (typeof n.id !== "string" || out.has(n.id)) return;
|
|
42758
|
+
const props = typeof n.body.props === "object" && n.body.props !== null ? n.body.props : {};
|
|
42759
|
+
out.set(n.id, { type: n.body.type, props });
|
|
42760
|
+
});
|
|
42761
|
+
return out;
|
|
42762
|
+
}
|
|
42763
|
+
function diffDescriptors(screen, before, after) {
|
|
42764
|
+
const a = componentsOf(before);
|
|
42765
|
+
const b = componentsOf(after);
|
|
42766
|
+
const props = [];
|
|
42767
|
+
const added = [];
|
|
42768
|
+
for (const [id, now] of b) {
|
|
42769
|
+
const was = a.get(id);
|
|
42770
|
+
if (!was) {
|
|
42771
|
+
added.push({ kind: "added", screen, node: id, type: now.type });
|
|
42772
|
+
continue;
|
|
42773
|
+
}
|
|
42774
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(was.props), ...Object.keys(now.props)]);
|
|
42775
|
+
for (const key2 of keys) {
|
|
42776
|
+
const x = was.props[key2];
|
|
42777
|
+
const y = now.props[key2];
|
|
42778
|
+
if (!scalar2(x) && !scalar2(y)) continue;
|
|
42779
|
+
if (x === y) continue;
|
|
42780
|
+
props.push({
|
|
42781
|
+
kind: TEXT_PROPS.has(key2) ? "text" : "prop",
|
|
42782
|
+
screen,
|
|
42783
|
+
node: id,
|
|
42784
|
+
path: key2,
|
|
42785
|
+
...scalar2(x) ? { from: cut(String(x)) } : {},
|
|
42786
|
+
...scalar2(y) ? { to: cut(String(y)) } : {}
|
|
42787
|
+
});
|
|
42788
|
+
}
|
|
42789
|
+
}
|
|
42790
|
+
const removed = [];
|
|
42791
|
+
for (const [id, was] of a) if (!b.has(id)) removed.push({ kind: "removed", screen, node: id, type: was.type });
|
|
42792
|
+
return [...props.filter((c) => c.kind === "text"), ...added, ...removed, ...props.filter((c) => c.kind === "prop")];
|
|
42793
|
+
}
|
|
42794
|
+
function leaves(value, prefix, out) {
|
|
42795
|
+
if (scalar2(value)) {
|
|
42796
|
+
out.set(prefix, String(value));
|
|
42797
|
+
return;
|
|
42798
|
+
}
|
|
42799
|
+
if (typeof value !== "object" || value === null) return;
|
|
42800
|
+
for (const [k, v] of Object.entries(value)) leaves(v, prefix ? `${prefix}.${k}` : k, out);
|
|
42801
|
+
}
|
|
42802
|
+
function diffTokens(before, after) {
|
|
42803
|
+
const a = /* @__PURE__ */ new Map();
|
|
42804
|
+
const b = /* @__PURE__ */ new Map();
|
|
42805
|
+
leaves(before, "", a);
|
|
42806
|
+
leaves(after, "", b);
|
|
42807
|
+
const paths = [.../* @__PURE__ */ new Set([...a.keys(), ...b.keys()])].sort();
|
|
42808
|
+
const out = [];
|
|
42809
|
+
for (const path2 of paths) {
|
|
42810
|
+
const x = a.get(path2);
|
|
42811
|
+
const y = b.get(path2);
|
|
42812
|
+
if (x === y) continue;
|
|
42813
|
+
out.push({ kind: "token", path: path2, ...x !== void 0 ? { from: cut(x) } : {}, ...y !== void 0 ? { to: cut(y) } : {} });
|
|
42814
|
+
}
|
|
42815
|
+
return out;
|
|
42816
|
+
}
|
|
42817
|
+
function describeChanges(oldTree, newTree, diff, opts = {}) {
|
|
42818
|
+
if (!existsSync40(oldTree) || !existsSync40(newTree)) return { items: [], more: 0 };
|
|
42819
|
+
const all = [];
|
|
42820
|
+
const before = screensIn(oldTree);
|
|
42821
|
+
const after = screensIn(newTree);
|
|
42822
|
+
for (const id of diff.screens) {
|
|
42823
|
+
if (!after.has(id) || !before.has(id)) continue;
|
|
42824
|
+
const was = readJson2(join38(oldTree, "screens", `${id}.json`));
|
|
42825
|
+
const now = readJson2(join38(newTree, "screens", `${id}.json`));
|
|
42826
|
+
const changes = diffDescriptors(id, was, now);
|
|
42827
|
+
if (changes.length) all.push(...changes);
|
|
42828
|
+
else all.push({ kind: JSON.stringify(was) === JSON.stringify(now) ? "logic" : "descriptor", screen: id });
|
|
42829
|
+
}
|
|
42830
|
+
if (diff.tokens) all.push(...diffTokens(readJson2(join38(oldTree, "tokens.json")), readJson2(join38(newTree, "tokens.json"))));
|
|
42831
|
+
for (const id of [...after].sort()) if (!before.has(id)) all.push({ kind: "screen-added", screen: id });
|
|
42832
|
+
for (const id of [...before].sort()) if (!after.has(id)) all.push({ kind: "screen-removed", screen: id });
|
|
42833
|
+
const ranked = all.map((c, i) => ({ c, i })).sort((x, y) => RANK[x.c.kind] - RANK[y.c.kind] || x.i - y.i).map((x) => x.c);
|
|
42834
|
+
const max = opts.max ?? MAX_ITEMS;
|
|
42835
|
+
return { items: ranked.slice(0, max), more: Math.max(0, ranked.length - max) };
|
|
42836
|
+
}
|
|
42837
|
+
function headline(changes) {
|
|
42838
|
+
const c = changes.items[0];
|
|
42839
|
+
return c ? lineOf(c) : null;
|
|
42840
|
+
}
|
|
42841
|
+
function boardLines(changes) {
|
|
42842
|
+
const lines = [];
|
|
42843
|
+
for (const c of changes.items) {
|
|
42844
|
+
const text5 = lineOf(c);
|
|
42845
|
+
const same2 = lines.find((l) => l.text === text5);
|
|
42846
|
+
if (same2) {
|
|
42847
|
+
same2.n++;
|
|
42848
|
+
continue;
|
|
42849
|
+
}
|
|
42850
|
+
lines.push({
|
|
42851
|
+
text: text5,
|
|
42852
|
+
n: 1,
|
|
42853
|
+
...c.kind === "token" && c.from && HEX.test(c.from) ? { from: c.from } : {},
|
|
42854
|
+
...c.kind === "token" && c.to && HEX.test(c.to) ? { to: c.to } : {}
|
|
42855
|
+
});
|
|
42856
|
+
}
|
|
42857
|
+
return { lines: lines.map(({ n, ...l }) => n > 1 ? { ...l, text: `${l.text} (\xD7${n})` } : l), more: changes.more };
|
|
42858
|
+
}
|
|
42859
|
+
function lineOf(c) {
|
|
42860
|
+
switch (c.kind) {
|
|
42861
|
+
case "text":
|
|
42862
|
+
case "prop":
|
|
42863
|
+
return `${c.screen}: \u201C${c.from ?? ""}\u201D \u2192 \u201C${c.to ?? ""}\u201D`;
|
|
42864
|
+
case "added":
|
|
42865
|
+
return `${c.screen}: + ${c.type}`;
|
|
42866
|
+
case "removed":
|
|
42867
|
+
return `${c.screen}: \u2212 ${c.type}`;
|
|
42868
|
+
case "token":
|
|
42869
|
+
return `${c.path} ${c.from ?? "(new)"} \u2192 ${c.to ?? "(removed)"}`;
|
|
42870
|
+
case "descriptor":
|
|
42871
|
+
return `${c.screen}: descriptor changed`;
|
|
42872
|
+
case "logic":
|
|
42873
|
+
return `${c.screen}: logic changed`;
|
|
42874
|
+
case "screen-added":
|
|
42875
|
+
return `new screen: ${c.screen}`;
|
|
42876
|
+
case "screen-removed":
|
|
42877
|
+
return `screen removed: ${c.screen}`;
|
|
42878
|
+
}
|
|
42879
|
+
}
|
|
42880
|
+
var TEXT_PROPS, RANK, MAX_TEXT, MAX_ITEMS, cut, scalar2, readJson2, screensIn, HEX;
|
|
42881
|
+
var init_build_changes = __esm({
|
|
42882
|
+
"src/build-changes.ts"() {
|
|
42883
|
+
init_stable_ids();
|
|
42884
|
+
TEXT_PROPS = /* @__PURE__ */ new Set(["text", "template", "title", "subtitle", "label", "placeholder", "caption", "message", "value", "hint", "description"]);
|
|
42885
|
+
RANK = { text: 0, added: 1, removed: 1, token: 2, prop: 3, "screen-added": 4, "screen-removed": 4, descriptor: 5, logic: 5 };
|
|
42886
|
+
MAX_TEXT = 60;
|
|
42887
|
+
MAX_ITEMS = 12;
|
|
42888
|
+
cut = (s) => s.length > MAX_TEXT ? `${s.slice(0, MAX_TEXT - 1)}\u2026` : s;
|
|
42889
|
+
scalar2 = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean";
|
|
42890
|
+
readJson2 = (path2) => {
|
|
42891
|
+
try {
|
|
42892
|
+
return JSON.parse(readFileSync43(path2, "utf8"));
|
|
42893
|
+
} catch {
|
|
42894
|
+
return void 0;
|
|
42895
|
+
}
|
|
42896
|
+
};
|
|
42897
|
+
screensIn = (tree) => {
|
|
42898
|
+
try {
|
|
42899
|
+
return new Set(readdirSync22(join38(tree, "screens")).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5)));
|
|
42900
|
+
} catch {
|
|
42901
|
+
return /* @__PURE__ */ new Set();
|
|
42902
|
+
}
|
|
42903
|
+
};
|
|
42904
|
+
HEX = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
42905
|
+
}
|
|
42906
|
+
});
|
|
42907
|
+
|
|
42908
|
+
// src/studio-timeline.ts
|
|
42909
|
+
import { existsSync as existsSync41, readFileSync as readFileSync44 } from "node:fs";
|
|
42910
|
+
import { join as join39 } from "node:path";
|
|
42604
42911
|
function stateOf(view) {
|
|
42605
42912
|
const j = view.journal[0];
|
|
42606
42913
|
const h = view.health;
|
|
@@ -42667,10 +42974,10 @@ function validFrame(f) {
|
|
|
42667
42974
|
return true;
|
|
42668
42975
|
}
|
|
42669
42976
|
function readTimeline(dir) {
|
|
42670
|
-
const file =
|
|
42671
|
-
if (!
|
|
42977
|
+
const file = join39(dir, TIMELINE_FILE);
|
|
42978
|
+
if (!existsSync41(file)) return [];
|
|
42672
42979
|
const out = [];
|
|
42673
|
-
for (const line of
|
|
42980
|
+
for (const line of readFileSync44(file, "utf8").split("\n")) {
|
|
42674
42981
|
if (!line.trim()) continue;
|
|
42675
42982
|
try {
|
|
42676
42983
|
const f = JSON.parse(line);
|
|
@@ -42687,22 +42994,23 @@ function trim(frames) {
|
|
|
42687
42994
|
return frames.slice(-MAX_FRAMES);
|
|
42688
42995
|
}
|
|
42689
42996
|
function writeTimelineJs(dir, frames) {
|
|
42690
|
-
writeFileAtomic(
|
|
42997
|
+
writeFileAtomic(join39(dir, TIMELINE_JS), `window.__himiTimeline && window.__himiTimeline(${scriptJson(frames)});
|
|
42691
42998
|
`);
|
|
42692
42999
|
}
|
|
42693
43000
|
function appendFrame(dir, view, reveal = null) {
|
|
42694
43001
|
const frames = readTimeline(dir);
|
|
42695
43002
|
const last = frames[frames.length - 1];
|
|
42696
43003
|
if (last && last.v === view.v && !reveal) {
|
|
42697
|
-
if (!
|
|
43004
|
+
if (!existsSync41(join39(dir, TIMELINE_JS))) writeTimelineJs(dir, frames);
|
|
42698
43005
|
return frames.length;
|
|
42699
43006
|
}
|
|
42700
43007
|
let prev = null;
|
|
42701
43008
|
for (const f of frames) prev = fold(prev, f);
|
|
42702
43009
|
const frame = frameFor(stateOf(view), prev, view.generatedAt, view.v, frames.length % KEYFRAME_EVERY === 0);
|
|
43010
|
+
if (!frame.key && !reveal && Object.keys(frame).every((k) => k === "ts" || k === "v")) return frames.length;
|
|
42703
43011
|
if (reveal) frame.reveal = reveal;
|
|
42704
43012
|
const kept = trim([...frames, frame]);
|
|
42705
|
-
writeFileAtomic(
|
|
43013
|
+
writeFileAtomic(join39(dir, TIMELINE_FILE), kept.map((f) => JSON.stringify(f)).join("\n") + "\n");
|
|
42706
43014
|
writeTimelineJs(dir, kept);
|
|
42707
43015
|
return kept.length;
|
|
42708
43016
|
}
|
|
@@ -42724,8 +43032,8 @@ var init_studio_timeline = __esm({
|
|
|
42724
43032
|
"src/studio-timeline.ts"() {
|
|
42725
43033
|
init_progress();
|
|
42726
43034
|
init_studio_page();
|
|
42727
|
-
TIMELINE_FILE =
|
|
42728
|
-
TIMELINE_JS =
|
|
43035
|
+
TIMELINE_FILE = join39(".himi", "studio", "timeline.jsonl");
|
|
43036
|
+
TIMELINE_JS = join39(".himi", "studio", "timeline.js");
|
|
42729
43037
|
MAX_FRAMES = 2e3;
|
|
42730
43038
|
KEYFRAME_EVERY = 50;
|
|
42731
43039
|
same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
@@ -42748,6 +43056,7 @@ var init_studio_timeline = __esm({
|
|
|
42748
43056
|
var studio_exports = {};
|
|
42749
43057
|
__export(studio_exports, {
|
|
42750
43058
|
EDGES_RECORD: () => EDGES_RECORD,
|
|
43059
|
+
MAP_RECORD: () => MAP_RECORD,
|
|
42751
43060
|
PUSH_RECORD: () => PUSH_RECORD,
|
|
42752
43061
|
RUN_RECORD: () => RUN_RECORD,
|
|
42753
43062
|
STUDIO_DIR: () => STUDIO_DIR,
|
|
@@ -42762,8 +43071,8 @@ __export(studio_exports, {
|
|
|
42762
43071
|
writeStudioRecord: () => writeStudioRecord
|
|
42763
43072
|
});
|
|
42764
43073
|
import { createHash as createHash21 } from "node:crypto";
|
|
42765
|
-
import { existsSync as
|
|
42766
|
-
import { basename as basename10, extname as extname3, join as
|
|
43074
|
+
import { existsSync as existsSync42, readdirSync as readdirSync23, readFileSync as readFileSync45, realpathSync as realpathSync5, statSync as statSync8 } from "node:fs";
|
|
43075
|
+
import { basename as basename10, extname as extname3, join as join40, relative as relative7, resolve as resolve33, sep as sep9 } from "node:path";
|
|
42767
43076
|
import { pathToFileURL as pathToFileURL7 } from "node:url";
|
|
42768
43077
|
function realInside(dir, abs) {
|
|
42769
43078
|
try {
|
|
@@ -42788,12 +43097,12 @@ function archiveFile(dir, memory, abs) {
|
|
|
42788
43097
|
if (size === 0) return null;
|
|
42789
43098
|
const key2 = relative7(dir, abs);
|
|
42790
43099
|
const hit = memory.files?.[key2];
|
|
42791
|
-
if (hit && hit.size === size && hit.mtimeMs === mtimeMs && hit.ino === ino &&
|
|
43100
|
+
if (hit && hit.size === size && hit.mtimeMs === mtimeMs && hit.ino === ino && existsSync42(join40(dir, HISTORY_DIR, `${hit.sha}.${hit.ext}`))) {
|
|
42792
43101
|
return { sha: hit.sha, ext: hit.ext, file: `${hit.sha}.${hit.ext}` };
|
|
42793
43102
|
}
|
|
42794
43103
|
let archived;
|
|
42795
43104
|
try {
|
|
42796
|
-
archived = archiveBytes(dir,
|
|
43105
|
+
archived = archiveBytes(dir, readFileSync45(real));
|
|
42797
43106
|
} catch {
|
|
42798
43107
|
return null;
|
|
42799
43108
|
}
|
|
@@ -42802,17 +43111,17 @@ function archiveFile(dir, memory, abs) {
|
|
|
42802
43111
|
return { sha: archived.sha256, ext: archived.ext, file: `${archived.sha256}.${archived.ext}` };
|
|
42803
43112
|
}
|
|
42804
43113
|
function loadMemory(dir, now) {
|
|
42805
|
-
const raw = obj(
|
|
43114
|
+
const raw = obj(readJson3(join40(dir, MEMORY_FILE)));
|
|
42806
43115
|
if (raw && raw.version === 1 && obj(raw.shots) && Array.isArray(raw.timeline)) return raw;
|
|
42807
43116
|
return { version: 1, createdAt: now, shots: {}, timeline: [] };
|
|
42808
43117
|
}
|
|
42809
43118
|
function observeShots(dir, memory, now) {
|
|
42810
|
-
const shotsDir =
|
|
43119
|
+
const shotsDir = join40(dir, ".himi", "shots");
|
|
42811
43120
|
const seen = /* @__PURE__ */ new Set();
|
|
42812
|
-
const files =
|
|
43121
|
+
const files = existsSync42(shotsDir) ? readdirSync23(shotsDir).filter((f) => /\.(png|jpe?g)$/i.test(f)).sort() : [];
|
|
42813
43122
|
for (const f of files) {
|
|
42814
43123
|
const id = basename10(f, extname3(f));
|
|
42815
|
-
const archived = archiveFile(dir, memory,
|
|
43124
|
+
const archived = archiveFile(dir, memory, join40(shotsDir, f));
|
|
42816
43125
|
if (!archived) continue;
|
|
42817
43126
|
seen.add(id);
|
|
42818
43127
|
const { sha, ext } = archived;
|
|
@@ -42827,14 +43136,14 @@ function observeShots(dir, memory, now) {
|
|
|
42827
43136
|
memory.shots[id] = { ...prev, present: true };
|
|
42828
43137
|
}
|
|
42829
43138
|
}
|
|
42830
|
-
if (
|
|
43139
|
+
if (existsSync42(shotsDir)) {
|
|
42831
43140
|
for (const [id, shot] of Object.entries(memory.shots)) if (!seen.has(id) && shot.present) memory.shots[id] = { ...shot, present: false };
|
|
42832
43141
|
}
|
|
42833
43142
|
if (memory.timeline.length > MAX_TIMELINE) memory.timeline = memory.timeline.slice(-MAX_TIMELINE);
|
|
42834
43143
|
return memory;
|
|
42835
43144
|
}
|
|
42836
43145
|
function palette(dir) {
|
|
42837
|
-
const colors = obj(obj(
|
|
43146
|
+
const colors = obj(obj(readJson3(join40(dir, "tokens.json")))?.colors);
|
|
42838
43147
|
if (!colors) return [];
|
|
42839
43148
|
const pick2 = (key2) => {
|
|
42840
43149
|
const v = colors[key2];
|
|
@@ -42844,7 +43153,7 @@ function palette(dir) {
|
|
|
42844
43153
|
return ["accentPrimary", "accentSecondary", "accentSurface", "surfacePrimary", "textPrimary"].map(pick2).filter((x) => !!x);
|
|
42845
43154
|
}
|
|
42846
43155
|
function appIdentity(dir) {
|
|
42847
|
-
const manifest = obj(
|
|
43156
|
+
const manifest = obj(readJson3(join40(dir, "himalaya.content.json")));
|
|
42848
43157
|
const name = text(manifest?.name) ?? basename10(resolve33(dir));
|
|
42849
43158
|
const icon = text(manifest?.icon)?.trim();
|
|
42850
43159
|
const iconPath = icon ? resolve33(dir, icon) : null;
|
|
@@ -42852,12 +43161,12 @@ function appIdentity(dir) {
|
|
|
42852
43161
|
return { name, iconFile: real && statSync8(real).isFile() ? iconPath : null };
|
|
42853
43162
|
}
|
|
42854
43163
|
function testRuns(dir) {
|
|
42855
|
-
const att =
|
|
42856
|
-
if (!
|
|
43164
|
+
const att = join40(dir, ".himi", "attestations");
|
|
43165
|
+
if (!existsSync42(att)) return [];
|
|
42857
43166
|
const runs = [];
|
|
42858
|
-
for (const f of
|
|
43167
|
+
for (const f of readdirSync23(att)) {
|
|
42859
43168
|
if (!f.endsWith(".json") || f === "latest.json") continue;
|
|
42860
|
-
const r = obj(
|
|
43169
|
+
const r = obj(readJson3(join40(att, f)));
|
|
42861
43170
|
if (!r || r.tool !== "himi-test" || typeof r.runId !== "string") continue;
|
|
42862
43171
|
const report2 = obj(r.report);
|
|
42863
43172
|
const coverage = obj(r.coverage);
|
|
@@ -42873,20 +43182,20 @@ function testRuns(dir) {
|
|
|
42873
43182
|
return runs.sort((a, b) => a.runId.localeCompare(b.runId));
|
|
42874
43183
|
}
|
|
42875
43184
|
function siteHome(dir) {
|
|
42876
|
-
for (const pages of [
|
|
42877
|
-
if (!
|
|
42878
|
-
const home =
|
|
42879
|
-
if (home) return
|
|
43185
|
+
for (const pages of [join40(dir, ".himi", "business-book", "evidence", "pages"), join40(dir, "evidence", "pages")]) {
|
|
43186
|
+
if (!existsSync42(pages)) continue;
|
|
43187
|
+
const home = readdirSync23(pages).filter((f) => /^home.*\.(png|jpe?g)$/i.test(f)).sort()[0];
|
|
43188
|
+
if (home) return join40(pages, home);
|
|
42880
43189
|
}
|
|
42881
43190
|
return null;
|
|
42882
43191
|
}
|
|
42883
43192
|
function uxStatuses(dir) {
|
|
42884
|
-
const platforms = obj(obj(
|
|
43193
|
+
const platforms = obj(obj(readJson3(join40(dir, ".himi", "ux-audit.json")))?.platforms);
|
|
42885
43194
|
if (!platforms) return [];
|
|
42886
43195
|
return Object.entries(platforms).map(([platform, rec]) => ({ platform, status: text(obj(rec)?.status) ?? "" })).filter((p) => p.status);
|
|
42887
43196
|
}
|
|
42888
43197
|
function liveRun(dir) {
|
|
42889
|
-
const rec = obj(
|
|
43198
|
+
const rec = obj(readJson3(join40(dir, RUN_RECORD)));
|
|
42890
43199
|
const url = text(rec?.url);
|
|
42891
43200
|
const pid = rec?.pid;
|
|
42892
43201
|
if (!url || !/^https?:\/\//i.test(url) || typeof pid !== "number") return null;
|
|
@@ -42907,7 +43216,8 @@ function liveRun(dir) {
|
|
|
42907
43216
|
ms: typeof build2.ms === "number" && Number.isFinite(build2.ms) ? Math.max(0, Math.round(build2.ms)) : null,
|
|
42908
43217
|
screens: (Array.isArray(build2.screens) ? build2.screens : []).filter((x) => typeof x === "string").slice(0, 20),
|
|
42909
43218
|
tokens: build2.tokens === true,
|
|
42910
|
-
config: build2.config === true
|
|
43219
|
+
config: build2.config === true,
|
|
43220
|
+
...changesOf(build2.changes)
|
|
42911
43221
|
} : null,
|
|
42912
43222
|
lan: lanOf(rec?.lanUrl)
|
|
42913
43223
|
};
|
|
@@ -42915,6 +43225,47 @@ function liveRun(dir) {
|
|
|
42915
43225
|
return null;
|
|
42916
43226
|
}
|
|
42917
43227
|
}
|
|
43228
|
+
function mapOf(value) {
|
|
43229
|
+
const raw = obj(value);
|
|
43230
|
+
if (!raw || !Array.isArray(raw.screens)) return null;
|
|
43231
|
+
const screens = [];
|
|
43232
|
+
const ids = /* @__PURE__ */ new Set();
|
|
43233
|
+
for (const it of raw.screens.slice(0, 300)) {
|
|
43234
|
+
const o = obj(it);
|
|
43235
|
+
const id = typeof o?.id === "string" ? o.id.slice(0, 120) : null;
|
|
43236
|
+
if (!o || !id || ids.has(id) || typeof o.status !== "string" || !MAP_STATUSES.has(o.status)) continue;
|
|
43237
|
+
ids.add(id);
|
|
43238
|
+
screens.push({ id, entry: o.entry === true, reached: o.reached === true, status: o.status, unfollowed: count(o.unfollowed) });
|
|
43239
|
+
}
|
|
43240
|
+
if (!screens.length) return null;
|
|
43241
|
+
const link = (it, needTo) => {
|
|
43242
|
+
const o = obj(it);
|
|
43243
|
+
const from = typeof o?.from === "string" ? o.from.slice(0, 120) : null;
|
|
43244
|
+
const to = typeof o?.to === "string" ? o.to.slice(0, 120) : null;
|
|
43245
|
+
if (!from || !to || !ids.has(from) || needTo && !ids.has(to)) return null;
|
|
43246
|
+
return { from, to, via: typeof o?.via === "string" ? o.via.slice(0, 120) : "" };
|
|
43247
|
+
};
|
|
43248
|
+
const edges = (Array.isArray(raw.edges) ? raw.edges.slice(0, 600) : []).map((e) => link(e, true)).filter((e) => !!e);
|
|
43249
|
+
const broken = (Array.isArray(raw.broken) ? raw.broken.slice(0, 100) : []).map((e) => link(e, false)).filter((e) => !!e);
|
|
43250
|
+
return { screens, edges, broken, unfollowed: count(raw.unfollowed), edgesDropped: count(raw.edgesDropped), done: raw.done === true };
|
|
43251
|
+
}
|
|
43252
|
+
function changesOf(value) {
|
|
43253
|
+
const raw = obj(value);
|
|
43254
|
+
const items = [];
|
|
43255
|
+
for (const it of Array.isArray(raw?.items) ? raw.items.slice(0, 12) : []) {
|
|
43256
|
+
const o = obj(it);
|
|
43257
|
+
if (!o || typeof o.kind !== "string" || !CHANGE_KINDS.has(o.kind)) continue;
|
|
43258
|
+
const c = { kind: o.kind };
|
|
43259
|
+
for (const k of ["screen", "node", "type", "path", "from", "to"]) {
|
|
43260
|
+
if (typeof o[k] === "string") c[k] = o[k].slice(0, 80);
|
|
43261
|
+
}
|
|
43262
|
+
items.push(c);
|
|
43263
|
+
}
|
|
43264
|
+
if (!items.length) return { headline: null, changes: null };
|
|
43265
|
+
const more = typeof raw?.more === "number" && Number.isFinite(raw.more) ? Math.max(0, Math.round(raw.more)) : 0;
|
|
43266
|
+
const changes = { items, more };
|
|
43267
|
+
return { headline: headline(changes), changes: boardLines(changes) };
|
|
43268
|
+
}
|
|
42918
43269
|
function lanOf(value) {
|
|
42919
43270
|
const raw = text(value);
|
|
42920
43271
|
if (!raw) return null;
|
|
@@ -42954,9 +43305,9 @@ function buildView(dir, memory, now) {
|
|
|
42954
43305
|
const runs = testRuns(dir);
|
|
42955
43306
|
const last = runs[runs.length - 1];
|
|
42956
43307
|
const prev = runs[runs.length - 2];
|
|
42957
|
-
const validate3 = obj(
|
|
42958
|
-
const push = obj(
|
|
42959
|
-
const edges =
|
|
43308
|
+
const validate3 = obj(readJson3(join40(dir, VALIDATE_RECORD)));
|
|
43309
|
+
const push = obj(readJson3(join40(dir, PUSH_RECORD)));
|
|
43310
|
+
const edges = readJson3(join40(dir, EDGES_RECORD));
|
|
42960
43311
|
const nav = [];
|
|
42961
43312
|
if (Array.isArray(edges)) {
|
|
42962
43313
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -42994,6 +43345,7 @@ function buildView(dir, memory, now) {
|
|
|
42994
43345
|
},
|
|
42995
43346
|
brand: { site: siteImg },
|
|
42996
43347
|
nav,
|
|
43348
|
+
map: mapOf(readJson3(join40(dir, MAP_RECORD))),
|
|
42997
43349
|
live: liveRun(dir),
|
|
42998
43350
|
timelineFrames: 0,
|
|
42999
43351
|
reveal: memory.reveal ?? null
|
|
@@ -43027,15 +43379,15 @@ function writeBoard(dir, now) {
|
|
|
43027
43379
|
} catch {
|
|
43028
43380
|
view.timelineFrames = 0;
|
|
43029
43381
|
}
|
|
43030
|
-
writeAtomic(
|
|
43031
|
-
writeAtomic(
|
|
43382
|
+
writeAtomic(join40(dir, MEMORY_FILE), JSON.stringify(memory));
|
|
43383
|
+
writeAtomic(join40(dir, STATE_FILE), `window.__himiStudio && window.__himiStudio(${scriptJson(view)});
|
|
43032
43384
|
`);
|
|
43033
|
-
writeAtomic(
|
|
43385
|
+
writeAtomic(join40(dir, STUDIO_PAGE), renderStudioHtml(view));
|
|
43034
43386
|
return view;
|
|
43035
43387
|
}
|
|
43036
43388
|
function refreshStudio(dir, now = /* @__PURE__ */ new Date()) {
|
|
43037
43389
|
try {
|
|
43038
|
-
if (!
|
|
43390
|
+
if (!existsSync42(join40(dir, STUDIO_PAGE))) return { refreshed: false };
|
|
43039
43391
|
return { refreshed: true, view: writeBoard(dir, now.toISOString()) };
|
|
43040
43392
|
} catch {
|
|
43041
43393
|
return { refreshed: false };
|
|
@@ -43043,39 +43395,41 @@ function refreshStudio(dir, now = /* @__PURE__ */ new Date()) {
|
|
|
43043
43395
|
}
|
|
43044
43396
|
function openStudio(dir, now = /* @__PURE__ */ new Date()) {
|
|
43045
43397
|
const view = writeBoard(dir, now.toISOString());
|
|
43046
|
-
const page =
|
|
43398
|
+
const page = join40(dir, STUDIO_PAGE);
|
|
43047
43399
|
return { page, url: pathToFileURL7(page).href, view };
|
|
43048
43400
|
}
|
|
43049
43401
|
function writeStudioRecord(dir, record2, value) {
|
|
43050
43402
|
try {
|
|
43051
43403
|
if (!realDirIn(dir, ".himi")) return;
|
|
43052
|
-
writeAtomic(
|
|
43404
|
+
writeAtomic(join40(dir, record2), `${JSON.stringify(value, null, 2)}
|
|
43053
43405
|
`);
|
|
43054
43406
|
} catch {
|
|
43055
43407
|
}
|
|
43056
43408
|
}
|
|
43057
|
-
var STUDIO_DIR, STUDIO_PAGE, STATE_FILE, MEMORY_FILE, VALIDATE_RECORD, PUSH_RECORD, EDGES_RECORD, RUN_RECORD, MAX_TIMELINE, MAX_JOURNAL, MAX_NAV_EDGES,
|
|
43409
|
+
var STUDIO_DIR, STUDIO_PAGE, STATE_FILE, MEMORY_FILE, VALIDATE_RECORD, PUSH_RECORD, EDGES_RECORD, MAP_RECORD, RUN_RECORD, MAX_TIMELINE, MAX_JOURNAL, MAX_NAV_EDGES, readJson3, obj, num, text, historyUrl, runTime, MAP_STATUSES, count, CHANGE_KINDS;
|
|
43058
43410
|
var init_studio = __esm({
|
|
43059
43411
|
"src/studio.ts"() {
|
|
43060
43412
|
init_studio_page();
|
|
43061
43413
|
init_qr();
|
|
43414
|
+
init_build_changes();
|
|
43062
43415
|
init_studio_timeline();
|
|
43063
43416
|
init_progress();
|
|
43064
43417
|
init_studio_page();
|
|
43065
|
-
STUDIO_DIR =
|
|
43066
|
-
STUDIO_PAGE =
|
|
43067
|
-
STATE_FILE =
|
|
43068
|
-
MEMORY_FILE =
|
|
43069
|
-
VALIDATE_RECORD =
|
|
43070
|
-
PUSH_RECORD =
|
|
43071
|
-
EDGES_RECORD =
|
|
43072
|
-
|
|
43418
|
+
STUDIO_DIR = join40(".himi", "studio");
|
|
43419
|
+
STUDIO_PAGE = join40(STUDIO_DIR, "index.html");
|
|
43420
|
+
STATE_FILE = join40(STUDIO_DIR, "state.js");
|
|
43421
|
+
MEMORY_FILE = join40(STUDIO_DIR, "memory.json");
|
|
43422
|
+
VALIDATE_RECORD = join40(".himi", "validate.json");
|
|
43423
|
+
PUSH_RECORD = join40(".himi", "last-push.json");
|
|
43424
|
+
EDGES_RECORD = join40(".himi", "test-edges.json");
|
|
43425
|
+
MAP_RECORD = join40(".himi", "test-map.json");
|
|
43426
|
+
RUN_RECORD = join40(".himi", "run.json");
|
|
43073
43427
|
MAX_TIMELINE = 500;
|
|
43074
43428
|
MAX_JOURNAL = 80;
|
|
43075
43429
|
MAX_NAV_EDGES = 40;
|
|
43076
|
-
|
|
43430
|
+
readJson3 = (file) => {
|
|
43077
43431
|
try {
|
|
43078
|
-
return JSON.parse(
|
|
43432
|
+
return JSON.parse(readFileSync45(file, "utf8"));
|
|
43079
43433
|
} catch {
|
|
43080
43434
|
return null;
|
|
43081
43435
|
}
|
|
@@ -43085,6 +43439,9 @@ var init_studio = __esm({
|
|
|
43085
43439
|
text = (v) => typeof v === "string" && v ? v : null;
|
|
43086
43440
|
historyUrl = (fileName) => `../history/${fileName}`;
|
|
43087
43441
|
runTime = (runId) => runId.replace(/-[0-9a-f]+$/i, "");
|
|
43442
|
+
MAP_STATUSES = /* @__PURE__ */ new Set(["ok", "failed", "pending", "skipped"]);
|
|
43443
|
+
count = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? Math.min(Math.round(v), 1e5) : 0;
|
|
43444
|
+
CHANGE_KINDS = /* @__PURE__ */ new Set(["text", "prop", "added", "removed", "token", "descriptor", "logic", "screen-added", "screen-removed"]);
|
|
43088
43445
|
}
|
|
43089
43446
|
});
|
|
43090
43447
|
|
|
@@ -43374,16 +43731,16 @@ function regressionDiff(base, live2, touched) {
|
|
|
43374
43731
|
rows.push({ item: `screen:${id}`, live: resolveBundleSha(live2, l.bundle), base: resolveBundleSha(base, b.bundle), effect: `${id} rebinds to its ${base.releaseId} worker bundle` });
|
|
43375
43732
|
}
|
|
43376
43733
|
}
|
|
43377
|
-
const
|
|
43734
|
+
const scalar4 = (key2, item, what) => {
|
|
43378
43735
|
if (moves.has(item)) return;
|
|
43379
43736
|
const l = live2[key2] ?? null;
|
|
43380
43737
|
const b = base[key2] ?? null;
|
|
43381
43738
|
if (l !== b) rows.push({ item, live: l, base: b, effect: `${what} reverts to ${base.releaseId}` });
|
|
43382
43739
|
};
|
|
43383
|
-
|
|
43384
|
-
|
|
43385
|
-
|
|
43386
|
-
|
|
43740
|
+
scalar4("tokensHash", "tokens", "design tokens");
|
|
43741
|
+
scalar4("appConfigHash", "app-config", "app-config");
|
|
43742
|
+
scalar4("iconHash", "icon", "the launcher icon");
|
|
43743
|
+
scalar4("minBinaryVersion", "minBinaryVersion", "the minimum binary version");
|
|
43387
43744
|
for (const name of /* @__PURE__ */ new Set([...Object.keys(live2.assets ?? {}), ...Object.keys(base.assets ?? {})])) {
|
|
43388
43745
|
const l = live2.assets?.[name]?.sha256 ?? null;
|
|
43389
43746
|
const b = base.assets?.[name]?.sha256 ?? null;
|
|
@@ -43563,11 +43920,11 @@ __export(captcha_exports, {
|
|
|
43563
43920
|
captchaContentInput: () => captchaContentInput,
|
|
43564
43921
|
runCaptcha: () => runCaptcha
|
|
43565
43922
|
});
|
|
43566
|
-
import { readFileSync as
|
|
43923
|
+
import { readFileSync as readFileSync46 } from "node:fs";
|
|
43567
43924
|
import { resolve as resolve34 } from "node:path";
|
|
43568
43925
|
function readObject(path2) {
|
|
43569
43926
|
try {
|
|
43570
|
-
return JSON.parse(
|
|
43927
|
+
return JSON.parse(readFileSync46(path2, "utf8"));
|
|
43571
43928
|
} catch {
|
|
43572
43929
|
return {};
|
|
43573
43930
|
}
|
|
@@ -43711,11 +44068,11 @@ var init_push_setup_apple_credentials = __esm({
|
|
|
43711
44068
|
});
|
|
43712
44069
|
|
|
43713
44070
|
// src/push-onboarding.ts
|
|
43714
|
-
import { existsSync as
|
|
43715
|
-
import { basename as basename11, dirname as dirname24, join as
|
|
43716
|
-
function
|
|
44071
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync19, readFileSync as readFileSync47, statSync as statSync9, writeFileSync as writeFileSync15, chmodSync as chmodSync2 } from "node:fs";
|
|
44072
|
+
import { basename as basename11, dirname as dirname24, join as join41, resolve as resolve35 } from "node:path";
|
|
44073
|
+
function readJson4(path2) {
|
|
43717
44074
|
try {
|
|
43718
|
-
const parsed = JSON.parse(
|
|
44075
|
+
const parsed = JSON.parse(readFileSync47(path2, "utf8"));
|
|
43719
44076
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
43720
44077
|
} catch {
|
|
43721
44078
|
return {};
|
|
@@ -43723,9 +44080,9 @@ function readJson3(path2) {
|
|
|
43723
44080
|
}
|
|
43724
44081
|
function pushInputsFromContent(dir) {
|
|
43725
44082
|
const root = resolve35(dir);
|
|
43726
|
-
if (!
|
|
43727
|
-
const content =
|
|
43728
|
-
const provisioning =
|
|
44083
|
+
if (!existsSync43(join41(root, "himalaya.content.json"))) return { initialized: false };
|
|
44084
|
+
const content = readJson4(join41(root, "himalaya.content.json"));
|
|
44085
|
+
const provisioning = readJson4(join41(root, "provisioning.json"));
|
|
43729
44086
|
const native = provisioning.native ?? {};
|
|
43730
44087
|
return {
|
|
43731
44088
|
initialized: true,
|
|
@@ -43800,7 +44157,7 @@ function readKeyFile(path2) {
|
|
|
43800
44157
|
}
|
|
43801
44158
|
let body;
|
|
43802
44159
|
try {
|
|
43803
|
-
body =
|
|
44160
|
+
body = readFileSync47(path2, "utf8");
|
|
43804
44161
|
} catch {
|
|
43805
44162
|
return { ok: false, code: "key_file_unreadable", reason: "cannot read the selected key file; check its path and file permissions" };
|
|
43806
44163
|
}
|
|
@@ -43854,13 +44211,13 @@ function buildPushSetupBody(i, keys) {
|
|
|
43854
44211
|
};
|
|
43855
44212
|
}
|
|
43856
44213
|
function readPushOnboarding(dir) {
|
|
43857
|
-
const path2 =
|
|
43858
|
-
if (!
|
|
43859
|
-
const parsed =
|
|
44214
|
+
const path2 = join41(resolve35(dir), PUSH_ONBOARDING_PATH);
|
|
44215
|
+
if (!existsSync43(path2)) return { version: 1 };
|
|
44216
|
+
const parsed = readJson4(path2);
|
|
43860
44217
|
return { version: 1, ...parsed };
|
|
43861
44218
|
}
|
|
43862
44219
|
function writeFile(dir, file) {
|
|
43863
|
-
const path2 =
|
|
44220
|
+
const path2 = join41(resolve35(dir), PUSH_ONBOARDING_PATH);
|
|
43864
44221
|
mkdirSync19(dirname24(path2), { recursive: true, mode: 448 });
|
|
43865
44222
|
writeFileSync15(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
43866
44223
|
try {
|
|
@@ -43889,8 +44246,8 @@ function recordPushDeferral(dir, d) {
|
|
|
43889
44246
|
return push;
|
|
43890
44247
|
}
|
|
43891
44248
|
function clearPushDeferral(dir) {
|
|
43892
|
-
const path2 =
|
|
43893
|
-
if (!
|
|
44249
|
+
const path2 = join41(resolve35(dir), PUSH_ONBOARDING_PATH);
|
|
44250
|
+
if (!existsSync43(path2)) return;
|
|
43894
44251
|
const { push: _dropped, ...rest } = readPushOnboarding(dir);
|
|
43895
44252
|
writeFile(dir, { ...rest, version: 1 });
|
|
43896
44253
|
}
|
|
@@ -44661,8 +45018,8 @@ __export(template_trim_exports, {
|
|
|
44661
45018
|
routeMatcher: () => routeMatcher,
|
|
44662
45019
|
runTemplateTrim: () => runTemplateTrim
|
|
44663
45020
|
});
|
|
44664
|
-
import { cpSync, existsSync as
|
|
44665
|
-
import { dirname as dirname25, join as
|
|
45021
|
+
import { cpSync, existsSync as existsSync44, mkdirSync as mkdirSync20, readdirSync as readdirSync24, readFileSync as readFileSync48, renameSync as renameSync5, rmSync as rmSync8, statSync as statSync10, writeFileSync as writeFileSync16 } from "node:fs";
|
|
45022
|
+
import { dirname as dirname25, join as join42 } from "node:path";
|
|
44666
45023
|
function routeMatcher(pattern) {
|
|
44667
45024
|
const detail = /^\^([A-Za-z0-9_]+)\(\?:\[_\/\]\(\.\+\)\)\?\$$/.exec(pattern);
|
|
44668
45025
|
if (detail) {
|
|
@@ -44777,8 +45134,8 @@ function parseApp(dev, config) {
|
|
|
44777
45134
|
while (!dev.startsWith("})", pos)) {
|
|
44778
45135
|
ENTRY.lastIndex = pos;
|
|
44779
45136
|
const m = ENTRY.exec(dev);
|
|
44780
|
-
if (!m) throw new TrimRefusal(`dev/index.ts line ${
|
|
44781
|
-
const id = jsonString(m[1], `dev/index.ts line ${
|
|
45137
|
+
if (!m) throw new TrimRefusal(`dev/index.ts line ${lineOf2(dev, pos)}: expected a \`"<screenId>": {\` entry of the SCREENS map`);
|
|
45138
|
+
const id = jsonString(m[1], `dev/index.ts line ${lineOf2(dev, pos)}: the SCREENS key`);
|
|
44782
45139
|
const open = pos + m[0].length - 1;
|
|
44783
45140
|
const close = objectEnd(dev, open);
|
|
44784
45141
|
if (close < 0 || dev.slice(close, close + 2) !== ",\n") {
|
|
@@ -44807,9 +45164,9 @@ function parseApp(dev, config) {
|
|
|
44807
45164
|
if (dev.startsWith("];", pos) || dev.startsWith("\n];", pos)) break;
|
|
44808
45165
|
TENTRY.lastIndex = pos;
|
|
44809
45166
|
const m = TENTRY.exec(dev);
|
|
44810
|
-
if (!m) throw new TrimRefusal(`dev/index.ts line ${
|
|
44811
|
-
const pattern = jsonString(m[1], `dev/index.ts line ${
|
|
44812
|
-
const display = jsonString(m[2], `dev/index.ts line ${
|
|
45167
|
+
if (!m) throw new TrimRefusal(`dev/index.ts line ${lineOf2(dev, pos)}: expected a \`{ pattern: \u2026, display: \u2026, template: {\u2026} },\` entry of TEMPLATED`);
|
|
45168
|
+
const pattern = jsonString(m[1], `dev/index.ts line ${lineOf2(dev, pos)}: the TEMPLATED pattern`);
|
|
45169
|
+
const display = jsonString(m[2], `dev/index.ts line ${lineOf2(dev, pos)}: the TEMPLATED display`);
|
|
44813
45170
|
const lineEnd = dev.indexOf("\n", pos);
|
|
44814
45171
|
const tk = dev.indexOf("template: {", pos);
|
|
44815
45172
|
if (tk < 0 || tk > lineEnd) throw new TrimRefusal(`dev/index.ts: the templated route ${display} has no \`template: {\` on its first line`);
|
|
@@ -45281,7 +45638,7 @@ function planTrim(src, keepIds, links) {
|
|
|
45281
45638
|
const homeModules = links === "drop" ? homeModulesPass(app, kept, edited) : void 0;
|
|
45282
45639
|
let dev = "";
|
|
45283
45640
|
let cursor = 0;
|
|
45284
|
-
const
|
|
45641
|
+
const cut2 = (from, to, replacement = "") => {
|
|
45285
45642
|
dev += app.dev.slice(cursor, from) + replacement;
|
|
45286
45643
|
cursor = to;
|
|
45287
45644
|
};
|
|
@@ -45290,15 +45647,15 @@ function planTrim(src, keepIds, links) {
|
|
|
45290
45647
|
for (const r of app.routes) {
|
|
45291
45648
|
if (templatedEmptied && r.kind === "templated") continue;
|
|
45292
45649
|
if (!kept.has(r)) {
|
|
45293
|
-
|
|
45650
|
+
cut2(r.lineStart, r.end);
|
|
45294
45651
|
continue;
|
|
45295
45652
|
}
|
|
45296
45653
|
const block = edited.get(r);
|
|
45297
45654
|
let text5 = block ? serializeAt(block, app.dev, r.open) : void 0;
|
|
45298
45655
|
if (r === app.home && homeModules?.text !== void 0) text5 = homeModules.text;
|
|
45299
|
-
if (text5 !== void 0)
|
|
45656
|
+
if (text5 !== void 0) cut2(r.open, r.close, text5);
|
|
45300
45657
|
}
|
|
45301
|
-
if (templatedEmptied)
|
|
45658
|
+
if (templatedEmptied) cut2(templatedEmptied[0], templatedEmptied[1], "\n");
|
|
45302
45659
|
dev += app.dev.slice(cursor);
|
|
45303
45660
|
let config = app.config;
|
|
45304
45661
|
const edits = [];
|
|
@@ -45356,20 +45713,20 @@ function homeModulesPass(app, kept, edited) {
|
|
|
45356
45713
|
return { text: patched.src, dropped: patched.droppedModules };
|
|
45357
45714
|
}
|
|
45358
45715
|
function listWorkers(dir) {
|
|
45359
|
-
const root =
|
|
45360
|
-
if (!
|
|
45361
|
-
const dirs =
|
|
45716
|
+
const root = join42(dir, "tier5-src");
|
|
45717
|
+
if (!existsSync44(root)) return { dirs: [], files: {} };
|
|
45718
|
+
const dirs = readdirSync24(root).filter((n) => statSync10(join42(root, n)).isDirectory()).sort();
|
|
45362
45719
|
const files = {};
|
|
45363
45720
|
const walk2 = (abs, rel) => {
|
|
45364
|
-
for (const name of
|
|
45721
|
+
for (const name of readdirSync24(abs)) {
|
|
45365
45722
|
if (name === "node_modules") continue;
|
|
45366
|
-
const p =
|
|
45723
|
+
const p = join42(abs, name);
|
|
45367
45724
|
const r = `${rel}/${name}`;
|
|
45368
45725
|
if (statSync10(p).isDirectory()) walk2(p, r);
|
|
45369
|
-
else if (/\.(?:[cm]?[jt]sx?|json)$/.test(name)) files[r] =
|
|
45726
|
+
else if (/\.(?:[cm]?[jt]sx?|json)$/.test(name)) files[r] = readFileSync48(p, "utf8");
|
|
45370
45727
|
}
|
|
45371
45728
|
};
|
|
45372
|
-
for (const d of dirs) walk2(
|
|
45729
|
+
for (const d of dirs) walk2(join42(root, d), `tier5-src/${d}`);
|
|
45373
45730
|
return { dirs, files };
|
|
45374
45731
|
}
|
|
45375
45732
|
function csv(v) {
|
|
@@ -45392,16 +45749,16 @@ async function runTemplateTrim(req, deps) {
|
|
|
45392
45749
|
links = req.links;
|
|
45393
45750
|
}
|
|
45394
45751
|
const dir = req.dir;
|
|
45395
|
-
const devPath =
|
|
45396
|
-
const configPath =
|
|
45397
|
-
if (!
|
|
45752
|
+
const devPath = join42(dir, "dev/index.ts");
|
|
45753
|
+
const configPath = join42(dir, "config.ts");
|
|
45754
|
+
if (!existsSync44(devPath) || !existsSync44(configPath)) {
|
|
45398
45755
|
return refuse3(new TrimRefusal(`${dir} has no dev/index.ts + config.ts \u2014 point --content at an app scaffolded with \`himi init --template\``));
|
|
45399
45756
|
}
|
|
45400
45757
|
if (isTemplateSourceTree(dir)) {
|
|
45401
45758
|
return refuse3(new TrimRefusal(`${dir} is a template source tree (its identity is still __HIMI_APP_*__ sentinels) \u2014 trim the app \`himi init --template\` scaffolds from it, not the template itself`));
|
|
45402
45759
|
}
|
|
45403
|
-
const dev =
|
|
45404
|
-
const config =
|
|
45760
|
+
const dev = readFileSync48(devPath, "utf8");
|
|
45761
|
+
const config = readFileSync48(configPath, "utf8");
|
|
45405
45762
|
const workers = listWorkers(dir);
|
|
45406
45763
|
let plan;
|
|
45407
45764
|
try {
|
|
@@ -45411,23 +45768,23 @@ async function runTemplateTrim(req, deps) {
|
|
|
45411
45768
|
throw e;
|
|
45412
45769
|
}
|
|
45413
45770
|
if (req.dryRun) return { code: 0, result: { ok: true, dryRun: true, ...plan.report, validate: null } };
|
|
45414
|
-
const hadHimi =
|
|
45415
|
-
const backupRel =
|
|
45416
|
-
const backup =
|
|
45771
|
+
const hadHimi = existsSync44(join42(dir, ".himi"));
|
|
45772
|
+
const backupRel = join42(".himi", "trim-backup", (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
|
|
45773
|
+
const backup = join42(dir, backupRel);
|
|
45417
45774
|
const originals = [[devPath, "dev/index.ts"], [configPath, "config.ts"]];
|
|
45418
45775
|
const moved = [];
|
|
45419
45776
|
const restore = () => {
|
|
45420
45777
|
for (const [path2, rel] of originals) {
|
|
45421
|
-
const original =
|
|
45422
|
-
if (!
|
|
45778
|
+
const original = readFileSync48(join42(backup, rel));
|
|
45779
|
+
if (!existsSync44(path2) || !readFileSync48(path2).equals(original)) writeFileSync16(path2, original);
|
|
45423
45780
|
}
|
|
45424
|
-
for (const name of [...moved].reverse()) renameSync5(
|
|
45781
|
+
for (const name of [...moved].reverse()) renameSync5(join42(backup, "tier5-src", name), join42(dir, "tier5-src", name));
|
|
45425
45782
|
moved.length = 0;
|
|
45426
45783
|
};
|
|
45427
45784
|
const apply = () => {
|
|
45428
45785
|
const moveDir = deps.moveDir ?? renameSync5;
|
|
45429
45786
|
for (const name of plan.removedWorkers) {
|
|
45430
|
-
moveDir(
|
|
45787
|
+
moveDir(join42(dir, "tier5-src", name), join42(backup, "tier5-src", name));
|
|
45431
45788
|
moved.push(name);
|
|
45432
45789
|
}
|
|
45433
45790
|
if (plan.dev !== dev) writeFileSync16(devPath, plan.dev);
|
|
@@ -45435,10 +45792,10 @@ async function runTemplateTrim(req, deps) {
|
|
|
45435
45792
|
};
|
|
45436
45793
|
const dropBackup = () => {
|
|
45437
45794
|
rmSync8(backup, { recursive: true, force: true });
|
|
45438
|
-
for (const d of [dirname25(backup),
|
|
45439
|
-
if (d ===
|
|
45795
|
+
for (const d of [dirname25(backup), join42(dir, ".himi")]) {
|
|
45796
|
+
if (d === join42(dir, ".himi") && hadHimi) break;
|
|
45440
45797
|
try {
|
|
45441
|
-
if (!
|
|
45798
|
+
if (!readdirSync24(d).length) rmSync8(d, { recursive: true });
|
|
45442
45799
|
} catch {
|
|
45443
45800
|
}
|
|
45444
45801
|
}
|
|
@@ -45462,9 +45819,9 @@ async function runTemplateTrim(req, deps) {
|
|
|
45462
45819
|
return { code: 1, result: { ok: false, error: `${error} (${message}); every file was restored`, rolledBack: true, ...base(validate4) } };
|
|
45463
45820
|
};
|
|
45464
45821
|
try {
|
|
45465
|
-
mkdirSync20(
|
|
45466
|
-
for (const [path2, rel] of originals) cpSync(path2,
|
|
45467
|
-
if (plan.removedWorkers.length) mkdirSync20(
|
|
45822
|
+
mkdirSync20(join42(backup, "dev"), { recursive: true });
|
|
45823
|
+
for (const [path2, rel] of originals) cpSync(path2, join42(backup, rel));
|
|
45824
|
+
if (plan.removedWorkers.length) mkdirSync20(join42(backup, "tier5-src"), { recursive: true });
|
|
45468
45825
|
} catch (e) {
|
|
45469
45826
|
dropBackup();
|
|
45470
45827
|
return { code: 1, result: { ok: false, error: `could not back up the app before trimming it (${e.message}); nothing was changed`, rolledBack: true, ...base() } };
|
|
@@ -45477,7 +45834,7 @@ async function runTemplateTrim(req, deps) {
|
|
|
45477
45834
|
let failure;
|
|
45478
45835
|
let validate3;
|
|
45479
45836
|
try {
|
|
45480
|
-
const written = parseApp(
|
|
45837
|
+
const written = parseApp(readFileSync48(devPath, "utf8"), readFileSync48(configPath, "utf8"));
|
|
45481
45838
|
const leftovers = leftoverNavRefs(written.nav.value, plan.removedIds);
|
|
45482
45839
|
if (leftovers.length) failure = { error: "navigation still names screens this trim removed", leftovers };
|
|
45483
45840
|
else {
|
|
@@ -45581,7 +45938,7 @@ function summarize3(errors) {
|
|
|
45581
45938
|
const shown2 = errors.slice(0, 5).map(one).join("; ");
|
|
45582
45939
|
return errors.length > 5 ? `${shown2}; and ${errors.length - 5} more` : shown2;
|
|
45583
45940
|
}
|
|
45584
|
-
var TrimRefusal, LIT, ATOM, QUANT, CAP, SAFE_ROUTE_PATTERN,
|
|
45941
|
+
var TrimRefusal, LIT, ATOM, QUANT, CAP, SAFE_ROUTE_PATTERN, lineOf2, isStatic, entryLabel, isNode3, asItems, NAV_SCREEN_KEYS, sorted, refuse3, plural;
|
|
45585
45942
|
var init_template_trim = __esm({
|
|
45586
45943
|
"src/template-trim.ts"() {
|
|
45587
45944
|
init_validate_descriptor();
|
|
@@ -45601,7 +45958,7 @@ var init_template_trim = __esm({
|
|
|
45601
45958
|
SAFE_ROUTE_PATTERN = new RegExp(
|
|
45602
45959
|
String.raw`^\^${LIT}(?:${CAP}${LIT}|\(\?:(?:${LIT}|\[(?:[^\]\\[]|\\.)+\])${CAP}\)\?)?\$$`
|
|
45603
45960
|
);
|
|
45604
|
-
|
|
45961
|
+
lineOf2 = (src, at) => src.slice(0, at).split("\n").length;
|
|
45605
45962
|
isStatic = (id) => typeof id === "string" && id !== "" && !id.startsWith("$");
|
|
45606
45963
|
entryLabel = (entry) => {
|
|
45607
45964
|
const id = entry?.id;
|
|
@@ -46150,10 +46507,10 @@ function parseZipEntries(buf) {
|
|
|
46150
46507
|
}
|
|
46151
46508
|
}
|
|
46152
46509
|
if (eocd < 0) throw new Error("not a zip archive (no end-of-central-directory record)");
|
|
46153
|
-
const
|
|
46510
|
+
const count2 = u16(eocd + 10);
|
|
46154
46511
|
let p = u32(eocd + 16);
|
|
46155
46512
|
const out = [];
|
|
46156
|
-
for (let i = 0; i <
|
|
46513
|
+
for (let i = 0; i < count2; i++) {
|
|
46157
46514
|
if (p + 46 > buf.length || u32(p) !== ZIP_CENTRAL_SIG) throw new Error("corrupt zip central directory");
|
|
46158
46515
|
const method = u16(p + 10);
|
|
46159
46516
|
const crc = u32(p + 16);
|
|
@@ -46245,8 +46602,8 @@ __export(pack_exports, {
|
|
|
46245
46602
|
});
|
|
46246
46603
|
import { createHash as createHash22 } from "node:crypto";
|
|
46247
46604
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
46248
|
-
import { existsSync as
|
|
46249
|
-
import { dirname as dirname26, join as
|
|
46605
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync21, readFileSync as readFileSync49, readdirSync as readdirSync25, rmSync as rmSync9, statSync as statSync11, writeFileSync as writeFileSync17 } from "node:fs";
|
|
46606
|
+
import { dirname as dirname26, join as join43, resolve as resolve37 } from "node:path";
|
|
46250
46607
|
function writeZip(entries) {
|
|
46251
46608
|
const sorted2 = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
46252
46609
|
const total = sorted2.reduce((n, e) => n + e.bytes.length, 0);
|
|
@@ -46340,13 +46697,13 @@ function inflateEntry(buf, entry) {
|
|
|
46340
46697
|
return bytes2;
|
|
46341
46698
|
}
|
|
46342
46699
|
function readIf(path2) {
|
|
46343
|
-
return
|
|
46700
|
+
return existsSync45(path2) && statSync11(path2).isFile() ? readFileSync49(path2) : null;
|
|
46344
46701
|
}
|
|
46345
46702
|
function listDir(dir) {
|
|
46346
|
-
return
|
|
46703
|
+
return existsSync45(dir) ? readdirSync25(dir).filter((f) => statSync11(join43(dir, f)).isFile()) : [];
|
|
46347
46704
|
}
|
|
46348
46705
|
function gatherReleaseEntries(appDir2) {
|
|
46349
|
-
const manifestPath =
|
|
46706
|
+
const manifestPath = join43(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
|
|
46350
46707
|
const manifestBytes = readIf(manifestPath);
|
|
46351
46708
|
if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir2} \u2014 build a release there first`);
|
|
46352
46709
|
const manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
@@ -46370,7 +46727,7 @@ function gatherReleaseEntries(appDir2) {
|
|
|
46370
46727
|
}
|
|
46371
46728
|
const missing = [];
|
|
46372
46729
|
for (const rel of wanted) {
|
|
46373
|
-
const bytes2 = readIf(
|
|
46730
|
+
const bytes2 = readIf(join43(appDir2, rel));
|
|
46374
46731
|
if (bytes2) entries.push({ path: rel, bytes: bytes2 });
|
|
46375
46732
|
else missing.push(rel);
|
|
46376
46733
|
}
|
|
@@ -46381,12 +46738,12 @@ function gatherReleaseEntries(appDir2) {
|
|
|
46381
46738
|
);
|
|
46382
46739
|
}
|
|
46383
46740
|
for (const name of SINGLETONS) {
|
|
46384
|
-
const bytes2 = readIf(
|
|
46741
|
+
const bytes2 = readIf(join43(appDir2, name));
|
|
46385
46742
|
if (bytes2) entries.push({ path: name, bytes: bytes2 });
|
|
46386
46743
|
}
|
|
46387
46744
|
const skipped = [];
|
|
46388
46745
|
for (const sub of ["screens", "bundles", "assets", "widgets"]) {
|
|
46389
|
-
for (const f of listDir(
|
|
46746
|
+
for (const f of listDir(join43(appDir2, sub))) {
|
|
46390
46747
|
if (!wanted.has(`${sub}/${f}`)) skipped.push(`${sub}/${f}`);
|
|
46391
46748
|
}
|
|
46392
46749
|
}
|
|
@@ -46419,18 +46776,18 @@ function buildEntries(appDir2, app, opts) {
|
|
|
46419
46776
|
return { all, header, manifest, skipped };
|
|
46420
46777
|
}
|
|
46421
46778
|
function packRelease(releaseRoot, app, out, opts = {}) {
|
|
46422
|
-
const appDir2 =
|
|
46779
|
+
const appDir2 = join43(resolve37(releaseRoot), app);
|
|
46423
46780
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
46424
46781
|
const buf = writeZip(all);
|
|
46425
|
-
const isDir2 =
|
|
46426
|
-
const outFile = isDir2 ?
|
|
46782
|
+
const isDir2 = existsSync45(out) && statSync11(out).isDirectory();
|
|
46783
|
+
const outFile = isDir2 ? join43(resolve37(out), packageFileName(app, header.releaseId)) : resolve37(out);
|
|
46427
46784
|
mkdirSync21(dirname26(outFile), { recursive: true });
|
|
46428
46785
|
writeFileSync17(outFile, buf);
|
|
46429
46786
|
return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
|
|
46430
46787
|
}
|
|
46431
46788
|
function resolvePackageDirDest(outDir, app, releaseId) {
|
|
46432
46789
|
const packagedApp = (dir) => {
|
|
46433
|
-
const bytes2 = readIf(
|
|
46790
|
+
const bytes2 = readIf(join43(dir, HIMI_PACKAGE_HEADER_PATH));
|
|
46434
46791
|
if (!bytes2) return void 0;
|
|
46435
46792
|
try {
|
|
46436
46793
|
return JSON.parse(bytes2.toString("utf8")).app;
|
|
@@ -46439,15 +46796,15 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
46439
46796
|
}
|
|
46440
46797
|
};
|
|
46441
46798
|
const replaceable = (dir) => {
|
|
46442
|
-
if (!
|
|
46799
|
+
if (!existsSync45(dir)) return true;
|
|
46443
46800
|
if (!statSync11(dir).isDirectory()) return false;
|
|
46444
|
-
return
|
|
46801
|
+
return readdirSync25(dir).length === 0 || packagedApp(dir) === app;
|
|
46445
46802
|
};
|
|
46446
|
-
if (
|
|
46803
|
+
if (existsSync45(outDir) && !statSync11(outDir).isDirectory()) {
|
|
46447
46804
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
46448
46805
|
}
|
|
46449
46806
|
if (replaceable(outDir)) return outDir;
|
|
46450
|
-
const child =
|
|
46807
|
+
const child = join43(outDir, packageDirName(app, releaseId));
|
|
46451
46808
|
if (!replaceable(child)) {
|
|
46452
46809
|
throw new Error(
|
|
46453
46810
|
`refusing to replace ${child}: it is not empty and is not a ${app} package (no ${HIMI_PACKAGE_HEADER_PATH}). Pass --out to a new or empty directory.`
|
|
@@ -46461,13 +46818,13 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
|
46461
46818
|
"a package carrying the app's source has no --format dir form: readers that predate the source entry drop it before hashing a directory and refuse the package as tampered. Pack it as a .himi archive."
|
|
46462
46819
|
);
|
|
46463
46820
|
}
|
|
46464
|
-
const appDir2 =
|
|
46821
|
+
const appDir2 = join43(resolve37(releaseRoot), app);
|
|
46465
46822
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
46466
46823
|
const dest = resolvePackageDirDest(resolve37(outDir), app, header.releaseId);
|
|
46467
46824
|
rmSync9(dest, { recursive: true, force: true });
|
|
46468
46825
|
let bytes2 = 0;
|
|
46469
46826
|
for (const entry of all) {
|
|
46470
|
-
const target =
|
|
46827
|
+
const target = join43(dest, entry.path);
|
|
46471
46828
|
mkdirSync21(dirname26(target), { recursive: true });
|
|
46472
46829
|
writeFileSync17(target, entry.bytes);
|
|
46473
46830
|
bytes2 += entry.bytes.length;
|
|
@@ -46490,21 +46847,21 @@ function openPackageBuffer(buf) {
|
|
|
46490
46847
|
return openFromEntries(readZip(buf), { requireHeader: true });
|
|
46491
46848
|
}
|
|
46492
46849
|
function openPackageFile(file) {
|
|
46493
|
-
return openPackageBuffer(
|
|
46850
|
+
return openPackageBuffer(readFileSync49(file));
|
|
46494
46851
|
}
|
|
46495
46852
|
function openPackageDir(dir) {
|
|
46496
46853
|
const root = resolve37(dir);
|
|
46497
46854
|
const entries = /* @__PURE__ */ new Map();
|
|
46498
46855
|
const walk2 = (rel) => {
|
|
46499
|
-
const abs = rel ?
|
|
46500
|
-
for (const name of
|
|
46856
|
+
const abs = rel ? join43(root, rel) : root;
|
|
46857
|
+
for (const name of readdirSync25(abs)) {
|
|
46501
46858
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
46502
|
-
const childAbs =
|
|
46859
|
+
const childAbs = join43(abs, name);
|
|
46503
46860
|
if (statSync11(childAbs).isDirectory()) walk2(childRel);
|
|
46504
|
-
else if (isSafeEntryName(childRel)) entries.set(childRel,
|
|
46861
|
+
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync49(childAbs));
|
|
46505
46862
|
}
|
|
46506
46863
|
};
|
|
46507
|
-
if (!
|
|
46864
|
+
if (!existsSync45(root)) throw new Error(`no such package directory: ${root}`);
|
|
46508
46865
|
walk2("");
|
|
46509
46866
|
const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
|
|
46510
46867
|
if (manifestBytes) {
|
|
@@ -46546,10 +46903,10 @@ function unpackTo(buf, dest, appFallback) {
|
|
|
46546
46903
|
if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
|
|
46547
46904
|
if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
|
|
46548
46905
|
const root = resolve37(dest);
|
|
46549
|
-
const appDir2 =
|
|
46906
|
+
const appDir2 = join43(root, app);
|
|
46550
46907
|
rmSync9(appDir2, { recursive: true, force: true });
|
|
46551
46908
|
for (const [rel, bytes2] of entries) {
|
|
46552
|
-
const target =
|
|
46909
|
+
const target = join43(appDir2, rel);
|
|
46553
46910
|
mkdirSync21(dirname26(target), { recursive: true });
|
|
46554
46911
|
writeFileSync17(target, bytes2);
|
|
46555
46912
|
}
|
|
@@ -46585,20 +46942,20 @@ __export(app_source_exports, {
|
|
|
46585
46942
|
writeConflicts: () => writeConflicts,
|
|
46586
46943
|
zipAppSource: () => zipAppSource
|
|
46587
46944
|
});
|
|
46588
|
-
import { readdirSync as
|
|
46589
|
-
import { join as
|
|
46945
|
+
import { readdirSync as readdirSync26, lstatSync as lstatSync8, readFileSync as readFileSync50, mkdirSync as mkdirSync22, writeFileSync as writeFileSync18, existsSync as existsSync46, rmSync as rmSync10, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3 } from "node:fs";
|
|
46946
|
+
import { join as join44, resolve as resolve38, sep as sep10 } from "node:path";
|
|
46590
46947
|
import { deflateRawSync as deflateRawSync2 } from "node:zlib";
|
|
46591
46948
|
function walkSourceTree(dir, file, skip) {
|
|
46592
46949
|
const walk2 = (relDir) => {
|
|
46593
|
-
for (const name of
|
|
46594
|
-
const rel = relDir ?
|
|
46595
|
-
const st = lstatSync8(
|
|
46950
|
+
for (const name of readdirSync26(join44(dir, relDir))) {
|
|
46951
|
+
const rel = relDir ? join44(relDir, name) : name;
|
|
46952
|
+
const st = lstatSync8(join44(dir, rel));
|
|
46596
46953
|
if (st.isSymbolicLink()) {
|
|
46597
46954
|
skip(rel);
|
|
46598
46955
|
continue;
|
|
46599
46956
|
}
|
|
46600
46957
|
if (st.isDirectory()) {
|
|
46601
|
-
if (isDeniedSourceDir(name, relDir) ||
|
|
46958
|
+
if (isDeniedSourceDir(name, relDir) || existsSync46(join44(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
|
|
46602
46959
|
else walk2(rel);
|
|
46603
46960
|
continue;
|
|
46604
46961
|
}
|
|
@@ -46616,7 +46973,7 @@ function collectAppSource(dir) {
|
|
|
46616
46973
|
const skipped = [];
|
|
46617
46974
|
walkSourceTree(
|
|
46618
46975
|
dir,
|
|
46619
|
-
(archivePath, hostRel) => entries.push({ path: archivePath, bytes:
|
|
46976
|
+
(archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync50(join44(dir, hostRel)) }),
|
|
46620
46977
|
(hostRel) => skipped.push(hostRel)
|
|
46621
46978
|
);
|
|
46622
46979
|
entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
@@ -46670,13 +47027,13 @@ function writeAppSource(entries, destDir) {
|
|
|
46670
47027
|
const segments = entry.path.split("/");
|
|
46671
47028
|
let dir = root;
|
|
46672
47029
|
for (const segment of segments.slice(0, -1)) {
|
|
46673
|
-
dir =
|
|
47030
|
+
dir = join44(dir, segment);
|
|
46674
47031
|
const kind = pathKind(dir);
|
|
46675
47032
|
if (kind?.isSymbolicLink()) unlinkSync3(dir);
|
|
46676
47033
|
else if (kind) continue;
|
|
46677
47034
|
mkdirSync22(dir);
|
|
46678
47035
|
}
|
|
46679
|
-
const target =
|
|
47036
|
+
const target = join44(root, ...segments);
|
|
46680
47037
|
if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
|
|
46681
47038
|
writeFileSync18(target, entry.bytes);
|
|
46682
47039
|
written.push(entry.path);
|
|
@@ -46684,7 +47041,7 @@ function writeAppSource(entries, destDir) {
|
|
|
46684
47041
|
return written;
|
|
46685
47042
|
}
|
|
46686
47043
|
function staleSourcePaths(entries, destDir) {
|
|
46687
|
-
if (!
|
|
47044
|
+
if (!existsSync46(destDir)) return [];
|
|
46688
47045
|
const archived = new Set(entries.map((e) => e.path));
|
|
46689
47046
|
const stale = [];
|
|
46690
47047
|
walkSourceTree(destDir, (archivePath) => {
|
|
@@ -46711,7 +47068,7 @@ function writeConflicts(entries, destDir) {
|
|
|
46711
47068
|
let dir = root;
|
|
46712
47069
|
let stop = false;
|
|
46713
47070
|
for (const [i, segment] of segments.slice(0, -1).entries()) {
|
|
46714
|
-
dir =
|
|
47071
|
+
dir = join44(dir, segment);
|
|
46715
47072
|
const kind2 = pathKind(dir);
|
|
46716
47073
|
if (!kind2 || kind2.isSymbolicLink()) {
|
|
46717
47074
|
stop = true;
|
|
@@ -46723,7 +47080,7 @@ function writeConflicts(entries, destDir) {
|
|
|
46723
47080
|
break;
|
|
46724
47081
|
}
|
|
46725
47082
|
if (stop) continue;
|
|
46726
|
-
const kind = pathKind(
|
|
47083
|
+
const kind = pathKind(join44(root, ...segments));
|
|
46727
47084
|
if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
|
|
46728
47085
|
say(entry.path, "is a directory here, but the release has a file at that path");
|
|
46729
47086
|
}
|
|
@@ -46733,22 +47090,22 @@ function writeConflicts(entries, destDir) {
|
|
|
46733
47090
|
function removeStaleSource(entries, destDir) {
|
|
46734
47091
|
const root = resolve38(destDir);
|
|
46735
47092
|
const removed = staleSourcePaths(entries, root);
|
|
46736
|
-
for (const rel of removed) rmSync10(
|
|
47093
|
+
for (const rel of removed) rmSync10(join44(root, ...rel.split("/")), { force: true });
|
|
46737
47094
|
const needed = /* @__PURE__ */ new Set();
|
|
46738
47095
|
for (const entry of entries) {
|
|
46739
47096
|
if (isDeniedSourcePath(entry.path)) continue;
|
|
46740
47097
|
const segments = entry.path.split("/");
|
|
46741
47098
|
for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
|
|
46742
47099
|
}
|
|
46743
|
-
if (
|
|
47100
|
+
if (existsSync46(root)) pruneEmptyDirs(root, "", needed, removed);
|
|
46744
47101
|
return removed.sort();
|
|
46745
47102
|
}
|
|
46746
47103
|
function pruneEmptyDirs(root, rel, needed, removed) {
|
|
46747
47104
|
let empty = true;
|
|
46748
|
-
for (const name of
|
|
46749
|
-
const childRel = rel ?
|
|
47105
|
+
for (const name of readdirSync26(rel ? join44(root, rel) : root)) {
|
|
47106
|
+
const childRel = rel ? join44(rel, name) : name;
|
|
46750
47107
|
const posix4 = childRel.split(sep10).join("/");
|
|
46751
|
-
const kind = lstatSync8(
|
|
47108
|
+
const kind = lstatSync8(join44(root, childRel));
|
|
46752
47109
|
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name, rel)) {
|
|
46753
47110
|
empty = false;
|
|
46754
47111
|
continue;
|
|
@@ -46758,7 +47115,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
46758
47115
|
empty = false;
|
|
46759
47116
|
continue;
|
|
46760
47117
|
}
|
|
46761
|
-
rmdirSync2(
|
|
47118
|
+
rmdirSync2(join44(root, childRel));
|
|
46762
47119
|
removed.push(`${posix4}/`);
|
|
46763
47120
|
}
|
|
46764
47121
|
return empty;
|
|
@@ -46813,13 +47170,13 @@ __export(eject_exports, {
|
|
|
46813
47170
|
EJECTABLE: () => EJECTABLE,
|
|
46814
47171
|
ejectModule: () => ejectModule
|
|
46815
47172
|
});
|
|
46816
|
-
import { existsSync as
|
|
46817
|
-
import { dirname as dirname27, join as
|
|
47173
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync23, readFileSync as readFileSync51, writeFileSync as writeFileSync19 } from "node:fs";
|
|
47174
|
+
import { dirname as dirname27, join as join45, relative as relative8, resolve as resolve39, sep as sep11 } from "node:path";
|
|
46818
47175
|
function locate(repoRootOrCwd, mod) {
|
|
46819
47176
|
const inRepo = resolve39(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
46820
|
-
if (
|
|
47177
|
+
if (existsSync47(inRepo)) return { path: inRepo, form: "source" };
|
|
46821
47178
|
const dist = resolve39(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
|
|
46822
|
-
if (
|
|
47179
|
+
if (existsSync47(dist)) return { path: dist, form: "bundle" };
|
|
46823
47180
|
return null;
|
|
46824
47181
|
}
|
|
46825
47182
|
function specifiersFor(mod) {
|
|
@@ -46843,7 +47200,7 @@ function ejectModule(opts) {
|
|
|
46843
47200
|
};
|
|
46844
47201
|
}
|
|
46845
47202
|
const ext = found.form === "source" ? "ts" : "mjs";
|
|
46846
|
-
const target =
|
|
47203
|
+
const target = join45(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
|
|
46847
47204
|
mkdirSync23(dirname27(target), { recursive: true });
|
|
46848
47205
|
const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
|
|
46849
47206
|
//
|
|
@@ -46857,15 +47214,15 @@ function ejectModule(opts) {
|
|
|
46857
47214
|
// gate still applies. Ejecting buys layout and flow, never the floor.
|
|
46858
47215
|
|
|
46859
47216
|
`;
|
|
46860
|
-
const normalized =
|
|
47217
|
+
const normalized = readFileSync51(found.path, "utf8").replace(
|
|
46861
47218
|
/(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
|
|
46862
47219
|
(_m, q, sub) => `${q}@wix/himalaya/${sub}${q}`
|
|
46863
47220
|
);
|
|
46864
47221
|
writeFileSync19(target, banner + normalized);
|
|
46865
47222
|
const rewired = [];
|
|
46866
47223
|
for (const f of files) {
|
|
46867
|
-
if (!
|
|
46868
|
-
const before =
|
|
47224
|
+
if (!existsSync47(f)) continue;
|
|
47225
|
+
const before = readFileSync51(f, "utf8");
|
|
46869
47226
|
let after = before;
|
|
46870
47227
|
let rel = relative8(dirname27(f), target).split(sep11).join("/").replace(/\.tsx?$/, ".js");
|
|
46871
47228
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
@@ -46897,9 +47254,96 @@ var init_eject = __esm({
|
|
|
46897
47254
|
}
|
|
46898
47255
|
});
|
|
46899
47256
|
|
|
47257
|
+
// src/app-map.ts
|
|
47258
|
+
function buildAppMap(input) {
|
|
47259
|
+
const declared = [...new Set(input.declared)].slice(0, MAX_SCREENS);
|
|
47260
|
+
const known = new Set(declared);
|
|
47261
|
+
let entries = [...new Set(input.entries)].filter((id) => known.has(id));
|
|
47262
|
+
if (!entries.length && declared.length) entries = [declared[0]];
|
|
47263
|
+
const entrySet = new Set(entries);
|
|
47264
|
+
const all = [];
|
|
47265
|
+
const broken = [];
|
|
47266
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47267
|
+
const crawled = /* @__PURE__ */ new Map();
|
|
47268
|
+
const unfollowed = /* @__PURE__ */ new Map();
|
|
47269
|
+
for (const r of input.results) {
|
|
47270
|
+
crawled.set(r.screen, (crawled.get(r.screen) ?? false) || r.failed);
|
|
47271
|
+
if (r.navUnfollowed) unfollowed.set(r.screen, Math.max(unfollowed.get(r.screen) ?? 0, r.navUnfollowed));
|
|
47272
|
+
for (const e of r.navEdges ?? []) {
|
|
47273
|
+
const to = known.has(e.target) ? e.target : baseOf(e.target, input.linkable, known);
|
|
47274
|
+
if (!to) {
|
|
47275
|
+
const key3 = `${r.screen}>!${e.target}`;
|
|
47276
|
+
if (input.linkable?.size && !resolvesToLinkable(e.target, input.linkable) && !seen.has(key3)) {
|
|
47277
|
+
seen.add(key3);
|
|
47278
|
+
broken.push({ from: r.screen, to: e.target, via: e.via });
|
|
47279
|
+
}
|
|
47280
|
+
continue;
|
|
47281
|
+
}
|
|
47282
|
+
const key2 = `${r.screen}>${to}`;
|
|
47283
|
+
if (seen.has(key2)) continue;
|
|
47284
|
+
seen.add(key2);
|
|
47285
|
+
all.push({ from: r.screen, to, via: e.via });
|
|
47286
|
+
}
|
|
47287
|
+
}
|
|
47288
|
+
const reached = new Set(entries);
|
|
47289
|
+
const out = /* @__PURE__ */ new Map();
|
|
47290
|
+
for (const e of all) {
|
|
47291
|
+
const next = out.get(e.from);
|
|
47292
|
+
if (next) next.push(e.to);
|
|
47293
|
+
else out.set(e.from, [e.to]);
|
|
47294
|
+
}
|
|
47295
|
+
for (const queue = [...entries]; queue.length; ) {
|
|
47296
|
+
for (const next of out.get(queue.shift()) ?? []) {
|
|
47297
|
+
if (reached.has(next)) continue;
|
|
47298
|
+
reached.add(next);
|
|
47299
|
+
queue.push(next);
|
|
47300
|
+
}
|
|
47301
|
+
}
|
|
47302
|
+
const screens = declared.map((id) => ({
|
|
47303
|
+
id,
|
|
47304
|
+
entry: entrySet.has(id),
|
|
47305
|
+
reached: reached.has(id),
|
|
47306
|
+
status: crawled.has(id) ? crawled.get(id) ? "failed" : "ok" : input.done ? "skipped" : "pending",
|
|
47307
|
+
unfollowed: unfollowed.get(id) ?? 0
|
|
47308
|
+
}));
|
|
47309
|
+
const totalUnfollowed = [...unfollowed.values()].reduce((a, b) => a + b, 0);
|
|
47310
|
+
return {
|
|
47311
|
+
screens,
|
|
47312
|
+
edges: all.slice(0, MAX_EDGES),
|
|
47313
|
+
broken,
|
|
47314
|
+
unreached: declared.filter((id) => !reached.has(id)),
|
|
47315
|
+
unfollowed: totalUnfollowed,
|
|
47316
|
+
edgesDropped: Math.max(0, all.length - MAX_EDGES),
|
|
47317
|
+
done: input.done
|
|
47318
|
+
};
|
|
47319
|
+
}
|
|
47320
|
+
function resolvesToLinkable(target, linkable) {
|
|
47321
|
+
if (linkable.has(target)) return true;
|
|
47322
|
+
for (const base of linkable) {
|
|
47323
|
+
if (target.length > base.length + 1 && target.startsWith(base) && (target[base.length] === "_" || target[base.length] === "/")) return true;
|
|
47324
|
+
}
|
|
47325
|
+
return false;
|
|
47326
|
+
}
|
|
47327
|
+
function baseOf(target, linkable, known) {
|
|
47328
|
+
let best = null;
|
|
47329
|
+
for (const base of linkable ?? []) {
|
|
47330
|
+
if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
|
|
47331
|
+
const sep15 = target[base.length];
|
|
47332
|
+
if ((sep15 === "_" || sep15 === "/") && (!best || base.length > best.length)) best = base;
|
|
47333
|
+
}
|
|
47334
|
+
return best;
|
|
47335
|
+
}
|
|
47336
|
+
var MAX_SCREENS, MAX_EDGES;
|
|
47337
|
+
var init_app_map = __esm({
|
|
47338
|
+
"src/app-map.ts"() {
|
|
47339
|
+
MAX_SCREENS = 300;
|
|
47340
|
+
MAX_EDGES = 600;
|
|
47341
|
+
}
|
|
47342
|
+
});
|
|
47343
|
+
|
|
46900
47344
|
// src/wix-writes.ts
|
|
46901
|
-
import { existsSync as
|
|
46902
|
-
import { join as
|
|
47345
|
+
import { existsSync as existsSync48, readFileSync as readFileSync52 } from "node:fs";
|
|
47346
|
+
import { join as join46 } from "node:path";
|
|
46903
47347
|
function isProvenRead(method, path2) {
|
|
46904
47348
|
if (/[#\x00-\x1F\x7F]/.test(path2)) return false;
|
|
46905
47349
|
const verb = method.toUpperCase();
|
|
@@ -46980,11 +47424,11 @@ function parseDataAccess(text5, from) {
|
|
|
46980
47424
|
}
|
|
46981
47425
|
function readDataAccess(dir) {
|
|
46982
47426
|
for (const name of ["SPEC.md", "MOBILE-UX.md"]) {
|
|
46983
|
-
const p =
|
|
46984
|
-
if (!
|
|
47427
|
+
const p = join46(dir, name);
|
|
47428
|
+
if (!existsSync48(p)) continue;
|
|
46985
47429
|
let text5;
|
|
46986
47430
|
try {
|
|
46987
|
-
text5 =
|
|
47431
|
+
text5 = readFileSync52(p, "utf8");
|
|
46988
47432
|
} catch {
|
|
46989
47433
|
continue;
|
|
46990
47434
|
}
|
|
@@ -47091,14 +47535,14 @@ __export(test_exports, {
|
|
|
47091
47535
|
scopeDescriptors: () => scopeDescriptors,
|
|
47092
47536
|
writeRecordedMocks: () => writeRecordedMocks
|
|
47093
47537
|
});
|
|
47094
|
-
import { existsSync as
|
|
47095
|
-
import { join as
|
|
47538
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync24, readFileSync as readFileSync53, writeFileSync as writeFileSync20 } from "node:fs";
|
|
47539
|
+
import { join as join47, resolve as resolve40 } from "node:path";
|
|
47096
47540
|
function readTestConfig(dir) {
|
|
47097
47541
|
const p = resolve40(dir, TEST_CONFIG_FILE);
|
|
47098
|
-
if (!
|
|
47542
|
+
if (!existsSync49(p)) return {};
|
|
47099
47543
|
let parsed;
|
|
47100
47544
|
try {
|
|
47101
|
-
parsed = JSON.parse(
|
|
47545
|
+
parsed = JSON.parse(readFileSync53(p, "utf8"));
|
|
47102
47546
|
} catch (e) {
|
|
47103
47547
|
throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e.message}`);
|
|
47104
47548
|
}
|
|
@@ -47145,7 +47589,7 @@ function readTestConfig(dir) {
|
|
|
47145
47589
|
function readNetRules(path2) {
|
|
47146
47590
|
let parsed;
|
|
47147
47591
|
try {
|
|
47148
|
-
parsed = JSON.parse(
|
|
47592
|
+
parsed = JSON.parse(readFileSync53(path2, "utf8"));
|
|
47149
47593
|
} catch (e) {
|
|
47150
47594
|
throw new Error(`--net ${path2} could not be read as JSON \u2014 ${e.message}`);
|
|
47151
47595
|
}
|
|
@@ -47166,7 +47610,7 @@ function readNetRules(path2) {
|
|
|
47166
47610
|
function defaultNetRules(dir) {
|
|
47167
47611
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
47168
47612
|
const p = resolve40(dir, rel);
|
|
47169
|
-
if (
|
|
47613
|
+
if (existsSync49(p)) {
|
|
47170
47614
|
const rules = readNetRules(p);
|
|
47171
47615
|
if (rules.length) return { rules, from: rel };
|
|
47172
47616
|
}
|
|
@@ -47182,13 +47626,13 @@ function readCannedResponses() {
|
|
|
47182
47626
|
];
|
|
47183
47627
|
for (const url of candidates) {
|
|
47184
47628
|
try {
|
|
47185
|
-
const parsed = JSON.parse(
|
|
47629
|
+
const parsed = JSON.parse(readFileSync53(url, "utf8"));
|
|
47186
47630
|
const byKey = {};
|
|
47187
47631
|
for (const [k, v] of Object.entries(parsed)) {
|
|
47188
47632
|
if (!k.startsWith("//")) byKey[k] = v;
|
|
47189
47633
|
}
|
|
47190
|
-
const
|
|
47191
|
-
if (
|
|
47634
|
+
const count2 = Object.keys(byKey).length;
|
|
47635
|
+
if (count2) return { byKey, count: count2, from: url.pathname.includes("web-renderer") ? "in-repo fixture" : "bundled fixture" };
|
|
47192
47636
|
} catch {
|
|
47193
47637
|
}
|
|
47194
47638
|
}
|
|
@@ -47272,8 +47716,8 @@ function writeRecordedMocks(opts) {
|
|
|
47272
47716
|
mkdir: (p) => mkdirSync24(p, { recursive: true }),
|
|
47273
47717
|
write: (p, s) => writeFileSync20(p, s)
|
|
47274
47718
|
};
|
|
47275
|
-
fs.mkdir(
|
|
47276
|
-
fs.write(
|
|
47719
|
+
fs.mkdir(join47(opts.dir, "dev"));
|
|
47720
|
+
fs.write(join47(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
47277
47721
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
47278
47722
|
}
|
|
47279
47723
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -47310,6 +47754,15 @@ async function runShotsPass(opts) {
|
|
|
47310
47754
|
}
|
|
47311
47755
|
return { dir: opts.outDir, written };
|
|
47312
47756
|
}
|
|
47757
|
+
function withCovered(rows, coveredBy) {
|
|
47758
|
+
const byScreen = new Map(rows.map((r) => [r.screen, r]));
|
|
47759
|
+
const out = [...rows];
|
|
47760
|
+
for (const [instance, representative] of coveredBy) {
|
|
47761
|
+
const r = byScreen.get(representative);
|
|
47762
|
+
if (r && !byScreen.has(instance)) out.push({ ...r, screen: instance, navEdges: [], navUnfollowed: 0 });
|
|
47763
|
+
}
|
|
47764
|
+
return out;
|
|
47765
|
+
}
|
|
47313
47766
|
async function runCrawl(opts) {
|
|
47314
47767
|
const { descriptors, deps } = opts;
|
|
47315
47768
|
const localDbSchema = await localDbEntities(opts.dir);
|
|
@@ -47320,6 +47773,7 @@ async function runCrawl(opts) {
|
|
|
47320
47773
|
const notCrawled = descriptors.filter((d) => (!only || only.has(d.screenId)) && invalid.has(d.screenId)).map((d) => ({ screen: d.screenId, why: "descriptor fails `himi validate` \u2014 fix that first, then this screen is crawled too" }));
|
|
47321
47774
|
const requested = descriptors.filter((d) => (!only || only.has(d.screenId)) && !invalid.has(d.screenId));
|
|
47322
47775
|
const collapsed = [];
|
|
47776
|
+
const coveredBy = /* @__PURE__ */ new Map();
|
|
47323
47777
|
let targets = requested;
|
|
47324
47778
|
if (!opts.allScreens) {
|
|
47325
47779
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -47334,6 +47788,7 @@ async function runCrawl(opts) {
|
|
|
47334
47788
|
const rep = list.find((d) => Object.keys(d.descriptor?.input ?? {}).length > 0) ?? list[0];
|
|
47335
47789
|
targets.push(rep);
|
|
47336
47790
|
if (list.length > 1) collapsed.push({ representative: rep.screenId, instances: list.length });
|
|
47791
|
+
for (const d of list) if (d.screenId !== rep.screenId) coveredBy.set(d.screenId, rep.screenId);
|
|
47337
47792
|
}
|
|
47338
47793
|
}
|
|
47339
47794
|
const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(resolve40(opts.netPath)), from: opts.netPath } : defaultNetRules(opts.dir);
|
|
@@ -47379,6 +47834,12 @@ async function runCrawl(opts) {
|
|
|
47379
47834
|
const cov = baked.bundleJs && deps.startWorkerCoverage ? await deps.startWorkerCoverage() : null;
|
|
47380
47835
|
const r = await deps.crawlScreen(args);
|
|
47381
47836
|
results.push(r);
|
|
47837
|
+
if (opts.onScreen) {
|
|
47838
|
+
try {
|
|
47839
|
+
opts.onScreen(buildAppMap({ declared: [...knownScreenIds], entries: opts.mapEntries ?? opts.tabRoots ?? [], ...opts.linkableScreenIds?.size ? { linkable: opts.linkableScreenIds } : {}, results: withCovered(results.map(mapResult), coveredBy), done: false }));
|
|
47840
|
+
} catch {
|
|
47841
|
+
}
|
|
47842
|
+
}
|
|
47382
47843
|
writes.push(...writesFromEffects(baked.screenId, r.effects));
|
|
47383
47844
|
for (const journey of opts.config?.journeys?.filter((candidate) => candidate.screen === baked.screenId) ?? []) {
|
|
47384
47845
|
if (!deps.crawlScreenJourney) {
|
|
@@ -47587,6 +48048,8 @@ async function runCrawl(opts) {
|
|
|
47587
48048
|
...bundleOf.get(r.screen)?.bundleMapWhy ? { sourcemap: bundleOf.get(r.screen).bundleMapWhy } : {}
|
|
47588
48049
|
})),
|
|
47589
48050
|
...edgesFollowed.length ? { edges: edgesFollowed } : {},
|
|
48051
|
+
// Final statuses come from the whole run's failures (hostile, deep, journeys), not one pass.
|
|
48052
|
+
navGraph: buildAppMap({ declared: [...knownScreenIds], entries: opts.mapEntries ?? opts.tabRoots ?? [], ...opts.linkableScreenIds?.size ? { linkable: opts.linkableScreenIds } : {}, results: withCovered(results.map((r) => ({ ...mapResult(r), failed: failedScreens.has(r.screen) })), coveredBy), done: true }),
|
|
47590
48053
|
...edgesCapped.length ? { edgesCapped } : {},
|
|
47591
48054
|
...retired.length ? { retired } : {},
|
|
47592
48055
|
...opts.deep && opts.deep >= 2 ? { deep: { depth: opts.deep, ...deepTotals } } : {},
|
|
@@ -47739,13 +48202,15 @@ function formatReport(r) {
|
|
|
47739
48202
|
}
|
|
47740
48203
|
return out.join("\n");
|
|
47741
48204
|
}
|
|
47742
|
-
var TEST_CONFIG_FILE, triggerLabel;
|
|
48205
|
+
var TEST_CONFIG_FILE, mapResult, triggerLabel;
|
|
47743
48206
|
var init_test = __esm({
|
|
47744
48207
|
"src/test.ts"() {
|
|
48208
|
+
init_app_map();
|
|
47745
48209
|
init_wix_gateway_rules();
|
|
47746
48210
|
init_crawl_layers();
|
|
47747
48211
|
init_wix_writes();
|
|
47748
48212
|
TEST_CONFIG_FILE = "himi-test.json";
|
|
48213
|
+
mapResult = (r) => ({ screen: r.screen, navEdges: r.navEdges ?? [], navUnfollowed: r.navUnfollowed ?? 0, failed: (r.findings ?? []).some((x) => x.severity === "error") });
|
|
47749
48214
|
triggerLabel = (f) => (f.trigger === "boot" ? "on appear" : `${f.trigger.key} ${f.trigger.tap ?? "(no id)"} \u2192 ${f.trigger.action}`) + (f.axis ? ` [${f.axis}]` : "");
|
|
47750
48215
|
}
|
|
47751
48216
|
});
|
|
@@ -47755,14 +48220,14 @@ var mobile_ux_lint_exports = {};
|
|
|
47755
48220
|
__export(mobile_ux_lint_exports, {
|
|
47756
48221
|
mobileUxIssues: () => mobileUxIssues
|
|
47757
48222
|
});
|
|
47758
|
-
import { existsSync as
|
|
47759
|
-
import { join as
|
|
48223
|
+
import { existsSync as existsSync50, readFileSync as readFileSync54 } from "node:fs";
|
|
48224
|
+
import { join as join48 } from "node:path";
|
|
47760
48225
|
function mobileUxIssues(dir, strict) {
|
|
47761
|
-
const file =
|
|
47762
|
-
if (!
|
|
48226
|
+
const file = join48(dir, "MOBILE-UX.md");
|
|
48227
|
+
if (!existsSync50(file)) return [];
|
|
47763
48228
|
let text5;
|
|
47764
48229
|
try {
|
|
47765
|
-
text5 =
|
|
48230
|
+
text5 = readFileSync54(file, "utf8");
|
|
47766
48231
|
} catch {
|
|
47767
48232
|
return [];
|
|
47768
48233
|
}
|
|
@@ -49437,8 +49902,8 @@ __export(functions_exports, {
|
|
|
49437
49902
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
49438
49903
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
49439
49904
|
});
|
|
49440
|
-
import { readFileSync as
|
|
49441
|
-
import { join as
|
|
49905
|
+
import { readFileSync as readFileSync55, existsSync as existsSync51 } from "node:fs";
|
|
49906
|
+
import { join as join49, resolve as resolve41 } from "node:path";
|
|
49442
49907
|
function resolveFunctionsTarget(input) {
|
|
49443
49908
|
const explicitUrl = input.functionsUrl?.trim();
|
|
49444
49909
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -49457,9 +49922,9 @@ async function loadFunctionsApp(dir) {
|
|
|
49457
49922
|
}
|
|
49458
49923
|
const sources = {};
|
|
49459
49924
|
for (const definition of config.functions.functions) {
|
|
49460
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
49925
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join49(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync51);
|
|
49461
49926
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
49462
|
-
sources[definition.name] =
|
|
49927
|
+
sources[definition.name] = readFileSync55(source, "utf8");
|
|
49463
49928
|
}
|
|
49464
49929
|
const data = config.cms || config.data ? mergeDataResources(config) : void 0;
|
|
49465
49930
|
const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
|
|
@@ -49619,10 +50084,10 @@ __export(studio_reel_exports, {
|
|
|
49619
50084
|
utcDay: () => utcDay
|
|
49620
50085
|
});
|
|
49621
50086
|
import { createHash as createHash25 } from "node:crypto";
|
|
49622
|
-
import { lstatSync as lstatSync9, readFileSync as
|
|
49623
|
-
import { basename as basename12, join as
|
|
50087
|
+
import { lstatSync as lstatSync9, readFileSync as readFileSync56 } from "node:fs";
|
|
50088
|
+
import { basename as basename12, join as join50 } from "node:path";
|
|
49624
50089
|
function loadMemory2(dir) {
|
|
49625
|
-
const m =
|
|
50090
|
+
const m = readJson5(join50(dir, ".himi", "studio", "memory.json"));
|
|
49626
50091
|
if (!isObj2(m) || m.version !== 1 || !isObj2(m.shots) || !Array.isArray(m.timeline)) return null;
|
|
49627
50092
|
const shots = [];
|
|
49628
50093
|
for (const [id, s] of Object.entries(m.shots)) {
|
|
@@ -49659,8 +50124,8 @@ function planReel(dir) {
|
|
|
49659
50124
|
const memory = loadMemory2(dir);
|
|
49660
50125
|
const { entries } = readProgress(dir);
|
|
49661
50126
|
const summary = summarizeProgress(entries);
|
|
49662
|
-
const manifest =
|
|
49663
|
-
const tokens =
|
|
50127
|
+
const manifest = readJson5(join50(dir, "himalaya.content.json"));
|
|
50128
|
+
const tokens = readJson5(join50(dir, "tokens.json"));
|
|
49664
50129
|
const accentToken = tokens?.colors?.accentPrimary;
|
|
49665
50130
|
const accentRaw = typeof accentToken === "string" ? accentToken : accentToken?.light;
|
|
49666
50131
|
const accent = typeof accentRaw === "string" && ACCENT.test(accentRaw) ? accentRaw : DEFAULT_ACCENT;
|
|
@@ -49702,10 +50167,10 @@ function inlineImages(dir, plan, budget = REEL_BUDGET_BYTES) {
|
|
|
49702
50167
|
const verified = (f) => {
|
|
49703
50168
|
if (!HISTORY_NAME.test(f)) return null;
|
|
49704
50169
|
try {
|
|
49705
|
-
const path2 =
|
|
50170
|
+
const path2 = join50(dir, HISTORY_DIR, f);
|
|
49706
50171
|
const st = lstatSync9(path2);
|
|
49707
50172
|
if (!st.isFile() || st.nlink !== 1) return null;
|
|
49708
|
-
const bytes2 =
|
|
50173
|
+
const bytes2 = readFileSync56(path2);
|
|
49709
50174
|
return createHash25("sha256").update(bytes2).digest("hex") === f.slice(0, 64) && imageExtension(bytes2) === f.slice(65) ? bytes2 : null;
|
|
49710
50175
|
} catch {
|
|
49711
50176
|
return null;
|
|
@@ -49778,7 +50243,7 @@ function sinceStart(start, ts2) {
|
|
|
49778
50243
|
}
|
|
49779
50244
|
function renderReel(plan, images) {
|
|
49780
50245
|
const img = (f, alt, cls = "") => f && images.has(f) ? `<img class="${cls}" src="${images.get(f)}" alt="${escapeHtml(alt)}">` : "";
|
|
49781
|
-
const
|
|
50246
|
+
const count2 = (n) => escapeHtml(String(Number.isSafeInteger(n) && n >= 0 ? n : 0));
|
|
49782
50247
|
const accent = ACCENT.test(plan.accent) ? plan.accent : DEFAULT_ACCENT;
|
|
49783
50248
|
const clock = (ts2) => sinceStart(plan.startedAt, ts2);
|
|
49784
50249
|
const frames = plan.frames.filter((f) => images.has(f.file));
|
|
@@ -49804,14 +50269,14 @@ figcaption{font-size:12px;color:var(--muted);margin-top:6px;word-break:break-all
|
|
|
49804
50269
|
footer{margin-top:48px;font-size:12px;color:var(--muted)}
|
|
49805
50270
|
</style></head><body><div class="wrap">
|
|
49806
50271
|
<h1>${escapeHtml(plan.app)}</h1><div class="muted">The making of \u2014 every version of the app as it was built${plan.startedAt ? `, ${escapeHtml(utcDay(plan.startedAt))}` : ""}</div>
|
|
49807
|
-
<div class="stats"><div><b>${duration(plan.stats.elapsedMs)}</b><span class="muted">from first picture to last</span></div><div><b>${
|
|
50272
|
+
<div class="stats"><div><b>${duration(plan.stats.elapsedMs)}</b><span class="muted">from first picture to last</span></div><div><b>${count2(plan.stats.screens)}</b><span class="muted">screens</span></div><div><b>${count2(plan.stats.versions)}</b><span class="muted">versions rendered</span></div><div><b>${count2(plan.stats.postcards)}</b><span class="muted">postcards</span></div></div>
|
|
49808
50273
|
<h2>${escapeHtml(plan.focusId ?? "The app")}, version by version</h2>
|
|
49809
50274
|
${flip}
|
|
49810
50275
|
<h2>Where it ended up</h2>
|
|
49811
50276
|
<div class="grid">${plan.finals.map((f) => `<figure>${img(f.file, f.id)}<figcaption>${escapeHtml(f.id)}</figcaption></figure>`).join("")}</div>
|
|
49812
50277
|
<h2>Postcards</h2>
|
|
49813
50278
|
<ul class="log">${plan.postcards.map((c) => `<li><div class="t">${clock(c.ts)}</div><div><div>${escapeHtml(c.message)}</div>${c.step ? `<div class="s">step ${JOURNEY_STEPS.indexOf(c.step) + 1} \xB7 ${escapeHtml(c.step)}</div>` : ""}${c.files.length ? `<div class="imgs">${c.files.map((f) => img(f, c.message)).join("")}</div>` : ""}</div></li>`).join("") || `<li class="muted">No postcards were journaled.</li>`}</ul>
|
|
49814
|
-
<footer>Built with himi.${plan.dropped ? ` ${
|
|
50279
|
+
<footer>Built with himi.${plan.dropped ? ` ${count2(plan.dropped)} pictures were left out to keep this file small.` : ""}</footer>
|
|
49815
50280
|
</div>
|
|
49816
50281
|
<script>
|
|
49817
50282
|
(function(){var F=${data};var imgs=document.querySelectorAll(".phone img");if(imgs.length<2)return;var i=0;
|
|
@@ -49825,7 +50290,7 @@ function buildReel(dir, budget = REEL_BUDGET_BYTES) {
|
|
|
49825
50290
|
const { plan, images } = inlineImages(dir, planReel(dir), budget);
|
|
49826
50291
|
return { html: renderReel(plan, images), plan };
|
|
49827
50292
|
}
|
|
49828
|
-
var REEL_BUDGET_BYTES, MAX_FLIP_FRAMES, DEFAULT_ACCENT, ACCENT, HISTORY_NAME, MIME2, mimeOf,
|
|
50293
|
+
var REEL_BUDGET_BYTES, MAX_FLIP_FRAMES, DEFAULT_ACCENT, ACCENT, HISTORY_NAME, MIME2, mimeOf, readJson5, isObj2, str, historyName, cited;
|
|
49829
50294
|
var init_studio_reel = __esm({
|
|
49830
50295
|
"src/studio-reel.ts"() {
|
|
49831
50296
|
init_progress();
|
|
@@ -49837,9 +50302,9 @@ var init_studio_reel = __esm({
|
|
|
49837
50302
|
HISTORY_NAME = /^[0-9a-f]{64}\.(png|jpg|gif|webp)$/;
|
|
49838
50303
|
MIME2 = { png: "image/png", jpg: "image/jpeg", gif: "image/gif", webp: "image/webp" };
|
|
49839
50304
|
mimeOf = (file) => MIME2[file.slice(65)] ?? "image/png";
|
|
49840
|
-
|
|
50305
|
+
readJson5 = (file) => {
|
|
49841
50306
|
try {
|
|
49842
|
-
return JSON.parse(
|
|
50307
|
+
return JSON.parse(readFileSync56(file, "utf8"));
|
|
49843
50308
|
} catch {
|
|
49844
50309
|
return null;
|
|
49845
50310
|
}
|
|
@@ -49870,9 +50335,9 @@ __export(native_decode_exports, {
|
|
|
49870
50335
|
runNativeDecode: () => runNativeDecode
|
|
49871
50336
|
});
|
|
49872
50337
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
49873
|
-
import { existsSync as
|
|
50338
|
+
import { existsSync as existsSync52, mkdtempSync as mkdtempSync2, readFileSync as readFileSync57, rmSync as rmSync11, writeFileSync as writeFileSync21 } from "node:fs";
|
|
49874
50339
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
49875
|
-
import { join as
|
|
50340
|
+
import { join as join51 } from "node:path";
|
|
49876
50341
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
49877
50342
|
function nativeDecodePackageDir() {
|
|
49878
50343
|
return fileURLToPath20(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -49882,8 +50347,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
49882
50347
|
}
|
|
49883
50348
|
function nativeOracleShipped() {
|
|
49884
50349
|
return {
|
|
49885
|
-
ios:
|
|
49886
|
-
android:
|
|
50350
|
+
ios: existsSync52(join51(nativeDecodePackageDir(), "Package.swift")),
|
|
50351
|
+
android: existsSync52(join51(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
49887
50352
|
};
|
|
49888
50353
|
}
|
|
49889
50354
|
function detectNativeDecode(options = {}) {
|
|
@@ -49894,7 +50359,7 @@ function detectNativeDecode(options = {}) {
|
|
|
49894
50359
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
49895
50360
|
}
|
|
49896
50361
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
49897
|
-
const packageAvailable = options.packageAvailable ??
|
|
50362
|
+
const packageAvailable = options.packageAvailable ?? existsSync52(join51(packageDir, "Package.swift"));
|
|
49898
50363
|
if (!packageAvailable) {
|
|
49899
50364
|
return {
|
|
49900
50365
|
platform: "ios",
|
|
@@ -49906,7 +50371,7 @@ function detectNativeDecode(options = {}) {
|
|
|
49906
50371
|
}
|
|
49907
50372
|
function localPropertiesSdk(harnessDir) {
|
|
49908
50373
|
try {
|
|
49909
|
-
const match =
|
|
50374
|
+
const match = readFileSync57(join51(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
49910
50375
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
49911
50376
|
} catch {
|
|
49912
50377
|
return null;
|
|
@@ -49914,8 +50379,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
49914
50379
|
}
|
|
49915
50380
|
function detectAndroidNativeDecode(options = {}) {
|
|
49916
50381
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
49917
|
-
const gradlew =
|
|
49918
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
50382
|
+
const gradlew = join51(harnessDir, "gradlew");
|
|
50383
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync52(gradlew);
|
|
49919
50384
|
if (!gradlewAvailable) {
|
|
49920
50385
|
return {
|
|
49921
50386
|
platform: "android",
|
|
@@ -49925,7 +50390,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
49925
50390
|
}
|
|
49926
50391
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
49927
50392
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
49928
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
50393
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync52(sdk));
|
|
49929
50394
|
if (!sdkAvailable) {
|
|
49930
50395
|
return {
|
|
49931
50396
|
platform: "android",
|
|
@@ -49997,14 +50462,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
49997
50462
|
return verdicts;
|
|
49998
50463
|
}
|
|
49999
50464
|
function runNativeDecode(options) {
|
|
50000
|
-
const descriptorDir = mkdtempSync2(
|
|
50465
|
+
const descriptorDir = mkdtempSync2(join51(tmpdir3(), "himi-native-decode-"));
|
|
50001
50466
|
const startedAt = Date.now();
|
|
50002
50467
|
try {
|
|
50003
50468
|
for (const descriptor of options.descriptors) {
|
|
50004
50469
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
50005
50470
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
50006
50471
|
}
|
|
50007
|
-
writeFileSync21(
|
|
50472
|
+
writeFileSync21(join51(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
50008
50473
|
}
|
|
50009
50474
|
options.progress?.("building cached Swift oracle");
|
|
50010
50475
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -50016,7 +50481,7 @@ function runNativeDecode(options) {
|
|
|
50016
50481
|
encoding: "utf8"
|
|
50017
50482
|
}).trim();
|
|
50018
50483
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
50019
|
-
const stdout = execFileSync5(
|
|
50484
|
+
const stdout = execFileSync5(join51(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
50020
50485
|
stdio: ["ignore", "pipe", "pipe"],
|
|
50021
50486
|
encoding: "utf8"
|
|
50022
50487
|
});
|
|
@@ -50034,15 +50499,15 @@ function runNativeDecode(options) {
|
|
|
50034
50499
|
}
|
|
50035
50500
|
}
|
|
50036
50501
|
function runAndroidNativeDecode(options) {
|
|
50037
|
-
const descriptorDir = mkdtempSync2(
|
|
50038
|
-
const outputPath =
|
|
50502
|
+
const descriptorDir = mkdtempSync2(join51(tmpdir3(), "himi-native-decode-android-"));
|
|
50503
|
+
const outputPath = join51(descriptorDir, "verdicts.ndjson");
|
|
50039
50504
|
const startedAt = Date.now();
|
|
50040
50505
|
try {
|
|
50041
50506
|
for (const descriptor of options.descriptors) {
|
|
50042
50507
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
50043
50508
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
50044
50509
|
}
|
|
50045
|
-
writeFileSync21(
|
|
50510
|
+
writeFileSync21(join51(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
50046
50511
|
}
|
|
50047
50512
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
50048
50513
|
execFileSync5(options.gradlew, [
|
|
@@ -50057,7 +50522,7 @@ function runAndroidNativeDecode(options) {
|
|
|
50057
50522
|
stdio: ["ignore", "ignore", "pipe"],
|
|
50058
50523
|
encoding: "utf8"
|
|
50059
50524
|
});
|
|
50060
|
-
const stdout =
|
|
50525
|
+
const stdout = readFileSync57(outputPath, "utf8");
|
|
50061
50526
|
return {
|
|
50062
50527
|
platform: "android",
|
|
50063
50528
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -50127,30 +50592,30 @@ __export(browser_authoring_exports, {
|
|
|
50127
50592
|
});
|
|
50128
50593
|
import { createServer as createServer3 } from "node:http";
|
|
50129
50594
|
import { createHash as createHash26, randomBytes as randomBytes4 } from "node:crypto";
|
|
50130
|
-
import { existsSync as
|
|
50131
|
-
import { join as
|
|
50595
|
+
import { existsSync as existsSync53, readdirSync as readdirSync27, readFileSync as readFileSync58, realpathSync as realpathSync6, statSync as statSync12 } from "node:fs";
|
|
50596
|
+
import { join as join52, posix as posix2, relative as relative9, sep as sep12 } from "node:path";
|
|
50132
50597
|
function humanMs(ms) {
|
|
50133
50598
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
50134
50599
|
}
|
|
50135
50600
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
50136
|
-
const root =
|
|
50601
|
+
const root = join52(tier5SrcDir, bundleName);
|
|
50137
50602
|
const files = {};
|
|
50138
50603
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
50139
50604
|
const walk2 = (abs, rel) => {
|
|
50140
50605
|
const real = realpathSync6(abs);
|
|
50141
50606
|
if (visitedDirs.has(real)) return;
|
|
50142
50607
|
visitedDirs.add(real);
|
|
50143
|
-
for (const name of
|
|
50144
|
-
const childAbs =
|
|
50608
|
+
for (const name of readdirSync27(abs).sort()) {
|
|
50609
|
+
const childAbs = join52(abs, name);
|
|
50145
50610
|
const childRel = posix2.join(rel, name);
|
|
50146
50611
|
if (statSync12(childAbs).isDirectory()) {
|
|
50147
50612
|
walk2(childAbs, childRel);
|
|
50148
50613
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
50149
|
-
files[childRel] =
|
|
50614
|
+
files[childRel] = readFileSync58(childAbs, "utf8");
|
|
50150
50615
|
}
|
|
50151
50616
|
}
|
|
50152
50617
|
};
|
|
50153
|
-
if (!
|
|
50618
|
+
if (!existsSync53(root)) return null;
|
|
50154
50619
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
50155
50620
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
50156
50621
|
if (!entry) return null;
|
|
@@ -50167,20 +50632,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
50167
50632
|
const spec = m[1];
|
|
50168
50633
|
const virtual = posix2.normalize(posix2.join(dir, spec));
|
|
50169
50634
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
50170
|
-
const onDisk =
|
|
50635
|
+
const onDisk = join52(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
50171
50636
|
const candidates = [
|
|
50172
50637
|
onDisk,
|
|
50173
50638
|
`${onDisk}.ts`,
|
|
50174
50639
|
`${onDisk}.js`,
|
|
50175
50640
|
onDisk.replace(/\.js$/, ".ts"),
|
|
50176
|
-
|
|
50177
|
-
|
|
50641
|
+
join52(onDisk, "index.ts"),
|
|
50642
|
+
join52(onDisk, "index.js")
|
|
50178
50643
|
];
|
|
50179
50644
|
for (const abs of candidates) {
|
|
50180
|
-
if (!
|
|
50645
|
+
if (!existsSync53(abs) || statSync12(abs).isDirectory()) continue;
|
|
50181
50646
|
const key2 = `/tier5-src/${relative9(tier5SrcDir, abs).split(sep12).join(posix2.sep)}`;
|
|
50182
50647
|
if (key2 in files) break;
|
|
50183
|
-
files[key2] =
|
|
50648
|
+
files[key2] = readFileSync58(abs, "utf8");
|
|
50184
50649
|
queue.push(key2);
|
|
50185
50650
|
break;
|
|
50186
50651
|
}
|
|
@@ -50215,7 +50680,7 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
50215
50680
|
function sdkSubpathReader(resolve48) {
|
|
50216
50681
|
return (sub) => {
|
|
50217
50682
|
try {
|
|
50218
|
-
return
|
|
50683
|
+
return readFileSync58(resolve48(`@wix/himalaya/${sub}`), "utf8");
|
|
50219
50684
|
} catch {
|
|
50220
50685
|
return null;
|
|
50221
50686
|
}
|
|
@@ -50387,8 +50852,8 @@ __export(coverage_exports, {
|
|
|
50387
50852
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
50388
50853
|
trendAndStore: () => trendAndStore
|
|
50389
50854
|
});
|
|
50390
|
-
import { existsSync as
|
|
50391
|
-
import { dirname as dirname28, join as
|
|
50855
|
+
import { existsSync as existsSync54, mkdirSync as mkdirSync25, readFileSync as readFileSync59, writeFileSync as writeFileSync22 } from "node:fs";
|
|
50856
|
+
import { dirname as dirname28, join as join53 } from "node:path";
|
|
50392
50857
|
function suppressedNativeKeys(oracle) {
|
|
50393
50858
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
50394
50859
|
}
|
|
@@ -50568,11 +51033,11 @@ function assembleLedger(r, options = {}) {
|
|
|
50568
51033
|
return out;
|
|
50569
51034
|
}
|
|
50570
51035
|
function trendAndStore(dir, entries, suppressed) {
|
|
50571
|
-
const p =
|
|
51036
|
+
const p = join53(dir, LEDGER_FILE);
|
|
50572
51037
|
let previous = null;
|
|
50573
51038
|
try {
|
|
50574
|
-
if (
|
|
50575
|
-
const parsed = JSON.parse(
|
|
51039
|
+
if (existsSync54(p)) {
|
|
51040
|
+
const parsed = JSON.parse(readFileSync59(p, "utf8"));
|
|
50576
51041
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
50577
51042
|
}
|
|
50578
51043
|
} catch {
|
|
@@ -50611,11 +51076,11 @@ function formatLedger(entries, trend) {
|
|
|
50611
51076
|
return out.join("\n");
|
|
50612
51077
|
}
|
|
50613
51078
|
function diffAndStoreObservations(dir, current) {
|
|
50614
|
-
const p =
|
|
51079
|
+
const p = join53(dir, OBS_FILE);
|
|
50615
51080
|
let previous = null;
|
|
50616
51081
|
try {
|
|
50617
|
-
if (
|
|
50618
|
-
const parsed = JSON.parse(
|
|
51082
|
+
if (existsSync54(p)) {
|
|
51083
|
+
const parsed = JSON.parse(readFileSync59(p, "utf8"));
|
|
50619
51084
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
50620
51085
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
50621
51086
|
)) {
|
|
@@ -50664,8 +51129,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
50664
51129
|
var init_coverage = __esm({
|
|
50665
51130
|
"src/coverage.ts"() {
|
|
50666
51131
|
init_native_decode();
|
|
50667
|
-
LEDGER_FILE =
|
|
50668
|
-
OBS_FILE =
|
|
51132
|
+
LEDGER_FILE = join53(".himi", "test-ledger.json");
|
|
51133
|
+
OBS_FILE = join53(".himi", "test-observations.json");
|
|
50669
51134
|
}
|
|
50670
51135
|
});
|
|
50671
51136
|
|
|
@@ -50676,16 +51141,16 @@ __export(design_kits_exports, {
|
|
|
50676
51141
|
kitsDir: () => kitsDir,
|
|
50677
51142
|
listKits: () => listKits2
|
|
50678
51143
|
});
|
|
50679
|
-
import { existsSync as
|
|
50680
|
-
import { join as
|
|
51144
|
+
import { existsSync as existsSync55, readFileSync as readFileSync60, readdirSync as readdirSync28 } from "node:fs";
|
|
51145
|
+
import { join as join54, basename as basename13 } from "node:path";
|
|
50681
51146
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
50682
51147
|
function kitsDir() {
|
|
50683
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
51148
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync55(p));
|
|
50684
51149
|
}
|
|
50685
51150
|
function listKits2() {
|
|
50686
51151
|
const dir = kitsDir();
|
|
50687
51152
|
if (!dir) return [];
|
|
50688
|
-
return
|
|
51153
|
+
return readdirSync28(dir).filter((f) => f.endsWith(".json")).map((f) => basename13(f, ".json")).sort();
|
|
50689
51154
|
}
|
|
50690
51155
|
function kitReport(name) {
|
|
50691
51156
|
const dir = kitsDir();
|
|
@@ -50704,7 +51169,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
50704
51169
|
if (!kits.includes(name)) {
|
|
50705
51170
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
50706
51171
|
}
|
|
50707
|
-
const raw =
|
|
51172
|
+
const raw = readFileSync60(join54(dir, `${name}.json`), "utf8");
|
|
50708
51173
|
let parsed;
|
|
50709
51174
|
try {
|
|
50710
51175
|
parsed = JSON.parse(raw);
|
|
@@ -50728,9 +51193,9 @@ var init_design_kits = __esm({
|
|
|
50728
51193
|
"src/design-kits.ts"() {
|
|
50729
51194
|
KIT_DIR_CANDIDATES = [
|
|
50730
51195
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
50731
|
-
|
|
51196
|
+
join54(fileURLToPath21(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
50732
51197
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
50733
|
-
|
|
51198
|
+
join54(fileURLToPath21(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
50734
51199
|
];
|
|
50735
51200
|
}
|
|
50736
51201
|
});
|
|
@@ -50744,11 +51209,11 @@ __export(assets_exports, {
|
|
|
50744
51209
|
removeAssetPayload: () => removeAssetPayload,
|
|
50745
51210
|
verifyReport: () => verifyReport
|
|
50746
51211
|
});
|
|
50747
|
-
import { readFileSync as
|
|
51212
|
+
import { readFileSync as readFileSync61 } from "node:fs";
|
|
50748
51213
|
import { basename as basename14 } from "node:path";
|
|
50749
51214
|
function declaredAssets(dir) {
|
|
50750
51215
|
return collectAssets(dir).map((a) => {
|
|
50751
|
-
const bytes2 =
|
|
51216
|
+
const bytes2 = readFileSync61(a.path);
|
|
50752
51217
|
return {
|
|
50753
51218
|
name: a.name,
|
|
50754
51219
|
sha256: assetSha256(bytes2),
|
|
@@ -50825,7 +51290,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
50825
51290
|
};
|
|
50826
51291
|
}
|
|
50827
51292
|
function addAssetPayload(manifest, filePath, opts) {
|
|
50828
|
-
const bytes2 =
|
|
51293
|
+
const bytes2 = readFileSync61(filePath);
|
|
50829
51294
|
const name = opts.name ?? basename14(filePath);
|
|
50830
51295
|
const sha2565 = assetSha256(bytes2);
|
|
50831
51296
|
const record2 = {
|
|
@@ -52468,21 +52933,21 @@ var init_preview_assets_generated = __esm({
|
|
|
52468
52933
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
52469
52934
|
init_preview_assets_format();
|
|
52470
52935
|
PREVIEW_ASSET_MANIFEST = [
|
|
52471
|
-
{ key: "assets/index-
|
|
52472
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
52473
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
52474
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
52475
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
52476
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
52477
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
52478
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
52479
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
52480
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
52481
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
52482
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
52483
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
52484
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
52485
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
52936
|
+
{ key: "assets/index-BU6QijMM.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1060352, sha256: "f608f6d0e14dafe6c495e5df15d09d7512e0a8d87732feea4f4e8e36de7917e4" },
|
|
52937
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1060360, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
52938
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1064970, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
52939
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1553554, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
52940
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1644478, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
52941
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1735462, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
52942
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1826442, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
52943
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1917314, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
52944
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2008294, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
52945
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2116930, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
52946
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2226014, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
52947
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2335062, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
52948
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2442762, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
52949
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 2530870, length: 4947, sha256: "c760d7592d0a40904bb13edaec8e8991f79fc2eb732c5dfee54fea36e6dceecb" },
|
|
52950
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2535817, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
52486
52951
|
];
|
|
52487
52952
|
}
|
|
52488
52953
|
});
|
|
@@ -52500,9 +52965,9 @@ __export(run_exports, {
|
|
|
52500
52965
|
runPackage: () => runPackage,
|
|
52501
52966
|
withoutProdServe: () => withoutProdServe
|
|
52502
52967
|
});
|
|
52503
|
-
import { cpSync as cpSync2, existsSync as
|
|
52968
|
+
import { cpSync as cpSync2, existsSync as existsSync56, mkdirSync as mkdirSync26, mkdtempSync as mkdtempSync3, readFileSync as readFileSync62, rmSync as rmSync12, statSync as statSync13 } from "node:fs";
|
|
52504
52969
|
import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
|
|
52505
|
-
import { dirname as dirname29, join as
|
|
52970
|
+
import { dirname as dirname29, join as join55 } from "node:path";
|
|
52506
52971
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
52507
52972
|
function makePackageRunHandler(opts) {
|
|
52508
52973
|
const store = new FileReleaseStore(opts.releaseRoot);
|
|
@@ -52530,9 +52995,9 @@ async function fetchBytes(url) {
|
|
|
52530
52995
|
}
|
|
52531
52996
|
async function resolvePackage(source, workDir) {
|
|
52532
52997
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
52533
|
-
if (!isUrl2 &&
|
|
52534
|
-
const appDirManifest =
|
|
52535
|
-
if (
|
|
52998
|
+
if (!isUrl2 && existsSync56(source) && statSync13(source).isDirectory()) {
|
|
52999
|
+
const appDirManifest = join55(source, "release-manifest.json");
|
|
53000
|
+
if (existsSync56(appDirManifest)) {
|
|
52536
53001
|
const opened2 = openPackageDir(source);
|
|
52537
53002
|
if (!opened2.validation.ok) {
|
|
52538
53003
|
throw new Error(`package is not valid:
|
|
@@ -52541,9 +53006,9 @@ async function resolvePackage(source, workDir) {
|
|
|
52541
53006
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
52542
53007
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
52543
53008
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
52544
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
52545
|
-
const target =
|
|
52546
|
-
if (
|
|
53009
|
+
const root2 = workDir ?? mkdtempSync3(join55(tmpdir4(), "himi-run-"));
|
|
53010
|
+
const target = join55(root2, app2);
|
|
53011
|
+
if (join55(source) !== target) {
|
|
52547
53012
|
mkdirSync26(root2, { recursive: true });
|
|
52548
53013
|
rmSync12(target, { recursive: true, force: true });
|
|
52549
53014
|
cpSync2(source, target, { recursive: true });
|
|
@@ -52560,8 +53025,8 @@ async function resolvePackage(source, workDir) {
|
|
|
52560
53025
|
}
|
|
52561
53026
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
52562
53027
|
}
|
|
52563
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
52564
|
-
const root = workDir ?? mkdtempSync3(
|
|
53028
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync62(source);
|
|
53029
|
+
const root = workDir ?? mkdtempSync3(join55(tmpdir4(), "himi-run-"));
|
|
52565
53030
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
52566
53031
|
const opened = openPackageDir(appDir2);
|
|
52567
53032
|
if (!opened.validation.ok) {
|
|
@@ -52584,14 +53049,14 @@ async function loadPreviewAssets() {
|
|
|
52584
53049
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
52585
53050
|
const here = dirname29(fileURLToPath22(import.meta.url));
|
|
52586
53051
|
const candidates = [
|
|
52587
|
-
|
|
53052
|
+
join55(here, "preview-assets.generated.bin"),
|
|
52588
53053
|
// published: copied next to the bundled CLI
|
|
52589
|
-
|
|
53054
|
+
join55(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
52590
53055
|
// in-repo checkout
|
|
52591
53056
|
];
|
|
52592
53057
|
for (const path2 of candidates) {
|
|
52593
|
-
if (!
|
|
52594
|
-
const blob =
|
|
53058
|
+
if (!existsSync56(path2)) continue;
|
|
53059
|
+
const blob = readFileSync62(path2);
|
|
52595
53060
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
52596
53061
|
}
|
|
52597
53062
|
return /* @__PURE__ */ new Map();
|
|
@@ -52738,9 +53203,9 @@ __export(run_watch_exports, {
|
|
|
52738
53203
|
watchedContentDir: () => watchedContentDir,
|
|
52739
53204
|
writeRunRecord: () => writeRunRecord
|
|
52740
53205
|
});
|
|
52741
|
-
import { closeSync as closeSync2, constants, existsSync as
|
|
53206
|
+
import { closeSync as closeSync2, constants, existsSync as existsSync57, fstatSync, lstatSync as lstatSync10, statSync as statSync14, mkdirSync as mkdirSync27, openSync as openSync2, readFileSync as readFileSync63, realpathSync as realpathSync7, renameSync as renameSync6, rmSync as rmSync13, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
|
|
52742
53207
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
52743
|
-
import { extname as extname4, join as
|
|
53208
|
+
import { extname as extname4, join as join56, resolve as resolve42, sep as sep13 } from "node:path";
|
|
52744
53209
|
function diffReleases(prev, next) {
|
|
52745
53210
|
const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
|
|
52746
53211
|
const changedBundles = new Set(bundles);
|
|
@@ -52781,7 +53246,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
52781
53246
|
let timer = null;
|
|
52782
53247
|
const pending = /* @__PURE__ */ new Set();
|
|
52783
53248
|
const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
|
|
52784
|
-
if (!file || ignoredChange(file, (rel) => isDir(
|
|
53249
|
+
if (!file || ignoredChange(file, (rel) => isDir(join56(dir, rel)))) return;
|
|
52785
53250
|
pending.add(file);
|
|
52786
53251
|
if (timer) clearTimeout(timer);
|
|
52787
53252
|
timer = setTimeout(() => {
|
|
@@ -52802,7 +53267,7 @@ function watchedContentDir(source) {
|
|
|
52802
53267
|
if (!source || /^https?:\/\//i.test(source)) return null;
|
|
52803
53268
|
const dir = resolve42(source);
|
|
52804
53269
|
try {
|
|
52805
|
-
return statSync14(dir).isDirectory() &&
|
|
53270
|
+
return statSync14(dir).isDirectory() && existsSync57(join56(dir, "himalaya.content.json")) ? dir : null;
|
|
52806
53271
|
} catch {
|
|
52807
53272
|
return null;
|
|
52808
53273
|
}
|
|
@@ -52859,7 +53324,7 @@ function serialize(task) {
|
|
|
52859
53324
|
});
|
|
52860
53325
|
}
|
|
52861
53326
|
function himiDir(dir) {
|
|
52862
|
-
const root =
|
|
53327
|
+
const root = join56(dir, ".himi");
|
|
52863
53328
|
try {
|
|
52864
53329
|
return lstatSync10(root).isDirectory() ? root : null;
|
|
52865
53330
|
} catch (e) {
|
|
@@ -52871,11 +53336,11 @@ function himiDir(dir) {
|
|
|
52871
53336
|
function writeRunRecord(dir, record2) {
|
|
52872
53337
|
const root = himiDir(dir);
|
|
52873
53338
|
if (!root) return false;
|
|
52874
|
-
const tmp =
|
|
53339
|
+
const tmp = join56(root, `.run.json.${process.pid}.${randomUUID3()}.tmp`);
|
|
52875
53340
|
try {
|
|
52876
53341
|
writeFileSync23(tmp, `${JSON.stringify(record2, null, 2)}
|
|
52877
53342
|
`, { flag: "wx" });
|
|
52878
|
-
renameSync6(tmp,
|
|
53343
|
+
renameSync6(tmp, join56(root, "run.json"));
|
|
52879
53344
|
} catch (e) {
|
|
52880
53345
|
rmSync13(tmp, { force: true });
|
|
52881
53346
|
throw e;
|
|
@@ -52883,7 +53348,7 @@ function writeRunRecord(dir, record2) {
|
|
|
52883
53348
|
return true;
|
|
52884
53349
|
}
|
|
52885
53350
|
function removeRunRecord(dir, owner) {
|
|
52886
|
-
const root =
|
|
53351
|
+
const root = join56(dir, ".himi");
|
|
52887
53352
|
try {
|
|
52888
53353
|
if (!lstatSync10(root).isDirectory()) return;
|
|
52889
53354
|
} catch {
|
|
@@ -52898,16 +53363,16 @@ function removeRunRecord(dir, owner) {
|
|
|
52898
53363
|
}
|
|
52899
53364
|
if (typeof pid === "number" && pid !== owner) return;
|
|
52900
53365
|
}
|
|
52901
|
-
rmSync13(
|
|
53366
|
+
rmSync13(join56(root, "run.json"), { force: true });
|
|
52902
53367
|
}
|
|
52903
53368
|
function boardFile(dir, pathname) {
|
|
52904
53369
|
let rel = null;
|
|
52905
|
-
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel =
|
|
52906
|
-
else if (pathname === "/__himi/studio/state.js") rel =
|
|
52907
|
-
else if (pathname === "/__himi/studio/timeline.js") rel =
|
|
53370
|
+
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join56("studio", "index.html");
|
|
53371
|
+
else if (pathname === "/__himi/studio/state.js") rel = join56("studio", "state.js");
|
|
53372
|
+
else if (pathname === "/__himi/studio/timeline.js") rel = join56("studio", "timeline.js");
|
|
52908
53373
|
else {
|
|
52909
53374
|
const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
|
|
52910
|
-
if (m) rel =
|
|
53375
|
+
if (m) rel = join56("history", m[1]);
|
|
52911
53376
|
}
|
|
52912
53377
|
if (!rel) return null;
|
|
52913
53378
|
const bytes2 = readConfined(resolve42(dir, ".himi"), rel);
|
|
@@ -52923,7 +53388,7 @@ function readConfined(root, rel) {
|
|
|
52923
53388
|
const parts = rel.split(sep13);
|
|
52924
53389
|
let at = root;
|
|
52925
53390
|
for (let i = 0; i < parts.length; i++) {
|
|
52926
|
-
at =
|
|
53391
|
+
at = join56(at, parts[i]);
|
|
52927
53392
|
const st = lstatSync10(at);
|
|
52928
53393
|
if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
|
|
52929
53394
|
}
|
|
@@ -52932,7 +53397,7 @@ function readConfined(root, rel) {
|
|
|
52932
53397
|
const fd = openSync2(at, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
52933
53398
|
try {
|
|
52934
53399
|
if (!fstatSync(fd).isFile()) return null;
|
|
52935
|
-
return
|
|
53400
|
+
return readFileSync63(fd);
|
|
52936
53401
|
} finally {
|
|
52937
53402
|
closeSync2(fd);
|
|
52938
53403
|
}
|
|
@@ -52984,7 +53449,7 @@ __export(run_browser_exports, {
|
|
|
52984
53449
|
runInBrowser: () => runInBrowser
|
|
52985
53450
|
});
|
|
52986
53451
|
import { createServer as createServer5 } from "node:http";
|
|
52987
|
-
import { existsSync as
|
|
53452
|
+
import { existsSync as existsSync58, readFileSync as readFileSync64 } from "node:fs";
|
|
52988
53453
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
52989
53454
|
import { dirname as dirname30, resolve as resolve43 } from "node:path";
|
|
52990
53455
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
@@ -52992,7 +53457,7 @@ function stagedDir() {
|
|
|
52992
53457
|
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve43(process.env.HIMI_BROWSER_PLANE_OUT) : resolve43(REPO, "packages", "serve", "dist", "browser-plane");
|
|
52993
53458
|
}
|
|
52994
53459
|
function missingStaged() {
|
|
52995
|
-
return [...SERVED].filter((f) => !
|
|
53460
|
+
return [...SERVED].filter((f) => !existsSync58(resolve43(stagedDir(), f))).sort();
|
|
52996
53461
|
}
|
|
52997
53462
|
function ensureBrowserPlaneStaged() {
|
|
52998
53463
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
@@ -53077,7 +53542,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
53077
53542
|
}
|
|
53078
53543
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
53079
53544
|
if (SERVED.has(name)) {
|
|
53080
|
-
if (!
|
|
53545
|
+
if (!existsSync58(resolve43(stagedDir(), name))) {
|
|
53081
53546
|
const restaged = ensureBrowserPlaneStaged();
|
|
53082
53547
|
if (!restaged.ok) {
|
|
53083
53548
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -53087,7 +53552,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
53087
53552
|
}
|
|
53088
53553
|
let bytes2;
|
|
53089
53554
|
try {
|
|
53090
|
-
bytes2 =
|
|
53555
|
+
bytes2 = readFileSync64(resolve43(stagedDir(), name));
|
|
53091
53556
|
} catch (e) {
|
|
53092
53557
|
res.writeHead(503, { "content-type": "application/json" });
|
|
53093
53558
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -53548,7 +54013,7 @@ __export(preflight_exports, {
|
|
|
53548
54013
|
parseStoreConfig: () => parseStoreConfig,
|
|
53549
54014
|
requireEnv: () => requireEnv
|
|
53550
54015
|
});
|
|
53551
|
-
import { existsSync as
|
|
54016
|
+
import { existsSync as existsSync59, readFileSync as readFileSync65 } from "node:fs";
|
|
53552
54017
|
import { isAbsolute as isAbsolute3, relative as relative10, resolve as resolve44 } from "node:path";
|
|
53553
54018
|
function isInsideRepo(p) {
|
|
53554
54019
|
const rel = relative10(REPO_ROOT3, resolve44(p));
|
|
@@ -53572,7 +54037,7 @@ function strip2(line) {
|
|
|
53572
54037
|
const hash = line.indexOf("#");
|
|
53573
54038
|
return (hash >= 0 ? line.slice(0, hash) : line).replace(/\s+$/, "");
|
|
53574
54039
|
}
|
|
53575
|
-
function
|
|
54040
|
+
function scalar3(v) {
|
|
53576
54041
|
const t = v.trim();
|
|
53577
54042
|
if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'")) {
|
|
53578
54043
|
return t.slice(1, -1);
|
|
@@ -53595,20 +54060,20 @@ function parseStoreConfig(text5) {
|
|
|
53595
54060
|
cfg[key2] = section2;
|
|
53596
54061
|
} else {
|
|
53597
54062
|
section2 = null;
|
|
53598
|
-
cfg[key2] =
|
|
54063
|
+
cfg[key2] = scalar3(rest);
|
|
53599
54064
|
}
|
|
53600
54065
|
} else if (section2) {
|
|
53601
|
-
section2[key2] =
|
|
54066
|
+
section2[key2] = scalar3(rest);
|
|
53602
54067
|
}
|
|
53603
54068
|
}
|
|
53604
54069
|
return cfg;
|
|
53605
54070
|
}
|
|
53606
54071
|
function loadStoreConfig(app) {
|
|
53607
54072
|
const p = storeConfigPath(app);
|
|
53608
|
-
if (!
|
|
54073
|
+
if (!existsSync59(p)) {
|
|
53609
54074
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
53610
54075
|
}
|
|
53611
|
-
return parseStoreConfig(
|
|
54076
|
+
return parseStoreConfig(readFileSync65(p, "utf8"));
|
|
53612
54077
|
}
|
|
53613
54078
|
var init_preflight = __esm({
|
|
53614
54079
|
"../store-release/preflight.ts"() {
|
|
@@ -53627,19 +54092,19 @@ __export(credential_profile_exports, {
|
|
|
53627
54092
|
profilePath: () => profilePath,
|
|
53628
54093
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
53629
54094
|
});
|
|
53630
|
-
import { existsSync as
|
|
54095
|
+
import { existsSync as existsSync60, readFileSync as readFileSync66 } from "node:fs";
|
|
53631
54096
|
import { homedir as homedir5 } from "node:os";
|
|
53632
|
-
import { join as
|
|
54097
|
+
import { join as join57 } from "node:path";
|
|
53633
54098
|
function credentialsDir(home = homedir5()) {
|
|
53634
|
-
return
|
|
54099
|
+
return join57(home, ".himalaya", "store-credentials");
|
|
53635
54100
|
}
|
|
53636
54101
|
function profilePath(name, home = homedir5()) {
|
|
53637
54102
|
if (!PROFILE_NAME.test(name)) {
|
|
53638
54103
|
throw new Error(
|
|
53639
|
-
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${
|
|
54104
|
+
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join57(credentialsDir(home), "<name>.json")}; it is never a path.`
|
|
53640
54105
|
);
|
|
53641
54106
|
}
|
|
53642
|
-
return
|
|
54107
|
+
return join57(credentialsDir(home), `${name}.json`);
|
|
53643
54108
|
}
|
|
53644
54109
|
function parseProfile(text5, label2) {
|
|
53645
54110
|
let doc;
|
|
@@ -53670,8 +54135,8 @@ function resolveStoreCredentials(opts) {
|
|
|
53670
54135
|
const { app, cfg } = opts;
|
|
53671
54136
|
const env = opts.env ?? process.env;
|
|
53672
54137
|
const home = opts.home ?? homedir5();
|
|
53673
|
-
const read = opts.readProfile ?? ((p) =>
|
|
53674
|
-
const exists = opts.profileExists ??
|
|
54138
|
+
const read = opts.readProfile ?? ((p) => readFileSync66(p, "utf8"));
|
|
54139
|
+
const exists = opts.profileExists ?? existsSync60;
|
|
53675
54140
|
const ios = cfg.ios ?? {};
|
|
53676
54141
|
const flagName = opts.profileFlag?.trim();
|
|
53677
54142
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -53751,9 +54216,9 @@ __export(preflight_app_exports, {
|
|
|
53751
54216
|
preflightApp: () => preflightApp,
|
|
53752
54217
|
profileAccount: () => profileAccount
|
|
53753
54218
|
});
|
|
53754
|
-
import { readFileSync as
|
|
54219
|
+
import { readFileSync as readFileSync67, existsSync as existsSync61, readdirSync as readdirSync29, statSync as statSync15 } from "node:fs";
|
|
53755
54220
|
import { createHash as createHash27 } from "node:crypto";
|
|
53756
|
-
import { join as
|
|
54221
|
+
import { join as join58 } from "node:path";
|
|
53757
54222
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
53758
54223
|
const f = [];
|
|
53759
54224
|
const has = (re, s) => re.test(s);
|
|
@@ -53817,13 +54282,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
53817
54282
|
}
|
|
53818
54283
|
}
|
|
53819
54284
|
async function preflightApp(app, opts = {}) {
|
|
53820
|
-
const projectYml =
|
|
53821
|
-
const storeConfig =
|
|
54285
|
+
const projectYml = existsSync61(iosProjectYml(app)) ? readFileSync67(iosProjectYml(app), "utf8") : "";
|
|
54286
|
+
const storeConfig = existsSync61(storeConfigPath(app)) ? readFileSync67(storeConfigPath(app), "utf8") : "";
|
|
53822
54287
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
53823
54288
|
const findings = analyze(
|
|
53824
54289
|
projectYml,
|
|
53825
54290
|
storeConfig,
|
|
53826
|
-
await appIconState(
|
|
54291
|
+
await appIconState(join58(appDir(app), "ios")),
|
|
53827
54292
|
profileAccount(app, storeConfig, opts)
|
|
53828
54293
|
);
|
|
53829
54294
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -53852,18 +54317,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
53852
54317
|
return f;
|
|
53853
54318
|
}
|
|
53854
54319
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
53855
|
-
const root =
|
|
54320
|
+
const root = join58(storeDir(app), "metadata");
|
|
53856
54321
|
const out = /* @__PURE__ */ new Set();
|
|
53857
|
-
if (
|
|
53858
|
-
for (const n of
|
|
54322
|
+
if (existsSync61(root)) {
|
|
54323
|
+
for (const n of readdirSync29(root)) if (n.endsWith(".txt")) out.add(n);
|
|
53859
54324
|
}
|
|
53860
|
-
if (
|
|
54325
|
+
if (existsSync61(join58(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
53861
54326
|
return out;
|
|
53862
54327
|
}
|
|
53863
54328
|
function reviewInfoFiles(app) {
|
|
53864
|
-
const dir =
|
|
53865
|
-
if (!
|
|
53866
|
-
return new Set(
|
|
54329
|
+
const dir = join58(storeDir(app), "review_information");
|
|
54330
|
+
if (!existsSync61(dir)) return /* @__PURE__ */ new Set();
|
|
54331
|
+
return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
|
|
53867
54332
|
}
|
|
53868
54333
|
function isValidAppStoreSize(w, h) {
|
|
53869
54334
|
return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
|
|
@@ -53972,12 +54437,12 @@ function analyzePlayListing(assets) {
|
|
|
53972
54437
|
return f;
|
|
53973
54438
|
}
|
|
53974
54439
|
function playListingAssets(app, locale = "en-US") {
|
|
53975
|
-
const dir =
|
|
54440
|
+
const dir = join58(storeDir(app), "play", locale, "images");
|
|
53976
54441
|
const read = (names) => {
|
|
53977
54442
|
for (const name of names) {
|
|
53978
|
-
const p =
|
|
54443
|
+
const p = join58(dir, name);
|
|
53979
54444
|
try {
|
|
53980
|
-
if (statSync15(p).isFile()) return { name, bytes:
|
|
54445
|
+
if (statSync15(p).isFile()) return { name, bytes: readFileSync67(p) };
|
|
53981
54446
|
} catch {
|
|
53982
54447
|
}
|
|
53983
54448
|
}
|
|
@@ -54008,26 +54473,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
54008
54473
|
return f;
|
|
54009
54474
|
}
|
|
54010
54475
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
54011
|
-
const dir =
|
|
54012
|
-
if (!
|
|
54013
|
-
return new Set(
|
|
54476
|
+
const dir = join58(storeDir(app), "metadata", locale);
|
|
54477
|
+
if (!existsSync61(dir)) return /* @__PURE__ */ new Set();
|
|
54478
|
+
return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
|
|
54014
54479
|
}
|
|
54015
54480
|
function listScreenshots(app, locale = "en-US") {
|
|
54016
54481
|
const out = [];
|
|
54017
|
-
const flat =
|
|
54018
|
-
if (
|
|
54019
|
-
for (const png of
|
|
54020
|
-
const sz = pngSize(
|
|
54482
|
+
const flat = join58(storeDir(app), "screenshots", locale);
|
|
54483
|
+
if (existsSync61(flat)) {
|
|
54484
|
+
for (const png of readdirSync29(flat).filter((n) => n.endsWith(".png"))) {
|
|
54485
|
+
const sz = pngSize(readFileSync67(join58(flat, png)));
|
|
54021
54486
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
54022
54487
|
}
|
|
54023
54488
|
}
|
|
54024
|
-
const legacy =
|
|
54025
|
-
if (
|
|
54026
|
-
for (const deviceDir of
|
|
54027
|
-
const d =
|
|
54489
|
+
const legacy = join58(storeDir(app), "metadata", locale, "screenshots");
|
|
54490
|
+
if (existsSync61(legacy)) {
|
|
54491
|
+
for (const deviceDir of readdirSync29(legacy)) {
|
|
54492
|
+
const d = join58(legacy, deviceDir);
|
|
54028
54493
|
if (!statSync15(d).isDirectory()) continue;
|
|
54029
|
-
for (const png of
|
|
54030
|
-
const sz = pngSize(
|
|
54494
|
+
for (const png of readdirSync29(d).filter((n) => n.endsWith(".png"))) {
|
|
54495
|
+
const sz = pngSize(readFileSync67(join58(d, png)));
|
|
54031
54496
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
54032
54497
|
}
|
|
54033
54498
|
}
|
|
@@ -54035,13 +54500,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
54035
54500
|
return out;
|
|
54036
54501
|
}
|
|
54037
54502
|
function placeholderHashes2() {
|
|
54038
|
-
const templateIos =
|
|
54039
|
-
if (!
|
|
54040
|
-
for (const target of
|
|
54041
|
-
const p =
|
|
54503
|
+
const templateIos = join58(appDir("_template"), "ios");
|
|
54504
|
+
if (!existsSync61(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
54505
|
+
for (const target of readdirSync29(templateIos)) {
|
|
54506
|
+
const p = join58(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
54042
54507
|
try {
|
|
54043
54508
|
if (!statSync15(p).isFile()) continue;
|
|
54044
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash27("sha256").update(
|
|
54509
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash27("sha256").update(readFileSync67(p)).digest("hex")];
|
|
54045
54510
|
} catch {
|
|
54046
54511
|
}
|
|
54047
54512
|
}
|
|
@@ -54072,12 +54537,12 @@ async function pixelIssues(bytes2) {
|
|
|
54072
54537
|
}
|
|
54073
54538
|
}
|
|
54074
54539
|
async function appIconState(iosDir) {
|
|
54075
|
-
if (!
|
|
54076
|
-
for (const target of
|
|
54077
|
-
const p =
|
|
54540
|
+
if (!existsSync61(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
54541
|
+
for (const target of readdirSync29(iosDir)) {
|
|
54542
|
+
const p = join58(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
54078
54543
|
try {
|
|
54079
54544
|
if (!statSync15(p).isFile()) continue;
|
|
54080
|
-
const bytes2 =
|
|
54545
|
+
const bytes2 = readFileSync67(p);
|
|
54081
54546
|
const hash = createHash27("sha256").update(bytes2).digest("hex");
|
|
54082
54547
|
const pixels = await pixelIssues(bytes2);
|
|
54083
54548
|
return {
|
|
@@ -54149,7 +54614,7 @@ __export(version_exports, {
|
|
|
54149
54614
|
setAndroidVersion: () => setAndroidVersion,
|
|
54150
54615
|
setIosVersion: () => setIosVersion
|
|
54151
54616
|
});
|
|
54152
|
-
import { readFileSync as
|
|
54617
|
+
import { readFileSync as readFileSync68, writeFileSync as writeFileSync24 } from "node:fs";
|
|
54153
54618
|
function readIosVersion(projectYml) {
|
|
54154
54619
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
54155
54620
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -54207,8 +54672,8 @@ function setAndroidVersion(gradle, v) {
|
|
|
54207
54672
|
function bumpVersion(app, opts) {
|
|
54208
54673
|
const iosPath = iosProjectYml(app);
|
|
54209
54674
|
const gradlePath = androidGradle(app);
|
|
54210
|
-
const iosYml =
|
|
54211
|
-
const gradle =
|
|
54675
|
+
const iosYml = readFileSync68(iosPath, "utf8");
|
|
54676
|
+
const gradle = readFileSync68(gradlePath, "utf8");
|
|
54212
54677
|
const current = readIosVersion(iosYml);
|
|
54213
54678
|
const next = {
|
|
54214
54679
|
marketing: opts.marketing ?? current.marketing,
|
|
@@ -54225,7 +54690,7 @@ var init_version = __esm({
|
|
|
54225
54690
|
});
|
|
54226
54691
|
|
|
54227
54692
|
// ../store-release/register-bundle.ts
|
|
54228
|
-
import { readFileSync as
|
|
54693
|
+
import { readFileSync as readFileSync69 } from "node:fs";
|
|
54229
54694
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
54230
54695
|
function b64url2(b) {
|
|
54231
54696
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -54243,7 +54708,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
54243
54708
|
async function registerBundleId(opts) {
|
|
54244
54709
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
54245
54710
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
54246
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
54711
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync69(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
54247
54712
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
54248
54713
|
method: "POST",
|
|
54249
54714
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -54297,7 +54762,7 @@ __export(asc_status_exports, {
|
|
|
54297
54762
|
ascStatus: () => ascStatus,
|
|
54298
54763
|
buildVerdict: () => buildVerdict
|
|
54299
54764
|
});
|
|
54300
|
-
import { readFileSync as
|
|
54765
|
+
import { readFileSync as readFileSync70 } from "node:fs";
|
|
54301
54766
|
function buildVerdict(builds) {
|
|
54302
54767
|
if (!builds.length) {
|
|
54303
54768
|
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).";
|
|
@@ -54311,7 +54776,7 @@ function buildVerdict(builds) {
|
|
|
54311
54776
|
function client(creds) {
|
|
54312
54777
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
54313
54778
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
54314
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
54779
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync70(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
54315
54780
|
return async (path2) => {
|
|
54316
54781
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
54317
54782
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -54471,7 +54936,7 @@ __export(secrets_exports, {
|
|
|
54471
54936
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
54472
54937
|
runSecretsCommand: () => runSecretsCommand
|
|
54473
54938
|
});
|
|
54474
|
-
import { readFileSync as
|
|
54939
|
+
import { readFileSync as readFileSync71 } from "node:fs";
|
|
54475
54940
|
function environment(value) {
|
|
54476
54941
|
if (value === "preview" || value === "production") return value;
|
|
54477
54942
|
throw new Error("--environment must be preview or production");
|
|
@@ -54502,7 +54967,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
54502
54967
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
54503
54968
|
return 0;
|
|
54504
54969
|
}
|
|
54505
|
-
const value = options.readValue ? options.readValue() :
|
|
54970
|
+
const value = options.readValue ? options.readValue() : readFileSync71(0, "utf8").replace(/\r?\n$/, "");
|
|
54506
54971
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
54507
54972
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
54508
54973
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -54531,7 +54996,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
54531
54996
|
}
|
|
54532
54997
|
let body;
|
|
54533
54998
|
if (operation !== "list") {
|
|
54534
|
-
const value = options.readValue ? options.readValue() :
|
|
54999
|
+
const value = options.readValue ? options.readValue() : readFileSync71(0, "utf8").replace(/\r?\n$/, "");
|
|
54535
55000
|
body = JSON.stringify({ value });
|
|
54536
55001
|
}
|
|
54537
55002
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -54567,15 +55032,15 @@ __export(notify_exports, {
|
|
|
54567
55032
|
runNotify: () => runNotify,
|
|
54568
55033
|
saveAdminSession: () => saveAdminSession
|
|
54569
55034
|
});
|
|
54570
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync28, readFileSync as
|
|
55035
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync28, readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
|
|
54571
55036
|
import { homedir as homedir6 } from "node:os";
|
|
54572
|
-
import { dirname as dirname32, join as
|
|
55037
|
+
import { dirname as dirname32, join as join59 } from "node:path";
|
|
54573
55038
|
function defaultSessionsPath() {
|
|
54574
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
55039
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join59(homedir6(), ".himalaya", "admin-sessions.json");
|
|
54575
55040
|
}
|
|
54576
55041
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
54577
55042
|
try {
|
|
54578
|
-
return JSON.parse(
|
|
55043
|
+
return JSON.parse(readFileSync72(path2, "utf8"));
|
|
54579
55044
|
} catch {
|
|
54580
55045
|
return {};
|
|
54581
55046
|
}
|
|
@@ -54850,11 +55315,11 @@ function resolveWixUrl(path2) {
|
|
|
54850
55315
|
if (/^https?:\/\//i.test(path2)) return path2;
|
|
54851
55316
|
return `${WIX_API3}${path2}`;
|
|
54852
55317
|
}
|
|
54853
|
-
function classifyHttp(status,
|
|
55318
|
+
function classifyHttp(status, count2) {
|
|
54854
55319
|
if (status === 428) return "not-installed";
|
|
54855
55320
|
if (status === 404) return "wrong-path";
|
|
54856
55321
|
if (status && status >= 400) return "error";
|
|
54857
|
-
return
|
|
55322
|
+
return count2 > 0 ? "ok" : "empty";
|
|
54858
55323
|
}
|
|
54859
55324
|
function makeTransport(fetchImpl, auth, timeoutMs = DEFAULT_TIMEOUT_MS4) {
|
|
54860
55325
|
return async (method, path2, body) => {
|
|
@@ -55097,9 +55562,9 @@ function planDetail(p) {
|
|
|
55097
55562
|
const pricing = p.pricing && typeof p.pricing === "object" ? p.pricing : void 0;
|
|
55098
55563
|
const sub = pricing?.subscription && typeof pricing.subscription === "object" ? pricing.subscription : void 0;
|
|
55099
55564
|
const cycleDur = sub?.cycleDuration && typeof sub.cycleDuration === "object" ? sub.cycleDuration : void 0;
|
|
55100
|
-
const
|
|
55565
|
+
const count2 = cycleDur?.count;
|
|
55101
55566
|
const unit = str4(cycleDur?.unit ?? cycleDur?.period).toLowerCase();
|
|
55102
|
-
const cycle = typeof
|
|
55567
|
+
const cycle = typeof count2 === "number" && unit ? `${count2} ${unit}` : str4(sub?.cycle ?? pricing?.cycle ?? p.period ?? p.billingPeriod);
|
|
55103
55568
|
const perks = asArr(p.perks ?? p.benefits).map((x) => str4(x) || str4(x.name)).filter(Boolean);
|
|
55104
55569
|
const bits = [cycle, perks.slice(0, 4).join("; ")].filter(Boolean);
|
|
55105
55570
|
return bits.length ? bits.join(" \xB7 ") : void 0;
|
|
@@ -55740,9 +56205,9 @@ function deriveTailoring(ctx, overrides = {}, revision = "site-derived") {
|
|
|
55740
56205
|
}
|
|
55741
56206
|
function bounded(s, max) {
|
|
55742
56207
|
if (s.length <= max) return s;
|
|
55743
|
-
const
|
|
55744
|
-
const space =
|
|
55745
|
-
return `${(space > max * 0.6 ?
|
|
56208
|
+
const cut2 = s.slice(0, max - 1);
|
|
56209
|
+
const space = cut2.lastIndexOf(" ");
|
|
56210
|
+
return `${(space > max * 0.6 ? cut2.slice(0, space) : cut2).trimEnd()}\u2026`;
|
|
55746
56211
|
}
|
|
55747
56212
|
function deriveStaticFaq(faq) {
|
|
55748
56213
|
if (!Array.isArray(faq)) return [];
|
|
@@ -57440,11 +57905,11 @@ function editorText(fields, probes) {
|
|
|
57440
57905
|
function stripLead(name) {
|
|
57441
57906
|
const [left = "", ...rest] = name.split(/\s+&\s+/);
|
|
57442
57907
|
const words = left.split(/\s+/);
|
|
57443
|
-
let
|
|
57908
|
+
let cut2 = 0;
|
|
57444
57909
|
words.forEach((w, i) => {
|
|
57445
|
-
if (LEAD_STOPWORDS.has(w.toLowerCase()))
|
|
57910
|
+
if (LEAD_STOPWORDS.has(w.toLowerCase())) cut2 = i + 1;
|
|
57446
57911
|
});
|
|
57447
|
-
const kept = words.slice(
|
|
57912
|
+
const kept = words.slice(cut2).join(" ");
|
|
57448
57913
|
return kept ? [kept, ...rest].join(" & ") : "";
|
|
57449
57914
|
}
|
|
57450
57915
|
function nameMismatches(identity, look, fields) {
|
|
@@ -57495,13 +57960,13 @@ function duplicateMedia(look, probes) {
|
|
|
57495
57960
|
const k = mediaKey(u);
|
|
57496
57961
|
counts.set(k, (counts.get(k) ?? 0) + 1);
|
|
57497
57962
|
}
|
|
57498
|
-
for (const [k,
|
|
57499
|
-
if (
|
|
57963
|
+
for (const [k, count2] of counts) {
|
|
57964
|
+
if (count2 < DUPLICATE_MEDIA_MIN || out.length >= CAP3.perKind) continue;
|
|
57500
57965
|
out.push({
|
|
57501
57966
|
kind: "duplicate-media",
|
|
57502
57967
|
value: k.slice(0, 80),
|
|
57503
57968
|
where: [where],
|
|
57504
|
-
note: `the same image is used ${
|
|
57969
|
+
note: `the same image is used ${count2} times here \u2014 template filler, not ${count2} distinct photos; do not present it as the business's gallery`
|
|
57505
57970
|
});
|
|
57506
57971
|
}
|
|
57507
57972
|
};
|
|
@@ -58344,7 +58809,7 @@ var init_brand_font = __esm({
|
|
|
58344
58809
|
|
|
58345
58810
|
// src/site-analyze/write-artifacts.ts
|
|
58346
58811
|
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync26 } from "node:fs";
|
|
58347
|
-
import { join as
|
|
58812
|
+
import { join as join60 } from "node:path";
|
|
58348
58813
|
function attachVeloSources(book, sources, put) {
|
|
58349
58814
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
58350
58815
|
for (const f of book.velo.files) {
|
|
@@ -58499,12 +58964,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
58499
58964
|
}
|
|
58500
58965
|
async function writeBusinessBook(result, opts) {
|
|
58501
58966
|
const out = opts.outDir;
|
|
58502
|
-
mkdirSync29(
|
|
58503
|
-
mkdirSync29(
|
|
58967
|
+
mkdirSync29(join60(out, "evidence/pages"), { recursive: true });
|
|
58968
|
+
mkdirSync29(join60(out, "media/catalog"), { recursive: true });
|
|
58504
58969
|
const files = [];
|
|
58505
58970
|
const put = (rel, body) => {
|
|
58506
|
-
const p =
|
|
58507
|
-
mkdirSync29(
|
|
58971
|
+
const p = join60(out, rel);
|
|
58972
|
+
mkdirSync29(join60(p, ".."), { recursive: true });
|
|
58508
58973
|
writeFileSync26(p, body);
|
|
58509
58974
|
files.push(rel);
|
|
58510
58975
|
};
|
|
@@ -58598,8 +59063,8 @@ var init_customer_build = __esm({
|
|
|
58598
59063
|
});
|
|
58599
59064
|
|
|
58600
59065
|
// src/site-analyze/apply.ts
|
|
58601
|
-
import { existsSync as
|
|
58602
|
-
import { dirname as dirname33, isAbsolute as isAbsolute4, join as
|
|
59066
|
+
import { existsSync as existsSync62, readFileSync as readFileSync73, writeFileSync as writeFileSync27, copyFileSync as copyFileSync3, mkdirSync as mkdirSync30, realpathSync as realpathSync8, statSync as statSync16 } from "node:fs";
|
|
59067
|
+
import { dirname as dirname33, isAbsolute as isAbsolute4, join as join61, resolve as resolve45, sep as sep14 } from "node:path";
|
|
58603
59068
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
58604
59069
|
function unpairedRedirectNote(overlay) {
|
|
58605
59070
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
@@ -58614,7 +59079,7 @@ function committedShellProvisioning(path2) {
|
|
|
58614
59079
|
function findRepoRoot(cwd) {
|
|
58615
59080
|
let dir = cwd;
|
|
58616
59081
|
for (let i = 0; i < 8; i++) {
|
|
58617
|
-
if (SHELL_NAMES2.some((name) =>
|
|
59082
|
+
if (SHELL_NAMES2.some((name) => existsSync62(join61(dir, shellAppDir(name), "package.json")))) return dir;
|
|
58618
59083
|
const next = dirname33(dir);
|
|
58619
59084
|
if (next === dir) break;
|
|
58620
59085
|
dir = next;
|
|
@@ -58683,11 +59148,11 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
58683
59148
|
}
|
|
58684
59149
|
function buildMergedContract(options) {
|
|
58685
59150
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
58686
|
-
const committedPath =
|
|
58687
|
-
if (!
|
|
59151
|
+
const committedPath = join61(appDir2, "provisioning.json");
|
|
59152
|
+
if (!existsSync62(committedPath)) {
|
|
58688
59153
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
58689
59154
|
}
|
|
58690
|
-
const committed = JSON.parse(
|
|
59155
|
+
const committed = JSON.parse(readFileSync73(committedPath, "utf8"));
|
|
58691
59156
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
58692
59157
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
58693
59158
|
const branding = merged.branding ?? {};
|
|
@@ -58699,8 +59164,8 @@ function buildMergedContract(options) {
|
|
|
58699
59164
|
};
|
|
58700
59165
|
const stage = (fromRel, toRel) => {
|
|
58701
59166
|
const from = contained(packageDir, fromRel);
|
|
58702
|
-
const to = contained(
|
|
58703
|
-
if (!from || !to || !
|
|
59167
|
+
const to = contained(join61(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
59168
|
+
if (!from || !to || !existsSync62(from)) return void 0;
|
|
58704
59169
|
let real;
|
|
58705
59170
|
let realRoot;
|
|
58706
59171
|
try {
|
|
@@ -58722,11 +59187,11 @@ function buildMergedContract(options) {
|
|
|
58722
59187
|
};
|
|
58723
59188
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
58724
59189
|
if (icon) branding.appIconPath = icon;
|
|
58725
|
-
const facesPath =
|
|
58726
|
-
if (
|
|
59190
|
+
const facesPath = join61(packageDir, "media/fonts/faces.json");
|
|
59191
|
+
if (existsSync62(facesPath)) {
|
|
58727
59192
|
let faces = [];
|
|
58728
59193
|
try {
|
|
58729
|
-
const parsed = JSON.parse(
|
|
59194
|
+
const parsed = JSON.parse(readFileSync73(facesPath, "utf8"));
|
|
58730
59195
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
58731
59196
|
} catch {
|
|
58732
59197
|
faces = [];
|
|
@@ -58747,9 +59212,9 @@ function buildMergedContract(options) {
|
|
|
58747
59212
|
merged.branding = branding;
|
|
58748
59213
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
58749
59214
|
`;
|
|
58750
|
-
const path2 =
|
|
59215
|
+
const path2 = join61(packageDir, "provisioning.contract.json");
|
|
58751
59216
|
writeFileSync27(path2, body);
|
|
58752
|
-
const localPath =
|
|
59217
|
+
const localPath = join61(appDir2, LOCAL_CONTRACT_REL);
|
|
58753
59218
|
mkdirSync30(dirname33(localPath), { recursive: true });
|
|
58754
59219
|
writeFileSync27(localPath, body);
|
|
58755
59220
|
staged.push(localPath);
|
|
@@ -58784,10 +59249,10 @@ function catalogTypography(overlay, template) {
|
|
|
58784
59249
|
function staticFaqFor(overlay, overlayPath) {
|
|
58785
59250
|
const own3 = overlay.faq;
|
|
58786
59251
|
if (own3 !== void 0) return deriveStaticFaq(own3);
|
|
58787
|
-
const bookPath =
|
|
58788
|
-
if (!
|
|
59252
|
+
const bookPath = join61(dirname33(resolve45(overlayPath)), "book.json");
|
|
59253
|
+
if (!existsSync62(bookPath)) return void 0;
|
|
58789
59254
|
try {
|
|
58790
|
-
const book = JSON.parse(
|
|
59255
|
+
const book = JSON.parse(readFileSync73(bookPath, "utf8"));
|
|
58791
59256
|
const copy = book?.copy;
|
|
58792
59257
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
58793
59258
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -58801,8 +59266,8 @@ async function applyOverlays(input) {
|
|
|
58801
59266
|
const cwd = resolve45(input.cwd);
|
|
58802
59267
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
58803
59268
|
assertKnownShell(shell);
|
|
58804
|
-
const overlay = JSON.parse(
|
|
58805
|
-
const tokens = JSON.parse(
|
|
59269
|
+
const overlay = JSON.parse(readFileSync73(input.overlayPath, "utf8"));
|
|
59270
|
+
const tokens = JSON.parse(readFileSync73(input.tokensPath, "utf8"));
|
|
58806
59271
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
58807
59272
|
if (faq !== void 0) overlay.faq = faq;
|
|
58808
59273
|
const wrote = [];
|
|
@@ -58814,7 +59279,7 @@ async function applyOverlays(input) {
|
|
|
58814
59279
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
58815
59280
|
);
|
|
58816
59281
|
}
|
|
58817
|
-
const appDir2 =
|
|
59282
|
+
const appDir2 = join61(repoRoot2, shellAppDir(shell));
|
|
58818
59283
|
const packageDir = dirname33(resolve45(input.overlayPath));
|
|
58819
59284
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
58820
59285
|
wrote.push(...staged);
|
|
@@ -58836,11 +59301,11 @@ async function applyOverlays(input) {
|
|
|
58836
59301
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
58837
59302
|
};
|
|
58838
59303
|
}
|
|
58839
|
-
const pkgProv =
|
|
59304
|
+
const pkgProv = join61(cwd, "provisioning.json");
|
|
58840
59305
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
58841
59306
|
let packageFaq = faq;
|
|
58842
|
-
if (
|
|
58843
|
-
const cur = JSON.parse(
|
|
59307
|
+
if (existsSync62(pkgProv)) {
|
|
59308
|
+
const cur = JSON.parse(readFileSync73(pkgProv, "utf8"));
|
|
58844
59309
|
const merged = deepMerge4(cur, overlay);
|
|
58845
59310
|
packageFaq = merged.faq;
|
|
58846
59311
|
writeFileSync27(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
@@ -58849,9 +59314,9 @@ async function applyOverlays(input) {
|
|
|
58849
59314
|
writeFileSync27(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
58850
59315
|
wrote.push(pkgProv);
|
|
58851
59316
|
}
|
|
58852
|
-
const pkgTokens =
|
|
58853
|
-
if (
|
|
58854
|
-
const cur = JSON.parse(
|
|
59317
|
+
const pkgTokens = join61(cwd, "tokens.json");
|
|
59318
|
+
if (existsSync62(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
59319
|
+
const cur = JSON.parse(readFileSync73(pkgTokens, "utf8"));
|
|
58855
59320
|
let tokensIn = tokens;
|
|
58856
59321
|
if (tokens.typography) {
|
|
58857
59322
|
const fonts = catalogTypography(tokens.typography, cur.typography);
|
|
@@ -58876,9 +59341,9 @@ async function applyOverlays(input) {
|
|
|
58876
59341
|
wrote.push(pkgTokens);
|
|
58877
59342
|
}
|
|
58878
59343
|
const homeAction = homeRefreshActionId(shell);
|
|
58879
|
-
const homeSrc =
|
|
58880
|
-
if (homeAction &&
|
|
58881
|
-
const prev =
|
|
59344
|
+
const homeSrc = join61(cwd, "dev/index.ts");
|
|
59345
|
+
if (homeAction && existsSync62(homeSrc)) {
|
|
59346
|
+
const prev = readFileSync73(homeSrc, "utf8");
|
|
58882
59347
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
58883
59348
|
let next = patched.src;
|
|
58884
59349
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -58909,13 +59374,13 @@ async function applyOverlays(input) {
|
|
|
58909
59374
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
58910
59375
|
}
|
|
58911
59376
|
}
|
|
58912
|
-
if (!input.iconPath || !
|
|
59377
|
+
if (!input.iconPath || !existsSync62(input.iconPath)) {
|
|
58913
59378
|
const book = input.iconPath ? dirname33(dirname33(resolve45(input.iconPath))) : void 0;
|
|
58914
59379
|
notes.push(
|
|
58915
59380
|
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"
|
|
58916
59381
|
);
|
|
58917
59382
|
}
|
|
58918
|
-
if (input.iconPath &&
|
|
59383
|
+
if (input.iconPath && existsSync62(input.iconPath)) {
|
|
58919
59384
|
try {
|
|
58920
59385
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
58921
59386
|
wrote.push(...installed.wrote);
|
|
@@ -63102,7 +63567,7 @@ __export(cli_exports, {
|
|
|
63102
63567
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
63103
63568
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
63104
63569
|
});
|
|
63105
|
-
import { readFileSync as
|
|
63570
|
+
import { readFileSync as readFileSync74 } from "node:fs";
|
|
63106
63571
|
import { resolve as resolve46 } from "node:path";
|
|
63107
63572
|
function assetFetchFor(_opts) {
|
|
63108
63573
|
return pinnedFetch2;
|
|
@@ -63201,7 +63666,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
63201
63666
|
let source;
|
|
63202
63667
|
if (opts.sourcePath) {
|
|
63203
63668
|
const p = resolve46(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
63204
|
-
source =
|
|
63669
|
+
source = readFileSync74(p, "utf8");
|
|
63205
63670
|
}
|
|
63206
63671
|
let body;
|
|
63207
63672
|
if (opts.bodyRaw != null) {
|
|
@@ -63460,7 +63925,7 @@ __export(site_create_exports, {
|
|
|
63460
63925
|
runSiteList: () => runSiteList,
|
|
63461
63926
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
63462
63927
|
});
|
|
63463
|
-
import { existsSync as
|
|
63928
|
+
import { existsSync as existsSync63, readFileSync as readFileSync75, writeFileSync as writeFileSync28 } from "node:fs";
|
|
63464
63929
|
import { resolve as resolvePath2 } from "node:path";
|
|
63465
63930
|
function oauthClientName(projectName) {
|
|
63466
63931
|
return `${projectName} client`;
|
|
@@ -63609,7 +64074,7 @@ async function runSiteCreate(opts) {
|
|
|
63609
64074
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
63610
64075
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
63611
64076
|
}
|
|
63612
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
64077
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync63, readFileSync: readFileSync75, writeFileSync: writeFileSync28 }) {
|
|
63613
64078
|
const msid = binding2.siteId;
|
|
63614
64079
|
const path2 = resolvePath2(target);
|
|
63615
64080
|
const committed = committedShellProvisioning(path2);
|
|
@@ -64282,11 +64747,11 @@ var init_context = __esm({
|
|
|
64282
64747
|
});
|
|
64283
64748
|
|
|
64284
64749
|
// src/cli.ts
|
|
64285
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
64750
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync76, mkdirSync as mkdirSync31, writeFileSync as writeFileSync29, existsSync as existsSync64, rmSync as rmSync14, readdirSync as readdirSync30, statSync as statSync17, lstatSync as lstatSync11, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
|
|
64286
64751
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn6 } from "node:child_process";
|
|
64287
64752
|
import { createHash as createHash28, randomUUID as randomUUID5 } from "node:crypto";
|
|
64288
64753
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
64289
|
-
import { join as
|
|
64754
|
+
import { join as join62, resolve as resolve47, relative as relative11, basename as basename15, dirname as dirname34 } from "node:path";
|
|
64290
64755
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
64291
64756
|
|
|
64292
64757
|
// ../serve-cli/src/client.ts
|
|
@@ -65487,14 +65952,14 @@ async function seedCms(opts) {
|
|
|
65487
65952
|
report2.ok = false;
|
|
65488
65953
|
continue;
|
|
65489
65954
|
}
|
|
65490
|
-
const
|
|
65491
|
-
if (
|
|
65955
|
+
const count2 = await countItems(call, id);
|
|
65956
|
+
if (count2 === null && !force) {
|
|
65492
65957
|
report2.skipped.push({ collection: id, reason: "could not read the current row count, so seeding might bury existing content. Re-run, or pass --force if you are sure." });
|
|
65493
65958
|
report2.ok = false;
|
|
65494
65959
|
continue;
|
|
65495
65960
|
}
|
|
65496
|
-
if (
|
|
65497
|
-
report2.skipped.push({ collection: id, reason: `already has ${
|
|
65961
|
+
if (count2 !== null && count2 > 0 && !force) {
|
|
65962
|
+
report2.skipped.push({ collection: id, reason: `already has ${count2} items \u2014 seeding an already-populated collection needs --force so real content is never buried under sample rows` });
|
|
65498
65963
|
continue;
|
|
65499
65964
|
}
|
|
65500
65965
|
if (!dryRun) {
|
|
@@ -65585,7 +66050,7 @@ function placeholder(type, key2, i) {
|
|
|
65585
66050
|
}
|
|
65586
66051
|
}
|
|
65587
66052
|
async function writeSeedRows(opts) {
|
|
65588
|
-
const { app, cms, dir, count = 8 } = opts;
|
|
66053
|
+
const { app, cms, dir, count: count2 = 8 } = opts;
|
|
65589
66054
|
const file = join8(dir, "cms-seed.json");
|
|
65590
66055
|
const owned = (cms?.collections ?? []).filter((s) => s.id?.startsWith(namespacePrefix(app)));
|
|
65591
66056
|
if (!owned.length) {
|
|
@@ -65616,10 +66081,10 @@ async function writeSeedRows(opts) {
|
|
|
65616
66081
|
const collections = {};
|
|
65617
66082
|
for (const spec of owned) {
|
|
65618
66083
|
existing[spec.id] = Array.from(
|
|
65619
|
-
{ length:
|
|
66084
|
+
{ length: count2 },
|
|
65620
66085
|
(_, i) => Object.fromEntries(spec.fields.map((f) => [f.key, placeholder(f.type, f.displayName || f.key, i)]))
|
|
65621
66086
|
);
|
|
65622
|
-
collections[spec.id] =
|
|
66087
|
+
collections[spec.id] = count2;
|
|
65623
66088
|
}
|
|
65624
66089
|
writeFileSync6(file, `${JSON.stringify(existing, null, 2)}
|
|
65625
66090
|
`);
|
|
@@ -65634,7 +66099,7 @@ ${s.fields.map((f) => ` ${f.key} (${f.type})`).join("\n")}`
|
|
|
65634
66099
|
schema,
|
|
65635
66100
|
``,
|
|
65636
66101
|
`Rules:`,
|
|
65637
|
-
` - Keep the exact same JSON shape: one key per collection id, an array of ${
|
|
66102
|
+
` - Keep the exact same JSON shape: one key per collection id, an array of ${count2} row objects.`,
|
|
65638
66103
|
` - Use ONLY the field keys listed above, and keep each value's JSON type (TEXT\u2192string, NUMBER\u2192number, BOOLEAN\u2192boolean, DATE/DATETIME\u2192ISO string, IMAGE/VIDEO/AUDIO/DOCUMENT\u2192an https URL).`,
|
|
65639
66104
|
` - Make the content specific and plausible for this app's domain \u2014 real-sounding names, sensible prices, varied categories. No "Lorem ipsum", no "Sample item 1".`,
|
|
65640
66105
|
` - Leave any collection key already in the file that is not listed above untouched.`,
|
|
@@ -66402,8 +66867,8 @@ var str6 = (v) => typeof v === "string" ? v : void 0;
|
|
|
66402
66867
|
var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
66403
66868
|
function embeddedTemplateCatalog() {
|
|
66404
66869
|
return availableTemplates().map((name) => {
|
|
66405
|
-
const path2 =
|
|
66406
|
-
const meta = JSON.parse(
|
|
66870
|
+
const path2 = join62(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
66871
|
+
const meta = JSON.parse(readFileSync76(path2, "utf8"));
|
|
66407
66872
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
66408
66873
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
66409
66874
|
}
|
|
@@ -67082,7 +67547,7 @@ var COMMANDS = [
|
|
|
67082
67547
|
];
|
|
67083
67548
|
function cliVersion() {
|
|
67084
67549
|
try {
|
|
67085
|
-
return JSON.parse(
|
|
67550
|
+
return JSON.parse(readFileSync76(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
67086
67551
|
} catch {
|
|
67087
67552
|
return "unknown";
|
|
67088
67553
|
}
|
|
@@ -67200,7 +67665,7 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
67200
67665
|
}
|
|
67201
67666
|
function packageVersion(path2) {
|
|
67202
67667
|
try {
|
|
67203
|
-
const version2 = JSON.parse(
|
|
67668
|
+
const version2 = JSON.parse(readFileSync76(path2, "utf8")).version;
|
|
67204
67669
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
67205
67670
|
} catch {
|
|
67206
67671
|
return void 0;
|
|
@@ -67209,7 +67674,7 @@ function packageVersion(path2) {
|
|
|
67209
67674
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
67210
67675
|
let dir = resolve47(fromDir);
|
|
67211
67676
|
for (; ; ) {
|
|
67212
|
-
const version2 = packageVersion(
|
|
67677
|
+
const version2 = packageVersion(join62(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
67213
67678
|
if (version2) return { version: version2, source: "local" };
|
|
67214
67679
|
const parent = dirname34(dir);
|
|
67215
67680
|
if (parent === dir) break;
|
|
@@ -67219,7 +67684,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
67219
67684
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
67220
67685
|
try {
|
|
67221
67686
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
67222
|
-
const version2 = root ? packageVersion(
|
|
67687
|
+
const version2 = root ? packageVersion(join62(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
67223
67688
|
return version2 ? { version: version2, source: "global" } : {};
|
|
67224
67689
|
} catch {
|
|
67225
67690
|
return {};
|
|
@@ -67266,11 +67731,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
67266
67731
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
67267
67732
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
67268
67733
|
function updateCachePath(env = process.env) {
|
|
67269
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
67734
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join62(homedir7(), ".himalaya", "update-check.json");
|
|
67270
67735
|
}
|
|
67271
67736
|
function readUpdateCache(path2) {
|
|
67272
67737
|
try {
|
|
67273
|
-
const parsed = JSON.parse(
|
|
67738
|
+
const parsed = JSON.parse(readFileSync76(path2, "utf8"));
|
|
67274
67739
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
67275
67740
|
} catch {
|
|
67276
67741
|
return {};
|
|
@@ -67338,12 +67803,12 @@ function createUpdateRunner(spawn7 = spawnSync5) {
|
|
|
67338
67803
|
},
|
|
67339
67804
|
installedVersion: () => {
|
|
67340
67805
|
const root = globalNodeModulesRoot();
|
|
67341
|
-
return root ? packageVersion(
|
|
67806
|
+
return root ? packageVersion(join62(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
67342
67807
|
},
|
|
67343
67808
|
reexec: (argv) => {
|
|
67344
67809
|
const root = globalNodeModulesRoot();
|
|
67345
|
-
const entry = root ?
|
|
67346
|
-
if (!entry || !
|
|
67810
|
+
const entry = root ? join62(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
67811
|
+
if (!entry || !existsSync64(entry)) return void 0;
|
|
67347
67812
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
67348
67813
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
67349
67814
|
stdio: "inherit",
|
|
@@ -67390,7 +67855,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
67390
67855
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
67391
67856
|
let content;
|
|
67392
67857
|
try {
|
|
67393
|
-
content =
|
|
67858
|
+
content = readFileSync76(path2, "utf8");
|
|
67394
67859
|
} catch {
|
|
67395
67860
|
continue;
|
|
67396
67861
|
}
|
|
@@ -67413,7 +67878,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
67413
67878
|
const mine = lockStamp(now);
|
|
67414
67879
|
const readLock = (path2) => {
|
|
67415
67880
|
try {
|
|
67416
|
-
return
|
|
67881
|
+
return readFileSync76(path2, "utf8");
|
|
67417
67882
|
} catch {
|
|
67418
67883
|
return void 0;
|
|
67419
67884
|
}
|
|
@@ -67997,7 +68462,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
67997
68462
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
67998
68463
|
for (const dir of entries) {
|
|
67999
68464
|
for (const suffix of suffixes) {
|
|
68000
|
-
const candidate =
|
|
68465
|
+
const candidate = join62(dir, `${name}${suffix}`);
|
|
68001
68466
|
try {
|
|
68002
68467
|
if (!statSync17(candidate).isFile()) continue;
|
|
68003
68468
|
if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
|
|
@@ -68106,7 +68571,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
68106
68571
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
68107
68572
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
68108
68573
|
const iosYmlPath = iosProjectYml2(app);
|
|
68109
|
-
const iosYml =
|
|
68574
|
+
const iosYml = existsSync64(iosYmlPath) ? readFileSync76(iosYmlPath, "utf8") : "";
|
|
68110
68575
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
68111
68576
|
if (!optedIn) {
|
|
68112
68577
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -68120,7 +68585,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
68120
68585
|
}
|
|
68121
68586
|
function readConfigSource(dir) {
|
|
68122
68587
|
try {
|
|
68123
|
-
return
|
|
68588
|
+
return readFileSync76(join62(dir, "config.ts"), "utf8");
|
|
68124
68589
|
} catch {
|
|
68125
68590
|
return null;
|
|
68126
68591
|
}
|
|
@@ -68156,7 +68621,7 @@ function keptPlan(kept) {
|
|
|
68156
68621
|
}
|
|
68157
68622
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
68158
68623
|
const dir = resolve47(parentDir, name);
|
|
68159
|
-
if (
|
|
68624
|
+
if (existsSync64(join62(dir, "himalaya.content.json"))) {
|
|
68160
68625
|
throw new Error(`content package already exists at ${dir}`);
|
|
68161
68626
|
}
|
|
68162
68627
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -68199,11 +68664,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
68199
68664
|
function restoreDestinationIssue(dest, force) {
|
|
68200
68665
|
const link = symlinkDestinationIssue(dest);
|
|
68201
68666
|
if (link) return link;
|
|
68202
|
-
if (!
|
|
68667
|
+
if (!existsSync64(dest)) return null;
|
|
68203
68668
|
if (!statSync17(dest).isDirectory()) {
|
|
68204
68669
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
68205
68670
|
}
|
|
68206
|
-
if (
|
|
68671
|
+
if (readdirSync30(dest).length > 0 && !force) {
|
|
68207
68672
|
return {
|
|
68208
68673
|
error: `${dest} already exists and is not empty`,
|
|
68209
68674
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -68214,7 +68679,7 @@ function restoreDestinationIssue(dest, force) {
|
|
|
68214
68679
|
function isHimalayaMonorepoCheckout(start) {
|
|
68215
68680
|
let dir = resolve47(start);
|
|
68216
68681
|
for (; ; ) {
|
|
68217
|
-
if (
|
|
68682
|
+
if (existsSync64(join62(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync64(join62(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
68218
68683
|
const parent = dirname34(dir);
|
|
68219
68684
|
if (parent === dir) return false;
|
|
68220
68685
|
dir = parent;
|
|
@@ -68275,7 +68740,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
68275
68740
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
68276
68741
|
);
|
|
68277
68742
|
const repoRoot2 = resolve47(fileURLToPath24(new URL("../../..", import.meta.url)));
|
|
68278
|
-
const root =
|
|
68743
|
+
const root = join62(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
68279
68744
|
const stillRunning = (pid) => {
|
|
68280
68745
|
try {
|
|
68281
68746
|
process.kill(pid, 0);
|
|
@@ -68285,16 +68750,16 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
68285
68750
|
}
|
|
68286
68751
|
};
|
|
68287
68752
|
try {
|
|
68288
|
-
for (const entry of
|
|
68753
|
+
for (const entry of readdirSync30(root, { withFileTypes: true })) {
|
|
68289
68754
|
if (!entry.isDirectory()) continue;
|
|
68290
68755
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
68291
68756
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
68292
|
-
rmSync14(
|
|
68757
|
+
rmSync14(join62(root, entry.name), { recursive: true, force: true });
|
|
68293
68758
|
}
|
|
68294
68759
|
}
|
|
68295
68760
|
} catch {
|
|
68296
68761
|
}
|
|
68297
|
-
const dest =
|
|
68762
|
+
const dest = join62(root, `${slug}-${process.pid}`);
|
|
68298
68763
|
rmSync14(dest, { recursive: true, force: true });
|
|
68299
68764
|
mkdirSync31(dest, { recursive: true });
|
|
68300
68765
|
try {
|
|
@@ -68307,8 +68772,8 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
68307
68772
|
}
|
|
68308
68773
|
async function appId(dir) {
|
|
68309
68774
|
try {
|
|
68310
|
-
const { readFileSync:
|
|
68311
|
-
const m = JSON.parse(
|
|
68775
|
+
const { readFileSync: readFileSync77 } = await import("node:fs");
|
|
68776
|
+
const m = JSON.parse(readFileSync77(join62(dir, "himalaya.content.json"), "utf8"));
|
|
68312
68777
|
if (m.name) return m.name;
|
|
68313
68778
|
} catch {
|
|
68314
68779
|
}
|
|
@@ -68316,8 +68781,8 @@ async function appId(dir) {
|
|
|
68316
68781
|
}
|
|
68317
68782
|
async function contentVisibility(dir) {
|
|
68318
68783
|
try {
|
|
68319
|
-
const { readFileSync:
|
|
68320
|
-
const m = JSON.parse(
|
|
68784
|
+
const { readFileSync: readFileSync77 } = await import("node:fs");
|
|
68785
|
+
const m = JSON.parse(readFileSync77(join62(dir, "himalaya.content.json"), "utf8"));
|
|
68321
68786
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
68322
68787
|
} catch {
|
|
68323
68788
|
}
|
|
@@ -68541,7 +69006,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
68541
69006
|
...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/" } : {},
|
|
68542
69007
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
68543
69008
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
68544
|
-
...
|
|
69009
|
+
...existsSync64(join62(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" } : {},
|
|
68545
69010
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
68546
69011
|
portalUrl: idx.portalUrl
|
|
68547
69012
|
});
|
|
@@ -68564,7 +69029,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
68564
69029
|
try {
|
|
68565
69030
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
68566
69031
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
68567
|
-
out = mkdtempSync4(
|
|
69032
|
+
out = mkdtempSync4(join62(tmpdir5(), "himi-ux-record-"));
|
|
68568
69033
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
68569
69034
|
const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
68570
69035
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -68731,7 +69196,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
68731
69196
|
}
|
|
68732
69197
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
68733
69198
|
try {
|
|
68734
|
-
|
|
69199
|
+
readdirSync30(outDir);
|
|
68735
69200
|
} catch {
|
|
68736
69201
|
return { families: void 0, source: "unbuilt" };
|
|
68737
69202
|
}
|
|
@@ -68742,7 +69207,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
68742
69207
|
let js;
|
|
68743
69208
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
68744
69209
|
try {
|
|
68745
|
-
js =
|
|
69210
|
+
js = readFileSync76(join62(outDir, candidate), "utf8");
|
|
68746
69211
|
break;
|
|
68747
69212
|
} catch {
|
|
68748
69213
|
}
|
|
@@ -68773,12 +69238,27 @@ async function producedWidgetFamilies(dir) {
|
|
|
68773
69238
|
}
|
|
68774
69239
|
return { families, source: "dist/bundles" };
|
|
68775
69240
|
}
|
|
68776
|
-
var boardOpen = (dir) =>
|
|
69241
|
+
var boardOpen = (dir) => existsSync64(join62(dir, ".himi", "studio", "index.html"));
|
|
68777
69242
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
68778
69243
|
async function leaveForBoard(dir, record2, value) {
|
|
68779
69244
|
if (!boardOpen(dir)) return;
|
|
68780
|
-
const { writeStudioRecord: writeStudioRecord2, VALIDATE_RECORD: VALIDATE_RECORD2, PUSH_RECORD: PUSH_RECORD2, EDGES_RECORD: EDGES_RECORD2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
68781
|
-
writeStudioRecord2(dir, { validate: VALIDATE_RECORD2, push: PUSH_RECORD2, edges: EDGES_RECORD2 }[record2], value);
|
|
69245
|
+
const { writeStudioRecord: writeStudioRecord2, VALIDATE_RECORD: VALIDATE_RECORD2, PUSH_RECORD: PUSH_RECORD2, EDGES_RECORD: EDGES_RECORD2, MAP_RECORD: MAP_RECORD2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
69246
|
+
writeStudioRecord2(dir, { validate: VALIDATE_RECORD2, push: PUSH_RECORD2, edges: EDGES_RECORD2, map: MAP_RECORD2 }[record2], value);
|
|
69247
|
+
}
|
|
69248
|
+
async function liveMapFor(dir) {
|
|
69249
|
+
if (!boardOpen(dir)) return void 0;
|
|
69250
|
+
const { writeStudioRecord: writeStudioRecord2, refreshStudio: refreshStudio2, MAP_RECORD: MAP_RECORD2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
69251
|
+
let last = 0;
|
|
69252
|
+
return (map) => {
|
|
69253
|
+
const now = Date.now();
|
|
69254
|
+
if (now - last < 1e3) return;
|
|
69255
|
+
last = now;
|
|
69256
|
+
try {
|
|
69257
|
+
writeStudioRecord2(dir, MAP_RECORD2, map);
|
|
69258
|
+
refreshStudio2(dir);
|
|
69259
|
+
} catch {
|
|
69260
|
+
}
|
|
69261
|
+
};
|
|
68782
69262
|
}
|
|
68783
69263
|
async function run(argv, io = defaultIO, deps = {}) {
|
|
68784
69264
|
const code = await runCommand(argv, io, deps);
|
|
@@ -69053,7 +69533,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69053
69533
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
69054
69534
|
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`);
|
|
69055
69535
|
}
|
|
69056
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) =>
|
|
69536
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync64(join62(parentDir, f)));
|
|
69057
69537
|
if (planInParent.length) {
|
|
69058
69538
|
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}`);
|
|
69059
69539
|
}
|
|
@@ -69180,7 +69660,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69180
69660
|
const sourceDir = resolve47(str6(flags["source-dir"]) ?? appDir2);
|
|
69181
69661
|
let meta;
|
|
69182
69662
|
try {
|
|
69183
|
-
meta = JSON.parse(
|
|
69663
|
+
meta = JSON.parse(readFileSync76(join62(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
69184
69664
|
} catch {
|
|
69185
69665
|
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>)` }));
|
|
69186
69666
|
return 2;
|
|
@@ -69190,7 +69670,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69190
69670
|
return 2;
|
|
69191
69671
|
}
|
|
69192
69672
|
try {
|
|
69193
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
69673
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync76(join62(sourceDir, "tokens.json"), "utf8")));
|
|
69194
69674
|
meta = { ...appearance, ...meta };
|
|
69195
69675
|
} catch {
|
|
69196
69676
|
}
|
|
@@ -69212,7 +69692,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69212
69692
|
const force = flags.force === true;
|
|
69213
69693
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
69214
69694
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
69215
|
-
const out = mkdtempSync4(
|
|
69695
|
+
const out = mkdtempSync4(join62(tmpdir5(), "himi-template-"));
|
|
69216
69696
|
publishScratch.push(out);
|
|
69217
69697
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
69218
69698
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
@@ -69266,7 +69746,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69266
69746
|
let iconHash;
|
|
69267
69747
|
if (iconPath) {
|
|
69268
69748
|
try {
|
|
69269
|
-
const bytes2 =
|
|
69749
|
+
const bytes2 = readFileSync76(iconPath);
|
|
69270
69750
|
payload.icon = bytes2.toString("base64");
|
|
69271
69751
|
iconHash = createHash28("sha256").update(bytes2).digest("hex");
|
|
69272
69752
|
} catch {
|
|
@@ -69472,12 +69952,12 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69472
69952
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
69473
69953
|
return 2;
|
|
69474
69954
|
}
|
|
69475
|
-
const { readdirSync:
|
|
69955
|
+
const { readdirSync: readdirSync31, existsSync: fileExists } = await import("node:fs");
|
|
69476
69956
|
const { join: pathJoin } = await import("node:path");
|
|
69477
69957
|
const targets = [];
|
|
69478
69958
|
const t5 = pathJoin(dir, "tier5-src");
|
|
69479
69959
|
if (fileExists(t5)) {
|
|
69480
|
-
for (const d of
|
|
69960
|
+
for (const d of readdirSync31(t5, { withFileTypes: true })) {
|
|
69481
69961
|
if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
|
|
69482
69962
|
}
|
|
69483
69963
|
}
|
|
@@ -69509,7 +69989,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69509
69989
|
const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
|
|
69510
69990
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
69511
69991
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
69512
|
-
const out = mkdtempSync4(
|
|
69992
|
+
const out = mkdtempSync4(join62(tmpdir5(), "himi-validate-"));
|
|
69513
69993
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
69514
69994
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
69515
69995
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -69552,7 +70032,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69552
70032
|
const path2 = dpxSessionTokenPath();
|
|
69553
70033
|
let raw;
|
|
69554
70034
|
try {
|
|
69555
|
-
raw =
|
|
70035
|
+
raw = readFileSync76(path2, "utf8");
|
|
69556
70036
|
} catch {
|
|
69557
70037
|
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`);
|
|
69558
70038
|
}
|
|
@@ -69672,13 +70152,13 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69672
70152
|
case "studio": {
|
|
69673
70153
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
69674
70154
|
const dir = contentDir(flags);
|
|
69675
|
-
if (!
|
|
70155
|
+
if (!existsSync64(join62(dir, "himalaya.content.json"))) {
|
|
69676
70156
|
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/" }));
|
|
69677
70157
|
return 2;
|
|
69678
70158
|
}
|
|
69679
70159
|
if (pos[1] === "reel") {
|
|
69680
70160
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
69681
|
-
const out = resolve47(str6(flags.out) ??
|
|
70161
|
+
const out = resolve47(str6(flags.out) ?? join62(dir, ".himi", "making-of.html"));
|
|
69682
70162
|
const { html, plan } = buildReel2(dir);
|
|
69683
70163
|
mkdirSync31(dirname34(out), { recursive: true });
|
|
69684
70164
|
writeFileSync29(out, html);
|
|
@@ -69745,7 +70225,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69745
70225
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
69746
70226
|
const dir = contentDir(flags);
|
|
69747
70227
|
const journal = journalPath2(dir);
|
|
69748
|
-
const isContentPackage =
|
|
70228
|
+
const isContentPackage = existsSync64(join62(dir, "himalaya.content.json"));
|
|
69749
70229
|
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" };
|
|
69750
70230
|
const message = pos.slice(1).join(" ").trim();
|
|
69751
70231
|
const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
|
|
@@ -69817,8 +70297,8 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69817
70297
|
try {
|
|
69818
70298
|
const entry = appendProgress2(dir, { message, ...step ? { step } : {}, images });
|
|
69819
70299
|
const notified = flags.notify === true ? await notifyDesktop2(`himi \xB7 ${appLabel2(dir) ?? "your app"}`, message) : void 0;
|
|
69820
|
-
const { count } = summarizeProgress2(readProgress2(dir).entries);
|
|
69821
|
-
print({ ok: true, entry, journal, count, ...notified === void 0 ? {} : { notified }, ...hint });
|
|
70300
|
+
const { count: count2 } = summarizeProgress2(readProgress2(dir).entries);
|
|
70301
|
+
print({ ok: true, entry, journal, count: count2, ...notified === void 0 ? {} : { notified }, ...hint });
|
|
69822
70302
|
return 0;
|
|
69823
70303
|
} catch (e) {
|
|
69824
70304
|
if (e instanceof ProgressError2) {
|
|
@@ -69881,7 +70361,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69881
70361
|
case "test": {
|
|
69882
70362
|
const dir = contentDir(flags);
|
|
69883
70363
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
69884
|
-
if (
|
|
70364
|
+
if (existsSync64(join62(dir, "functions"))) {
|
|
69885
70365
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
69886
70366
|
const loaded = await loadFunctionsApp2(dir);
|
|
69887
70367
|
const results = [];
|
|
@@ -69968,7 +70448,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
69968
70448
|
}
|
|
69969
70449
|
}
|
|
69970
70450
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
69971
|
-
const out = mkdtempSync4(
|
|
70451
|
+
const out = mkdtempSync4(join62(tmpdir5(), "himi-test-"));
|
|
69972
70452
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
69973
70453
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
69974
70454
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -70013,7 +70493,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70013
70493
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
70014
70494
|
return 2;
|
|
70015
70495
|
}
|
|
70016
|
-
const sources = collectWorkerSources2(
|
|
70496
|
+
const sources = collectWorkerSources2(join62(dir, "tier5-src"), screen.bundleName);
|
|
70017
70497
|
if (!sources) {
|
|
70018
70498
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
70019
70499
|
return 2;
|
|
@@ -70114,6 +70594,8 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70114
70594
|
const cmsSeed = offline ? null : await cmsSeedRows(dir, app);
|
|
70115
70595
|
const canned = offline ? null : readCannedResponses2();
|
|
70116
70596
|
const tabRoots = await tabRootScreens(dir);
|
|
70597
|
+
const onScreen = await liveMapFor(dir);
|
|
70598
|
+
const mapEntries = await navEntryScreens(dir, outcome.homeScreenId);
|
|
70117
70599
|
let result;
|
|
70118
70600
|
try {
|
|
70119
70601
|
result = await runCrawl2({
|
|
@@ -70130,6 +70612,8 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70130
70612
|
...cmsSeed ? { cmsSeed } : {},
|
|
70131
70613
|
...canned ? { canned } : {},
|
|
70132
70614
|
...tabRoots.size ? { tabRoots } : {},
|
|
70615
|
+
...onScreen ? { onScreen } : {},
|
|
70616
|
+
...mapEntries.size ? { mapEntries } : {},
|
|
70133
70617
|
// The app's exact linkable set, straight off the build outcome (#2512) — arms the
|
|
70134
70618
|
// nav-target check. Omitted when the build reported none, so the crawl stays silent
|
|
70135
70619
|
// rather than judging every target against an empty set.
|
|
@@ -70174,7 +70658,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70174
70658
|
const sp = await runShotsPass2({
|
|
70175
70659
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
70176
70660
|
tokens: outcome.tokens,
|
|
70177
|
-
outDir:
|
|
70661
|
+
outDir: join62(dir, ".himi", "shots"),
|
|
70178
70662
|
width: 390,
|
|
70179
70663
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
70180
70664
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -70212,11 +70696,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70212
70696
|
releaseId: result.releaseId,
|
|
70213
70697
|
releasePayload: release,
|
|
70214
70698
|
descriptors: attestedDescriptors,
|
|
70215
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
70699
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join62(dir, ".himi", "shots", name)])),
|
|
70216
70700
|
coverage: {
|
|
70217
70701
|
screens: crawledScreens.size,
|
|
70218
70702
|
actionsDispatched: result.actions.exercised,
|
|
70219
|
-
uncoveredFns: (result.crawled ?? []).reduce((
|
|
70703
|
+
uncoveredFns: (result.crawled ?? []).reduce((count2, screen) => count2 + (screen.uncoveredFunctions?.length ?? 0), 0),
|
|
70220
70704
|
gaps: ledger.length
|
|
70221
70705
|
},
|
|
70222
70706
|
report: {
|
|
@@ -70233,6 +70717,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70233
70717
|
}));
|
|
70234
70718
|
} else io.log(formatReport2(result) + formatDelta2(delta) + formatLedger2(ledger, trend));
|
|
70235
70719
|
await leaveForBoard(dir, "edges", result.edges ?? []);
|
|
70720
|
+
if (result.navGraph) await leaveForBoard(dir, "map", result.navGraph);
|
|
70236
70721
|
return result.ok ? 0 : 1;
|
|
70237
70722
|
}
|
|
70238
70723
|
case "render": {
|
|
@@ -70302,7 +70787,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70302
70787
|
return 2;
|
|
70303
70788
|
}
|
|
70304
70789
|
try {
|
|
70305
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
70790
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync76(stateArg.replace(/^@/, ""), "utf8");
|
|
70306
70791
|
injectedState = JSON.parse(raw);
|
|
70307
70792
|
} catch (e) {
|
|
70308
70793
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -70317,7 +70802,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70317
70802
|
return 2;
|
|
70318
70803
|
}
|
|
70319
70804
|
try {
|
|
70320
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
70805
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync76(inputArg.replace(/^@/, ""), "utf8");
|
|
70321
70806
|
const parsed = JSON.parse(raw);
|
|
70322
70807
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
70323
70808
|
injectedInput = parsed;
|
|
@@ -70366,7 +70851,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70366
70851
|
}
|
|
70367
70852
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
70368
70853
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
70369
|
-
const out = mkdtempSync4(
|
|
70854
|
+
const out = mkdtempSync4(join62(tmpdir5(), "himi-render-"));
|
|
70370
70855
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
70371
70856
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
70372
70857
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -70380,7 +70865,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
70380
70865
|
const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
|
|
70381
70866
|
let pngFile;
|
|
70382
70867
|
let attestationPngFile;
|
|
70383
|
-
const shotPath =
|
|
70868
|
+
const shotPath = join62(dir, ".himi", "shots", `${screenId}.png`);
|
|
70384
70869
|
const pngTarget = typeof flags.png === "string" ? str6(flags.png) : flags.png === true ? shotPath : void 0;
|
|
70385
70870
|
if (pngTarget && r.pngBase64) {
|
|
70386
70871
|
pngFile = writePngFile(pngTarget, r.pngBase64);
|
|
@@ -70716,7 +71201,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70716
71201
|
io.error(JSON.stringify(linked));
|
|
70717
71202
|
return 1;
|
|
70718
71203
|
}
|
|
70719
|
-
if (
|
|
71204
|
+
if (existsSync64(dest)) {
|
|
70720
71205
|
if (!statSync17(dest).isDirectory()) {
|
|
70721
71206
|
io.error(JSON.stringify({
|
|
70722
71207
|
error: `${dest} exists and is not a directory`,
|
|
@@ -70724,12 +71209,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70724
71209
|
}));
|
|
70725
71210
|
return 1;
|
|
70726
71211
|
}
|
|
70727
|
-
const occupied =
|
|
71212
|
+
const occupied = readdirSync30(dest).length > 0;
|
|
70728
71213
|
if (occupied && !force) {
|
|
70729
71214
|
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" }));
|
|
70730
71215
|
return 1;
|
|
70731
71216
|
}
|
|
70732
|
-
if (replace && occupied && !
|
|
71217
|
+
if (replace && occupied && !existsSync64(join62(dest, "himalaya.content.json"))) {
|
|
70733
71218
|
io.error(JSON.stringify({
|
|
70734
71219
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
70735
71220
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -70870,7 +71355,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70870
71355
|
const force = flags.force === true;
|
|
70871
71356
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
70872
71357
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
70873
|
-
const out = mkdtempSync4(
|
|
71358
|
+
const out = mkdtempSync4(join62(tmpdir5(), "himi-push-"));
|
|
70874
71359
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
70875
71360
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
70876
71361
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -71391,7 +71876,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71391
71876
|
}
|
|
71392
71877
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
71393
71878
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
71394
|
-
const built = mkdtempSync4(
|
|
71879
|
+
const built = mkdtempSync4(join62(tmpdir5(), "himi-pack-"));
|
|
71395
71880
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
71396
71881
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
71397
71882
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -71596,7 +72081,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71596
72081
|
}));
|
|
71597
72082
|
return 1;
|
|
71598
72083
|
}
|
|
71599
|
-
const archive =
|
|
72084
|
+
const archive = readFileSync76(resolve47(file));
|
|
71600
72085
|
const result = await client2().createPackageShare({
|
|
71601
72086
|
app: opened.header.app,
|
|
71602
72087
|
releaseId: opened.header.releaseId,
|
|
@@ -71656,11 +72141,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71656
72141
|
const app = await appId(dir2);
|
|
71657
72142
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
71658
72143
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
71659
|
-
temp = mkdtempSync4(
|
|
72144
|
+
temp = mkdtempSync4(join62(tmpdir5(), "himi-run-build-"));
|
|
71660
72145
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
71661
72146
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
71662
72147
|
servedMissing = initial.missingBundles;
|
|
71663
|
-
source =
|
|
72148
|
+
source = join62(temp, app);
|
|
71664
72149
|
}
|
|
71665
72150
|
const chromeArg = str6(flags.chrome) ?? "preview";
|
|
71666
72151
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -71696,7 +72181,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71696
72181
|
if (!recordKit) return;
|
|
71697
72182
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
71698
72183
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
71699
|
-
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
72184
|
+
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join62(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
|
|
71700
72185
|
await refreshBoard();
|
|
71701
72186
|
};
|
|
71702
72187
|
const retract = async () => {
|
|
@@ -71727,7 +72212,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71727
72212
|
}
|
|
71728
72213
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
71729
72214
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
71730
|
-
if (watch2) served = mkdtempSync4(
|
|
72215
|
+
if (watch2) served = mkdtempSync4(join62(tmpdir5(), "himi-run-served-"));
|
|
71731
72216
|
const running = await runPackage2(source, {
|
|
71732
72217
|
port,
|
|
71733
72218
|
chrome: chromeArg,
|
|
@@ -71749,8 +72234,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71749
72234
|
await announce(running);
|
|
71750
72235
|
if (watchKit && bus) {
|
|
71751
72236
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
71752
|
-
const live2 =
|
|
71753
|
-
const manifestOf = (tree) => JSON.parse(
|
|
72237
|
+
const live2 = join62(running.releaseRoot, running.app);
|
|
72238
|
+
const manifestOf = (tree) => JSON.parse(readFileSync76(join62(tree, "release-manifest.json"), "utf8"));
|
|
71754
72239
|
let current = manifestOf(live2);
|
|
71755
72240
|
const failed2 = async (message) => {
|
|
71756
72241
|
if (stopping) return;
|
|
@@ -71761,7 +72246,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71761
72246
|
};
|
|
71762
72247
|
rebuild = watchKit.serialize(async () => {
|
|
71763
72248
|
const t0 = Date.now();
|
|
71764
|
-
const next = mkdtempSync4(
|
|
72249
|
+
const next = mkdtempSync4(join62(tmpdir5(), "himi-run-build-"));
|
|
71765
72250
|
try {
|
|
71766
72251
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
71767
72252
|
if (bres.compileErrors.length) {
|
|
@@ -71778,22 +72263,24 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
71778
72263
|
return;
|
|
71779
72264
|
}
|
|
71780
72265
|
if (stopping) return;
|
|
71781
|
-
const fresh = manifestOf(
|
|
72266
|
+
const fresh = manifestOf(join62(next, running.app));
|
|
71782
72267
|
const diff = watchKit.diffReleases(current, fresh);
|
|
72268
|
+
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
72269
|
+
const changes = describeChanges2(live2, join62(next, running.app), diff);
|
|
71783
72270
|
const retired = `${live2}.retired-${Date.now()}`;
|
|
71784
72271
|
renameSync7(live2, retired);
|
|
71785
72272
|
try {
|
|
71786
|
-
renameSync7(
|
|
72273
|
+
renameSync7(join62(next, running.app), live2);
|
|
71787
72274
|
} catch {
|
|
71788
|
-
cpSync3(
|
|
72275
|
+
cpSync3(join62(next, running.app), live2, { recursive: true });
|
|
71789
72276
|
}
|
|
71790
72277
|
rmSync14(retired, { recursive: true, force: true });
|
|
71791
72278
|
current = fresh;
|
|
71792
72279
|
servedMissing = outcome.missingBundles;
|
|
71793
72280
|
for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
|
|
71794
|
-
record2(running, { ok: true, at: (/* @__PURE__ */ new Date()).toISOString(), ms: Date.now() - t0, screens: diff.screens, tokens: diff.tokens, config: diff.config });
|
|
72281
|
+
record2(running, { ok: true, at: (/* @__PURE__ */ new Date()).toISOString(), ms: Date.now() - t0, screens: diff.screens, tokens: diff.tokens, config: diff.config, changes });
|
|
71795
72282
|
await refreshBoard();
|
|
71796
|
-
io.error(JSON.stringify({ watch: "rebuilt", ms: Date.now() - t0, screens: diff.screens, tokens: diff.tokens, config: diff.config, tabs: bus.listeners }));
|
|
72283
|
+
io.error(JSON.stringify({ watch: "rebuilt", ms: Date.now() - t0, screens: diff.screens, tokens: diff.tokens, config: diff.config, ...changes.items.length ? { changed: headline2(changes), changes } : {}, tabs: bus.listeners }));
|
|
71797
72284
|
} catch (e) {
|
|
71798
72285
|
await failed2(e.message.split("\n")[0]);
|
|
71799
72286
|
} finally {
|
|
@@ -72395,7 +72882,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
72395
72882
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
72396
72883
|
return 2;
|
|
72397
72884
|
}
|
|
72398
|
-
if (!
|
|
72885
|
+
if (!existsSync64(file)) {
|
|
72399
72886
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
72400
72887
|
return 2;
|
|
72401
72888
|
}
|
|
@@ -72451,7 +72938,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
72451
72938
|
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."
|
|
72452
72939
|
};
|
|
72453
72940
|
if (kind === "tokens" || kind === "app-config") {
|
|
72454
|
-
const body =
|
|
72941
|
+
const body = readFileSync76(file, "utf8");
|
|
72455
72942
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
72456
72943
|
return runReleasePatch({
|
|
72457
72944
|
...common,
|
|
@@ -72466,7 +72953,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
72466
72953
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
72467
72954
|
return 2;
|
|
72468
72955
|
}
|
|
72469
|
-
const descriptor =
|
|
72956
|
+
const descriptor = readFileSync76(file, "utf8");
|
|
72470
72957
|
try {
|
|
72471
72958
|
JSON.parse(descriptor);
|
|
72472
72959
|
} catch (e) {
|
|
@@ -72506,7 +72993,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
72506
72993
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
72507
72994
|
});
|
|
72508
72995
|
}
|
|
72509
|
-
const bytes2 =
|
|
72996
|
+
const bytes2 = readFileSync76(file);
|
|
72510
72997
|
const sha = createHash28("sha256").update(bytes2).digest("hex");
|
|
72511
72998
|
const forScreens = (str6(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
72512
72999
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -72650,7 +73137,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
72650
73137
|
}
|
|
72651
73138
|
let def;
|
|
72652
73139
|
try {
|
|
72653
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
73140
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync76(arg.slice(1), "utf8") : arg);
|
|
72654
73141
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
72655
73142
|
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}`] }));
|
|
72656
73143
|
return 2;
|
|
@@ -73114,7 +73601,7 @@ ${label2}`);
|
|
|
73114
73601
|
const platform = str6(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
73115
73602
|
{
|
|
73116
73603
|
const distDir = contentDir(flags);
|
|
73117
|
-
if (
|
|
73604
|
+
if (existsSync64(join62(distDir, "himalaya.content.json"))) {
|
|
73118
73605
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
73119
73606
|
const errors = issues.filter((i) => i.severity === "error");
|
|
73120
73607
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -73383,7 +73870,7 @@ ${label2}`);
|
|
|
73383
73870
|
const dpxPath = dpxSessionTokenPath();
|
|
73384
73871
|
let dpx;
|
|
73385
73872
|
try {
|
|
73386
|
-
dpx =
|
|
73873
|
+
dpx = readFileSync76(dpxPath, "utf8").trim();
|
|
73387
73874
|
} catch {
|
|
73388
73875
|
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` }));
|
|
73389
73876
|
return 1;
|
|
@@ -73791,7 +74278,7 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
|
|
|
73791
74278
|
const path2 = dpxSessionTokenPath();
|
|
73792
74279
|
let raw;
|
|
73793
74280
|
try {
|
|
73794
|
-
raw =
|
|
74281
|
+
raw = readFileSync76(path2, "utf8");
|
|
73795
74282
|
} catch {
|
|
73796
74283
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
73797
74284
|
return 1;
|