@wix/himalaya-cli 0.855.0 → 0.857.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 +1077 -745
- package/guides/himi-test.md +1 -1
- package/guides/mobile-ux.md +65 -13
- package/guides/tier-5-add-a-screen.md +4 -0
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -832,19 +832,120 @@ var init_source_deny = __esm({
|
|
|
832
832
|
});
|
|
833
833
|
|
|
834
834
|
// src/mobile-ux-contract.ts
|
|
835
|
-
function
|
|
835
|
+
function mobileUxDocumentBody(mobile) {
|
|
836
|
+
const comments = /<!--[\s\S]*?(?:-->|$)/g;
|
|
837
|
+
let out = "";
|
|
838
|
+
let last = 0;
|
|
839
|
+
let blankBefore = true;
|
|
840
|
+
for (const match of mobile.matchAll(comments)) {
|
|
841
|
+
const offset = match.index ?? 0;
|
|
842
|
+
const between = mobile.slice(last, offset);
|
|
843
|
+
const newline = between.lastIndexOf("\n");
|
|
844
|
+
if (newline >= 0) blankBefore = between.slice(newline + 1).trim() === "";
|
|
845
|
+
else blankBefore = blankBefore && between.trim() === "";
|
|
846
|
+
out += between;
|
|
847
|
+
const ownsTheLine = offset === 0 || mobile[offset - 1] === "\n";
|
|
848
|
+
const precedesHeading = blankBefore && mobile.startsWith("#", offset + match[0].length);
|
|
849
|
+
out += ownsTheLine || precedesHeading ? "\n" : " ";
|
|
850
|
+
last = offset + match[0].length;
|
|
851
|
+
}
|
|
852
|
+
return out + mobile.slice(last);
|
|
853
|
+
}
|
|
854
|
+
function mobileUxSection(text2, heading) {
|
|
855
|
+
const match = new RegExp(`(?:^|\\n)##[ \\t]+${heading}\\b[^\\n]*([\\s\\S]*?)(?=\\n##[ \\t]|$)`, "i").exec(text2);
|
|
856
|
+
return match ? match[1] : null;
|
|
857
|
+
}
|
|
858
|
+
function sectionTables(markdown) {
|
|
859
|
+
const lines = markdown.split("\n").map((line) => line.trim());
|
|
860
|
+
const tables = [];
|
|
861
|
+
for (let i = 1; i < lines.length; i++) {
|
|
862
|
+
if (!DELIMITER_ROW.test(lines[i])) continue;
|
|
863
|
+
const header = lines[i - 1];
|
|
864
|
+
if (!header.includes("|")) continue;
|
|
865
|
+
const table = { header: splitCells(header), data: [] };
|
|
866
|
+
let j = i + 1;
|
|
867
|
+
for (; j < lines.length; j++) {
|
|
868
|
+
const line = lines[j];
|
|
869
|
+
if (!line.includes("|")) break;
|
|
870
|
+
if (DELIMITER_ROW.test(line)) continue;
|
|
871
|
+
const cells = splitCells(line);
|
|
872
|
+
if (cells.every((cell) => cell === "")) continue;
|
|
873
|
+
table.data.push(cells);
|
|
874
|
+
}
|
|
875
|
+
tables.push(table);
|
|
876
|
+
i = j;
|
|
877
|
+
}
|
|
878
|
+
return tables;
|
|
879
|
+
}
|
|
880
|
+
function namesOneCta(cell) {
|
|
881
|
+
if (!cell) return false;
|
|
882
|
+
return !/[,;]|\s\/\s/.test(cell);
|
|
883
|
+
}
|
|
884
|
+
function declaredStates(text2) {
|
|
885
|
+
const contract = section(text2, "Screen contract");
|
|
886
|
+
if (!contract) return [];
|
|
887
|
+
const states = [];
|
|
888
|
+
for (const bullet of contract.matchAll(/^[ \t]*[-*][ \t]*[^:\n]*\bstates?[ \t]*:[ \t]*(\S.*)$/gim)) {
|
|
889
|
+
const items = bullet[1].split(/[,;/]/).map((item) => item.trim().replace(/[.:]+$/, "")).filter(Boolean);
|
|
890
|
+
if (!items.length || items.some((item) => !/^[\w][\w.\-+]*$/.test(item))) continue;
|
|
891
|
+
states.push(...items);
|
|
892
|
+
}
|
|
893
|
+
return [...new Set(states.map((state) => state.toLowerCase()))];
|
|
894
|
+
}
|
|
895
|
+
function primaryCtaStructureGap(text2) {
|
|
896
|
+
const acceptance = section(text2, "Implementation acceptance");
|
|
897
|
+
if (acceptance === null) return "There is no `## Implementation acceptance` section to read it from.";
|
|
898
|
+
const tables = sectionTables(acceptance).filter((table) => table.data.length > 0);
|
|
899
|
+
if (!tables.length) return "Its acceptance table has no rows.";
|
|
900
|
+
const ctaTables = tables.map((table) => ({ table, cta: table.header.findIndex((cell) => /primary\s*(?:cta|call[- ]?to[- ]?action|action)/i.test(cell)) })).filter((entry) => entry.cta >= 0);
|
|
901
|
+
if (!ctaTables.length) return "Its acceptance table has no `Primary CTA` column.";
|
|
902
|
+
const unanswered = ctaTables.flatMap(({ table, cta }) => table.data.filter((row) => !namesOneCta(row[cta] ?? "")));
|
|
903
|
+
if (unanswered.length) {
|
|
904
|
+
return `${unanswered.length} acceptance row(s) do not name exactly one primary CTA (first: ${JSON.stringify(unanswered[0][0] ?? "")}).`;
|
|
905
|
+
}
|
|
906
|
+
const data = ctaTables.flatMap(({ table }) => table.data);
|
|
907
|
+
const flat = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
908
|
+
const rowText = data.map((row) => flat(row.join(" ")));
|
|
909
|
+
const missing = declaredStates(text2).filter((state) => !rowText.some((row) => row.includes(flat(state))));
|
|
910
|
+
if (missing.length) return `The acceptance table has no row for the declared state(s): ${missing.join(", ")}.`;
|
|
911
|
+
return null;
|
|
912
|
+
}
|
|
913
|
+
function hasUnterminatedComment(mobile) {
|
|
914
|
+
let i = 0;
|
|
915
|
+
for (; ; ) {
|
|
916
|
+
const open = mobile.indexOf("<!--", i);
|
|
917
|
+
if (open < 0) return false;
|
|
918
|
+
const close = mobile.indexOf("-->", open + 4);
|
|
919
|
+
if (close < 0) return true;
|
|
920
|
+
i = close + 3;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
function mobileUxMarkerFindings(mobile, renderedWidths = []) {
|
|
924
|
+
const text2 = mobileUxDocumentBody(mobile);
|
|
836
925
|
const findings = [];
|
|
837
|
-
if (!/^## Implementation acceptance\b/im.test(
|
|
838
|
-
findings.push({ code: "missing-acceptance-matrix", message: "MOBILE-UX.md must contain the
|
|
926
|
+
if (!/^## Implementation acceptance\b/im.test(text2)) {
|
|
927
|
+
findings.push({ code: "missing-acceptance-matrix", message: "MOBILE-UX.md must contain the heading `## Implementation acceptance` at the start of a line. Case is not checked, but use this spelling: other tooling addresses the document by it." });
|
|
839
928
|
}
|
|
840
|
-
if (!/^## Evidence\b/im.test(
|
|
841
|
-
findings.push({ code: "missing-evidence-section", message: "MOBILE-UX.md must contain the
|
|
929
|
+
if (!/^## Evidence\b/im.test(text2)) {
|
|
930
|
+
findings.push({ code: "missing-evidence-section", message: "MOBILE-UX.md must contain the heading `## Evidence` at the start of a line. Case is not checked, but use this spelling: other tooling addresses the document by it." });
|
|
842
931
|
}
|
|
843
|
-
if (!/one primary CTA per state/i.test(
|
|
844
|
-
|
|
932
|
+
if (!/one primary CTA per state/i.test(text2)) {
|
|
933
|
+
const gap = primaryCtaStructureGap(text2);
|
|
934
|
+
if (gap) {
|
|
935
|
+
findings.push({
|
|
936
|
+
code: "missing-primary-cta-rule",
|
|
937
|
+
message: "MOBILE-UX.md must establish one primary CTA per state: give `## Implementation acceptance` a `Primary CTA` column with a row per declared state and exactly one CTA in each cell, or keep the phrase `one primary CTA per state`. " + gap
|
|
938
|
+
});
|
|
939
|
+
}
|
|
845
940
|
}
|
|
846
|
-
if (!hasWidthEvidence(
|
|
847
|
-
findings.push({ code: "missing-width-evidence", message: widthEvidenceMessage(
|
|
941
|
+
if (!hasWidthEvidence(text2, renderedWidths)) {
|
|
942
|
+
findings.push({ code: "missing-width-evidence", message: widthEvidenceMessage(text2, renderedWidths) });
|
|
943
|
+
}
|
|
944
|
+
if (findings.length && hasUnterminatedComment(mobile)) {
|
|
945
|
+
return [{
|
|
946
|
+
code: "unterminated-html-comment",
|
|
947
|
+
message: "MOBILE-UX.md has an HTML comment opened with `<!--` and never closed with `-->`, so everything after it is commented out \u2014 in this check and in any renderer. Close the comment and re-run: the headings and phrases below it are not being read."
|
|
948
|
+
}];
|
|
848
949
|
}
|
|
849
950
|
return findings;
|
|
850
951
|
}
|
|
@@ -886,13 +987,33 @@ function closestWidthPair(mentions) {
|
|
|
886
987
|
}
|
|
887
988
|
return best;
|
|
888
989
|
}
|
|
889
|
-
function
|
|
990
|
+
function recordedWidthSpan(widths) {
|
|
991
|
+
const compact = widths.find((width) => inRange(width) && width <= COMPACT_MAX);
|
|
992
|
+
const wider = widths.find((width) => inRange(width) && width >= WIDER_MIN);
|
|
993
|
+
return compact !== void 0 && wider !== void 0 ? { compact, wider } : null;
|
|
994
|
+
}
|
|
995
|
+
function hasWidthEvidence(mobile, renderedWidths) {
|
|
996
|
+
if (recordedWidthSpan(renderedWidths)) return true;
|
|
890
997
|
if (WIDTH_LITERAL.test(mobile)) return true;
|
|
891
998
|
const pair = closestWidthPair(widthMentions(mobile));
|
|
892
999
|
return pair !== null && pair.gap <= WIDTH_WINDOW;
|
|
893
1000
|
}
|
|
894
|
-
function
|
|
895
|
-
|
|
1001
|
+
function recordedRenderNote(renderedWidths) {
|
|
1002
|
+
if (renderedWidths.length === 0) return "";
|
|
1003
|
+
const list = (values) => {
|
|
1004
|
+
const unique = [...new Set(values)].sort((a, b) => a - b);
|
|
1005
|
+
const shown2 = unique.slice(0, 6).map((width) => `${width}px`).join(", ");
|
|
1006
|
+
return unique.length > 6 ? `${shown2}, \u2026` : shown2;
|
|
1007
|
+
};
|
|
1008
|
+
const plausible = renderedWidths.filter(inRange);
|
|
1009
|
+
const held = `The render record in \`${UX_EVIDENCE_PATH}\` holds`;
|
|
1010
|
+
if (plausible.length === 0) {
|
|
1011
|
+
return ` ${held} ${list(renderedWidths)}, and none of those is a plausible viewport (${PLAUSIBLE_WIDTH.min}-${PLAUSIBLE_WIDTH.max}px), so the record proves nothing about a size class.`;
|
|
1012
|
+
}
|
|
1013
|
+
return ` ${held} ${list(plausible)} \u2014 ` + (plausible.some((width) => width <= COMPACT_MAX) ? `compact only. Render the same screen again at ${WIDER_MIN}px or wider \u2014 \`himi render <screenId> --device ipad\`.` : `wider than compact only. Render the same screen again at ${COMPACT_MAX}px or less \u2014 \`himi render <screenId> --device iphone\`.`);
|
|
1014
|
+
}
|
|
1015
|
+
function widthEvidenceMessage(mobile, renderedWidths) {
|
|
1016
|
+
const base = `MOBILE-UX.md has no width evidence. The shortest way to supply it is to RENDER: \`himi render <screenId> --content <dir> --device iphone\` and again \`--device ipad\` (or any two \`--width\`s spanning the bands below) write the widths they rendered into \`${UX_EVIDENCE_PATH}\`, and a recorded compact render plus a wider one satisfy this marker with no prose at all. Otherwise write the widths you actually rendered into this document \u2014 one at most ${COMPACT_MAX}px (compact) and one at least ${WIDER_MIN}px (medium or expanded), within ~${WIDTH_WINDOW} characters of each other so they read as one statement. A number counts only where it is spelled as a width on itself: a unit (\`320px\`, \`320 pt\`, \`320 dp\`, \`320 pixels\`, \`320 wide\`) or a screenshot filename (\`home-320.png\`). For example: \`Rendered 320px and 834px (home-320.png, home-834.png)\`. The scaffold's \`compact (320/360) \u2026 expanded\` sentence is still accepted as-is.` + recordedRenderNote(renderedWidths);
|
|
896
1017
|
if (/compact \(320\/360\)/i.test(mobile)) {
|
|
897
1018
|
return base + " `compact (320/360)` is present, but no `expanded` follows it within ~400 characters \u2014 keep them in the same sentence.";
|
|
898
1019
|
}
|
|
@@ -911,9 +1032,10 @@ function widthEvidenceMessage(mobile) {
|
|
|
911
1032
|
}
|
|
912
1033
|
return base;
|
|
913
1034
|
}
|
|
914
|
-
var SPEC_TEMPLATE, MOBILE_UX_TEMPLATE, WIDTH_LITERAL, COMPACT_MAX, WIDER_MIN, PLAUSIBLE_WIDTH, YEAR, inRange, looksLikeYear, UNIT_ATTACHED, UNIT_WORD_ATTACHED, WIDTH_WINDOW, EDGE_WINDOW, FILENAME_AFTER, ANTI_CUE_BEFORE, PAIR_HEIGHT_BEFORE, ANTI_CUE_AFTER, isCompact, isWider;
|
|
1035
|
+
var UX_EVIDENCE_PATH, SPEC_TEMPLATE, MOBILE_UX_MARKER_NOTE, MOBILE_UX_TEMPLATE, section, DELIMITER_ROW, splitCells, WIDTH_LITERAL, COMPACT_MAX, WIDER_MIN, PLAUSIBLE_WIDTH, YEAR, inRange, looksLikeYear, UNIT_ATTACHED, UNIT_WORD_ATTACHED, WIDTH_WINDOW, EDGE_WINDOW, FILENAME_AFTER, ANTI_CUE_BEFORE, PAIR_HEIGHT_BEFORE, ANTI_CUE_AFTER, isCompact, isWider;
|
|
915
1036
|
var init_mobile_ux_contract = __esm({
|
|
916
1037
|
"src/mobile-ux-contract.ts"() {
|
|
1038
|
+
UX_EVIDENCE_PATH = ".himi/ux-audit.json";
|
|
917
1039
|
SPEC_TEMPLATE = `# App specification
|
|
918
1040
|
|
|
919
1041
|
## User and outcome
|
|
@@ -938,8 +1060,37 @@ var init_mobile_ux_contract = __esm({
|
|
|
938
1060
|
- Required: iOS, Android
|
|
939
1061
|
- Optional: web, desktop, watch, widgets
|
|
940
1062
|
`;
|
|
1063
|
+
MOBILE_UX_MARKER_NOTE = `<!-- LOAD-BEARING \u2014 read this before you rewrite the file.
|
|
1064
|
+
|
|
1065
|
+
\`himi validate\` warns, and \`himi validate --strict\` / \`himi ux audit --strict\` REFUSE, a
|
|
1066
|
+
MOBILE-UX.md that satisfies none of the forms below. Everything else here is yours to
|
|
1067
|
+
replace freely. This comment is not itself an answer: HTML comments are stripped before the
|
|
1068
|
+
check runs, so keeping it satisfies nothing.
|
|
1069
|
+
|
|
1070
|
+
1. The headings \`## Implementation acceptance\` and \`## Evidence\`, each at the start of
|
|
1071
|
+
a line. Case is not checked; use these spellings anyway, because other tooling
|
|
1072
|
+
addresses this document by them.
|
|
1073
|
+
2. One primary CTA per state \u2014 EITHER the phrase \`one primary CTA per state\`, OR a
|
|
1074
|
+
\`Primary CTA\` column in the acceptance table below, with a row for every state you
|
|
1075
|
+
declare under \`## Screen contract\` and exactly one CTA named in each row's cell.
|
|
1076
|
+
3. Width evidence \u2014 EITHER a RECORDED RENDER, which is the shortest way and needs no prose
|
|
1077
|
+
at all: \`himi render <screenId> --device iphone\` and again \`--device ipad\` each append
|
|
1078
|
+
the width they rendered to \`.himi/ux-audit.json\`, and one below 600px plus one at 600px
|
|
1079
|
+
or wider satisfies this on their own. OR the scaffold's own sentence,
|
|
1080
|
+
\`compact (320/360)\` followed by
|
|
1081
|
+
\`expanded\`, OR two widths you actually rendered, EACH SPELLED AS A WIDTH ON ITSELF:
|
|
1082
|
+
one below 600px and one at 600px or wider, within about 400 characters of each other.
|
|
1083
|
+
A number is spelled as a width when it carries a unit (\`320px\`, \`834 pt\`,
|
|
1084
|
+
\`320 pixels\`, \`320 wide\`) or sits in a screenshot filename (\`home-320.png\`,
|
|
1085
|
+
\`home-390x844.png\`). Nothing is read from the words around the number, so a BARE
|
|
1086
|
+
figure never counts however you label it \u2014 \`Widths: 320, 390, 834\` and
|
|
1087
|
+
\`compact (320) and expanded (834)\` both name no width. One unit per number fixes it.
|
|
1088
|
+
|
|
1089
|
+
Full contract: \`himi docs mobile-ux\` -> "Strict audit contract". -->`;
|
|
941
1090
|
MOBILE_UX_TEMPLATE = `# Mobile UX
|
|
942
1091
|
|
|
1092
|
+
${MOBILE_UX_MARKER_NOTE}
|
|
1093
|
+
|
|
943
1094
|
## Flows
|
|
944
1095
|
### <Task>
|
|
945
1096
|
1. Entry:
|
|
@@ -982,6 +1133,9 @@ in preview fixtures or labelled, capability-limited fallback states\u2014not ord
|
|
|
982
1133
|
> Keep this document safe to publish with a release: do not include credentials, personal data,
|
|
983
1134
|
> internal URLs, private research, or unreviewed notes. Read \`himi docs mobile-ux\` before filling it in.
|
|
984
1135
|
`;
|
|
1136
|
+
section = mobileUxSection;
|
|
1137
|
+
DELIMITER_ROW = /^\|?\s*:?-+:?\s*(?:\|\s*:?-+:?\s*)+\|?$/;
|
|
1138
|
+
splitCells = (line) => line.replace(/^\|/, "").replace(/\|\s*$/, "").split("|").map((cell) => cell.trim());
|
|
985
1139
|
WIDTH_LITERAL = /compact \(320\/360\)[\s\S]{0,400}?expanded/i;
|
|
986
1140
|
COMPACT_MAX = 599;
|
|
987
1141
|
WIDER_MIN = 600;
|
|
@@ -2083,7 +2237,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
2083
2237
|
tokenCache.set(cacheKey, fromEnv);
|
|
2084
2238
|
return fromEnv;
|
|
2085
2239
|
}
|
|
2086
|
-
const token = await new Promise((
|
|
2240
|
+
const token = await new Promise((resolve42, reject) => {
|
|
2087
2241
|
let child;
|
|
2088
2242
|
try {
|
|
2089
2243
|
child = spawnImpl("wix", [...args]);
|
|
@@ -2112,12 +2266,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
2112
2266
|
child.stdout?.on("data", (d) => {
|
|
2113
2267
|
out += String(d);
|
|
2114
2268
|
const m = out.match(TOKEN_RE);
|
|
2115
|
-
if (m) done(() =>
|
|
2269
|
+
if (m) done(() => resolve42(m[0]));
|
|
2116
2270
|
});
|
|
2117
2271
|
child.stderr?.on("data", (d) => {
|
|
2118
2272
|
out += String(d);
|
|
2119
2273
|
const m = out.match(TOKEN_RE);
|
|
2120
|
-
if (m) done(() =>
|
|
2274
|
+
if (m) done(() => resolve42(m[0]));
|
|
2121
2275
|
});
|
|
2122
2276
|
child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
|
|
2123
2277
|
child.on("exit", (code) => done(() => reject(new Error(
|
|
@@ -2298,8 +2452,8 @@ function committedProvisioningPath(name) {
|
|
|
2298
2452
|
function committedShellFor(path) {
|
|
2299
2453
|
const normalized = path.replace(/\\/g, "/");
|
|
2300
2454
|
return SHELL_NAMES2.find((name) => {
|
|
2301
|
-
const
|
|
2302
|
-
return normalized ===
|
|
2455
|
+
const relative8 = committedProvisioningPath(name);
|
|
2456
|
+
return normalized === relative8 || normalized.endsWith(`/${relative8}`);
|
|
2303
2457
|
});
|
|
2304
2458
|
}
|
|
2305
2459
|
function isBrandable(repoRoot2, name) {
|
|
@@ -4729,7 +4883,6 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
4729
4883
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
4730
4884
|
var init_bindings = __esm({
|
|
4731
4885
|
"../../core/ts/src/bindings.ts"() {
|
|
4732
|
-
"use strict";
|
|
4733
4886
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
4734
4887
|
BINDING_SIGIL_RE = new RegExp(
|
|
4735
4888
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -6606,7 +6759,7 @@ function validateWorkerAction(action, context) {
|
|
|
6606
6759
|
}
|
|
6607
6760
|
}
|
|
6608
6761
|
if (context.actionCatalogWithheld) {
|
|
6609
|
-
return actionIssue(action, "warning", `worker actionId "${action.actionId}" was not cross-checked: this surface has precomputed service state but no precomputed action catalog`);
|
|
6762
|
+
return actionIssue(action, "warning", `worker actionId "${action.actionId}" was not cross-checked: this surface has precomputed service state but no precomputed action catalog. This is a property of the surface doing the checking, not of your app \u2014 there is nothing to fix in the content package; re-run the check where the bundle can be inspected (\`himi validate\` / \`himi test\` locally) to have it cross-checked`);
|
|
6610
6763
|
}
|
|
6611
6764
|
const reason = context.bundleInspectionError ? `the bound bundle could not be inspected: ${context.bundleInspectionError}` : "no inspectable logic bundle is bound";
|
|
6612
6765
|
return actionIssue(action, "error", `worker actionId "${action.actionId}" cannot resolve because ${reason}`);
|
|
@@ -9003,8 +9156,8 @@ Lifetime used`) : new QuickJSUseAfterFree("Lifetime not alive");
|
|
|
9003
9156
|
this.dispose = () => {
|
|
9004
9157
|
this.handle.alive && this.handle.dispose(), this.disposeResolvers();
|
|
9005
9158
|
};
|
|
9006
|
-
this.context = args.context, this.owner = args.context.runtime, this.handle = args.promiseHandle, this.settled = new Promise((
|
|
9007
|
-
this.onSettled =
|
|
9159
|
+
this.context = args.context, this.owner = args.context.runtime, this.handle = args.promiseHandle, this.settled = new Promise((resolve42) => {
|
|
9160
|
+
this.onSettled = resolve42;
|
|
9008
9161
|
}), this.resolveHandle = args.resolveHandle, this.rejectHandle = args.rejectHandle;
|
|
9009
9162
|
}
|
|
9010
9163
|
get alive() {
|
|
@@ -9368,12 +9521,12 @@ Lifetime used`) : new QuickJSUseAfterFree("Lifetime not alive");
|
|
|
9368
9521
|
let vmPromise = scope.manage(this.getProp(this.global, "Promise")), vmPromiseResolve = scope.manage(this.getProp(vmPromise, "resolve"));
|
|
9369
9522
|
return this.callFunction(vmPromiseResolve, vmPromise, promiseLikeHandle);
|
|
9370
9523
|
});
|
|
9371
|
-
return vmResolveResult.error ? Promise.resolve(vmResolveResult) : new Promise((
|
|
9524
|
+
return vmResolveResult.error ? Promise.resolve(vmResolveResult) : new Promise((resolve42) => {
|
|
9372
9525
|
Scope.withScope((scope) => {
|
|
9373
9526
|
let resolveHandle = scope.manage(this.newFunction("resolve", (value) => {
|
|
9374
|
-
|
|
9527
|
+
resolve42(this.success(value && value.dup()));
|
|
9375
9528
|
})), rejectHandle = scope.manage(this.newFunction("reject", (error) => {
|
|
9376
|
-
|
|
9529
|
+
resolve42(this.fail(error && error.dup()));
|
|
9377
9530
|
})), promiseHandle = scope.manage(vmResolveResult.value), promiseThenHandle = scope.manage(this.getProp(promiseHandle, "then"));
|
|
9378
9531
|
this.callFunction(promiseThenHandle, promiseHandle, resolveHandle, rejectHandle).unwrap().dispose();
|
|
9379
9532
|
});
|
|
@@ -10219,13 +10372,13 @@ async function QuickJSRaw(moduleArg = {}) {
|
|
|
10219
10372
|
}
|
|
10220
10373
|
readAsync = async (url) => {
|
|
10221
10374
|
if (isFileURI(url)) {
|
|
10222
|
-
return new Promise((
|
|
10375
|
+
return new Promise((resolve42, reject) => {
|
|
10223
10376
|
var xhr = new XMLHttpRequest();
|
|
10224
10377
|
xhr.open("GET", url, true);
|
|
10225
10378
|
xhr.responseType = "arraybuffer";
|
|
10226
10379
|
xhr.onload = () => {
|
|
10227
10380
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
10228
|
-
|
|
10381
|
+
resolve42(xhr.response);
|
|
10229
10382
|
return;
|
|
10230
10383
|
}
|
|
10231
10384
|
reject(xhr.status);
|
|
@@ -10513,10 +10666,10 @@ async function QuickJSRaw(moduleArg = {}) {
|
|
|
10513
10666
|
}
|
|
10514
10667
|
var info = getWasmImports();
|
|
10515
10668
|
if (Module["instantiateWasm"]) {
|
|
10516
|
-
return new Promise((
|
|
10669
|
+
return new Promise((resolve42, reject) => {
|
|
10517
10670
|
try {
|
|
10518
10671
|
Module["instantiateWasm"](info, (inst, mod) => {
|
|
10519
|
-
|
|
10672
|
+
resolve42(receiveInstance(inst, mod));
|
|
10520
10673
|
});
|
|
10521
10674
|
} catch (e) {
|
|
10522
10675
|
err(`Module.instantiateWasm callback failed with error: ${e}`);
|
|
@@ -10689,15 +10842,15 @@ async function QuickJSRaw(moduleArg = {}) {
|
|
|
10689
10842
|
return parts;
|
|
10690
10843
|
},
|
|
10691
10844
|
normalize: (path) => {
|
|
10692
|
-
var
|
|
10693
|
-
path = PATH.normalizeArray(path.split("/").filter((p) => !!p), !
|
|
10694
|
-
if (!path && !
|
|
10845
|
+
var isAbsolute5 = PATH.isAbs(path), trailingSlash = path.slice(-1) === "/";
|
|
10846
|
+
path = PATH.normalizeArray(path.split("/").filter((p) => !!p), !isAbsolute5).join("/");
|
|
10847
|
+
if (!path && !isAbsolute5) {
|
|
10695
10848
|
path = ".";
|
|
10696
10849
|
}
|
|
10697
10850
|
if (path && trailingSlash) {
|
|
10698
10851
|
path += "/";
|
|
10699
10852
|
}
|
|
10700
|
-
return (
|
|
10853
|
+
return (isAbsolute5 ? "/" : "") + path;
|
|
10701
10854
|
},
|
|
10702
10855
|
dirname: (path) => {
|
|
10703
10856
|
var result = PATH.splitPath(path), root = result[0], dir = result[1];
|
|
@@ -12163,12 +12316,12 @@ async function QuickJSRaw(moduleArg = {}) {
|
|
|
12163
12316
|
throw new FS.ErrnoError(75);
|
|
12164
12317
|
}
|
|
12165
12318
|
var old_node = FS.lookupNode(old_dir, old_name);
|
|
12166
|
-
var
|
|
12167
|
-
if (
|
|
12319
|
+
var relative8 = PATH_FS.relative(old_path, new_dirname);
|
|
12320
|
+
if (relative8.charAt(0) !== ".") {
|
|
12168
12321
|
throw new FS.ErrnoError(28);
|
|
12169
12322
|
}
|
|
12170
|
-
|
|
12171
|
-
if (
|
|
12323
|
+
relative8 = PATH_FS.relative(new_path, old_dirname);
|
|
12324
|
+
if (relative8.charAt(0) !== ".") {
|
|
12172
12325
|
throw new FS.ErrnoError(55);
|
|
12173
12326
|
}
|
|
12174
12327
|
var new_node;
|
|
@@ -14577,8 +14730,8 @@ async function QuickJSRaw(moduleArg = {}) {
|
|
|
14577
14730
|
if (runtimeInitialized) {
|
|
14578
14731
|
moduleRtn = Module;
|
|
14579
14732
|
} else {
|
|
14580
|
-
moduleRtn = new Promise((
|
|
14581
|
-
readyPromiseResolve =
|
|
14733
|
+
moduleRtn = new Promise((resolve42, reject) => {
|
|
14734
|
+
readyPromiseResolve = resolve42;
|
|
14582
14735
|
readyPromiseReject = reject;
|
|
14583
14736
|
});
|
|
14584
14737
|
}
|
|
@@ -15442,13 +15595,13 @@ async function QuickJSRaw3(moduleArg = {}) {
|
|
|
15442
15595
|
}
|
|
15443
15596
|
readAsync = async (url) => {
|
|
15444
15597
|
if (isFileURI(url)) {
|
|
15445
|
-
return new Promise((
|
|
15598
|
+
return new Promise((resolve42, reject) => {
|
|
15446
15599
|
var xhr = new XMLHttpRequest();
|
|
15447
15600
|
xhr.open("GET", url, true);
|
|
15448
15601
|
xhr.responseType = "arraybuffer";
|
|
15449
15602
|
xhr.onload = () => {
|
|
15450
15603
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
15451
|
-
|
|
15604
|
+
resolve42(xhr.response);
|
|
15452
15605
|
return;
|
|
15453
15606
|
}
|
|
15454
15607
|
reject(xhr.status);
|
|
@@ -15715,10 +15868,10 @@ async function QuickJSRaw3(moduleArg = {}) {
|
|
|
15715
15868
|
}
|
|
15716
15869
|
var info = getWasmImports();
|
|
15717
15870
|
if (Module["instantiateWasm"]) {
|
|
15718
|
-
return new Promise((
|
|
15871
|
+
return new Promise((resolve42, reject) => {
|
|
15719
15872
|
try {
|
|
15720
15873
|
Module["instantiateWasm"](info, (inst, mod) => {
|
|
15721
|
-
|
|
15874
|
+
resolve42(receiveInstance(inst, mod));
|
|
15722
15875
|
});
|
|
15723
15876
|
} catch (e) {
|
|
15724
15877
|
err(`Module.instantiateWasm callback failed with error: ${e}`);
|
|
@@ -16146,8 +16299,8 @@ async function QuickJSRaw3(moduleArg = {}) {
|
|
|
16146
16299
|
}, whenDone() {
|
|
16147
16300
|
assert(Asyncify.currData, "Tried to wait for an async operation when none is in progress.");
|
|
16148
16301
|
assert(!Asyncify.asyncPromiseHandlers, "Cannot have multiple async operations in flight at once");
|
|
16149
|
-
return new Promise((
|
|
16150
|
-
Asyncify.asyncPromiseHandlers = { resolve:
|
|
16302
|
+
return new Promise((resolve42, reject) => {
|
|
16303
|
+
Asyncify.asyncPromiseHandlers = { resolve: resolve42, reject };
|
|
16151
16304
|
});
|
|
16152
16305
|
}, allocateData() {
|
|
16153
16306
|
var ptr = _malloc(12 + Asyncify.StackSize);
|
|
@@ -16775,8 +16928,8 @@ async function QuickJSRaw3(moduleArg = {}) {
|
|
|
16775
16928
|
if (runtimeInitialized) {
|
|
16776
16929
|
moduleRtn = Module;
|
|
16777
16930
|
} else {
|
|
16778
|
-
moduleRtn = new Promise((
|
|
16779
|
-
readyPromiseResolve =
|
|
16931
|
+
moduleRtn = new Promise((resolve42, reject) => {
|
|
16932
|
+
readyPromiseResolve = resolve42;
|
|
16780
16933
|
readyPromiseReject = reject;
|
|
16781
16934
|
});
|
|
16782
16935
|
}
|
|
@@ -20469,6 +20622,101 @@ var init_wix_gateway_rules = __esm({
|
|
|
20469
20622
|
}
|
|
20470
20623
|
});
|
|
20471
20624
|
|
|
20625
|
+
// src/ux-evidence.ts
|
|
20626
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync23, writeFileSync as writeFileSync9 } from "node:fs";
|
|
20627
|
+
import { dirname as dirname15, isAbsolute as isAbsolute2, join as join25, relative as relative3, resolve as resolve15 } from "node:path";
|
|
20628
|
+
function readText(path) {
|
|
20629
|
+
try {
|
|
20630
|
+
return existsSync21(path) ? readFileSync23(path, "utf8") : null;
|
|
20631
|
+
} catch {
|
|
20632
|
+
return null;
|
|
20633
|
+
}
|
|
20634
|
+
}
|
|
20635
|
+
function parseEvidence(path) {
|
|
20636
|
+
const raw = readText(path);
|
|
20637
|
+
if (raw === null) return { evidence: null };
|
|
20638
|
+
try {
|
|
20639
|
+
const value = JSON.parse(raw);
|
|
20640
|
+
if (value.version !== 1 || !value.platforms || typeof value.platforms !== "object") {
|
|
20641
|
+
return { evidence: null, error: "must be an object with version: 1 and a platforms object" };
|
|
20642
|
+
}
|
|
20643
|
+
return { evidence: value };
|
|
20644
|
+
} catch (error) {
|
|
20645
|
+
return { evidence: null, error: `is not valid JSON: ${error.message}` };
|
|
20646
|
+
}
|
|
20647
|
+
}
|
|
20648
|
+
function uxEvidencePath(content) {
|
|
20649
|
+
return join25(resolve15(content), UX_EVIDENCE_PATH);
|
|
20650
|
+
}
|
|
20651
|
+
function isRenderEntry(value) {
|
|
20652
|
+
if (!value || typeof value !== "object") return false;
|
|
20653
|
+
const entry = value;
|
|
20654
|
+
return typeof entry.screenId === "string" && entry.screenId.length > 0 && typeof entry.width === "number" && Number.isFinite(entry.width) && entry.width > 0 && typeof entry.recordedAt === "string" && entry.recordedAt.length > 0;
|
|
20655
|
+
}
|
|
20656
|
+
function renderEvidenceEntries(evidence) {
|
|
20657
|
+
const raw = evidence?.renders;
|
|
20658
|
+
return Array.isArray(raw) ? raw.filter(isRenderEntry) : [];
|
|
20659
|
+
}
|
|
20660
|
+
function recordedRenderWidths(content) {
|
|
20661
|
+
const { evidence } = parseEvidence(uxEvidencePath(content));
|
|
20662
|
+
return renderEvidenceEntries(evidence).map((entry) => entry.width);
|
|
20663
|
+
}
|
|
20664
|
+
function writeEvidence(path, evidence) {
|
|
20665
|
+
mkdirSync10(dirname15(path), { recursive: true });
|
|
20666
|
+
writeFileSync9(path, JSON.stringify(evidence, null, 2) + "\n");
|
|
20667
|
+
}
|
|
20668
|
+
function recordedFilePath(dir, file) {
|
|
20669
|
+
const rel = relative3(dir, resolve15(file));
|
|
20670
|
+
return rel && !rel.startsWith("..") && !isAbsolute2(rel) ? rel : file;
|
|
20671
|
+
}
|
|
20672
|
+
function recordRenderWidth(content, entry) {
|
|
20673
|
+
try {
|
|
20674
|
+
if (!entry.screenId || !Number.isFinite(entry.width) || entry.width <= 0) return null;
|
|
20675
|
+
const dir = resolve15(content);
|
|
20676
|
+
const path = join25(dir, UX_EVIDENCE_PATH);
|
|
20677
|
+
const parsed = parseEvidence(path);
|
|
20678
|
+
if (parsed.error) return null;
|
|
20679
|
+
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
20680
|
+
const width = entry.width;
|
|
20681
|
+
const written = {
|
|
20682
|
+
screenId: entry.screenId,
|
|
20683
|
+
width,
|
|
20684
|
+
...entry.device ? { device: entry.device } : {},
|
|
20685
|
+
...entry.file ? { file: recordedFilePath(dir, entry.file) } : {},
|
|
20686
|
+
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20687
|
+
};
|
|
20688
|
+
const renders = renderEvidenceEntries(evidence);
|
|
20689
|
+
const at = renders.findIndex((existing) => existing.screenId === written.screenId && existing.width === width);
|
|
20690
|
+
if (at >= 0) renders[at] = written;
|
|
20691
|
+
else renders.push(written);
|
|
20692
|
+
evidence.renders = renders;
|
|
20693
|
+
writeEvidence(path, evidence);
|
|
20694
|
+
return written;
|
|
20695
|
+
} catch {
|
|
20696
|
+
return null;
|
|
20697
|
+
}
|
|
20698
|
+
}
|
|
20699
|
+
function recordNativeAudit(content, platform, status, checks, reason) {
|
|
20700
|
+
const normalizedChecks = status === "unavailable" ? [] : [...new Set(checks.map((check) => check.trim()).filter(Boolean))];
|
|
20701
|
+
if (status !== "unavailable" && !normalizedChecks.length) {
|
|
20702
|
+
throw new Error("--checks needs at least one comma-separated check (for example: back,keyboard,voiceover)");
|
|
20703
|
+
}
|
|
20704
|
+
if (status === "unavailable" && !reason?.trim()) throw new Error("--reason is required when --status unavailable");
|
|
20705
|
+
const dir = resolve15(content);
|
|
20706
|
+
const path = join25(dir, UX_EVIDENCE_PATH);
|
|
20707
|
+
const parsed = parseEvidence(path);
|
|
20708
|
+
if (parsed.error) throw new Error(`${UX_EVIDENCE_PATH} ${parsed.error}`);
|
|
20709
|
+
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
20710
|
+
evidence.platforms[platform] = { status, checks: normalizedChecks, ...reason?.trim() ? { reason: reason.trim() } : {}, recordedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
20711
|
+
writeEvidence(path, evidence);
|
|
20712
|
+
return evidence;
|
|
20713
|
+
}
|
|
20714
|
+
var init_ux_evidence = __esm({
|
|
20715
|
+
"src/ux-evidence.ts"() {
|
|
20716
|
+
init_mobile_ux_contract();
|
|
20717
|
+
}
|
|
20718
|
+
});
|
|
20719
|
+
|
|
20472
20720
|
// ../../core/sdk/capability-catalog/src/types.ts
|
|
20473
20721
|
var init_types = __esm({
|
|
20474
20722
|
"../../core/sdk/capability-catalog/src/types.ts"() {
|
|
@@ -21195,9 +21443,9 @@ var init_src2 = __esm({
|
|
|
21195
21443
|
});
|
|
21196
21444
|
|
|
21197
21445
|
// ../app-icons/plan.ts
|
|
21198
|
-
import { existsSync as
|
|
21446
|
+
import { existsSync as existsSync24, readFileSync as readFileSync26, readdirSync as readdirSync12 } from "node:fs";
|
|
21199
21447
|
import { createHash as createHash7 } from "node:crypto";
|
|
21200
|
-
import { dirname as
|
|
21448
|
+
import { dirname as dirname17, join as join28, resolve as resolve18 } from "node:path";
|
|
21201
21449
|
function stripComments(src) {
|
|
21202
21450
|
let out = "";
|
|
21203
21451
|
let i = 0;
|
|
@@ -21326,15 +21574,15 @@ function rotateHue(hex2, deg) {
|
|
|
21326
21574
|
}
|
|
21327
21575
|
function resolveTokensPath(app, configTs) {
|
|
21328
21576
|
const literal = /^ {2}designTokensPath\s*:\s*["']([^"']+)["']/m.exec(stripComments(configTs))?.[1];
|
|
21329
|
-
if (literal) return { path:
|
|
21330
|
-
return { path:
|
|
21577
|
+
if (literal) return { path: resolve18(appDir(app), literal), source: "declared" };
|
|
21578
|
+
return { path: join28(appDir(app), "tokens.json"), source: "assumed" };
|
|
21331
21579
|
}
|
|
21332
21580
|
function resolveToken(app, token, tokensPathOverride) {
|
|
21333
|
-
const tokensPath = tokensPathOverride ??
|
|
21334
|
-
if (!
|
|
21581
|
+
const tokensPath = tokensPathOverride ?? join28(appDir(app), "tokens.json");
|
|
21582
|
+
if (!existsSync24(tokensPath)) {
|
|
21335
21583
|
throw new Error(`app-icons: ${app} has no tokens.json at ${tokensPath} (needed to resolve "${token}").`);
|
|
21336
21584
|
}
|
|
21337
|
-
const tokens = JSON.parse(
|
|
21585
|
+
const tokens = JSON.parse(readFileSync26(tokensPath, "utf8"));
|
|
21338
21586
|
const value = tokens.colors?.[token];
|
|
21339
21587
|
if (value === void 0) {
|
|
21340
21588
|
throw new Error(`app-icons: ${app} references icon colour token "${token}" but tokens.json has no such color.`);
|
|
@@ -21375,8 +21623,8 @@ function iconSpec(app, configTs, id, tokensPathOverride) {
|
|
|
21375
21623
|
assertIconContract(app, cfg);
|
|
21376
21624
|
const tokens = tokensPathOverride ?? resolveTokensPath(app, configTs).path;
|
|
21377
21625
|
if (cfg.source) {
|
|
21378
|
-
const abs =
|
|
21379
|
-
if (!
|
|
21626
|
+
const abs = resolve18(appDir(app), cfg.source);
|
|
21627
|
+
if (!existsSync24(abs)) {
|
|
21380
21628
|
throw new Error(`app-icons: ${app} declares icon.source "${cfg.source}" but ${abs} does not exist.`);
|
|
21381
21629
|
}
|
|
21382
21630
|
return {
|
|
@@ -21413,17 +21661,17 @@ function iconSpec(app, configTs, id, tokensPathOverride) {
|
|
|
21413
21661
|
};
|
|
21414
21662
|
}
|
|
21415
21663
|
function iosAssetCatalog2(app) {
|
|
21416
|
-
return assetCatalogIn(
|
|
21664
|
+
return assetCatalogIn(join28(appDir(app), "ios"));
|
|
21417
21665
|
}
|
|
21418
21666
|
function assetCatalogIn(platformDir) {
|
|
21419
|
-
if (!
|
|
21667
|
+
if (!existsSync24(platformDir)) return void 0;
|
|
21420
21668
|
const children = readdirSync12(platformDir).filter((c) => !c.startsWith("build")).sort();
|
|
21421
|
-
const catalogs = children.map((c) =>
|
|
21669
|
+
const catalogs = children.map((c) => join28(platformDir, c, "Assets.xcassets")).filter(existsSync24);
|
|
21422
21670
|
if (catalogs.length === 1) return catalogs[0];
|
|
21423
21671
|
if (catalogs.length > 1) return void 0;
|
|
21424
21672
|
const targets = [];
|
|
21425
21673
|
for (const child of children) {
|
|
21426
|
-
const dir =
|
|
21674
|
+
const dir = join28(platformDir, child);
|
|
21427
21675
|
let entries;
|
|
21428
21676
|
try {
|
|
21429
21677
|
entries = readdirSync12(dir);
|
|
@@ -21431,29 +21679,29 @@ function assetCatalogIn(platformDir) {
|
|
|
21431
21679
|
continue;
|
|
21432
21680
|
}
|
|
21433
21681
|
if (entries.includes("Info.plist") || entries.some((e) => e.endsWith(".swift"))) {
|
|
21434
|
-
targets.push(
|
|
21682
|
+
targets.push(join28(dir, "Assets.xcassets"));
|
|
21435
21683
|
}
|
|
21436
21684
|
}
|
|
21437
21685
|
return targets.length === 1 ? targets[0] : void 0;
|
|
21438
21686
|
}
|
|
21439
21687
|
function androidResDir2(manifestPath) {
|
|
21440
|
-
return
|
|
21688
|
+
return join28(dirname17(manifestPath), "res");
|
|
21441
21689
|
}
|
|
21442
21690
|
function androidManifestPath(app) {
|
|
21443
|
-
const androidDir =
|
|
21444
|
-
if (!
|
|
21445
|
-
const preferred =
|
|
21446
|
-
if (
|
|
21447
|
-
const candidates = readdirSync12(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) =>
|
|
21691
|
+
const androidDir = join28(appDir(app), "android");
|
|
21692
|
+
if (!existsSync24(androidDir)) return void 0;
|
|
21693
|
+
const preferred = join28(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
21694
|
+
if (existsSync24(preferred)) return preferred;
|
|
21695
|
+
const candidates = readdirSync12(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) => join28(androidDir, d.name, "src", "main", "AndroidManifest.xml")).filter(existsSync24);
|
|
21448
21696
|
return candidates.length === 1 ? candidates[0] : void 0;
|
|
21449
21697
|
}
|
|
21450
21698
|
function androidOptedIn2(manifestPath) {
|
|
21451
|
-
if (!manifestPath || !
|
|
21452
|
-
return
|
|
21699
|
+
if (!manifestPath || !existsSync24(manifestPath)) return false;
|
|
21700
|
+
return readFileSync26(manifestPath, "utf8").includes("@mipmap/ic_launcher");
|
|
21453
21701
|
}
|
|
21454
21702
|
function templateIconSha256() {
|
|
21455
21703
|
const cat = iosAssetCatalog2("_template");
|
|
21456
|
-
return cat ? fileSha256(
|
|
21704
|
+
return cat ? fileSha256(join28(cat, "AppIcon.appiconset", "icon_1024.png")) : null;
|
|
21457
21705
|
}
|
|
21458
21706
|
function placeholderHashes() {
|
|
21459
21707
|
const current = templateIconSha256();
|
|
@@ -21461,7 +21709,7 @@ function placeholderHashes() {
|
|
|
21461
21709
|
}
|
|
21462
21710
|
function fileSha256(path) {
|
|
21463
21711
|
try {
|
|
21464
|
-
return createHash7("sha256").update(
|
|
21712
|
+
return createHash7("sha256").update(readFileSync26(path)).digest("hex");
|
|
21465
21713
|
} catch {
|
|
21466
21714
|
return null;
|
|
21467
21715
|
}
|
|
@@ -21472,8 +21720,8 @@ function generationAllowed(app, configTs, opts = {}) {
|
|
|
21472
21720
|
return { allowed: true, reason: "declares an icon block" };
|
|
21473
21721
|
}
|
|
21474
21722
|
const iosCat = iosAssetCatalog2(app);
|
|
21475
|
-
const iosIcon = iosCat ?
|
|
21476
|
-
if (!iosIcon || !
|
|
21723
|
+
const iosIcon = iosCat ? join28(iosCat, "AppIcon.appiconset", "icon_1024.png") : void 0;
|
|
21724
|
+
if (!iosIcon || !existsSync24(iosIcon)) return { allowed: true, reason: "no icon yet" };
|
|
21477
21725
|
const hash = fileSha256(iosIcon);
|
|
21478
21726
|
const placeholders = opts.placeholderHashes ?? placeholderHashes();
|
|
21479
21727
|
if (app === "_template") return { allowed: true, reason: "the template itself" };
|
|
@@ -21497,8 +21745,8 @@ var init_plan2 = __esm({
|
|
|
21497
21745
|
});
|
|
21498
21746
|
|
|
21499
21747
|
// ../native-config/icon.ts
|
|
21500
|
-
import { existsSync as
|
|
21501
|
-
import { join as
|
|
21748
|
+
import { existsSync as existsSync25, readFileSync as readFileSync27 } from "node:fs";
|
|
21749
|
+
import { join as join29 } from "node:path";
|
|
21502
21750
|
function androidAdaptiveIconXml() {
|
|
21503
21751
|
return [
|
|
21504
21752
|
'<?xml version="1.0" encoding="utf-8"?>',
|
|
@@ -21525,8 +21773,8 @@ function androidIconArtifacts(app, configTs) {
|
|
|
21525
21773
|
if (!androidOptedIn2(manifest)) return [];
|
|
21526
21774
|
if (!generationAllowed(app, configTs).allowed) return [];
|
|
21527
21775
|
const res = androidResDir2(manifest);
|
|
21528
|
-
const foreground =
|
|
21529
|
-
if (!
|
|
21776
|
+
const foreground = join29(res, "mipmap-mdpi", "ic_launcher_foreground.png");
|
|
21777
|
+
if (!existsSync25(foreground)) {
|
|
21530
21778
|
throw new Error(
|
|
21531
21779
|
`native-config icon: ${app} opts into @mipmap/ic_launcher but has no mipmap-*/ic_launcher_foreground.png. Run \`npm run app-icons -- ${app}\` first \u2014 the XML emitted here points at those rasters.`
|
|
21532
21780
|
);
|
|
@@ -21535,11 +21783,11 @@ function androidIconArtifacts(app, configTs) {
|
|
|
21535
21783
|
const spec = iconSpec(app, configTs, id, resolveTokensPath(app, configTs).path);
|
|
21536
21784
|
return [
|
|
21537
21785
|
...ANDROID_ADAPTIVE_FILES.map((name) => ({
|
|
21538
|
-
path:
|
|
21786
|
+
path: join29(res, "mipmap-anydpi-v26", name),
|
|
21539
21787
|
content: androidAdaptiveIconXml()
|
|
21540
21788
|
})),
|
|
21541
21789
|
{
|
|
21542
|
-
path:
|
|
21790
|
+
path: join29(res, "values", ANDROID_ICON_BACKGROUND_FILE),
|
|
21543
21791
|
content: androidIconBackgroundXml(spec.background)
|
|
21544
21792
|
}
|
|
21545
21793
|
];
|
|
@@ -21773,8 +22021,8 @@ __export(gen_native_config_exports, {
|
|
|
21773
22021
|
tvInfoPlan: () => tvInfoPlan,
|
|
21774
22022
|
watchInfoPlan: () => watchInfoPlan
|
|
21775
22023
|
});
|
|
21776
|
-
import { existsSync as
|
|
21777
|
-
import { dirname as
|
|
22024
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync12, readFileSync as readFileSync28, readdirSync as readdirSync13, rmSync as rmSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
22025
|
+
import { dirname as dirname18, join as join30 } from "node:path";
|
|
21778
22026
|
function parseStringArray(configTs, field) {
|
|
21779
22027
|
const m = new RegExp(`${field}:\\s*\\[([^\\]]*)\\]`).exec(configTs);
|
|
21780
22028
|
if (!m) return [];
|
|
@@ -21846,9 +22094,9 @@ function buildSet(capabilities, envelope = []) {
|
|
|
21846
22094
|
return [...new Set([...capabilities, ...envelope].map(catalogKey))].sort();
|
|
21847
22095
|
}
|
|
21848
22096
|
function loadOverrides(app) {
|
|
21849
|
-
const p =
|
|
21850
|
-
if (!
|
|
21851
|
-
return JSON.parse(
|
|
22097
|
+
const p = join30(appDir(app), "native-config.overrides.json");
|
|
22098
|
+
if (!existsSync26(p)) return {};
|
|
22099
|
+
return JSON.parse(readFileSync28(p, "utf8"));
|
|
21852
22100
|
}
|
|
21853
22101
|
function needsQuote(s) {
|
|
21854
22102
|
if (s === "") return true;
|
|
@@ -21903,19 +22151,19 @@ function endText(kind, label2, indent) {
|
|
|
21903
22151
|
return kind === "yaml" ? `${indent}# <<< ${label2} <<<` : `${indent}<!-- <<< ${label2} <<< -->`;
|
|
21904
22152
|
}
|
|
21905
22153
|
function hostAppliesDeferredWidgetActions(app) {
|
|
21906
|
-
const root =
|
|
21907
|
-
if (!
|
|
22154
|
+
const root = join30(appDir(app), "ios");
|
|
22155
|
+
if (!existsSync26(root)) return false;
|
|
21908
22156
|
const stack = [root];
|
|
21909
22157
|
while (stack.length) {
|
|
21910
22158
|
const dir = stack.pop();
|
|
21911
22159
|
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
21912
22160
|
if (entry.name.startsWith(".") || entry.name === "GeneratedLiveActivity") continue;
|
|
21913
|
-
const path =
|
|
22161
|
+
const path = join30(dir, entry.name);
|
|
21914
22162
|
if (entry.isDirectory()) {
|
|
21915
22163
|
if (entry.name.endsWith(".xcodeproj") || entry.name === "build") continue;
|
|
21916
22164
|
stack.push(path);
|
|
21917
22165
|
} else if (entry.name.endsWith(".swift")) {
|
|
21918
|
-
if (
|
|
22166
|
+
if (readFileSync28(path, "utf8").includes("WidgetActionRelay.drain(")) return true;
|
|
21919
22167
|
}
|
|
21920
22168
|
}
|
|
21921
22169
|
}
|
|
@@ -21937,18 +22185,18 @@ function injectBlock(text2, kind, label2, render) {
|
|
|
21937
22185
|
return [...lines.slice(0, beginIdx), ...block, ...lines.slice(endIdx + 1)].join("\n");
|
|
21938
22186
|
}
|
|
21939
22187
|
function androidManifestPath2(app) {
|
|
21940
|
-
const androidDir =
|
|
21941
|
-
const preferred =
|
|
21942
|
-
if (
|
|
21943
|
-
const candidates =
|
|
22188
|
+
const androidDir = join30(appDir(app), "android");
|
|
22189
|
+
const preferred = join30(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
22190
|
+
if (existsSync26(preferred)) return preferred;
|
|
22191
|
+
const candidates = existsSync26(androidDir) ? readdirSync13(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) => join30(androidDir, d.name, "src", "main", "AndroidManifest.xml")).filter(existsSync26) : [];
|
|
21944
22192
|
return candidates.length === 1 ? candidates[0] : preferred;
|
|
21945
22193
|
}
|
|
21946
22194
|
function automotiveAppDescPath(app) {
|
|
21947
|
-
return
|
|
22195
|
+
return join30(dirname18(androidManifestPath2(app)), "res", "xml", "automotive_app_desc.xml");
|
|
21948
22196
|
}
|
|
21949
22197
|
function applyToFile(path, kind, label2, render, check) {
|
|
21950
|
-
if (!
|
|
21951
|
-
const before =
|
|
22198
|
+
if (!existsSync26(path)) return { path, outcome: "skipped" };
|
|
22199
|
+
const before = readFileSync28(path, "utf8");
|
|
21952
22200
|
if (!hasMarkers(before, kind, label2)) return { path, outcome: "skipped" };
|
|
21953
22201
|
const after = injectBlock(before, kind, label2, render);
|
|
21954
22202
|
if (after === before) return { path, outcome: "unchanged" };
|
|
@@ -21957,15 +22205,15 @@ function applyToFile(path, kind, label2, render, check) {
|
|
|
21957
22205
|
return { path, outcome: "written" };
|
|
21958
22206
|
}
|
|
21959
22207
|
function applyWholeFile(path, content, check) {
|
|
21960
|
-
const current =
|
|
22208
|
+
const current = existsSync26(path) ? readFileSync28(path, "utf8") : null;
|
|
21961
22209
|
if (current === content) return { path, outcome: "unchanged" };
|
|
21962
22210
|
if (check) return { path, outcome: "drift" };
|
|
21963
|
-
mkdirSync12(
|
|
22211
|
+
mkdirSync12(dirname18(path), { recursive: true });
|
|
21964
22212
|
writeFileSync11(path, content);
|
|
21965
22213
|
return { path, outcome: "written" };
|
|
21966
22214
|
}
|
|
21967
22215
|
function removeWholeFile(path, check) {
|
|
21968
|
-
if (!
|
|
22216
|
+
if (!existsSync26(path)) return { path, outcome: "skipped" };
|
|
21969
22217
|
if (check) return { path, outcome: "drift" };
|
|
21970
22218
|
rmSync3(path);
|
|
21971
22219
|
return { path, outcome: "removed" };
|
|
@@ -21973,7 +22221,7 @@ function removeWholeFile(path, check) {
|
|
|
21973
22221
|
function genNativeConfig(app, opts = {}) {
|
|
21974
22222
|
const check = opts.check ?? false;
|
|
21975
22223
|
const configPath = appConfigTs(app);
|
|
21976
|
-
const configTs =
|
|
22224
|
+
const configTs = existsSync26(configPath) ? readFileSync28(configPath, "utf8") : "";
|
|
21977
22225
|
const capabilities = parseStringArray(configTs, "capabilities");
|
|
21978
22226
|
const envelope = parseStringArray(configTs, "capabilityEnvelope");
|
|
21979
22227
|
const ids = buildSet(capabilities, envelope);
|
|
@@ -21989,7 +22237,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
21989
22237
|
const carBlock = applyToFile(carManifestPath, "xml", LABEL_CAR, (i) => renderCarManifestXml(carCategory, i), check);
|
|
21990
22238
|
assertCarBlockLanded(app, carCategory, carManifestPath, carBlock.outcome, LABEL_CAR);
|
|
21991
22239
|
const iosYml = iosProjectYml(app);
|
|
21992
|
-
const project =
|
|
22240
|
+
const project = existsSync26(iosYml) ? readFileSync28(iosYml, "utf8") : "";
|
|
21993
22241
|
const targetManaged = hasMarkers(project, "yaml", LABEL_LIVE_TARGET);
|
|
21994
22242
|
const embedManaged = hasMarkers(project, "yaml", LABEL_LIVE_EMBED);
|
|
21995
22243
|
if (targetManaged !== embedManaged) throw new Error(`${app}: Live Activity target and embedding markers must be installed together`);
|
|
@@ -22043,12 +22291,12 @@ function genNativeConfig(app, opts = {}) {
|
|
|
22043
22291
|
const plan = live2;
|
|
22044
22292
|
files.push(applyToFile(iosYml, "yaml", LABEL_LIVE_TARGET, (i) => plan.target.map((line) => i + line), check));
|
|
22045
22293
|
files.push(applyToFile(iosYml, "yaml", LABEL_LIVE_EMBED, (i) => plan.embed.map((line) => i + line), check));
|
|
22046
|
-
const source =
|
|
22294
|
+
const source = join30(dirname18(iosYml), LIVE_SOURCE_PATH);
|
|
22047
22295
|
files.push(plan.source ? applyWholeFile(source, plan.source, check) : removeWholeFile(source, check));
|
|
22048
|
-
const entitlements =
|
|
22296
|
+
const entitlements = join30(dirname18(iosYml), LIVE_ENTITLEMENTS_PATH);
|
|
22049
22297
|
files.push(plan.entitlements ? applyWholeFile(entitlements, plan.entitlements, check) : removeWholeFile(entitlements, check));
|
|
22050
22298
|
}
|
|
22051
|
-
const iosSplashManaged =
|
|
22299
|
+
const iosSplashManaged = existsSync26(iosYml) && hasMarkers(readFileSync28(iosYml, "utf8"), "yaml", LABEL_IOS_SPLASH);
|
|
22052
22300
|
const manifest = androidManifestPath2(app);
|
|
22053
22301
|
const splash = splashPlan(app, configTs, manifest, iosSplashManaged);
|
|
22054
22302
|
for (const artifact of splash.artifacts) files.push(applyWholeFile(artifact.path, artifact.content, check));
|
|
@@ -22136,8 +22384,8 @@ var init_app_module = __esm({
|
|
|
22136
22384
|
});
|
|
22137
22385
|
|
|
22138
22386
|
// ../../core/dev-server/src/loader.ts
|
|
22139
|
-
import { resolve as
|
|
22140
|
-
import { existsSync as
|
|
22387
|
+
import { resolve as resolve19, basename as basename7, dirname as dirname19 } from "node:path";
|
|
22388
|
+
import { existsSync as existsSync27, readdirSync as readdirSync14, readFileSync as readFileSync29, mkdirSync as mkdirSync13 } from "node:fs";
|
|
22141
22389
|
import { pathToFileURL as pathToFileURL5, fileURLToPath as fileURLToPath11 } from "node:url";
|
|
22142
22390
|
function resolveWixWebAuthConfig(app) {
|
|
22143
22391
|
const auth = app?.meta.auth;
|
|
@@ -22166,17 +22414,17 @@ function resolveWixClientId(app) {
|
|
|
22166
22414
|
}
|
|
22167
22415
|
function resolveDevEntry(name) {
|
|
22168
22416
|
for (const base of APP_ROOTS2) {
|
|
22169
|
-
const dir =
|
|
22170
|
-
const entry =
|
|
22171
|
-
if (
|
|
22417
|
+
const dir = resolve19(ROOT2, base, name);
|
|
22418
|
+
const entry = resolve19(dir, "dev/index.ts");
|
|
22419
|
+
if (existsSync27(entry)) return { entry, dir };
|
|
22172
22420
|
}
|
|
22173
22421
|
return null;
|
|
22174
22422
|
}
|
|
22175
22423
|
async function devModuleUrl(entry, dir) {
|
|
22176
22424
|
const hasTypeScriptLoader = process.execArgv.some((arg) => arg.includes("tsx"));
|
|
22177
22425
|
if (!isOffRepo() && hasTypeScriptLoader) return pathToFileURL5(entry).href;
|
|
22178
|
-
const out =
|
|
22179
|
-
mkdirSync13(
|
|
22426
|
+
const out = resolve19(dir, "dist/.himi/dev.mjs");
|
|
22427
|
+
mkdirSync13(dirname19(out), { recursive: true });
|
|
22180
22428
|
await buildAppEntry(entry, out, {
|
|
22181
22429
|
// Plain Node must resolve the published-style umbrella entry points for
|
|
22182
22430
|
// both standalone and in-repo CLI content. In-repo workspace packages
|
|
@@ -22198,7 +22446,7 @@ async function importDevModule(name, entry, dir) {
|
|
|
22198
22446
|
}
|
|
22199
22447
|
function readPlatformsJson(dir) {
|
|
22200
22448
|
try {
|
|
22201
|
-
const raw = JSON.parse(
|
|
22449
|
+
const raw = JSON.parse(readFileSync29(resolve19(dir, "platforms.json"), "utf8"));
|
|
22202
22450
|
return Object.fromEntries(
|
|
22203
22451
|
Object.entries(raw).filter(([k, v]) => VALID_PLATFORM_KEYS2.has(k) && typeof v === "boolean")
|
|
22204
22452
|
);
|
|
@@ -22207,17 +22455,17 @@ function readPlatformsJson(dir) {
|
|
|
22207
22455
|
}
|
|
22208
22456
|
}
|
|
22209
22457
|
async function loadContent(dir) {
|
|
22210
|
-
const absDir =
|
|
22211
|
-
const entry =
|
|
22212
|
-
if (!
|
|
22458
|
+
const absDir = resolve19(dir);
|
|
22459
|
+
const entry = resolve19(absDir, "dev/index.ts");
|
|
22460
|
+
if (!existsSync27(entry)) {
|
|
22213
22461
|
throw new Error(`No content package at "${absDir}": expected ${entry}.`);
|
|
22214
22462
|
}
|
|
22215
22463
|
let name = basename7(absDir);
|
|
22216
|
-
const manifestPath =
|
|
22217
|
-
if (
|
|
22464
|
+
const manifestPath = resolve19(absDir, "himalaya.content.json");
|
|
22465
|
+
if (existsSync27(manifestPath)) {
|
|
22218
22466
|
let manifest;
|
|
22219
22467
|
try {
|
|
22220
|
-
manifest = JSON.parse(
|
|
22468
|
+
manifest = JSON.parse(readFileSync29(manifestPath, "utf8"));
|
|
22221
22469
|
} catch (e) {
|
|
22222
22470
|
throw new Error(`Invalid himalaya.content.json at ${manifestPath}: ${e.message}`);
|
|
22223
22471
|
}
|
|
@@ -22243,11 +22491,11 @@ function listAvailableApps() {
|
|
|
22243
22491
|
const out = [];
|
|
22244
22492
|
const seen = /* @__PURE__ */ new Set();
|
|
22245
22493
|
for (const base of APP_ROOTS2) {
|
|
22246
|
-
const baseDir =
|
|
22247
|
-
if (!
|
|
22494
|
+
const baseDir = resolve19(ROOT2, base);
|
|
22495
|
+
if (!existsSync27(baseDir)) continue;
|
|
22248
22496
|
for (const name of readdirSync14(baseDir)) {
|
|
22249
22497
|
if (name.startsWith("_") || name.startsWith(".") || seen.has(name)) continue;
|
|
22250
|
-
if (
|
|
22498
|
+
if (existsSync27(resolve19(baseDir, name, "dev/index.ts"))) {
|
|
22251
22499
|
seen.add(name);
|
|
22252
22500
|
out.push({ name, root: base, kind: base === "test-apps" ? "test" : "app" });
|
|
22253
22501
|
}
|
|
@@ -22261,7 +22509,7 @@ var init_loader = __esm({
|
|
|
22261
22509
|
init_app_module();
|
|
22262
22510
|
init_preview_surfaces();
|
|
22263
22511
|
init_build_lib();
|
|
22264
|
-
ROOT2 =
|
|
22512
|
+
ROOT2 = resolve19(fileURLToPath11(new URL("../../..", import.meta.url)));
|
|
22265
22513
|
APP_ROOTS2 = ["apps", "test-apps"];
|
|
22266
22514
|
VALID_PLATFORM_KEYS2 = /* @__PURE__ */ new Set([
|
|
22267
22515
|
...PREVIEW_SURFACES.map((s) => s.platformKey).filter((k) => k !== null),
|
|
@@ -22306,8 +22554,8 @@ var init_build_sha = __esm({
|
|
|
22306
22554
|
|
|
22307
22555
|
// ../../core/dev-server/src/app-assets.ts
|
|
22308
22556
|
import { createHash as createHash8 } from "node:crypto";
|
|
22309
|
-
import { existsSync as
|
|
22310
|
-
import { join as
|
|
22557
|
+
import { existsSync as existsSync28, lstatSync as lstatSync3, readFileSync as readFileSync30, readdirSync as readdirSync15, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
|
|
22558
|
+
import { join as join31, resolve as resolve20, sep as sep5 } from "node:path";
|
|
22311
22559
|
function contentTypeFor(name) {
|
|
22312
22560
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
22313
22561
|
return CONTENT_TYPES[ext] ?? "application/octet-stream";
|
|
@@ -22321,19 +22569,19 @@ function assetSha256(bytes2) {
|
|
|
22321
22569
|
function findAssetsDir(appDir2) {
|
|
22322
22570
|
let declared;
|
|
22323
22571
|
try {
|
|
22324
|
-
declared = JSON.parse(
|
|
22572
|
+
declared = JSON.parse(readFileSync30(join31(appDir2, "himalaya.content.json"), "utf8")).assets;
|
|
22325
22573
|
} catch {
|
|
22326
22574
|
declared = void 0;
|
|
22327
22575
|
}
|
|
22328
22576
|
const rel = typeof declared === "string" && declared ? declared : "assets";
|
|
22329
|
-
const abs =
|
|
22330
|
-
const base =
|
|
22577
|
+
const abs = resolve20(appDir2, rel);
|
|
22578
|
+
const base = resolve20(appDir2);
|
|
22331
22579
|
if (abs !== base && !abs.startsWith(base + sep5)) return null;
|
|
22332
|
-
return
|
|
22580
|
+
return existsSync28(abs) && statSync5(abs).isDirectory() ? abs : null;
|
|
22333
22581
|
}
|
|
22334
22582
|
function readOtaOnlyPatterns(appDir2) {
|
|
22335
22583
|
try {
|
|
22336
|
-
const raw = JSON.parse(
|
|
22584
|
+
const raw = JSON.parse(readFileSync30(join31(appDir2, "assets.json"), "utf8"));
|
|
22337
22585
|
return Array.isArray(raw.otaOnly) ? raw.otaOnly.filter((p) => typeof p === "string") : [];
|
|
22338
22586
|
} catch {
|
|
22339
22587
|
return [];
|
|
@@ -22351,7 +22599,7 @@ function collectAssets(appDir2) {
|
|
|
22351
22599
|
const walk2 = (abs, prefix) => {
|
|
22352
22600
|
for (const entry of readdirSync15(abs, { withFileTypes: true })) {
|
|
22353
22601
|
if (entry.name.startsWith(".")) continue;
|
|
22354
|
-
const child =
|
|
22602
|
+
const child = join31(abs, entry.name);
|
|
22355
22603
|
const name = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
22356
22604
|
if (entry.isDirectory()) {
|
|
22357
22605
|
walk2(child, name);
|
|
@@ -22360,7 +22608,7 @@ function collectAssets(appDir2) {
|
|
|
22360
22608
|
if (!entry.isFile()) continue;
|
|
22361
22609
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
22362
22610
|
const baked = !OTA_ONLY_BY_DEFAULT.has(ext) && !otaOnly.some((p) => matchesPattern(name, p));
|
|
22363
|
-
out.push({ name, path: child, bytes:
|
|
22611
|
+
out.push({ name, path: child, bytes: statSync5(child).size, contentType: contentTypeFor(name), baked });
|
|
22364
22612
|
}
|
|
22365
22613
|
};
|
|
22366
22614
|
walk2(dir, "");
|
|
@@ -22369,7 +22617,7 @@ function collectAssets(appDir2) {
|
|
|
22369
22617
|
function collectBrandFonts(appDir2) {
|
|
22370
22618
|
let faces;
|
|
22371
22619
|
try {
|
|
22372
|
-
faces = JSON.parse(
|
|
22620
|
+
faces = JSON.parse(readFileSync30(join31(appDir2, "media/fonts/faces.json"), "utf8"));
|
|
22373
22621
|
} catch {
|
|
22374
22622
|
return [];
|
|
22375
22623
|
}
|
|
@@ -22382,7 +22630,7 @@ function collectBrandFonts(appDir2) {
|
|
|
22382
22630
|
const rel = typeof raw?.file === "string" ? raw.file : "";
|
|
22383
22631
|
if (!family || !postscriptName || !rel) continue;
|
|
22384
22632
|
if (rel.startsWith("/") || rel.split("/").includes("..")) continue;
|
|
22385
|
-
const path =
|
|
22633
|
+
const path = join31(appDir2, rel);
|
|
22386
22634
|
try {
|
|
22387
22635
|
if (!lstatSync3(path).isFile()) continue;
|
|
22388
22636
|
const root = realpathSync3(appDir2);
|
|
@@ -22418,7 +22666,7 @@ function resolveAssetForBuild(appDir2, name, serverBaseUrl, appId2) {
|
|
|
22418
22666
|
if (!hit) return null;
|
|
22419
22667
|
let bytes2;
|
|
22420
22668
|
try {
|
|
22421
|
-
bytes2 =
|
|
22669
|
+
bytes2 = readFileSync30(hit.path);
|
|
22422
22670
|
} catch {
|
|
22423
22671
|
return null;
|
|
22424
22672
|
}
|
|
@@ -22492,7 +22740,7 @@ async function injectRequest(listener, request) {
|
|
|
22492
22740
|
req.headers.host ??= url.host;
|
|
22493
22741
|
if (body && body.length > 0) req.push(body);
|
|
22494
22742
|
req.push(null);
|
|
22495
|
-
return await new Promise((
|
|
22743
|
+
return await new Promise((resolve42, reject) => {
|
|
22496
22744
|
const streamed = () => {
|
|
22497
22745
|
queueMicrotask(() => {
|
|
22498
22746
|
req.emit("close");
|
|
@@ -22508,7 +22756,7 @@ async function injectRequest(listener, request) {
|
|
|
22508
22756
|
else headers2.set(name, value);
|
|
22509
22757
|
}
|
|
22510
22758
|
const bodyless = out.status === 204 || out.status === 304 || request.method === "HEAD";
|
|
22511
|
-
|
|
22759
|
+
resolve42(new Response(bodyless ? null : out.body, { status: out.status, headers: headers2 }));
|
|
22512
22760
|
}, streamed);
|
|
22513
22761
|
res.on("inject-error", reject);
|
|
22514
22762
|
try {
|
|
@@ -22611,25 +22859,25 @@ var init_inject = __esm({
|
|
|
22611
22859
|
|
|
22612
22860
|
// ../../core/dev-server/src/store.ts
|
|
22613
22861
|
import { mkdirSync as mkdirSync14 } from "node:fs";
|
|
22614
|
-
import { dirname as
|
|
22862
|
+
import { dirname as dirname20, resolve as resolve21 } from "node:path";
|
|
22615
22863
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
22616
22864
|
import { createRequire } from "node:module";
|
|
22617
22865
|
var nodeRequire, ROOT3, Store;
|
|
22618
22866
|
var init_store2 = __esm({
|
|
22619
22867
|
"../../core/dev-server/src/store.ts"() {
|
|
22620
22868
|
nodeRequire = createRequire(import.meta.url);
|
|
22621
|
-
ROOT3 =
|
|
22869
|
+
ROOT3 = resolve21(fileURLToPath12(new URL("../../..", import.meta.url)));
|
|
22622
22870
|
Store = class {
|
|
22623
22871
|
_db;
|
|
22624
22872
|
dbPath;
|
|
22625
22873
|
constructor(appName) {
|
|
22626
|
-
const dataRoot = process.env.HIMALAYA_DEV_STORE_DIR ?
|
|
22627
|
-
this.dbPath =
|
|
22874
|
+
const dataRoot = process.env.HIMALAYA_DEV_STORE_DIR ? resolve21(process.env.HIMALAYA_DEV_STORE_DIR) : resolve21(ROOT3, "core/dev-server/data");
|
|
22875
|
+
this.dbPath = resolve21(dataRoot, `${appName}.sqlite`);
|
|
22628
22876
|
}
|
|
22629
22877
|
/** The node:sqlite handle — opened, bootstrapped, and seeded on first access. */
|
|
22630
22878
|
get db() {
|
|
22631
22879
|
if (this._db) return this._db;
|
|
22632
|
-
mkdirSync14(
|
|
22880
|
+
mkdirSync14(dirname20(this.dbPath), { recursive: true });
|
|
22633
22881
|
const { DatabaseSync } = nodeRequire("node:sqlite");
|
|
22634
22882
|
this._db = new DatabaseSync(this.dbPath, { timeout: 5e3 });
|
|
22635
22883
|
this.bootstrap();
|
|
@@ -22968,15 +23216,15 @@ var init_store2 = __esm({
|
|
|
22968
23216
|
});
|
|
22969
23217
|
|
|
22970
23218
|
// ../../core/dev-server/src/derive-transport-capability.ts
|
|
22971
|
-
import { readFileSync as
|
|
22972
|
-
import { resolve as
|
|
23219
|
+
import { readFileSync as readFileSync31 } from "node:fs";
|
|
23220
|
+
import { resolve as resolve22 } from "node:path";
|
|
22973
23221
|
function bundleRidesWixTransport(bundleJs) {
|
|
22974
23222
|
return /himalaya\.wixApi|wixApi\.call/.test(bundleJs);
|
|
22975
23223
|
}
|
|
22976
23224
|
function readFirst(roots, file) {
|
|
22977
23225
|
for (const root of typeof roots === "string" ? [roots] : roots) {
|
|
22978
23226
|
try {
|
|
22979
|
-
return
|
|
23227
|
+
return readFileSync31(resolve22(root, file), "utf8");
|
|
22980
23228
|
} catch {
|
|
22981
23229
|
}
|
|
22982
23230
|
}
|
|
@@ -23144,7 +23392,7 @@ var init_wix_member_login = __esm({
|
|
|
23144
23392
|
});
|
|
23145
23393
|
|
|
23146
23394
|
// ../../core/dev-server/src/wix-gateway.ts
|
|
23147
|
-
import { readFileSync as
|
|
23395
|
+
import { readFileSync as readFileSync32, existsSync as existsSync29 } from "node:fs";
|
|
23148
23396
|
function redactJsonValue(v) {
|
|
23149
23397
|
if (Array.isArray(v)) return v.map(redactJsonValue);
|
|
23150
23398
|
if (v && typeof v === "object") {
|
|
@@ -23183,8 +23431,8 @@ function resolveNetMocks(fileMocks, appDeclared) {
|
|
|
23183
23431
|
}
|
|
23184
23432
|
function readNetMocksFile(path) {
|
|
23185
23433
|
try {
|
|
23186
|
-
if (!
|
|
23187
|
-
const raw = JSON.parse(
|
|
23434
|
+
if (!existsSync29(path)) return null;
|
|
23435
|
+
const raw = JSON.parse(readFileSync32(path, "utf-8"));
|
|
23188
23436
|
if (Array.isArray(raw)) return wixMockRuleErrors(raw).length ? null : { rules: raw };
|
|
23189
23437
|
if (raw && typeof raw === "object") {
|
|
23190
23438
|
const o = raw;
|
|
@@ -23984,13 +24232,13 @@ var init_l10n_catalog = __esm({
|
|
|
23984
24232
|
});
|
|
23985
24233
|
|
|
23986
24234
|
// ../../core/dev-server/src/l10n.ts
|
|
23987
|
-
import { readFileSync as
|
|
23988
|
-
import { resolve as
|
|
24235
|
+
import { readFileSync as readFileSync33, existsSync as existsSync30 } from "node:fs";
|
|
24236
|
+
import { resolve as resolve23 } from "node:path";
|
|
23989
24237
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
23990
24238
|
function loadCatalog2(tag) {
|
|
23991
24239
|
if (catalogCache.has(tag)) return catalogCache.get(tag);
|
|
23992
|
-
const path =
|
|
23993
|
-
const map =
|
|
24240
|
+
const path = resolve23(ROOT4, `tools/l10n/catalog.${tag}.json`);
|
|
24241
|
+
const map = existsSync30(path) ? sourceMap(parseCatalog(readFileSync33(path, "utf8"))) : /* @__PURE__ */ new Map();
|
|
23994
24242
|
catalogCache.set(tag, map);
|
|
23995
24243
|
return map;
|
|
23996
24244
|
}
|
|
@@ -23999,8 +24247,8 @@ function pickLocale(acceptLanguage) {
|
|
|
23999
24247
|
const tags = acceptLanguage.split(",").map((s) => s.split(";")[0].trim().toLowerCase()).map((s) => s.split("-")[0]).filter((s) => s.length > 0);
|
|
24000
24248
|
for (const tag of tags) {
|
|
24001
24249
|
if (tag === "en") continue;
|
|
24002
|
-
const path =
|
|
24003
|
-
if (
|
|
24250
|
+
const path = resolve23(ROOT4, `tools/l10n/catalog.${tag}.json`);
|
|
24251
|
+
if (existsSync30(path)) return tag;
|
|
24004
24252
|
}
|
|
24005
24253
|
return null;
|
|
24006
24254
|
}
|
|
@@ -24056,7 +24304,7 @@ var init_l10n = __esm({
|
|
|
24056
24304
|
"../../core/dev-server/src/l10n.ts"() {
|
|
24057
24305
|
init_l10n_strings();
|
|
24058
24306
|
init_l10n_catalog();
|
|
24059
|
-
ROOT4 =
|
|
24307
|
+
ROOT4 = resolve23(fileURLToPath13(new URL("../../..", import.meta.url)));
|
|
24060
24308
|
catalogCache = /* @__PURE__ */ new Map();
|
|
24061
24309
|
}
|
|
24062
24310
|
});
|
|
@@ -24120,13 +24368,13 @@ var init_stable_ids = __esm({
|
|
|
24120
24368
|
// ../../core/dev-server/src/preview.ts
|
|
24121
24369
|
import { spawn as spawn2 } from "node:child_process";
|
|
24122
24370
|
import { createHash as createHash11 } from "node:crypto";
|
|
24123
|
-
import { existsSync as
|
|
24371
|
+
import { existsSync as existsSync31, createReadStream, statSync as statSync6, readFileSync as readFileSync34, renameSync, unlinkSync as unlinkSync2 } from "node:fs";
|
|
24124
24372
|
import { homedir as homedir5, tmpdir as tmpdir2 } from "node:os";
|
|
24125
|
-
import { resolve as resolvePath, dirname as
|
|
24373
|
+
import { resolve as resolvePath, dirname as dirname21 } from "node:path";
|
|
24126
24374
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
24127
24375
|
function firstExisting(paths) {
|
|
24128
24376
|
for (const p of paths) {
|
|
24129
|
-
if (p &&
|
|
24377
|
+
if (p && existsSync31(p)) return p;
|
|
24130
24378
|
}
|
|
24131
24379
|
return null;
|
|
24132
24380
|
}
|
|
@@ -24135,7 +24383,7 @@ function macosWinlistBin() {
|
|
|
24135
24383
|
}
|
|
24136
24384
|
function macosWinlistSourceHash() {
|
|
24137
24385
|
try {
|
|
24138
|
-
return createHash11("sha1").update(
|
|
24386
|
+
return createHash11("sha1").update(readFileSync34(MACOS_WINLIST)).digest("hex").slice(0, 12);
|
|
24139
24387
|
} catch {
|
|
24140
24388
|
return "missing";
|
|
24141
24389
|
}
|
|
@@ -24165,7 +24413,7 @@ function isHimalayaAppWindow(w) {
|
|
|
24165
24413
|
}
|
|
24166
24414
|
async function macosWinlistCommand() {
|
|
24167
24415
|
const bin = macosWinlistBin();
|
|
24168
|
-
if (
|
|
24416
|
+
if (existsSync31(bin)) return compiledWinlist(bin);
|
|
24169
24417
|
if (macosWinlistCompileFailed) return interpretWinlist();
|
|
24170
24418
|
if (!macosWinlistInFlight) {
|
|
24171
24419
|
macosWinlistInFlight = buildMacosWinlist(bin).finally(() => {
|
|
@@ -24193,7 +24441,7 @@ async function buildMacosWinlist(bin) {
|
|
|
24193
24441
|
unlinkSync2(staging);
|
|
24194
24442
|
} catch {
|
|
24195
24443
|
}
|
|
24196
|
-
return
|
|
24444
|
+
return existsSync31(bin) ? compiledWinlist(bin) : interpretWinlist();
|
|
24197
24445
|
}
|
|
24198
24446
|
return compiledWinlist(bin);
|
|
24199
24447
|
}
|
|
@@ -24280,7 +24528,7 @@ async function captureFrame(params, format = "png") {
|
|
|
24280
24528
|
const tmp = resolvePath(tmpdir2(), `himalaya-macos-preview-${windowId}-${process.pid}-${++macosCaptureSeq}.png`);
|
|
24281
24529
|
try {
|
|
24282
24530
|
await runner.capture(SCREENCAPTURE_BIN, ["-o", "-x", `-l${windowId}`, tmp]);
|
|
24283
|
-
return { buf:
|
|
24531
|
+
return { buf: readFileSync34(tmp), mime: "image/png" };
|
|
24284
24532
|
} finally {
|
|
24285
24533
|
try {
|
|
24286
24534
|
unlinkSync2(tmp);
|
|
@@ -24793,12 +25041,12 @@ function finalizeRecording(key2, rec) {
|
|
|
24793
25041
|
if (rec.finalize) return rec.finalize;
|
|
24794
25042
|
rec.finalize = (async () => {
|
|
24795
25043
|
clearTimeout(rec.autoStop);
|
|
24796
|
-
await new Promise((
|
|
25044
|
+
await new Promise((resolve42) => {
|
|
24797
25045
|
let done = false;
|
|
24798
25046
|
const finish2 = () => {
|
|
24799
25047
|
if (!done) {
|
|
24800
25048
|
done = true;
|
|
24801
|
-
|
|
25049
|
+
resolve42();
|
|
24802
25050
|
}
|
|
24803
25051
|
};
|
|
24804
25052
|
rec.child.once("close", finish2);
|
|
@@ -24818,7 +25066,7 @@ function finalizeRecording(key2, rec) {
|
|
|
24818
25066
|
} catch {
|
|
24819
25067
|
}
|
|
24820
25068
|
}
|
|
24821
|
-
const sizeBytes =
|
|
25069
|
+
const sizeBytes = existsSync31(rec.localPath) ? statSync6(rec.localPath).size : 0;
|
|
24822
25070
|
clips.set(rec.id, { path: rec.localPath, mime: rec.mime });
|
|
24823
25071
|
recordings.delete(key2);
|
|
24824
25072
|
return { sizeBytes };
|
|
@@ -24890,12 +25138,12 @@ async function handlePreviewClip(res, url) {
|
|
|
24890
25138
|
const q = new URLSearchParams(url.split("?")[1] ?? "");
|
|
24891
25139
|
const id = q.get("id") ?? "";
|
|
24892
25140
|
const clip = clips.get(id);
|
|
24893
|
-
if (!clip || !
|
|
25141
|
+
if (!clip || !existsSync31(clip.path)) {
|
|
24894
25142
|
res.statusCode = 404;
|
|
24895
25143
|
res.setHeader("content-type", "application/json");
|
|
24896
25144
|
return void res.end(JSON.stringify({ error: "clip_not_found", id }));
|
|
24897
25145
|
}
|
|
24898
|
-
const size =
|
|
25146
|
+
const size = statSync6(clip.path).size;
|
|
24899
25147
|
res.statusCode = 200;
|
|
24900
25148
|
res.setHeader("content-type", clip.mime);
|
|
24901
25149
|
res.setHeader("content-length", String(size));
|
|
@@ -24909,7 +25157,7 @@ var init_preview = __esm({
|
|
|
24909
25157
|
DEVICE_LIST_TIMEOUT_MS = 5e3;
|
|
24910
25158
|
defaultRunner2 = {
|
|
24911
25159
|
capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
|
|
24912
|
-
return new Promise((
|
|
25160
|
+
return new Promise((resolve42, reject) => {
|
|
24913
25161
|
const child = spawn2(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
24914
25162
|
const out = [];
|
|
24915
25163
|
const err = [];
|
|
@@ -24931,7 +25179,7 @@ var init_preview = __esm({
|
|
|
24931
25179
|
child.stderr.on("data", (b) => err.push(b));
|
|
24932
25180
|
child.on("error", (e) => settle(reject, e));
|
|
24933
25181
|
child.on("close", (code) => {
|
|
24934
|
-
if (code === 0) settle(
|
|
25182
|
+
if (code === 0) settle(resolve42, Buffer.concat(out));
|
|
24935
25183
|
else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
24936
25184
|
});
|
|
24937
25185
|
});
|
|
@@ -24951,7 +25199,7 @@ var init_preview = __esm({
|
|
|
24951
25199
|
SWIFT_BIN = process.env.HIMALAYA_SWIFT_PATH ?? "swift";
|
|
24952
25200
|
SWIFTC_BIN = process.env.HIMALAYA_SWIFTC_PATH ?? "swiftc";
|
|
24953
25201
|
SCREENCAPTURE_BIN = process.env.HIMALAYA_SCREENCAPTURE_PATH ?? "screencapture";
|
|
24954
|
-
MACOS_WINLIST = resolvePath(
|
|
25202
|
+
MACOS_WINLIST = resolvePath(dirname21(fileURLToPath14(import.meta.url)), "../scripts/macos-winshot.swift");
|
|
24955
25203
|
MACOS_WINLIST_BUILD_TIMEOUT_MS = 12e4;
|
|
24956
25204
|
MACOS_WINLIST_INTERPRET_TIMEOUT_MS = 3e4;
|
|
24957
25205
|
HIMALAYA_MAC_BUNDLE_ID = /^(com\.himalaya\.|com\.wix\.himi\.|dev\.himalaya\.)/i;
|
|
@@ -25008,8 +25256,8 @@ var init_tier4_integrity = __esm({
|
|
|
25008
25256
|
});
|
|
25009
25257
|
|
|
25010
25258
|
// ../../core/dev-server/src/tier4-verifier.ts
|
|
25011
|
-
import { readFileSync as
|
|
25012
|
-
import { resolve as
|
|
25259
|
+
import { readFileSync as readFileSync35, existsSync as existsSync32 } from "node:fs";
|
|
25260
|
+
import { resolve as resolve24 } from "node:path";
|
|
25013
25261
|
var TierFourVerifier;
|
|
25014
25262
|
var init_tier4_verifier = __esm({
|
|
25015
25263
|
"../../core/dev-server/src/tier4-verifier.ts"() {
|
|
@@ -25025,8 +25273,8 @@ var init_tier4_verifier = __esm({
|
|
|
25025
25273
|
async verifyServedFile(bundleId, relPath, providedBytes) {
|
|
25026
25274
|
const expected = this.expectedSri(bundleId, relPath);
|
|
25027
25275
|
if (!expected) return { ok: true };
|
|
25028
|
-
const path =
|
|
25029
|
-
const bytes2 = providedBytes ?? (
|
|
25276
|
+
const path = resolve24(this.tier4Root, bundleId, relPath);
|
|
25277
|
+
const bytes2 = providedBytes ?? (existsSync32(path) ? readFileSync35(path) : null);
|
|
25030
25278
|
if (!bytes2) return { ok: false, reason: "file not found" };
|
|
25031
25279
|
if (computeSri(bytes2) !== expected) return { ok: false, reason: "sri mismatch" };
|
|
25032
25280
|
return { ok: true };
|
|
@@ -25034,9 +25282,9 @@ var init_tier4_verifier = __esm({
|
|
|
25034
25282
|
bundle(bundleId) {
|
|
25035
25283
|
let cached3 = this.cache.get(bundleId);
|
|
25036
25284
|
if (cached3) return cached3;
|
|
25037
|
-
const manifestPath =
|
|
25038
|
-
if (!
|
|
25039
|
-
const manifest = JSON.parse(
|
|
25285
|
+
const manifestPath = resolve24(this.tier4Root, bundleId, "manifest.json");
|
|
25286
|
+
if (!existsSync32(manifestPath)) return void 0;
|
|
25287
|
+
const manifest = JSON.parse(readFileSync35(manifestPath, "utf8"));
|
|
25040
25288
|
cached3 = { integrity: parseManifestIntegrity(manifest) };
|
|
25041
25289
|
this.cache.set(bundleId, cached3);
|
|
25042
25290
|
return cached3;
|
|
@@ -35616,7 +35864,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
35616
35864
|
const browser = globalThis;
|
|
35617
35865
|
browser.document.documentElement.style.colorScheme = selected;
|
|
35618
35866
|
await browser.document.fonts?.ready;
|
|
35619
|
-
await new Promise((
|
|
35867
|
+
await new Promise((resolve42) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve42())));
|
|
35620
35868
|
}, scheme);
|
|
35621
35869
|
}
|
|
35622
35870
|
async function renderPngBatch(items) {
|
|
@@ -36560,8 +36808,8 @@ var init_src5 = __esm({
|
|
|
36560
36808
|
});
|
|
36561
36809
|
|
|
36562
36810
|
// ../../core/dev-server/src/flags/index.ts
|
|
36563
|
-
import { readFileSync as
|
|
36564
|
-
import { resolve as
|
|
36811
|
+
import { readFileSync as readFileSync36 } from "node:fs";
|
|
36812
|
+
import { resolve as resolve25 } from "node:path";
|
|
36565
36813
|
function selectProvider(config, store) {
|
|
36566
36814
|
const local = new LocalFlagProvider(store, () => config?.overrides);
|
|
36567
36815
|
if (!config || config.provider === "local") return local;
|
|
@@ -36656,7 +36904,7 @@ var init_flags2 = __esm({
|
|
|
36656
36904
|
if (now - this.lastFetch < this.ttlMs) return;
|
|
36657
36905
|
this.lastFetch = now;
|
|
36658
36906
|
try {
|
|
36659
|
-
const defs = JSON.parse(
|
|
36907
|
+
const defs = JSON.parse(readFileSync36(resolve25(appDir2, "flags.json"), "utf8"));
|
|
36660
36908
|
if (Array.isArray(defs) && defs.length > 0) store.replaceAll(defs);
|
|
36661
36909
|
} catch {
|
|
36662
36910
|
}
|
|
@@ -36706,19 +36954,19 @@ var init_motion_flags = __esm({
|
|
|
36706
36954
|
});
|
|
36707
36955
|
|
|
36708
36956
|
// ../../core/dev-server/src/kits.ts
|
|
36709
|
-
import { readdirSync as readdirSync16, readFileSync as
|
|
36710
|
-
import { resolve as
|
|
36957
|
+
import { readdirSync as readdirSync16, readFileSync as readFileSync37 } from "node:fs";
|
|
36958
|
+
import { resolve as resolve26, join as join32 } from "node:path";
|
|
36711
36959
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
36712
36960
|
function listKits() {
|
|
36713
36961
|
return readdirSync16(CATALOG).filter((f) => f.endsWith(".json")).map((f) => {
|
|
36714
|
-
const { tokens, ...meta } = JSON.parse(
|
|
36962
|
+
const { tokens, ...meta } = JSON.parse(readFileSync37(join32(CATALOG, f), "utf8"));
|
|
36715
36963
|
return meta;
|
|
36716
36964
|
});
|
|
36717
36965
|
}
|
|
36718
36966
|
function readKit(id) {
|
|
36719
36967
|
if (!/^[a-z0-9-]+$/.test(id)) return null;
|
|
36720
36968
|
try {
|
|
36721
|
-
return JSON.parse(
|
|
36969
|
+
return JSON.parse(readFileSync37(join32(CATALOG, `${id}.json`), "utf8"));
|
|
36722
36970
|
} catch {
|
|
36723
36971
|
return null;
|
|
36724
36972
|
}
|
|
@@ -36726,8 +36974,8 @@ function readKit(id) {
|
|
|
36726
36974
|
var ROOT5, CATALOG;
|
|
36727
36975
|
var init_kits = __esm({
|
|
36728
36976
|
"../../core/dev-server/src/kits.ts"() {
|
|
36729
|
-
ROOT5 =
|
|
36730
|
-
CATALOG =
|
|
36977
|
+
ROOT5 = resolve26(fileURLToPath15(new URL("../../..", import.meta.url)));
|
|
36978
|
+
CATALOG = join32(ROOT5, "stdlib/design-kits");
|
|
36731
36979
|
}
|
|
36732
36980
|
});
|
|
36733
36981
|
|
|
@@ -37095,12 +37343,12 @@ __export(validate_descriptor_exports, {
|
|
|
37095
37343
|
validateScreenDescriptor: () => validateScreenDescriptor,
|
|
37096
37344
|
workerSubtreeAllowed: () => workerSubtreeAllowed
|
|
37097
37345
|
});
|
|
37098
|
-
import { readFileSync as
|
|
37099
|
-
import { resolve as
|
|
37346
|
+
import { readFileSync as readFileSync38, existsSync as existsSync33, readdirSync as readdirSync17 } from "node:fs";
|
|
37347
|
+
import { resolve as resolve27 } from "node:path";
|
|
37100
37348
|
import { runInNewContext as runInNewContext2 } from "node:vm";
|
|
37101
37349
|
async function loadAllowedComponents(appDir2) {
|
|
37102
|
-
const modPath =
|
|
37103
|
-
if (!
|
|
37350
|
+
const modPath = resolve27(appDir2, "components.ts");
|
|
37351
|
+
if (!existsSync33(modPath)) return void 0;
|
|
37104
37352
|
try {
|
|
37105
37353
|
const { pathToFileURL: pathToFileURL8 } = await import("node:url");
|
|
37106
37354
|
const mod = await import(pathToFileURL8(modPath).href);
|
|
@@ -37112,8 +37360,8 @@ async function loadAllowedComponents(appDir2) {
|
|
|
37112
37360
|
return void 0;
|
|
37113
37361
|
}
|
|
37114
37362
|
function readBuiltBundle(tier5Root, bundleName) {
|
|
37115
|
-
const p =
|
|
37116
|
-
return
|
|
37363
|
+
const p = resolve27(tier5Root, `${bundleName}.bundle.js`);
|
|
37364
|
+
return existsSync33(p) ? readFileSync38(p, "utf8") : void 0;
|
|
37117
37365
|
}
|
|
37118
37366
|
function bundleNameFromUrl(url) {
|
|
37119
37367
|
if (typeof url !== "string") return null;
|
|
@@ -37140,11 +37388,11 @@ function appWorkerActionsFor(config, tier5Root) {
|
|
|
37140
37388
|
}
|
|
37141
37389
|
}
|
|
37142
37390
|
function readBuiltBundleMap(tier5Root, bundleName) {
|
|
37143
|
-
const p =
|
|
37144
|
-
return
|
|
37391
|
+
const p = resolve27(tier5Root, `${bundleName}.bundle.js.map`);
|
|
37392
|
+
return existsSync33(p) ? readFileSync38(p, "utf8") : void 0;
|
|
37145
37393
|
}
|
|
37146
37394
|
function nativeSourceFiles(directory, extension, buildDirMaxDepth, depth = 1) {
|
|
37147
|
-
if (!
|
|
37395
|
+
if (!existsSync33(directory)) return [];
|
|
37148
37396
|
let entries;
|
|
37149
37397
|
try {
|
|
37150
37398
|
entries = readdirSync17(directory, { withFileTypes: true });
|
|
@@ -37155,7 +37403,7 @@ function nativeSourceFiles(directory, extension, buildDirMaxDepth, depth = 1) {
|
|
|
37155
37403
|
return entries.flatMap((entry) => {
|
|
37156
37404
|
if (NATIVE_SCRATCH_DIRS.has(entry.name)) return [];
|
|
37157
37405
|
if (entry.name === BUILD_OUTPUT_DIR && depth <= buildDirMaxDepth) return [];
|
|
37158
|
-
const path =
|
|
37406
|
+
const path = resolve27(directory, entry.name);
|
|
37159
37407
|
if (entry.isDirectory()) return nativeSourceFiles(path, extension, buildDirMaxDepth, depth + 1);
|
|
37160
37408
|
return entry.name.endsWith(extension) ? [path] : [];
|
|
37161
37409
|
});
|
|
@@ -37164,12 +37412,12 @@ function registeredActions(source) {
|
|
|
37164
37412
|
return [...source.matchAll(/ActionDispatcher(?:\.shared)?\s*\.\s*register\s*\(\s*"([A-Za-z0-9_.]+)"/g)].map((match) => match[1]);
|
|
37165
37413
|
}
|
|
37166
37414
|
function discoverNativeActions(appDir2) {
|
|
37167
|
-
const roots = NATIVE_SOURCE_ROOTS.filter(({ directory }) =>
|
|
37168
|
-
const sources = roots.flatMap(({ directory, extension, buildDirMaxDepth }) => nativeSourceFiles(
|
|
37415
|
+
const roots = NATIVE_SOURCE_ROOTS.filter(({ directory }) => existsSync33(resolve27(appDir2, directory)));
|
|
37416
|
+
const sources = roots.flatMap(({ directory, extension, buildDirMaxDepth }) => nativeSourceFiles(resolve27(appDir2, directory), extension, buildDirMaxDepth));
|
|
37169
37417
|
const registered = sources.flatMap((source) => {
|
|
37170
37418
|
let text2;
|
|
37171
37419
|
try {
|
|
37172
|
-
text2 =
|
|
37420
|
+
text2 = readFileSync38(source, "utf8");
|
|
37173
37421
|
} catch (err) {
|
|
37174
37422
|
if (!vanished(err)) throw err;
|
|
37175
37423
|
return [];
|
|
@@ -37285,8 +37533,8 @@ __export(config_exports, {
|
|
|
37285
37533
|
serializeRolloutYaml: () => serializeRolloutYaml,
|
|
37286
37534
|
validateOverlayPatch: () => validateOverlayPatch
|
|
37287
37535
|
});
|
|
37288
|
-
import { mkdirSync as mkdirSync15, readFileSync as
|
|
37289
|
-
import { dirname as
|
|
37536
|
+
import { mkdirSync as mkdirSync15, readFileSync as readFileSync39, writeFileSync as writeFileSync12 } from "node:fs";
|
|
37537
|
+
import { dirname as dirname22, join as join33, resolve as resolve28 } from "node:path";
|
|
37290
37538
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
37291
37539
|
function strip(line) {
|
|
37292
37540
|
const h = line.indexOf("#");
|
|
@@ -37351,14 +37599,14 @@ function parseRevocationsYaml(text2) {
|
|
|
37351
37599
|
function appConfigPath(app, file, root = REPO_ROOT6) {
|
|
37352
37600
|
assertAppId(app, "appConfigPath");
|
|
37353
37601
|
for (const base of ["apps", "test-apps"]) {
|
|
37354
|
-
const p =
|
|
37602
|
+
const p = join33(root, base, app, file);
|
|
37355
37603
|
try {
|
|
37356
|
-
|
|
37604
|
+
readFileSync39(p);
|
|
37357
37605
|
return p;
|
|
37358
37606
|
} catch {
|
|
37359
37607
|
}
|
|
37360
37608
|
}
|
|
37361
|
-
return
|
|
37609
|
+
return join33(root, "apps", app, file);
|
|
37362
37610
|
}
|
|
37363
37611
|
function serializeRolloutYaml(cfg) {
|
|
37364
37612
|
const lines = [`app: ${cfg.app}`, "rings:"];
|
|
@@ -37393,14 +37641,14 @@ function validateOverlayPatch(patch) {
|
|
|
37393
37641
|
}
|
|
37394
37642
|
function readJsonAt(app, file, root) {
|
|
37395
37643
|
try {
|
|
37396
|
-
return JSON.parse(
|
|
37644
|
+
return JSON.parse(readFileSync39(appConfigPath(app, file, root), "utf8"));
|
|
37397
37645
|
} catch {
|
|
37398
37646
|
return null;
|
|
37399
37647
|
}
|
|
37400
37648
|
}
|
|
37401
37649
|
function writeJsonAt(app, file, root, value) {
|
|
37402
37650
|
const path = appConfigPath(app, file, root);
|
|
37403
|
-
mkdirSync15(
|
|
37651
|
+
mkdirSync15(dirname22(path), { recursive: true });
|
|
37404
37652
|
writeFileSync12(path, JSON.stringify(value, null, 2) + "\n");
|
|
37405
37653
|
return path;
|
|
37406
37654
|
}
|
|
@@ -37423,14 +37671,14 @@ function saveLocalFlags(app, defs, root = REPO_ROOT6) {
|
|
|
37423
37671
|
}
|
|
37424
37672
|
function loadRollout(app) {
|
|
37425
37673
|
try {
|
|
37426
|
-
return parseRolloutYaml(
|
|
37674
|
+
return parseRolloutYaml(readFileSync39(appConfigPath(app, "rollout.yaml"), "utf8"));
|
|
37427
37675
|
} catch {
|
|
37428
37676
|
return null;
|
|
37429
37677
|
}
|
|
37430
37678
|
}
|
|
37431
37679
|
function loadRevocations(app) {
|
|
37432
37680
|
try {
|
|
37433
|
-
return parseRevocationsYaml(
|
|
37681
|
+
return parseRevocationsYaml(readFileSync39(appConfigPath(app, "revocations.yaml"), "utf8")).revoked;
|
|
37434
37682
|
} catch {
|
|
37435
37683
|
return [];
|
|
37436
37684
|
}
|
|
@@ -37440,7 +37688,7 @@ var init_config2 = __esm({
|
|
|
37440
37688
|
"../../core/serve-control/src/config.ts"() {
|
|
37441
37689
|
init_errors();
|
|
37442
37690
|
init_contract();
|
|
37443
|
-
REPO_ROOT6 =
|
|
37691
|
+
REPO_ROOT6 = resolve28(dirname22(fileURLToPath16(import.meta.url)), "../../..");
|
|
37444
37692
|
OPERATIONAL_OVERLAY_KEYS = /* @__PURE__ */ new Set([
|
|
37445
37693
|
"wixCachePolicy",
|
|
37446
37694
|
"telemetryConfig",
|
|
@@ -37501,8 +37749,8 @@ var init_config2 = __esm({
|
|
|
37501
37749
|
// ../../core/dev-server/src/index.ts
|
|
37502
37750
|
import { createServer as createServer2 } from "node:http";
|
|
37503
37751
|
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
37504
|
-
import { readFileSync as
|
|
37505
|
-
import { extname, resolve as
|
|
37752
|
+
import { readFileSync as readFileSync40, existsSync as existsSync34, watch, mkdirSync as mkdirSync16, rmSync as rmSync4 } from "node:fs";
|
|
37753
|
+
import { extname, resolve as resolve29, normalize as normalize3, sep as sep6, join as join34 } from "node:path";
|
|
37506
37754
|
import { createHash as createHash15, randomUUID } from "node:crypto";
|
|
37507
37755
|
import { fileURLToPath as fileURLToPath17, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
37508
37756
|
function deepMerge2(base, patch) {
|
|
@@ -37551,8 +37799,8 @@ function makeEtag(body) {
|
|
|
37551
37799
|
function readAppTokens(state) {
|
|
37552
37800
|
if (!state.app) return null;
|
|
37553
37801
|
try {
|
|
37554
|
-
const tokenPath = state.app.module.designTokensPath ??
|
|
37555
|
-
const parsed = JSON.parse(
|
|
37802
|
+
const tokenPath = state.app.module.designTokensPath ?? resolve29(state.app.dir, state.app.module.config.designTokensPath ?? "tokens.json");
|
|
37803
|
+
const parsed = JSON.parse(readFileSync40(tokenPath, "utf8"));
|
|
37556
37804
|
delete parsed._meta;
|
|
37557
37805
|
return parsed;
|
|
37558
37806
|
} catch {
|
|
@@ -37564,7 +37812,7 @@ function effectiveAppConfigOverride(state) {
|
|
|
37564
37812
|
if (state.app) {
|
|
37565
37813
|
try {
|
|
37566
37814
|
gitOverlay = JSON.parse(
|
|
37567
|
-
|
|
37815
|
+
readFileSync40(resolve29(state.app.dir, "app-config.overlay.json"), "utf8")
|
|
37568
37816
|
);
|
|
37569
37817
|
} catch {
|
|
37570
37818
|
}
|
|
@@ -37620,8 +37868,8 @@ function handleL10nRequest(req, res, state) {
|
|
|
37620
37868
|
if (!state.app || app !== state.app.name) {
|
|
37621
37869
|
return sendJson(res, 404, { error: "unknown_app", app }, cors);
|
|
37622
37870
|
}
|
|
37623
|
-
const path =
|
|
37624
|
-
if (!
|
|
37871
|
+
const path = resolve29(state.app.dir, "l10n", `${tag}.json`);
|
|
37872
|
+
if (!existsSync34(path)) {
|
|
37625
37873
|
res.writeHead(204, cors);
|
|
37626
37874
|
res.end();
|
|
37627
37875
|
return;
|
|
@@ -37630,7 +37878,7 @@ function handleL10nRequest(req, res, state) {
|
|
|
37630
37878
|
let messages;
|
|
37631
37879
|
try {
|
|
37632
37880
|
messages = Object.fromEntries(
|
|
37633
|
-
keyMap(parseCatalog(
|
|
37881
|
+
keyMap(parseCatalog(readFileSync40(path, "utf8")), { sourceFallback: tag === sourceLocale })
|
|
37634
37882
|
);
|
|
37635
37883
|
} catch {
|
|
37636
37884
|
return sendJson(res, 500, { error: "catalog_unreadable", app, tag }, cors);
|
|
@@ -37677,8 +37925,8 @@ async function runScreenDiagnostics(state, screenId, descriptor) {
|
|
|
37677
37925
|
}
|
|
37678
37926
|
function servedFontFaces(appDir2, tokens) {
|
|
37679
37927
|
try {
|
|
37680
|
-
const policyPath =
|
|
37681
|
-
const policy =
|
|
37928
|
+
const policyPath = join34(appDir2, "fonts.json");
|
|
37929
|
+
const policy = existsSync34(policyPath) ? JSON.parse(readFileSync40(policyPath, "utf8")) : {};
|
|
37682
37930
|
const plan = planFonts(tokens, policy);
|
|
37683
37931
|
if (plan.families.length === 0) return void 0;
|
|
37684
37932
|
return servedProjection(plan);
|
|
@@ -37693,7 +37941,7 @@ function fontFaceBytesBySha(_appDir, sha) {
|
|
|
37693
37941
|
for (const face of family.faces) {
|
|
37694
37942
|
if (face.sha256 !== sha) continue;
|
|
37695
37943
|
const src = faceSource(face.file, face.sha256);
|
|
37696
|
-
if (src) return
|
|
37944
|
+
if (src) return readFileSync40(src);
|
|
37697
37945
|
}
|
|
37698
37946
|
}
|
|
37699
37947
|
} catch {
|
|
@@ -38040,7 +38288,7 @@ async function buildDescriptorForScreenId(state, screenId, query = new URLSearch
|
|
|
38040
38288
|
function bundleIntegritySync(name, dir) {
|
|
38041
38289
|
for (const root of dir ? [dir, TIER5_ROOT] : [TIER5_ROOT]) {
|
|
38042
38290
|
try {
|
|
38043
|
-
const bytes2 =
|
|
38291
|
+
const bytes2 = readFileSync40(resolve29(root, `${name}.bundle.js`));
|
|
38044
38292
|
return "sha256-" + createHash15("sha256").update(bytes2).digest("base64");
|
|
38045
38293
|
} catch {
|
|
38046
38294
|
}
|
|
@@ -38290,7 +38538,7 @@ function startBundleArtifactWatcher(state) {
|
|
|
38290
38538
|
}
|
|
38291
38539
|
}
|
|
38292
38540
|
async function rebuildBundleSource(name) {
|
|
38293
|
-
const lib = await import(pathToFileURL6(
|
|
38541
|
+
const lib = await import(pathToFileURL6(resolve29(TIER5_SRC_ROOT, "build-lib.mjs")).href);
|
|
38294
38542
|
await lib.buildBundle(name);
|
|
38295
38543
|
}
|
|
38296
38544
|
function startBundleSourceWatcher(state) {
|
|
@@ -38345,11 +38593,11 @@ function applyTopBarDefault(descriptor, config) {
|
|
|
38345
38593
|
async function reloadAppModule(state, opts) {
|
|
38346
38594
|
const current = state.app;
|
|
38347
38595
|
if (!current) return { ok: false, error: "no_app" };
|
|
38348
|
-
const entry =
|
|
38596
|
+
const entry = resolve29(current.dir, "dev/index.ts");
|
|
38349
38597
|
mkdirSync16(HMR_TMP_DIR, { recursive: true });
|
|
38350
|
-
const outfile =
|
|
38598
|
+
const outfile = resolve29(HMR_TMP_DIR, `${current.name}-${++appReloadSeq}.mjs`);
|
|
38351
38599
|
try {
|
|
38352
|
-
const lib = await import(pathToFileURL6(
|
|
38600
|
+
const lib = await import(pathToFileURL6(resolve29(TIER5_SRC_ROOT, "build-lib.mjs")).href);
|
|
38353
38601
|
await lib.buildAppEntry(entry, outfile, { confineTo: current.dir });
|
|
38354
38602
|
const mod = await import(pathToFileURL6(outfile).href);
|
|
38355
38603
|
const next = mod.default;
|
|
@@ -38622,7 +38870,7 @@ async function handleWebWix(req, res, state) {
|
|
|
38622
38870
|
}
|
|
38623
38871
|
if (match && (match.rule.kind ?? "mock") === "mock") {
|
|
38624
38872
|
const mocked = match.rule.response;
|
|
38625
|
-
if (mocked.delayMs) await new Promise((
|
|
38873
|
+
if (mocked.delayMs) await new Promise((resolve42) => setTimeout(resolve42, mocked.delayMs));
|
|
38626
38874
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
38627
38875
|
recordWixTraffic(state.wix, state.appName, state.adminUrl, {
|
|
38628
38876
|
ts: started,
|
|
@@ -39113,7 +39361,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
39113
39361
|
const name = decodeURIComponent(sampleMatch[1]);
|
|
39114
39362
|
if (!/^[a-zA-Z0-9._-]+$/.test(name)) return sendJson(res, 400, { error: "bad_name" });
|
|
39115
39363
|
try {
|
|
39116
|
-
const body = await readFile2(
|
|
39364
|
+
const body = await readFile2(resolve29(SAMPLES_ROOT, name), "utf-8");
|
|
39117
39365
|
return sendJson(res, 200, JSON.parse(body));
|
|
39118
39366
|
} catch {
|
|
39119
39367
|
return sendJson(res, 404, { error: "sample_not_found", name });
|
|
@@ -39383,9 +39631,9 @@ async function readBundleFile(name, dir) {
|
|
|
39383
39631
|
if (!/^[A-Za-z0-9_.\-]+$/.test(name)) return null;
|
|
39384
39632
|
const roots = dir ? [dir, TIER5_ROOT] : [TIER5_ROOT];
|
|
39385
39633
|
const candidates = roots.flatMap((root) => [
|
|
39386
|
-
|
|
39387
|
-
|
|
39388
|
-
|
|
39634
|
+
resolve29(root, `${name}.bundle.js`),
|
|
39635
|
+
resolve29(root, `${name}.js`),
|
|
39636
|
+
resolve29(root, name)
|
|
39389
39637
|
]);
|
|
39390
39638
|
for (const path of candidates) {
|
|
39391
39639
|
if (!roots.some((root) => path.startsWith(root))) continue;
|
|
@@ -39536,14 +39784,14 @@ async function handleWidgetClearPreview(res, state, widgetId) {
|
|
|
39536
39784
|
}
|
|
39537
39785
|
function readActionHandlerManifest(app) {
|
|
39538
39786
|
if (!/^[A-Za-z0-9_.\-]+$/.test(app)) return { handlers: [] };
|
|
39539
|
-
const manifestPath =
|
|
39540
|
-
const bundlePath =
|
|
39787
|
+
const manifestPath = resolve29(ACTION_HANDLERS_ROOT, `${app}.manifest.json`);
|
|
39788
|
+
const bundlePath = resolve29(ACTION_HANDLERS_ROOT, `${app}.handlers.js`);
|
|
39541
39789
|
if (!manifestPath.startsWith(ACTION_HANDLERS_ROOT) || !bundlePath.startsWith(ACTION_HANDLERS_ROOT)) return { handlers: [] };
|
|
39542
39790
|
let decls;
|
|
39543
39791
|
let bytes2;
|
|
39544
39792
|
try {
|
|
39545
|
-
decls = JSON.parse(
|
|
39546
|
-
bytes2 =
|
|
39793
|
+
decls = JSON.parse(readFileSync40(manifestPath, "utf8"));
|
|
39794
|
+
bytes2 = readFileSync40(bundlePath);
|
|
39547
39795
|
} catch {
|
|
39548
39796
|
return { handlers: [] };
|
|
39549
39797
|
}
|
|
@@ -39556,7 +39804,7 @@ function handleActionHandlersManifest(res, app) {
|
|
|
39556
39804
|
}
|
|
39557
39805
|
async function handleActionHandlerBundleGet(res, app) {
|
|
39558
39806
|
if (!/^[A-Za-z0-9_.\-]+$/.test(app)) return sendJson(res, 404, { error: "not_found" });
|
|
39559
|
-
const path =
|
|
39807
|
+
const path = resolve29(ACTION_HANDLERS_ROOT, `${app}.handlers.js`);
|
|
39560
39808
|
if (!path.startsWith(ACTION_HANDLERS_ROOT)) return sendJson(res, 404, { error: "not_found" });
|
|
39561
39809
|
try {
|
|
39562
39810
|
const bytes2 = await readFile2(path);
|
|
@@ -39573,9 +39821,9 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
39573
39821
|
}
|
|
39574
39822
|
async function serveStatic(req, res, root, prefix) {
|
|
39575
39823
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
39576
|
-
const
|
|
39577
|
-
const safe = normalize3(
|
|
39578
|
-
const fullPath =
|
|
39824
|
+
const relative8 = requested.replace(prefix, "").replace(/^\//, "");
|
|
39825
|
+
const safe = normalize3(relative8).replace(/^(\.\.[\/\\])+/, "");
|
|
39826
|
+
const fullPath = resolve29(root, safe);
|
|
39579
39827
|
if (!fullPath.startsWith(root)) {
|
|
39580
39828
|
return send(res, 403, "forbidden");
|
|
39581
39829
|
}
|
|
@@ -39781,7 +40029,7 @@ function createDevServer(opts = {}) {
|
|
|
39781
40029
|
};
|
|
39782
40030
|
const netMocksDisabled = opts.netMocks === false;
|
|
39783
40031
|
const explicitNetMocksPath = typeof opts.netMocks === "string" ? opts.netMocks : process.env.HIMALAYA_NET_MOCKS;
|
|
39784
|
-
const netMocksPath = netMocksDisabled ? void 0 : explicitNetMocksPath ?? (state.app?.meta.devGateway?.enabled === false ? void 0 : state.app ?
|
|
40032
|
+
const netMocksPath = netMocksDisabled ? void 0 : explicitNetMocksPath ?? (state.app?.meta.devGateway?.enabled === false ? void 0 : state.app ? resolve29(state.app.dir, "dev/net-mocks.json") : void 0);
|
|
39785
40033
|
const resolved2 = netMocksDisabled ? null : resolveNetMocks(
|
|
39786
40034
|
netMocksPath ? readNetMocksFile(netMocksPath) : null,
|
|
39787
40035
|
state.app?.meta.devGateway
|
|
@@ -39841,7 +40089,7 @@ function createDevServer(opts = {}) {
|
|
|
39841
40089
|
const q = new URLSearchParams(url.split("?")[1] ?? "");
|
|
39842
40090
|
const assetApp = q.get("app") ?? state.appName;
|
|
39843
40091
|
const assetDir = state.app && assetApp === state.app.name ? state.app.dir : resolveAppDir(assetApp);
|
|
39844
|
-
const hit = assetDir ? collectAssets(assetDir).find((a) => assetSha256(
|
|
40092
|
+
const hit = assetDir ? collectAssets(assetDir).find((a) => assetSha256(readFileSync40(a.path)) === sha) : void 0;
|
|
39845
40093
|
if (!hit && assetDir) {
|
|
39846
40094
|
const fontBytes = fontFaceBytesBySha(assetDir, sha);
|
|
39847
40095
|
if (fontBytes) {
|
|
@@ -39864,7 +40112,7 @@ function createDevServer(opts = {}) {
|
|
|
39864
40112
|
res.end(JSON.stringify({ error: "asset_not_found", app: assetApp, sha }));
|
|
39865
40113
|
return;
|
|
39866
40114
|
}
|
|
39867
|
-
const bytes2 =
|
|
40115
|
+
const bytes2 = readFileSync40(hit.path);
|
|
39868
40116
|
res.writeHead(200, {
|
|
39869
40117
|
"content-type": hit.contentType,
|
|
39870
40118
|
"content-length": String(bytes2.length),
|
|
@@ -39950,8 +40198,8 @@ function createDevServer(opts = {}) {
|
|
|
39950
40198
|
}
|
|
39951
40199
|
if (url === "/v1/schema/screen-descriptor.json" && req.method === "GET") {
|
|
39952
40200
|
try {
|
|
39953
|
-
const schemaPath =
|
|
39954
|
-
const body =
|
|
40201
|
+
const schemaPath = resolve29(ROOT6, "core/schema/generated/screen-descriptor.schema.json");
|
|
40202
|
+
const body = readFileSync40(schemaPath, "utf8");
|
|
39955
40203
|
return send(res, 200, body, {
|
|
39956
40204
|
"content-type": "application/schema+json; charset=utf-8",
|
|
39957
40205
|
"cache-control": "no-store",
|
|
@@ -39985,7 +40233,7 @@ function createDevServer(opts = {}) {
|
|
|
39985
40233
|
try {
|
|
39986
40234
|
const { parseRevocationsYaml: parseRevocationsYaml2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
39987
40235
|
revoked = parseRevocationsYaml2(
|
|
39988
|
-
|
|
40236
|
+
readFileSync40(resolve29(state.app.dir, "revocations.yaml"), "utf8")
|
|
39989
40237
|
).revoked;
|
|
39990
40238
|
} catch {
|
|
39991
40239
|
}
|
|
@@ -40217,18 +40465,18 @@ var init_src6 = __esm({
|
|
|
40217
40465
|
init_src5();
|
|
40218
40466
|
init_kits();
|
|
40219
40467
|
init_widgets();
|
|
40220
|
-
ROOT6 =
|
|
40221
|
-
TIER3_ROOT =
|
|
40222
|
-
TIER4_ROOT =
|
|
40468
|
+
ROOT6 = resolve29(fileURLToPath17(new URL("../../..", import.meta.url)));
|
|
40469
|
+
TIER3_ROOT = resolve29(ROOT6, "core/dev-server/web");
|
|
40470
|
+
TIER4_ROOT = resolve29(ROOT6, "core/dev-server/tier4-bundles");
|
|
40223
40471
|
tier4Verifier = new TierFourVerifier(TIER4_ROOT);
|
|
40224
|
-
TIER5_ROOT =
|
|
40225
|
-
ACTION_HANDLERS_ROOT =
|
|
40226
|
-
SAMPLES_ROOT =
|
|
40472
|
+
TIER5_ROOT = resolve29(ROOT6, "core/dev-server/tier5-bundles");
|
|
40473
|
+
ACTION_HANDLERS_ROOT = resolve29(ROOT6, "core/dev-server/action-handlers");
|
|
40474
|
+
SAMPLES_ROOT = resolve29(ROOT6, "core/dev-server/sdui-samples");
|
|
40227
40475
|
TELEMETRY_BUFFER_CAP = 1e3;
|
|
40228
40476
|
overrideHistorySeq = 0;
|
|
40229
40477
|
CACHE_CONTROL = "max-age=600, stale-while-revalidate=86400";
|
|
40230
|
-
TIER5_SRC_ROOT =
|
|
40231
|
-
HMR_TMP_DIR =
|
|
40478
|
+
TIER5_SRC_ROOT = resolve29(ROOT6, "core/dev-server/tier5-bundles-src");
|
|
40479
|
+
HMR_TMP_DIR = resolve29(ROOT6, "node_modules/.cache/himalaya-hmr");
|
|
40232
40480
|
appReloadSeq = 0;
|
|
40233
40481
|
WEBWIX_CLIENT_ID = process.env.DEMO_APP_WIX_CLIENT_ID ?? "4f58d461-c1f5-4a5d-a467-62cc2329e4dd";
|
|
40234
40482
|
WEBWIX_REDIRECT = "himalaya-demo-app://oauth/callback";
|
|
@@ -40593,12 +40841,12 @@ var init_query = __esm({
|
|
|
40593
40841
|
});
|
|
40594
40842
|
|
|
40595
40843
|
// ../../core/dev-server/src/crawl-input.ts
|
|
40596
|
-
function resolved(v,
|
|
40597
|
-
if (typeof v === "string") return v.startsWith("$service:") ?
|
|
40844
|
+
function resolved(v, resolve42) {
|
|
40845
|
+
if (typeof v === "string") return v.startsWith("$service:") ? resolve42(v) : v;
|
|
40598
40846
|
if (Array.isArray(v)) {
|
|
40599
40847
|
const out = v.flatMap((el) => {
|
|
40600
40848
|
if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
|
|
40601
|
-
const r =
|
|
40849
|
+
const r = resolve42(el);
|
|
40602
40850
|
return Array.isArray(r) ? r : [r];
|
|
40603
40851
|
});
|
|
40604
40852
|
return out;
|
|
@@ -40612,9 +40860,9 @@ function hasRowBinding(props) {
|
|
|
40612
40860
|
return itemToken(v) || Array.isArray(v) && v.some(itemToken);
|
|
40613
40861
|
});
|
|
40614
40862
|
}
|
|
40615
|
-
function declaredOptionIds(props,
|
|
40863
|
+
function declaredOptionIds(props, resolve42) {
|
|
40616
40864
|
const literal = props.options ?? props.tabs ?? props.chips;
|
|
40617
|
-
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath,
|
|
40865
|
+
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve42) : void 0;
|
|
40618
40866
|
const raw = Array.isArray(bound) ? bound : literal;
|
|
40619
40867
|
if (!Array.isArray(raw)) return [];
|
|
40620
40868
|
const out = [];
|
|
@@ -40657,24 +40905,24 @@ function seedTokens(state, limit = 48) {
|
|
|
40657
40905
|
walk2(state, 0);
|
|
40658
40906
|
return out;
|
|
40659
40907
|
}
|
|
40660
|
-
function synthesizeInput(control,
|
|
40908
|
+
function synthesizeInput(control, resolve42, tokens) {
|
|
40661
40909
|
const id = `${control.type}.${control.callback}`;
|
|
40662
40910
|
const row = SYNTHESIZED_CONTROLS[id];
|
|
40663
40911
|
if (!row) return null;
|
|
40664
40912
|
const props = control.props;
|
|
40665
40913
|
if (hasRowBinding(props)) return null;
|
|
40666
40914
|
if (row.from === "declared-options") {
|
|
40667
|
-
const ids = declaredOptionIds(props,
|
|
40915
|
+
const ids = declaredOptionIds(props, resolve42);
|
|
40668
40916
|
if (!ids.length) return null;
|
|
40669
40917
|
if (row.encoding === "string-array") {
|
|
40670
|
-
const currentRaw2 = resolved(props.selectedIds,
|
|
40918
|
+
const currentRaw2 = resolved(props.selectedIds, resolve42);
|
|
40671
40919
|
const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
|
|
40672
40920
|
const pick4 = ids.find((o) => !current3.includes(o));
|
|
40673
40921
|
if (pick4 === void 0) return null;
|
|
40674
40922
|
const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
|
|
40675
40923
|
return { key: row.key, value, from: row.from, current: current3, control: id };
|
|
40676
40924
|
}
|
|
40677
|
-
const currentRaw = resolved(props.selectedId,
|
|
40925
|
+
const currentRaw = resolved(props.selectedId, resolve42);
|
|
40678
40926
|
const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
|
|
40679
40927
|
const pick3 = ids.find((o) => o !== current2);
|
|
40680
40928
|
if (pick3 === void 0) return null;
|
|
@@ -40682,7 +40930,7 @@ function synthesizeInput(control, resolve41, tokens) {
|
|
|
40682
40930
|
}
|
|
40683
40931
|
if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
|
|
40684
40932
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
|
|
40685
|
-
const bound = binding2 === void 0 ? void 0 :
|
|
40933
|
+
const bound = binding2 === void 0 ? void 0 : resolve42(binding2);
|
|
40686
40934
|
const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
|
|
40687
40935
|
const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
|
|
40688
40936
|
const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
|
|
@@ -42899,8 +43147,8 @@ __export(build_exports2, {
|
|
|
42899
43147
|
withStoreNavBundle: () => withStoreNavBundle
|
|
42900
43148
|
});
|
|
42901
43149
|
import { createHash as createHash18 } from "node:crypto";
|
|
42902
|
-
import { readFileSync as
|
|
42903
|
-
import { dirname as
|
|
43150
|
+
import { readFileSync as readFileSync41, readdirSync as readdirSync18, existsSync as existsSync35 } from "node:fs";
|
|
43151
|
+
import { dirname as dirname23, join as join35, resolve as resolve30 } from "node:path";
|
|
42904
43152
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
42905
43153
|
import { createRequire as createRequire2 } from "node:module";
|
|
42906
43154
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
@@ -42922,7 +43170,7 @@ function bundleMapFor(tier5Dir, bundleName) {
|
|
|
42922
43170
|
if (!bundleName) return { bundleMap: null };
|
|
42923
43171
|
const built = readBuiltBundleMap(tier5Dir, bundleName);
|
|
42924
43172
|
if (built) return { bundleMap: built };
|
|
42925
|
-
if (
|
|
43173
|
+
if (resolve30(tier5Dir) !== TIER5_DIR) return { bundleMap: null };
|
|
42926
43174
|
let r;
|
|
42927
43175
|
try {
|
|
42928
43176
|
const { sourcemapForCommittedBundleSync } = requireFromHere(SOURCEMAP_ON_DEMAND_PATH);
|
|
@@ -42938,10 +43186,10 @@ function l10nLintOptions(locale, appDir2) {
|
|
|
42938
43186
|
const tags = (locale.translations ?? []).filter((t) => t !== locale.default);
|
|
42939
43187
|
const catalog = /* @__PURE__ */ new Set();
|
|
42940
43188
|
for (const tag of tags) {
|
|
42941
|
-
const path =
|
|
42942
|
-
if (!
|
|
43189
|
+
const path = join35(appDir2, "l10n", `${tag}.json`);
|
|
43190
|
+
if (!existsSync35(path)) continue;
|
|
42943
43191
|
try {
|
|
42944
|
-
const parsed = JSON.parse(
|
|
43192
|
+
const parsed = JSON.parse(readFileSync41(path, "utf8"));
|
|
42945
43193
|
for (const m of Object.values(parsed.messages ?? {})) {
|
|
42946
43194
|
if (typeof m?.source === "string" && typeof m.translation === "string" && m.translation.length > 0) {
|
|
42947
43195
|
catalog.add(m.source);
|
|
@@ -43106,7 +43354,7 @@ function shellSha(root = REPO_ROOT7) {
|
|
|
43106
43354
|
function isMonorepoCheckout(dir) {
|
|
43107
43355
|
try {
|
|
43108
43356
|
const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
43109
|
-
return top.length > 0 &&
|
|
43357
|
+
return top.length > 0 && existsSync35(join35(top, "core", "schema", "core.proto"));
|
|
43110
43358
|
} catch {
|
|
43111
43359
|
return false;
|
|
43112
43360
|
}
|
|
@@ -43239,8 +43487,8 @@ async function buildReleaseFromContent(contentDir2, dest, opts = {}) {
|
|
|
43239
43487
|
}
|
|
43240
43488
|
function readTokensForLint(preloaded) {
|
|
43241
43489
|
try {
|
|
43242
|
-
const tokenPath = preloaded.module.designTokensPath ??
|
|
43243
|
-
const parsed = JSON.parse(
|
|
43490
|
+
const tokenPath = preloaded.module.designTokensPath ?? resolve30(preloaded.dir, preloaded.module.config.designTokensPath ?? "tokens.json");
|
|
43491
|
+
const parsed = JSON.parse(readFileSync41(tokenPath, "utf8"));
|
|
43244
43492
|
delete parsed._meta;
|
|
43245
43493
|
return parsed;
|
|
43246
43494
|
} catch {
|
|
@@ -43377,7 +43625,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43377
43625
|
if (addrCache.has(name)) return addrCache.get(name);
|
|
43378
43626
|
let bytes2;
|
|
43379
43627
|
try {
|
|
43380
|
-
bytes2 =
|
|
43628
|
+
bytes2 = readFileSync41(join35(tier5Dir, `${name}.bundle.js`));
|
|
43381
43629
|
} catch {
|
|
43382
43630
|
return null;
|
|
43383
43631
|
}
|
|
@@ -43398,9 +43646,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43398
43646
|
const MAX_AUTHORING_DOC_BYTES = 128 * 1024;
|
|
43399
43647
|
if (store.putDoc) {
|
|
43400
43648
|
for (const [name, file] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
|
|
43401
|
-
const path =
|
|
43402
|
-
if (!
|
|
43403
|
-
const bytes2 =
|
|
43649
|
+
const path = join35(preloaded.dir, file);
|
|
43650
|
+
if (!existsSync35(path)) continue;
|
|
43651
|
+
const bytes2 = readFileSync41(path);
|
|
43404
43652
|
if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
|
|
43405
43653
|
throw new Error(`${file} must be non-empty and at most ${MAX_AUTHORING_DOC_BYTES} bytes to ship with a release.`);
|
|
43406
43654
|
}
|
|
@@ -43415,7 +43663,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43415
43663
|
const iconPath = resolveAppDirIcon(preloaded.dir);
|
|
43416
43664
|
if (iconPath) {
|
|
43417
43665
|
try {
|
|
43418
|
-
const bytes2 =
|
|
43666
|
+
const bytes2 = readFileSync41(iconPath);
|
|
43419
43667
|
await store.putIcon(app, bytes2);
|
|
43420
43668
|
iconHash = sha2564(bytes2);
|
|
43421
43669
|
} catch {
|
|
@@ -43437,7 +43685,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43437
43685
|
}
|
|
43438
43686
|
const seenAssetSha = /* @__PURE__ */ new Set();
|
|
43439
43687
|
for (const a of collected) {
|
|
43440
|
-
const bytes2 =
|
|
43688
|
+
const bytes2 = readFileSync41(a.path);
|
|
43441
43689
|
const hash = sha2564(bytes2);
|
|
43442
43690
|
if (!seenAssetSha.has(hash)) {
|
|
43443
43691
|
await store.putAsset(app, hash, bytes2, a.contentType);
|
|
@@ -43458,7 +43706,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43458
43706
|
const canEmitFonts = hasVendoredFloor();
|
|
43459
43707
|
try {
|
|
43460
43708
|
const appTokens = readTokensForLint(preloaded) ?? {};
|
|
43461
|
-
const policy =
|
|
43709
|
+
const policy = existsSync35(join35(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync41(join35(preloaded.dir, "fonts.json"), "utf8")) : {};
|
|
43462
43710
|
fontPlan = planFonts(appTokens, policy);
|
|
43463
43711
|
} catch (err) {
|
|
43464
43712
|
throw new Error(
|
|
@@ -43474,7 +43722,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43474
43722
|
`[release-build] ${family.name} face ${face.postScriptName} has no local bytes (sha ${face.sha256.slice(0, 12)}\u2026), so the release would declare a face the asset route cannot serve. Run \`npm run fonts:catalog\` to warm the cache before publishing.`
|
|
43475
43723
|
);
|
|
43476
43724
|
}
|
|
43477
|
-
const bytes2 =
|
|
43725
|
+
const bytes2 = readFileSync41(src);
|
|
43478
43726
|
const hash = sha2564(bytes2);
|
|
43479
43727
|
if (hash !== face.sha256) {
|
|
43480
43728
|
throw new Error(
|
|
@@ -43498,7 +43746,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
43498
43746
|
if (store.putAsset) {
|
|
43499
43747
|
for (const face of collectBrandFonts(preloaded.dir)) {
|
|
43500
43748
|
try {
|
|
43501
|
-
const bytes2 =
|
|
43749
|
+
const bytes2 = readFileSync41(face.path);
|
|
43502
43750
|
if (bytes2.length === 0) continue;
|
|
43503
43751
|
const hash = sha2564(bytes2);
|
|
43504
43752
|
await store.putAsset(app, hash, bytes2, "font/ttf");
|
|
@@ -43920,10 +44168,10 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
|
|
|
43920
44168
|
await store.reset(app);
|
|
43921
44169
|
const sources = {};
|
|
43922
44170
|
for (const definition of config.functions.functions) {
|
|
43923
|
-
const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
43924
|
-
const source = candidates.find((candidate) =>
|
|
44171
|
+
const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join35(preloaded.dir, "functions", `${definition.name}${extension}`));
|
|
44172
|
+
const source = candidates.find((candidate) => existsSync35(candidate));
|
|
43925
44173
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
43926
|
-
sources[definition.name] =
|
|
44174
|
+
sources[definition.name] = readFileSync41(source, "utf8");
|
|
43927
44175
|
}
|
|
43928
44176
|
const built = await buildFunctions(config.functions.functions, sources);
|
|
43929
44177
|
const bundles = {};
|
|
@@ -43951,7 +44199,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
|
|
|
43951
44199
|
return { manifest, failedToBuild: [], missingBundles: [], auth: {} };
|
|
43952
44200
|
}
|
|
43953
44201
|
function listBuildableApps() {
|
|
43954
|
-
const appsDir =
|
|
44202
|
+
const appsDir = join35(REPO_ROOT7, "apps");
|
|
43955
44203
|
return readdirSync18(appsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("_")).map((d) => d.name);
|
|
43956
44204
|
}
|
|
43957
44205
|
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL;
|
|
@@ -43982,10 +44230,10 @@ var init_build3 = __esm({
|
|
|
43982
44230
|
BAKE_OFFLINE_BASE = "http://himalaya-bake.invalid";
|
|
43983
44231
|
KNOWN_ICON_NAMES = [...ICON_NAMES].sort();
|
|
43984
44232
|
KNOWN_ICONS = new Set(KNOWN_ICON_NAMES);
|
|
43985
|
-
REPO_ROOT7 =
|
|
43986
|
-
TIER5_DIR =
|
|
44233
|
+
REPO_ROOT7 = resolve30(dirname23(fileURLToPath18(import.meta.url)), "../..");
|
|
44234
|
+
TIER5_DIR = join35(REPO_ROOT7, "core/dev-server/tier5-bundles");
|
|
43987
44235
|
requireFromHere = createRequire2(import.meta.url);
|
|
43988
|
-
SOURCEMAP_ON_DEMAND_PATH =
|
|
44236
|
+
SOURCEMAP_ON_DEMAND_PATH = join35(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
|
|
43989
44237
|
BAKED_SERVER_BASE_URL = "http://baked.himalaya.invalid";
|
|
43990
44238
|
}
|
|
43991
44239
|
});
|
|
@@ -44162,18 +44410,18 @@ __export(captcha_exports, {
|
|
|
44162
44410
|
captchaContentInput: () => captchaContentInput,
|
|
44163
44411
|
runCaptcha: () => runCaptcha
|
|
44164
44412
|
});
|
|
44165
|
-
import { readFileSync as
|
|
44166
|
-
import { resolve as
|
|
44413
|
+
import { readFileSync as readFileSync42 } from "node:fs";
|
|
44414
|
+
import { resolve as resolve31 } from "node:path";
|
|
44167
44415
|
function readObject(path) {
|
|
44168
44416
|
try {
|
|
44169
|
-
return JSON.parse(
|
|
44417
|
+
return JSON.parse(readFileSync42(path, "utf8"));
|
|
44170
44418
|
} catch {
|
|
44171
44419
|
return {};
|
|
44172
44420
|
}
|
|
44173
44421
|
}
|
|
44174
44422
|
function captchaContentInput(dir) {
|
|
44175
|
-
const content = readObject(
|
|
44176
|
-
const provisioning = readObject(
|
|
44423
|
+
const content = readObject(resolve31(dir, "himalaya.content.json"));
|
|
44424
|
+
const provisioning = readObject(resolve31(dir, "provisioning.json"));
|
|
44177
44425
|
return {
|
|
44178
44426
|
app: text(content.name),
|
|
44179
44427
|
siteId: text(provisioning.siteId),
|
|
@@ -44825,8 +45073,8 @@ __export(pack_exports, {
|
|
|
44825
45073
|
});
|
|
44826
45074
|
import { createHash as createHash19 } from "node:crypto";
|
|
44827
45075
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
44828
|
-
import { existsSync as
|
|
44829
|
-
import { dirname as
|
|
45076
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync17, readFileSync as readFileSync43, readdirSync as readdirSync19, rmSync as rmSync5, statSync as statSync7, writeFileSync as writeFileSync13 } from "node:fs";
|
|
45077
|
+
import { dirname as dirname24, join as join36, resolve as resolve32 } from "node:path";
|
|
44830
45078
|
function writeZip(entries) {
|
|
44831
45079
|
const sorted = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
44832
45080
|
const total = sorted.reduce((n, e) => n + e.bytes.length, 0);
|
|
@@ -44920,13 +45168,13 @@ function inflateEntry(buf, entry) {
|
|
|
44920
45168
|
return bytes2;
|
|
44921
45169
|
}
|
|
44922
45170
|
function readIf(path) {
|
|
44923
|
-
return
|
|
45171
|
+
return existsSync36(path) && statSync7(path).isFile() ? readFileSync43(path) : null;
|
|
44924
45172
|
}
|
|
44925
45173
|
function listDir(dir) {
|
|
44926
|
-
return
|
|
45174
|
+
return existsSync36(dir) ? readdirSync19(dir).filter((f) => statSync7(join36(dir, f)).isFile()) : [];
|
|
44927
45175
|
}
|
|
44928
45176
|
function gatherReleaseEntries(appDir2) {
|
|
44929
|
-
const manifestPath =
|
|
45177
|
+
const manifestPath = join36(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
|
|
44930
45178
|
const manifestBytes = readIf(manifestPath);
|
|
44931
45179
|
if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir2} \u2014 build a release there first`);
|
|
44932
45180
|
const manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
@@ -44950,7 +45198,7 @@ function gatherReleaseEntries(appDir2) {
|
|
|
44950
45198
|
}
|
|
44951
45199
|
const missing = [];
|
|
44952
45200
|
for (const rel of wanted) {
|
|
44953
|
-
const bytes2 = readIf(
|
|
45201
|
+
const bytes2 = readIf(join36(appDir2, rel));
|
|
44954
45202
|
if (bytes2) entries.push({ path: rel, bytes: bytes2 });
|
|
44955
45203
|
else missing.push(rel);
|
|
44956
45204
|
}
|
|
@@ -44961,12 +45209,12 @@ function gatherReleaseEntries(appDir2) {
|
|
|
44961
45209
|
);
|
|
44962
45210
|
}
|
|
44963
45211
|
for (const name of SINGLETONS) {
|
|
44964
|
-
const bytes2 = readIf(
|
|
45212
|
+
const bytes2 = readIf(join36(appDir2, name));
|
|
44965
45213
|
if (bytes2) entries.push({ path: name, bytes: bytes2 });
|
|
44966
45214
|
}
|
|
44967
45215
|
const skipped = [];
|
|
44968
45216
|
for (const sub of ["screens", "bundles", "assets", "widgets"]) {
|
|
44969
|
-
for (const f of listDir(
|
|
45217
|
+
for (const f of listDir(join36(appDir2, sub))) {
|
|
44970
45218
|
if (!wanted.has(`${sub}/${f}`)) skipped.push(`${sub}/${f}`);
|
|
44971
45219
|
}
|
|
44972
45220
|
}
|
|
@@ -44999,18 +45247,18 @@ function buildEntries(appDir2, app, opts) {
|
|
|
44999
45247
|
return { all, header, manifest, skipped };
|
|
45000
45248
|
}
|
|
45001
45249
|
function packRelease(releaseRoot, app, out, opts = {}) {
|
|
45002
|
-
const appDir2 =
|
|
45250
|
+
const appDir2 = join36(resolve32(releaseRoot), app);
|
|
45003
45251
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
45004
45252
|
const buf = writeZip(all);
|
|
45005
|
-
const isDir =
|
|
45006
|
-
const outFile = isDir ?
|
|
45007
|
-
mkdirSync17(
|
|
45253
|
+
const isDir = existsSync36(out) && statSync7(out).isDirectory();
|
|
45254
|
+
const outFile = isDir ? join36(resolve32(out), packageFileName(app, header.releaseId)) : resolve32(out);
|
|
45255
|
+
mkdirSync17(dirname24(outFile), { recursive: true });
|
|
45008
45256
|
writeFileSync13(outFile, buf);
|
|
45009
45257
|
return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
|
|
45010
45258
|
}
|
|
45011
45259
|
function resolvePackageDirDest(outDir, app, releaseId) {
|
|
45012
45260
|
const packagedApp = (dir) => {
|
|
45013
|
-
const bytes2 = readIf(
|
|
45261
|
+
const bytes2 = readIf(join36(dir, HIMI_PACKAGE_HEADER_PATH));
|
|
45014
45262
|
if (!bytes2) return void 0;
|
|
45015
45263
|
try {
|
|
45016
45264
|
return JSON.parse(bytes2.toString("utf8")).app;
|
|
@@ -45019,15 +45267,15 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
45019
45267
|
}
|
|
45020
45268
|
};
|
|
45021
45269
|
const replaceable = (dir) => {
|
|
45022
|
-
if (!
|
|
45023
|
-
if (!
|
|
45270
|
+
if (!existsSync36(dir)) return true;
|
|
45271
|
+
if (!statSync7(dir).isDirectory()) return false;
|
|
45024
45272
|
return readdirSync19(dir).length === 0 || packagedApp(dir) === app;
|
|
45025
45273
|
};
|
|
45026
|
-
if (
|
|
45274
|
+
if (existsSync36(outDir) && !statSync7(outDir).isDirectory()) {
|
|
45027
45275
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
45028
45276
|
}
|
|
45029
45277
|
if (replaceable(outDir)) return outDir;
|
|
45030
|
-
const child =
|
|
45278
|
+
const child = join36(outDir, packageDirName(app, releaseId));
|
|
45031
45279
|
if (!replaceable(child)) {
|
|
45032
45280
|
throw new Error(
|
|
45033
45281
|
`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.`
|
|
@@ -45041,14 +45289,14 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
|
45041
45289
|
"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."
|
|
45042
45290
|
);
|
|
45043
45291
|
}
|
|
45044
|
-
const appDir2 =
|
|
45292
|
+
const appDir2 = join36(resolve32(releaseRoot), app);
|
|
45045
45293
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
45046
|
-
const dest = resolvePackageDirDest(
|
|
45294
|
+
const dest = resolvePackageDirDest(resolve32(outDir), app, header.releaseId);
|
|
45047
45295
|
rmSync5(dest, { recursive: true, force: true });
|
|
45048
45296
|
let bytes2 = 0;
|
|
45049
45297
|
for (const entry of all) {
|
|
45050
|
-
const target =
|
|
45051
|
-
mkdirSync17(
|
|
45298
|
+
const target = join36(dest, entry.path);
|
|
45299
|
+
mkdirSync17(dirname24(target), { recursive: true });
|
|
45052
45300
|
writeFileSync13(target, entry.bytes);
|
|
45053
45301
|
bytes2 += entry.bytes.length;
|
|
45054
45302
|
}
|
|
@@ -45070,21 +45318,21 @@ function openPackageBuffer(buf) {
|
|
|
45070
45318
|
return openFromEntries(readZip(buf), { requireHeader: true });
|
|
45071
45319
|
}
|
|
45072
45320
|
function openPackageFile(file) {
|
|
45073
|
-
return openPackageBuffer(
|
|
45321
|
+
return openPackageBuffer(readFileSync43(file));
|
|
45074
45322
|
}
|
|
45075
45323
|
function openPackageDir(dir) {
|
|
45076
|
-
const root =
|
|
45324
|
+
const root = resolve32(dir);
|
|
45077
45325
|
const entries = /* @__PURE__ */ new Map();
|
|
45078
45326
|
const walk2 = (rel) => {
|
|
45079
|
-
const abs = rel ?
|
|
45327
|
+
const abs = rel ? join36(root, rel) : root;
|
|
45080
45328
|
for (const name of readdirSync19(abs)) {
|
|
45081
45329
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
45082
|
-
const childAbs =
|
|
45083
|
-
if (
|
|
45084
|
-
else if (isSafeEntryName(childRel)) entries.set(childRel,
|
|
45330
|
+
const childAbs = join36(abs, name);
|
|
45331
|
+
if (statSync7(childAbs).isDirectory()) walk2(childRel);
|
|
45332
|
+
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync43(childAbs));
|
|
45085
45333
|
}
|
|
45086
45334
|
};
|
|
45087
|
-
if (!
|
|
45335
|
+
if (!existsSync36(root)) throw new Error(`no such package directory: ${root}`);
|
|
45088
45336
|
walk2("");
|
|
45089
45337
|
const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
|
|
45090
45338
|
if (manifestBytes) {
|
|
@@ -45125,12 +45373,12 @@ function unpackTo(buf, dest, appFallback) {
|
|
|
45125
45373
|
const app = header.app ?? manifest?.app ?? appFallback;
|
|
45126
45374
|
if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
|
|
45127
45375
|
if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
|
|
45128
|
-
const root =
|
|
45129
|
-
const appDir2 =
|
|
45376
|
+
const root = resolve32(dest);
|
|
45377
|
+
const appDir2 = join36(root, app);
|
|
45130
45378
|
rmSync5(appDir2, { recursive: true, force: true });
|
|
45131
45379
|
for (const [rel, bytes2] of entries) {
|
|
45132
|
-
const target =
|
|
45133
|
-
mkdirSync17(
|
|
45380
|
+
const target = join36(appDir2, rel);
|
|
45381
|
+
mkdirSync17(dirname24(target), { recursive: true });
|
|
45134
45382
|
writeFileSync13(target, bytes2);
|
|
45135
45383
|
}
|
|
45136
45384
|
return { root, appDir: appDir2, app };
|
|
@@ -45164,19 +45412,19 @@ __export(app_source_exports, {
|
|
|
45164
45412
|
writeConflicts: () => writeConflicts,
|
|
45165
45413
|
zipAppSource: () => zipAppSource
|
|
45166
45414
|
});
|
|
45167
|
-
import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as
|
|
45168
|
-
import { join as
|
|
45415
|
+
import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as readFileSync44, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14, existsSync as existsSync37, rmSync as rmSync6, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
45416
|
+
import { join as join37, resolve as resolve33, sep as sep7 } from "node:path";
|
|
45169
45417
|
function walkSourceTree(dir, file, skip) {
|
|
45170
45418
|
const walk2 = (relDir) => {
|
|
45171
|
-
for (const name of readdirSync20(
|
|
45172
|
-
const rel = relDir ?
|
|
45173
|
-
const st = lstatSync4(
|
|
45419
|
+
for (const name of readdirSync20(join37(dir, relDir))) {
|
|
45420
|
+
const rel = relDir ? join37(relDir, name) : name;
|
|
45421
|
+
const st = lstatSync4(join37(dir, rel));
|
|
45174
45422
|
if (st.isSymbolicLink()) {
|
|
45175
45423
|
skip(rel);
|
|
45176
45424
|
continue;
|
|
45177
45425
|
}
|
|
45178
45426
|
if (st.isDirectory()) {
|
|
45179
|
-
if (isDeniedSourceDir(name) ||
|
|
45427
|
+
if (isDeniedSourceDir(name) || existsSync37(join37(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
|
|
45180
45428
|
else walk2(rel);
|
|
45181
45429
|
continue;
|
|
45182
45430
|
}
|
|
@@ -45194,7 +45442,7 @@ function collectAppSource(dir) {
|
|
|
45194
45442
|
const skipped = [];
|
|
45195
45443
|
walkSourceTree(
|
|
45196
45444
|
dir,
|
|
45197
|
-
(archivePath, hostRel) => entries.push({ path: archivePath, bytes:
|
|
45445
|
+
(archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync44(join37(dir, hostRel)) }),
|
|
45198
45446
|
(hostRel) => skipped.push(hostRel)
|
|
45199
45447
|
);
|
|
45200
45448
|
entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
@@ -45224,7 +45472,7 @@ function pathKind(p) {
|
|
|
45224
45472
|
}
|
|
45225
45473
|
}
|
|
45226
45474
|
function writeAppSource(entries, destDir) {
|
|
45227
|
-
const root =
|
|
45475
|
+
const root = resolve33(destDir);
|
|
45228
45476
|
if (pathKind(root)?.isSymbolicLink()) {
|
|
45229
45477
|
throw new Error(
|
|
45230
45478
|
`refusing to restore into ${root}: the destination itself is a symlink, so every file would be written outside it. Remove it, or pass --out/--name somewhere else.`
|
|
@@ -45237,13 +45485,13 @@ function writeAppSource(entries, destDir) {
|
|
|
45237
45485
|
const segments = entry.path.split("/");
|
|
45238
45486
|
let dir = root;
|
|
45239
45487
|
for (const segment of segments.slice(0, -1)) {
|
|
45240
|
-
dir =
|
|
45488
|
+
dir = join37(dir, segment);
|
|
45241
45489
|
const kind = pathKind(dir);
|
|
45242
45490
|
if (kind?.isSymbolicLink()) unlinkSync3(dir);
|
|
45243
45491
|
else if (kind) continue;
|
|
45244
45492
|
mkdirSync18(dir);
|
|
45245
45493
|
}
|
|
45246
|
-
const target =
|
|
45494
|
+
const target = join37(root, ...segments);
|
|
45247
45495
|
if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
|
|
45248
45496
|
writeFileSync14(target, entry.bytes);
|
|
45249
45497
|
written.push(entry.path);
|
|
@@ -45251,7 +45499,7 @@ function writeAppSource(entries, destDir) {
|
|
|
45251
45499
|
return written;
|
|
45252
45500
|
}
|
|
45253
45501
|
function staleSourcePaths(entries, destDir) {
|
|
45254
|
-
if (!
|
|
45502
|
+
if (!existsSync37(destDir)) return [];
|
|
45255
45503
|
const archived = new Set(entries.map((e) => e.path));
|
|
45256
45504
|
const stale = [];
|
|
45257
45505
|
walkSourceTree(destDir, (archivePath) => {
|
|
@@ -45264,7 +45512,7 @@ function deniedArchivePaths(entries) {
|
|
|
45264
45512
|
return entries.filter((e) => isDeniedSourcePath(e.path)).map((e) => e.path).sort();
|
|
45265
45513
|
}
|
|
45266
45514
|
function writeConflicts(entries, destDir) {
|
|
45267
|
-
const root =
|
|
45515
|
+
const root = resolve33(destDir);
|
|
45268
45516
|
const conflicts = [];
|
|
45269
45517
|
const seen = /* @__PURE__ */ new Set();
|
|
45270
45518
|
const say = (rel, what) => {
|
|
@@ -45278,7 +45526,7 @@ function writeConflicts(entries, destDir) {
|
|
|
45278
45526
|
let dir = root;
|
|
45279
45527
|
let stop = false;
|
|
45280
45528
|
for (const [i, segment] of segments.slice(0, -1).entries()) {
|
|
45281
|
-
dir =
|
|
45529
|
+
dir = join37(dir, segment);
|
|
45282
45530
|
const kind2 = pathKind(dir);
|
|
45283
45531
|
if (!kind2 || kind2.isSymbolicLink()) {
|
|
45284
45532
|
stop = true;
|
|
@@ -45290,7 +45538,7 @@ function writeConflicts(entries, destDir) {
|
|
|
45290
45538
|
break;
|
|
45291
45539
|
}
|
|
45292
45540
|
if (stop) continue;
|
|
45293
|
-
const kind = pathKind(
|
|
45541
|
+
const kind = pathKind(join37(root, ...segments));
|
|
45294
45542
|
if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
|
|
45295
45543
|
say(entry.path, "is a directory here, but the release has a file at that path");
|
|
45296
45544
|
}
|
|
@@ -45298,24 +45546,24 @@ function writeConflicts(entries, destDir) {
|
|
|
45298
45546
|
return conflicts;
|
|
45299
45547
|
}
|
|
45300
45548
|
function removeStaleSource(entries, destDir) {
|
|
45301
|
-
const root =
|
|
45549
|
+
const root = resolve33(destDir);
|
|
45302
45550
|
const removed = staleSourcePaths(entries, root);
|
|
45303
|
-
for (const rel of removed) rmSync6(
|
|
45551
|
+
for (const rel of removed) rmSync6(join37(root, ...rel.split("/")), { force: true });
|
|
45304
45552
|
const needed = /* @__PURE__ */ new Set();
|
|
45305
45553
|
for (const entry of entries) {
|
|
45306
45554
|
if (isDeniedSourcePath(entry.path)) continue;
|
|
45307
45555
|
const segments = entry.path.split("/");
|
|
45308
45556
|
for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
|
|
45309
45557
|
}
|
|
45310
|
-
if (
|
|
45558
|
+
if (existsSync37(root)) pruneEmptyDirs(root, "", needed, removed);
|
|
45311
45559
|
return removed.sort();
|
|
45312
45560
|
}
|
|
45313
45561
|
function pruneEmptyDirs(root, rel, needed, removed) {
|
|
45314
45562
|
let empty = true;
|
|
45315
|
-
for (const name of readdirSync20(rel ?
|
|
45316
|
-
const childRel = rel ?
|
|
45563
|
+
for (const name of readdirSync20(rel ? join37(root, rel) : root)) {
|
|
45564
|
+
const childRel = rel ? join37(rel, name) : name;
|
|
45317
45565
|
const posix3 = childRel.split(sep7).join("/");
|
|
45318
|
-
const kind = lstatSync4(
|
|
45566
|
+
const kind = lstatSync4(join37(root, childRel));
|
|
45319
45567
|
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name)) {
|
|
45320
45568
|
empty = false;
|
|
45321
45569
|
continue;
|
|
@@ -45325,7 +45573,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
45325
45573
|
empty = false;
|
|
45326
45574
|
continue;
|
|
45327
45575
|
}
|
|
45328
|
-
rmdirSync(
|
|
45576
|
+
rmdirSync(join37(root, childRel));
|
|
45329
45577
|
removed.push(`${posix3}/`);
|
|
45330
45578
|
}
|
|
45331
45579
|
return empty;
|
|
@@ -45353,13 +45601,13 @@ __export(eject_exports, {
|
|
|
45353
45601
|
EJECTABLE: () => EJECTABLE,
|
|
45354
45602
|
ejectModule: () => ejectModule
|
|
45355
45603
|
});
|
|
45356
|
-
import { existsSync as
|
|
45357
|
-
import { dirname as
|
|
45604
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync19, readFileSync as readFileSync45, writeFileSync as writeFileSync15 } from "node:fs";
|
|
45605
|
+
import { dirname as dirname25, join as join38, relative as relative5, resolve as resolve34, sep as sep8 } from "node:path";
|
|
45358
45606
|
function locate(repoRootOrCwd, mod) {
|
|
45359
|
-
const inRepo =
|
|
45360
|
-
if (
|
|
45361
|
-
const dist =
|
|
45362
|
-
if (
|
|
45607
|
+
const inRepo = resolve34(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
45608
|
+
if (existsSync38(inRepo)) return { path: inRepo, form: "source" };
|
|
45609
|
+
const dist = resolve34(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
|
|
45610
|
+
if (existsSync38(dist)) return { path: dist, form: "bundle" };
|
|
45363
45611
|
return null;
|
|
45364
45612
|
}
|
|
45365
45613
|
function specifiersFor(mod) {
|
|
@@ -45383,8 +45631,8 @@ function ejectModule(opts) {
|
|
|
45383
45631
|
};
|
|
45384
45632
|
}
|
|
45385
45633
|
const ext = found.form === "source" ? "ts" : "mjs";
|
|
45386
|
-
const target =
|
|
45387
|
-
mkdirSync19(
|
|
45634
|
+
const target = join38(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
|
|
45635
|
+
mkdirSync19(dirname25(target), { recursive: true });
|
|
45388
45636
|
const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
|
|
45389
45637
|
//
|
|
45390
45638
|
// Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
|
|
@@ -45397,17 +45645,17 @@ function ejectModule(opts) {
|
|
|
45397
45645
|
// gate still applies. Ejecting buys layout and flow, never the floor.
|
|
45398
45646
|
|
|
45399
45647
|
`;
|
|
45400
|
-
const normalized =
|
|
45648
|
+
const normalized = readFileSync45(found.path, "utf8").replace(
|
|
45401
45649
|
/(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
|
|
45402
45650
|
(_m, q, sub) => `${q}@wix/himalaya/${sub}${q}`
|
|
45403
45651
|
);
|
|
45404
45652
|
writeFileSync15(target, banner + normalized);
|
|
45405
45653
|
const rewired = [];
|
|
45406
45654
|
for (const f of files) {
|
|
45407
|
-
if (!
|
|
45408
|
-
const before =
|
|
45655
|
+
if (!existsSync38(f)) continue;
|
|
45656
|
+
const before = readFileSync45(f, "utf8");
|
|
45409
45657
|
let after = before;
|
|
45410
|
-
let rel =
|
|
45658
|
+
let rel = relative5(dirname25(f), target).split(sep8).join("/").replace(/\.tsx?$/, ".js");
|
|
45411
45659
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
45412
45660
|
for (const spec of specifiersFor(mod)) {
|
|
45413
45661
|
const q = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -45453,14 +45701,14 @@ __export(test_exports, {
|
|
|
45453
45701
|
scopeDescriptors: () => scopeDescriptors,
|
|
45454
45702
|
writeRecordedMocks: () => writeRecordedMocks
|
|
45455
45703
|
});
|
|
45456
|
-
import { existsSync as
|
|
45457
|
-
import { join as
|
|
45704
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync20, readFileSync as readFileSync46, writeFileSync as writeFileSync16 } from "node:fs";
|
|
45705
|
+
import { join as join39, resolve as resolve35 } from "node:path";
|
|
45458
45706
|
function readTestConfig(dir) {
|
|
45459
|
-
const p =
|
|
45460
|
-
if (!
|
|
45707
|
+
const p = resolve35(dir, TEST_CONFIG_FILE);
|
|
45708
|
+
if (!existsSync39(p)) return {};
|
|
45461
45709
|
let parsed;
|
|
45462
45710
|
try {
|
|
45463
|
-
parsed = JSON.parse(
|
|
45711
|
+
parsed = JSON.parse(readFileSync46(p, "utf8"));
|
|
45464
45712
|
} catch (e) {
|
|
45465
45713
|
throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e.message}`);
|
|
45466
45714
|
}
|
|
@@ -45503,7 +45751,7 @@ function readTestConfig(dir) {
|
|
|
45503
45751
|
function readNetRules(path) {
|
|
45504
45752
|
let parsed;
|
|
45505
45753
|
try {
|
|
45506
|
-
parsed = JSON.parse(
|
|
45754
|
+
parsed = JSON.parse(readFileSync46(path, "utf8"));
|
|
45507
45755
|
} catch (e) {
|
|
45508
45756
|
throw new Error(`--net ${path} could not be read as JSON \u2014 ${e.message}`);
|
|
45509
45757
|
}
|
|
@@ -45523,8 +45771,8 @@ function readNetRules(path) {
|
|
|
45523
45771
|
}
|
|
45524
45772
|
function defaultNetRules(dir) {
|
|
45525
45773
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
45526
|
-
const p =
|
|
45527
|
-
if (
|
|
45774
|
+
const p = resolve35(dir, rel);
|
|
45775
|
+
if (existsSync39(p)) {
|
|
45528
45776
|
const rules = readNetRules(p);
|
|
45529
45777
|
if (rules.length) return { rules, from: rel };
|
|
45530
45778
|
}
|
|
@@ -45540,7 +45788,7 @@ function readCannedResponses() {
|
|
|
45540
45788
|
];
|
|
45541
45789
|
for (const url of candidates) {
|
|
45542
45790
|
try {
|
|
45543
|
-
const parsed = JSON.parse(
|
|
45791
|
+
const parsed = JSON.parse(readFileSync46(url, "utf8"));
|
|
45544
45792
|
const byKey = {};
|
|
45545
45793
|
for (const [k, v] of Object.entries(parsed)) {
|
|
45546
45794
|
if (!k.startsWith("//")) byKey[k] = v;
|
|
@@ -45632,8 +45880,8 @@ function writeRecordedMocks(opts) {
|
|
|
45632
45880
|
mkdir: (p) => mkdirSync20(p, { recursive: true }),
|
|
45633
45881
|
write: (p, s) => writeFileSync16(p, s)
|
|
45634
45882
|
};
|
|
45635
|
-
fs.mkdir(
|
|
45636
|
-
fs.write(
|
|
45883
|
+
fs.mkdir(join39(opts.dir, "dev"));
|
|
45884
|
+
fs.write(join39(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
45637
45885
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
45638
45886
|
}
|
|
45639
45887
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -45696,7 +45944,7 @@ async function runCrawl(opts) {
|
|
|
45696
45944
|
if (list.length > 1) collapsed.push({ representative: rep.screenId, instances: list.length });
|
|
45697
45945
|
}
|
|
45698
45946
|
}
|
|
45699
|
-
const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(
|
|
45947
|
+
const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(resolve35(opts.netPath)), from: opts.netPath } : defaultNetRules(opts.dir);
|
|
45700
45948
|
const suppressions = opts.config?.skip ?? [];
|
|
45701
45949
|
const suppressed = [];
|
|
45702
45950
|
const matchSuppression = (screen, actionId, componentId, invariant) => suppressions.find((s) => (s.screen === void 0 || s.screen === screen) && (s.action === void 0 || s.action === actionId) && (s.component === void 0 || s.component === componentId) && (s.invariant === void 0 || s.invariant === invariant));
|
|
@@ -46090,19 +46338,19 @@ var mobile_ux_lint_exports = {};
|
|
|
46090
46338
|
__export(mobile_ux_lint_exports, {
|
|
46091
46339
|
mobileUxIssues: () => mobileUxIssues
|
|
46092
46340
|
});
|
|
46093
|
-
import { existsSync as
|
|
46094
|
-
import { join as
|
|
46341
|
+
import { existsSync as existsSync40, readFileSync as readFileSync47 } from "node:fs";
|
|
46342
|
+
import { join as join40 } from "node:path";
|
|
46095
46343
|
function mobileUxIssues(dir, strict) {
|
|
46096
|
-
const file =
|
|
46097
|
-
if (!
|
|
46344
|
+
const file = join40(dir, "MOBILE-UX.md");
|
|
46345
|
+
if (!existsSync40(file)) return [];
|
|
46098
46346
|
let text2;
|
|
46099
46347
|
try {
|
|
46100
|
-
text2 =
|
|
46348
|
+
text2 = readFileSync47(file, "utf8");
|
|
46101
46349
|
} catch {
|
|
46102
46350
|
return [];
|
|
46103
46351
|
}
|
|
46104
46352
|
if (!text2) return [];
|
|
46105
|
-
return mobileUxMarkerFindings(text2).map((finding) => ({
|
|
46353
|
+
return mobileUxMarkerFindings(text2, recordedRenderWidths(dir)).map((finding) => ({
|
|
46106
46354
|
screen: null,
|
|
46107
46355
|
pass: "mobile-ux",
|
|
46108
46356
|
ruleCode: finding.code,
|
|
@@ -46118,6 +46366,7 @@ function mobileUxIssues(dir, strict) {
|
|
|
46118
46366
|
var init_mobile_ux_lint = __esm({
|
|
46119
46367
|
"src/mobile-ux-lint.ts"() {
|
|
46120
46368
|
init_mobile_ux_contract();
|
|
46369
|
+
init_ux_evidence();
|
|
46121
46370
|
}
|
|
46122
46371
|
});
|
|
46123
46372
|
|
|
@@ -46300,9 +46549,9 @@ function ipv6Private(address) {
|
|
|
46300
46549
|
const value = address.toLowerCase().replace(/^\[|\]$/g, "");
|
|
46301
46550
|
const sections = value.split("::");
|
|
46302
46551
|
if (sections.length > 2) return true;
|
|
46303
|
-
const parse = (
|
|
46304
|
-
if (!
|
|
46305
|
-
const parts =
|
|
46552
|
+
const parse = (section2) => {
|
|
46553
|
+
if (!section2) return [];
|
|
46554
|
+
const parts = section2.split(":");
|
|
46306
46555
|
const last = parts.at(-1) ?? "";
|
|
46307
46556
|
if (!last.includes(".")) return parts.map((part) => Number.parseInt(part, 16));
|
|
46308
46557
|
parts.pop();
|
|
@@ -46376,7 +46625,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
46376
46625
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
46377
46626
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
46378
46627
|
const hostname = url.hostname.replace(/^\[|\]$/g, "");
|
|
46379
|
-
return await new Promise((
|
|
46628
|
+
return await new Promise((resolve42, reject) => {
|
|
46380
46629
|
let settled = false;
|
|
46381
46630
|
const finish2 = (fn) => {
|
|
46382
46631
|
if (settled) return;
|
|
@@ -46413,7 +46662,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
46413
46662
|
}
|
|
46414
46663
|
const responseHeaders = new Headers();
|
|
46415
46664
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
46416
|
-
|
|
46665
|
+
resolve42(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
46417
46666
|
}));
|
|
46418
46667
|
});
|
|
46419
46668
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -46713,7 +46962,7 @@ function createLocalTestSandbox() {
|
|
|
46713
46962
|
}
|
|
46714
46963
|
})();
|
|
46715
46964
|
`;
|
|
46716
|
-
return await new Promise((
|
|
46965
|
+
return await new Promise((resolve42, reject) => {
|
|
46717
46966
|
const { port1, port2 } = new MessageChannel();
|
|
46718
46967
|
const serializableContext = {
|
|
46719
46968
|
auth: context.auth,
|
|
@@ -46789,7 +47038,7 @@ function createLocalTestSandbox() {
|
|
|
46789
47038
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
46790
47039
|
return;
|
|
46791
47040
|
}
|
|
46792
|
-
if (message.ok) finish2(() =>
|
|
47041
|
+
if (message.ok) finish2(() => resolve42({ value: message.value, durationMs: Date.now() - started }));
|
|
46793
47042
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
46794
47043
|
});
|
|
46795
47044
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -47756,8 +48005,8 @@ __export(functions_exports, {
|
|
|
47756
48005
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
47757
48006
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
47758
48007
|
});
|
|
47759
|
-
import { readFileSync as
|
|
47760
|
-
import { join as
|
|
48008
|
+
import { readFileSync as readFileSync48, existsSync as existsSync41 } from "node:fs";
|
|
48009
|
+
import { join as join41, resolve as resolve36 } from "node:path";
|
|
47761
48010
|
function resolveFunctionsTarget(input) {
|
|
47762
48011
|
const explicitUrl = input.functionsUrl?.trim();
|
|
47763
48012
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -47769,16 +48018,16 @@ function resolveFunctionsTarget(input) {
|
|
|
47769
48018
|
return { mode: "local" };
|
|
47770
48019
|
}
|
|
47771
48020
|
async function loadFunctionsApp(dir) {
|
|
47772
|
-
const loaded = await loadContent(
|
|
48021
|
+
const loaded = await loadContent(resolve36(dir));
|
|
47773
48022
|
const config = loaded.module.config;
|
|
47774
48023
|
if (config.kind !== "functions" || !Array.isArray(config.functions?.functions)) {
|
|
47775
48024
|
throw new Error(`content package "${dir}" is not a functions-only app`);
|
|
47776
48025
|
}
|
|
47777
48026
|
const sources = {};
|
|
47778
48027
|
for (const definition of config.functions.functions) {
|
|
47779
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
48028
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join41(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync41);
|
|
47780
48029
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
47781
|
-
sources[definition.name] =
|
|
48030
|
+
sources[definition.name] = readFileSync48(source, "utf8");
|
|
47782
48031
|
}
|
|
47783
48032
|
const data = config.cms || config.data ? mergeDataResources(config) : void 0;
|
|
47784
48033
|
const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
|
|
@@ -47927,14 +48176,15 @@ __export(native_decode_exports, {
|
|
|
47927
48176
|
nativeDecodeAndroidHarnessDir: () => nativeDecodeAndroidHarnessDir,
|
|
47928
48177
|
nativeDecodePackageDir: () => nativeDecodePackageDir,
|
|
47929
48178
|
nativeDecodePlatforms: () => nativeDecodePlatforms,
|
|
48179
|
+
nativeOracleShipped: () => nativeOracleShipped,
|
|
47930
48180
|
parseNativeDecodeOutput: () => parseNativeDecodeOutput,
|
|
47931
48181
|
runAndroidNativeDecode: () => runAndroidNativeDecode,
|
|
47932
48182
|
runNativeDecode: () => runNativeDecode
|
|
47933
48183
|
});
|
|
47934
48184
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
47935
|
-
import { existsSync as
|
|
48185
|
+
import { existsSync as existsSync42, mkdtempSync as mkdtempSync2, readFileSync as readFileSync49, rmSync as rmSync7, writeFileSync as writeFileSync17 } from "node:fs";
|
|
47936
48186
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
47937
|
-
import { join as
|
|
48187
|
+
import { join as join42 } from "node:path";
|
|
47938
48188
|
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
47939
48189
|
function nativeDecodePackageDir() {
|
|
47940
48190
|
return fileURLToPath19(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -47942,6 +48192,12 @@ function nativeDecodePackageDir() {
|
|
|
47942
48192
|
function nativeDecodeAndroidHarnessDir() {
|
|
47943
48193
|
return fileURLToPath19(new URL("../../../tools/wix-sdk-android-tests/", import.meta.url));
|
|
47944
48194
|
}
|
|
48195
|
+
function nativeOracleShipped() {
|
|
48196
|
+
return {
|
|
48197
|
+
ios: existsSync42(join42(nativeDecodePackageDir(), "Package.swift")),
|
|
48198
|
+
android: existsSync42(join42(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
48199
|
+
};
|
|
48200
|
+
}
|
|
47945
48201
|
function detectNativeDecode(options = {}) {
|
|
47946
48202
|
const hostPlatform = options.hostPlatform ?? process.platform;
|
|
47947
48203
|
const packageDir = options.packageDir ?? nativeDecodePackageDir();
|
|
@@ -47950,7 +48206,7 @@ function detectNativeDecode(options = {}) {
|
|
|
47950
48206
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
47951
48207
|
}
|
|
47952
48208
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
47953
|
-
const packageAvailable = options.packageAvailable ??
|
|
48209
|
+
const packageAvailable = options.packageAvailable ?? existsSync42(join42(packageDir, "Package.swift"));
|
|
47954
48210
|
if (!packageAvailable) {
|
|
47955
48211
|
return {
|
|
47956
48212
|
platform: "ios",
|
|
@@ -47962,7 +48218,7 @@ function detectNativeDecode(options = {}) {
|
|
|
47962
48218
|
}
|
|
47963
48219
|
function localPropertiesSdk(harnessDir) {
|
|
47964
48220
|
try {
|
|
47965
|
-
const match =
|
|
48221
|
+
const match = readFileSync49(join42(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
47966
48222
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
47967
48223
|
} catch {
|
|
47968
48224
|
return null;
|
|
@@ -47970,8 +48226,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
47970
48226
|
}
|
|
47971
48227
|
function detectAndroidNativeDecode(options = {}) {
|
|
47972
48228
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
47973
|
-
const gradlew =
|
|
47974
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
48229
|
+
const gradlew = join42(harnessDir, "gradlew");
|
|
48230
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync42(gradlew);
|
|
47975
48231
|
if (!gradlewAvailable) {
|
|
47976
48232
|
return {
|
|
47977
48233
|
platform: "android",
|
|
@@ -47981,7 +48237,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
47981
48237
|
}
|
|
47982
48238
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
47983
48239
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
47984
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
48240
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync42(sdk));
|
|
47985
48241
|
if (!sdkAvailable) {
|
|
47986
48242
|
return {
|
|
47987
48243
|
platform: "android",
|
|
@@ -48053,14 +48309,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
48053
48309
|
return verdicts;
|
|
48054
48310
|
}
|
|
48055
48311
|
function runNativeDecode(options) {
|
|
48056
|
-
const descriptorDir = mkdtempSync2(
|
|
48312
|
+
const descriptorDir = mkdtempSync2(join42(tmpdir3(), "himi-native-decode-"));
|
|
48057
48313
|
const startedAt = Date.now();
|
|
48058
48314
|
try {
|
|
48059
48315
|
for (const descriptor of options.descriptors) {
|
|
48060
48316
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
48061
48317
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
48062
48318
|
}
|
|
48063
|
-
writeFileSync17(
|
|
48319
|
+
writeFileSync17(join42(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
48064
48320
|
}
|
|
48065
48321
|
options.progress?.("building cached Swift oracle");
|
|
48066
48322
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -48072,7 +48328,7 @@ function runNativeDecode(options) {
|
|
|
48072
48328
|
encoding: "utf8"
|
|
48073
48329
|
}).trim();
|
|
48074
48330
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
48075
|
-
const stdout = execFileSync5(
|
|
48331
|
+
const stdout = execFileSync5(join42(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
48076
48332
|
stdio: ["ignore", "pipe", "pipe"],
|
|
48077
48333
|
encoding: "utf8"
|
|
48078
48334
|
});
|
|
@@ -48090,15 +48346,15 @@ function runNativeDecode(options) {
|
|
|
48090
48346
|
}
|
|
48091
48347
|
}
|
|
48092
48348
|
function runAndroidNativeDecode(options) {
|
|
48093
|
-
const descriptorDir = mkdtempSync2(
|
|
48094
|
-
const outputPath =
|
|
48349
|
+
const descriptorDir = mkdtempSync2(join42(tmpdir3(), "himi-native-decode-android-"));
|
|
48350
|
+
const outputPath = join42(descriptorDir, "verdicts.ndjson");
|
|
48095
48351
|
const startedAt = Date.now();
|
|
48096
48352
|
try {
|
|
48097
48353
|
for (const descriptor of options.descriptors) {
|
|
48098
48354
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
48099
48355
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
48100
48356
|
}
|
|
48101
|
-
writeFileSync17(
|
|
48357
|
+
writeFileSync17(join42(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
48102
48358
|
}
|
|
48103
48359
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
48104
48360
|
execFileSync5(options.gradlew, [
|
|
@@ -48113,7 +48369,7 @@ function runAndroidNativeDecode(options) {
|
|
|
48113
48369
|
stdio: ["ignore", "ignore", "pipe"],
|
|
48114
48370
|
encoding: "utf8"
|
|
48115
48371
|
});
|
|
48116
|
-
const stdout =
|
|
48372
|
+
const stdout = readFileSync49(outputPath, "utf8");
|
|
48117
48373
|
return {
|
|
48118
48374
|
platform: "android",
|
|
48119
48375
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -48184,13 +48440,13 @@ __export(browser_authoring_exports, {
|
|
|
48184
48440
|
import { createServer as createServer3 } from "node:http";
|
|
48185
48441
|
import { createHash as createHash22, randomBytes as randomBytes5 } from "node:crypto";
|
|
48186
48442
|
import { execFile as execFile2 } from "node:child_process";
|
|
48187
|
-
import { existsSync as
|
|
48188
|
-
import { join as
|
|
48443
|
+
import { existsSync as existsSync43, readdirSync as readdirSync21, readFileSync as readFileSync50, realpathSync as realpathSync4, statSync as statSync8 } from "node:fs";
|
|
48444
|
+
import { join as join43, posix, relative as relative6, sep as sep9 } from "node:path";
|
|
48189
48445
|
function humanMs(ms) {
|
|
48190
48446
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
48191
48447
|
}
|
|
48192
48448
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
48193
|
-
const root =
|
|
48449
|
+
const root = join43(tier5SrcDir, bundleName);
|
|
48194
48450
|
const files = {};
|
|
48195
48451
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
48196
48452
|
const walk2 = (abs, rel) => {
|
|
@@ -48198,16 +48454,16 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
|
48198
48454
|
if (visitedDirs.has(real)) return;
|
|
48199
48455
|
visitedDirs.add(real);
|
|
48200
48456
|
for (const name of readdirSync21(abs).sort()) {
|
|
48201
|
-
const childAbs =
|
|
48457
|
+
const childAbs = join43(abs, name);
|
|
48202
48458
|
const childRel = posix.join(rel, name);
|
|
48203
|
-
if (
|
|
48459
|
+
if (statSync8(childAbs).isDirectory()) {
|
|
48204
48460
|
walk2(childAbs, childRel);
|
|
48205
48461
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
48206
|
-
files[childRel] =
|
|
48462
|
+
files[childRel] = readFileSync50(childAbs, "utf8");
|
|
48207
48463
|
}
|
|
48208
48464
|
}
|
|
48209
48465
|
};
|
|
48210
|
-
if (!
|
|
48466
|
+
if (!existsSync43(root)) return null;
|
|
48211
48467
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
48212
48468
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
48213
48469
|
if (!entry) return null;
|
|
@@ -48224,20 +48480,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
48224
48480
|
const spec = m[1];
|
|
48225
48481
|
const virtual = posix.normalize(posix.join(dir, spec));
|
|
48226
48482
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
48227
|
-
const onDisk =
|
|
48483
|
+
const onDisk = join43(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
48228
48484
|
const candidates = [
|
|
48229
48485
|
onDisk,
|
|
48230
48486
|
`${onDisk}.ts`,
|
|
48231
48487
|
`${onDisk}.js`,
|
|
48232
48488
|
onDisk.replace(/\.js$/, ".ts"),
|
|
48233
|
-
|
|
48234
|
-
|
|
48489
|
+
join43(onDisk, "index.ts"),
|
|
48490
|
+
join43(onDisk, "index.js")
|
|
48235
48491
|
];
|
|
48236
48492
|
for (const abs of candidates) {
|
|
48237
|
-
if (!
|
|
48238
|
-
const key2 = `/tier5-src/${
|
|
48493
|
+
if (!existsSync43(abs) || statSync8(abs).isDirectory()) continue;
|
|
48494
|
+
const key2 = `/tier5-src/${relative6(tier5SrcDir, abs).split(sep9).join(posix.sep)}`;
|
|
48239
48495
|
if (key2 in files) break;
|
|
48240
|
-
files[key2] =
|
|
48496
|
+
files[key2] = readFileSync50(abs, "utf8");
|
|
48241
48497
|
queue.push(key2);
|
|
48242
48498
|
break;
|
|
48243
48499
|
}
|
|
@@ -48269,10 +48525,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
48269
48525
|
for (const source of Object.values(files)) visit(source);
|
|
48270
48526
|
return { modules, unsupported };
|
|
48271
48527
|
}
|
|
48272
|
-
function sdkSubpathReader(
|
|
48528
|
+
function sdkSubpathReader(resolve42) {
|
|
48273
48529
|
return (sub) => {
|
|
48274
48530
|
try {
|
|
48275
|
-
return
|
|
48531
|
+
return readFileSync50(resolve42(`@wix/himalaya/${sub}`), "utf8");
|
|
48276
48532
|
} catch {
|
|
48277
48533
|
return null;
|
|
48278
48534
|
}
|
|
@@ -48353,7 +48609,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
48353
48609
|
const token = mintToken2(payload);
|
|
48354
48610
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
48355
48611
|
if (unusable) throw new Error(unusable);
|
|
48356
|
-
return await new Promise((
|
|
48612
|
+
return await new Promise((resolve42, reject) => {
|
|
48357
48613
|
let settled = false;
|
|
48358
48614
|
let url = "";
|
|
48359
48615
|
const server = createServer3();
|
|
@@ -48405,7 +48661,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
48405
48661
|
}
|
|
48406
48662
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
48407
48663
|
const report = body.result;
|
|
48408
|
-
finish2(() =>
|
|
48664
|
+
finish2(() => resolve42({ report, url }));
|
|
48409
48665
|
})();
|
|
48410
48666
|
});
|
|
48411
48667
|
server.on("error", (e) => finish2(() => reject(e)));
|
|
@@ -48443,11 +48699,15 @@ __export(coverage_exports, {
|
|
|
48443
48699
|
diffAndStoreObservations: () => diffAndStoreObservations,
|
|
48444
48700
|
formatDelta: () => formatDelta,
|
|
48445
48701
|
formatLedger: () => formatLedger,
|
|
48702
|
+
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
48446
48703
|
trendAndStore: () => trendAndStore
|
|
48447
48704
|
});
|
|
48448
|
-
import { existsSync as
|
|
48449
|
-
import { dirname as
|
|
48450
|
-
function
|
|
48705
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync21, readFileSync as readFileSync51, writeFileSync as writeFileSync18 } from "node:fs";
|
|
48706
|
+
import { dirname as dirname26, join as join44 } from "node:path";
|
|
48707
|
+
function suppressedNativeKeys(oracle) {
|
|
48708
|
+
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
48709
|
+
}
|
|
48710
|
+
function assembleLedger(r, options = {}) {
|
|
48451
48711
|
const out = [];
|
|
48452
48712
|
for (const c of r.crawled ?? []) {
|
|
48453
48713
|
const noRow = (c.actionsSkipped ?? []).filter((s) => s.why === "no-row-value");
|
|
@@ -48569,8 +48829,9 @@ function assembleLedger(r) {
|
|
|
48569
48829
|
remedy: "npx playwright install chromium (~170MB, one time) \u2014 then every himi test writes a PNG per screen to .himi/shots/"
|
|
48570
48830
|
});
|
|
48571
48831
|
}
|
|
48832
|
+
const oracle = options.nativeOracle ?? nativeOracleShipped();
|
|
48572
48833
|
const nativeIos = r.nativeDecode?.ios;
|
|
48573
|
-
if (!nativeIos || "unavailable" in nativeIos) {
|
|
48834
|
+
if (oracle.ios && (!nativeIos || "unavailable" in nativeIos)) {
|
|
48574
48835
|
const reason = nativeIos && "unavailable" in nativeIos ? ` (${nativeIos.reason})` : "";
|
|
48575
48836
|
out.push({
|
|
48576
48837
|
key: "native-decode|ios",
|
|
@@ -48581,7 +48842,7 @@ function assembleLedger(r) {
|
|
|
48581
48842
|
});
|
|
48582
48843
|
}
|
|
48583
48844
|
const nativeAndroid = r.nativeDecode?.android;
|
|
48584
|
-
if (!nativeAndroid || "unavailable" in nativeAndroid) {
|
|
48845
|
+
if (oracle.android && (!nativeAndroid || "unavailable" in nativeAndroid)) {
|
|
48585
48846
|
const reason = nativeAndroid && "unavailable" in nativeAndroid ? ` (${nativeAndroid.reason})` : "";
|
|
48586
48847
|
out.push({
|
|
48587
48848
|
key: "native-decode|android",
|
|
@@ -48611,30 +48872,32 @@ function assembleLedger(r) {
|
|
|
48611
48872
|
}
|
|
48612
48873
|
return out;
|
|
48613
48874
|
}
|
|
48614
|
-
function trendAndStore(dir, entries) {
|
|
48615
|
-
const p =
|
|
48875
|
+
function trendAndStore(dir, entries, suppressed) {
|
|
48876
|
+
const p = join44(dir, LEDGER_FILE);
|
|
48616
48877
|
let previous = null;
|
|
48617
48878
|
try {
|
|
48618
|
-
if (
|
|
48619
|
-
const parsed = JSON.parse(
|
|
48879
|
+
if (existsSync44(p)) {
|
|
48880
|
+
const parsed = JSON.parse(readFileSync51(p, "utf8"));
|
|
48620
48881
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
48621
48882
|
}
|
|
48622
48883
|
} catch {
|
|
48623
48884
|
}
|
|
48624
48885
|
const current = entries.map((e) => e.key);
|
|
48886
|
+
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
48625
48887
|
try {
|
|
48626
|
-
mkdirSync21(
|
|
48627
|
-
writeFileSync18(p, JSON.stringify({ keys:
|
|
48888
|
+
mkdirSync21(dirname26(p), { recursive: true });
|
|
48889
|
+
writeFileSync18(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
48628
48890
|
} catch {
|
|
48629
48891
|
return null;
|
|
48630
48892
|
}
|
|
48631
48893
|
if (previous === null) return { opened: 0, closed: 0 };
|
|
48632
|
-
const
|
|
48894
|
+
const baseline = previous.filter((key2) => !(suppressed ?? []).includes(key2));
|
|
48895
|
+
const prev = new Set(baseline);
|
|
48633
48896
|
const cur = new Set(current);
|
|
48634
48897
|
return {
|
|
48635
48898
|
opened: current.filter((k) => !prev.has(k)).length,
|
|
48636
|
-
closed:
|
|
48637
|
-
previousTotal:
|
|
48899
|
+
closed: baseline.filter((k) => !cur.has(k)).length,
|
|
48900
|
+
previousTotal: baseline.length
|
|
48638
48901
|
};
|
|
48639
48902
|
}
|
|
48640
48903
|
function formatLedger(entries, trend) {
|
|
@@ -48653,11 +48916,11 @@ function formatLedger(entries, trend) {
|
|
|
48653
48916
|
return out.join("\n");
|
|
48654
48917
|
}
|
|
48655
48918
|
function diffAndStoreObservations(dir, current) {
|
|
48656
|
-
const p =
|
|
48919
|
+
const p = join44(dir, OBS_FILE);
|
|
48657
48920
|
let previous = null;
|
|
48658
48921
|
try {
|
|
48659
|
-
if (
|
|
48660
|
-
const parsed = JSON.parse(
|
|
48922
|
+
if (existsSync44(p)) {
|
|
48923
|
+
const parsed = JSON.parse(readFileSync51(p, "utf8"));
|
|
48661
48924
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
48662
48925
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
48663
48926
|
)) {
|
|
@@ -48667,7 +48930,7 @@ function diffAndStoreObservations(dir, current) {
|
|
|
48667
48930
|
} catch {
|
|
48668
48931
|
}
|
|
48669
48932
|
try {
|
|
48670
|
-
mkdirSync21(
|
|
48933
|
+
mkdirSync21(dirname26(p), { recursive: true });
|
|
48671
48934
|
writeFileSync18(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
48672
48935
|
} catch {
|
|
48673
48936
|
return null;
|
|
@@ -48705,8 +48968,9 @@ function formatDelta(delta) {
|
|
|
48705
48968
|
var LEDGER_FILE, OBS_FILE;
|
|
48706
48969
|
var init_coverage = __esm({
|
|
48707
48970
|
"src/coverage.ts"() {
|
|
48708
|
-
|
|
48709
|
-
|
|
48971
|
+
init_native_decode();
|
|
48972
|
+
LEDGER_FILE = join44(".himi", "test-ledger.json");
|
|
48973
|
+
OBS_FILE = join44(".himi", "test-observations.json");
|
|
48710
48974
|
}
|
|
48711
48975
|
});
|
|
48712
48976
|
|
|
@@ -48719,11 +48983,11 @@ __export(assets_exports, {
|
|
|
48719
48983
|
removeAssetPayload: () => removeAssetPayload,
|
|
48720
48984
|
verifyReport: () => verifyReport
|
|
48721
48985
|
});
|
|
48722
|
-
import { readFileSync as
|
|
48986
|
+
import { readFileSync as readFileSync52 } from "node:fs";
|
|
48723
48987
|
import { basename as basename8 } from "node:path";
|
|
48724
48988
|
function declaredAssets(dir) {
|
|
48725
48989
|
return collectAssets(dir).map((a) => {
|
|
48726
|
-
const bytes2 =
|
|
48990
|
+
const bytes2 = readFileSync52(a.path);
|
|
48727
48991
|
return {
|
|
48728
48992
|
name: a.name,
|
|
48729
48993
|
sha256: assetSha256(bytes2),
|
|
@@ -48799,7 +49063,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
48799
49063
|
};
|
|
48800
49064
|
}
|
|
48801
49065
|
function addAssetPayload(manifest, filePath, opts) {
|
|
48802
|
-
const bytes2 =
|
|
49066
|
+
const bytes2 = readFileSync52(filePath);
|
|
48803
49067
|
const name = opts.name ?? basename8(filePath);
|
|
48804
49068
|
const sha2565 = assetSha256(bytes2);
|
|
48805
49069
|
const record2 = {
|
|
@@ -50213,9 +50477,9 @@ __export(run_exports, {
|
|
|
50213
50477
|
runPackage: () => runPackage,
|
|
50214
50478
|
withoutProdServe: () => withoutProdServe
|
|
50215
50479
|
});
|
|
50216
|
-
import { cpSync, existsSync as
|
|
50480
|
+
import { cpSync, existsSync as existsSync45, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync3, readFileSync as readFileSync53, rmSync as rmSync8, statSync as statSync9 } from "node:fs";
|
|
50217
50481
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
50218
|
-
import { join as
|
|
50482
|
+
import { join as join45 } from "node:path";
|
|
50219
50483
|
import { spawn as spawn3 } from "node:child_process";
|
|
50220
50484
|
function makePackageRunHandler(opts) {
|
|
50221
50485
|
return makeRunHandler({
|
|
@@ -50233,9 +50497,9 @@ async function fetchBytes(url) {
|
|
|
50233
50497
|
}
|
|
50234
50498
|
async function resolvePackage(source, workDir) {
|
|
50235
50499
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
50236
|
-
if (!isUrl2 &&
|
|
50237
|
-
const appDirManifest =
|
|
50238
|
-
if (
|
|
50500
|
+
if (!isUrl2 && existsSync45(source) && statSync9(source).isDirectory()) {
|
|
50501
|
+
const appDirManifest = join45(source, "release-manifest.json");
|
|
50502
|
+
if (existsSync45(appDirManifest)) {
|
|
50239
50503
|
const opened2 = openPackageDir(source);
|
|
50240
50504
|
if (!opened2.validation.ok) {
|
|
50241
50505
|
throw new Error(`package is not valid:
|
|
@@ -50244,9 +50508,9 @@ async function resolvePackage(source, workDir) {
|
|
|
50244
50508
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
50245
50509
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
50246
50510
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
50247
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
50248
|
-
const target =
|
|
50249
|
-
if (
|
|
50511
|
+
const root2 = workDir ?? mkdtempSync3(join45(tmpdir4(), "himi-run-"));
|
|
50512
|
+
const target = join45(root2, app2);
|
|
50513
|
+
if (join45(source) !== target) {
|
|
50250
50514
|
mkdirSync22(root2, { recursive: true });
|
|
50251
50515
|
rmSync8(target, { recursive: true, force: true });
|
|
50252
50516
|
cpSync(source, target, { recursive: true });
|
|
@@ -50263,8 +50527,8 @@ async function resolvePackage(source, workDir) {
|
|
|
50263
50527
|
}
|
|
50264
50528
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
50265
50529
|
}
|
|
50266
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
50267
|
-
const root = workDir ?? mkdtempSync3(
|
|
50530
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync53(source);
|
|
50531
|
+
const root = workDir ?? mkdtempSync3(join45(tmpdir4(), "himi-run-"));
|
|
50268
50532
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
50269
50533
|
const opened = openPackageDir(appDir2);
|
|
50270
50534
|
if (!opened.validation.ok) {
|
|
@@ -50364,19 +50628,19 @@ __export(run_browser_exports, {
|
|
|
50364
50628
|
runInBrowser: () => runInBrowser
|
|
50365
50629
|
});
|
|
50366
50630
|
import { createServer as createServer5 } from "node:http";
|
|
50367
|
-
import { existsSync as
|
|
50631
|
+
import { existsSync as existsSync46, readFileSync as readFileSync54 } from "node:fs";
|
|
50368
50632
|
import { spawnSync as spawnSync3, execFile as execFile3 } from "node:child_process";
|
|
50369
|
-
import { dirname as
|
|
50633
|
+
import { dirname as dirname27, resolve as resolve37 } from "node:path";
|
|
50370
50634
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
50371
50635
|
function stagedDir() {
|
|
50372
|
-
return process.env.HIMI_BROWSER_PLANE_OUT ?
|
|
50636
|
+
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve37(process.env.HIMI_BROWSER_PLANE_OUT) : resolve37(REPO, "packages", "serve", "dist", "browser-plane");
|
|
50373
50637
|
}
|
|
50374
50638
|
function missingStaged() {
|
|
50375
|
-
return [...SERVED].filter((f) => !
|
|
50639
|
+
return [...SERVED].filter((f) => !existsSync46(resolve37(stagedDir(), f))).sort();
|
|
50376
50640
|
}
|
|
50377
50641
|
function ensureBrowserPlaneStaged() {
|
|
50378
50642
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
50379
|
-
const r = spawnSync3(process.execPath, [
|
|
50643
|
+
const r = spawnSync3(process.execPath, [resolve37(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
|
|
50380
50644
|
cwd: REPO,
|
|
50381
50645
|
encoding: "utf8"
|
|
50382
50646
|
});
|
|
@@ -50462,7 +50726,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
50462
50726
|
}
|
|
50463
50727
|
const name = path === "/" || path === "/index.html" ? "host.html" : path.slice(1);
|
|
50464
50728
|
if (SERVED.has(name)) {
|
|
50465
|
-
if (!
|
|
50729
|
+
if (!existsSync46(resolve37(stagedDir(), name))) {
|
|
50466
50730
|
const restaged = ensureBrowserPlaneStaged();
|
|
50467
50731
|
if (!restaged.ok) {
|
|
50468
50732
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -50472,7 +50736,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
50472
50736
|
}
|
|
50473
50737
|
let bytes2;
|
|
50474
50738
|
try {
|
|
50475
|
-
bytes2 =
|
|
50739
|
+
bytes2 = readFileSync54(resolve37(stagedDir(), name));
|
|
50476
50740
|
} catch (e) {
|
|
50477
50741
|
res.writeHead(503, { "content-type": "application/json" });
|
|
50478
50742
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -50515,8 +50779,8 @@ var HERE, REPO, SERVED;
|
|
|
50515
50779
|
var init_run_browser = __esm({
|
|
50516
50780
|
"src/run-browser.ts"() {
|
|
50517
50781
|
init_file_store();
|
|
50518
|
-
HERE =
|
|
50519
|
-
REPO =
|
|
50782
|
+
HERE = dirname27(fileURLToPath20(import.meta.url));
|
|
50783
|
+
REPO = resolve37(HERE, "..", "..", "..");
|
|
50520
50784
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
50521
50785
|
}
|
|
50522
50786
|
});
|
|
@@ -50890,11 +51154,11 @@ __export(preflight_exports, {
|
|
|
50890
51154
|
parseStoreConfig: () => parseStoreConfig,
|
|
50891
51155
|
requireEnv: () => requireEnv
|
|
50892
51156
|
});
|
|
50893
|
-
import { existsSync as
|
|
50894
|
-
import { isAbsolute as
|
|
51157
|
+
import { existsSync as existsSync47, readFileSync as readFileSync55 } from "node:fs";
|
|
51158
|
+
import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve38 } from "node:path";
|
|
50895
51159
|
function isInsideRepo(p) {
|
|
50896
|
-
const rel =
|
|
50897
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
51160
|
+
const rel = relative7(REPO_ROOT3, resolve38(p));
|
|
51161
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute3(rel);
|
|
50898
51162
|
}
|
|
50899
51163
|
function assertCredentialOutsideRepo(label2, p) {
|
|
50900
51164
|
if (isInsideRepo(p)) {
|
|
@@ -50923,7 +51187,7 @@ function scalar2(v) {
|
|
|
50923
51187
|
}
|
|
50924
51188
|
function parseStoreConfig(text2) {
|
|
50925
51189
|
const cfg = {};
|
|
50926
|
-
let
|
|
51190
|
+
let section2 = null;
|
|
50927
51191
|
for (const raw of text2.split("\n")) {
|
|
50928
51192
|
const line = strip2(raw);
|
|
50929
51193
|
if (!line.trim()) continue;
|
|
@@ -50933,24 +51197,24 @@ function parseStoreConfig(text2) {
|
|
|
50933
51197
|
const [, key2, rest] = kv;
|
|
50934
51198
|
if (!indented) {
|
|
50935
51199
|
if (rest.trim() === "") {
|
|
50936
|
-
|
|
50937
|
-
cfg[key2] =
|
|
51200
|
+
section2 = {};
|
|
51201
|
+
cfg[key2] = section2;
|
|
50938
51202
|
} else {
|
|
50939
|
-
|
|
51203
|
+
section2 = null;
|
|
50940
51204
|
cfg[key2] = scalar2(rest);
|
|
50941
51205
|
}
|
|
50942
|
-
} else if (
|
|
50943
|
-
|
|
51206
|
+
} else if (section2) {
|
|
51207
|
+
section2[key2] = scalar2(rest);
|
|
50944
51208
|
}
|
|
50945
51209
|
}
|
|
50946
51210
|
return cfg;
|
|
50947
51211
|
}
|
|
50948
51212
|
function loadStoreConfig(app) {
|
|
50949
51213
|
const p = storeConfigPath(app);
|
|
50950
|
-
if (!
|
|
51214
|
+
if (!existsSync47(p)) {
|
|
50951
51215
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
50952
51216
|
}
|
|
50953
|
-
return parseStoreConfig(
|
|
51217
|
+
return parseStoreConfig(readFileSync55(p, "utf8"));
|
|
50954
51218
|
}
|
|
50955
51219
|
var init_preflight = __esm({
|
|
50956
51220
|
"../store-release/preflight.ts"() {
|
|
@@ -50973,9 +51237,9 @@ __export(preflight_app_exports, {
|
|
|
50973
51237
|
pngSize: () => pngSize,
|
|
50974
51238
|
preflightApp: () => preflightApp
|
|
50975
51239
|
});
|
|
50976
|
-
import { readFileSync as
|
|
51240
|
+
import { readFileSync as readFileSync56, existsSync as existsSync48, readdirSync as readdirSync22, statSync as statSync10 } from "node:fs";
|
|
50977
51241
|
import { createHash as createHash23 } from "node:crypto";
|
|
50978
|
-
import { join as
|
|
51242
|
+
import { join as join46 } from "node:path";
|
|
50979
51243
|
function analyze(projectYml, storeConfig, icon) {
|
|
50980
51244
|
const f = [];
|
|
50981
51245
|
const has = (re, s) => re.test(s);
|
|
@@ -51023,10 +51287,10 @@ function analyze(projectYml, storeConfig, icon) {
|
|
|
51023
51287
|
return f;
|
|
51024
51288
|
}
|
|
51025
51289
|
async function preflightApp(app) {
|
|
51026
|
-
const projectYml =
|
|
51027
|
-
const storeConfig =
|
|
51290
|
+
const projectYml = existsSync48(iosProjectYml(app)) ? readFileSync56(iosProjectYml(app), "utf8") : "";
|
|
51291
|
+
const storeConfig = existsSync48(storeConfigPath(app)) ? readFileSync56(storeConfigPath(app), "utf8") : "";
|
|
51028
51292
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
51029
|
-
const findings = analyze(projectYml, storeConfig, await appIconState(
|
|
51293
|
+
const findings = analyze(projectYml, storeConfig, await appIconState(join46(appDir(app), "ios")));
|
|
51030
51294
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
51031
51295
|
findings.push(
|
|
51032
51296
|
...analyzePlayListing(playListingAssets(app)).map((finding) => ({ ...finding, level: "warn" }))
|
|
@@ -51053,17 +51317,17 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
51053
51317
|
return f;
|
|
51054
51318
|
}
|
|
51055
51319
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
51056
|
-
const root =
|
|
51320
|
+
const root = join46(storeDir(app), "metadata");
|
|
51057
51321
|
const out = /* @__PURE__ */ new Set();
|
|
51058
|
-
if (
|
|
51322
|
+
if (existsSync48(root)) {
|
|
51059
51323
|
for (const n of readdirSync22(root)) if (n.endsWith(".txt")) out.add(n);
|
|
51060
51324
|
}
|
|
51061
|
-
if (
|
|
51325
|
+
if (existsSync48(join46(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
51062
51326
|
return out;
|
|
51063
51327
|
}
|
|
51064
51328
|
function reviewInfoFiles(app) {
|
|
51065
|
-
const dir =
|
|
51066
|
-
if (!
|
|
51329
|
+
const dir = join46(storeDir(app), "review_information");
|
|
51330
|
+
if (!existsSync48(dir)) return /* @__PURE__ */ new Set();
|
|
51067
51331
|
return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
|
|
51068
51332
|
}
|
|
51069
51333
|
function isValidAppStoreSize(w, h) {
|
|
@@ -51173,12 +51437,12 @@ function analyzePlayListing(assets) {
|
|
|
51173
51437
|
return f;
|
|
51174
51438
|
}
|
|
51175
51439
|
function playListingAssets(app, locale = "en-US") {
|
|
51176
|
-
const dir =
|
|
51440
|
+
const dir = join46(storeDir(app), "play", locale, "images");
|
|
51177
51441
|
const read = (names) => {
|
|
51178
51442
|
for (const name of names) {
|
|
51179
|
-
const p =
|
|
51443
|
+
const p = join46(dir, name);
|
|
51180
51444
|
try {
|
|
51181
|
-
if (
|
|
51445
|
+
if (statSync10(p).isFile()) return { name, bytes: readFileSync56(p) };
|
|
51182
51446
|
} catch {
|
|
51183
51447
|
}
|
|
51184
51448
|
}
|
|
@@ -51209,26 +51473,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
51209
51473
|
return f;
|
|
51210
51474
|
}
|
|
51211
51475
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
51212
|
-
const dir =
|
|
51213
|
-
if (!
|
|
51476
|
+
const dir = join46(storeDir(app), "metadata", locale);
|
|
51477
|
+
if (!existsSync48(dir)) return /* @__PURE__ */ new Set();
|
|
51214
51478
|
return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
|
|
51215
51479
|
}
|
|
51216
51480
|
function listScreenshots(app, locale = "en-US") {
|
|
51217
51481
|
const out = [];
|
|
51218
|
-
const flat =
|
|
51219
|
-
if (
|
|
51482
|
+
const flat = join46(storeDir(app), "screenshots", locale);
|
|
51483
|
+
if (existsSync48(flat)) {
|
|
51220
51484
|
for (const png of readdirSync22(flat).filter((n) => n.endsWith(".png"))) {
|
|
51221
|
-
const sz = pngSize(
|
|
51485
|
+
const sz = pngSize(readFileSync56(join46(flat, png)));
|
|
51222
51486
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
51223
51487
|
}
|
|
51224
51488
|
}
|
|
51225
|
-
const legacy =
|
|
51226
|
-
if (
|
|
51489
|
+
const legacy = join46(storeDir(app), "metadata", locale, "screenshots");
|
|
51490
|
+
if (existsSync48(legacy)) {
|
|
51227
51491
|
for (const deviceDir of readdirSync22(legacy)) {
|
|
51228
|
-
const d =
|
|
51229
|
-
if (!
|
|
51492
|
+
const d = join46(legacy, deviceDir);
|
|
51493
|
+
if (!statSync10(d).isDirectory()) continue;
|
|
51230
51494
|
for (const png of readdirSync22(d).filter((n) => n.endsWith(".png"))) {
|
|
51231
|
-
const sz = pngSize(
|
|
51495
|
+
const sz = pngSize(readFileSync56(join46(d, png)));
|
|
51232
51496
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
51233
51497
|
}
|
|
51234
51498
|
}
|
|
@@ -51236,13 +51500,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
51236
51500
|
return out;
|
|
51237
51501
|
}
|
|
51238
51502
|
function placeholderHashes2() {
|
|
51239
|
-
const templateIos =
|
|
51240
|
-
if (!
|
|
51503
|
+
const templateIos = join46(appDir("_template"), "ios");
|
|
51504
|
+
if (!existsSync48(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
51241
51505
|
for (const target of readdirSync22(templateIos)) {
|
|
51242
|
-
const p =
|
|
51506
|
+
const p = join46(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
51243
51507
|
try {
|
|
51244
|
-
if (!
|
|
51245
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(
|
|
51508
|
+
if (!statSync10(p).isFile()) continue;
|
|
51509
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync56(p)).digest("hex")];
|
|
51246
51510
|
} catch {
|
|
51247
51511
|
}
|
|
51248
51512
|
}
|
|
@@ -51273,12 +51537,12 @@ async function pixelIssues(bytes2) {
|
|
|
51273
51537
|
}
|
|
51274
51538
|
}
|
|
51275
51539
|
async function appIconState(iosDir) {
|
|
51276
|
-
if (!
|
|
51540
|
+
if (!existsSync48(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
51277
51541
|
for (const target of readdirSync22(iosDir)) {
|
|
51278
|
-
const p =
|
|
51542
|
+
const p = join46(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
51279
51543
|
try {
|
|
51280
|
-
if (!
|
|
51281
|
-
const bytes2 =
|
|
51544
|
+
if (!statSync10(p).isFile()) continue;
|
|
51545
|
+
const bytes2 = readFileSync56(p);
|
|
51282
51546
|
const hash = createHash23("sha256").update(bytes2).digest("hex");
|
|
51283
51547
|
const pixels = await pixelIssues(bytes2);
|
|
51284
51548
|
return {
|
|
@@ -51348,14 +51612,14 @@ __export(credential_profile_exports, {
|
|
|
51348
51612
|
profilePath: () => profilePath,
|
|
51349
51613
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
51350
51614
|
});
|
|
51351
|
-
import { existsSync as
|
|
51615
|
+
import { existsSync as existsSync49, readFileSync as readFileSync57 } from "node:fs";
|
|
51352
51616
|
import { homedir as homedir6 } from "node:os";
|
|
51353
|
-
import { join as
|
|
51617
|
+
import { join as join47 } from "node:path";
|
|
51354
51618
|
function credentialsDir(home = homedir6()) {
|
|
51355
|
-
return
|
|
51619
|
+
return join47(home, ".himalaya", "store-credentials");
|
|
51356
51620
|
}
|
|
51357
51621
|
function profilePath(name, home = homedir6()) {
|
|
51358
|
-
return
|
|
51622
|
+
return join47(credentialsDir(home), `${name}.json`);
|
|
51359
51623
|
}
|
|
51360
51624
|
function parseProfile(text2, label2) {
|
|
51361
51625
|
let doc;
|
|
@@ -51382,8 +51646,8 @@ function resolveStoreCredentials(opts) {
|
|
|
51382
51646
|
const { app, cfg } = opts;
|
|
51383
51647
|
const env = opts.env ?? process.env;
|
|
51384
51648
|
const home = opts.home ?? homedir6();
|
|
51385
|
-
const read = opts.readProfile ?? ((p) =>
|
|
51386
|
-
const exists = opts.profileExists ??
|
|
51649
|
+
const read = opts.readProfile ?? ((p) => readFileSync57(p, "utf8"));
|
|
51650
|
+
const exists = opts.profileExists ?? existsSync49;
|
|
51387
51651
|
const ios = cfg.ios ?? {};
|
|
51388
51652
|
const flagName = opts.profileFlag?.trim();
|
|
51389
51653
|
const named = flagName || ios.credentialProfile?.trim();
|
|
@@ -51457,7 +51721,7 @@ __export(version_exports, {
|
|
|
51457
51721
|
setAndroidVersion: () => setAndroidVersion,
|
|
51458
51722
|
setIosVersion: () => setIosVersion
|
|
51459
51723
|
});
|
|
51460
|
-
import { readFileSync as
|
|
51724
|
+
import { readFileSync as readFileSync58, writeFileSync as writeFileSync19 } from "node:fs";
|
|
51461
51725
|
function readIosVersion(projectYml) {
|
|
51462
51726
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
51463
51727
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -51515,8 +51779,8 @@ function setAndroidVersion(gradle, v) {
|
|
|
51515
51779
|
function bumpVersion(app, opts) {
|
|
51516
51780
|
const iosPath = iosProjectYml(app);
|
|
51517
51781
|
const gradlePath = androidGradle(app);
|
|
51518
|
-
const iosYml =
|
|
51519
|
-
const gradle =
|
|
51782
|
+
const iosYml = readFileSync58(iosPath, "utf8");
|
|
51783
|
+
const gradle = readFileSync58(gradlePath, "utf8");
|
|
51520
51784
|
const current = readIosVersion(iosYml);
|
|
51521
51785
|
const next = {
|
|
51522
51786
|
marketing: opts.marketing ?? current.marketing,
|
|
@@ -51533,7 +51797,7 @@ var init_version = __esm({
|
|
|
51533
51797
|
});
|
|
51534
51798
|
|
|
51535
51799
|
// ../store-release/register-bundle.ts
|
|
51536
|
-
import { readFileSync as
|
|
51800
|
+
import { readFileSync as readFileSync59 } from "node:fs";
|
|
51537
51801
|
import { createPrivateKey, sign } from "node:crypto";
|
|
51538
51802
|
function b64url2(b) {
|
|
51539
51803
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -51551,7 +51815,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
51551
51815
|
async function registerBundleId(opts) {
|
|
51552
51816
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
51553
51817
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
51554
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
51818
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync59(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
51555
51819
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
51556
51820
|
method: "POST",
|
|
51557
51821
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -51605,7 +51869,7 @@ __export(asc_status_exports, {
|
|
|
51605
51869
|
ascStatus: () => ascStatus,
|
|
51606
51870
|
buildVerdict: () => buildVerdict
|
|
51607
51871
|
});
|
|
51608
|
-
import { readFileSync as
|
|
51872
|
+
import { readFileSync as readFileSync60 } from "node:fs";
|
|
51609
51873
|
function buildVerdict(builds) {
|
|
51610
51874
|
if (!builds.length) {
|
|
51611
51875
|
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).";
|
|
@@ -51619,7 +51883,7 @@ function buildVerdict(builds) {
|
|
|
51619
51883
|
function client2(creds) {
|
|
51620
51884
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
51621
51885
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
51622
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
51886
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync60(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
51623
51887
|
return async (path) => {
|
|
51624
51888
|
const r = await fetch(`${ASC}${path}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
51625
51889
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -53635,11 +53899,11 @@ function suggestKeys(args) {
|
|
|
53635
53899
|
if (rule.tab && allowed2(rule) && rule.re.test(label2)) set(rule.tab, label2);
|
|
53636
53900
|
}
|
|
53637
53901
|
}
|
|
53638
|
-
for (const
|
|
53902
|
+
for (const section2 of sections) {
|
|
53639
53903
|
for (const rule of KEY_RULES) {
|
|
53640
|
-
if (!allowed2(rule) || !rule.re.test(
|
|
53641
|
-
set(rule.title,
|
|
53642
|
-
if (
|
|
53904
|
+
if (!allowed2(rule) || !rule.re.test(section2.heading)) continue;
|
|
53905
|
+
set(rule.title, section2.heading);
|
|
53906
|
+
if (section2.body) set(rule.subtitle, section2.body);
|
|
53643
53907
|
}
|
|
53644
53908
|
}
|
|
53645
53909
|
if (tagline) set("home.onboardingBody", tagline.text);
|
|
@@ -53672,12 +53936,12 @@ function buildCopyChapter(args) {
|
|
|
53672
53936
|
pageUrl: page.url
|
|
53673
53937
|
}))
|
|
53674
53938
|
);
|
|
53675
|
-
for (const
|
|
53939
|
+
for (const section2 of candidates) {
|
|
53676
53940
|
if (faq.length >= CAP.faq) break;
|
|
53677
|
-
if (!
|
|
53678
|
-
if (about &&
|
|
53679
|
-
if (faq.some((f) => f.q.toLowerCase() ===
|
|
53680
|
-
faq.push({ q:
|
|
53941
|
+
if (!section2.heading || !section2.body || !/\?\s*$/.test(section2.heading)) continue;
|
|
53942
|
+
if (about && section2.body === about) continue;
|
|
53943
|
+
if (faq.some((f) => f.q.toLowerCase() === section2.heading.toLowerCase())) continue;
|
|
53944
|
+
faq.push({ q: section2.heading, a: section2.body, pageUrl: section2.pageUrl });
|
|
53681
53945
|
}
|
|
53682
53946
|
}
|
|
53683
53947
|
const testimonials = dedupe2(pages.flatMap((p) => p.testimonials ?? []), CAP.testimonials);
|
|
@@ -54709,10 +54973,10 @@ function isFetchableFontUrl(raw) {
|
|
|
54709
54973
|
return true;
|
|
54710
54974
|
}
|
|
54711
54975
|
function resolveAll(hostname) {
|
|
54712
|
-
return new Promise((
|
|
54976
|
+
return new Promise((resolve42, reject) => {
|
|
54713
54977
|
dnsLookup(hostname, { all: true, verbatim: true }, (err, addresses) => {
|
|
54714
54978
|
if (err) reject(err);
|
|
54715
|
-
else
|
|
54979
|
+
else resolve42(addresses);
|
|
54716
54980
|
});
|
|
54717
54981
|
});
|
|
54718
54982
|
}
|
|
@@ -54720,13 +54984,13 @@ function withAbort(start, signal, what) {
|
|
|
54720
54984
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
54721
54985
|
const work = start();
|
|
54722
54986
|
if (!signal) return work;
|
|
54723
|
-
return new Promise((
|
|
54987
|
+
return new Promise((resolve42, reject) => {
|
|
54724
54988
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
54725
54989
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
54726
|
-
work.then(
|
|
54990
|
+
work.then(resolve42, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
54727
54991
|
});
|
|
54728
54992
|
}
|
|
54729
|
-
async function pinAddress(url,
|
|
54993
|
+
async function pinAddress(url, resolve42 = resolveAll, signal) {
|
|
54730
54994
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
54731
54995
|
if (ipv4Octets(host)) {
|
|
54732
54996
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -54736,7 +55000,7 @@ async function pinAddress(url, resolve41 = resolveAll, signal) {
|
|
|
54736
55000
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
54737
55001
|
return { address: host, family: 6 };
|
|
54738
55002
|
}
|
|
54739
|
-
const addresses = await withAbort(() =>
|
|
55003
|
+
const addresses = await withAbort(() => resolve42(host), signal, `${host} lookup`);
|
|
54740
55004
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
54741
55005
|
const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
|
|
54742
55006
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -54759,7 +55023,7 @@ function decodedBody(res, hasBody) {
|
|
|
54759
55023
|
return out;
|
|
54760
55024
|
}
|
|
54761
55025
|
function requestOnce(url, pinned, init) {
|
|
54762
|
-
return new Promise((
|
|
55026
|
+
return new Promise((resolve42, reject) => {
|
|
54763
55027
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
54764
55028
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
54765
55029
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -54793,7 +55057,7 @@ function requestOnce(url, pinned, init) {
|
|
|
54793
55057
|
reject(err);
|
|
54794
55058
|
return;
|
|
54795
55059
|
}
|
|
54796
|
-
|
|
55060
|
+
resolve42(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out }));
|
|
54797
55061
|
}
|
|
54798
55062
|
);
|
|
54799
55063
|
req.on("error", reject);
|
|
@@ -54902,7 +55166,7 @@ var init_brand_font = __esm({
|
|
|
54902
55166
|
|
|
54903
55167
|
// src/site-analyze/write-artifacts.ts
|
|
54904
55168
|
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync20 } from "node:fs";
|
|
54905
|
-
import { join as
|
|
55169
|
+
import { join as join48 } from "node:path";
|
|
54906
55170
|
function attachVeloSources(book, sources, put) {
|
|
54907
55171
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
54908
55172
|
for (const f of book.velo.files) {
|
|
@@ -55057,12 +55321,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
55057
55321
|
}
|
|
55058
55322
|
async function writeBusinessBook(result, opts) {
|
|
55059
55323
|
const out = opts.outDir;
|
|
55060
|
-
mkdirSync23(
|
|
55061
|
-
mkdirSync23(
|
|
55324
|
+
mkdirSync23(join48(out, "evidence/pages"), { recursive: true });
|
|
55325
|
+
mkdirSync23(join48(out, "media/catalog"), { recursive: true });
|
|
55062
55326
|
const files = [];
|
|
55063
55327
|
const put = (rel, body) => {
|
|
55064
|
-
const p =
|
|
55065
|
-
mkdirSync23(
|
|
55328
|
+
const p = join48(out, rel);
|
|
55329
|
+
mkdirSync23(join48(p, ".."), { recursive: true });
|
|
55066
55330
|
writeFileSync20(p, body);
|
|
55067
55331
|
files.push(rel);
|
|
55068
55332
|
};
|
|
@@ -55393,15 +55657,15 @@ var init_home_descriptor = __esm({
|
|
|
55393
55657
|
});
|
|
55394
55658
|
|
|
55395
55659
|
// src/site-analyze/apply.ts
|
|
55396
|
-
import { existsSync as
|
|
55397
|
-
import { dirname as
|
|
55660
|
+
import { existsSync as existsSync50, readFileSync as readFileSync61, writeFileSync as writeFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync24, realpathSync as realpathSync5, statSync as statSync11 } from "node:fs";
|
|
55661
|
+
import { dirname as dirname28, isAbsolute as isAbsolute4, join as join49, resolve as resolve39, sep as sep10 } from "node:path";
|
|
55398
55662
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
55399
55663
|
function unpairedRedirectNote(overlay) {
|
|
55400
55664
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
55401
55665
|
return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
|
|
55402
55666
|
}
|
|
55403
55667
|
function posix2(p) {
|
|
55404
|
-
return
|
|
55668
|
+
return resolve39(p).replace(/\\/g, "/");
|
|
55405
55669
|
}
|
|
55406
55670
|
function committedShellProvisioning(path) {
|
|
55407
55671
|
return committedShellFor(posix2(path));
|
|
@@ -55409,8 +55673,8 @@ function committedShellProvisioning(path) {
|
|
|
55409
55673
|
function findRepoRoot(cwd) {
|
|
55410
55674
|
let dir = cwd;
|
|
55411
55675
|
for (let i = 0; i < 8; i++) {
|
|
55412
|
-
if (SHELL_NAMES2.some((name) =>
|
|
55413
|
-
const next =
|
|
55676
|
+
if (SHELL_NAMES2.some((name) => existsSync50(join49(dir, shellAppDir(name), "package.json")))) return dir;
|
|
55677
|
+
const next = dirname28(dir);
|
|
55414
55678
|
if (next === dir) break;
|
|
55415
55679
|
dir = next;
|
|
55416
55680
|
}
|
|
@@ -55435,7 +55699,7 @@ function assertNotCommitted(path, forbidden) {
|
|
|
55435
55699
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
55436
55700
|
);
|
|
55437
55701
|
}
|
|
55438
|
-
if (forbidden &&
|
|
55702
|
+
if (forbidden && resolve39(path) === resolve39(forbidden)) {
|
|
55439
55703
|
const named = committedShellProvisioning(forbidden);
|
|
55440
55704
|
throw new Error(
|
|
55441
55705
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -55477,24 +55741,24 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
55477
55741
|
}
|
|
55478
55742
|
function buildMergedContract(options) {
|
|
55479
55743
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
55480
|
-
const committedPath =
|
|
55481
|
-
if (!
|
|
55744
|
+
const committedPath = join49(appDir2, "provisioning.json");
|
|
55745
|
+
if (!existsSync50(committedPath)) {
|
|
55482
55746
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
55483
55747
|
}
|
|
55484
|
-
const committed = JSON.parse(
|
|
55748
|
+
const committed = JSON.parse(readFileSync61(committedPath, "utf8"));
|
|
55485
55749
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
55486
55750
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
55487
55751
|
const branding = merged.branding ?? {};
|
|
55488
55752
|
const staged = [];
|
|
55489
55753
|
const contained = (root, rel) => {
|
|
55490
|
-
if (
|
|
55491
|
-
const full =
|
|
55492
|
-
return full.startsWith(
|
|
55754
|
+
if (isAbsolute4(rel)) return void 0;
|
|
55755
|
+
const full = resolve39(root, rel);
|
|
55756
|
+
return full.startsWith(resolve39(root) + sep10) ? full : void 0;
|
|
55493
55757
|
};
|
|
55494
55758
|
const stage = (fromRel, toRel) => {
|
|
55495
55759
|
const from = contained(packageDir, fromRel);
|
|
55496
|
-
const to = contained(
|
|
55497
|
-
if (!from || !to || !
|
|
55760
|
+
const to = contained(join49(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
55761
|
+
if (!from || !to || !existsSync50(from)) return void 0;
|
|
55498
55762
|
let real;
|
|
55499
55763
|
let realRoot;
|
|
55500
55764
|
try {
|
|
@@ -55505,8 +55769,8 @@ function buildMergedContract(options) {
|
|
|
55505
55769
|
}
|
|
55506
55770
|
if (!real.startsWith(realRoot + sep10)) return void 0;
|
|
55507
55771
|
try {
|
|
55508
|
-
if (!
|
|
55509
|
-
mkdirSync24(
|
|
55772
|
+
if (!statSync11(real).isFile()) return void 0;
|
|
55773
|
+
mkdirSync24(dirname28(to), { recursive: true });
|
|
55510
55774
|
copyFileSync3(real, to);
|
|
55511
55775
|
} catch {
|
|
55512
55776
|
return void 0;
|
|
@@ -55516,11 +55780,11 @@ function buildMergedContract(options) {
|
|
|
55516
55780
|
};
|
|
55517
55781
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
55518
55782
|
if (icon) branding.appIconPath = icon;
|
|
55519
|
-
const facesPath =
|
|
55520
|
-
if (
|
|
55783
|
+
const facesPath = join49(packageDir, "media/fonts/faces.json");
|
|
55784
|
+
if (existsSync50(facesPath)) {
|
|
55521
55785
|
let faces = [];
|
|
55522
55786
|
try {
|
|
55523
|
-
const parsed = JSON.parse(
|
|
55787
|
+
const parsed = JSON.parse(readFileSync61(facesPath, "utf8"));
|
|
55524
55788
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
55525
55789
|
} catch {
|
|
55526
55790
|
faces = [];
|
|
@@ -55541,20 +55805,20 @@ function buildMergedContract(options) {
|
|
|
55541
55805
|
merged.branding = branding;
|
|
55542
55806
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
55543
55807
|
`;
|
|
55544
|
-
const path =
|
|
55808
|
+
const path = join49(packageDir, "provisioning.contract.json");
|
|
55545
55809
|
writeFileSync21(path, body);
|
|
55546
|
-
const localPath =
|
|
55547
|
-
mkdirSync24(
|
|
55810
|
+
const localPath = join49(appDir2, LOCAL_CONTRACT_REL);
|
|
55811
|
+
mkdirSync24(dirname28(localPath), { recursive: true });
|
|
55548
55812
|
writeFileSync21(localPath, body);
|
|
55549
55813
|
staged.push(localPath);
|
|
55550
55814
|
return { path, staged };
|
|
55551
55815
|
}
|
|
55552
55816
|
async function applyOverlays(input) {
|
|
55553
|
-
const cwd =
|
|
55817
|
+
const cwd = resolve39(input.cwd);
|
|
55554
55818
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
55555
55819
|
assertKnownShell(shell);
|
|
55556
|
-
const overlay = JSON.parse(
|
|
55557
|
-
const tokens = JSON.parse(
|
|
55820
|
+
const overlay = JSON.parse(readFileSync61(input.overlayPath, "utf8"));
|
|
55821
|
+
const tokens = JSON.parse(readFileSync61(input.tokensPath, "utf8"));
|
|
55558
55822
|
const wrote = [];
|
|
55559
55823
|
const notes = [];
|
|
55560
55824
|
const repoRoot2 = findRepoRoot(cwd);
|
|
@@ -55564,8 +55828,8 @@ async function applyOverlays(input) {
|
|
|
55564
55828
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
55565
55829
|
);
|
|
55566
55830
|
}
|
|
55567
|
-
const appDir2 =
|
|
55568
|
-
const packageDir =
|
|
55831
|
+
const appDir2 = join49(repoRoot2, shellAppDir(shell));
|
|
55832
|
+
const packageDir = dirname28(resolve39(input.overlayPath));
|
|
55569
55833
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
55570
55834
|
wrote.push(...staged);
|
|
55571
55835
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -55586,10 +55850,10 @@ async function applyOverlays(input) {
|
|
|
55586
55850
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
55587
55851
|
};
|
|
55588
55852
|
}
|
|
55589
|
-
const pkgProv =
|
|
55853
|
+
const pkgProv = join49(cwd, "provisioning.json");
|
|
55590
55854
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
55591
|
-
if (
|
|
55592
|
-
const cur = JSON.parse(
|
|
55855
|
+
if (existsSync50(pkgProv)) {
|
|
55856
|
+
const cur = JSON.parse(readFileSync61(pkgProv, "utf8"));
|
|
55593
55857
|
const merged = deepMerge3(cur, overlay);
|
|
55594
55858
|
writeFileSync21(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
55595
55859
|
wrote.push(pkgProv);
|
|
@@ -55597,17 +55861,17 @@ async function applyOverlays(input) {
|
|
|
55597
55861
|
writeFileSync21(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
55598
55862
|
wrote.push(pkgProv);
|
|
55599
55863
|
}
|
|
55600
|
-
const pkgTokens =
|
|
55601
|
-
if (
|
|
55602
|
-
const cur = JSON.parse(
|
|
55864
|
+
const pkgTokens = join49(cwd, "tokens.json");
|
|
55865
|
+
if (existsSync50(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
55866
|
+
const cur = JSON.parse(readFileSync61(pkgTokens, "utf8"));
|
|
55603
55867
|
const merged = deepMerge3(cur, tokens);
|
|
55604
55868
|
writeFileSync21(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
55605
55869
|
wrote.push(pkgTokens);
|
|
55606
55870
|
}
|
|
55607
55871
|
const homeAction = homeRefreshActionId(shell);
|
|
55608
|
-
const homeSrc =
|
|
55609
|
-
if (homeAction &&
|
|
55610
|
-
const prev =
|
|
55872
|
+
const homeSrc = join49(cwd, "dev/index.ts");
|
|
55873
|
+
if (homeAction && existsSync50(homeSrc)) {
|
|
55874
|
+
const prev = readFileSync61(homeSrc, "utf8");
|
|
55611
55875
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
55612
55876
|
let next = patched.src;
|
|
55613
55877
|
if (!patched.foreign && overlay.installedVerticals?.length) {
|
|
@@ -55627,13 +55891,13 @@ async function applyOverlays(input) {
|
|
|
55627
55891
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
55628
55892
|
}
|
|
55629
55893
|
}
|
|
55630
|
-
if (!input.iconPath || !
|
|
55631
|
-
const book = input.iconPath ?
|
|
55894
|
+
if (!input.iconPath || !existsSync50(input.iconPath)) {
|
|
55895
|
+
const book = input.iconPath ? dirname28(dirname28(resolve39(input.iconPath))) : void 0;
|
|
55632
55896
|
notes.push(
|
|
55633
55897
|
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"
|
|
55634
55898
|
);
|
|
55635
55899
|
}
|
|
55636
|
-
if (input.iconPath &&
|
|
55900
|
+
if (input.iconPath && existsSync50(input.iconPath)) {
|
|
55637
55901
|
try {
|
|
55638
55902
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
55639
55903
|
wrote.push(...installed.wrote);
|
|
@@ -56767,13 +57031,13 @@ __export(cli_exports, {
|
|
|
56767
57031
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
56768
57032
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
56769
57033
|
});
|
|
56770
|
-
import { readFileSync as
|
|
56771
|
-
import { resolve as
|
|
57034
|
+
import { readFileSync as readFileSync62 } from "node:fs";
|
|
57035
|
+
import { resolve as resolve40 } from "node:path";
|
|
56772
57036
|
async function runSiteAnalyze(opts) {
|
|
56773
57037
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
56774
57038
|
const assetFetch = opts.fetchImpl ?? pinnedFetch2;
|
|
56775
57039
|
const cwd = opts.cwd ?? process.cwd();
|
|
56776
|
-
const outDir =
|
|
57040
|
+
const outDir = resolve40(cwd, opts.outDir ?? ".himi/business-book");
|
|
56777
57041
|
let ownerAuth;
|
|
56778
57042
|
let msid;
|
|
56779
57043
|
try {
|
|
@@ -56810,9 +57074,9 @@ async function runSiteAnalyze(opts) {
|
|
|
56810
57074
|
if (opts.apply) {
|
|
56811
57075
|
applied = await applyOverlays({
|
|
56812
57076
|
cwd,
|
|
56813
|
-
overlayPath:
|
|
56814
|
-
tokensPath:
|
|
56815
|
-
iconPath:
|
|
57077
|
+
overlayPath: resolve40(outDir, "provisioning.overlay.json"),
|
|
57078
|
+
tokensPath: resolve40(outDir, "tokens.overlay.json"),
|
|
57079
|
+
iconPath: resolve40(outDir, "media/icon.png"),
|
|
56816
57080
|
shell: opts.shell
|
|
56817
57081
|
});
|
|
56818
57082
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -56848,8 +57112,8 @@ async function runSiteFunctionCli(opts) {
|
|
|
56848
57112
|
const token = opts.token ?? await siteToken(msid);
|
|
56849
57113
|
let source;
|
|
56850
57114
|
if (opts.sourcePath) {
|
|
56851
|
-
const p =
|
|
56852
|
-
source =
|
|
57115
|
+
const p = resolve40(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
57116
|
+
source = readFileSync62(p, "utf8");
|
|
56853
57117
|
}
|
|
56854
57118
|
let body;
|
|
56855
57119
|
if (opts.bodyRaw != null) {
|
|
@@ -56900,7 +57164,7 @@ async function accountToken2(spawnImpl = spawn4) {
|
|
|
56900
57164
|
cached2 = fromEnv;
|
|
56901
57165
|
return fromEnv;
|
|
56902
57166
|
}
|
|
56903
|
-
const token = await new Promise((
|
|
57167
|
+
const token = await new Promise((resolve42, reject) => {
|
|
56904
57168
|
let child;
|
|
56905
57169
|
try {
|
|
56906
57170
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -56929,7 +57193,7 @@ async function accountToken2(spawnImpl = spawn4) {
|
|
|
56929
57193
|
const scan = (d) => {
|
|
56930
57194
|
out += String(d);
|
|
56931
57195
|
const m = out.match(TOKEN_RE2);
|
|
56932
|
-
if (m) done(() =>
|
|
57196
|
+
if (m) done(() => resolve42(m[0]));
|
|
56933
57197
|
};
|
|
56934
57198
|
child.stdout?.on("data", scan);
|
|
56935
57199
|
child.stderr?.on("data", scan);
|
|
@@ -57106,7 +57370,7 @@ __export(site_create_exports, {
|
|
|
57106
57370
|
runSiteList: () => runSiteList,
|
|
57107
57371
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
57108
57372
|
});
|
|
57109
|
-
import { existsSync as
|
|
57373
|
+
import { existsSync as existsSync51, readFileSync as readFileSync63, writeFileSync as writeFileSync22 } from "node:fs";
|
|
57110
57374
|
import { resolve as resolvePath2 } from "node:path";
|
|
57111
57375
|
function oauthClientName(projectName) {
|
|
57112
57376
|
return `${projectName} client`;
|
|
@@ -57255,7 +57519,7 @@ async function runSiteCreate(opts) {
|
|
|
57255
57519
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
57256
57520
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
57257
57521
|
}
|
|
57258
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
57522
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync51, readFileSync: readFileSync63, writeFileSync: writeFileSync22 }) {
|
|
57259
57523
|
const msid = binding2.siteId;
|
|
57260
57524
|
const path = resolvePath2(target);
|
|
57261
57525
|
const committed = committedShellProvisioning(path);
|
|
@@ -57589,11 +57853,11 @@ var init_site_oauth_client = __esm({
|
|
|
57589
57853
|
});
|
|
57590
57854
|
|
|
57591
57855
|
// src/cli.ts
|
|
57592
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
57856
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync64, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync52, rmSync as rmSync9, readdirSync as readdirSync23, statSync as statSync12, lstatSync as lstatSync5 } from "node:fs";
|
|
57593
57857
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
57594
57858
|
import { createHash as createHash24 } from "node:crypto";
|
|
57595
57859
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
57596
|
-
import { join as
|
|
57860
|
+
import { join as join50, resolve as resolve41, basename as basename9, dirname as dirname29 } from "node:path";
|
|
57597
57861
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
57598
57862
|
|
|
57599
57863
|
// ../serve-cli/src/client.ts
|
|
@@ -59109,7 +59373,7 @@ async function browserLogin(opts) {
|
|
|
59109
59373
|
const log = opts.log ?? (() => {
|
|
59110
59374
|
});
|
|
59111
59375
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
59112
|
-
return await new Promise((
|
|
59376
|
+
return await new Promise((resolve42, reject) => {
|
|
59113
59377
|
let settled = false;
|
|
59114
59378
|
let loginUrl = "";
|
|
59115
59379
|
const server = createServer();
|
|
@@ -59173,7 +59437,7 @@ async function browserLogin(opts) {
|
|
|
59173
59437
|
return;
|
|
59174
59438
|
}
|
|
59175
59439
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
|
|
59176
|
-
finish2(() =>
|
|
59440
|
+
finish2(() => resolve42({ token, loginUrl }));
|
|
59177
59441
|
});
|
|
59178
59442
|
});
|
|
59179
59443
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -60583,17 +60847,18 @@ init_crawl_layers();
|
|
|
60583
60847
|
// src/ux-audit.ts
|
|
60584
60848
|
init_wix_gateway_rules();
|
|
60585
60849
|
init_mobile_ux_contract();
|
|
60586
|
-
|
|
60587
|
-
|
|
60588
|
-
|
|
60850
|
+
init_ux_evidence();
|
|
60851
|
+
init_ux_evidence();
|
|
60852
|
+
import { existsSync as existsSync22, readFileSync as readFileSync24, readdirSync as readdirSync11 } from "node:fs";
|
|
60853
|
+
import { join as join26, relative as relative4, resolve as resolve16 } from "node:path";
|
|
60589
60854
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".json"]);
|
|
60590
60855
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".himi", "coverage"]);
|
|
60591
60856
|
function issue(issues, strict, code, message, path) {
|
|
60592
60857
|
issues.push({ code, message, ...path ? { path } : {}, severity: strict ? "error" : "warning" });
|
|
60593
60858
|
}
|
|
60594
|
-
function
|
|
60859
|
+
function readText2(path) {
|
|
60595
60860
|
try {
|
|
60596
|
-
return
|
|
60861
|
+
return existsSync22(path) ? readFileSync24(path, "utf8") : null;
|
|
60597
60862
|
} catch {
|
|
60598
60863
|
return null;
|
|
60599
60864
|
}
|
|
@@ -60602,32 +60867,19 @@ function walkSource(dir, root = dir) {
|
|
|
60602
60867
|
const found = [];
|
|
60603
60868
|
for (const entry of readdirSync11(dir, { withFileTypes: true })) {
|
|
60604
60869
|
if (entry.isDirectory()) {
|
|
60605
|
-
if (!IGNORED_DIRECTORIES.has(entry.name)) found.push(...walkSource(
|
|
60870
|
+
if (!IGNORED_DIRECTORIES.has(entry.name)) found.push(...walkSource(join26(dir, entry.name), root));
|
|
60606
60871
|
continue;
|
|
60607
60872
|
}
|
|
60608
60873
|
const ext = entry.name.slice(entry.name.lastIndexOf("."));
|
|
60609
60874
|
if (!SOURCE_EXTENSIONS.has(ext)) continue;
|
|
60610
|
-
const absolute =
|
|
60611
|
-
const text2 =
|
|
60612
|
-
if (text2 !== null) found.push({ path:
|
|
60875
|
+
const absolute = join26(dir, entry.name);
|
|
60876
|
+
const text2 = readText2(absolute);
|
|
60877
|
+
if (text2 !== null) found.push({ path: relative4(root, absolute), text: text2 });
|
|
60613
60878
|
}
|
|
60614
60879
|
return found;
|
|
60615
60880
|
}
|
|
60616
|
-
function parseEvidence(path) {
|
|
60617
|
-
const raw = readText(path);
|
|
60618
|
-
if (raw === null) return { evidence: null };
|
|
60619
|
-
try {
|
|
60620
|
-
const value = JSON.parse(raw);
|
|
60621
|
-
if (value.version !== 1 || !value.platforms || typeof value.platforms !== "object") {
|
|
60622
|
-
return { evidence: null, error: "must be an object with version: 1 and a platforms object" };
|
|
60623
|
-
}
|
|
60624
|
-
return { evidence: value };
|
|
60625
|
-
} catch (error) {
|
|
60626
|
-
return { evidence: null, error: `is not valid JSON: ${error.message}` };
|
|
60627
|
-
}
|
|
60628
|
-
}
|
|
60629
60881
|
function blankMatrixRows(text2) {
|
|
60630
|
-
const acceptance = text2
|
|
60882
|
+
const acceptance = mobileUxSection(mobileUxDocumentBody(text2), "Implementation acceptance") ?? "";
|
|
60631
60883
|
return /\|\s*(?:Ready|Empty|Add\s*\/\s*edit|Saved\s*\/\s*completed|Error\s*\/\s*recovery)\s*\|\s*\|\s*\|\s*\|\s*\|/i.test(acceptance);
|
|
60632
60884
|
}
|
|
60633
60885
|
function usesAppNetwork(source) {
|
|
@@ -60635,40 +60887,41 @@ function usesAppNetwork(source) {
|
|
|
60635
60887
|
return source.some(({ text: text2 }) => /\bwixApi\b|(?:from|import)\s*["']@(?:himalaya|wix\/himalaya)\/wix-[^"']+["']/.test(code(text2)));
|
|
60636
60888
|
}
|
|
60637
60889
|
function auditUx(content, strict = false) {
|
|
60638
|
-
const dir =
|
|
60890
|
+
const dir = resolve16(content);
|
|
60639
60891
|
const issues = [];
|
|
60640
|
-
const evidencePath =
|
|
60641
|
-
const
|
|
60642
|
-
const
|
|
60892
|
+
const evidencePath = join26(dir, UX_EVIDENCE_PATH);
|
|
60893
|
+
const parsed = parseEvidence(evidencePath);
|
|
60894
|
+
const renderedWidths = renderEvidenceEntries(parsed.evidence).map((entry) => entry.width);
|
|
60895
|
+
const spec = readText2(join26(dir, "SPEC.md"));
|
|
60896
|
+
const mobile = readText2(join26(dir, "MOBILE-UX.md"));
|
|
60643
60897
|
if (!spec) issue(issues, strict, "missing-spec", "SPEC.md is missing; define the customer task before calling this UX-ready.", "SPEC.md");
|
|
60644
60898
|
if (!mobile) {
|
|
60645
60899
|
issue(issues, strict, "missing-mobile-ux", "MOBILE-UX.md is missing; add the mobile state and platform contract.", "MOBILE-UX.md");
|
|
60646
60900
|
} else {
|
|
60647
|
-
for (const finding of mobileUxMarkerFindings(mobile)) issue(issues, strict, finding.code, finding.message, "MOBILE-UX.md");
|
|
60901
|
+
for (const finding of mobileUxMarkerFindings(mobile, renderedWidths)) issue(issues, strict, finding.code, finding.message, "MOBILE-UX.md");
|
|
60648
60902
|
if (blankMatrixRows(mobile)) issue(issues, strict, "blank-acceptance-matrix", "The seeded acceptance rows are still blank; replace them with this app's flows and visible results.", "MOBILE-UX.md");
|
|
60649
60903
|
}
|
|
60650
|
-
const parsed = parseEvidence(evidencePath);
|
|
60651
60904
|
if (parsed.error) {
|
|
60652
|
-
issues.push({ code: "invalid-native-evidence", message: `${
|
|
60905
|
+
issues.push({ code: "invalid-native-evidence", message: `${UX_EVIDENCE_PATH} ${parsed.error}.`, path: UX_EVIDENCE_PATH, severity: "error" });
|
|
60653
60906
|
}
|
|
60654
60907
|
for (const platform of ["ios", "android"]) {
|
|
60655
60908
|
const record2 = parsed.evidence?.platforms[platform];
|
|
60656
60909
|
if (!record2) {
|
|
60657
|
-
issue(issues, strict, `missing-${platform}-audit`, `No ${platform} native audit is recorded. Use \`himi ux record --platform ${platform} \u2026\` after driving the installed app.`,
|
|
60910
|
+
issue(issues, strict, `missing-${platform}-audit`, `No ${platform} native audit is recorded. Use \`himi ux record --platform ${platform} \u2026\` after driving the installed app.`, UX_EVIDENCE_PATH);
|
|
60658
60911
|
continue;
|
|
60659
60912
|
}
|
|
60660
60913
|
if (!["passed", "failed", "unavailable"].includes(record2.status)) {
|
|
60661
|
-
issues.push({ code: `invalid-${platform}-status`, message: `${platform} audit has an invalid status.`, path:
|
|
60914
|
+
issues.push({ code: `invalid-${platform}-status`, message: `${platform} audit has an invalid status.`, path: UX_EVIDENCE_PATH, severity: "error" });
|
|
60662
60915
|
} else if (record2.status === "failed") {
|
|
60663
|
-
issues.push({ code: `${platform}-audit-failed`, message: `${platform} native audit is recorded as failed; fix it or record a justified unavailable platform.`, path:
|
|
60916
|
+
issues.push({ code: `${platform}-audit-failed`, message: `${platform} native audit is recorded as failed; fix it or record a justified unavailable platform.`, path: UX_EVIDENCE_PATH, severity: "error" });
|
|
60664
60917
|
}
|
|
60665
60918
|
const malformedChecks = record2.checks !== void 0 && !Array.isArray(record2.checks);
|
|
60666
60919
|
if (malformedChecks || record2.status !== "unavailable" && (record2.checks ?? []).length === 0) {
|
|
60667
60920
|
const message = malformedChecks ? `${platform} audit has a malformed checks list; it must be an array.` : `${platform} audit needs the checks that were driven.`;
|
|
60668
|
-
issues.push({ code: `missing-${platform}-checks`, message, path:
|
|
60921
|
+
issues.push({ code: `missing-${platform}-checks`, message, path: UX_EVIDENCE_PATH, severity: "error" });
|
|
60669
60922
|
}
|
|
60670
60923
|
if (record2.status === "unavailable" && !record2.reason?.trim()) {
|
|
60671
|
-
issues.push({ code: `missing-${platform}-reason`, message: `${platform} is unavailable but has no reason.`, path:
|
|
60924
|
+
issues.push({ code: `missing-${platform}-reason`, message: `${platform} is unavailable but has no reason.`, path: UX_EVIDENCE_PATH, severity: "error" });
|
|
60672
60925
|
}
|
|
60673
60926
|
}
|
|
60674
60927
|
const source = walkSource(dir);
|
|
@@ -60680,12 +60933,12 @@ function auditUx(content, strict = false) {
|
|
|
60680
60933
|
const preview = matches(previewControl);
|
|
60681
60934
|
if (preview) issue(issues, strict, "possible-preview-control", "Possible customer-visible test/demo state control found. Keep scenario controls out of shipping UI, or document a capability-limited fallback.", preview.path);
|
|
60682
60935
|
if (usesAppNetwork(source)) {
|
|
60683
|
-
const mocksPath =
|
|
60684
|
-
if (!
|
|
60936
|
+
const mocksPath = join26(dir, "dev", "net-mocks.json");
|
|
60937
|
+
if (!existsSync22(mocksPath)) {
|
|
60685
60938
|
issue(issues, strict, "missing-app-mocks", "This package uses a Wix/network client but has no app-specific dev/net-mocks.json. Add fixtures for dynamic, entitlement, or recovery flows.", "dev/net-mocks.json");
|
|
60686
60939
|
} else {
|
|
60687
60940
|
try {
|
|
60688
|
-
const parsed2 = JSON.parse(
|
|
60941
|
+
const parsed2 = JSON.parse(readFileSync24(mocksPath, "utf8"));
|
|
60689
60942
|
const errors2 = Array.isArray(parsed2?.rules) ? wixMockRuleErrors(parsed2.rules) : ['missing top-level "rules" array'];
|
|
60690
60943
|
if (errors2.length) issue(issues, strict, "invalid-app-mocks", `dev/net-mocks.json cannot serve the flows it claims to mock: ${errors2.join("; ")}`, "dev/net-mocks.json");
|
|
60691
60944
|
} catch (error) {
|
|
@@ -60695,49 +60948,33 @@ function auditUx(content, strict = false) {
|
|
|
60695
60948
|
}
|
|
60696
60949
|
const errors = issues.filter((item) => item.severity === "error");
|
|
60697
60950
|
const warnings = issues.filter((item) => item.severity === "warning");
|
|
60698
|
-
return { ok: errors.length === 0, strict, content: dir, evidencePath:
|
|
60699
|
-
}
|
|
60700
|
-
function recordNativeAudit(content, platform, status, checks, reason) {
|
|
60701
|
-
const normalizedChecks = status === "unavailable" ? [] : [...new Set(checks.map((check) => check.trim()).filter(Boolean))];
|
|
60702
|
-
if (status !== "unavailable" && !normalizedChecks.length) {
|
|
60703
|
-
throw new Error("--checks needs at least one comma-separated check (for example: back,keyboard,voiceover)");
|
|
60704
|
-
}
|
|
60705
|
-
if (status === "unavailable" && !reason?.trim()) throw new Error("--reason is required when --status unavailable");
|
|
60706
|
-
const dir = resolve15(content);
|
|
60707
|
-
const path = join25(dir, EVIDENCE_RELATIVE_PATH);
|
|
60708
|
-
const parsed = parseEvidence(path);
|
|
60709
|
-
if (parsed.error) throw new Error(`${EVIDENCE_RELATIVE_PATH} ${parsed.error}`);
|
|
60710
|
-
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
60711
|
-
evidence.platforms[platform] = { status, checks: normalizedChecks, ...reason?.trim() ? { reason: reason.trim() } : {}, recordedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
60712
|
-
mkdirSync10(join25(dir, ".himi"), { recursive: true });
|
|
60713
|
-
writeFileSync9(path, JSON.stringify(evidence, null, 2) + "\n");
|
|
60714
|
-
return evidence;
|
|
60951
|
+
return { ok: errors.length === 0, strict, content: dir, evidencePath: UX_EVIDENCE_PATH, errors, warnings, counts: { errors: errors.length, warnings: warnings.length } };
|
|
60715
60952
|
}
|
|
60716
60953
|
|
|
60717
60954
|
// src/guides.ts
|
|
60718
60955
|
init_mobile_ux_contract();
|
|
60719
|
-
import { readFileSync as
|
|
60956
|
+
import { readFileSync as readFileSync25, existsSync as existsSync23, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, copyFileSync as copyFileSync2 } from "node:fs";
|
|
60720
60957
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
60721
|
-
import { dirname as
|
|
60722
|
-
var GUIDES_DIR =
|
|
60958
|
+
import { dirname as dirname16, join as join27, resolve as resolve17 } from "node:path";
|
|
60959
|
+
var GUIDES_DIR = resolve17(dirname16(fileURLToPath10(import.meta.url)), "../guides");
|
|
60723
60960
|
function guidesAvailable() {
|
|
60724
|
-
return
|
|
60961
|
+
return existsSync23(join27(GUIDES_DIR, "index.json"));
|
|
60725
60962
|
}
|
|
60726
60963
|
function loadIndex() {
|
|
60727
|
-
return JSON.parse(
|
|
60964
|
+
return JSON.parse(readFileSync25(join27(GUIDES_DIR, "index.json"), "utf8"));
|
|
60728
60965
|
}
|
|
60729
60966
|
function readGuide(id) {
|
|
60730
60967
|
const meta = loadIndex().guides.find((g) => g.id === id);
|
|
60731
60968
|
if (!meta) return null;
|
|
60732
|
-
return
|
|
60969
|
+
return readFileSync25(join27(GUIDES_DIR, meta.file), "utf8");
|
|
60733
60970
|
}
|
|
60734
60971
|
function loadComponentReference() {
|
|
60735
60972
|
const idx = loadIndex();
|
|
60736
|
-
return JSON.parse(
|
|
60973
|
+
return JSON.parse(readFileSync25(join27(GUIDES_DIR, idx.componentReferenceFile), "utf8"));
|
|
60737
60974
|
}
|
|
60738
60975
|
function loadSdkReference() {
|
|
60739
60976
|
const idx = loadIndex();
|
|
60740
|
-
return JSON.parse(
|
|
60977
|
+
return JSON.parse(readFileSync25(join27(GUIDES_DIR, idx.sdkReferenceFile), "utf8"));
|
|
60741
60978
|
}
|
|
60742
60979
|
function buildAgentPrimer() {
|
|
60743
60980
|
const idx = loadIndex();
|
|
@@ -60846,19 +61083,19 @@ function writeAgentContext(targetDir) {
|
|
|
60846
61083
|
const idx = loadIndex();
|
|
60847
61084
|
const files = [];
|
|
60848
61085
|
const write2 = (rel, body) => {
|
|
60849
|
-
const p =
|
|
60850
|
-
mkdirSync11(
|
|
61086
|
+
const p = join27(targetDir, rel);
|
|
61087
|
+
mkdirSync11(dirname16(p), { recursive: true });
|
|
60851
61088
|
writeFileSync10(p, body);
|
|
60852
61089
|
files.push(rel);
|
|
60853
61090
|
};
|
|
60854
61091
|
const copy = (srcRel, destRel) => {
|
|
60855
|
-
const p =
|
|
60856
|
-
mkdirSync11(
|
|
60857
|
-
copyFileSync2(
|
|
61092
|
+
const p = join27(targetDir, destRel);
|
|
61093
|
+
mkdirSync11(dirname16(p), { recursive: true });
|
|
61094
|
+
copyFileSync2(join27(GUIDES_DIR, srcRel), p);
|
|
60858
61095
|
files.push(destRel);
|
|
60859
61096
|
};
|
|
60860
61097
|
const writeIfMissing = (rel, body) => {
|
|
60861
|
-
if (
|
|
61098
|
+
if (existsSync23(join27(targetDir, rel))) return;
|
|
60862
61099
|
write2(rel, body);
|
|
60863
61100
|
};
|
|
60864
61101
|
write2("HIMALAYA.md", buildAgentPrimer());
|
|
@@ -60919,8 +61156,8 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
|
|
|
60919
61156
|
var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
60920
61157
|
function embeddedTemplateCatalog() {
|
|
60921
61158
|
return availableTemplates().map((name) => {
|
|
60922
|
-
const path =
|
|
60923
|
-
const meta = JSON.parse(
|
|
61159
|
+
const path = join50(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
61160
|
+
const meta = JSON.parse(readFileSync64(path, "utf8"));
|
|
60924
61161
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
60925
61162
|
throw new Error(`${path} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
60926
61163
|
}
|
|
@@ -61377,7 +61614,7 @@ var COMMANDS = [
|
|
|
61377
61614
|
{ name: "functions", summary: "inspect/invoke server functions and operate durable jobs or schedules", required: "list|describe|openapi|invoke | jobs list|get|cancel|retry|dlq | schedule describe|invoke [--app <a>] [--environment preview|production] [--release <id>]" },
|
|
61378
61615
|
{ name: "eject", summary: "take ownership of a shared flow module (auth|checkout|screens): copies its source into tier5-src/_ejected/ and repoints this package's imports at the copy. The ladder's escape hatch \u2014 for when the factory options cannot express what you need. AFTER EJECTING, CENTRAL FIXES NO LONGER REACH THIS APP, including future corrections to the fail-closed entitlement and confirm-the-session rules. The floor is unaffected: credentials still go only through the native auth actions and money only through the cashier rail.", required: "<auth|checkout|screens> [--content <dir>]" },
|
|
61379
61616
|
{ name: "validate", summary: "lint the content package (no push): fixed-contract TypeScript checking for tier5-src workers + schema/proto + token refs + component allowlist + $service bindings + strict-enum foot-guns + capability decls + worker boot dry-run + build/compile failures. Type issues are advisory warnings normally; --strict promotes them and hygiene warnings to errors. Exit 1 on any error. Off-repo, the CLI supplies its compiler and SDK declarations.", required: "[--content <dir>] [--strict]" },
|
|
61380
|
-
{ name: "test", summary: "DERIVED behavioral crawl \u2014 no test files to write. Boots each screen's real worker, replays its onAppear, then dispatches every action site the descriptor already declares (each from a fresh boot) and checks a narrow set of unambiguous invariants: no uncaught throw, never stuck on `loading`, no `$service:` token or NaN/undefined/[object Object] reaching visible text, no binding aimed at state the worker never defines, no nav param silently dropped, no dead nav target. Catches what validate/render cannot \u2014 a WRONG REDUCER passes both with ok:true. Runs the worker in a DEVICE-PARITY sandbox (no setTimeout/setInterval, as on JSC/WebView) so a bundle that would die on device fails here. Crawls on HERMETIC DATA by default \u2014 zero network: the app's own dev/net-mocks.json first (--net <file> overrides), then the config's CMS `seed:` rows, then a canned fixture of frozen real vertical responses shipped with the CLI (exercises code paths, not API-contract truth) \u2014 so the success/mapping path runs, not just the failure UI. Two boot-only HOSTILE passes (every list empty; every request 500) then check the failure/empty day \u2014 corpus-proven, so their findings are errors. NAV EDGES are followed too: every himi.open site ($item params resolved against row 0 of its list, $service against worker state) and worker _nav directive is harvested, and each baked target is booted WITH the params the source sends \u2014 detail screens finally run their content arm; edge findings are errors tagged edge:<source>. --native runs both real native decoders over the exact baked JSON bytes; --native ios or --native android selects one. It is explicit and needs the selected local toolchain.
|
|
61617
|
+
{ name: "test", summary: "DERIVED behavioral crawl \u2014 no test files to write. Boots each screen's real worker, replays its onAppear, then dispatches every action site the descriptor already declares (each from a fresh boot) and checks a narrow set of unambiguous invariants: no uncaught throw, never stuck on `loading`, no `$service:` token or NaN/undefined/[object Object] reaching visible text, no binding aimed at state the worker never defines, no nav param silently dropped, no dead nav target. Catches what validate/render cannot \u2014 a WRONG REDUCER passes both with ok:true. Runs the worker in a DEVICE-PARITY sandbox (no setTimeout/setInterval, as on JSC/WebView) so a bundle that would die on device fails here. Crawls on HERMETIC DATA by default \u2014 zero network: the app's own dev/net-mocks.json first (--net <file> overrides), then the config's CMS `seed:` rows, then a canned fixture of frozen real vertical responses shipped with the CLI (exercises code paths, not API-contract truth) \u2014 so the success/mapping path runs, not just the failure UI. Two boot-only HOSTILE passes (every list empty; every request 500) then check the failure/empty day \u2014 corpus-proven, so their findings are errors. NAV EDGES are followed too: every himi.open site ($item params resolved against row 0 of its list, $service against worker state) and worker _nav directive is harvested, and each baked target is booted WITH the params the source sends \u2014 detail screens finally run their content arm; edge findings are errors tagged edge:<source>. --native runs both real native decoders over the exact baked JSON bytes; --native ios or --native android selects one. It is explicit, runs only from a Himalaya SOURCE CHECKOUT (the decoder oracles are that tree's own HimalayaCore Swift package and Gradle harness, which a published install does not ship), and needs the selected local toolchain. From a source checkout, default runs name missing native verdicts in the coverage ledger; elsewhere the ledger stays silent about them rather than offering a remedy you cannot run. --offline strips all data layers (the old reject-all axis); --no-hostile skips the hostile passes. --record (EXPLICIT, never automatic) refreshes dev/net-mocks.json from live reads first: it boots each screen (load + root onAppear ONLY \u2014 nothing the app's own launch would not fire; the tap/action crawl never sees the live transport, and only proven reads \u2014 GET, or read-shaped POST (/query, /search, /list*, \u2026) \u2014 ever reach the wire), freezes the round-trips, then crawls hermetically on the fresh fixture; record against a QA site, not production. Nodes it cannot judge headless are named, never silently passed. Exit 1 on any error. The CLI carries the authoring runtime off-repo; no per-app SDK install is required. --browser runs the whole loop (build \u2192 extract \u2192 validate \u2192 render \u2192 test) in YOUR browser instead of here, so the source never reaches a pod: it opens one screen's worker + descriptor in a tab, blocks on a loopback callback, and prints the report it posts back. One screen per tab \u2014 name it. --no-open prints the URL rather than launching a browser (SSH); --timeout <ms> bounds the wait, which matters because the page has no execution deadline of its own and an infinite loop in the worker hangs the tab.", required: "[<screenId>\u2026] [--content <dir>] [--net <file>] [--budget <ms>] [--deep [n]] [--record] [--native [ios|android]] [--no-shots] [--offline] [--no-hostile] [--all-screens] [--browser] [--no-open] [--timeout <ms>] [--json]" },
|
|
61381
61618
|
{ name: "ux", summary: "audit or record mobile UX evidence. `audit` checks the public-safe contract, seeded blank acceptance rows, placeholder source copy, app-specific mocks, and iOS/Android audit records. It warns while existing templates migrate; `--strict` promotes missing evidence. `record` stores checks performed on an installed iOS/Android build: `--checks` is required for passed|failed and empty for unavailable, which drove nothing and needs a `--reason` instead.", required: "audit [--content <dir>] [--strict] [--json] | record --content <dir> --platform ios|android --status passed|failed|unavailable [--checks back,keyboard,...] [--reason <text>]" },
|
|
61382
61619
|
{ name: "render", summary: "headless-render a screen with the web renderer: render-tree + diagnostics, optional --png <file>, --scheme dark, --tree. Local by default (content dir). Pass --remote --app --release to hit GET /v1/preview/\u2026/render on the serve plane after a push. Boots the worker so $service bindings resolve; --static raw bindings; --live real Wix fetches; --state injects worker state; --input supplies pre-boot navigation params; --width/--device for PNG viewport; --rtl for dir=rtl + $env:isRTL.", required: "<screenId> [--content <dir>] [--scheme dark] [--png <file>] [--tree] [--static] [--live] [--state <json|file>] [--input <json|file>] [--width <px> | --device <name>] [--rtl] [--remote --app --release]" },
|
|
61383
61620
|
{ name: "cms", summary: "inspect, provision, and seed the app's CMS (Wix Data) collections, declared as a `cms` block in config.ts. `query` is READ-ONLY \u2014 by default it fetches ONLY the physical ids `config.ts` declares (item counts + schema drift) and reports `siteScanned: false`; it never lists the site, so an UNDECLARED `himi_<app>_` collection this app owns is not reached without `--all`. `--all` SCANS the site \u2014 every collection it lists is labeled `owned`/`adopted`/`foreign`, and it describes every foreign one \u2014 id, non-system field keys + types, and the site's read role \u2014 so an app with no `cms` block at all can DISCOVER a collection to adopt (`--all` is the one case where a missing `cms` block is not 'nothing to do'). Foreign collections are described up to a cap and are never item-counted (`itemCount: null`), because a row count is one query each; `foreign.count` is how many the scan LISTED \u2014 NOT a site census, since the list endpoint is paged and is not followed \u2014 and `foreign.truncated` says how many of those went undescribed, while `unlistedCollections` reports what the listing itself left out (from Wix's own paging total). The scan is OWNER-scoped \u2014 it needs --site <msid> (or WIX_SITE_ID) plus owner auth via `wix token`; a visitor token can read a public collection's ITEMS but can never enumerate collections, so there is no tokenless discovery path. `create` reconciles declared collections additively and idempotently, and REFUSES any id outside the app's `himi_<app>_` namespace, so it is safe against a production site. It reports declared-vs-site `permissionDrift` but never writes permissions unless asked with --apply-permissions, so a field reconcile can't silently revert access control changed in the dashboard. `seed` inserts the git-tracked `seed:` rows into EMPTY owned collections (--force to add to a non-empty one; --ai writes placeholder rows plus a refinement prompt for you to review). Adopted collections (declared by `wixId`) are read-only and never created, updated, or seeded. Site from --site <msid> or WIX_SITE_ID; owner auth via `wix token`.", required: "query|create|seed [--site <msid>] [--content <dir>] [--all] [--dry-run] [--force] [--allow-destructive] [--apply-permissions] [--only <id>] [--ai] [--count <n>]" },
|
|
@@ -61423,7 +61660,7 @@ var COMMANDS = [
|
|
|
61423
61660
|
];
|
|
61424
61661
|
function cliVersion() {
|
|
61425
61662
|
try {
|
|
61426
|
-
return JSON.parse(
|
|
61663
|
+
return JSON.parse(readFileSync64(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
61427
61664
|
} catch {
|
|
61428
61665
|
return "unknown";
|
|
61429
61666
|
}
|
|
@@ -61439,18 +61676,18 @@ function compareVersions2(a, b) {
|
|
|
61439
61676
|
}
|
|
61440
61677
|
function packageVersion(path) {
|
|
61441
61678
|
try {
|
|
61442
|
-
const version = JSON.parse(
|
|
61679
|
+
const version = JSON.parse(readFileSync64(path, "utf8")).version;
|
|
61443
61680
|
return typeof version === "string" && version ? version : void 0;
|
|
61444
61681
|
} catch {
|
|
61445
61682
|
return void 0;
|
|
61446
61683
|
}
|
|
61447
61684
|
}
|
|
61448
61685
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
61449
|
-
let dir =
|
|
61686
|
+
let dir = resolve41(fromDir);
|
|
61450
61687
|
for (; ; ) {
|
|
61451
|
-
const version = packageVersion(
|
|
61688
|
+
const version = packageVersion(join50(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
61452
61689
|
if (version) return { version, source: "local" };
|
|
61453
|
-
const parent =
|
|
61690
|
+
const parent = dirname29(dir);
|
|
61454
61691
|
if (parent === dir) break;
|
|
61455
61692
|
dir = parent;
|
|
61456
61693
|
}
|
|
@@ -61458,7 +61695,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
61458
61695
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
61459
61696
|
try {
|
|
61460
61697
|
const root = execFileSync6("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
61461
|
-
const version = root ? packageVersion(
|
|
61698
|
+
const version = root ? packageVersion(join50(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
61462
61699
|
return version ? { version, source: "global" } : {};
|
|
61463
61700
|
} catch {
|
|
61464
61701
|
return {};
|
|
@@ -61557,6 +61794,40 @@ function previewLogsUrl(serveBase, app, release) {
|
|
|
61557
61794
|
function previewTelemetryUrl(serveBase, app, release) {
|
|
61558
61795
|
return `${serveBase.replace(/\/$/, "")}/v1/telemetry/events?app=${encodeURIComponent(app)}&release=${encodeURIComponent(release)}`;
|
|
61559
61796
|
}
|
|
61797
|
+
function diagnoseBody(body) {
|
|
61798
|
+
const findings = body.findings;
|
|
61799
|
+
if (!Array.isArray(findings)) return body;
|
|
61800
|
+
const messageOf2 = (entry) => {
|
|
61801
|
+
const message = entry && typeof entry === "object" ? entry.message : void 0;
|
|
61802
|
+
return typeof message === "string" ? message : void 0;
|
|
61803
|
+
};
|
|
61804
|
+
const shown2 = new Set(findings.map(messageOf2).filter((message) => message !== void 0));
|
|
61805
|
+
const folded = (value) => Array.isArray(value) && value.length > 0 && value.every((entry) => {
|
|
61806
|
+
const message = messageOf2(entry);
|
|
61807
|
+
return message !== void 0 && shown2.has(message);
|
|
61808
|
+
});
|
|
61809
|
+
const out = {};
|
|
61810
|
+
const emptied = [];
|
|
61811
|
+
for (const [key2, value] of Object.entries(body)) {
|
|
61812
|
+
const fold = (key2 === "issues" || key2 === "failures" || key2 === "warnings") && folded(value);
|
|
61813
|
+
if (fold) emptied.push(key2);
|
|
61814
|
+
out[key2] = fold ? [] : value;
|
|
61815
|
+
}
|
|
61816
|
+
if (emptied.length) out.foldedIntoFindings = emptied;
|
|
61817
|
+
return out;
|
|
61818
|
+
}
|
|
61819
|
+
var PREVIEW_TOKEN_NOTE = "the preview link carries a bearer with a limited lifetime, and this call has no usable expiry for it \u2014 the plane stated none, or the one it stated is unreadable, already past, or beyond the hour this CLI will reason about. Run the `previewRenew` command printed beside this note \u2014 from the same plane and credentials as this call (any `--serve-url`/`--control-url`/token flags you passed) \u2014 for a fresh one.";
|
|
61820
|
+
function previewTokenNote(expiresAt, now = Date.now()) {
|
|
61821
|
+
const at = expiresAt ? Date.parse(expiresAt) : NaN;
|
|
61822
|
+
if (!Number.isFinite(at)) return PREVIEW_TOKEN_NOTE;
|
|
61823
|
+
const seconds = (at - now) / 1e3;
|
|
61824
|
+
if (seconds <= 0 || seconds > 3600) return PREVIEW_TOKEN_NOTE;
|
|
61825
|
+
const minutes = Math.max(1, Math.round(seconds / 60));
|
|
61826
|
+
return `the preview link carries a bearer that expires at ${expiresAt} \u2014 about ${minutes} minute${minutes === 1 ? "" : "s"} from now; run the \`previewRenew\` command printed beside this note \u2014 from the same plane and credentials as this call (any \`--serve-url\`/\`--control-url\`/token flags you passed) \u2014 for a fresh one.`;
|
|
61827
|
+
}
|
|
61828
|
+
function previewRenewCommand(app, release, target, scope = {}) {
|
|
61829
|
+
return `himi preview --app ${app} --release ${release}` + (scope.screen ? ` --screen ${scope.screen}` : "") + (scope.surface ? ` --surface ${scope.surface}` : "") + (target !== "local" ? ` --target ${target}` : "");
|
|
61830
|
+
}
|
|
61560
61831
|
function previewPlayerLink(app, release, screenId) {
|
|
61561
61832
|
return buildPlayerPreviewUrl({ app, releaseId: release, screenId, source: "cli" });
|
|
61562
61833
|
}
|
|
@@ -61838,7 +62109,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
61838
62109
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
61839
62110
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
61840
62111
|
const iosYmlPath = iosProjectYml2(app);
|
|
61841
|
-
const iosYml =
|
|
62112
|
+
const iosYml = existsSync52(iosYmlPath) ? readFileSync64(iosYmlPath, "utf8") : "";
|
|
61842
62113
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
61843
62114
|
if (!optedIn) {
|
|
61844
62115
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -61852,19 +62123,19 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
61852
62123
|
}
|
|
61853
62124
|
function readConfigSource(dir) {
|
|
61854
62125
|
try {
|
|
61855
|
-
return
|
|
62126
|
+
return readFileSync64(join50(dir, "config.ts"), "utf8");
|
|
61856
62127
|
} catch {
|
|
61857
62128
|
return null;
|
|
61858
62129
|
}
|
|
61859
62130
|
}
|
|
61860
62131
|
function writePngFile(path, base64) {
|
|
61861
|
-
mkdirSync25(
|
|
62132
|
+
mkdirSync25(dirname29(path), { recursive: true });
|
|
61862
62133
|
writeFileSync23(path, Buffer.from(base64, "base64"));
|
|
61863
62134
|
return path;
|
|
61864
62135
|
}
|
|
61865
62136
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
61866
|
-
const dir =
|
|
61867
|
-
if (
|
|
62137
|
+
const dir = resolve41(parentDir, name);
|
|
62138
|
+
if (existsSync52(join50(dir, "himalaya.content.json"))) {
|
|
61868
62139
|
throw new Error(`content package already exists at ${dir}`);
|
|
61869
62140
|
}
|
|
61870
62141
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -61876,7 +62147,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
|
61876
62147
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
61877
62148
|
}
|
|
61878
62149
|
function contentDir(flags) {
|
|
61879
|
-
return
|
|
62150
|
+
return resolve41(str5(flags.content) ?? process.cwd());
|
|
61880
62151
|
}
|
|
61881
62152
|
function renameRestoredSource(restored, declaredApp, renamed) {
|
|
61882
62153
|
const text2 = {};
|
|
@@ -61907,8 +62178,8 @@ function symlinkDestinationIssue(dest) {
|
|
|
61907
62178
|
function restoreDestinationIssue(dest, force) {
|
|
61908
62179
|
const link = symlinkDestinationIssue(dest);
|
|
61909
62180
|
if (link) return link;
|
|
61910
|
-
if (!
|
|
61911
|
-
if (!
|
|
62181
|
+
if (!existsSync52(dest)) return null;
|
|
62182
|
+
if (!statSync12(dest).isDirectory()) {
|
|
61912
62183
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
61913
62184
|
}
|
|
61914
62185
|
if (readdirSync23(dest).length > 0 && !force) {
|
|
@@ -61920,10 +62191,10 @@ function restoreDestinationIssue(dest, force) {
|
|
|
61920
62191
|
return null;
|
|
61921
62192
|
}
|
|
61922
62193
|
function isHimalayaMonorepoCheckout(start) {
|
|
61923
|
-
let dir =
|
|
62194
|
+
let dir = resolve41(start);
|
|
61924
62195
|
for (; ; ) {
|
|
61925
|
-
if (
|
|
61926
|
-
const parent =
|
|
62196
|
+
if (existsSync52(join50(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync52(join50(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
62197
|
+
const parent = dirname29(dir);
|
|
61927
62198
|
if (parent === dir) return false;
|
|
61928
62199
|
dir = parent;
|
|
61929
62200
|
}
|
|
@@ -61953,8 +62224,8 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
61953
62224
|
const forBuild = Object.fromEntries(
|
|
61954
62225
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
61955
62226
|
);
|
|
61956
|
-
const repoRoot2 =
|
|
61957
|
-
const dest =
|
|
62227
|
+
const repoRoot2 = resolve41(fileURLToPath21(new URL("../../..", import.meta.url)));
|
|
62228
|
+
const dest = join50(repoRoot2, "node_modules", ".cache", "himi-template-preview", slug);
|
|
61958
62229
|
rmSync9(dest, { recursive: true, force: true });
|
|
61959
62230
|
mkdirSync25(dest, { recursive: true });
|
|
61960
62231
|
materializeSource(forBuild, displayName, dest, slug);
|
|
@@ -61962,8 +62233,8 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
61962
62233
|
}
|
|
61963
62234
|
async function appId(dir) {
|
|
61964
62235
|
try {
|
|
61965
|
-
const { readFileSync:
|
|
61966
|
-
const m = JSON.parse(
|
|
62236
|
+
const { readFileSync: readFileSync65 } = await import("node:fs");
|
|
62237
|
+
const m = JSON.parse(readFileSync65(join50(dir, "himalaya.content.json"), "utf8"));
|
|
61967
62238
|
if (m.name) return m.name;
|
|
61968
62239
|
} catch {
|
|
61969
62240
|
}
|
|
@@ -61971,8 +62242,8 @@ async function appId(dir) {
|
|
|
61971
62242
|
}
|
|
61972
62243
|
async function contentVisibility(dir) {
|
|
61973
62244
|
try {
|
|
61974
|
-
const { readFileSync:
|
|
61975
|
-
const m = JSON.parse(
|
|
62245
|
+
const { readFileSync: readFileSync65 } = await import("node:fs");
|
|
62246
|
+
const m = JSON.parse(readFileSync65(join50(dir, "himalaya.content.json"), "utf8"));
|
|
61976
62247
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
61977
62248
|
} catch {
|
|
61978
62249
|
}
|
|
@@ -62173,7 +62444,7 @@ Seed your coding agent with \`himi agent-init\`. Portal: ${idx.portalUrl}`);
|
|
|
62173
62444
|
return 0;
|
|
62174
62445
|
}
|
|
62175
62446
|
case "agent-init": {
|
|
62176
|
-
const dir =
|
|
62447
|
+
const dir = resolve41(str5(flags.dir) ?? process.cwd());
|
|
62177
62448
|
const res = writeAgentContext(dir);
|
|
62178
62449
|
print({ ok: true, dir: res.dir, files: res.files, portalUrl: idx.portalUrl });
|
|
62179
62450
|
return 0;
|
|
@@ -62259,7 +62530,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
62259
62530
|
let js;
|
|
62260
62531
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
62261
62532
|
try {
|
|
62262
|
-
js =
|
|
62533
|
+
js = readFileSync64(join50(outDir, candidate), "utf8");
|
|
62263
62534
|
break;
|
|
62264
62535
|
} catch {
|
|
62265
62536
|
}
|
|
@@ -62349,7 +62620,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62349
62620
|
return 2;
|
|
62350
62621
|
}
|
|
62351
62622
|
const template = str5(flags.template);
|
|
62352
|
-
const parentDir =
|
|
62623
|
+
const parentDir = resolve41(str5(flags.dir) ?? process.cwd());
|
|
62353
62624
|
if (template && flags.remote === true) {
|
|
62354
62625
|
try {
|
|
62355
62626
|
const res2 = await initFromRemoteTemplate(name, parentDir, template, client3());
|
|
@@ -62437,11 +62708,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62437
62708
|
return 0;
|
|
62438
62709
|
}
|
|
62439
62710
|
if (sub === "publish") {
|
|
62440
|
-
const appDir2 =
|
|
62441
|
-
const sourceDir =
|
|
62711
|
+
const appDir2 = resolve41(str5(flags.dir) ?? process.cwd());
|
|
62712
|
+
const sourceDir = resolve41(str5(flags["source-dir"]) ?? appDir2);
|
|
62442
62713
|
let meta;
|
|
62443
62714
|
try {
|
|
62444
|
-
meta = JSON.parse(
|
|
62715
|
+
meta = JSON.parse(readFileSync64(join50(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
62445
62716
|
} catch {
|
|
62446
62717
|
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>)` }));
|
|
62447
62718
|
return 2;
|
|
@@ -62451,7 +62722,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62451
62722
|
return 2;
|
|
62452
62723
|
}
|
|
62453
62724
|
try {
|
|
62454
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
62725
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync64(join50(sourceDir, "tokens.json"), "utf8")));
|
|
62455
62726
|
meta = { ...appearance, ...meta };
|
|
62456
62727
|
} catch {
|
|
62457
62728
|
}
|
|
@@ -62463,13 +62734,13 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62463
62734
|
const force = flags.force === true;
|
|
62464
62735
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
62465
62736
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
62466
|
-
const out = mkdtempSync4(
|
|
62737
|
+
const out = mkdtempSync4(join50(tmpdir5(), "himi-template-"));
|
|
62467
62738
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62468
62739
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
62469
62740
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
62470
62741
|
collect: { lint: true, strict }
|
|
62471
62742
|
});
|
|
62472
|
-
const scaffoldSourceFindings =
|
|
62743
|
+
const scaffoldSourceFindings = resolve41(sourceDir) === resolve41(appDir2) ? [] : [
|
|
62473
62744
|
...tokenColorIssues(sourceDir),
|
|
62474
62745
|
...surfaceIssues(sourceDir, void 0, strict),
|
|
62475
62746
|
...fontIssues(sourceDir, strict),
|
|
@@ -62512,11 +62783,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62512
62783
|
}));
|
|
62513
62784
|
return 1;
|
|
62514
62785
|
}
|
|
62515
|
-
const iconPath = str5(flags.icon) ?
|
|
62786
|
+
const iconPath = str5(flags.icon) ? resolve41(str5(flags.icon)) : templateIconPath(name);
|
|
62516
62787
|
let iconHash;
|
|
62517
62788
|
if (iconPath) {
|
|
62518
62789
|
try {
|
|
62519
|
-
const bytes2 =
|
|
62790
|
+
const bytes2 = readFileSync64(iconPath);
|
|
62520
62791
|
payload.icon = bytes2.toString("base64");
|
|
62521
62792
|
iconHash = createHash24("sha256").update(bytes2).digest("hex");
|
|
62522
62793
|
} catch {
|
|
@@ -62715,7 +62986,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62715
62986
|
const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
|
|
62716
62987
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
62717
62988
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
62718
|
-
const out = mkdtempSync4(
|
|
62989
|
+
const out = mkdtempSync4(join50(tmpdir5(), "himi-validate-"));
|
|
62719
62990
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62720
62991
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
62721
62992
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -62752,7 +63023,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62752
63023
|
const path = dpxSessionTokenPath();
|
|
62753
63024
|
let raw;
|
|
62754
63025
|
try {
|
|
62755
|
-
raw =
|
|
63026
|
+
raw = readFileSync64(path, "utf8");
|
|
62756
63027
|
} catch {
|
|
62757
63028
|
throw new Error(`no DPX BO session at ${path}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
|
|
62758
63029
|
}
|
|
@@ -62904,7 +63175,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62904
63175
|
case "test": {
|
|
62905
63176
|
const dir = contentDir(flags);
|
|
62906
63177
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
62907
|
-
if (
|
|
63178
|
+
if (existsSync52(join50(dir, "functions"))) {
|
|
62908
63179
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
62909
63180
|
const loaded = await loadFunctionsApp2(dir);
|
|
62910
63181
|
const results = [];
|
|
@@ -62991,7 +63262,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62991
63262
|
}
|
|
62992
63263
|
}
|
|
62993
63264
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
62994
|
-
const out = mkdtempSync4(
|
|
63265
|
+
const out = mkdtempSync4(join50(tmpdir5(), "himi-test-"));
|
|
62995
63266
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62996
63267
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
62997
63268
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63036,7 +63307,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63036
63307
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
63037
63308
|
return 2;
|
|
63038
63309
|
}
|
|
63039
|
-
const sources = collectWorkerSources2(
|
|
63310
|
+
const sources = collectWorkerSources2(join50(dir, "tier5-src"), screen.bundleName);
|
|
63040
63311
|
if (!sources) {
|
|
63041
63312
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
63042
63313
|
return 2;
|
|
@@ -63197,7 +63468,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63197
63468
|
const sp = await runShotsPass2({
|
|
63198
63469
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
63199
63470
|
tokens: outcome.tokens,
|
|
63200
|
-
outDir:
|
|
63471
|
+
outDir: join50(dir, ".himi", "shots"),
|
|
63201
63472
|
width: 390,
|
|
63202
63473
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
63203
63474
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -63214,9 +63485,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63214
63485
|
result.shots = { ...sp.written.length ? { dir: sp.dir } : {}, written: sp.written.length, ...sp.unavailable ? { unavailable: true } : {} };
|
|
63215
63486
|
}
|
|
63216
63487
|
}
|
|
63217
|
-
const { assembleLedger: assembleLedger2, trendAndStore: trendAndStore2, formatLedger: formatLedger2, diffAndStoreObservations: diffAndStoreObservations2, formatDelta: formatDelta2 } = await Promise.resolve().then(() => (init_coverage(), coverage_exports));
|
|
63218
|
-
const
|
|
63219
|
-
const
|
|
63488
|
+
const { assembleLedger: assembleLedger2, trendAndStore: trendAndStore2, formatLedger: formatLedger2, diffAndStoreObservations: diffAndStoreObservations2, formatDelta: formatDelta2, suppressedNativeKeys: suppressedNativeKeys2 } = await Promise.resolve().then(() => (init_coverage(), coverage_exports));
|
|
63489
|
+
const { nativeOracleShipped: nativeOracleShipped2 } = await Promise.resolve().then(() => (init_native_decode(), native_decode_exports));
|
|
63490
|
+
const nativeOracle = nativeOracleShipped2();
|
|
63491
|
+
const ledger = assembleLedger2(result, { nativeOracle });
|
|
63492
|
+
const trend = trendAndStore2(dir, ledger, suppressedNativeKeys2(nativeOracle));
|
|
63220
63493
|
const delta = diffAndStoreObservations2(dir, result.observations ?? {});
|
|
63221
63494
|
const legacy = { ...result, ledger, ...trend ? { trend } : {}, ...delta ? { delta } : {}, ...recorded ? { recorded } : {} };
|
|
63222
63495
|
const release = await loadReleaseFromDir(app, out);
|
|
@@ -63233,7 +63506,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63233
63506
|
releaseId: result.releaseId,
|
|
63234
63507
|
releasePayload: release,
|
|
63235
63508
|
descriptors: attestedDescriptors,
|
|
63236
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
63509
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join50(dir, ".himi", "shots", name)])),
|
|
63237
63510
|
coverage: {
|
|
63238
63511
|
screens: crawledScreens.size,
|
|
63239
63512
|
actionsDispatched: result.actions.exercised,
|
|
@@ -63322,7 +63595,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63322
63595
|
return 2;
|
|
63323
63596
|
}
|
|
63324
63597
|
try {
|
|
63325
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
63598
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync64(stateArg.replace(/^@/, ""), "utf8");
|
|
63326
63599
|
injectedState = JSON.parse(raw);
|
|
63327
63600
|
} catch (e) {
|
|
63328
63601
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -63337,7 +63610,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63337
63610
|
return 2;
|
|
63338
63611
|
}
|
|
63339
63612
|
try {
|
|
63340
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
63613
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync64(inputArg.replace(/^@/, ""), "utf8");
|
|
63341
63614
|
const parsed = JSON.parse(raw);
|
|
63342
63615
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
63343
63616
|
injectedInput = parsed;
|
|
@@ -63370,7 +63643,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63370
63643
|
return 2;
|
|
63371
63644
|
}
|
|
63372
63645
|
} else if (typeof flags.width === "string" && flags.width) {
|
|
63373
|
-
renderWidth = Number(flags.width);
|
|
63646
|
+
renderWidth = Math.round(Number(flags.width));
|
|
63374
63647
|
if (!Number.isFinite(renderWidth) || renderWidth <= 0) {
|
|
63375
63648
|
io.error(JSON.stringify({ error: `--width must be a positive number of pixels (got "${str5(flags.width)}")` }));
|
|
63376
63649
|
return 2;
|
|
@@ -63386,7 +63659,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63386
63659
|
}
|
|
63387
63660
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
63388
63661
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
63389
|
-
const out = mkdtempSync4(
|
|
63662
|
+
const out = mkdtempSync4(join50(tmpdir5(), "himi-render-"));
|
|
63390
63663
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63391
63664
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63392
63665
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63402,7 +63675,15 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63402
63675
|
let attestationPngFile;
|
|
63403
63676
|
if (typeof flags.png === "string" && r.pngBase64) {
|
|
63404
63677
|
pngFile = writePngFile(str5(flags.png), r.pngBase64);
|
|
63405
|
-
attestationPngFile = writePngFile(
|
|
63678
|
+
attestationPngFile = writePngFile(join50(dir, ".himi", "shots", `${screenId}.png`), r.pngBase64);
|
|
63679
|
+
}
|
|
63680
|
+
if (renderWidth !== void 0 && r.renderable) {
|
|
63681
|
+
recordRenderWidth(dir, {
|
|
63682
|
+
screenId,
|
|
63683
|
+
width: renderWidth,
|
|
63684
|
+
...deviceName ? { device: deviceName } : {},
|
|
63685
|
+
...pngFile ? { file: pngFile } : {}
|
|
63686
|
+
});
|
|
63406
63687
|
}
|
|
63407
63688
|
const legacyRender = {
|
|
63408
63689
|
ok: r.renderable,
|
|
@@ -63707,7 +63988,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
63707
63988
|
return 2;
|
|
63708
63989
|
}
|
|
63709
63990
|
const renamed = str5(flags.name);
|
|
63710
|
-
const dest =
|
|
63991
|
+
const dest = resolve41(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
63711
63992
|
const replace = flags.replace === true;
|
|
63712
63993
|
const force = replace || flags.force === true;
|
|
63713
63994
|
const linked = symlinkDestinationIssue(dest);
|
|
@@ -63715,8 +63996,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
63715
63996
|
io.error(JSON.stringify(linked));
|
|
63716
63997
|
return 1;
|
|
63717
63998
|
}
|
|
63718
|
-
if (
|
|
63719
|
-
if (!
|
|
63999
|
+
if (existsSync52(dest)) {
|
|
64000
|
+
if (!statSync12(dest).isDirectory()) {
|
|
63720
64001
|
io.error(JSON.stringify({
|
|
63721
64002
|
error: `${dest} exists and is not a directory`,
|
|
63722
64003
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
@@ -63728,7 +64009,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
63728
64009
|
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" }));
|
|
63729
64010
|
return 1;
|
|
63730
64011
|
}
|
|
63731
|
-
if (replace && occupied && !
|
|
64012
|
+
if (replace && occupied && !existsSync52(join50(dest, "himalaya.content.json"))) {
|
|
63732
64013
|
io.error(JSON.stringify({
|
|
63733
64014
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
63734
64015
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -63822,7 +64103,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
63822
64103
|
const force = flags.force === true;
|
|
63823
64104
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
63824
64105
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
63825
|
-
const out = mkdtempSync4(
|
|
64106
|
+
const out = mkdtempSync4(join50(tmpdir5(), "himi-push-"));
|
|
63826
64107
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63827
64108
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63828
64109
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -64048,7 +64329,16 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64048
64329
|
...loopbackWarning ? { warning: loopbackWarning } : {},
|
|
64049
64330
|
...report.issues ? { issues: report.issues } : {},
|
|
64050
64331
|
previewWeb: base ? previewWebUrl(base, app, release, void 0, void 0, previewToken) : null,
|
|
64051
|
-
|
|
64332
|
+
// A timestamp alone leaves the reader to work out both how long they have and how to
|
|
64333
|
+
// get another one. Print the duration and the re-mint command beside it (#2502 item 3).
|
|
64334
|
+
// No `mintedHere` guard is needed here, unlike `himi preview`: this bearer can only
|
|
64335
|
+
// have come from the publish response two hundred lines up, so THIS call minted it by
|
|
64336
|
+
// construction. `push` has no `--preview-token` to paste one in with.
|
|
64337
|
+
...previewToken ? {
|
|
64338
|
+
previewTokenExpiresAt: previewTokenExpiresAt ?? null,
|
|
64339
|
+
previewRenew: previewRenewCommand(app, release, targetName()),
|
|
64340
|
+
previewTokenNote: previewTokenNote(previewTokenExpiresAt)
|
|
64341
|
+
} : {},
|
|
64052
64342
|
// RFC 0051 — the surfaces THIS RELEASE targets, read from the manifest the
|
|
64053
64343
|
// push just published (never a re-read of the local file: review found the
|
|
64054
64344
|
// two can disagree — e.g. an older CLI whose local parser drops a key the
|
|
@@ -64132,7 +64422,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64132
64422
|
return 2;
|
|
64133
64423
|
}
|
|
64134
64424
|
try {
|
|
64135
|
-
const res = writePack(
|
|
64425
|
+
const res = writePack(resolve41(releaseDir), only, resolve41(str5(flags.out) ?? process.cwd()));
|
|
64136
64426
|
print({
|
|
64137
64427
|
ok: true,
|
|
64138
64428
|
app: res.app,
|
|
@@ -64181,7 +64471,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64181
64471
|
}
|
|
64182
64472
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64183
64473
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
64184
|
-
const built = mkdtempSync4(
|
|
64474
|
+
const built = mkdtempSync4(join50(tmpdir5(), "himi-pack-"));
|
|
64185
64475
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64186
64476
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
64187
64477
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -64203,7 +64493,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64203
64493
|
return 1;
|
|
64204
64494
|
}
|
|
64205
64495
|
try {
|
|
64206
|
-
const res = writePack(built, app,
|
|
64496
|
+
const res = writePack(built, app, resolve41(str5(flags.out) ?? dir), sourceArchive);
|
|
64207
64497
|
print({
|
|
64208
64498
|
ok: true,
|
|
64209
64499
|
app: res.app,
|
|
@@ -64248,7 +64538,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64248
64538
|
const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
|
|
64249
64539
|
let opened;
|
|
64250
64540
|
try {
|
|
64251
|
-
opened = openPackageFile2(
|
|
64541
|
+
opened = openPackageFile2(resolve41(file));
|
|
64252
64542
|
} catch (e) {
|
|
64253
64543
|
io.error(JSON.stringify({ error: e.message }));
|
|
64254
64544
|
return 1;
|
|
@@ -64261,7 +64551,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64261
64551
|
io.error(JSON.stringify({
|
|
64262
64552
|
ok: false,
|
|
64263
64553
|
error: "app_source_not_in_package",
|
|
64264
|
-
detail: `${
|
|
64554
|
+
detail: `${resolve41(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
|
|
64265
64555
|
hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
|
|
64266
64556
|
}));
|
|
64267
64557
|
return 1;
|
|
@@ -64284,7 +64574,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64284
64574
|
return 1;
|
|
64285
64575
|
}
|
|
64286
64576
|
}
|
|
64287
|
-
const dest =
|
|
64577
|
+
const dest = resolve41(str5(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
|
|
64288
64578
|
const issue2 = restoreDestinationIssue(dest, flags.force === true);
|
|
64289
64579
|
if (issue2) {
|
|
64290
64580
|
io.error(JSON.stringify(issue2));
|
|
@@ -64369,7 +64659,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64369
64659
|
}
|
|
64370
64660
|
try {
|
|
64371
64661
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
64372
|
-
const opened = openPackageFile2(
|
|
64662
|
+
const opened = openPackageFile2(resolve41(file));
|
|
64373
64663
|
if (!opened.validation.ok || !opened.header) {
|
|
64374
64664
|
io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
64375
64665
|
return 1;
|
|
@@ -64379,12 +64669,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64379
64669
|
io.error(JSON.stringify({
|
|
64380
64670
|
ok: false,
|
|
64381
64671
|
error: "refusing to share a package that carries the app's source",
|
|
64382
|
-
detail: `${
|
|
64672
|
+
detail: `${resolve41(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
|
|
64383
64673
|
hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
|
|
64384
64674
|
}));
|
|
64385
64675
|
return 1;
|
|
64386
64676
|
}
|
|
64387
|
-
const archive =
|
|
64677
|
+
const archive = readFileSync64(resolve41(file));
|
|
64388
64678
|
const result = await client3().createPackageShare({
|
|
64389
64679
|
app: opened.header.app,
|
|
64390
64680
|
releaseId: opened.header.releaseId,
|
|
@@ -64421,10 +64711,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64421
64711
|
const app = await appId(dir);
|
|
64422
64712
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64423
64713
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
64424
|
-
temp = mkdtempSync4(
|
|
64714
|
+
temp = mkdtempSync4(join50(tmpdir5(), "himi-run-build-"));
|
|
64425
64715
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64426
64716
|
await buildReleaseFromContent2(dir, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
|
|
64427
|
-
source =
|
|
64717
|
+
source = join50(temp, app);
|
|
64428
64718
|
}
|
|
64429
64719
|
const chromeArg = str5(flags.chrome) ?? "preview";
|
|
64430
64720
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -64449,9 +64739,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64449
64739
|
open: flags["no-open"] !== true
|
|
64450
64740
|
});
|
|
64451
64741
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
64452
|
-
await new Promise((
|
|
64742
|
+
await new Promise((resolve42) => {
|
|
64453
64743
|
const stop = () => {
|
|
64454
|
-
void run2.close().finally(() =>
|
|
64744
|
+
void run2.close().finally(() => resolve42());
|
|
64455
64745
|
};
|
|
64456
64746
|
process.once("SIGINT", stop);
|
|
64457
64747
|
process.once("SIGTERM", stop);
|
|
@@ -64509,6 +64799,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64509
64799
|
}
|
|
64510
64800
|
let previewToken = str5(flags["preview-token"]);
|
|
64511
64801
|
let previewTokenExpiresAt;
|
|
64802
|
+
let mintedHere = false;
|
|
64803
|
+
let mintFailure;
|
|
64512
64804
|
if (!previewToken) {
|
|
64513
64805
|
const target = resolveTarget({
|
|
64514
64806
|
target: str5(flags.target),
|
|
@@ -64521,15 +64813,24 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64521
64813
|
telemetryToken: str5(flags["telemetry-token"]),
|
|
64522
64814
|
controlToken: str5(flags["control-token"])
|
|
64523
64815
|
});
|
|
64524
|
-
if (target.controlToken) {
|
|
64816
|
+
if (!target.controlToken) {
|
|
64817
|
+
mintFailure = `this target has no stored control credential, so none was requested \u2014 run \`himi login --target ${targetName()}\`, or pass --control-token`;
|
|
64818
|
+
} else {
|
|
64525
64819
|
try {
|
|
64526
64820
|
const minted = await new ServeCliClient(target).previewToken(app, release);
|
|
64527
|
-
if (minted.ok
|
|
64821
|
+
if (!minted.ok) {
|
|
64822
|
+
mintFailure = `the plane refused the mint request (HTTP ${minted.status}). Your credential reached it, so this is the plane's answer, not your session`;
|
|
64823
|
+
} else if (!minted.json || typeof minted.json !== "object") {
|
|
64824
|
+
mintFailure = "the plane accepted the mint request but its answer was not a JSON object, so no token could be read. Your credential is fine";
|
|
64825
|
+
} else {
|
|
64528
64826
|
const body = minted.json;
|
|
64529
64827
|
previewToken = typeof body.previewToken === "string" ? body.previewToken : void 0;
|
|
64530
64828
|
previewTokenExpiresAt = typeof body.previewTokenExpiresAt === "string" ? body.previewTokenExpiresAt : void 0;
|
|
64829
|
+
mintedHere = previewToken !== void 0;
|
|
64830
|
+
if (!mintedHere) mintFailure = "the plane answered the mint request without a token \u2014 HIMALAYA_PREVIEW_TOKEN_SECRET may be unconfigured there. Your credential is fine";
|
|
64531
64831
|
}
|
|
64532
|
-
} catch {
|
|
64832
|
+
} catch (e) {
|
|
64833
|
+
mintFailure = `the mint request could not be sent: ${e.message}. Your credential was never judged`;
|
|
64533
64834
|
}
|
|
64534
64835
|
}
|
|
64535
64836
|
}
|
|
@@ -64540,7 +64841,22 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64540
64841
|
...screen ? { screen } : {},
|
|
64541
64842
|
...surface ? { surface } : {},
|
|
64542
64843
|
previewWeb: base ? previewWebUrl(base, app, release, screen, surface, previewToken) : null,
|
|
64543
|
-
|
|
64844
|
+
// Gated on the MINT, like the two fields below: a plane that returns an expiry but no
|
|
64845
|
+
// token would otherwise print a lifetime for a bearer the same envelope says does not
|
|
64846
|
+
// exist.
|
|
64847
|
+
...mintedHere && previewTokenExpiresAt ? { previewTokenExpiresAt } : {},
|
|
64848
|
+
// Same as the push envelope: the expiry alone leaves the reader to work out both how
|
|
64849
|
+
// long they have and how to get another link. `himi preview` re-mints, so the renew is
|
|
64850
|
+
// this very command — say so rather than making them find it again (#2502 item 3).
|
|
64851
|
+
//
|
|
64852
|
+
// Gated on the MINT, not on the expiry: a plane that mints a bearer but returns no
|
|
64853
|
+
// `previewTokenExpiresAt` would otherwise withhold the guidance in exactly the case
|
|
64854
|
+
// where the reader has no timestamp to reason from — while a bearer the caller pasted
|
|
64855
|
+
// in with `--preview-token` is one this command cannot promise to reissue.
|
|
64856
|
+
...mintedHere ? {
|
|
64857
|
+
previewRenew: previewRenewCommand(app, release, targetName(), { screen, surface }),
|
|
64858
|
+
previewTokenNote: previewTokenNote(previewTokenExpiresAt)
|
|
64859
|
+
} : previewToken || !mintFailure ? {} : { previewTokenNote: `no preview bearer was minted \u2014 ${mintFailure}. The link above carries no \`pvt\`, so it opens a LIVE release and will not open a draft.` },
|
|
64544
64860
|
previewPlayerDebug: previewPlayerDebugLink(app, release, screen, previewToken),
|
|
64545
64861
|
context: base ? previewContextUrl(base, app, release, screen) : null,
|
|
64546
64862
|
diagnose: base && screen ? previewDiagnoseUrl(base, app, release, screen) : null,
|
|
@@ -64718,8 +65034,16 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64718
65034
|
if (!r.ok) throw Object.assign(new Error("crashes_read_failed"), { response: r });
|
|
64719
65035
|
out.crashes = r.json?.crashes ?? [];
|
|
64720
65036
|
}
|
|
64721
|
-
|
|
64722
|
-
|
|
65037
|
+
const eventCount = out.events?.length ?? 0;
|
|
65038
|
+
const logCount = out.logs?.length ?? 0;
|
|
65039
|
+
const narrowed = !!(level || str5(flags.screen) || str5(flags.screenId) || str5(flags.type) || str5(flags.event) || flags["crashes-only"] === true || flags.crashesOnly === true || num(flags.limit) !== void 0 || eventSince !== void 0 || logSince !== void 0);
|
|
65040
|
+
const wholeChannels = includeEvents && includeLogs && !narrowed;
|
|
65041
|
+
if (wholeChannels && eventCount === 0 && logCount === 0 && !includeSummary && !includeCrashes) {
|
|
65042
|
+
out.note = "no events and no worker console output on this release \u2014 open the web preview or Himi Player link for it, then retry or use --follow";
|
|
65043
|
+
} else if (wholeChannels && eventCount > 0 && logCount === 0) {
|
|
65044
|
+
out.note = "events arrived but the worker console channel is empty \u2014 commonly because the worker never called `console.*`, though an empty channel can also mean the lines aged out or never made it through ingestion. What the CLI can say is that this channel returned nothing, not that the app was never opened";
|
|
65045
|
+
} else if (narrowed && eventCount === 0 && logCount === 0 && !includeSummary && !includeCrashes) {
|
|
65046
|
+
out.note = "nothing matched this query. Drop --screen/--type/--level/--since/--limit/--crashes-only to see the whole event and console channels for this release";
|
|
64723
65047
|
}
|
|
64724
65048
|
return out;
|
|
64725
65049
|
};
|
|
@@ -64800,7 +65124,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64800
65124
|
if (r.status !== 422) return printServeFailure(r);
|
|
64801
65125
|
}
|
|
64802
65126
|
const body = r.json ?? {};
|
|
64803
|
-
print(body);
|
|
65127
|
+
print(diagnoseBody(body));
|
|
64804
65128
|
return body.ok === false ? 1 : 0;
|
|
64805
65129
|
}
|
|
64806
65130
|
case "deeplinks": {
|
|
@@ -64856,8 +65180,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64856
65180
|
print({ ok: false, status: r.status, body: r.json ?? r.text });
|
|
64857
65181
|
return 1;
|
|
64858
65182
|
}
|
|
64859
|
-
const
|
|
64860
|
-
|
|
65183
|
+
const rawLogs = r.json?.logs ?? [];
|
|
65184
|
+
const logs = byLevel(rawLogs);
|
|
65185
|
+
const narrowed = !!(level || str5(flags.screen) || str5(flags.screenId) || num2(flags.since) !== void 0 || num2(flags.limit) !== void 0);
|
|
65186
|
+
const scope = release ? "this release" : "this app";
|
|
65187
|
+
const note = logs.length > 0 ? void 0 : narrowed ? `no worker \`console.*\` lines matched this query${level && rawLogs.length ? ` (${rawLogs.length} line(s) were hidden by --level ${level})` : ""}. Drop --level/--screen/--since/--limit to see the whole console channel for ${scope}; the telemetry EVENT stream is a separate channel, read with \`himi telemetry\`.` : `no worker \`console.*\` output on ${scope}. This is the console channel \u2014 distinct from the telemetry EVENT stream, which \`himi telemetry --app <app> --release <id>\` reads: ${scope} can carry many events and no console lines \u2014 commonly because the worker never logged any, though an empty channel can also mean the lines aged out or never made it through ingestion. Boot-time \`console.log\` is visible via \`himi validate\` / \`himi render\`.`;
|
|
65188
|
+
print({ ok: true, logs, ...note ? { note } : {} });
|
|
64861
65189
|
return 0;
|
|
64862
65190
|
}
|
|
64863
65191
|
const interval = num2(flags.interval) ?? 2e3;
|
|
@@ -65242,7 +65570,7 @@ ${label2}`);
|
|
|
65242
65570
|
const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
65243
65571
|
{
|
|
65244
65572
|
const distDir = contentDir(flags);
|
|
65245
|
-
if (
|
|
65573
|
+
if (existsSync52(join50(distDir, "himalaya.content.json"))) {
|
|
65246
65574
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
65247
65575
|
const errors = issues.filter((i) => i.severity === "error");
|
|
65248
65576
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -65512,7 +65840,7 @@ ${label2}`);
|
|
|
65512
65840
|
const dpxPath = dpxSessionTokenPath();
|
|
65513
65841
|
let dpx;
|
|
65514
65842
|
try {
|
|
65515
|
-
dpx =
|
|
65843
|
+
dpx = readFileSync64(dpxPath, "utf8").trim();
|
|
65516
65844
|
} catch {
|
|
65517
65845
|
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` }));
|
|
65518
65846
|
return 1;
|
|
@@ -65799,7 +66127,7 @@ ${report.ok ? "OK \u2014 data + serve plane reachable." : typeof report.hint ===
|
|
|
65799
66127
|
const path = dpxSessionTokenPath();
|
|
65800
66128
|
let raw;
|
|
65801
66129
|
try {
|
|
65802
|
-
raw =
|
|
66130
|
+
raw = readFileSync64(path, "utf8");
|
|
65803
66131
|
} catch {
|
|
65804
66132
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path}` }));
|
|
65805
66133
|
return 1;
|
|
@@ -66139,12 +66467,14 @@ export {
|
|
|
66139
66467
|
ConfigLoadError,
|
|
66140
66468
|
PLACEHOLDER_CLIENT_ID,
|
|
66141
66469
|
PLACEHOLDER_SITE_URL,
|
|
66470
|
+
PREVIEW_TOKEN_NOTE,
|
|
66142
66471
|
PUBLIC_WIX_API_BASE,
|
|
66143
66472
|
autoClaimSlug,
|
|
66144
66473
|
buildDoctorReport,
|
|
66145
66474
|
compareVersions2 as compareVersions,
|
|
66146
66475
|
decodeControlTokenClaims,
|
|
66147
66476
|
defaultTargetForCommand,
|
|
66477
|
+
diagnoseBody,
|
|
66148
66478
|
doctorVersionReport,
|
|
66149
66479
|
foreignPlaneError,
|
|
66150
66480
|
formatSdkVersionLine,
|
|
@@ -66167,8 +66497,10 @@ export {
|
|
|
66167
66497
|
previewPlayerDebugLink,
|
|
66168
66498
|
previewPlayerLink,
|
|
66169
66499
|
previewRenderUrl,
|
|
66500
|
+
previewRenewCommand,
|
|
66170
66501
|
previewScreensUrl,
|
|
66171
66502
|
previewTelemetryUrl,
|
|
66503
|
+
previewTokenNote,
|
|
66172
66504
|
previewWebUrl,
|
|
66173
66505
|
probeControlToken,
|
|
66174
66506
|
probeReachable,
|