@wix/himalaya-cli 0.1037.0 → 0.1038.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/genie-chat/src/index.d.ts +119 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-genie-chat.mjs +51 -1
- package/dist/cli.mjs +864 -400
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/headless-loop.md +7 -0
- package/guides/himi-test.md +66 -1
- package/guides/sdk-reference.json +74 -2
- package/guides/trim-a-template.md +5 -0
- package/package.json +2 -2
- package/templates/beauty-salon-owner/dev/index.ts +2148 -1262
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/community-club-owner/dev/index.ts +2151 -1265
- package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/community-club-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/events-meetups-owner/dev/index.ts +2151 -1265
- package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/events-meetups-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/gym-fitness-owner/dev/index.ts +2148 -1262
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/nonprofit-cause-owner/dev/index.ts +2148 -1262
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/owner-lite/dev/index.ts +2145 -1259
- package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/owner-lite/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/podcast-creator-owner/dev/index.ts +2151 -1265
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/portfolio-creative-owner/dev/index.ts +2148 -1262
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/restaurant-owner/dev/index.ts +2148 -1262
- package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/restaurant-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/retail-store-owner/dev/index.ts +2151 -1265
- package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/retail-store-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
- package/templates/yoga-studio-owner/dev/index.ts +2148 -1262
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +338 -26
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-mentions.ts +202 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +29 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-ask/index.ts +6 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-manage/index.ts +64 -6
package/dist/cli.mjs
CHANGED
|
@@ -1123,6 +1123,14 @@ var init_mobile_ux_contract = __esm({
|
|
|
1123
1123
|
| Screen | Job | Primary action | Data | Notes |
|
|
1124
1124
|
| --- | --- | --- | --- | --- |
|
|
1125
1125
|
|
|
1126
|
+
## Data access
|
|
1127
|
+
<!-- \`himi test\` checks every write to Wix it sees against this table. One row per screen id (and
|
|
1128
|
+
role); \`Wix writes\` is \`none\`, or the approved writes named by action (\`bookSelected\`),
|
|
1129
|
+
endpoint (\`POST /bookings/v2/bookings\`), capability (\`registerDirect\`) or kind (\`payment\`).
|
|
1130
|
+
\`himi docs himi-test\` -> "Writes to Wix". -->
|
|
1131
|
+
| Screen | Role | Reads | Wix writes | Prohibited |
|
|
1132
|
+
| --- | --- | --- | --- | --- |
|
|
1133
|
+
|
|
1126
1134
|
## Platform envelope
|
|
1127
1135
|
- Required: iOS, Android
|
|
1128
1136
|
- Optional: web, desktop, watch, widgets
|
|
@@ -1528,7 +1536,9 @@ export default defineService("home", {
|
|
|
1528
1536
|
surfaceTertiary: { light: "#eef1f4", dark: "#1c2128" },
|
|
1529
1537
|
textPrimary: { light: "#1f2328", dark: "#e6edf3" },
|
|
1530
1538
|
textSecondary: { light: "#57606a", dark: "#9198a1" },
|
|
1531
|
-
|
|
1539
|
+
// Dark ink on the dark arm: white on #388bfd is 3.34:1 and fails AA, which the tokens
|
|
1540
|
+
// pass now warns about (#3275); #0d1117 on it is 5.66:1.
|
|
1541
|
+
textOnAccent: { light: "#ffffff", dark: "#0d1117" },
|
|
1532
1542
|
accentPrimary: { light: "#0969da", dark: "#388bfd" },
|
|
1533
1543
|
border: { light: "#d0d7de", dark: "#30363d" },
|
|
1534
1544
|
danger: { light: "#cf222e", dark: "#f85149" },
|
|
@@ -11088,6 +11098,74 @@ var init_token_colors = __esm({
|
|
|
11088
11098
|
}
|
|
11089
11099
|
});
|
|
11090
11100
|
|
|
11101
|
+
// ../../core/ts/src/idiom.ts
|
|
11102
|
+
function authored(overlays, name) {
|
|
11103
|
+
return typeof name === "string" && overlays !== void 0 && Object.hasOwn(overlays, name) && overlays[name] !== null && typeof overlays[name] === "object" && !Array.isArray(overlays[name]);
|
|
11104
|
+
}
|
|
11105
|
+
function selectIdiomOverlay(doc, ctx = {}) {
|
|
11106
|
+
const policy = doc.idiomPolicy;
|
|
11107
|
+
const overlays = doc.idiom;
|
|
11108
|
+
const isRecord3 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
11109
|
+
if (!isRecord3(policy) || !isRecord3(overlays)) return void 0;
|
|
11110
|
+
const kind = policy.policy ?? "follow-surface";
|
|
11111
|
+
if (kind === "none") return void 0;
|
|
11112
|
+
if (kind === "pinned") return authored(overlays, policy.pin) ? policy.pin : void 0;
|
|
11113
|
+
if (kind !== "follow-surface") return void 0;
|
|
11114
|
+
const surfaces = policy.surfaces;
|
|
11115
|
+
const candidates = [
|
|
11116
|
+
ctx.surface !== void 0 && isRecord3(surfaces) && Object.hasOwn(surfaces, ctx.surface) ? surfaces[ctx.surface] : void 0,
|
|
11117
|
+
...ctx.native ?? [],
|
|
11118
|
+
policy.fallback
|
|
11119
|
+
];
|
|
11120
|
+
return candidates.find((c) => authored(overlays, c));
|
|
11121
|
+
}
|
|
11122
|
+
function isPlainObject(v) {
|
|
11123
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
11124
|
+
}
|
|
11125
|
+
function deepMerge(base, overlay) {
|
|
11126
|
+
if (!isPlainObject(overlay) || !isPlainObject(base)) return overlay;
|
|
11127
|
+
const out = { ...base };
|
|
11128
|
+
for (const [key2, value] of Object.entries(overlay)) {
|
|
11129
|
+
if (UNSAFE_KEYS.has(key2)) continue;
|
|
11130
|
+
out[key2] = Object.hasOwn(base, key2) ? deepMerge(base[key2], value) : value;
|
|
11131
|
+
}
|
|
11132
|
+
return out;
|
|
11133
|
+
}
|
|
11134
|
+
function mergeIdiomOverlay(base, overlay) {
|
|
11135
|
+
const merged = deepMerge(base, overlay);
|
|
11136
|
+
const baseColors = base.colors;
|
|
11137
|
+
const overlayColors = overlay.colors;
|
|
11138
|
+
if (isPlainObject(baseColors) && isPlainObject(overlayColors)) {
|
|
11139
|
+
const colors = { ...merged.colors };
|
|
11140
|
+
for (const [name, value] of Object.entries(overlayColors)) {
|
|
11141
|
+
if (UNSAFE_KEYS.has(name)) continue;
|
|
11142
|
+
const was = Object.hasOwn(baseColors, name) ? baseColors[name] : void 0;
|
|
11143
|
+
if (typeof was === "string" && isPlainObject(value)) colors[name] = { light: was, ...value };
|
|
11144
|
+
}
|
|
11145
|
+
merged.colors = colors;
|
|
11146
|
+
}
|
|
11147
|
+
return merged;
|
|
11148
|
+
}
|
|
11149
|
+
function resolveIdiom(tokens, ctx = {}) {
|
|
11150
|
+
const doc = tokens;
|
|
11151
|
+
const name = selectIdiomOverlay(doc, ctx);
|
|
11152
|
+
if (name === void 0) return tokens;
|
|
11153
|
+
const merged = mergeIdiomOverlay(tokens, doc.idiom[name]);
|
|
11154
|
+
const { idiomPolicy: _applied, ...final } = merged;
|
|
11155
|
+
return final;
|
|
11156
|
+
}
|
|
11157
|
+
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
11158
|
+
var init_idiom = __esm({
|
|
11159
|
+
"../../core/ts/src/idiom.ts"() {
|
|
11160
|
+
IDIOM_CONTEXTS = {
|
|
11161
|
+
ios: { native: ["ios"] },
|
|
11162
|
+
android: { native: ["material"] },
|
|
11163
|
+
mac: { native: ["desktop", "ios"], surface: "mac" }
|
|
11164
|
+
};
|
|
11165
|
+
UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
11166
|
+
}
|
|
11167
|
+
});
|
|
11168
|
+
|
|
11091
11169
|
// src/token-lint.ts
|
|
11092
11170
|
import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
|
|
11093
11171
|
import { join as join16 } from "node:path";
|
|
@@ -11178,11 +11256,109 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
11178
11256
|
`${tokensPath}: colors.${problem.path} is ${problem.value} \u2014 the native runtimes parse only #RRGGBB or #RRGGBBAA` + (problem.suggestion ? `. Write ${problem.suggestion}.` : `, and this value names no colour that can be converted for you. Write the hex it should be.`)
|
|
11179
11257
|
);
|
|
11180
11258
|
}
|
|
11259
|
+
const base = contrastFindings(colors);
|
|
11260
|
+
for (const f of base) warn(`${tokensPath}: ${f.render(f.schemes)}`);
|
|
11261
|
+
if (idiom !== null && typeof idiom === "object" && !Array.isArray(idiom)) {
|
|
11262
|
+
const seen = new Set(base.flatMap((f) => f.schemes.map((s) => `${f.key}|${s}`)));
|
|
11263
|
+
for (const [overlay, layer] of Object.entries(idiom)) {
|
|
11264
|
+
const layerColors = layer?.colors;
|
|
11265
|
+
if (layerColors === null || typeof layerColors !== "object" || Array.isArray(layerColors)) continue;
|
|
11266
|
+
const merged = mergeIdiomOverlay({ colors }, { colors: layerColors }).colors;
|
|
11267
|
+
for (const f of contrastFindings(merged)) {
|
|
11268
|
+
const added = f.schemes.filter((s) => !seen.has(`${f.key}|${s}`));
|
|
11269
|
+
if (added.length) warn(`${tokensPath}: under the idiom.${overlay} overlay, ${f.render(added)}`);
|
|
11270
|
+
}
|
|
11271
|
+
}
|
|
11272
|
+
}
|
|
11181
11273
|
return issues;
|
|
11182
11274
|
}
|
|
11275
|
+
function schemeValue(token, scheme) {
|
|
11276
|
+
let v = token;
|
|
11277
|
+
if (token !== null && typeof token === "object" && !Array.isArray(token)) {
|
|
11278
|
+
const o = token;
|
|
11279
|
+
v = scheme === "highContrast" ? o.highContrast ?? o.dark ?? o.light : scheme === "dark" ? o.dark ?? o.light : o.light;
|
|
11280
|
+
}
|
|
11281
|
+
return typeof v === "string" && isCanonicalHex(v) ? v.trim().toUpperCase() : void 0;
|
|
11282
|
+
}
|
|
11283
|
+
function paintedOver(fg, bg) {
|
|
11284
|
+
if (bg.length === 9 && bg.slice(7) !== "FF") return void 0;
|
|
11285
|
+
if (fg.length === 9) return mixHex(fg.slice(0, 7), bg.slice(0, 7), parseInt(fg.slice(7), 16) / 255);
|
|
11286
|
+
return fg;
|
|
11287
|
+
}
|
|
11288
|
+
function sameHueForContrast(fg, bg, target = AA_TEXT) {
|
|
11289
|
+
const base = fg.slice(0, 7);
|
|
11290
|
+
const opaqueBg = bg.slice(0, 7);
|
|
11291
|
+
const pole = contrastRatio("#000000", opaqueBg) >= contrastRatio("#FFFFFF", opaqueBg) ? "#000000" : "#FFFFFF";
|
|
11292
|
+
for (let step = 0; step <= 100; step++) {
|
|
11293
|
+
const candidate = mixHex(base, pole, 1 - step / 100);
|
|
11294
|
+
if (contrastRatio(candidate, opaqueBg) >= target) return candidate;
|
|
11295
|
+
}
|
|
11296
|
+
return void 0;
|
|
11297
|
+
}
|
|
11298
|
+
function contrastFindings(colors) {
|
|
11299
|
+
const declared = /* @__PURE__ */ new Set(["light"]);
|
|
11300
|
+
for (const v of Object.values(colors)) {
|
|
11301
|
+
if (v === null || typeof v !== "object" || Array.isArray(v)) continue;
|
|
11302
|
+
for (const s of SCHEMES) if (s in v) declared.add(s);
|
|
11303
|
+
}
|
|
11304
|
+
const findings = /* @__PURE__ */ new Map();
|
|
11305
|
+
for (const pair of CONTRAST_PAIRS) {
|
|
11306
|
+
const fgName = pair.fg;
|
|
11307
|
+
if (colors[fgName] === void 0 || colors[pair.bg] === void 0) continue;
|
|
11308
|
+
for (const scheme of SCHEMES) {
|
|
11309
|
+
if (!declared.has(scheme)) continue;
|
|
11310
|
+
const fg = schemeValue(colors[fgName], scheme);
|
|
11311
|
+
const bg = schemeValue(colors[pair.bg], scheme);
|
|
11312
|
+
if (!fg || !bg) continue;
|
|
11313
|
+
const painted = paintedOver(fg, bg);
|
|
11314
|
+
if (!painted) continue;
|
|
11315
|
+
const opaqueBg = bg.slice(0, 7);
|
|
11316
|
+
const ratio = contrastRatio(painted, opaqueBg);
|
|
11317
|
+
if (ratio >= AA_TEXT) continue;
|
|
11318
|
+
const key2 = `${fgName}|${pair.bg}|${fg}|${bg}`;
|
|
11319
|
+
const same2 = findings.get(key2);
|
|
11320
|
+
if (same2) {
|
|
11321
|
+
same2.schemes.push(scheme);
|
|
11322
|
+
continue;
|
|
11323
|
+
}
|
|
11324
|
+
const darker = contrastRatio("#000000", opaqueBg) >= contrastRatio("#FFFFFF", opaqueBg);
|
|
11325
|
+
const ink = darker ? "#000000" : "#FFFFFF";
|
|
11326
|
+
const suggestion = pair.suggest === "same-hue" ? sameHueForContrast(painted, opaqueBg) : pair.suggest === "ink" && contrastRatio(ink, opaqueBg) >= AA_TEXT ? ink : void 0;
|
|
11327
|
+
const fix = !suggestion ? ` Pick a ${fgName} that clears ${AA_TEXT}:1 against ${pair.bg}.` : pair.suggest === "same-hue" ? ` A ${darker ? "darker" : "lighter"} ${fgName} of the same hue that clears it is ${suggestion} (${contrastRatio(suggestion, opaqueBg).toFixed(2)}:1).` : ` ${suggestion} clears it (${contrastRatio(suggestion, opaqueBg).toFixed(2)}:1).`;
|
|
11328
|
+
findings.set(key2, {
|
|
11329
|
+
key: key2,
|
|
11330
|
+
schemes: [scheme],
|
|
11331
|
+
render: (schemes) => `colors.${fgName} (${fg}) on colors.${pair.bg} (${bg}) is ${ratio.toFixed(2)}:1 in ${schemes.join(" / ")} \u2014 below the WCAG AA ${AA_TEXT}:1 for text. ${fgName} is ${pair.use}, so that text is hard to read.${fix}`
|
|
11332
|
+
});
|
|
11333
|
+
}
|
|
11334
|
+
}
|
|
11335
|
+
return [...findings.values()];
|
|
11336
|
+
}
|
|
11337
|
+
var AA_TEXT, CONTRAST_PAIRS, SCHEMES, channels, toHex, mixHex;
|
|
11183
11338
|
var init_token_lint = __esm({
|
|
11184
11339
|
"src/token-lint.ts"() {
|
|
11185
11340
|
init_token_colors();
|
|
11341
|
+
init_idiom();
|
|
11342
|
+
AA_TEXT = 4.5;
|
|
11343
|
+
CONTRAST_PAIRS = [
|
|
11344
|
+
{
|
|
11345
|
+
fg: "accentPrimary",
|
|
11346
|
+
bg: "surfacePrimary",
|
|
11347
|
+
use: "the text colour of secondary, plain and link buttons, selected tab labels and inline action text",
|
|
11348
|
+
suggest: "same-hue"
|
|
11349
|
+
},
|
|
11350
|
+
{ fg: "accentText", bg: "surfacePrimary", use: "the dedicated colour for accent-coloured text", suggest: "same-hue" },
|
|
11351
|
+
{ fg: "textOnAccent", bg: "accentPrimary", use: "the label on filled (primary) buttons and selected chips", suggest: "ink" },
|
|
11352
|
+
{ fg: "textPrimary", bg: "surfacePrimary", use: "body and title text" },
|
|
11353
|
+
{ fg: "textSecondary", bg: "surfacePrimary", use: "secondary text (subtitles, captions, metadata)" }
|
|
11354
|
+
];
|
|
11355
|
+
SCHEMES = ["light", "dark", "highContrast"];
|
|
11356
|
+
channels = (hex2) => [1, 3, 5].map((i) => parseInt(hex2.slice(i, i + 2), 16));
|
|
11357
|
+
toHex = (rgb) => `#${rgb.map((c) => Math.round(Math.min(255, Math.max(0, c))).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
11358
|
+
mixHex = (a, b, w) => {
|
|
11359
|
+
const [ca, cb] = [channels(a), channels(b)];
|
|
11360
|
+
return toHex(ca.map((c, i) => c * w + cb[i] * (1 - w)));
|
|
11361
|
+
};
|
|
11186
11362
|
}
|
|
11187
11363
|
});
|
|
11188
11364
|
|
|
@@ -11841,8 +12017,8 @@ async function sharpOrThrow() {
|
|
|
11841
12017
|
async function inspectIconPixels(png) {
|
|
11842
12018
|
const sharp = await sharpOrThrow();
|
|
11843
12019
|
const { data, info } = await sharp(png).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
11844
|
-
const { width, height, channels:
|
|
11845
|
-
if (
|
|
12020
|
+
const { width, height, channels: channels3 } = info;
|
|
12021
|
+
if (channels3 !== 4) throw new Error(`app-icons: expected RGBA after ensureAlpha, got ${channels3} channels`);
|
|
11846
12022
|
let minAlpha = 255;
|
|
11847
12023
|
let transparent = 0;
|
|
11848
12024
|
for (let i = 3; i < data.length; i += 4) {
|
|
@@ -12691,75 +12867,6 @@ var init_face_source = __esm({
|
|
|
12691
12867
|
}
|
|
12692
12868
|
});
|
|
12693
12869
|
|
|
12694
|
-
// ../../core/ts/src/idiom.ts
|
|
12695
|
-
function authored(overlays, name) {
|
|
12696
|
-
return typeof name === "string" && overlays !== void 0 && Object.hasOwn(overlays, name) && overlays[name] !== null && typeof overlays[name] === "object" && !Array.isArray(overlays[name]);
|
|
12697
|
-
}
|
|
12698
|
-
function selectIdiomOverlay(doc, ctx = {}) {
|
|
12699
|
-
const policy = doc.idiomPolicy;
|
|
12700
|
-
const overlays = doc.idiom;
|
|
12701
|
-
const isRecord3 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
12702
|
-
if (!isRecord3(policy) || !isRecord3(overlays)) return void 0;
|
|
12703
|
-
const kind = policy.policy ?? "follow-surface";
|
|
12704
|
-
if (kind === "none") return void 0;
|
|
12705
|
-
if (kind === "pinned") return authored(overlays, policy.pin) ? policy.pin : void 0;
|
|
12706
|
-
if (kind !== "follow-surface") return void 0;
|
|
12707
|
-
const surfaces = policy.surfaces;
|
|
12708
|
-
const candidates = [
|
|
12709
|
-
ctx.surface !== void 0 && isRecord3(surfaces) && Object.hasOwn(surfaces, ctx.surface) ? surfaces[ctx.surface] : void 0,
|
|
12710
|
-
...ctx.native ?? [],
|
|
12711
|
-
policy.fallback
|
|
12712
|
-
];
|
|
12713
|
-
return candidates.find((c) => authored(overlays, c));
|
|
12714
|
-
}
|
|
12715
|
-
function isPlainObject(v) {
|
|
12716
|
-
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
12717
|
-
}
|
|
12718
|
-
function deepMerge(base, overlay) {
|
|
12719
|
-
if (!isPlainObject(overlay) || !isPlainObject(base)) return overlay;
|
|
12720
|
-
const out = { ...base };
|
|
12721
|
-
for (const [key2, value] of Object.entries(overlay)) {
|
|
12722
|
-
if (UNSAFE_KEYS.has(key2)) continue;
|
|
12723
|
-
out[key2] = Object.hasOwn(base, key2) ? deepMerge(base[key2], value) : value;
|
|
12724
|
-
}
|
|
12725
|
-
return out;
|
|
12726
|
-
}
|
|
12727
|
-
function mergeIdiomOverlay(base, overlay) {
|
|
12728
|
-
const merged = deepMerge(base, overlay);
|
|
12729
|
-
const baseColors = base.colors;
|
|
12730
|
-
const overlayColors = overlay.colors;
|
|
12731
|
-
if (isPlainObject(baseColors) && isPlainObject(overlayColors)) {
|
|
12732
|
-
const colors = { ...merged.colors };
|
|
12733
|
-
for (const [name, value] of Object.entries(overlayColors)) {
|
|
12734
|
-
if (UNSAFE_KEYS.has(name)) continue;
|
|
12735
|
-
const was = Object.hasOwn(baseColors, name) ? baseColors[name] : void 0;
|
|
12736
|
-
if (typeof was === "string" && isPlainObject(value)) colors[name] = { light: was, ...value };
|
|
12737
|
-
}
|
|
12738
|
-
merged.colors = colors;
|
|
12739
|
-
}
|
|
12740
|
-
return merged;
|
|
12741
|
-
}
|
|
12742
|
-
function resolveIdiom(tokens, ctx = {}) {
|
|
12743
|
-
const doc = tokens;
|
|
12744
|
-
const name = selectIdiomOverlay(doc, ctx);
|
|
12745
|
-
if (name === void 0) return tokens;
|
|
12746
|
-
const merged = mergeIdiomOverlay(tokens, doc.idiom[name]);
|
|
12747
|
-
const { idiomPolicy: _applied, ...final } = merged;
|
|
12748
|
-
return final;
|
|
12749
|
-
}
|
|
12750
|
-
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
12751
|
-
var init_idiom = __esm({
|
|
12752
|
-
"../../core/ts/src/idiom.ts"() {
|
|
12753
|
-
"use strict";
|
|
12754
|
-
IDIOM_CONTEXTS = {
|
|
12755
|
-
ios: { native: ["ios"] },
|
|
12756
|
-
android: { native: ["material"] },
|
|
12757
|
-
mac: { native: ["desktop", "ios"], surface: "mac" }
|
|
12758
|
-
};
|
|
12759
|
-
UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
12760
|
-
}
|
|
12761
|
-
});
|
|
12762
|
-
|
|
12763
12870
|
// ../../core/web-renderer/src/idiom-controls.ts
|
|
12764
12871
|
function pickRole(colors, role) {
|
|
12765
12872
|
if (typeof role === "string") return role;
|
|
@@ -20137,7 +20244,6 @@ function shouldRevealError(args) {
|
|
|
20137
20244
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
20138
20245
|
var init_validation = __esm({
|
|
20139
20246
|
"../../core/ts/src/validation.ts"() {
|
|
20140
|
-
"use strict";
|
|
20141
20247
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
20142
20248
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
20143
20249
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -23724,7 +23830,6 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
23724
23830
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
23725
23831
|
var init_worker_subtree = __esm({
|
|
23726
23832
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
23727
|
-
"use strict";
|
|
23728
23833
|
init_worker_subtree_safe_types_generated();
|
|
23729
23834
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
23730
23835
|
maxEncodedBytes: 65536,
|
|
@@ -36627,6 +36732,8 @@ async function bootScreenWorker(opts) {
|
|
|
36627
36732
|
...opts.inputOverride ?? {}
|
|
36628
36733
|
};
|
|
36629
36734
|
const appear = opts.skipAppear ? null : rootOnAppear(opts.descriptor);
|
|
36735
|
+
const hostCalls = [];
|
|
36736
|
+
const host = hostDispatch(opts.localDbSchema, declaredCapabilitiesOf(opts.descriptor), opts.capabilitySuccess === true, opts.clock ?? CRAWL_CLOCK);
|
|
36630
36737
|
const w = await bootBundleWorker(opts.bundleJs, {
|
|
36631
36738
|
wixCall: opts.wixCall,
|
|
36632
36739
|
input,
|
|
@@ -36635,7 +36742,10 @@ async function bootScreenWorker(opts) {
|
|
|
36635
36742
|
// while the worker believed it was 2026, so a modelled session carried a timestamp fifty-six
|
|
36636
36743
|
// years before the "now" the app computes against — inconsistent rendered dates, and any
|
|
36637
36744
|
// time-dependent branch taking the wrong arm.
|
|
36638
|
-
dispatch:
|
|
36745
|
+
dispatch: (action, params) => {
|
|
36746
|
+
hostCalls.push(String(action));
|
|
36747
|
+
return host(action, params);
|
|
36748
|
+
},
|
|
36639
36749
|
deviceParity: true,
|
|
36640
36750
|
clock: opts.clock ?? CRAWL_CLOCK,
|
|
36641
36751
|
seed: opts.seed ?? 1,
|
|
@@ -36658,7 +36768,12 @@ async function bootScreenWorker(opts) {
|
|
|
36658
36768
|
}
|
|
36659
36769
|
for (let i = 0; i < 20; i++) await yieldMacrotask();
|
|
36660
36770
|
const { state, defects } = snapshot(w);
|
|
36661
|
-
return { ...w, state: Object.keys(state).length ? state : w.services, defects, ...deadLifecycle ? { deadLifecycle } : {} };
|
|
36771
|
+
return { ...w, hostCalls, state: Object.keys(state).length ? state : w.services, defects, ...deadLifecycle ? { deadLifecycle } : {} };
|
|
36772
|
+
}
|
|
36773
|
+
function effectSince(w, mark, action, componentId) {
|
|
36774
|
+
const wix = w.calls.slice(mark.wix);
|
|
36775
|
+
const host = w.hostCalls.slice(mark.host);
|
|
36776
|
+
return wix.length || host.length ? { action, componentId, wix, host } : null;
|
|
36662
36777
|
}
|
|
36663
36778
|
function resolveSiteRows(itemsPath, valueOf) {
|
|
36664
36779
|
if (!itemsPath || itemsPath === UNTRACKED_ITEMS) return void 0;
|
|
@@ -36719,7 +36834,10 @@ async function crawlScreenCapabilitySuccess(opts) {
|
|
|
36719
36834
|
const r = await crawlScreenInner({ ...opts, capabilitySuccess: true });
|
|
36720
36835
|
return {
|
|
36721
36836
|
findings: r.findings.map((f) => ({ ...f, axis: f.axis ? `capability:success+${f.axis}` : "capability:success" })),
|
|
36722
|
-
modelled: modelled.length
|
|
36837
|
+
modelled: modelled.length,
|
|
36838
|
+
// The success arm is where a paid flow goes on past `isAvailable` to `proceedToPayment`, so
|
|
36839
|
+
// its effects are the write inventory's too — unlike its counts, they cannot double anything.
|
|
36840
|
+
...r.effects?.length ? { effects: r.effects } : {}
|
|
36723
36841
|
};
|
|
36724
36842
|
});
|
|
36725
36843
|
}
|
|
@@ -36759,6 +36877,9 @@ async function crawlScreenJourney(opts) {
|
|
|
36759
36877
|
});
|
|
36760
36878
|
const sites = actionSitesForDescriptor(opts.descriptor);
|
|
36761
36879
|
let stepsExercised = 0;
|
|
36880
|
+
const effects = [];
|
|
36881
|
+
const bootEffect = effectSince(worker, { wix: 0, host: 0 }, "boot", null);
|
|
36882
|
+
if (bootEffect) effects.push(bootEffect);
|
|
36762
36883
|
for (const step of opts.journey.steps) {
|
|
36763
36884
|
const declared = sites.find((site2) => site2.actionId === step.action && (step.component === void 0 || site2.componentId === step.component));
|
|
36764
36885
|
if (!declared) {
|
|
@@ -36781,6 +36902,7 @@ async function crawlScreenJourney(opts) {
|
|
|
36781
36902
|
fail2(`journey "${opts.journey.name}" names unavailable worker action ${step.action}`, step);
|
|
36782
36903
|
continue;
|
|
36783
36904
|
}
|
|
36905
|
+
const mark = { wix: worker.calls.length, host: worker.hostCalls.length };
|
|
36784
36906
|
try {
|
|
36785
36907
|
await handle.dispatch(parsed.action, ...workerArgs({ params: { ...site.params ?? {}, ...site.args ?? {}, ...step.params ?? {} } }));
|
|
36786
36908
|
for (let i = 0; i < 8; i++) await yieldMacrotask();
|
|
@@ -36788,6 +36910,8 @@ async function crawlScreenJourney(opts) {
|
|
|
36788
36910
|
} catch (error) {
|
|
36789
36911
|
fail2(`journey "${opts.journey.name}" step ${step.action} threw: ${errText(error)}`, step);
|
|
36790
36912
|
}
|
|
36913
|
+
const stepEffect = effectSince(worker, mark, site.actionId, site.componentId);
|
|
36914
|
+
if (stepEffect) effects.push(stepEffect);
|
|
36791
36915
|
}
|
|
36792
36916
|
const settled = snapshot(worker);
|
|
36793
36917
|
if (worker.errors.length) {
|
|
@@ -36797,7 +36921,7 @@ async function crawlScreenJourney(opts) {
|
|
|
36797
36921
|
for (const expected of opts.journey.expectText) {
|
|
36798
36922
|
if (!values.includes(expected)) fail2(`journey "${opts.journey.name}" never rendered its expected visible result: ${JSON.stringify(expected)}`);
|
|
36799
36923
|
}
|
|
36800
|
-
return { screen: opts.screenId, journey: opts.journey.name, stepsExercised, findings };
|
|
36924
|
+
return { screen: opts.screenId, journey: opts.journey.name, stepsExercised, findings, ...effects.length ? { effects } : {} };
|
|
36801
36925
|
});
|
|
36802
36926
|
}
|
|
36803
36927
|
async function crawlScreenInner(opts) {
|
|
@@ -36812,6 +36936,7 @@ async function crawlScreenInner(opts) {
|
|
|
36812
36936
|
const actionsSkipped = [];
|
|
36813
36937
|
const navEdges = [];
|
|
36814
36938
|
const unobservedActions = [];
|
|
36939
|
+
const effects = [];
|
|
36815
36940
|
let observations;
|
|
36816
36941
|
let seedWords = [];
|
|
36817
36942
|
const harvestStaticEdges = (state) => {
|
|
@@ -37095,6 +37220,8 @@ async function crawlScreenInner(opts) {
|
|
|
37095
37220
|
harvestStaticEdges(first.state);
|
|
37096
37221
|
drainWorkerEdges(first, "worker:boot");
|
|
37097
37222
|
drainPollDirectives(first, "boot");
|
|
37223
|
+
const bootEffect = effectSince(first, { wix: 0, host: 0 }, "boot", null);
|
|
37224
|
+
if (bootEffect) effects.push(bootEffect);
|
|
37098
37225
|
if (/\bwixApi\b/.test(bundleJs) && first.calls.length === 0) {
|
|
37099
37226
|
const inputGated = /himalaya\??\.input\b|\binput\s*[.?]/.test(bundleJs);
|
|
37100
37227
|
findings.push({
|
|
@@ -37180,6 +37307,7 @@ async function crawlScreenInner(opts) {
|
|
|
37180
37307
|
const dispatched = typed ? { ...effective, args: { ...effective.args ?? {}, [typed.key]: typed.value } } : effective;
|
|
37181
37308
|
const before = JSON.stringify(preState);
|
|
37182
37309
|
const callsBefore = w.calls.length;
|
|
37310
|
+
const hostBefore = w.hostCalls.length;
|
|
37183
37311
|
const errors = [];
|
|
37184
37312
|
try {
|
|
37185
37313
|
await handle.dispatch(parsed.action, ...workerArgs(dispatched));
|
|
@@ -37192,6 +37320,8 @@ async function crawlScreenInner(opts) {
|
|
|
37192
37320
|
const navCountBefore = navEdges.length;
|
|
37193
37321
|
drainWorkerEdges(w, `worker:${site.actionId}`);
|
|
37194
37322
|
drainPollDirectives(w, trigger);
|
|
37323
|
+
const tapEffect = effectSince(w, { wix: callsBefore, host: hostBefore }, site.actionId, site.componentId);
|
|
37324
|
+
if (tapEffect) effects.push(tapEffect);
|
|
37195
37325
|
if (!errors.length && navEdges.length === navCountBefore && w.calls.length === callsBefore && JSON.stringify(state) === before) {
|
|
37196
37326
|
if (typed) {
|
|
37197
37327
|
findings.push({
|
|
@@ -37256,6 +37386,7 @@ async function crawlScreenInner(opts) {
|
|
|
37256
37386
|
actionsExercised: exercised,
|
|
37257
37387
|
actionsSkipped,
|
|
37258
37388
|
navEdges: edges,
|
|
37389
|
+
...effects.length ? { effects } : {},
|
|
37259
37390
|
...observations ? { observations } : {},
|
|
37260
37391
|
...unobservedActions.length ? { unobservedActions } : {},
|
|
37261
37392
|
findings: dedupe(findings),
|
|
@@ -37474,6 +37605,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
37474
37605
|
const queue = [[]];
|
|
37475
37606
|
let dispatches = 0;
|
|
37476
37607
|
let capped = false;
|
|
37608
|
+
const effects = [];
|
|
37477
37609
|
const boot = () => bootScreenWorker({
|
|
37478
37610
|
bundleJs,
|
|
37479
37611
|
descriptor,
|
|
@@ -37494,6 +37626,13 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
37494
37626
|
}
|
|
37495
37627
|
const path2 = queue.shift();
|
|
37496
37628
|
const w = await boot();
|
|
37629
|
+
let pending = null;
|
|
37630
|
+
const flushStep = () => {
|
|
37631
|
+
if (!pending) return;
|
|
37632
|
+
const e = effectSince(w, pending.mark, pending.site.actionId, pending.site.componentId);
|
|
37633
|
+
if (e) effects.push(e);
|
|
37634
|
+
pending = null;
|
|
37635
|
+
};
|
|
37497
37636
|
try {
|
|
37498
37637
|
let threwAt = null;
|
|
37499
37638
|
for (const [step, siteIdx] of path2.entries()) {
|
|
@@ -37515,6 +37654,8 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
37515
37654
|
break;
|
|
37516
37655
|
}
|
|
37517
37656
|
dispatches += 1;
|
|
37657
|
+
flushStep();
|
|
37658
|
+
pending = { mark: { wix: w.calls.length, host: w.hostCalls.length }, site };
|
|
37518
37659
|
try {
|
|
37519
37660
|
await handle.dispatch(parsed.action, ...workerArgs(effective));
|
|
37520
37661
|
} catch (e) {
|
|
@@ -37535,8 +37676,12 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
37535
37676
|
break;
|
|
37536
37677
|
}
|
|
37537
37678
|
}
|
|
37538
|
-
if (threwAt)
|
|
37679
|
+
if (threwAt) {
|
|
37680
|
+
flushStep();
|
|
37681
|
+
continue;
|
|
37682
|
+
}
|
|
37539
37683
|
for (let i = 0; i < 20; i++) await yieldMacrotask();
|
|
37684
|
+
flushStep();
|
|
37540
37685
|
const { state, defects } = snapshot(w);
|
|
37541
37686
|
const hash = deepStateSignature(state, defects);
|
|
37542
37687
|
if (visited.has(hash)) continue;
|
|
@@ -37581,7 +37726,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
37581
37726
|
w.dispose();
|
|
37582
37727
|
}
|
|
37583
37728
|
}
|
|
37584
|
-
return { findings: dedupe(findings), nodesVisited: visited.size, dispatches, capped };
|
|
37729
|
+
return { findings: dedupe(findings), nodesVisited: visited.size, dispatches, capped, ...effects.length ? { effects } : {} };
|
|
37585
37730
|
});
|
|
37586
37731
|
}
|
|
37587
37732
|
function effectiveSiteForRow(site, row) {
|
|
@@ -40896,11 +41041,11 @@ function notCarriedDiff(local, base) {
|
|
|
40896
41041
|
const CARRIED = /* @__PURE__ */ new Set(["screens", "bundles", "tokensHash", "appConfigHash"]);
|
|
40897
41042
|
const PROVENANCE = /* @__PURE__ */ new Set(["releaseId", "gitSha", "shellSha", "label", "notes", "publishedAt", "publishedBy", "attestation", "forcedPastErrors", "app", "appSourceHash"]);
|
|
40898
41043
|
const REPORTED_IN_DETAIL = /* @__PURE__ */ new Set(["assets", "minBinaryVersion", "iconHash"]);
|
|
40899
|
-
const
|
|
41044
|
+
const comparable2 = (key2, value) => key2 === "widgets" ? stableWidgets(value) : value;
|
|
40900
41045
|
for (const key2 of /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(base)])) {
|
|
40901
41046
|
if (CARRIED.has(key2) || PROVENANCE.has(key2) || REPORTED_IN_DETAIL.has(key2)) continue;
|
|
40902
|
-
const l =
|
|
40903
|
-
const b =
|
|
41047
|
+
const l = comparable2(key2, local[key2] ?? null);
|
|
41048
|
+
const b = comparable2(key2, base[key2] ?? null);
|
|
40904
41049
|
const ls = JSON.stringify(l) ?? "null";
|
|
40905
41050
|
const bs = JSON.stringify(b) ?? "null";
|
|
40906
41051
|
if (ls === bs) continue;
|
|
@@ -42067,6 +42212,7 @@ var init_home_descriptor = __esm({
|
|
|
42067
42212
|
var template_trim_exports = {};
|
|
42068
42213
|
__export(template_trim_exports, {
|
|
42069
42214
|
TrimRefusal: () => TrimRefusal,
|
|
42215
|
+
compareErrors: () => compareErrors,
|
|
42070
42216
|
leftoverNavRefs: () => leftoverNavRefs,
|
|
42071
42217
|
linearSafePattern: () => linearSafePattern,
|
|
42072
42218
|
parseApp: () => parseApp,
|
|
@@ -42835,6 +42981,16 @@ async function runTemplateTrim(req, deps) {
|
|
|
42835
42981
|
if (!existsSync42(path2) || !readFileSync46(path2).equals(original)) writeFileSync15(path2, original);
|
|
42836
42982
|
}
|
|
42837
42983
|
for (const name of [...moved].reverse()) renameSync4(join39(backup, "tier5-src", name), join39(dir, "tier5-src", name));
|
|
42984
|
+
moved.length = 0;
|
|
42985
|
+
};
|
|
42986
|
+
const apply = () => {
|
|
42987
|
+
const moveDir = deps.moveDir ?? renameSync4;
|
|
42988
|
+
for (const name of plan.removedWorkers) {
|
|
42989
|
+
moveDir(join39(dir, "tier5-src", name), join39(backup, "tier5-src", name));
|
|
42990
|
+
moved.push(name);
|
|
42991
|
+
}
|
|
42992
|
+
if (plan.dev !== dev) writeFileSync15(devPath, plan.dev);
|
|
42993
|
+
if (plan.config !== config) writeFileSync15(configPath, plan.config);
|
|
42838
42994
|
};
|
|
42839
42995
|
const dropBackup = () => {
|
|
42840
42996
|
rmSync8(backup, { recursive: true, force: true });
|
|
@@ -42873,13 +43029,7 @@ async function runTemplateTrim(req, deps) {
|
|
|
42873
43029
|
return { code: 1, result: { ok: false, error: `could not back up the app before trimming it (${e.message}); nothing was changed`, rolledBack: true, ...base() } };
|
|
42874
43030
|
}
|
|
42875
43031
|
try {
|
|
42876
|
-
|
|
42877
|
-
for (const name of plan.removedWorkers) {
|
|
42878
|
-
moveDir(join39(dir, "tier5-src", name), join39(backup, "tier5-src", name));
|
|
42879
|
-
moved.push(name);
|
|
42880
|
-
}
|
|
42881
|
-
if (plan.dev !== dev) writeFileSync15(devPath, plan.dev);
|
|
42882
|
-
if (plan.config !== config) writeFileSync15(configPath, plan.config);
|
|
43032
|
+
apply();
|
|
42883
43033
|
} catch (e) {
|
|
42884
43034
|
return abort("the trim failed while writing", e);
|
|
42885
43035
|
}
|
|
@@ -42896,9 +43046,53 @@ async function runTemplateTrim(req, deps) {
|
|
|
42896
43046
|
} catch (e) {
|
|
42897
43047
|
return abort("the trim could not be checked", e, validate3);
|
|
42898
43048
|
}
|
|
43049
|
+
let compared;
|
|
43050
|
+
if (failure && validate3 && validate3.code !== 0 && comparable(validate3)) {
|
|
43051
|
+
try {
|
|
43052
|
+
restore();
|
|
43053
|
+
} catch (e) {
|
|
43054
|
+
return abort(String(failure.error), e, validate3);
|
|
43055
|
+
}
|
|
43056
|
+
let original;
|
|
43057
|
+
try {
|
|
43058
|
+
original = await deps.validate(dir, { fresh: true });
|
|
43059
|
+
} catch {
|
|
43060
|
+
}
|
|
43061
|
+
if (original && comparable(original)) {
|
|
43062
|
+
compared = compareErrors(validate3.errors ?? [], original.code === 0 ? [] : original.errors ?? []);
|
|
43063
|
+
}
|
|
43064
|
+
const clean2 = compared !== void 0 && compared.introduced.length === 0;
|
|
43065
|
+
if (clean2 || req.force) {
|
|
43066
|
+
try {
|
|
43067
|
+
apply();
|
|
43068
|
+
} catch (e) {
|
|
43069
|
+
return abort("the trim failed while re-applying it after validating the untrimmed app", e, validate3);
|
|
43070
|
+
}
|
|
43071
|
+
}
|
|
43072
|
+
if (clean2) failure = void 0;
|
|
43073
|
+
else if (compared) {
|
|
43074
|
+
failure = {
|
|
43075
|
+
...failure,
|
|
43076
|
+
error: `himi validate --strict failed on the trimmed app \u2014 the trim introduced ${plural(compared.introduced.length, "error")} the untrimmed app does not have: ${summarize3(compared.introduced)}`,
|
|
43077
|
+
introducedErrors: compared.introduced,
|
|
43078
|
+
preExistingErrors: compared.preExisting
|
|
43079
|
+
};
|
|
43080
|
+
}
|
|
43081
|
+
}
|
|
42899
43082
|
if (!failure) {
|
|
42900
43083
|
dropBackup();
|
|
42901
|
-
|
|
43084
|
+
const preExisting = compared?.preExisting ?? [];
|
|
43085
|
+
return {
|
|
43086
|
+
code: 0,
|
|
43087
|
+
result: {
|
|
43088
|
+
ok: true,
|
|
43089
|
+
...base(validate3),
|
|
43090
|
+
...preExisting.length ? {
|
|
43091
|
+
preExistingErrors: preExisting,
|
|
43092
|
+
note: `trimmed; ${plural(preExisting.length, "error")} ${preExisting.length === 1 ? "was" : "were"} already present before trim: ${summarize3(preExisting)}`
|
|
43093
|
+
} : {}
|
|
43094
|
+
}
|
|
43095
|
+
};
|
|
42902
43096
|
}
|
|
42903
43097
|
if (req.force) {
|
|
42904
43098
|
return {
|
|
@@ -42917,7 +43111,36 @@ async function runTemplateTrim(req, deps) {
|
|
|
42917
43111
|
result: { ok: false, ...failure, rolledBack: true, hint: "nothing changed \u2014 fix what validate reports (or keep more screens) and trim again, or pass --force to keep the trimmed tree anyway", ...base(validate3) }
|
|
42918
43112
|
};
|
|
42919
43113
|
}
|
|
42920
|
-
|
|
43114
|
+
function comparable(v) {
|
|
43115
|
+
if (v.code === 0) return true;
|
|
43116
|
+
if (!v.errors?.length) return false;
|
|
43117
|
+
return v.counts === void 0 || v.counts.errors === v.errors.length;
|
|
43118
|
+
}
|
|
43119
|
+
function compareErrors(trimmed, original) {
|
|
43120
|
+
const left = /* @__PURE__ */ new Map();
|
|
43121
|
+
for (const e of original) left.set(e.id, (left.get(e.id) ?? 0) + 1);
|
|
43122
|
+
const out = { preExisting: [], introduced: [] };
|
|
43123
|
+
for (const e of trimmed) {
|
|
43124
|
+
const n = left.get(e.id) ?? 0;
|
|
43125
|
+
if (n > 0) {
|
|
43126
|
+
left.set(e.id, n - 1);
|
|
43127
|
+
out.preExisting.push(e);
|
|
43128
|
+
} else out.introduced.push(e);
|
|
43129
|
+
}
|
|
43130
|
+
return out;
|
|
43131
|
+
}
|
|
43132
|
+
function summarize3(errors) {
|
|
43133
|
+
const one = (e) => {
|
|
43134
|
+
const rule = e.pass ? e.ruleCode && e.ruleCode !== e.pass ? `${e.pass}/${e.ruleCode}` : e.pass : e.ruleCode;
|
|
43135
|
+
const place = e.screen ? `on ${e.screen}` : e.path ? `in ${e.path}` : void 0;
|
|
43136
|
+
const where = [rule, place].filter(Boolean).join(" ");
|
|
43137
|
+
const msg = e.message.length > 160 ? `${e.message.slice(0, 157)}...` : e.message;
|
|
43138
|
+
return where ? `${where}: ${msg}` : msg;
|
|
43139
|
+
};
|
|
43140
|
+
const shown2 = errors.slice(0, 5).map(one).join("; ");
|
|
43141
|
+
return errors.length > 5 ? `${shown2}; and ${errors.length - 5} more` : shown2;
|
|
43142
|
+
}
|
|
43143
|
+
var TrimRefusal, LIT, ATOM, QUANT, CAP, SAFE_ROUTE_PATTERN, lineOf, isStatic, entryLabel, isNode3, asItems, NAV_SCREEN_KEYS, sorted, refuse3, plural;
|
|
42921
43144
|
var init_template_trim = __esm({
|
|
42922
43145
|
"src/template-trim.ts"() {
|
|
42923
43146
|
init_validate_descriptor();
|
|
@@ -42951,6 +43174,7 @@ var init_template_trim = __esm({
|
|
|
42951
43174
|
NAV_SCREEN_KEYS = /* @__PURE__ */ new Set(["screenId", "parentScreenId", "contentScreenId", "badgeScreenId"]);
|
|
42952
43175
|
sorted = (xs) => [...new Set(xs)].sort();
|
|
42953
43176
|
refuse3 = (e) => ({ code: 2, result: { ok: false, error: e.message, ...e.detail } });
|
|
43177
|
+
plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
42954
43178
|
}
|
|
42955
43179
|
});
|
|
42956
43180
|
|
|
@@ -44232,6 +44456,184 @@ var init_eject = __esm({
|
|
|
44232
44456
|
}
|
|
44233
44457
|
});
|
|
44234
44458
|
|
|
44459
|
+
// src/wix-writes.ts
|
|
44460
|
+
import { existsSync as existsSync46, readFileSync as readFileSync50 } from "node:fs";
|
|
44461
|
+
import { join as join43 } from "node:path";
|
|
44462
|
+
function isProvenRead(method, path2) {
|
|
44463
|
+
if (/[#\x00-\x1F\x7F]/.test(path2)) return false;
|
|
44464
|
+
const verb = method.toUpperCase();
|
|
44465
|
+
if (verb === "GET") return true;
|
|
44466
|
+
const bare = path2.split("?")[0].replace(/\/+$/, "");
|
|
44467
|
+
return verb === "POST" && /\/(query|search|list[^/]*|get[^/]*|count|aggregate|facets|connections)$/i.test(bare);
|
|
44468
|
+
}
|
|
44469
|
+
function nativeWriteOf(verb) {
|
|
44470
|
+
const exact = NATIVE_WRITES[verb];
|
|
44471
|
+
if (exact) return { canonical: verb, ...exact };
|
|
44472
|
+
const member = MEMBER_VERB.exec(verb);
|
|
44473
|
+
if (member) return { canonical: `himi.wix.${member[1]}`, ...NATIVE_WRITES[`himi.wix.${member[1]}`] };
|
|
44474
|
+
return null;
|
|
44475
|
+
}
|
|
44476
|
+
function writesFromEffects(screen, effects) {
|
|
44477
|
+
const out = [];
|
|
44478
|
+
for (const e of effects ?? []) {
|
|
44479
|
+
const base = { screen, action: e.action, ...e.componentId ? { component: e.componentId } : {} };
|
|
44480
|
+
for (const call of e.wix) {
|
|
44481
|
+
const sp = call.indexOf(" ");
|
|
44482
|
+
const method = (sp < 0 ? call : call.slice(0, sp)).toUpperCase();
|
|
44483
|
+
const path2 = sp < 0 ? "" : call.slice(sp + 1);
|
|
44484
|
+
if (isProvenRead(method, path2)) continue;
|
|
44485
|
+
out.push({ ...base, via: "wix", method, path: path2.split("?")[0] });
|
|
44486
|
+
}
|
|
44487
|
+
for (const verb of e.host) {
|
|
44488
|
+
const native = nativeWriteOf(verb);
|
|
44489
|
+
if (native) out.push({ ...base, via: "native", capability: verb, kind: native.kind, what: native.what });
|
|
44490
|
+
}
|
|
44491
|
+
}
|
|
44492
|
+
return dedupeWrites(out);
|
|
44493
|
+
}
|
|
44494
|
+
function dedupeWrites(list) {
|
|
44495
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44496
|
+
const out = [];
|
|
44497
|
+
for (const w of list) {
|
|
44498
|
+
const k = writeKey(w);
|
|
44499
|
+
if (seen.has(k)) continue;
|
|
44500
|
+
seen.add(k);
|
|
44501
|
+
out.push(w);
|
|
44502
|
+
}
|
|
44503
|
+
return out;
|
|
44504
|
+
}
|
|
44505
|
+
function unreachedNativeWrites(screen, bundleJs, observed) {
|
|
44506
|
+
if (!bundleJs) return [];
|
|
44507
|
+
const seen = new Set(observed.filter((w) => w.screen === screen && w.via === "native").map((w) => nativeWriteOf(w.capability)?.canonical));
|
|
44508
|
+
const out = [];
|
|
44509
|
+
for (const [verb, native] of Object.entries(NATIVE_WRITES)) {
|
|
44510
|
+
if (seen.has(verb)) continue;
|
|
44511
|
+
if (!BUNDLE_TEXT[verb].test(bundleJs)) continue;
|
|
44512
|
+
out.push({ screen, action: "unreached", via: "native", capability: verb, kind: native.kind, what: native.what });
|
|
44513
|
+
}
|
|
44514
|
+
return out;
|
|
44515
|
+
}
|
|
44516
|
+
function parseDataAccess(text5, from) {
|
|
44517
|
+
const body = text5.replace(/<!--[\s\S]*?(?:-->|$)/g, "");
|
|
44518
|
+
const heading = new RegExp(`(?:^|\\n)##[ \\t]+${DATA_ACCESS_HEADING}\\b[^\\n]*([\\s\\S]*?)(?=\\n##[ \\t]|$)`, "i").exec(body);
|
|
44519
|
+
if (!heading) return null;
|
|
44520
|
+
const lines = heading[1].split("\n").map((l) => l.trim()).filter((l) => l.startsWith("|"));
|
|
44521
|
+
if (lines.length < 2) return null;
|
|
44522
|
+
const cells = (line) => line.replace(/^\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
|
|
44523
|
+
const header = cells(lines[0]).map((c) => unquote(c).toLowerCase());
|
|
44524
|
+
const screenCol = header.findIndex((h) => /^screens?$/.test(h));
|
|
44525
|
+
let writesCol = header.findIndex((h) => /^wix writes?$/.test(h));
|
|
44526
|
+
if (writesCol < 0) writesCol = header.findIndex((h) => /^writes?$/.test(h));
|
|
44527
|
+
if (screenCol < 0 || writesCol < 0) return null;
|
|
44528
|
+
const rows = [];
|
|
44529
|
+
for (const line of lines.slice(1)) {
|
|
44530
|
+
if (/^\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?$/.test(line)) continue;
|
|
44531
|
+
const row = cells(line);
|
|
44532
|
+
const screen = unquote(row[screenCol] ?? "");
|
|
44533
|
+
if (!screen) continue;
|
|
44534
|
+
const cell = unquote(row[writesCol] ?? "");
|
|
44535
|
+
const entries = cell.split(/[,;]/).map((e) => e.trim()).filter((e) => e && !NONE.test(e));
|
|
44536
|
+
rows.push({ screen, allowed: NONE.test(cell) || !entries.length ? null : entries });
|
|
44537
|
+
}
|
|
44538
|
+
return rows.length ? { from, rows } : null;
|
|
44539
|
+
}
|
|
44540
|
+
function readDataAccess(dir) {
|
|
44541
|
+
for (const name of ["SPEC.md", "MOBILE-UX.md"]) {
|
|
44542
|
+
const p = join43(dir, name);
|
|
44543
|
+
if (!existsSync46(p)) continue;
|
|
44544
|
+
let text5;
|
|
44545
|
+
try {
|
|
44546
|
+
text5 = readFileSync50(p, "utf8");
|
|
44547
|
+
} catch {
|
|
44548
|
+
continue;
|
|
44549
|
+
}
|
|
44550
|
+
const plan = parseDataAccess(text5, name);
|
|
44551
|
+
if (plan) return plan;
|
|
44552
|
+
}
|
|
44553
|
+
return null;
|
|
44554
|
+
}
|
|
44555
|
+
function entryApproves(entry, w) {
|
|
44556
|
+
const e = entry.trim();
|
|
44557
|
+
const lower = e.toLowerCase();
|
|
44558
|
+
const actionTail = w.action.split(".").pop() ?? w.action;
|
|
44559
|
+
if (e === w.action || e === actionTail) return true;
|
|
44560
|
+
if (w.via === "native") {
|
|
44561
|
+
const tail = w.capability.split(".").pop();
|
|
44562
|
+
if (e === w.capability || e === tail || e === nativeWriteOf(w.capability)?.canonical) return true;
|
|
44563
|
+
if (w.kind === "payment" && /^payments?$/.test(lower)) return true;
|
|
44564
|
+
if (w.kind === "member-signup" && /^(sign-?up|register|registration|member[- ]signup)$/.test(lower)) return true;
|
|
44565
|
+
return false;
|
|
44566
|
+
}
|
|
44567
|
+
const m = /^(?:(GET|POST|PUT|PATCH|DELETE)\s+)?(\/\S*|https?:\/\/\S+)$/i.exec(e);
|
|
44568
|
+
if (!m) return false;
|
|
44569
|
+
if (m[1] && m[1].toUpperCase() !== w.method) return false;
|
|
44570
|
+
return pathPattern(m[2]).test(w.path);
|
|
44571
|
+
}
|
|
44572
|
+
function pathPattern(p) {
|
|
44573
|
+
const body = p.replace(/\/+$/, "").split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join("[^/]+");
|
|
44574
|
+
return new RegExp(`^${body}/?$`);
|
|
44575
|
+
}
|
|
44576
|
+
function unapprovedWriteFindings(writes, plan) {
|
|
44577
|
+
if (!plan) return [];
|
|
44578
|
+
const byScreen = /* @__PURE__ */ new Map();
|
|
44579
|
+
for (const row of plan.rows) {
|
|
44580
|
+
const list = byScreen.get(row.screen) ?? [];
|
|
44581
|
+
list.push(row);
|
|
44582
|
+
byScreen.set(row.screen, list);
|
|
44583
|
+
}
|
|
44584
|
+
const findings = [];
|
|
44585
|
+
for (const w of writes) {
|
|
44586
|
+
const rows = byScreen.get(w.screen) ?? byScreen.get("*");
|
|
44587
|
+
const unreached = w.action === "unreached";
|
|
44588
|
+
const trigger = w.action === "boot" || unreached ? "boot" : { tap: w.component ?? null, key: "write", action: w.action };
|
|
44589
|
+
const does = unreached ? `can write to Wix (${writeLabel(w)} \u2014 its worker bundle calls it, on a path this crawl did not reach)` : `writes to Wix (${writeLabel(w)})`;
|
|
44590
|
+
const hint = `Before publishing, reconcile this with the owner-approved plan: remove the action (or trim the screen with \`himi template trim\`) if the owner did not approve it, or name the write in ${plan.from}'s \`## ${DATA_ACCESS_HEADING}\` table \u2014 ` + (unreached ? "" : `its action (\`${w.action.split(".").pop()}\`), `) + (w.via === "wix" ? `its endpoint (\`${w.method} ${w.path}\`)` : `its capability (\`${w.capability.split(".").pop()}\`)`) + ` \u2014 once they have.`;
|
|
44591
|
+
if (!rows) {
|
|
44592
|
+
findings.push({
|
|
44593
|
+
screen: w.screen,
|
|
44594
|
+
trigger,
|
|
44595
|
+
invariant: "write-not-approved",
|
|
44596
|
+
severity: "warning",
|
|
44597
|
+
message: `${does}, and ${plan.from}'s data-access table has no row for this screen`,
|
|
44598
|
+
hint
|
|
44599
|
+
});
|
|
44600
|
+
continue;
|
|
44601
|
+
}
|
|
44602
|
+
const allowed2 = rows.flatMap((r) => r.allowed ?? []);
|
|
44603
|
+
if (allowed2.some((entry) => entryApproves(entry, w))) continue;
|
|
44604
|
+
findings.push({
|
|
44605
|
+
screen: w.screen,
|
|
44606
|
+
trigger,
|
|
44607
|
+
invariant: "write-not-approved",
|
|
44608
|
+
severity: "warning",
|
|
44609
|
+
message: allowed2.length ? `${does}, which ${plan.from}'s data-access table does not name for this screen (approved: ${allowed2.join(", ")})` : `${does}, but ${plan.from}'s data-access table approves no writes on this screen`,
|
|
44610
|
+
hint
|
|
44611
|
+
});
|
|
44612
|
+
}
|
|
44613
|
+
return findings;
|
|
44614
|
+
}
|
|
44615
|
+
var NATIVE_WRITES, MEMBER_VERB, BUNDLE_TEXT, writeKey, writeLabel, DATA_ACCESS_HEADING, NONE, unquote;
|
|
44616
|
+
var init_wix_writes = __esm({
|
|
44617
|
+
"src/wix-writes.ts"() {
|
|
44618
|
+
NATIVE_WRITES = {
|
|
44619
|
+
"himi.wix.registerDirect": { kind: "member-signup", what: "creates a site member" },
|
|
44620
|
+
"himi.wix.resetPassword": { kind: "member-account", what: "sends a site member a password-reset email" },
|
|
44621
|
+
"capability.wix_cashier.proceedToPayment": { kind: "payment", what: "charges the customer through the Wix cashier" }
|
|
44622
|
+
};
|
|
44623
|
+
MEMBER_VERB = /^[a-z_]+\.wix\.(registerDirect|resetPassword)$/;
|
|
44624
|
+
BUNDLE_TEXT = {
|
|
44625
|
+
"himi.wix.registerDirect": /["'`][a-z_]+\.wix\.registerDirect["'`]|\}(?:\.wix)?\.registerDirect`/,
|
|
44626
|
+
"himi.wix.resetPassword": /["'`][a-z_]+\.wix\.resetPassword["'`]|\}(?:\.wix)?\.resetPassword`/,
|
|
44627
|
+
"capability.wix_cashier.proceedToPayment": /capability\.wix_cashier\.proceedToPayment["'`]/
|
|
44628
|
+
};
|
|
44629
|
+
writeKey = (w) => [w.screen, w.action, w.via, w.method ?? "", w.path ?? "", w.capability ?? ""].join("|");
|
|
44630
|
+
writeLabel = (w) => w.via === "wix" ? `${w.method} ${w.path}` : `${w.capability} (${w.what})`;
|
|
44631
|
+
DATA_ACCESS_HEADING = "Data access";
|
|
44632
|
+
NONE = /^(|-+|—|–|none|no|nothing|n\/a|na|read[- ]only|reads? only|✗|×)$/i;
|
|
44633
|
+
unquote = (cell) => cell.replace(/`/g, "").trim();
|
|
44634
|
+
}
|
|
44635
|
+
});
|
|
44636
|
+
|
|
44235
44637
|
// src/test.ts
|
|
44236
44638
|
var test_exports = {};
|
|
44237
44639
|
__export(test_exports, {
|
|
@@ -44248,14 +44650,14 @@ __export(test_exports, {
|
|
|
44248
44650
|
scopeDescriptors: () => scopeDescriptors,
|
|
44249
44651
|
writeRecordedMocks: () => writeRecordedMocks
|
|
44250
44652
|
});
|
|
44251
|
-
import { existsSync as
|
|
44252
|
-
import { join as
|
|
44653
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync23, readFileSync as readFileSync51, writeFileSync as writeFileSync19 } from "node:fs";
|
|
44654
|
+
import { join as join44, resolve as resolve40 } from "node:path";
|
|
44253
44655
|
function readTestConfig(dir) {
|
|
44254
44656
|
const p = resolve40(dir, TEST_CONFIG_FILE);
|
|
44255
|
-
if (!
|
|
44657
|
+
if (!existsSync47(p)) return {};
|
|
44256
44658
|
let parsed;
|
|
44257
44659
|
try {
|
|
44258
|
-
parsed = JSON.parse(
|
|
44660
|
+
parsed = JSON.parse(readFileSync51(p, "utf8"));
|
|
44259
44661
|
} catch (e) {
|
|
44260
44662
|
throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e.message}`);
|
|
44261
44663
|
}
|
|
@@ -44288,6 +44690,10 @@ function readTestConfig(dir) {
|
|
|
44288
44690
|
if (step.component !== void 0 && typeof step.component !== "string") throw new Error(`${TEST_CONFIG_FILE}: journeys[${i}].steps[${stepIndex}].component must be a string`);
|
|
44289
44691
|
if (step.params !== void 0 && (!step.params || typeof step.params !== "object" || Array.isArray(step.params))) throw new Error(`${TEST_CONFIG_FILE}: journeys[${i}].steps[${stepIndex}].params must be an object`);
|
|
44290
44692
|
});
|
|
44693
|
+
const input = journey.input;
|
|
44694
|
+
if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input) || Object.values(input).some((v) => typeof v !== "string"))) {
|
|
44695
|
+
throw new Error(`${TEST_CONFIG_FILE}: journeys[${i}].input must be an object of string values \u2014 the screen input a nav edge would send, e.g. { "id": "svc-0001" }`);
|
|
44696
|
+
}
|
|
44291
44697
|
if (!Array.isArray(journey.expectText) || !journey.expectText.length || journey.expectText.some((text5) => typeof text5 !== "string" || !text5.trim())) {
|
|
44292
44698
|
throw new Error(`${TEST_CONFIG_FILE}: journeys[${i}] needs non-empty expectText values that prove a visible result`);
|
|
44293
44699
|
}
|
|
@@ -44298,7 +44704,7 @@ function readTestConfig(dir) {
|
|
|
44298
44704
|
function readNetRules(path2) {
|
|
44299
44705
|
let parsed;
|
|
44300
44706
|
try {
|
|
44301
|
-
parsed = JSON.parse(
|
|
44707
|
+
parsed = JSON.parse(readFileSync51(path2, "utf8"));
|
|
44302
44708
|
} catch (e) {
|
|
44303
44709
|
throw new Error(`--net ${path2} could not be read as JSON \u2014 ${e.message}`);
|
|
44304
44710
|
}
|
|
@@ -44319,7 +44725,7 @@ function readNetRules(path2) {
|
|
|
44319
44725
|
function defaultNetRules(dir) {
|
|
44320
44726
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
44321
44727
|
const p = resolve40(dir, rel);
|
|
44322
|
-
if (
|
|
44728
|
+
if (existsSync47(p)) {
|
|
44323
44729
|
const rules = readNetRules(p);
|
|
44324
44730
|
if (rules.length) return { rules, from: rel };
|
|
44325
44731
|
}
|
|
@@ -44335,7 +44741,7 @@ function readCannedResponses() {
|
|
|
44335
44741
|
];
|
|
44336
44742
|
for (const url of candidates) {
|
|
44337
44743
|
try {
|
|
44338
|
-
const parsed = JSON.parse(
|
|
44744
|
+
const parsed = JSON.parse(readFileSync51(url, "utf8"));
|
|
44339
44745
|
const byKey = {};
|
|
44340
44746
|
for (const [k, v] of Object.entries(parsed)) {
|
|
44341
44747
|
if (!k.startsWith("//")) byKey[k] = v;
|
|
@@ -44357,9 +44763,7 @@ function makeRecordingWixCall(send2, token, app) {
|
|
|
44357
44763
|
refused.push(`${verb} ${path2}`);
|
|
44358
44764
|
throw new Error(`--record refused ${verb} ${path2}: the path carries a fragment or control character \u2014 not a provable read`);
|
|
44359
44765
|
}
|
|
44360
|
-
|
|
44361
|
-
const readShaped = verb === "GET" || verb === "POST" && /\/(query|search|list[^/]*|get[^/]*|count|aggregate|facets|connections)$/i.test(bare);
|
|
44362
|
-
if (!readShaped) {
|
|
44766
|
+
if (!isProvenRead(verb, path2)) {
|
|
44363
44767
|
refused.push(`${verb} ${path2}`);
|
|
44364
44768
|
throw new Error(`--record refused ${verb} ${path2}: recording sends only proven reads (GET, or POST ending in /query, /search, /list*, /get*, /count, /aggregate, /facets, /connections) \u2014 if this IS a read, add its rule to dev/net-mocks.json by hand`);
|
|
44365
44769
|
}
|
|
@@ -44427,8 +44831,8 @@ function writeRecordedMocks(opts) {
|
|
|
44427
44831
|
mkdir: (p) => mkdirSync23(p, { recursive: true }),
|
|
44428
44832
|
write: (p, s) => writeFileSync19(p, s)
|
|
44429
44833
|
};
|
|
44430
|
-
fs.mkdir(
|
|
44431
|
-
fs.write(
|
|
44834
|
+
fs.mkdir(join44(opts.dir, "dev"));
|
|
44835
|
+
fs.write(join44(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
44432
44836
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
44433
44837
|
}
|
|
44434
44838
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -44496,6 +44900,7 @@ async function runCrawl(opts) {
|
|
|
44496
44900
|
const suppressed = [];
|
|
44497
44901
|
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));
|
|
44498
44902
|
const results = [];
|
|
44903
|
+
const writes = [];
|
|
44499
44904
|
const uncoveredByScreen = /* @__PURE__ */ new Map();
|
|
44500
44905
|
const coverageFns = /* @__PURE__ */ new Map();
|
|
44501
44906
|
const bundleOf = new Map(descriptors.map((d) => [d.screenId, d]));
|
|
@@ -44533,18 +44938,21 @@ async function runCrawl(opts) {
|
|
|
44533
44938
|
const cov = baked.bundleJs && deps.startWorkerCoverage ? await deps.startWorkerCoverage() : null;
|
|
44534
44939
|
const r = await deps.crawlScreen(args);
|
|
44535
44940
|
results.push(r);
|
|
44941
|
+
writes.push(...writesFromEffects(baked.screenId, r.effects));
|
|
44536
44942
|
for (const journey of opts.config?.journeys?.filter((candidate) => candidate.screen === baked.screenId) ?? []) {
|
|
44537
44943
|
if (!deps.crawlScreenJourney) {
|
|
44538
44944
|
journeyFindings.push({ screen: baked.screenId, trigger: "boot", invariant: "journey-failed", severity: "error", message: `journey "${journey.name}" cannot run because this CLI's crawl engine is too old`, hint: "Upgrade @wix/himalaya-cli so typed journeys run instead of being silently skipped." });
|
|
44539
44945
|
journeyResults.push({ name: journey.name, screen: baked.screenId, stepsExercised: 0, ok: false });
|
|
44540
44946
|
continue;
|
|
44541
44947
|
}
|
|
44542
|
-
const jr = await deps.crawlScreenJourney({ ...args, journey });
|
|
44948
|
+
const jr = await deps.crawlScreenJourney({ ...args, ...journey.input ? { inputOverride: journey.input } : {}, journey });
|
|
44949
|
+
writes.push(...writesFromEffects(baked.screenId, jr.effects));
|
|
44543
44950
|
journeyFindings.push(...jr.findings);
|
|
44544
44951
|
journeyResults.push({ name: journey.name, screen: baked.screenId, stepsExercised: jr.stepsExercised, ok: jr.findings.length === 0 });
|
|
44545
44952
|
}
|
|
44546
44953
|
if (opts.deep && opts.deep >= 2 && deps.crawlScreenDeep && baked.bundleJs) {
|
|
44547
44954
|
const dr = await deps.crawlScreenDeep(args, { depth: opts.deep });
|
|
44955
|
+
writes.push(...writesFromEffects(baked.screenId, dr.effects));
|
|
44548
44956
|
deepTotals.nodesVisited += dr.nodesVisited;
|
|
44549
44957
|
deepTotals.dispatches += dr.dispatches;
|
|
44550
44958
|
deepTotals.capped = deepTotals.capped || dr.capped;
|
|
@@ -44584,6 +44992,7 @@ async function runCrawl(opts) {
|
|
|
44584
44992
|
}
|
|
44585
44993
|
if (deps.crawlScreenCapabilitySuccess && baked.bundleJs) {
|
|
44586
44994
|
const cr = await deps.crawlScreenCapabilitySuccess(args);
|
|
44995
|
+
writes.push(...writesFromEffects(baked.screenId, cr.effects));
|
|
44587
44996
|
capabilityModelled += cr.modelled;
|
|
44588
44997
|
const keyOfC = deps.findingKey ?? ((f) => `${f.invariant}|${f.at ?? ""}|${f.screen}|${f.message}`);
|
|
44589
44998
|
const seen = new Set([...r.findings, ...relationFindings].map(keyOfC));
|
|
@@ -44660,6 +45069,7 @@ async function runCrawl(opts) {
|
|
|
44660
45069
|
list.push(...fns);
|
|
44661
45070
|
coverageFns.set(target, list);
|
|
44662
45071
|
}
|
|
45072
|
+
writes.push(...writesFromEffects(target, er.effects));
|
|
44663
45073
|
edgesFollowed.push({ target, from: shape.from, params: shape.params, via: shape.via });
|
|
44664
45074
|
if (!er.findings.some((f) => f.invariant === "no-request-issued") && !opts.tabRoots?.has(target) && !fetchProven.has(target)) {
|
|
44665
45075
|
fetchProven.set(target, { from: shape.from, params: shape.params });
|
|
@@ -44684,7 +45094,11 @@ async function runCrawl(opts) {
|
|
|
44684
45094
|
if (uncovered.length) uncoveredByScreen.set(screen, uncovered);
|
|
44685
45095
|
}
|
|
44686
45096
|
}
|
|
44687
|
-
const
|
|
45097
|
+
const inventory = dedupeWrites(writes);
|
|
45098
|
+
const unreachedWrites = targets.flatMap((d) => unreachedNativeWrites(d.screenId, d.bundleJs, inventory));
|
|
45099
|
+
const plan = readDataAccess(opts.dir);
|
|
45100
|
+
const writeFindings = unapprovedWriteFindings([...inventory, ...unreachedWrites], plan);
|
|
45101
|
+
const all = [...results.flatMap((r) => r.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings, ...relationFindings, ...writeFindings].filter((f) => {
|
|
44688
45102
|
if (f.invariant === "no-request-issued" && !f.axis && fetchProven.has(f.screen)) {
|
|
44689
45103
|
const by = fetchProven.get(f.screen);
|
|
44690
45104
|
if (!retired.some((x) => x.screen === f.screen)) retired.push({ screen: f.screen, from: by.from, params: by.params });
|
|
@@ -44738,6 +45152,9 @@ async function runCrawl(opts) {
|
|
|
44738
45152
|
...deps.crawlScreenRelations ? { relations: { checked: relationsChecked, byKind: relationsByKind } } : {},
|
|
44739
45153
|
...deps.crawlScreenCapabilitySuccess ? { capabilities: { modelled: capabilityModelled } } : {},
|
|
44740
45154
|
...journeyResults.length ? { journeys: journeyResults } : {},
|
|
45155
|
+
writes: inventory,
|
|
45156
|
+
...unreachedWrites.length ? { unreachedWrites } : {},
|
|
45157
|
+
...plan ? { writesPlan: { from: plan.from, rows: plan.rows.length } } : {},
|
|
44741
45158
|
...results.some((r) => r.observations) ? { observations: Object.fromEntries(results.filter((r) => r.observations).map((r) => [r.screen, r.observations])) } : {}
|
|
44742
45159
|
};
|
|
44743
45160
|
}
|
|
@@ -44823,6 +45240,17 @@ function formatReport(r) {
|
|
|
44823
45240
|
}
|
|
44824
45241
|
out.push("");
|
|
44825
45242
|
}
|
|
45243
|
+
if (r.writes?.length || r.unreachedWrites?.length) {
|
|
45244
|
+
out.push(` Writes to Wix (${r.writes.length}) \u2014 every write the crawl saw a worker attempt (none reached Wix). A write behind a form or a selection shows only under --deep or a journey:`);
|
|
45245
|
+
const byScreenW = /* @__PURE__ */ new Map();
|
|
45246
|
+
for (const w of r.writes) byScreenW.set(w.screen, [...byScreenW.get(w.screen) ?? [], w]);
|
|
45247
|
+
for (const [screen, list] of [...byScreenW].sort(([a], [b]) => a.localeCompare(b))) {
|
|
45248
|
+
for (const w of list) out.push(` ${screen} ${w.action === "boot" ? "on appear" : w.action} ${writeLabel(w)}`);
|
|
45249
|
+
}
|
|
45250
|
+
for (const w of r.unreachedWrites ?? []) out.push(` ${w.screen} (not reached \u2014 in its worker bundle) ${writeLabel(w)}`);
|
|
45251
|
+
out.push(r.writesPlan ? ` checked against ${r.writesPlan.from}'s \`## ${DATA_ACCESS_HEADING}\` table (${r.writesPlan.rows} row${r.writesPlan.rows === 1 ? "" : "s"}) \u2014 unapproved writes are write-not-approved warnings above` : ` no \`## ${DATA_ACCESS_HEADING}\` table (Screen + Wix writes columns) in SPEC.md or MOBILE-UX.md, so nothing checked these against the approved plan \u2014 \`himi docs himi-test\` \u2192 "Writes to Wix"`);
|
|
45252
|
+
out.push("");
|
|
45253
|
+
}
|
|
44826
45254
|
if (r.shots?.written && r.shots.dir) {
|
|
44827
45255
|
out.push(` ${r.shots.written} screenshot${r.shots.written === 1 ? "" : "s"} \u2192 ${r.shots.dir}/`);
|
|
44828
45256
|
}
|
|
@@ -44875,6 +45303,7 @@ var init_test = __esm({
|
|
|
44875
45303
|
"src/test.ts"() {
|
|
44876
45304
|
init_wix_gateway_rules();
|
|
44877
45305
|
init_crawl_layers();
|
|
45306
|
+
init_wix_writes();
|
|
44878
45307
|
TEST_CONFIG_FILE = "himi-test.json";
|
|
44879
45308
|
triggerLabel = (f) => (f.trigger === "boot" ? "on appear" : `${f.trigger.key} ${f.trigger.tap ?? "(no id)"} \u2192 ${f.trigger.action}`) + (f.axis ? ` [${f.axis}]` : "");
|
|
44880
45309
|
}
|
|
@@ -44885,14 +45314,14 @@ var mobile_ux_lint_exports = {};
|
|
|
44885
45314
|
__export(mobile_ux_lint_exports, {
|
|
44886
45315
|
mobileUxIssues: () => mobileUxIssues
|
|
44887
45316
|
});
|
|
44888
|
-
import { existsSync as
|
|
44889
|
-
import { join as
|
|
45317
|
+
import { existsSync as existsSync48, readFileSync as readFileSync52 } from "node:fs";
|
|
45318
|
+
import { join as join45 } from "node:path";
|
|
44890
45319
|
function mobileUxIssues(dir, strict) {
|
|
44891
|
-
const file =
|
|
44892
|
-
if (!
|
|
45320
|
+
const file = join45(dir, "MOBILE-UX.md");
|
|
45321
|
+
if (!existsSync48(file)) return [];
|
|
44893
45322
|
let text5;
|
|
44894
45323
|
try {
|
|
44895
|
-
text5 =
|
|
45324
|
+
text5 = readFileSync52(file, "utf8");
|
|
44896
45325
|
} catch {
|
|
44897
45326
|
return [];
|
|
44898
45327
|
}
|
|
@@ -46567,8 +46996,8 @@ __export(functions_exports, {
|
|
|
46567
46996
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
46568
46997
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
46569
46998
|
});
|
|
46570
|
-
import { readFileSync as
|
|
46571
|
-
import { join as
|
|
46999
|
+
import { readFileSync as readFileSync53, existsSync as existsSync49 } from "node:fs";
|
|
47000
|
+
import { join as join46, resolve as resolve41 } from "node:path";
|
|
46572
47001
|
function resolveFunctionsTarget(input) {
|
|
46573
47002
|
const explicitUrl = input.functionsUrl?.trim();
|
|
46574
47003
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -46587,9 +47016,9 @@ async function loadFunctionsApp(dir) {
|
|
|
46587
47016
|
}
|
|
46588
47017
|
const sources = {};
|
|
46589
47018
|
for (const definition of config.functions.functions) {
|
|
46590
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
47019
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join46(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync49);
|
|
46591
47020
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
46592
|
-
sources[definition.name] =
|
|
47021
|
+
sources[definition.name] = readFileSync53(source, "utf8");
|
|
46593
47022
|
}
|
|
46594
47023
|
const data = config.cms || config.data ? mergeDataResources(config) : void 0;
|
|
46595
47024
|
const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
|
|
@@ -46741,10 +47170,10 @@ __export(studio_reel_exports, {
|
|
|
46741
47170
|
utcDay: () => utcDay
|
|
46742
47171
|
});
|
|
46743
47172
|
import { createHash as createHash24 } from "node:crypto";
|
|
46744
|
-
import { lstatSync as lstatSync7, readFileSync as
|
|
46745
|
-
import { basename as basename11, join as
|
|
47173
|
+
import { lstatSync as lstatSync7, readFileSync as readFileSync54 } from "node:fs";
|
|
47174
|
+
import { basename as basename11, join as join47 } from "node:path";
|
|
46746
47175
|
function loadMemory2(dir) {
|
|
46747
|
-
const m = readJson4(
|
|
47176
|
+
const m = readJson4(join47(dir, ".himi", "studio", "memory.json"));
|
|
46748
47177
|
if (!isObj2(m) || m.version !== 1 || !isObj2(m.shots) || !Array.isArray(m.timeline)) return null;
|
|
46749
47178
|
const shots = [];
|
|
46750
47179
|
for (const [id, s] of Object.entries(m.shots)) {
|
|
@@ -46781,8 +47210,8 @@ function planReel(dir) {
|
|
|
46781
47210
|
const memory = loadMemory2(dir);
|
|
46782
47211
|
const { entries } = readProgress(dir);
|
|
46783
47212
|
const summary = summarizeProgress(entries);
|
|
46784
|
-
const manifest = readJson4(
|
|
46785
|
-
const tokens = readJson4(
|
|
47213
|
+
const manifest = readJson4(join47(dir, "himalaya.content.json"));
|
|
47214
|
+
const tokens = readJson4(join47(dir, "tokens.json"));
|
|
46786
47215
|
const accentToken = tokens?.colors?.accentPrimary;
|
|
46787
47216
|
const accentRaw = typeof accentToken === "string" ? accentToken : accentToken?.light;
|
|
46788
47217
|
const accent = typeof accentRaw === "string" && ACCENT.test(accentRaw) ? accentRaw : DEFAULT_ACCENT;
|
|
@@ -46824,10 +47253,10 @@ function inlineImages(dir, plan, budget = REEL_BUDGET_BYTES) {
|
|
|
46824
47253
|
const verified = (f) => {
|
|
46825
47254
|
if (!HISTORY_NAME.test(f)) return null;
|
|
46826
47255
|
try {
|
|
46827
|
-
const path2 =
|
|
47256
|
+
const path2 = join47(dir, HISTORY_DIR, f);
|
|
46828
47257
|
const st = lstatSync7(path2);
|
|
46829
47258
|
if (!st.isFile() || st.nlink !== 1) return null;
|
|
46830
|
-
const bytes2 =
|
|
47259
|
+
const bytes2 = readFileSync54(path2);
|
|
46831
47260
|
return createHash24("sha256").update(bytes2).digest("hex") === f.slice(0, 64) && imageExtension(bytes2) === f.slice(65) ? bytes2 : null;
|
|
46832
47261
|
} catch {
|
|
46833
47262
|
return null;
|
|
@@ -46961,7 +47390,7 @@ var init_studio_reel = __esm({
|
|
|
46961
47390
|
mimeOf = (file) => MIME2[file.slice(65)] ?? "image/png";
|
|
46962
47391
|
readJson4 = (file) => {
|
|
46963
47392
|
try {
|
|
46964
|
-
return JSON.parse(
|
|
47393
|
+
return JSON.parse(readFileSync54(file, "utf8"));
|
|
46965
47394
|
} catch {
|
|
46966
47395
|
return null;
|
|
46967
47396
|
}
|
|
@@ -46992,9 +47421,9 @@ __export(native_decode_exports, {
|
|
|
46992
47421
|
runNativeDecode: () => runNativeDecode
|
|
46993
47422
|
});
|
|
46994
47423
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
46995
|
-
import { existsSync as
|
|
47424
|
+
import { existsSync as existsSync50, mkdtempSync as mkdtempSync2, readFileSync as readFileSync55, rmSync as rmSync11, writeFileSync as writeFileSync20 } from "node:fs";
|
|
46996
47425
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
46997
|
-
import { join as
|
|
47426
|
+
import { join as join48 } from "node:path";
|
|
46998
47427
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
46999
47428
|
function nativeDecodePackageDir() {
|
|
47000
47429
|
return fileURLToPath20(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -47004,8 +47433,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
47004
47433
|
}
|
|
47005
47434
|
function nativeOracleShipped() {
|
|
47006
47435
|
return {
|
|
47007
|
-
ios:
|
|
47008
|
-
android:
|
|
47436
|
+
ios: existsSync50(join48(nativeDecodePackageDir(), "Package.swift")),
|
|
47437
|
+
android: existsSync50(join48(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
47009
47438
|
};
|
|
47010
47439
|
}
|
|
47011
47440
|
function detectNativeDecode(options = {}) {
|
|
@@ -47016,7 +47445,7 @@ function detectNativeDecode(options = {}) {
|
|
|
47016
47445
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
47017
47446
|
}
|
|
47018
47447
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
47019
|
-
const packageAvailable = options.packageAvailable ??
|
|
47448
|
+
const packageAvailable = options.packageAvailable ?? existsSync50(join48(packageDir, "Package.swift"));
|
|
47020
47449
|
if (!packageAvailable) {
|
|
47021
47450
|
return {
|
|
47022
47451
|
platform: "ios",
|
|
@@ -47028,7 +47457,7 @@ function detectNativeDecode(options = {}) {
|
|
|
47028
47457
|
}
|
|
47029
47458
|
function localPropertiesSdk(harnessDir) {
|
|
47030
47459
|
try {
|
|
47031
|
-
const match =
|
|
47460
|
+
const match = readFileSync55(join48(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
47032
47461
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
47033
47462
|
} catch {
|
|
47034
47463
|
return null;
|
|
@@ -47036,8 +47465,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
47036
47465
|
}
|
|
47037
47466
|
function detectAndroidNativeDecode(options = {}) {
|
|
47038
47467
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
47039
|
-
const gradlew =
|
|
47040
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
47468
|
+
const gradlew = join48(harnessDir, "gradlew");
|
|
47469
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync50(gradlew);
|
|
47041
47470
|
if (!gradlewAvailable) {
|
|
47042
47471
|
return {
|
|
47043
47472
|
platform: "android",
|
|
@@ -47047,7 +47476,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
47047
47476
|
}
|
|
47048
47477
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
47049
47478
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
47050
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
47479
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync50(sdk));
|
|
47051
47480
|
if (!sdkAvailable) {
|
|
47052
47481
|
return {
|
|
47053
47482
|
platform: "android",
|
|
@@ -47119,14 +47548,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
47119
47548
|
return verdicts;
|
|
47120
47549
|
}
|
|
47121
47550
|
function runNativeDecode(options) {
|
|
47122
|
-
const descriptorDir = mkdtempSync2(
|
|
47551
|
+
const descriptorDir = mkdtempSync2(join48(tmpdir3(), "himi-native-decode-"));
|
|
47123
47552
|
const startedAt = Date.now();
|
|
47124
47553
|
try {
|
|
47125
47554
|
for (const descriptor of options.descriptors) {
|
|
47126
47555
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
47127
47556
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
47128
47557
|
}
|
|
47129
|
-
writeFileSync20(
|
|
47558
|
+
writeFileSync20(join48(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
47130
47559
|
}
|
|
47131
47560
|
options.progress?.("building cached Swift oracle");
|
|
47132
47561
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -47138,7 +47567,7 @@ function runNativeDecode(options) {
|
|
|
47138
47567
|
encoding: "utf8"
|
|
47139
47568
|
}).trim();
|
|
47140
47569
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
47141
|
-
const stdout = execFileSync5(
|
|
47570
|
+
const stdout = execFileSync5(join48(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
47142
47571
|
stdio: ["ignore", "pipe", "pipe"],
|
|
47143
47572
|
encoding: "utf8"
|
|
47144
47573
|
});
|
|
@@ -47156,15 +47585,15 @@ function runNativeDecode(options) {
|
|
|
47156
47585
|
}
|
|
47157
47586
|
}
|
|
47158
47587
|
function runAndroidNativeDecode(options) {
|
|
47159
|
-
const descriptorDir = mkdtempSync2(
|
|
47160
|
-
const outputPath =
|
|
47588
|
+
const descriptorDir = mkdtempSync2(join48(tmpdir3(), "himi-native-decode-android-"));
|
|
47589
|
+
const outputPath = join48(descriptorDir, "verdicts.ndjson");
|
|
47161
47590
|
const startedAt = Date.now();
|
|
47162
47591
|
try {
|
|
47163
47592
|
for (const descriptor of options.descriptors) {
|
|
47164
47593
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
47165
47594
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
47166
47595
|
}
|
|
47167
|
-
writeFileSync20(
|
|
47596
|
+
writeFileSync20(join48(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
47168
47597
|
}
|
|
47169
47598
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
47170
47599
|
execFileSync5(options.gradlew, [
|
|
@@ -47179,7 +47608,7 @@ function runAndroidNativeDecode(options) {
|
|
|
47179
47608
|
stdio: ["ignore", "ignore", "pipe"],
|
|
47180
47609
|
encoding: "utf8"
|
|
47181
47610
|
});
|
|
47182
|
-
const stdout =
|
|
47611
|
+
const stdout = readFileSync55(outputPath, "utf8");
|
|
47183
47612
|
return {
|
|
47184
47613
|
platform: "android",
|
|
47185
47614
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -47249,13 +47678,13 @@ __export(browser_authoring_exports, {
|
|
|
47249
47678
|
});
|
|
47250
47679
|
import { createServer as createServer3 } from "node:http";
|
|
47251
47680
|
import { createHash as createHash25, randomBytes as randomBytes4 } from "node:crypto";
|
|
47252
|
-
import { existsSync as
|
|
47253
|
-
import { join as
|
|
47681
|
+
import { existsSync as existsSync51, readdirSync as readdirSync24, readFileSync as readFileSync56, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
|
|
47682
|
+
import { join as join49, posix, relative as relative8, sep as sep12 } from "node:path";
|
|
47254
47683
|
function humanMs(ms) {
|
|
47255
47684
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
47256
47685
|
}
|
|
47257
47686
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
47258
|
-
const root =
|
|
47687
|
+
const root = join49(tier5SrcDir, bundleName);
|
|
47259
47688
|
const files = {};
|
|
47260
47689
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
47261
47690
|
const walk2 = (abs, rel) => {
|
|
@@ -47263,16 +47692,16 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
|
47263
47692
|
if (visitedDirs.has(real)) return;
|
|
47264
47693
|
visitedDirs.add(real);
|
|
47265
47694
|
for (const name of readdirSync24(abs).sort()) {
|
|
47266
|
-
const childAbs =
|
|
47695
|
+
const childAbs = join49(abs, name);
|
|
47267
47696
|
const childRel = posix.join(rel, name);
|
|
47268
47697
|
if (statSync12(childAbs).isDirectory()) {
|
|
47269
47698
|
walk2(childAbs, childRel);
|
|
47270
47699
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
47271
|
-
files[childRel] =
|
|
47700
|
+
files[childRel] = readFileSync56(childAbs, "utf8");
|
|
47272
47701
|
}
|
|
47273
47702
|
}
|
|
47274
47703
|
};
|
|
47275
|
-
if (!
|
|
47704
|
+
if (!existsSync51(root)) return null;
|
|
47276
47705
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
47277
47706
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
47278
47707
|
if (!entry) return null;
|
|
@@ -47289,20 +47718,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
47289
47718
|
const spec = m[1];
|
|
47290
47719
|
const virtual = posix.normalize(posix.join(dir, spec));
|
|
47291
47720
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
47292
|
-
const onDisk =
|
|
47721
|
+
const onDisk = join49(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
47293
47722
|
const candidates = [
|
|
47294
47723
|
onDisk,
|
|
47295
47724
|
`${onDisk}.ts`,
|
|
47296
47725
|
`${onDisk}.js`,
|
|
47297
47726
|
onDisk.replace(/\.js$/, ".ts"),
|
|
47298
|
-
|
|
47299
|
-
|
|
47727
|
+
join49(onDisk, "index.ts"),
|
|
47728
|
+
join49(onDisk, "index.js")
|
|
47300
47729
|
];
|
|
47301
47730
|
for (const abs of candidates) {
|
|
47302
|
-
if (!
|
|
47731
|
+
if (!existsSync51(abs) || statSync12(abs).isDirectory()) continue;
|
|
47303
47732
|
const key2 = `/tier5-src/${relative8(tier5SrcDir, abs).split(sep12).join(posix.sep)}`;
|
|
47304
47733
|
if (key2 in files) break;
|
|
47305
|
-
files[key2] =
|
|
47734
|
+
files[key2] = readFileSync56(abs, "utf8");
|
|
47306
47735
|
queue.push(key2);
|
|
47307
47736
|
break;
|
|
47308
47737
|
}
|
|
@@ -47337,7 +47766,7 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
47337
47766
|
function sdkSubpathReader(resolve48) {
|
|
47338
47767
|
return (sub) => {
|
|
47339
47768
|
try {
|
|
47340
|
-
return
|
|
47769
|
+
return readFileSync56(resolve48(`@wix/himalaya/${sub}`), "utf8");
|
|
47341
47770
|
} catch {
|
|
47342
47771
|
return null;
|
|
47343
47772
|
}
|
|
@@ -47509,8 +47938,8 @@ __export(coverage_exports, {
|
|
|
47509
47938
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
47510
47939
|
trendAndStore: () => trendAndStore
|
|
47511
47940
|
});
|
|
47512
|
-
import { existsSync as
|
|
47513
|
-
import { dirname as dirname26, join as
|
|
47941
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync24, readFileSync as readFileSync57, writeFileSync as writeFileSync21 } from "node:fs";
|
|
47942
|
+
import { dirname as dirname26, join as join50 } from "node:path";
|
|
47514
47943
|
function suppressedNativeKeys(oracle) {
|
|
47515
47944
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
47516
47945
|
}
|
|
@@ -47690,11 +48119,11 @@ function assembleLedger(r, options = {}) {
|
|
|
47690
48119
|
return out;
|
|
47691
48120
|
}
|
|
47692
48121
|
function trendAndStore(dir, entries, suppressed) {
|
|
47693
|
-
const p =
|
|
48122
|
+
const p = join50(dir, LEDGER_FILE);
|
|
47694
48123
|
let previous = null;
|
|
47695
48124
|
try {
|
|
47696
|
-
if (
|
|
47697
|
-
const parsed = JSON.parse(
|
|
48125
|
+
if (existsSync52(p)) {
|
|
48126
|
+
const parsed = JSON.parse(readFileSync57(p, "utf8"));
|
|
47698
48127
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
47699
48128
|
}
|
|
47700
48129
|
} catch {
|
|
@@ -47733,11 +48162,11 @@ function formatLedger(entries, trend) {
|
|
|
47733
48162
|
return out.join("\n");
|
|
47734
48163
|
}
|
|
47735
48164
|
function diffAndStoreObservations(dir, current) {
|
|
47736
|
-
const p =
|
|
48165
|
+
const p = join50(dir, OBS_FILE);
|
|
47737
48166
|
let previous = null;
|
|
47738
48167
|
try {
|
|
47739
|
-
if (
|
|
47740
|
-
const parsed = JSON.parse(
|
|
48168
|
+
if (existsSync52(p)) {
|
|
48169
|
+
const parsed = JSON.parse(readFileSync57(p, "utf8"));
|
|
47741
48170
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
47742
48171
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
47743
48172
|
)) {
|
|
@@ -47786,8 +48215,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
47786
48215
|
var init_coverage = __esm({
|
|
47787
48216
|
"src/coverage.ts"() {
|
|
47788
48217
|
init_native_decode();
|
|
47789
|
-
LEDGER_FILE =
|
|
47790
|
-
OBS_FILE =
|
|
48218
|
+
LEDGER_FILE = join50(".himi", "test-ledger.json");
|
|
48219
|
+
OBS_FILE = join50(".himi", "test-observations.json");
|
|
47791
48220
|
}
|
|
47792
48221
|
});
|
|
47793
48222
|
|
|
@@ -47798,11 +48227,11 @@ __export(design_kits_exports, {
|
|
|
47798
48227
|
kitsDir: () => kitsDir,
|
|
47799
48228
|
listKits: () => listKits2
|
|
47800
48229
|
});
|
|
47801
|
-
import { existsSync as
|
|
47802
|
-
import { join as
|
|
48230
|
+
import { existsSync as existsSync53, readFileSync as readFileSync58, readdirSync as readdirSync25 } from "node:fs";
|
|
48231
|
+
import { join as join51, basename as basename12 } from "node:path";
|
|
47803
48232
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
47804
48233
|
function kitsDir() {
|
|
47805
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
48234
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync53(p));
|
|
47806
48235
|
}
|
|
47807
48236
|
function listKits2() {
|
|
47808
48237
|
const dir = kitsDir();
|
|
@@ -47826,7 +48255,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
47826
48255
|
if (!kits.includes(name)) {
|
|
47827
48256
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
47828
48257
|
}
|
|
47829
|
-
const raw =
|
|
48258
|
+
const raw = readFileSync58(join51(dir, `${name}.json`), "utf8");
|
|
47830
48259
|
let parsed;
|
|
47831
48260
|
try {
|
|
47832
48261
|
parsed = JSON.parse(raw);
|
|
@@ -47850,9 +48279,9 @@ var init_design_kits = __esm({
|
|
|
47850
48279
|
"src/design-kits.ts"() {
|
|
47851
48280
|
KIT_DIR_CANDIDATES = [
|
|
47852
48281
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
47853
|
-
|
|
48282
|
+
join51(fileURLToPath21(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
47854
48283
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
47855
|
-
|
|
48284
|
+
join51(fileURLToPath21(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
47856
48285
|
];
|
|
47857
48286
|
}
|
|
47858
48287
|
});
|
|
@@ -47866,11 +48295,11 @@ __export(assets_exports, {
|
|
|
47866
48295
|
removeAssetPayload: () => removeAssetPayload,
|
|
47867
48296
|
verifyReport: () => verifyReport
|
|
47868
48297
|
});
|
|
47869
|
-
import { readFileSync as
|
|
48298
|
+
import { readFileSync as readFileSync59 } from "node:fs";
|
|
47870
48299
|
import { basename as basename13 } from "node:path";
|
|
47871
48300
|
function declaredAssets(dir) {
|
|
47872
48301
|
return collectAssets(dir).map((a) => {
|
|
47873
|
-
const bytes2 =
|
|
48302
|
+
const bytes2 = readFileSync59(a.path);
|
|
47874
48303
|
return {
|
|
47875
48304
|
name: a.name,
|
|
47876
48305
|
sha256: assetSha256(bytes2),
|
|
@@ -47947,7 +48376,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
47947
48376
|
};
|
|
47948
48377
|
}
|
|
47949
48378
|
function addAssetPayload(manifest, filePath, opts) {
|
|
47950
|
-
const bytes2 =
|
|
48379
|
+
const bytes2 = readFileSync59(filePath);
|
|
47951
48380
|
const name = opts.name ?? basename13(filePath);
|
|
47952
48381
|
const sha2565 = assetSha256(bytes2);
|
|
47953
48382
|
const record2 = {
|
|
@@ -49587,21 +50016,21 @@ var init_preview_assets_generated = __esm({
|
|
|
49587
50016
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
49588
50017
|
init_preview_assets_format();
|
|
49589
50018
|
PREVIEW_ASSET_MANIFEST = [
|
|
49590
|
-
{ key: "assets/index-
|
|
49591
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
49592
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
49593
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
49594
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
49595
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
49596
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
49597
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
49598
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
49599
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
49600
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
49601
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
49602
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
49603
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
49604
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
50019
|
+
{ key: "assets/index-BJFiKWYO.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1051133, sha256: "99b754e0231cb82ad2cafbca64ba3cd3bdc74aa53d8351f6a57828034c3a3f44" },
|
|
50020
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1051141, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
50021
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1055751, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
50022
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1544335, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
50023
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1635259, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
50024
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1726243, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
50025
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1817223, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
50026
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1908095, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
50027
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1999075, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
50028
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2107711, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
50029
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2216795, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
50030
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2325843, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
50031
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2433543, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
50032
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 2521651, length: 4947, sha256: "1c4dfb3d465449d6a73677293df29d93b1c236b46602b553a58ef6e89c52de11" },
|
|
50033
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2526598, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
49605
50034
|
];
|
|
49606
50035
|
}
|
|
49607
50036
|
});
|
|
@@ -49617,9 +50046,9 @@ __export(run_exports, {
|
|
|
49617
50046
|
runPackage: () => runPackage,
|
|
49618
50047
|
withoutProdServe: () => withoutProdServe
|
|
49619
50048
|
});
|
|
49620
|
-
import { cpSync as cpSync2, existsSync as
|
|
50049
|
+
import { cpSync as cpSync2, existsSync as existsSync54, mkdirSync as mkdirSync25, mkdtempSync as mkdtempSync3, readFileSync as readFileSync60, rmSync as rmSync12, statSync as statSync13 } from "node:fs";
|
|
49621
50050
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
49622
|
-
import { dirname as dirname27, join as
|
|
50051
|
+
import { dirname as dirname27, join as join52 } from "node:path";
|
|
49623
50052
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
49624
50053
|
function makePackageRunHandler(opts) {
|
|
49625
50054
|
const store = new FileReleaseStore(opts.releaseRoot);
|
|
@@ -49647,9 +50076,9 @@ async function fetchBytes(url) {
|
|
|
49647
50076
|
}
|
|
49648
50077
|
async function resolvePackage(source, workDir) {
|
|
49649
50078
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
49650
|
-
if (!isUrl2 &&
|
|
49651
|
-
const appDirManifest =
|
|
49652
|
-
if (
|
|
50079
|
+
if (!isUrl2 && existsSync54(source) && statSync13(source).isDirectory()) {
|
|
50080
|
+
const appDirManifest = join52(source, "release-manifest.json");
|
|
50081
|
+
if (existsSync54(appDirManifest)) {
|
|
49653
50082
|
const opened2 = openPackageDir(source);
|
|
49654
50083
|
if (!opened2.validation.ok) {
|
|
49655
50084
|
throw new Error(`package is not valid:
|
|
@@ -49658,9 +50087,9 @@ async function resolvePackage(source, workDir) {
|
|
|
49658
50087
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
49659
50088
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
49660
50089
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
49661
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
49662
|
-
const target =
|
|
49663
|
-
if (
|
|
50090
|
+
const root2 = workDir ?? mkdtempSync3(join52(tmpdir4(), "himi-run-"));
|
|
50091
|
+
const target = join52(root2, app2);
|
|
50092
|
+
if (join52(source) !== target) {
|
|
49664
50093
|
mkdirSync25(root2, { recursive: true });
|
|
49665
50094
|
rmSync12(target, { recursive: true, force: true });
|
|
49666
50095
|
cpSync2(source, target, { recursive: true });
|
|
@@ -49677,8 +50106,8 @@ async function resolvePackage(source, workDir) {
|
|
|
49677
50106
|
}
|
|
49678
50107
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
49679
50108
|
}
|
|
49680
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
49681
|
-
const root = workDir ?? mkdtempSync3(
|
|
50109
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync60(source);
|
|
50110
|
+
const root = workDir ?? mkdtempSync3(join52(tmpdir4(), "himi-run-"));
|
|
49682
50111
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
49683
50112
|
const opened = openPackageDir(appDir2);
|
|
49684
50113
|
if (!opened.validation.ok) {
|
|
@@ -49701,14 +50130,14 @@ async function loadPreviewAssets() {
|
|
|
49701
50130
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
49702
50131
|
const here = dirname27(fileURLToPath22(import.meta.url));
|
|
49703
50132
|
const candidates = [
|
|
49704
|
-
|
|
50133
|
+
join52(here, "preview-assets.generated.bin"),
|
|
49705
50134
|
// published: copied next to the bundled CLI
|
|
49706
|
-
|
|
50135
|
+
join52(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
49707
50136
|
// in-repo checkout
|
|
49708
50137
|
];
|
|
49709
50138
|
for (const path2 of candidates) {
|
|
49710
|
-
if (!
|
|
49711
|
-
const blob =
|
|
50139
|
+
if (!existsSync54(path2)) continue;
|
|
50140
|
+
const blob = readFileSync60(path2);
|
|
49712
50141
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
49713
50142
|
}
|
|
49714
50143
|
return /* @__PURE__ */ new Map();
|
|
@@ -49805,9 +50234,9 @@ __export(run_watch_exports, {
|
|
|
49805
50234
|
watchedContentDir: () => watchedContentDir,
|
|
49806
50235
|
writeRunRecord: () => writeRunRecord
|
|
49807
50236
|
});
|
|
49808
|
-
import { closeSync as closeSync2, constants, existsSync as
|
|
50237
|
+
import { closeSync as closeSync2, constants, existsSync as existsSync55, fstatSync, lstatSync as lstatSync8, statSync as statSync14, mkdirSync as mkdirSync26, openSync as openSync2, readFileSync as readFileSync61, realpathSync as realpathSync6, renameSync as renameSync5, rmSync as rmSync13, writeFileSync as writeFileSync22, watch as fsWatch } from "node:fs";
|
|
49809
50238
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
49810
|
-
import { extname as extname4, join as
|
|
50239
|
+
import { extname as extname4, join as join53, resolve as resolve42, sep as sep13 } from "node:path";
|
|
49811
50240
|
function diffReleases(prev, next) {
|
|
49812
50241
|
const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
|
|
49813
50242
|
const changedBundles = new Set(bundles);
|
|
@@ -49847,7 +50276,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
49847
50276
|
let timer = null;
|
|
49848
50277
|
const pending = /* @__PURE__ */ new Set();
|
|
49849
50278
|
const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
|
|
49850
|
-
if (!file || ignoredChange(file, (rel) => isDir(
|
|
50279
|
+
if (!file || ignoredChange(file, (rel) => isDir(join53(dir, rel)))) return;
|
|
49851
50280
|
pending.add(file);
|
|
49852
50281
|
if (timer) clearTimeout(timer);
|
|
49853
50282
|
timer = setTimeout(() => {
|
|
@@ -49868,7 +50297,7 @@ function watchedContentDir(source) {
|
|
|
49868
50297
|
if (!source || /^https?:\/\//i.test(source)) return null;
|
|
49869
50298
|
const dir = resolve42(source);
|
|
49870
50299
|
try {
|
|
49871
|
-
return statSync14(dir).isDirectory() &&
|
|
50300
|
+
return statSync14(dir).isDirectory() && existsSync55(join53(dir, "himalaya.content.json")) ? dir : null;
|
|
49872
50301
|
} catch {
|
|
49873
50302
|
return null;
|
|
49874
50303
|
}
|
|
@@ -49925,7 +50354,7 @@ function serialize(task) {
|
|
|
49925
50354
|
});
|
|
49926
50355
|
}
|
|
49927
50356
|
function himiDir(dir) {
|
|
49928
|
-
const root =
|
|
50357
|
+
const root = join53(dir, ".himi");
|
|
49929
50358
|
try {
|
|
49930
50359
|
return lstatSync8(root).isDirectory() ? root : null;
|
|
49931
50360
|
} catch (e) {
|
|
@@ -49937,11 +50366,11 @@ function himiDir(dir) {
|
|
|
49937
50366
|
function writeRunRecord(dir, record2) {
|
|
49938
50367
|
const root = himiDir(dir);
|
|
49939
50368
|
if (!root) return false;
|
|
49940
|
-
const tmp =
|
|
50369
|
+
const tmp = join53(root, `.run.json.${process.pid}.${randomUUID3()}.tmp`);
|
|
49941
50370
|
try {
|
|
49942
50371
|
writeFileSync22(tmp, `${JSON.stringify(record2, null, 2)}
|
|
49943
50372
|
`, { flag: "wx" });
|
|
49944
|
-
renameSync5(tmp,
|
|
50373
|
+
renameSync5(tmp, join53(root, "run.json"));
|
|
49945
50374
|
} catch (e) {
|
|
49946
50375
|
rmSync13(tmp, { force: true });
|
|
49947
50376
|
throw e;
|
|
@@ -49949,7 +50378,7 @@ function writeRunRecord(dir, record2) {
|
|
|
49949
50378
|
return true;
|
|
49950
50379
|
}
|
|
49951
50380
|
function removeRunRecord(dir, owner) {
|
|
49952
|
-
const root =
|
|
50381
|
+
const root = join53(dir, ".himi");
|
|
49953
50382
|
try {
|
|
49954
50383
|
if (!lstatSync8(root).isDirectory()) return;
|
|
49955
50384
|
} catch {
|
|
@@ -49964,16 +50393,16 @@ function removeRunRecord(dir, owner) {
|
|
|
49964
50393
|
}
|
|
49965
50394
|
if (typeof pid === "number" && pid !== owner) return;
|
|
49966
50395
|
}
|
|
49967
|
-
rmSync13(
|
|
50396
|
+
rmSync13(join53(root, "run.json"), { force: true });
|
|
49968
50397
|
}
|
|
49969
50398
|
function boardFile(dir, pathname) {
|
|
49970
50399
|
let rel = null;
|
|
49971
|
-
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel =
|
|
49972
|
-
else if (pathname === "/__himi/studio/state.js") rel =
|
|
49973
|
-
else if (pathname === "/__himi/studio/timeline.js") rel =
|
|
50400
|
+
if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join53("studio", "index.html");
|
|
50401
|
+
else if (pathname === "/__himi/studio/state.js") rel = join53("studio", "state.js");
|
|
50402
|
+
else if (pathname === "/__himi/studio/timeline.js") rel = join53("studio", "timeline.js");
|
|
49974
50403
|
else {
|
|
49975
50404
|
const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
|
|
49976
|
-
if (m) rel =
|
|
50405
|
+
if (m) rel = join53("history", m[1]);
|
|
49977
50406
|
}
|
|
49978
50407
|
if (!rel) return null;
|
|
49979
50408
|
const bytes2 = readConfined(resolve42(dir, ".himi"), rel);
|
|
@@ -49989,7 +50418,7 @@ function readConfined(root, rel) {
|
|
|
49989
50418
|
const parts = rel.split(sep13);
|
|
49990
50419
|
let at = root;
|
|
49991
50420
|
for (let i = 0; i < parts.length; i++) {
|
|
49992
|
-
at =
|
|
50421
|
+
at = join53(at, parts[i]);
|
|
49993
50422
|
const st = lstatSync8(at);
|
|
49994
50423
|
if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
|
|
49995
50424
|
}
|
|
@@ -49998,7 +50427,7 @@ function readConfined(root, rel) {
|
|
|
49998
50427
|
const fd = openSync2(at, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
49999
50428
|
try {
|
|
50000
50429
|
if (!fstatSync(fd).isFile()) return null;
|
|
50001
|
-
return
|
|
50430
|
+
return readFileSync61(fd);
|
|
50002
50431
|
} finally {
|
|
50003
50432
|
closeSync2(fd);
|
|
50004
50433
|
}
|
|
@@ -50049,7 +50478,7 @@ __export(run_browser_exports, {
|
|
|
50049
50478
|
runInBrowser: () => runInBrowser
|
|
50050
50479
|
});
|
|
50051
50480
|
import { createServer as createServer5 } from "node:http";
|
|
50052
|
-
import { existsSync as
|
|
50481
|
+
import { existsSync as existsSync56, readFileSync as readFileSync62 } from "node:fs";
|
|
50053
50482
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
50054
50483
|
import { dirname as dirname28, resolve as resolve43 } from "node:path";
|
|
50055
50484
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
@@ -50057,7 +50486,7 @@ function stagedDir() {
|
|
|
50057
50486
|
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve43(process.env.HIMI_BROWSER_PLANE_OUT) : resolve43(REPO, "packages", "serve", "dist", "browser-plane");
|
|
50058
50487
|
}
|
|
50059
50488
|
function missingStaged() {
|
|
50060
|
-
return [...SERVED].filter((f) => !
|
|
50489
|
+
return [...SERVED].filter((f) => !existsSync56(resolve43(stagedDir(), f))).sort();
|
|
50061
50490
|
}
|
|
50062
50491
|
function ensureBrowserPlaneStaged() {
|
|
50063
50492
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
@@ -50142,7 +50571,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
50142
50571
|
}
|
|
50143
50572
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
50144
50573
|
if (SERVED.has(name)) {
|
|
50145
|
-
if (!
|
|
50574
|
+
if (!existsSync56(resolve43(stagedDir(), name))) {
|
|
50146
50575
|
const restaged = ensureBrowserPlaneStaged();
|
|
50147
50576
|
if (!restaged.ok) {
|
|
50148
50577
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -50152,7 +50581,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
50152
50581
|
}
|
|
50153
50582
|
let bytes2;
|
|
50154
50583
|
try {
|
|
50155
|
-
bytes2 =
|
|
50584
|
+
bytes2 = readFileSync62(resolve43(stagedDir(), name));
|
|
50156
50585
|
} catch (e) {
|
|
50157
50586
|
res.writeHead(503, { "content-type": "application/json" });
|
|
50158
50587
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -50613,7 +51042,7 @@ __export(preflight_exports, {
|
|
|
50613
51042
|
parseStoreConfig: () => parseStoreConfig,
|
|
50614
51043
|
requireEnv: () => requireEnv
|
|
50615
51044
|
});
|
|
50616
|
-
import { existsSync as
|
|
51045
|
+
import { existsSync as existsSync57, readFileSync as readFileSync63 } from "node:fs";
|
|
50617
51046
|
import { isAbsolute as isAbsolute3, relative as relative9, resolve as resolve44 } from "node:path";
|
|
50618
51047
|
function isInsideRepo(p) {
|
|
50619
51048
|
const rel = relative9(REPO_ROOT3, resolve44(p));
|
|
@@ -50670,10 +51099,10 @@ function parseStoreConfig(text5) {
|
|
|
50670
51099
|
}
|
|
50671
51100
|
function loadStoreConfig(app) {
|
|
50672
51101
|
const p = storeConfigPath(app);
|
|
50673
|
-
if (!
|
|
51102
|
+
if (!existsSync57(p)) {
|
|
50674
51103
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
50675
51104
|
}
|
|
50676
|
-
return parseStoreConfig(
|
|
51105
|
+
return parseStoreConfig(readFileSync63(p, "utf8"));
|
|
50677
51106
|
}
|
|
50678
51107
|
var init_preflight = __esm({
|
|
50679
51108
|
"../store-release/preflight.ts"() {
|
|
@@ -50692,19 +51121,19 @@ __export(credential_profile_exports, {
|
|
|
50692
51121
|
profilePath: () => profilePath,
|
|
50693
51122
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
50694
51123
|
});
|
|
50695
|
-
import { existsSync as
|
|
51124
|
+
import { existsSync as existsSync58, readFileSync as readFileSync64 } from "node:fs";
|
|
50696
51125
|
import { homedir as homedir5 } from "node:os";
|
|
50697
|
-
import { join as
|
|
51126
|
+
import { join as join54 } from "node:path";
|
|
50698
51127
|
function credentialsDir(home = homedir5()) {
|
|
50699
|
-
return
|
|
51128
|
+
return join54(home, ".himalaya", "store-credentials");
|
|
50700
51129
|
}
|
|
50701
51130
|
function profilePath(name, home = homedir5()) {
|
|
50702
51131
|
if (!PROFILE_NAME.test(name)) {
|
|
50703
51132
|
throw new Error(
|
|
50704
|
-
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${
|
|
51133
|
+
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join54(credentialsDir(home), "<name>.json")}; it is never a path.`
|
|
50705
51134
|
);
|
|
50706
51135
|
}
|
|
50707
|
-
return
|
|
51136
|
+
return join54(credentialsDir(home), `${name}.json`);
|
|
50708
51137
|
}
|
|
50709
51138
|
function parseProfile(text5, label2) {
|
|
50710
51139
|
let doc;
|
|
@@ -50735,8 +51164,8 @@ function resolveStoreCredentials(opts) {
|
|
|
50735
51164
|
const { app, cfg } = opts;
|
|
50736
51165
|
const env = opts.env ?? process.env;
|
|
50737
51166
|
const home = opts.home ?? homedir5();
|
|
50738
|
-
const read = opts.readProfile ?? ((p) =>
|
|
50739
|
-
const exists = opts.profileExists ??
|
|
51167
|
+
const read = opts.readProfile ?? ((p) => readFileSync64(p, "utf8"));
|
|
51168
|
+
const exists = opts.profileExists ?? existsSync58;
|
|
50740
51169
|
const ios = cfg.ios ?? {};
|
|
50741
51170
|
const flagName = opts.profileFlag?.trim();
|
|
50742
51171
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -50816,9 +51245,9 @@ __export(preflight_app_exports, {
|
|
|
50816
51245
|
preflightApp: () => preflightApp,
|
|
50817
51246
|
profileAccount: () => profileAccount
|
|
50818
51247
|
});
|
|
50819
|
-
import { readFileSync as
|
|
51248
|
+
import { readFileSync as readFileSync65, existsSync as existsSync59, readdirSync as readdirSync26, statSync as statSync15 } from "node:fs";
|
|
50820
51249
|
import { createHash as createHash26 } from "node:crypto";
|
|
50821
|
-
import { join as
|
|
51250
|
+
import { join as join55 } from "node:path";
|
|
50822
51251
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
50823
51252
|
const f = [];
|
|
50824
51253
|
const has = (re, s) => re.test(s);
|
|
@@ -50882,13 +51311,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
50882
51311
|
}
|
|
50883
51312
|
}
|
|
50884
51313
|
async function preflightApp(app, opts = {}) {
|
|
50885
|
-
const projectYml =
|
|
50886
|
-
const storeConfig =
|
|
51314
|
+
const projectYml = existsSync59(iosProjectYml(app)) ? readFileSync65(iosProjectYml(app), "utf8") : "";
|
|
51315
|
+
const storeConfig = existsSync59(storeConfigPath(app)) ? readFileSync65(storeConfigPath(app), "utf8") : "";
|
|
50887
51316
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
50888
51317
|
const findings = analyze(
|
|
50889
51318
|
projectYml,
|
|
50890
51319
|
storeConfig,
|
|
50891
|
-
await appIconState(
|
|
51320
|
+
await appIconState(join55(appDir(app), "ios")),
|
|
50892
51321
|
profileAccount(app, storeConfig, opts)
|
|
50893
51322
|
);
|
|
50894
51323
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -50917,17 +51346,17 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
50917
51346
|
return f;
|
|
50918
51347
|
}
|
|
50919
51348
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
50920
|
-
const root =
|
|
51349
|
+
const root = join55(storeDir(app), "metadata");
|
|
50921
51350
|
const out = /* @__PURE__ */ new Set();
|
|
50922
|
-
if (
|
|
51351
|
+
if (existsSync59(root)) {
|
|
50923
51352
|
for (const n of readdirSync26(root)) if (n.endsWith(".txt")) out.add(n);
|
|
50924
51353
|
}
|
|
50925
|
-
if (
|
|
51354
|
+
if (existsSync59(join55(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
50926
51355
|
return out;
|
|
50927
51356
|
}
|
|
50928
51357
|
function reviewInfoFiles(app) {
|
|
50929
|
-
const dir =
|
|
50930
|
-
if (!
|
|
51358
|
+
const dir = join55(storeDir(app), "review_information");
|
|
51359
|
+
if (!existsSync59(dir)) return /* @__PURE__ */ new Set();
|
|
50931
51360
|
return new Set(readdirSync26(dir).filter((n) => n.endsWith(".txt")));
|
|
50932
51361
|
}
|
|
50933
51362
|
function isValidAppStoreSize(w, h) {
|
|
@@ -51037,12 +51466,12 @@ function analyzePlayListing(assets) {
|
|
|
51037
51466
|
return f;
|
|
51038
51467
|
}
|
|
51039
51468
|
function playListingAssets(app, locale = "en-US") {
|
|
51040
|
-
const dir =
|
|
51469
|
+
const dir = join55(storeDir(app), "play", locale, "images");
|
|
51041
51470
|
const read = (names) => {
|
|
51042
51471
|
for (const name of names) {
|
|
51043
|
-
const p =
|
|
51472
|
+
const p = join55(dir, name);
|
|
51044
51473
|
try {
|
|
51045
|
-
if (statSync15(p).isFile()) return { name, bytes:
|
|
51474
|
+
if (statSync15(p).isFile()) return { name, bytes: readFileSync65(p) };
|
|
51046
51475
|
} catch {
|
|
51047
51476
|
}
|
|
51048
51477
|
}
|
|
@@ -51073,26 +51502,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
51073
51502
|
return f;
|
|
51074
51503
|
}
|
|
51075
51504
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
51076
|
-
const dir =
|
|
51077
|
-
if (!
|
|
51505
|
+
const dir = join55(storeDir(app), "metadata", locale);
|
|
51506
|
+
if (!existsSync59(dir)) return /* @__PURE__ */ new Set();
|
|
51078
51507
|
return new Set(readdirSync26(dir).filter((n) => n.endsWith(".txt")));
|
|
51079
51508
|
}
|
|
51080
51509
|
function listScreenshots(app, locale = "en-US") {
|
|
51081
51510
|
const out = [];
|
|
51082
|
-
const flat =
|
|
51083
|
-
if (
|
|
51511
|
+
const flat = join55(storeDir(app), "screenshots", locale);
|
|
51512
|
+
if (existsSync59(flat)) {
|
|
51084
51513
|
for (const png of readdirSync26(flat).filter((n) => n.endsWith(".png"))) {
|
|
51085
|
-
const sz = pngSize(
|
|
51514
|
+
const sz = pngSize(readFileSync65(join55(flat, png)));
|
|
51086
51515
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
51087
51516
|
}
|
|
51088
51517
|
}
|
|
51089
|
-
const legacy =
|
|
51090
|
-
if (
|
|
51518
|
+
const legacy = join55(storeDir(app), "metadata", locale, "screenshots");
|
|
51519
|
+
if (existsSync59(legacy)) {
|
|
51091
51520
|
for (const deviceDir of readdirSync26(legacy)) {
|
|
51092
|
-
const d =
|
|
51521
|
+
const d = join55(legacy, deviceDir);
|
|
51093
51522
|
if (!statSync15(d).isDirectory()) continue;
|
|
51094
51523
|
for (const png of readdirSync26(d).filter((n) => n.endsWith(".png"))) {
|
|
51095
|
-
const sz = pngSize(
|
|
51524
|
+
const sz = pngSize(readFileSync65(join55(d, png)));
|
|
51096
51525
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
51097
51526
|
}
|
|
51098
51527
|
}
|
|
@@ -51100,13 +51529,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
51100
51529
|
return out;
|
|
51101
51530
|
}
|
|
51102
51531
|
function placeholderHashes2() {
|
|
51103
|
-
const templateIos =
|
|
51104
|
-
if (!
|
|
51532
|
+
const templateIos = join55(appDir("_template"), "ios");
|
|
51533
|
+
if (!existsSync59(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
51105
51534
|
for (const target of readdirSync26(templateIos)) {
|
|
51106
|
-
const p =
|
|
51535
|
+
const p = join55(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
51107
51536
|
try {
|
|
51108
51537
|
if (!statSync15(p).isFile()) continue;
|
|
51109
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash26("sha256").update(
|
|
51538
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash26("sha256").update(readFileSync65(p)).digest("hex")];
|
|
51110
51539
|
} catch {
|
|
51111
51540
|
}
|
|
51112
51541
|
}
|
|
@@ -51137,12 +51566,12 @@ async function pixelIssues(bytes2) {
|
|
|
51137
51566
|
}
|
|
51138
51567
|
}
|
|
51139
51568
|
async function appIconState(iosDir) {
|
|
51140
|
-
if (!
|
|
51569
|
+
if (!existsSync59(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
51141
51570
|
for (const target of readdirSync26(iosDir)) {
|
|
51142
|
-
const p =
|
|
51571
|
+
const p = join55(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
51143
51572
|
try {
|
|
51144
51573
|
if (!statSync15(p).isFile()) continue;
|
|
51145
|
-
const bytes2 =
|
|
51574
|
+
const bytes2 = readFileSync65(p);
|
|
51146
51575
|
const hash = createHash26("sha256").update(bytes2).digest("hex");
|
|
51147
51576
|
const pixels = await pixelIssues(bytes2);
|
|
51148
51577
|
return {
|
|
@@ -51214,7 +51643,7 @@ __export(version_exports, {
|
|
|
51214
51643
|
setAndroidVersion: () => setAndroidVersion,
|
|
51215
51644
|
setIosVersion: () => setIosVersion
|
|
51216
51645
|
});
|
|
51217
|
-
import { readFileSync as
|
|
51646
|
+
import { readFileSync as readFileSync66, writeFileSync as writeFileSync23 } from "node:fs";
|
|
51218
51647
|
function readIosVersion(projectYml) {
|
|
51219
51648
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
51220
51649
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -51272,8 +51701,8 @@ function setAndroidVersion(gradle, v) {
|
|
|
51272
51701
|
function bumpVersion(app, opts) {
|
|
51273
51702
|
const iosPath = iosProjectYml(app);
|
|
51274
51703
|
const gradlePath = androidGradle(app);
|
|
51275
|
-
const iosYml =
|
|
51276
|
-
const gradle =
|
|
51704
|
+
const iosYml = readFileSync66(iosPath, "utf8");
|
|
51705
|
+
const gradle = readFileSync66(gradlePath, "utf8");
|
|
51277
51706
|
const current = readIosVersion(iosYml);
|
|
51278
51707
|
const next = {
|
|
51279
51708
|
marketing: opts.marketing ?? current.marketing,
|
|
@@ -51290,7 +51719,7 @@ var init_version = __esm({
|
|
|
51290
51719
|
});
|
|
51291
51720
|
|
|
51292
51721
|
// ../store-release/register-bundle.ts
|
|
51293
|
-
import { readFileSync as
|
|
51722
|
+
import { readFileSync as readFileSync67 } from "node:fs";
|
|
51294
51723
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
51295
51724
|
function b64url2(b) {
|
|
51296
51725
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -51308,7 +51737,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
51308
51737
|
async function registerBundleId(opts) {
|
|
51309
51738
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
51310
51739
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
51311
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
51740
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync67(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
51312
51741
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
51313
51742
|
method: "POST",
|
|
51314
51743
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -51362,7 +51791,7 @@ __export(asc_status_exports, {
|
|
|
51362
51791
|
ascStatus: () => ascStatus,
|
|
51363
51792
|
buildVerdict: () => buildVerdict
|
|
51364
51793
|
});
|
|
51365
|
-
import { readFileSync as
|
|
51794
|
+
import { readFileSync as readFileSync68 } from "node:fs";
|
|
51366
51795
|
function buildVerdict(builds) {
|
|
51367
51796
|
if (!builds.length) {
|
|
51368
51797
|
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).";
|
|
@@ -51376,7 +51805,7 @@ function buildVerdict(builds) {
|
|
|
51376
51805
|
function client(creds) {
|
|
51377
51806
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
51378
51807
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
51379
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
51808
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync68(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
51380
51809
|
return async (path2) => {
|
|
51381
51810
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
51382
51811
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -51536,7 +51965,7 @@ __export(secrets_exports, {
|
|
|
51536
51965
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
51537
51966
|
runSecretsCommand: () => runSecretsCommand
|
|
51538
51967
|
});
|
|
51539
|
-
import { readFileSync as
|
|
51968
|
+
import { readFileSync as readFileSync69 } from "node:fs";
|
|
51540
51969
|
function environment(value) {
|
|
51541
51970
|
if (value === "preview" || value === "production") return value;
|
|
51542
51971
|
throw new Error("--environment must be preview or production");
|
|
@@ -51567,7 +51996,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
51567
51996
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
51568
51997
|
return 0;
|
|
51569
51998
|
}
|
|
51570
|
-
const value = options.readValue ? options.readValue() :
|
|
51999
|
+
const value = options.readValue ? options.readValue() : readFileSync69(0, "utf8").replace(/\r?\n$/, "");
|
|
51571
52000
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
51572
52001
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
51573
52002
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -51596,7 +52025,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
51596
52025
|
}
|
|
51597
52026
|
let body;
|
|
51598
52027
|
if (operation !== "list") {
|
|
51599
|
-
const value = options.readValue ? options.readValue() :
|
|
52028
|
+
const value = options.readValue ? options.readValue() : readFileSync69(0, "utf8").replace(/\r?\n$/, "");
|
|
51600
52029
|
body = JSON.stringify({ value });
|
|
51601
52030
|
}
|
|
51602
52031
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -51632,15 +52061,15 @@ __export(notify_exports, {
|
|
|
51632
52061
|
runNotify: () => runNotify,
|
|
51633
52062
|
saveAdminSession: () => saveAdminSession
|
|
51634
52063
|
});
|
|
51635
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync27, readFileSync as
|
|
52064
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync27, readFileSync as readFileSync70, writeFileSync as writeFileSync24 } from "node:fs";
|
|
51636
52065
|
import { homedir as homedir6 } from "node:os";
|
|
51637
|
-
import { dirname as dirname30, join as
|
|
52066
|
+
import { dirname as dirname30, join as join56 } from "node:path";
|
|
51638
52067
|
function defaultSessionsPath() {
|
|
51639
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
52068
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join56(homedir6(), ".himalaya", "admin-sessions.json");
|
|
51640
52069
|
}
|
|
51641
52070
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
51642
52071
|
try {
|
|
51643
|
-
return JSON.parse(
|
|
52072
|
+
return JSON.parse(readFileSync70(path2, "utf8"));
|
|
51644
52073
|
} catch {
|
|
51645
52074
|
return {};
|
|
51646
52075
|
}
|
|
@@ -53018,7 +53447,7 @@ var init_traits = __esm({
|
|
|
53018
53447
|
});
|
|
53019
53448
|
|
|
53020
53449
|
// src/site-analyze/tokens.ts
|
|
53021
|
-
function
|
|
53450
|
+
function channels2(css) {
|
|
53022
53451
|
const canonical3 = canonicalHex(css);
|
|
53023
53452
|
if (!canonical3) return null;
|
|
53024
53453
|
return [
|
|
@@ -53028,11 +53457,11 @@ function channels(css) {
|
|
|
53028
53457
|
];
|
|
53029
53458
|
}
|
|
53030
53459
|
function isNearWhite(css) {
|
|
53031
|
-
const c =
|
|
53460
|
+
const c = channels2(css);
|
|
53032
53461
|
return !!c && c[0] >= 240 && c[1] >= 240 && c[2] >= 240;
|
|
53033
53462
|
}
|
|
53034
53463
|
function isNearBlack(css) {
|
|
53035
|
-
const c =
|
|
53464
|
+
const c = channels2(css);
|
|
53036
53465
|
return !!c && c[0] <= 80 && c[1] <= 80 && c[2] <= 80;
|
|
53037
53466
|
}
|
|
53038
53467
|
function usableCssColor(v) {
|
|
@@ -53171,12 +53600,12 @@ var init_tokens3 = __esm({
|
|
|
53171
53600
|
function channel2(hex2, offset) {
|
|
53172
53601
|
return Number.parseInt(hex2.slice(offset, offset + 2), 16);
|
|
53173
53602
|
}
|
|
53174
|
-
function
|
|
53603
|
+
function toHex2(r, g, b) {
|
|
53175
53604
|
return `#${[r, g, b].map((value) => Math.round(value).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
53176
53605
|
}
|
|
53177
53606
|
function mix2(color, background, colorWeight) {
|
|
53178
53607
|
const values = [1, 3, 5].map((offset) => channel2(color, offset) * colorWeight + channel2(background, offset) * (1 - colorWeight));
|
|
53179
|
-
return
|
|
53608
|
+
return toHex2(values[0], values[1], values[2]);
|
|
53180
53609
|
}
|
|
53181
53610
|
function relativeLuminance2(color) {
|
|
53182
53611
|
const linear = [1, 3, 5].map((offset) => {
|
|
@@ -55516,7 +55945,7 @@ var init_brand_font = __esm({
|
|
|
55516
55945
|
|
|
55517
55946
|
// src/site-analyze/write-artifacts.ts
|
|
55518
55947
|
import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync25 } from "node:fs";
|
|
55519
|
-
import { join as
|
|
55948
|
+
import { join as join57 } from "node:path";
|
|
55520
55949
|
function attachVeloSources(book, sources, put) {
|
|
55521
55950
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
55522
55951
|
for (const f of book.velo.files) {
|
|
@@ -55671,12 +56100,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
55671
56100
|
}
|
|
55672
56101
|
async function writeBusinessBook(result, opts) {
|
|
55673
56102
|
const out = opts.outDir;
|
|
55674
|
-
mkdirSync28(
|
|
55675
|
-
mkdirSync28(
|
|
56103
|
+
mkdirSync28(join57(out, "evidence/pages"), { recursive: true });
|
|
56104
|
+
mkdirSync28(join57(out, "media/catalog"), { recursive: true });
|
|
55676
56105
|
const files = [];
|
|
55677
56106
|
const put = (rel, body) => {
|
|
55678
|
-
const p =
|
|
55679
|
-
mkdirSync28(
|
|
56107
|
+
const p = join57(out, rel);
|
|
56108
|
+
mkdirSync28(join57(p, ".."), { recursive: true });
|
|
55680
56109
|
writeFileSync25(p, body);
|
|
55681
56110
|
files.push(rel);
|
|
55682
56111
|
};
|
|
@@ -55770,8 +56199,8 @@ var init_customer_build = __esm({
|
|
|
55770
56199
|
});
|
|
55771
56200
|
|
|
55772
56201
|
// src/site-analyze/apply.ts
|
|
55773
|
-
import { existsSync as
|
|
55774
|
-
import { dirname as dirname31, isAbsolute as isAbsolute4, join as
|
|
56202
|
+
import { existsSync as existsSync60, readFileSync as readFileSync71, writeFileSync as writeFileSync26, copyFileSync as copyFileSync3, mkdirSync as mkdirSync29, realpathSync as realpathSync7, statSync as statSync16 } from "node:fs";
|
|
56203
|
+
import { dirname as dirname31, isAbsolute as isAbsolute4, join as join58, resolve as resolve45, sep as sep14 } from "node:path";
|
|
55775
56204
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
55776
56205
|
function unpairedRedirectNote(overlay) {
|
|
55777
56206
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
@@ -55786,7 +56215,7 @@ function committedShellProvisioning(path2) {
|
|
|
55786
56215
|
function findRepoRoot(cwd) {
|
|
55787
56216
|
let dir = cwd;
|
|
55788
56217
|
for (let i = 0; i < 8; i++) {
|
|
55789
|
-
if (SHELL_NAMES2.some((name) =>
|
|
56218
|
+
if (SHELL_NAMES2.some((name) => existsSync60(join58(dir, shellAppDir(name), "package.json")))) return dir;
|
|
55790
56219
|
const next = dirname31(dir);
|
|
55791
56220
|
if (next === dir) break;
|
|
55792
56221
|
dir = next;
|
|
@@ -55854,11 +56283,11 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
55854
56283
|
}
|
|
55855
56284
|
function buildMergedContract(options) {
|
|
55856
56285
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
55857
|
-
const committedPath =
|
|
55858
|
-
if (!
|
|
56286
|
+
const committedPath = join58(appDir2, "provisioning.json");
|
|
56287
|
+
if (!existsSync60(committedPath)) {
|
|
55859
56288
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
55860
56289
|
}
|
|
55861
|
-
const committed = JSON.parse(
|
|
56290
|
+
const committed = JSON.parse(readFileSync71(committedPath, "utf8"));
|
|
55862
56291
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
55863
56292
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
55864
56293
|
const branding = merged.branding ?? {};
|
|
@@ -55870,8 +56299,8 @@ function buildMergedContract(options) {
|
|
|
55870
56299
|
};
|
|
55871
56300
|
const stage = (fromRel, toRel) => {
|
|
55872
56301
|
const from = contained(packageDir, fromRel);
|
|
55873
|
-
const to = contained(
|
|
55874
|
-
if (!from || !to || !
|
|
56302
|
+
const to = contained(join58(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
56303
|
+
if (!from || !to || !existsSync60(from)) return void 0;
|
|
55875
56304
|
let real;
|
|
55876
56305
|
let realRoot;
|
|
55877
56306
|
try {
|
|
@@ -55893,11 +56322,11 @@ function buildMergedContract(options) {
|
|
|
55893
56322
|
};
|
|
55894
56323
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
55895
56324
|
if (icon) branding.appIconPath = icon;
|
|
55896
|
-
const facesPath =
|
|
55897
|
-
if (
|
|
56325
|
+
const facesPath = join58(packageDir, "media/fonts/faces.json");
|
|
56326
|
+
if (existsSync60(facesPath)) {
|
|
55898
56327
|
let faces = [];
|
|
55899
56328
|
try {
|
|
55900
|
-
const parsed = JSON.parse(
|
|
56329
|
+
const parsed = JSON.parse(readFileSync71(facesPath, "utf8"));
|
|
55901
56330
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
55902
56331
|
} catch {
|
|
55903
56332
|
faces = [];
|
|
@@ -55918,9 +56347,9 @@ function buildMergedContract(options) {
|
|
|
55918
56347
|
merged.branding = branding;
|
|
55919
56348
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
55920
56349
|
`;
|
|
55921
|
-
const path2 =
|
|
56350
|
+
const path2 = join58(packageDir, "provisioning.contract.json");
|
|
55922
56351
|
writeFileSync26(path2, body);
|
|
55923
|
-
const localPath =
|
|
56352
|
+
const localPath = join58(appDir2, LOCAL_CONTRACT_REL);
|
|
55924
56353
|
mkdirSync29(dirname31(localPath), { recursive: true });
|
|
55925
56354
|
writeFileSync26(localPath, body);
|
|
55926
56355
|
staged.push(localPath);
|
|
@@ -55930,8 +56359,8 @@ async function applyOverlays(input) {
|
|
|
55930
56359
|
const cwd = resolve45(input.cwd);
|
|
55931
56360
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
55932
56361
|
assertKnownShell(shell);
|
|
55933
|
-
const overlay = JSON.parse(
|
|
55934
|
-
const tokens = JSON.parse(
|
|
56362
|
+
const overlay = JSON.parse(readFileSync71(input.overlayPath, "utf8"));
|
|
56363
|
+
const tokens = JSON.parse(readFileSync71(input.tokensPath, "utf8"));
|
|
55935
56364
|
const wrote = [];
|
|
55936
56365
|
const notes = [];
|
|
55937
56366
|
const repoRoot2 = findRepoRoot(cwd);
|
|
@@ -55941,7 +56370,7 @@ async function applyOverlays(input) {
|
|
|
55941
56370
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
55942
56371
|
);
|
|
55943
56372
|
}
|
|
55944
|
-
const appDir2 =
|
|
56373
|
+
const appDir2 = join58(repoRoot2, shellAppDir(shell));
|
|
55945
56374
|
const packageDir = dirname31(resolve45(input.overlayPath));
|
|
55946
56375
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
55947
56376
|
wrote.push(...staged);
|
|
@@ -55963,10 +56392,10 @@ async function applyOverlays(input) {
|
|
|
55963
56392
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
55964
56393
|
};
|
|
55965
56394
|
}
|
|
55966
|
-
const pkgProv =
|
|
56395
|
+
const pkgProv = join58(cwd, "provisioning.json");
|
|
55967
56396
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
55968
|
-
if (
|
|
55969
|
-
const cur = JSON.parse(
|
|
56397
|
+
if (existsSync60(pkgProv)) {
|
|
56398
|
+
const cur = JSON.parse(readFileSync71(pkgProv, "utf8"));
|
|
55970
56399
|
const merged = deepMerge4(cur, overlay);
|
|
55971
56400
|
writeFileSync26(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
55972
56401
|
wrote.push(pkgProv);
|
|
@@ -55974,9 +56403,9 @@ async function applyOverlays(input) {
|
|
|
55974
56403
|
writeFileSync26(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
55975
56404
|
wrote.push(pkgProv);
|
|
55976
56405
|
}
|
|
55977
|
-
const pkgTokens =
|
|
55978
|
-
if (
|
|
55979
|
-
const cur = JSON.parse(
|
|
56406
|
+
const pkgTokens = join58(cwd, "tokens.json");
|
|
56407
|
+
if (existsSync60(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
56408
|
+
const cur = JSON.parse(readFileSync71(pkgTokens, "utf8"));
|
|
55980
56409
|
const merged = deepMerge4(cur, tokens);
|
|
55981
56410
|
const mergedColors = merged.colors;
|
|
55982
56411
|
if (mergedColors && typeof mergedColors === "object" && !Array.isArray(mergedColors)) {
|
|
@@ -55995,9 +56424,9 @@ async function applyOverlays(input) {
|
|
|
55995
56424
|
wrote.push(pkgTokens);
|
|
55996
56425
|
}
|
|
55997
56426
|
const homeAction = homeRefreshActionId(shell);
|
|
55998
|
-
const homeSrc =
|
|
55999
|
-
if (homeAction &&
|
|
56000
|
-
const prev =
|
|
56427
|
+
const homeSrc = join58(cwd, "dev/index.ts");
|
|
56428
|
+
if (homeAction && existsSync60(homeSrc)) {
|
|
56429
|
+
const prev = readFileSync71(homeSrc, "utf8");
|
|
56001
56430
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
56002
56431
|
let next = patched.src;
|
|
56003
56432
|
if (!patched.foreign && overlay.installedVerticals?.length) {
|
|
@@ -56020,13 +56449,13 @@ async function applyOverlays(input) {
|
|
|
56020
56449
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
56021
56450
|
}
|
|
56022
56451
|
}
|
|
56023
|
-
if (!input.iconPath || !
|
|
56452
|
+
if (!input.iconPath || !existsSync60(input.iconPath)) {
|
|
56024
56453
|
const book = input.iconPath ? dirname31(dirname31(resolve45(input.iconPath))) : void 0;
|
|
56025
56454
|
notes.push(
|
|
56026
56455
|
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"
|
|
56027
56456
|
);
|
|
56028
56457
|
}
|
|
56029
|
-
if (input.iconPath &&
|
|
56458
|
+
if (input.iconPath && existsSync60(input.iconPath)) {
|
|
56030
56459
|
try {
|
|
56031
56460
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
56032
56461
|
wrote.push(...installed.wrote);
|
|
@@ -60201,7 +60630,7 @@ __export(cli_exports, {
|
|
|
60201
60630
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
60202
60631
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
60203
60632
|
});
|
|
60204
|
-
import { readFileSync as
|
|
60633
|
+
import { readFileSync as readFileSync72 } from "node:fs";
|
|
60205
60634
|
import { resolve as resolve46 } from "node:path";
|
|
60206
60635
|
function assetFetchFor(_opts) {
|
|
60207
60636
|
return pinnedFetch2;
|
|
@@ -60300,7 +60729,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
60300
60729
|
let source;
|
|
60301
60730
|
if (opts.sourcePath) {
|
|
60302
60731
|
const p = resolve46(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
60303
|
-
source =
|
|
60732
|
+
source = readFileSync72(p, "utf8");
|
|
60304
60733
|
}
|
|
60305
60734
|
let body;
|
|
60306
60735
|
if (opts.bodyRaw != null) {
|
|
@@ -60559,7 +60988,7 @@ __export(site_create_exports, {
|
|
|
60559
60988
|
runSiteList: () => runSiteList,
|
|
60560
60989
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
60561
60990
|
});
|
|
60562
|
-
import { existsSync as
|
|
60991
|
+
import { existsSync as existsSync61, readFileSync as readFileSync73, writeFileSync as writeFileSync27 } from "node:fs";
|
|
60563
60992
|
import { resolve as resolvePath2 } from "node:path";
|
|
60564
60993
|
function oauthClientName(projectName) {
|
|
60565
60994
|
return `${projectName} client`;
|
|
@@ -60708,7 +61137,7 @@ async function runSiteCreate(opts) {
|
|
|
60708
61137
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
60709
61138
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
60710
61139
|
}
|
|
60711
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
61140
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync61, readFileSync: readFileSync73, writeFileSync: writeFileSync27 }) {
|
|
60712
61141
|
const msid = binding2.siteId;
|
|
60713
61142
|
const path2 = resolvePath2(target);
|
|
60714
61143
|
const committed = committedShellProvisioning(path2);
|
|
@@ -61381,11 +61810,11 @@ var init_context = __esm({
|
|
|
61381
61810
|
});
|
|
61382
61811
|
|
|
61383
61812
|
// src/cli.ts
|
|
61384
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
61813
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync74, mkdirSync as mkdirSync30, writeFileSync as writeFileSync28, existsSync as existsSync62, rmSync as rmSync14, readdirSync as readdirSync27, statSync as statSync17, lstatSync as lstatSync9, accessSync, constants as constants2, renameSync as renameSync6, cpSync as cpSync3 } from "node:fs";
|
|
61385
61814
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn6 } from "node:child_process";
|
|
61386
61815
|
import { createHash as createHash27, randomUUID as randomUUID5 } from "node:crypto";
|
|
61387
61816
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
61388
|
-
import { join as
|
|
61817
|
+
import { join as join59, resolve as resolve47, relative as relative10, basename as basename14, dirname as dirname32 } from "node:path";
|
|
61389
61818
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
61390
61819
|
|
|
61391
61820
|
// ../serve-cli/src/client.ts
|
|
@@ -64678,8 +65107,8 @@ var str6 = (v) => typeof v === "string" ? v : void 0;
|
|
|
64678
65107
|
var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
64679
65108
|
function embeddedTemplateCatalog() {
|
|
64680
65109
|
return availableTemplates().map((name) => {
|
|
64681
|
-
const path2 =
|
|
64682
|
-
const meta = JSON.parse(
|
|
65110
|
+
const path2 = join59(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
65111
|
+
const meta = JSON.parse(readFileSync74(path2, "utf8"));
|
|
64683
65112
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
64684
65113
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
64685
65114
|
}
|
|
@@ -65351,7 +65780,7 @@ var COMMANDS = [
|
|
|
65351
65780
|
];
|
|
65352
65781
|
function cliVersion() {
|
|
65353
65782
|
try {
|
|
65354
|
-
return JSON.parse(
|
|
65783
|
+
return JSON.parse(readFileSync74(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
65355
65784
|
} catch {
|
|
65356
65785
|
return "unknown";
|
|
65357
65786
|
}
|
|
@@ -65469,7 +65898,7 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
65469
65898
|
}
|
|
65470
65899
|
function packageVersion(path2) {
|
|
65471
65900
|
try {
|
|
65472
|
-
const version2 = JSON.parse(
|
|
65901
|
+
const version2 = JSON.parse(readFileSync74(path2, "utf8")).version;
|
|
65473
65902
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
65474
65903
|
} catch {
|
|
65475
65904
|
return void 0;
|
|
@@ -65478,7 +65907,7 @@ function packageVersion(path2) {
|
|
|
65478
65907
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
65479
65908
|
let dir = resolve47(fromDir);
|
|
65480
65909
|
for (; ; ) {
|
|
65481
|
-
const version2 = packageVersion(
|
|
65910
|
+
const version2 = packageVersion(join59(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
65482
65911
|
if (version2) return { version: version2, source: "local" };
|
|
65483
65912
|
const parent = dirname32(dir);
|
|
65484
65913
|
if (parent === dir) break;
|
|
@@ -65488,7 +65917,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
65488
65917
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
65489
65918
|
try {
|
|
65490
65919
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
65491
|
-
const version2 = root ? packageVersion(
|
|
65920
|
+
const version2 = root ? packageVersion(join59(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
65492
65921
|
return version2 ? { version: version2, source: "global" } : {};
|
|
65493
65922
|
} catch {
|
|
65494
65923
|
return {};
|
|
@@ -65535,11 +65964,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
65535
65964
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
65536
65965
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
65537
65966
|
function updateCachePath(env = process.env) {
|
|
65538
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
65967
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join59(homedir7(), ".himalaya", "update-check.json");
|
|
65539
65968
|
}
|
|
65540
65969
|
function readUpdateCache(path2) {
|
|
65541
65970
|
try {
|
|
65542
|
-
const parsed = JSON.parse(
|
|
65971
|
+
const parsed = JSON.parse(readFileSync74(path2, "utf8"));
|
|
65543
65972
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
65544
65973
|
} catch {
|
|
65545
65974
|
return {};
|
|
@@ -65607,12 +66036,12 @@ function createUpdateRunner(spawn7 = spawnSync5) {
|
|
|
65607
66036
|
},
|
|
65608
66037
|
installedVersion: () => {
|
|
65609
66038
|
const root = globalNodeModulesRoot();
|
|
65610
|
-
return root ? packageVersion(
|
|
66039
|
+
return root ? packageVersion(join59(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
65611
66040
|
},
|
|
65612
66041
|
reexec: (argv) => {
|
|
65613
66042
|
const root = globalNodeModulesRoot();
|
|
65614
|
-
const entry = root ?
|
|
65615
|
-
if (!entry || !
|
|
66043
|
+
const entry = root ? join59(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
66044
|
+
if (!entry || !existsSync62(entry)) return void 0;
|
|
65616
66045
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
65617
66046
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
65618
66047
|
stdio: "inherit",
|
|
@@ -65659,7 +66088,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
65659
66088
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
65660
66089
|
let content;
|
|
65661
66090
|
try {
|
|
65662
|
-
content =
|
|
66091
|
+
content = readFileSync74(path2, "utf8");
|
|
65663
66092
|
} catch {
|
|
65664
66093
|
continue;
|
|
65665
66094
|
}
|
|
@@ -65682,7 +66111,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
65682
66111
|
const mine = lockStamp(now);
|
|
65683
66112
|
const readLock = (path2) => {
|
|
65684
66113
|
try {
|
|
65685
|
-
return
|
|
66114
|
+
return readFileSync74(path2, "utf8");
|
|
65686
66115
|
} catch {
|
|
65687
66116
|
return void 0;
|
|
65688
66117
|
}
|
|
@@ -65793,6 +66222,52 @@ function loaderArgs(execArgv) {
|
|
|
65793
66222
|
return out;
|
|
65794
66223
|
}
|
|
65795
66224
|
var spawnUpdateRefresh = createUpdateRefreshSpawner();
|
|
66225
|
+
function createTrimValidator(deps = {}, spawnFn = spawn6) {
|
|
66226
|
+
const outcome = (code, report2, said) => {
|
|
66227
|
+
let counts;
|
|
66228
|
+
let errors;
|
|
66229
|
+
try {
|
|
66230
|
+
const parsed = JSON.parse(report2);
|
|
66231
|
+
counts = parsed.counts;
|
|
66232
|
+
if (Array.isArray(parsed.findings)) {
|
|
66233
|
+
const text5 = (v) => typeof v === "string" && v ? v : void 0;
|
|
66234
|
+
errors = parsed.findings.filter((f) => f && f.severity === "error" && typeof f.id === "string").map((f) => ({
|
|
66235
|
+
id: f.id,
|
|
66236
|
+
message: text5(f.message) ?? "",
|
|
66237
|
+
...text5(f.pass) ? { pass: text5(f.pass) } : {},
|
|
66238
|
+
...text5(f.screen) ? { screen: text5(f.screen) } : {},
|
|
66239
|
+
...text5(f.path) ? { path: text5(f.path) } : {},
|
|
66240
|
+
...text5(f.ruleCode) ? { ruleCode: text5(f.ruleCode) } : {}
|
|
66241
|
+
}));
|
|
66242
|
+
}
|
|
66243
|
+
} catch {
|
|
66244
|
+
}
|
|
66245
|
+
return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
|
|
66246
|
+
};
|
|
66247
|
+
return async (dir, opts = {}) => {
|
|
66248
|
+
const argv = ["validate", "--content", resolve47(dir), "--strict", "--skip-version-check"];
|
|
66249
|
+
if (!opts.fresh) {
|
|
66250
|
+
const out = [];
|
|
66251
|
+
const err = [];
|
|
66252
|
+
const code2 = await run(argv, { log: (l) => out.push(l), error: (l) => err.push(l) }, deps);
|
|
66253
|
+
return outcome(code2, out[out.length - 1] ?? "", [...out, ...err].join("\n"));
|
|
66254
|
+
}
|
|
66255
|
+
const { code, stdout, stderr } = await new Promise((done) => {
|
|
66256
|
+
const chunks = { out: [], err: [] };
|
|
66257
|
+
const child = spawnFn(process.execPath, [...loaderArgs(process.execArgv), fileURLToPath24(import.meta.url), ...argv], {
|
|
66258
|
+
cwd: process.cwd(),
|
|
66259
|
+
env: process.env,
|
|
66260
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
66261
|
+
});
|
|
66262
|
+
child.stdout?.on("data", (b) => chunks.out.push(b));
|
|
66263
|
+
child.stderr?.on("data", (b) => chunks.err.push(b));
|
|
66264
|
+
child.on("error", (e) => done({ code: 2, stdout: "", stderr: String(e) }));
|
|
66265
|
+
child.on("close", (c) => done({ code: c ?? 1, stdout: Buffer.concat(chunks.out).toString("utf8"), stderr: Buffer.concat(chunks.err).toString("utf8") }));
|
|
66266
|
+
});
|
|
66267
|
+
return outcome(code, stdout.trim(), `${stdout}
|
|
66268
|
+
${stderr}`);
|
|
66269
|
+
};
|
|
66270
|
+
}
|
|
65796
66271
|
async function maybeSelfUpdate(argv, io, opts = {}) {
|
|
65797
66272
|
const env = opts.env ?? process.env;
|
|
65798
66273
|
const running = opts.running ?? cliVersion();
|
|
@@ -66220,7 +66695,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
66220
66695
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
66221
66696
|
for (const dir of entries) {
|
|
66222
66697
|
for (const suffix of suffixes) {
|
|
66223
|
-
const candidate =
|
|
66698
|
+
const candidate = join59(dir, `${name}${suffix}`);
|
|
66224
66699
|
try {
|
|
66225
66700
|
if (!statSync17(candidate).isFile()) continue;
|
|
66226
66701
|
if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
|
|
@@ -66329,7 +66804,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
66329
66804
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
66330
66805
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
66331
66806
|
const iosYmlPath = iosProjectYml2(app);
|
|
66332
|
-
const iosYml =
|
|
66807
|
+
const iosYml = existsSync62(iosYmlPath) ? readFileSync74(iosYmlPath, "utf8") : "";
|
|
66333
66808
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
66334
66809
|
if (!optedIn) {
|
|
66335
66810
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -66343,7 +66818,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
66343
66818
|
}
|
|
66344
66819
|
function readConfigSource(dir) {
|
|
66345
66820
|
try {
|
|
66346
|
-
return
|
|
66821
|
+
return readFileSync74(join59(dir, "config.ts"), "utf8");
|
|
66347
66822
|
} catch {
|
|
66348
66823
|
return null;
|
|
66349
66824
|
}
|
|
@@ -66359,7 +66834,7 @@ function keptPlan(kept) {
|
|
|
66359
66834
|
}
|
|
66360
66835
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
66361
66836
|
const dir = resolve47(parentDir, name);
|
|
66362
|
-
if (
|
|
66837
|
+
if (existsSync62(join59(dir, "himalaya.content.json"))) {
|
|
66363
66838
|
throw new Error(`content package already exists at ${dir}`);
|
|
66364
66839
|
}
|
|
66365
66840
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -66402,7 +66877,7 @@ function symlinkDestinationIssue(dest) {
|
|
|
66402
66877
|
function restoreDestinationIssue(dest, force) {
|
|
66403
66878
|
const link = symlinkDestinationIssue(dest);
|
|
66404
66879
|
if (link) return link;
|
|
66405
|
-
if (!
|
|
66880
|
+
if (!existsSync62(dest)) return null;
|
|
66406
66881
|
if (!statSync17(dest).isDirectory()) {
|
|
66407
66882
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
66408
66883
|
}
|
|
@@ -66417,7 +66892,7 @@ function restoreDestinationIssue(dest, force) {
|
|
|
66417
66892
|
function isHimalayaMonorepoCheckout(start) {
|
|
66418
66893
|
let dir = resolve47(start);
|
|
66419
66894
|
for (; ; ) {
|
|
66420
|
-
if (
|
|
66895
|
+
if (existsSync62(join59(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync62(join59(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
66421
66896
|
const parent = dirname32(dir);
|
|
66422
66897
|
if (parent === dir) return false;
|
|
66423
66898
|
dir = parent;
|
|
@@ -66460,7 +66935,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
66460
66935
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
66461
66936
|
);
|
|
66462
66937
|
const repoRoot2 = resolve47(fileURLToPath24(new URL("../../..", import.meta.url)));
|
|
66463
|
-
const root =
|
|
66938
|
+
const root = join59(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
66464
66939
|
const stillRunning = (pid) => {
|
|
66465
66940
|
try {
|
|
66466
66941
|
process.kill(pid, 0);
|
|
@@ -66474,12 +66949,12 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
66474
66949
|
if (!entry.isDirectory()) continue;
|
|
66475
66950
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
66476
66951
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
66477
|
-
rmSync14(
|
|
66952
|
+
rmSync14(join59(root, entry.name), { recursive: true, force: true });
|
|
66478
66953
|
}
|
|
66479
66954
|
}
|
|
66480
66955
|
} catch {
|
|
66481
66956
|
}
|
|
66482
|
-
const dest =
|
|
66957
|
+
const dest = join59(root, `${slug}-${process.pid}`);
|
|
66483
66958
|
rmSync14(dest, { recursive: true, force: true });
|
|
66484
66959
|
mkdirSync30(dest, { recursive: true });
|
|
66485
66960
|
materializeSource(forBuild, displayName, dest, slug);
|
|
@@ -66487,8 +66962,8 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
66487
66962
|
}
|
|
66488
66963
|
async function appId(dir) {
|
|
66489
66964
|
try {
|
|
66490
|
-
const { readFileSync:
|
|
66491
|
-
const m = JSON.parse(
|
|
66965
|
+
const { readFileSync: readFileSync75 } = await import("node:fs");
|
|
66966
|
+
const m = JSON.parse(readFileSync75(join59(dir, "himalaya.content.json"), "utf8"));
|
|
66492
66967
|
if (m.name) return m.name;
|
|
66493
66968
|
} catch {
|
|
66494
66969
|
}
|
|
@@ -66496,8 +66971,8 @@ async function appId(dir) {
|
|
|
66496
66971
|
}
|
|
66497
66972
|
async function contentVisibility(dir) {
|
|
66498
66973
|
try {
|
|
66499
|
-
const { readFileSync:
|
|
66500
|
-
const m = JSON.parse(
|
|
66974
|
+
const { readFileSync: readFileSync75 } = await import("node:fs");
|
|
66975
|
+
const m = JSON.parse(readFileSync75(join59(dir, "himalaya.content.json"), "utf8"));
|
|
66501
66976
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
66502
66977
|
} catch {
|
|
66503
66978
|
}
|
|
@@ -66721,7 +67196,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
66721
67196
|
try {
|
|
66722
67197
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
66723
67198
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
66724
|
-
out = mkdtempSync4(
|
|
67199
|
+
out = mkdtempSync4(join59(tmpdir5(), "himi-ux-record-"));
|
|
66725
67200
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
66726
67201
|
const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
66727
67202
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -66899,7 +67374,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
66899
67374
|
let js;
|
|
66900
67375
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
66901
67376
|
try {
|
|
66902
|
-
js =
|
|
67377
|
+
js = readFileSync74(join59(outDir, candidate), "utf8");
|
|
66903
67378
|
break;
|
|
66904
67379
|
} catch {
|
|
66905
67380
|
}
|
|
@@ -66930,7 +67405,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
66930
67405
|
}
|
|
66931
67406
|
return { families, source: "dist/bundles" };
|
|
66932
67407
|
}
|
|
66933
|
-
var boardOpen = (dir) =>
|
|
67408
|
+
var boardOpen = (dir) => existsSync62(join59(dir, ".himi", "studio", "index.html"));
|
|
66934
67409
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
66935
67410
|
async function leaveForBoard(dir, record2, value) {
|
|
66936
67411
|
if (!boardOpen(dir)) return;
|
|
@@ -67295,19 +67770,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67295
67770
|
const { runTemplateTrim: runTemplateTrim2 } = await Promise.resolve().then(() => (init_template_trim(), template_trim_exports));
|
|
67296
67771
|
const outcome = await runTemplateTrim2(
|
|
67297
67772
|
{ dir: contentDir(flags), keep: flags.keep, links: flags.links, dryRun: flags["dry-run"] === true, force: flags.force === true },
|
|
67298
|
-
{
|
|
67299
|
-
validate: async (dir) => {
|
|
67300
|
-
const out = [];
|
|
67301
|
-
const err = [];
|
|
67302
|
-
const code = await run(["validate", "--content", dir, "--strict"], { log: (l) => out.push(l), error: (l) => err.push(l) }, deps);
|
|
67303
|
-
let counts;
|
|
67304
|
-
try {
|
|
67305
|
-
counts = JSON.parse(out[out.length - 1] ?? "").counts;
|
|
67306
|
-
} catch {
|
|
67307
|
-
}
|
|
67308
|
-
return { code, counts, ...code !== 0 ? { tail: [...out, ...err].join("\n").slice(-4e3) } : {} };
|
|
67309
|
-
}
|
|
67310
|
-
}
|
|
67773
|
+
{ validate: createTrimValidator(deps) }
|
|
67311
67774
|
);
|
|
67312
67775
|
if (outcome.code === 2) io.error(JSON.stringify(outcome.result));
|
|
67313
67776
|
else print(outcome.result);
|
|
@@ -67318,7 +67781,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67318
67781
|
const sourceDir = resolve47(str6(flags["source-dir"]) ?? appDir2);
|
|
67319
67782
|
let meta;
|
|
67320
67783
|
try {
|
|
67321
|
-
meta = JSON.parse(
|
|
67784
|
+
meta = JSON.parse(readFileSync74(join59(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
67322
67785
|
} catch {
|
|
67323
67786
|
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>)` }));
|
|
67324
67787
|
return 2;
|
|
@@ -67328,7 +67791,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67328
67791
|
return 2;
|
|
67329
67792
|
}
|
|
67330
67793
|
try {
|
|
67331
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
67794
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync74(join59(sourceDir, "tokens.json"), "utf8")));
|
|
67332
67795
|
meta = { ...appearance, ...meta };
|
|
67333
67796
|
} catch {
|
|
67334
67797
|
}
|
|
@@ -67340,7 +67803,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67340
67803
|
const force = flags.force === true;
|
|
67341
67804
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
67342
67805
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
67343
|
-
const out = mkdtempSync4(
|
|
67806
|
+
const out = mkdtempSync4(join59(tmpdir5(), "himi-template-"));
|
|
67344
67807
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
67345
67808
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
67346
67809
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
@@ -67393,7 +67856,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67393
67856
|
let iconHash;
|
|
67394
67857
|
if (iconPath) {
|
|
67395
67858
|
try {
|
|
67396
|
-
const bytes2 =
|
|
67859
|
+
const bytes2 = readFileSync74(iconPath);
|
|
67397
67860
|
payload.icon = bytes2.toString("base64");
|
|
67398
67861
|
iconHash = createHash27("sha256").update(bytes2).digest("hex");
|
|
67399
67862
|
} catch {
|
|
@@ -67626,7 +68089,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67626
68089
|
const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
|
|
67627
68090
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
67628
68091
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
67629
|
-
const out = mkdtempSync4(
|
|
68092
|
+
const out = mkdtempSync4(join59(tmpdir5(), "himi-validate-"));
|
|
67630
68093
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
67631
68094
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
67632
68095
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -67669,7 +68132,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67669
68132
|
const path2 = dpxSessionTokenPath();
|
|
67670
68133
|
let raw;
|
|
67671
68134
|
try {
|
|
67672
|
-
raw =
|
|
68135
|
+
raw = readFileSync74(path2, "utf8");
|
|
67673
68136
|
} catch {
|
|
67674
68137
|
throw new Error(`no DPX BO session at ${path2}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
|
|
67675
68138
|
}
|
|
@@ -67789,13 +68252,13 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67789
68252
|
case "studio": {
|
|
67790
68253
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
67791
68254
|
const dir = contentDir(flags);
|
|
67792
|
-
if (!
|
|
68255
|
+
if (!existsSync62(join59(dir, "himalaya.content.json"))) {
|
|
67793
68256
|
io.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
|
|
67794
68257
|
return 2;
|
|
67795
68258
|
}
|
|
67796
68259
|
if (pos[1] === "reel") {
|
|
67797
68260
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
67798
|
-
const out = resolve47(str6(flags.out) ??
|
|
68261
|
+
const out = resolve47(str6(flags.out) ?? join59(dir, ".himi", "making-of.html"));
|
|
67799
68262
|
const { html, plan } = buildReel2(dir);
|
|
67800
68263
|
mkdirSync30(dirname32(out), { recursive: true });
|
|
67801
68264
|
writeFileSync28(out, html);
|
|
@@ -67845,7 +68308,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67845
68308
|
const { appendProgress: appendProgress2, readProgress: readProgress2, summarizeProgress: summarizeProgress2, parseStep: parseStep2, notifyDesktop: notifyDesktop2, appLabel: appLabel2, journalPath: journalPath2, ProgressError: ProgressError2, JOURNEY_STEPS: JOURNEY_STEPS2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
67846
68309
|
const dir = contentDir(flags);
|
|
67847
68310
|
const journal = journalPath2(dir);
|
|
67848
|
-
const hint =
|
|
68311
|
+
const hint = existsSync62(join59(dir, "himalaya.content.json")) ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
|
|
67849
68312
|
const message = pos.slice(1).join(" ").trim();
|
|
67850
68313
|
if (!message) {
|
|
67851
68314
|
if (flags.step !== void 0 || flags.image !== void 0 || flags.notify === true) {
|
|
@@ -67937,7 +68400,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
67937
68400
|
case "test": {
|
|
67938
68401
|
const dir = contentDir(flags);
|
|
67939
68402
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
67940
|
-
if (
|
|
68403
|
+
if (existsSync62(join59(dir, "functions"))) {
|
|
67941
68404
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
67942
68405
|
const loaded = await loadFunctionsApp2(dir);
|
|
67943
68406
|
const results = [];
|
|
@@ -68024,7 +68487,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68024
68487
|
}
|
|
68025
68488
|
}
|
|
68026
68489
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
68027
|
-
const out = mkdtempSync4(
|
|
68490
|
+
const out = mkdtempSync4(join59(tmpdir5(), "himi-test-"));
|
|
68028
68491
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
68029
68492
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
68030
68493
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -68069,7 +68532,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68069
68532
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
68070
68533
|
return 2;
|
|
68071
68534
|
}
|
|
68072
|
-
const sources = collectWorkerSources2(
|
|
68535
|
+
const sources = collectWorkerSources2(join59(dir, "tier5-src"), screen.bundleName);
|
|
68073
68536
|
if (!sources) {
|
|
68074
68537
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
68075
68538
|
return 2;
|
|
@@ -68230,7 +68693,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68230
68693
|
const sp = await runShotsPass2({
|
|
68231
68694
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
68232
68695
|
tokens: outcome.tokens,
|
|
68233
|
-
outDir:
|
|
68696
|
+
outDir: join59(dir, ".himi", "shots"),
|
|
68234
68697
|
width: 390,
|
|
68235
68698
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
68236
68699
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -68268,7 +68731,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68268
68731
|
releaseId: result.releaseId,
|
|
68269
68732
|
releasePayload: release,
|
|
68270
68733
|
descriptors: attestedDescriptors,
|
|
68271
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
68734
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join59(dir, ".himi", "shots", name)])),
|
|
68272
68735
|
coverage: {
|
|
68273
68736
|
screens: crawledScreens.size,
|
|
68274
68737
|
actionsDispatched: result.actions.exercised,
|
|
@@ -68358,7 +68821,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68358
68821
|
return 2;
|
|
68359
68822
|
}
|
|
68360
68823
|
try {
|
|
68361
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
68824
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync74(stateArg.replace(/^@/, ""), "utf8");
|
|
68362
68825
|
injectedState = JSON.parse(raw);
|
|
68363
68826
|
} catch (e) {
|
|
68364
68827
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -68373,7 +68836,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68373
68836
|
return 2;
|
|
68374
68837
|
}
|
|
68375
68838
|
try {
|
|
68376
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
68839
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync74(inputArg.replace(/^@/, ""), "utf8");
|
|
68377
68840
|
const parsed = JSON.parse(raw);
|
|
68378
68841
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
68379
68842
|
injectedInput = parsed;
|
|
@@ -68422,7 +68885,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68422
68885
|
}
|
|
68423
68886
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
68424
68887
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
68425
|
-
const out = mkdtempSync4(
|
|
68888
|
+
const out = mkdtempSync4(join59(tmpdir5(), "himi-render-"));
|
|
68426
68889
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
68427
68890
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
68428
68891
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -68436,7 +68899,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68436
68899
|
const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
|
|
68437
68900
|
let pngFile;
|
|
68438
68901
|
let attestationPngFile;
|
|
68439
|
-
const shotPath =
|
|
68902
|
+
const shotPath = join59(dir, ".himi", "shots", `${screenId}.png`);
|
|
68440
68903
|
const pngTarget = typeof flags.png === "string" ? str6(flags.png) : flags.png === true ? shotPath : void 0;
|
|
68441
68904
|
if (pngTarget && r.pngBase64) {
|
|
68442
68905
|
pngFile = writePngFile(pngTarget, r.pngBase64);
|
|
@@ -68566,7 +69029,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68566
69029
|
installIcon: installIcon2,
|
|
68567
69030
|
siteBookIcon: siteBookIcon2,
|
|
68568
69031
|
siteLogoAbsence: siteLogoAbsence2,
|
|
68569
|
-
summarize:
|
|
69032
|
+
summarize: summarize4
|
|
68570
69033
|
} = await Promise.resolve().then(() => (init_icon(), icon_exports));
|
|
68571
69034
|
const requireVerified = sub === "check";
|
|
68572
69035
|
const report2 = async (status, extra = {}) => {
|
|
@@ -68591,11 +69054,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
68591
69054
|
}))
|
|
68592
69055
|
];
|
|
68593
69056
|
if (flags.json === true) {
|
|
68594
|
-
print({ ok: !blocksRelease2(status, { requireVerified }), ...extra, ...status, findings, summary:
|
|
69057
|
+
print({ ok: !blocksRelease2(status, { requireVerified }), ...extra, ...status, findings, summary: summarize4(status) });
|
|
68595
69058
|
return blocksRelease2(status, { requireVerified }) ? 1 : 0;
|
|
68596
69059
|
}
|
|
68597
69060
|
for (const [k, v] of Object.entries(extra)) io.log(`${k}: ${Array.isArray(v) ? v.join(", ") : String(v)}`);
|
|
68598
|
-
io.log(`launcher icon: ${
|
|
69061
|
+
io.log(`launcher icon: ${summarize4(status)}`);
|
|
68599
69062
|
if (status.path) io.log(` file: ${status.path}${status.header ? ` (${status.header.width}x${status.header.height})` : ""}`);
|
|
68600
69063
|
for (const f of findings) io.log(` ${f.level === "error" ? "\u2717" : "\u26A0"} ${f.message}`);
|
|
68601
69064
|
if (status.verdict === "ok" || status.verdict === "unverified") {
|
|
@@ -68772,7 +69235,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
68772
69235
|
io.error(JSON.stringify(linked));
|
|
68773
69236
|
return 1;
|
|
68774
69237
|
}
|
|
68775
|
-
if (
|
|
69238
|
+
if (existsSync62(dest)) {
|
|
68776
69239
|
if (!statSync17(dest).isDirectory()) {
|
|
68777
69240
|
io.error(JSON.stringify({
|
|
68778
69241
|
error: `${dest} exists and is not a directory`,
|
|
@@ -68785,7 +69248,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
68785
69248
|
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" }));
|
|
68786
69249
|
return 1;
|
|
68787
69250
|
}
|
|
68788
|
-
if (replace && occupied && !
|
|
69251
|
+
if (replace && occupied && !existsSync62(join59(dest, "himalaya.content.json"))) {
|
|
68789
69252
|
io.error(JSON.stringify({
|
|
68790
69253
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
68791
69254
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -68924,7 +69387,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
68924
69387
|
const force = flags.force === true;
|
|
68925
69388
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
68926
69389
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
68927
|
-
const out = mkdtempSync4(
|
|
69390
|
+
const out = mkdtempSync4(join59(tmpdir5(), "himi-push-"));
|
|
68928
69391
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
68929
69392
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
68930
69393
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -69445,7 +69908,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69445
69908
|
}
|
|
69446
69909
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
69447
69910
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
69448
|
-
const built = mkdtempSync4(
|
|
69911
|
+
const built = mkdtempSync4(join59(tmpdir5(), "himi-pack-"));
|
|
69449
69912
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
69450
69913
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
69451
69914
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -69648,7 +70111,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69648
70111
|
}));
|
|
69649
70112
|
return 1;
|
|
69650
70113
|
}
|
|
69651
|
-
const archive =
|
|
70114
|
+
const archive = readFileSync74(resolve47(file));
|
|
69652
70115
|
const result = await client2().createPackageShare({
|
|
69653
70116
|
app: opened.header.app,
|
|
69654
70117
|
releaseId: opened.header.releaseId,
|
|
@@ -69702,11 +70165,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69702
70165
|
const app = await appId(dir2);
|
|
69703
70166
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
69704
70167
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
69705
|
-
temp = mkdtempSync4(
|
|
70168
|
+
temp = mkdtempSync4(join59(tmpdir5(), "himi-run-build-"));
|
|
69706
70169
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
69707
70170
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
69708
70171
|
servedMissing = initial.missingBundles;
|
|
69709
|
-
source =
|
|
70172
|
+
source = join59(temp, app);
|
|
69710
70173
|
}
|
|
69711
70174
|
const chromeArg = str6(flags.chrome) ?? "preview";
|
|
69712
70175
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -69742,7 +70205,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69742
70205
|
if (!recordKit) return;
|
|
69743
70206
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
69744
70207
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
69745
|
-
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
70208
|
+
if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join59(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
|
|
69746
70209
|
await refreshBoard();
|
|
69747
70210
|
};
|
|
69748
70211
|
const retract = async () => {
|
|
@@ -69773,7 +70236,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69773
70236
|
}
|
|
69774
70237
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
69775
70238
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
69776
|
-
if (watch2) served = mkdtempSync4(
|
|
70239
|
+
if (watch2) served = mkdtempSync4(join59(tmpdir5(), "himi-run-served-"));
|
|
69777
70240
|
const running = await runPackage2(source, {
|
|
69778
70241
|
port,
|
|
69779
70242
|
chrome: chromeArg,
|
|
@@ -69794,8 +70257,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69794
70257
|
await announce(running);
|
|
69795
70258
|
if (watchKit && bus) {
|
|
69796
70259
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
69797
|
-
const live2 =
|
|
69798
|
-
const manifestOf = (tree) => JSON.parse(
|
|
70260
|
+
const live2 = join59(running.releaseRoot, running.app);
|
|
70261
|
+
const manifestOf = (tree) => JSON.parse(readFileSync74(join59(tree, "release-manifest.json"), "utf8"));
|
|
69799
70262
|
let current = manifestOf(live2);
|
|
69800
70263
|
const failed2 = async (message) => {
|
|
69801
70264
|
if (stopping) return;
|
|
@@ -69806,7 +70269,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69806
70269
|
};
|
|
69807
70270
|
rebuild = watchKit.serialize(async () => {
|
|
69808
70271
|
const t0 = Date.now();
|
|
69809
|
-
const next = mkdtempSync4(
|
|
70272
|
+
const next = mkdtempSync4(join59(tmpdir5(), "himi-run-build-"));
|
|
69810
70273
|
try {
|
|
69811
70274
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
69812
70275
|
if (bres.compileErrors.length) {
|
|
@@ -69823,14 +70286,14 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
69823
70286
|
return;
|
|
69824
70287
|
}
|
|
69825
70288
|
if (stopping) return;
|
|
69826
|
-
const fresh = manifestOf(
|
|
70289
|
+
const fresh = manifestOf(join59(next, running.app));
|
|
69827
70290
|
const diff = watchKit.diffReleases(current, fresh);
|
|
69828
70291
|
const retired = `${live2}.retired-${Date.now()}`;
|
|
69829
70292
|
renameSync6(live2, retired);
|
|
69830
70293
|
try {
|
|
69831
|
-
renameSync6(
|
|
70294
|
+
renameSync6(join59(next, running.app), live2);
|
|
69832
70295
|
} catch {
|
|
69833
|
-
cpSync3(
|
|
70296
|
+
cpSync3(join59(next, running.app), live2, { recursive: true });
|
|
69834
70297
|
}
|
|
69835
70298
|
rmSync14(retired, { recursive: true, force: true });
|
|
69836
70299
|
current = fresh;
|
|
@@ -70428,7 +70891,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70428
70891
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
70429
70892
|
return 2;
|
|
70430
70893
|
}
|
|
70431
|
-
if (!
|
|
70894
|
+
if (!existsSync62(file)) {
|
|
70432
70895
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
70433
70896
|
return 2;
|
|
70434
70897
|
}
|
|
@@ -70484,7 +70947,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70484
70947
|
lintNote: "`himi patch` sends a raw file. Nothing here built or linted your app \u2014 `himi push --only <selector>` is the same edit with the full lint gate in front of it."
|
|
70485
70948
|
};
|
|
70486
70949
|
if (kind === "tokens" || kind === "app-config") {
|
|
70487
|
-
const body =
|
|
70950
|
+
const body = readFileSync74(file, "utf8");
|
|
70488
70951
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
70489
70952
|
return runReleasePatch({
|
|
70490
70953
|
...common,
|
|
@@ -70499,7 +70962,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70499
70962
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
70500
70963
|
return 2;
|
|
70501
70964
|
}
|
|
70502
|
-
const descriptor =
|
|
70965
|
+
const descriptor = readFileSync74(file, "utf8");
|
|
70503
70966
|
try {
|
|
70504
70967
|
JSON.parse(descriptor);
|
|
70505
70968
|
} catch (e) {
|
|
@@ -70539,7 +71002,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70539
71002
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
70540
71003
|
});
|
|
70541
71004
|
}
|
|
70542
|
-
const bytes2 =
|
|
71005
|
+
const bytes2 = readFileSync74(file);
|
|
70543
71006
|
const sha = createHash27("sha256").update(bytes2).digest("hex");
|
|
70544
71007
|
const forScreens = (str6(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
70545
71008
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -70683,7 +71146,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
70683
71146
|
}
|
|
70684
71147
|
let def;
|
|
70685
71148
|
try {
|
|
70686
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
71149
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync74(arg.slice(1), "utf8") : arg);
|
|
70687
71150
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
70688
71151
|
io.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
|
|
70689
71152
|
return 2;
|
|
@@ -71147,7 +71610,7 @@ ${label2}`);
|
|
|
71147
71610
|
const platform = str6(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
71148
71611
|
{
|
|
71149
71612
|
const distDir = contentDir(flags);
|
|
71150
|
-
if (
|
|
71613
|
+
if (existsSync62(join59(distDir, "himalaya.content.json"))) {
|
|
71151
71614
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
71152
71615
|
const errors = issues.filter((i) => i.severity === "error");
|
|
71153
71616
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -71416,7 +71879,7 @@ ${label2}`);
|
|
|
71416
71879
|
const dpxPath = dpxSessionTokenPath();
|
|
71417
71880
|
let dpx;
|
|
71418
71881
|
try {
|
|
71419
|
-
dpx =
|
|
71882
|
+
dpx = readFileSync74(dpxPath, "utf8").trim();
|
|
71420
71883
|
} catch {
|
|
71421
71884
|
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` }));
|
|
71422
71885
|
return 1;
|
|
@@ -71818,7 +72281,7 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
|
|
|
71818
72281
|
const path2 = dpxSessionTokenPath();
|
|
71819
72282
|
let raw;
|
|
71820
72283
|
try {
|
|
71821
|
-
raw =
|
|
72284
|
+
raw = readFileSync74(path2, "utf8");
|
|
71822
72285
|
} catch {
|
|
71823
72286
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
71824
72287
|
return 1;
|
|
@@ -72207,6 +72670,7 @@ export {
|
|
|
72207
72670
|
buildDoctorReport,
|
|
72208
72671
|
compareVersions2 as compareVersions,
|
|
72209
72672
|
createScopedRegistryResolver,
|
|
72673
|
+
createTrimValidator,
|
|
72210
72674
|
createUpdateRefreshSpawner,
|
|
72211
72675
|
createUpdateRunner,
|
|
72212
72676
|
credentialKind,
|