@wix/himalaya-cli 0.1006.0 → 0.1008.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/core/dev-server/src/builder.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +7 -4
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-ecom.mjs +26 -6
- package/dist/cli.mjs +1792 -853
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/component-reference.json +2 -1
- package/guides/component-reference.md +8 -5
- package/guides/qa-builds.md +3 -0
- package/guides/recipe-form-submit.md +5 -0
- package/guides/release-notes.md +16 -0
- package/guides/templates.md +3 -1
- package/guides/trim-a-template.md +75 -11
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -2990,14 +2990,14 @@ function confinementMatcher(contentRoot, extraRoots = []) {
|
|
|
2990
2990
|
linked = [];
|
|
2991
2991
|
const scanned = /* @__PURE__ */ new Set();
|
|
2992
2992
|
const queue = [...roots];
|
|
2993
|
-
const
|
|
2993
|
+
const CAP4 = 4096;
|
|
2994
2994
|
const take = (abs) => {
|
|
2995
2995
|
const target = realpathOrSelf(abs);
|
|
2996
|
-
if (scanned.has(target) || linked.length >=
|
|
2996
|
+
if (scanned.has(target) || linked.length >= CAP4) return;
|
|
2997
2997
|
linked.push(target);
|
|
2998
2998
|
queue.push(target);
|
|
2999
2999
|
};
|
|
3000
|
-
while (queue.length && linked.length <
|
|
3000
|
+
while (queue.length && linked.length < CAP4) {
|
|
3001
3001
|
const r = queue.shift();
|
|
3002
3002
|
for (const nm of [r, join12(r, "node_modules")]) {
|
|
3003
3003
|
if (scanned.has(nm)) continue;
|
|
@@ -3061,7 +3061,7 @@ function confinementPlugin(contentRoot) {
|
|
|
3061
3061
|
}
|
|
3062
3062
|
function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
3063
3063
|
const seen = /* @__PURE__ */ new Set();
|
|
3064
|
-
const
|
|
3064
|
+
const refuse4 = (p, why) => {
|
|
3065
3065
|
throw new Error(
|
|
3066
3066
|
`refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
|
|
3067
3067
|
);
|
|
@@ -3127,7 +3127,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
|
3127
3127
|
try {
|
|
3128
3128
|
manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
|
|
3129
3129
|
} catch {
|
|
3130
|
-
|
|
3130
|
+
refuse4(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
|
|
3131
3131
|
}
|
|
3132
3132
|
const field = manifest?.tsconfig;
|
|
3133
3133
|
if (typeof field === "string" && field) {
|
|
@@ -3143,7 +3143,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
|
3143
3143
|
const real = realpathOrSelf(file);
|
|
3144
3144
|
if (seen.has(real)) return;
|
|
3145
3145
|
seen.add(real);
|
|
3146
|
-
if (!allows(real))
|
|
3146
|
+
if (!allows(real)) refuse4(file, "it is outside this content package");
|
|
3147
3147
|
let raw;
|
|
3148
3148
|
try {
|
|
3149
3149
|
raw = readFileSync10(real, "utf8");
|
|
@@ -3154,7 +3154,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
|
3154
3154
|
try {
|
|
3155
3155
|
parsed = JSON.parse(stripJsonc(raw));
|
|
3156
3156
|
} catch {
|
|
3157
|
-
|
|
3157
|
+
refuse4(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
|
|
3158
3158
|
}
|
|
3159
3159
|
const ext = parsed?.extends;
|
|
3160
3160
|
for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
|
|
@@ -5318,6 +5318,7 @@ function walk(node, registry, path2, out) {
|
|
|
5318
5318
|
var SYSTEM_FONT_FAMILY;
|
|
5319
5319
|
var init_tokens = __esm({
|
|
5320
5320
|
"../../core/ts/src/tokens.ts"() {
|
|
5321
|
+
"use strict";
|
|
5321
5322
|
SYSTEM_FONT_FAMILY = "$system";
|
|
5322
5323
|
}
|
|
5323
5324
|
});
|
|
@@ -8582,6 +8583,7 @@ var init_validate_descriptor_core = __esm({
|
|
|
8582
8583
|
action: "any",
|
|
8583
8584
|
cornerRadius: "number",
|
|
8584
8585
|
disabled: "boolean",
|
|
8586
|
+
disabledPath: "string",
|
|
8585
8587
|
fullWidth: "boolean",
|
|
8586
8588
|
iconOnly: "boolean",
|
|
8587
8589
|
leadingIcon: "string",
|
|
@@ -12016,11 +12018,11 @@ function facesFor(family, weights, catalog = loadCatalog()) {
|
|
|
12016
12018
|
}
|
|
12017
12019
|
function matchWeightCss(available, desired) {
|
|
12018
12020
|
if (available.length === 0) return void 0;
|
|
12019
|
-
const
|
|
12020
|
-
const upFrom = (n) =>
|
|
12021
|
-
const downFrom = (n) => [...
|
|
12021
|
+
const sorted2 = [...available].sort((a, b) => a - b);
|
|
12022
|
+
const upFrom = (n) => sorted2.find((w) => w >= n);
|
|
12023
|
+
const downFrom = (n) => [...sorted2].reverse().find((w) => w <= n);
|
|
12022
12024
|
if (desired >= 400 && desired <= 500) {
|
|
12023
|
-
const within =
|
|
12025
|
+
const within = sorted2.find((w) => w >= desired && w <= 500);
|
|
12024
12026
|
return within ?? downFrom(desired) ?? upFrom(desired);
|
|
12025
12027
|
}
|
|
12026
12028
|
if (desired < 400) return downFrom(desired) ?? upFrom(desired);
|
|
@@ -24039,7 +24041,7 @@ function daysForMode(anchor, mode, firstWeekday) {
|
|
|
24039
24041
|
return Array.from({ length: n }, (_, i) => new Date(anchor.getFullYear(), anchor.getMonth(), anchor.getDate() + i));
|
|
24040
24042
|
}
|
|
24041
24043
|
function packOverlaps(items) {
|
|
24042
|
-
const
|
|
24044
|
+
const sorted2 = [...items].sort((a, b) => a.startMin - b.startMin || a.endMin - b.endMin);
|
|
24043
24045
|
const result = [];
|
|
24044
24046
|
let cluster = [];
|
|
24045
24047
|
let clusterEnd = -Infinity;
|
|
@@ -24060,7 +24062,7 @@ function packOverlaps(items) {
|
|
|
24060
24062
|
cluster = [];
|
|
24061
24063
|
clusterEnd = -Infinity;
|
|
24062
24064
|
};
|
|
24063
|
-
for (const item of
|
|
24065
|
+
for (const item of sorted2) {
|
|
24064
24066
|
if (cluster.length && item.startMin >= clusterEnd) flush();
|
|
24065
24067
|
cluster.push(item);
|
|
24066
24068
|
clusterEnd = Math.max(clusterEnd, item.endMin);
|
|
@@ -26710,7 +26712,8 @@ var init_renderNode = __esm({
|
|
|
26710
26712
|
const primary = buttonStyle === "primary" || destructive;
|
|
26711
26713
|
const outlined = buttonStyle === "secondary";
|
|
26712
26714
|
const accent = destructive ? C("danger", "#E62214") : C("accentPrimary", "#116DFF");
|
|
26713
|
-
const
|
|
26715
|
+
const boundDisabled = useResolvedScalar(props.disabledPath, ctx);
|
|
26716
|
+
const disabled = props.disabled === true || props.loading === true || hiddenBool(boundDisabled);
|
|
26714
26717
|
const onClick = ctx.onAction && props.action && !disabled ? (e) => {
|
|
26715
26718
|
e?.stopPropagation?.();
|
|
26716
26719
|
ctx.onAction(resolveItemDeep2(props.action, ctx));
|
|
@@ -30549,9 +30552,9 @@ function freezeCaptured(def, widgetId, opts = {}) {
|
|
|
30549
30552
|
}
|
|
30550
30553
|
const raw = def.timeline.frames;
|
|
30551
30554
|
if (Array.isArray(raw) && raw.length) {
|
|
30552
|
-
const
|
|
30553
|
-
if (
|
|
30554
|
-
frames =
|
|
30555
|
+
const sorted2 = [...raw].filter((f) => f && typeof f.startsAt === "number" && f.component).sort((a, b) => a.startsAt - b.startsAt).slice(0, MAX_TIMELINE_FRAMES);
|
|
30556
|
+
if (sorted2.length) {
|
|
30557
|
+
frames = sorted2.map((f) => ({ startsAt: f.startsAt, payload: f.component }));
|
|
30555
30558
|
payload = frames[0].payload;
|
|
30556
30559
|
}
|
|
30557
30560
|
}
|
|
@@ -38555,16 +38558,16 @@ function pushSetupBodyBytes(body) {
|
|
|
38555
38558
|
return Buffer.byteLength(JSON.stringify(body), "utf8");
|
|
38556
38559
|
}
|
|
38557
38560
|
async function pushSetupRequest(options) {
|
|
38558
|
-
const
|
|
38559
|
-
if (!options.target.controlToken) return
|
|
38560
|
-
if (!options.wixToken) return
|
|
38561
|
-
if (credentialHostRefusal(options.target.control)) return
|
|
38562
|
-
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return
|
|
38561
|
+
const refuse4 = (error) => ({ ok: false, status: 0, body: null, error });
|
|
38562
|
+
if (!options.target.controlToken) return refuse4("control_token_required");
|
|
38563
|
+
if (!options.wixToken) return refuse4("wix_account_token_required");
|
|
38564
|
+
if (credentialHostRefusal(options.target.control)) return refuse4("insecure_target");
|
|
38565
|
+
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse4("invalid_preview_tag");
|
|
38563
38566
|
const setup = options.operation === "setup";
|
|
38564
|
-
if (setup && !options.body) return
|
|
38565
|
-
if (!setup && (!options.query?.app || !options.query?.site)) return
|
|
38567
|
+
if (setup && !options.body) return refuse4("push_setup_body_required");
|
|
38568
|
+
if (!setup && (!options.query?.app || !options.query?.site)) return refuse4("push_setup_query_required");
|
|
38566
38569
|
if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
|
|
38567
|
-
return
|
|
38570
|
+
return refuse4("push_setup_body_too_large");
|
|
38568
38571
|
}
|
|
38569
38572
|
const base = options.target.control.replace(/\/+$/, "");
|
|
38570
38573
|
let path2 = "/v1/admin/push/setup";
|
|
@@ -39146,6 +39149,1285 @@ var init_notify_setup = __esm({
|
|
|
39146
39149
|
}
|
|
39147
39150
|
});
|
|
39148
39151
|
|
|
39152
|
+
// src/site-analyze/types.ts
|
|
39153
|
+
function isRedirectUri(value) {
|
|
39154
|
+
return /^[a-z][a-z0-9+.-]*:\/\/\S*$/i.test(value);
|
|
39155
|
+
}
|
|
39156
|
+
function assertRedirectUri(value) {
|
|
39157
|
+
const trimmed = value.trim();
|
|
39158
|
+
if (!isRedirectUri(trimmed)) {
|
|
39159
|
+
throw new Error(
|
|
39160
|
+
`--redirect-uri must be a URI with a scheme (e.g. myapp://oauth/callback), got: ${JSON.stringify(value)}. It must also be REGISTERED on --client-id; register one with \`himi site client ensure --site <msid> --redirect-uri <uri> --yes\`.`
|
|
39161
|
+
);
|
|
39162
|
+
}
|
|
39163
|
+
return trimmed;
|
|
39164
|
+
}
|
|
39165
|
+
var BOOK_SCHEMA_VERSION, KNOWN_VERTICALS;
|
|
39166
|
+
var init_types2 = __esm({
|
|
39167
|
+
"src/site-analyze/types.ts"() {
|
|
39168
|
+
BOOK_SCHEMA_VERSION = 2;
|
|
39169
|
+
KNOWN_VERTICALS = [
|
|
39170
|
+
"store",
|
|
39171
|
+
"bookings",
|
|
39172
|
+
"restaurants",
|
|
39173
|
+
"programs",
|
|
39174
|
+
"plans",
|
|
39175
|
+
"feed",
|
|
39176
|
+
"members",
|
|
39177
|
+
"forum",
|
|
39178
|
+
"coupons",
|
|
39179
|
+
"notifications",
|
|
39180
|
+
"loyalty",
|
|
39181
|
+
"reviews",
|
|
39182
|
+
"portfolio",
|
|
39183
|
+
"reservations",
|
|
39184
|
+
"invoices",
|
|
39185
|
+
"badges",
|
|
39186
|
+
"notifsettings",
|
|
39187
|
+
"events",
|
|
39188
|
+
"blog",
|
|
39189
|
+
"groups",
|
|
39190
|
+
"cms",
|
|
39191
|
+
"donations",
|
|
39192
|
+
"giftCards",
|
|
39193
|
+
"videos",
|
|
39194
|
+
"podcasts",
|
|
39195
|
+
"forms",
|
|
39196
|
+
"galleries",
|
|
39197
|
+
"inbox"
|
|
39198
|
+
];
|
|
39199
|
+
}
|
|
39200
|
+
});
|
|
39201
|
+
|
|
39202
|
+
// src/site-analyze/home-descriptor.ts
|
|
39203
|
+
function objectEnd(src, open) {
|
|
39204
|
+
let depth = 0;
|
|
39205
|
+
let inString = false;
|
|
39206
|
+
for (let i = open; i < src.length; i += 1) {
|
|
39207
|
+
const c = src[i];
|
|
39208
|
+
if (inString) {
|
|
39209
|
+
if (c === "\\") i += 1;
|
|
39210
|
+
else if (c === '"') inString = false;
|
|
39211
|
+
continue;
|
|
39212
|
+
}
|
|
39213
|
+
if (c === '"') inString = true;
|
|
39214
|
+
else if (c === "{") depth += 1;
|
|
39215
|
+
else if (c === "}") {
|
|
39216
|
+
depth -= 1;
|
|
39217
|
+
if (depth === 0) return i + 1;
|
|
39218
|
+
}
|
|
39219
|
+
}
|
|
39220
|
+
return -1;
|
|
39221
|
+
}
|
|
39222
|
+
function hasScreen(src, screenId) {
|
|
39223
|
+
const id = escapeRe2(screenId);
|
|
39224
|
+
return new RegExp(`"${id}": \\{\\s*"screenId": "${id}"`).test(src);
|
|
39225
|
+
}
|
|
39226
|
+
function findNode(root, pred) {
|
|
39227
|
+
if (Array.isArray(root)) {
|
|
39228
|
+
for (const child of root) {
|
|
39229
|
+
const hit = findNode(child, pred);
|
|
39230
|
+
if (hit) return hit;
|
|
39231
|
+
}
|
|
39232
|
+
return void 0;
|
|
39233
|
+
}
|
|
39234
|
+
if (!root || typeof root !== "object") return void 0;
|
|
39235
|
+
const node = root;
|
|
39236
|
+
if (node.body && typeof node.body === "object" && pred(node)) return node;
|
|
39237
|
+
for (const value of Object.values(root)) {
|
|
39238
|
+
const hit = findNode(value, pred);
|
|
39239
|
+
if (hit) return hit;
|
|
39240
|
+
}
|
|
39241
|
+
return void 0;
|
|
39242
|
+
}
|
|
39243
|
+
function cloneCell(template, prefix, vertical, card) {
|
|
39244
|
+
const cell = structuredClone(template);
|
|
39245
|
+
const accent = findNode(cell, (n) => n.body?.type === "Icon" && textProps(n)?.tint === "accentPrimary");
|
|
39246
|
+
const title = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "bodyEmphasis");
|
|
39247
|
+
const body = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "footnote");
|
|
39248
|
+
if (!accent || !title || !body || !cell.modifiers) return void 0;
|
|
39249
|
+
const onTap = cell.modifiers.onTap;
|
|
39250
|
+
if (!onTap?.actionId) return void 0;
|
|
39251
|
+
textProps(accent).name = card.icon;
|
|
39252
|
+
textProps(title).text = card.title;
|
|
39253
|
+
textProps(body).text = card.body;
|
|
39254
|
+
cell.modifiers.onTap = { actionId: onTap.actionId, params: { screenId: card.screenId } };
|
|
39255
|
+
cell.id = `${prefix}.${vertical}`;
|
|
39256
|
+
cell.modifiers.accessibilityLabel = card.title;
|
|
39257
|
+
return cell;
|
|
39258
|
+
}
|
|
39259
|
+
function lineIndent(src, open) {
|
|
39260
|
+
return /^[ \t]*/.exec(src.slice(src.lastIndexOf("\n", open) + 1, open))[0];
|
|
39261
|
+
}
|
|
39262
|
+
function serializeAt(node, src, open) {
|
|
39263
|
+
const indent = lineIndent(src, open);
|
|
39264
|
+
return JSON.stringify(node, null, 2).split("\n").map((line, i) => i === 0 ? line : indent + line).join("\n");
|
|
39265
|
+
}
|
|
39266
|
+
function patchGrids(src, installed, patch) {
|
|
39267
|
+
const OPEN = /"id": "([A-Za-z_0-9]+(?:\.[A-Za-z_0-9]+)*\.verticals)"/g;
|
|
39268
|
+
let out = "";
|
|
39269
|
+
let cursor = 0;
|
|
39270
|
+
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
39271
|
+
const open = src.lastIndexOf("{", m.index);
|
|
39272
|
+
if (open < cursor) continue;
|
|
39273
|
+
const close = objectEnd(src, open);
|
|
39274
|
+
if (close < 0) continue;
|
|
39275
|
+
const blob = src.slice(open, close);
|
|
39276
|
+
let node;
|
|
39277
|
+
try {
|
|
39278
|
+
node = JSON.parse(blob);
|
|
39279
|
+
} catch {
|
|
39280
|
+
continue;
|
|
39281
|
+
}
|
|
39282
|
+
const items = node.body?.type === "Grid" ? node.body.props?.items : void 0;
|
|
39283
|
+
if (!Array.isArray(items) || !items.length) continue;
|
|
39284
|
+
const prefix = m[1].slice(0, -".verticals".length);
|
|
39285
|
+
const baked = /* @__PURE__ */ new Map();
|
|
39286
|
+
const foreignCells = [];
|
|
39287
|
+
for (const item of items) {
|
|
39288
|
+
const id = item.id;
|
|
39289
|
+
const legacy = item.modifiers?.accessibilityLabel;
|
|
39290
|
+
const claim = typeof id === "string" && id ? id : typeof legacy === "string" ? legacy : "";
|
|
39291
|
+
const vertical = claim.startsWith(`${prefix}.`) ? claim.slice(prefix.length + 1) : "";
|
|
39292
|
+
if (isKnown(vertical)) baked.set(vertical, item);
|
|
39293
|
+
else if (!GRID_VERTICAL_LABELS.has(vertical)) foreignCells.push(item);
|
|
39294
|
+
}
|
|
39295
|
+
const wanted = [];
|
|
39296
|
+
for (const vertical of EXPLORE_ORDER) {
|
|
39297
|
+
if (!installed.has(vertical)) continue;
|
|
39298
|
+
if (baked.has(vertical)) {
|
|
39299
|
+
wanted.push(vertical);
|
|
39300
|
+
continue;
|
|
39301
|
+
}
|
|
39302
|
+
const card = EXPLORE_CARDS[vertical];
|
|
39303
|
+
if (!hasScreen(src, card.screenId)) {
|
|
39304
|
+
patch.unreachable.push(vertical);
|
|
39305
|
+
continue;
|
|
39306
|
+
}
|
|
39307
|
+
wanted.push(vertical);
|
|
39308
|
+
}
|
|
39309
|
+
const shape = baked.values().next().value ?? items[0];
|
|
39310
|
+
const next = [...foreignCells];
|
|
39311
|
+
const cells = [];
|
|
39312
|
+
for (const vertical of wanted) {
|
|
39313
|
+
if (next.length >= EXPLORE_MAX_CELLS) break;
|
|
39314
|
+
const bakedCell = baked.get(vertical);
|
|
39315
|
+
if (bakedCell) {
|
|
39316
|
+
next.push(bakedCell);
|
|
39317
|
+
cells.push(vertical);
|
|
39318
|
+
continue;
|
|
39319
|
+
}
|
|
39320
|
+
const made = cloneCell(shape, prefix, vertical, EXPLORE_CARDS[vertical]);
|
|
39321
|
+
if (!made) {
|
|
39322
|
+
patch.unreachable.push(vertical);
|
|
39323
|
+
continue;
|
|
39324
|
+
}
|
|
39325
|
+
next.push(made);
|
|
39326
|
+
cells.push(vertical);
|
|
39327
|
+
patch.added.push(vertical);
|
|
39328
|
+
}
|
|
39329
|
+
if (!cells.length) continue;
|
|
39330
|
+
patch.cells = cells;
|
|
39331
|
+
node.body.props.items = next;
|
|
39332
|
+
out += src.slice(cursor, open) + serializeAt(node, src, open);
|
|
39333
|
+
cursor = close;
|
|
39334
|
+
OPEN.lastIndex = close;
|
|
39335
|
+
}
|
|
39336
|
+
return out + src.slice(cursor);
|
|
39337
|
+
}
|
|
39338
|
+
function patchHomeModules(src, verticals) {
|
|
39339
|
+
const patch = { src, cells: [], added: [], droppedModules: [], droppedCtas: [], unreachable: [] };
|
|
39340
|
+
const next = patchModules(src, new Set(verticals.filter(isKnown)), patch);
|
|
39341
|
+
return { src: next, droppedModules: patch.droppedModules };
|
|
39342
|
+
}
|
|
39343
|
+
function patchModules(src, installed, patch) {
|
|
39344
|
+
return src.replace(/"homeModules": "((?:[^"\\]|\\.)*)"/g, (whole, encoded2) => {
|
|
39345
|
+
let modules;
|
|
39346
|
+
try {
|
|
39347
|
+
const parsed = JSON.parse(JSON.parse(`"${encoded2}"`));
|
|
39348
|
+
if (!Array.isArray(parsed)) return whole;
|
|
39349
|
+
modules = parsed;
|
|
39350
|
+
} catch {
|
|
39351
|
+
return whole;
|
|
39352
|
+
}
|
|
39353
|
+
const kept = modules.filter((module) => {
|
|
39354
|
+
const source = module?.dataSource;
|
|
39355
|
+
if (typeof source !== "string") return true;
|
|
39356
|
+
const needs = MODULE_SOURCE_VERTICALS[source];
|
|
39357
|
+
return !needs || needs.some((vertical) => installed.has(vertical));
|
|
39358
|
+
});
|
|
39359
|
+
if (!kept.length || kept.length === modules.length) return whole;
|
|
39360
|
+
for (const module of modules) {
|
|
39361
|
+
if (!kept.includes(module) && typeof module?.id === "string") patch.droppedModules.push(module.id);
|
|
39362
|
+
}
|
|
39363
|
+
return `"homeModules": ${JSON.stringify(JSON.stringify(kept))}`;
|
|
39364
|
+
});
|
|
39365
|
+
}
|
|
39366
|
+
function homeScreenSpan(src, homeActionId) {
|
|
39367
|
+
const OPEN = screenDeclarations();
|
|
39368
|
+
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
39369
|
+
const open = src.indexOf("{", m.index);
|
|
39370
|
+
const close = objectEnd(src, open);
|
|
39371
|
+
if (close < 0) continue;
|
|
39372
|
+
if (src.slice(open, close).includes(`"actionId": "${homeActionId}"`)) return { open, close };
|
|
39373
|
+
OPEN.lastIndex = close;
|
|
39374
|
+
}
|
|
39375
|
+
return void 0;
|
|
39376
|
+
}
|
|
39377
|
+
function isDeadStoreCta(node) {
|
|
39378
|
+
if (node.body?.type !== "Button") return false;
|
|
39379
|
+
const action = node.body.props?.action;
|
|
39380
|
+
const screenId = action?.params?.screenId;
|
|
39381
|
+
return typeof screenId === "string" && isStoreScreen(screenId);
|
|
39382
|
+
}
|
|
39383
|
+
function pruneTree(root, isDead) {
|
|
39384
|
+
const dropped = [];
|
|
39385
|
+
if (!isNode2(root)) return { emptied: false, dropped };
|
|
39386
|
+
return { emptied: !pruneNode(root, dropped, isDead), dropped };
|
|
39387
|
+
}
|
|
39388
|
+
function pruneNode(node, dropped, isDead = isDeadStoreCta) {
|
|
39389
|
+
const props = node.body?.props;
|
|
39390
|
+
if (!props) return true;
|
|
39391
|
+
const lists = props.itemsPath ? ["children"] : ["children", "items"];
|
|
39392
|
+
for (const key2 of lists) {
|
|
39393
|
+
const list = props[key2];
|
|
39394
|
+
if (!Array.isArray(list) || !list.length) continue;
|
|
39395
|
+
const kept = list.filter((child) => {
|
|
39396
|
+
if (child && typeof child === "object" && isDead(child)) {
|
|
39397
|
+
dropped.push(typeof child.id === "string" && child.id ? child.id : "(unnamed CTA)");
|
|
39398
|
+
return false;
|
|
39399
|
+
}
|
|
39400
|
+
if (!isNode2(child)) return true;
|
|
39401
|
+
return pruneNode(child, dropped, isDead);
|
|
39402
|
+
});
|
|
39403
|
+
if (kept.length === list.length) continue;
|
|
39404
|
+
if (!kept.length) return false;
|
|
39405
|
+
props[key2] = kept;
|
|
39406
|
+
}
|
|
39407
|
+
for (const [key2, child] of Object.entries(props)) {
|
|
39408
|
+
if (lists.includes(key2)) continue;
|
|
39409
|
+
pruneWithin(child, dropped, isDead);
|
|
39410
|
+
}
|
|
39411
|
+
return true;
|
|
39412
|
+
}
|
|
39413
|
+
function pruneWithin(value, dropped, isDead) {
|
|
39414
|
+
if (Array.isArray(value)) {
|
|
39415
|
+
for (const child of value) pruneWithin(child, dropped, isDead);
|
|
39416
|
+
return;
|
|
39417
|
+
}
|
|
39418
|
+
if (!value || typeof value !== "object") return;
|
|
39419
|
+
if (isNode2(value)) {
|
|
39420
|
+
pruneNode(value, dropped, isDead);
|
|
39421
|
+
return;
|
|
39422
|
+
}
|
|
39423
|
+
for (const child of Object.values(value)) pruneWithin(child, dropped, isDead);
|
|
39424
|
+
}
|
|
39425
|
+
function patchStoreCtas(src, verticals, homeActionId) {
|
|
39426
|
+
if (verticals.includes("store")) return { src, dropped: [] };
|
|
39427
|
+
const span = homeScreenSpan(src, homeActionId);
|
|
39428
|
+
if (!span) return { src, dropped: [] };
|
|
39429
|
+
let screen;
|
|
39430
|
+
try {
|
|
39431
|
+
screen = JSON.parse(src.slice(span.open, span.close));
|
|
39432
|
+
} catch {
|
|
39433
|
+
return { src, dropped: [] };
|
|
39434
|
+
}
|
|
39435
|
+
if (!isNode2(screen.payload)) return { src, dropped: [] };
|
|
39436
|
+
const dropped = [];
|
|
39437
|
+
if (!pruneNode(screen.payload, dropped) || !dropped.length) return { src, dropped: [] };
|
|
39438
|
+
return {
|
|
39439
|
+
src: src.slice(0, span.open) + serializeAt(screen, src, span.open) + src.slice(span.close),
|
|
39440
|
+
dropped
|
|
39441
|
+
};
|
|
39442
|
+
}
|
|
39443
|
+
function patchHomeForVerticals(src, verticals, homeActionId) {
|
|
39444
|
+
const installed = new Set(verticals.filter(isKnown));
|
|
39445
|
+
const patch = { src, cells: [], added: [], droppedModules: [], droppedCtas: [], unreachable: [] };
|
|
39446
|
+
if (!installed.size) return patch;
|
|
39447
|
+
const ctas = patchStoreCtas(patchModules(patchGrids(src, installed, patch), installed, patch), [...installed], homeActionId);
|
|
39448
|
+
patch.src = ctas.src;
|
|
39449
|
+
patch.droppedCtas = ctas.dropped;
|
|
39450
|
+
return patch;
|
|
39451
|
+
}
|
|
39452
|
+
var EXPLORE_CARDS, EXPLORE_ORDER, EXPLORE_MAX_CELLS, MODULE_SOURCE_VERTICALS, isKnown, GRID_VERTICAL_LABELS, escapeRe2, textProps, STORE_SCREENS, isStoreScreen, screenDeclarations, isNode2;
|
|
39453
|
+
var init_home_descriptor = __esm({
|
|
39454
|
+
"src/site-analyze/home-descriptor.ts"() {
|
|
39455
|
+
init_types2();
|
|
39456
|
+
EXPLORE_CARDS = {
|
|
39457
|
+
store: { icon: "bag", screenId: "himi_shop", title: "Shop", body: "Browse products and manage your cart." },
|
|
39458
|
+
bookings: { icon: "calendar", screenId: "himi_services", title: "Book", body: "Find a service and choose a time." },
|
|
39459
|
+
restaurants: { icon: "grid", screenId: "himi_menu", title: "Food", body: "Browse the menu and reserve a table." },
|
|
39460
|
+
events: { icon: "calendar", screenId: "himi_events", title: "Events", body: "Discover events and RSVP." },
|
|
39461
|
+
plans: { icon: "star", screenId: "himi_plans", title: "Plans", body: "Compare membership plans and join." },
|
|
39462
|
+
blog: { icon: "newspaper", screenId: "himi_blog", title: "Blog", body: "Read, save and discuss the latest posts." },
|
|
39463
|
+
groups: { icon: "people", screenId: "himi_groups", title: "Groups", body: "Meet members and join the conversation." },
|
|
39464
|
+
portfolio: { icon: "photo", screenId: "himi_portfolio", title: "Portfolio", body: "A showcase of our work." },
|
|
39465
|
+
galleries: { icon: "image", screenId: "himi_galleries", title: "Galleries", body: "Browse our photo galleries." },
|
|
39466
|
+
videos: { icon: "play", screenId: "himi_videos", title: "Videos", body: "Watch our video channels." },
|
|
39467
|
+
podcasts: { icon: "microphone", screenId: "himi_podcasts", title: "Podcast", body: "Listen to our latest episodes." },
|
|
39468
|
+
programs: { icon: "layers", screenId: "himi_programs", title: "Programs", body: "Follow structured programs at your own pace." },
|
|
39469
|
+
reservations: { icon: "clock", screenId: "himi_reservations", title: "Reservations", body: "Your table reservations." },
|
|
39470
|
+
donations: { icon: "heart", screenId: "himi_donations", title: "Donate", body: "Support the causes we care about." },
|
|
39471
|
+
giftCards: { icon: "tag", screenId: "himi_gift_cards", title: "Gift Cards", body: "Your gift cards and balances." },
|
|
39472
|
+
coupons: { icon: "tag", screenId: "himi_coupons", title: "Offers", body: "Deals and coupons available to you." },
|
|
39473
|
+
loyalty: { icon: "star", screenId: "himi_loyalty", title: "Rewards", body: "Earn points and redeem them for rewards." },
|
|
39474
|
+
forms: { icon: "list", screenId: "himi_forms", title: "Forms", body: "Fill out our forms." },
|
|
39475
|
+
cms: { icon: "grid", screenId: "himi_cms", title: "Content", body: "Explore custom content published by this business." },
|
|
39476
|
+
members: { icon: "people", screenId: "himi_members", title: "Members", body: "Meet the people in this community." },
|
|
39477
|
+
forum: { icon: "chat", screenId: "himi_forum", title: "Forum", body: "Join the discussion with the community." },
|
|
39478
|
+
feed: { icon: "chat", screenId: "himi_feed", title: "Feed", body: "Share updates and react to the latest posts." },
|
|
39479
|
+
reviews: { icon: "star_fill", screenId: "himi_reviews", title: "Reviews", body: "What customers are saying." },
|
|
39480
|
+
inbox: { icon: "chat", screenId: "himi_inbox", title: "Inbox", body: "Your messages with us." },
|
|
39481
|
+
invoices: { icon: "doc", screenId: "himi_invoices", title: "Invoices", body: "Your billing history." },
|
|
39482
|
+
badges: { icon: "star", screenId: "himi_badges", title: "Badges", body: "Achievements you can earn." },
|
|
39483
|
+
notifications: { icon: "bell", screenId: "himi_notifications", title: "Notifications", body: "Your activity and updates." },
|
|
39484
|
+
notifsettings: { icon: "settings", screenId: "himi_notif_settings", title: "Notification Settings", body: "Choose what you hear about." }
|
|
39485
|
+
};
|
|
39486
|
+
EXPLORE_ORDER = [
|
|
39487
|
+
"store",
|
|
39488
|
+
"bookings",
|
|
39489
|
+
"restaurants",
|
|
39490
|
+
"events",
|
|
39491
|
+
"plans",
|
|
39492
|
+
"blog",
|
|
39493
|
+
"groups",
|
|
39494
|
+
"portfolio",
|
|
39495
|
+
"galleries",
|
|
39496
|
+
"videos",
|
|
39497
|
+
"podcasts",
|
|
39498
|
+
"programs",
|
|
39499
|
+
"reservations",
|
|
39500
|
+
"donations",
|
|
39501
|
+
"giftCards",
|
|
39502
|
+
"coupons",
|
|
39503
|
+
"loyalty",
|
|
39504
|
+
"forms",
|
|
39505
|
+
"cms",
|
|
39506
|
+
"members",
|
|
39507
|
+
"forum",
|
|
39508
|
+
"feed",
|
|
39509
|
+
"reviews",
|
|
39510
|
+
"inbox",
|
|
39511
|
+
"invoices",
|
|
39512
|
+
"badges",
|
|
39513
|
+
"notifications",
|
|
39514
|
+
"notifsettings"
|
|
39515
|
+
];
|
|
39516
|
+
EXPLORE_MAX_CELLS = 8;
|
|
39517
|
+
MODULE_SOURCE_VERTICALS = {
|
|
39518
|
+
"member.bookings": ["bookings"],
|
|
39519
|
+
"member.bookings.schedule": ["bookings"],
|
|
39520
|
+
"device.saved_items": ["store", "blog"]
|
|
39521
|
+
};
|
|
39522
|
+
isKnown = (v) => KNOWN_VERTICALS.includes(v);
|
|
39523
|
+
GRID_VERTICAL_LABELS = /* @__PURE__ */ new Set([...KNOWN_VERTICALS, "faq"]);
|
|
39524
|
+
escapeRe2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
39525
|
+
textProps = (n) => n?.body?.props;
|
|
39526
|
+
STORE_SCREENS = /* @__PURE__ */ new Set([
|
|
39527
|
+
"himi_shop",
|
|
39528
|
+
"himi_saved_products",
|
|
39529
|
+
"himi_collections",
|
|
39530
|
+
"himi_collection",
|
|
39531
|
+
"himi_cart",
|
|
39532
|
+
"himi_orders"
|
|
39533
|
+
]);
|
|
39534
|
+
isStoreScreen = (id) => STORE_SCREENS.has(id) || /^himi_(?:product|order)[_/]/.test(id);
|
|
39535
|
+
screenDeclarations = () => /"([A-Za-z_0-9]+)": \{\s*"screenId": "\1"/g;
|
|
39536
|
+
isNode2 = (v) => !!v && typeof v === "object" && !!v.body && typeof v.body === "object";
|
|
39537
|
+
}
|
|
39538
|
+
});
|
|
39539
|
+
|
|
39540
|
+
// src/template-trim.ts
|
|
39541
|
+
var template_trim_exports = {};
|
|
39542
|
+
__export(template_trim_exports, {
|
|
39543
|
+
TrimRefusal: () => TrimRefusal,
|
|
39544
|
+
leftoverNavRefs: () => leftoverNavRefs,
|
|
39545
|
+
linearSafePattern: () => linearSafePattern,
|
|
39546
|
+
parseApp: () => parseApp,
|
|
39547
|
+
planTrim: () => planTrim,
|
|
39548
|
+
routeMatcher: () => routeMatcher,
|
|
39549
|
+
runTemplateTrim: () => runTemplateTrim
|
|
39550
|
+
});
|
|
39551
|
+
import { cpSync, existsSync as existsSync39, mkdirSync as mkdirSync18, readdirSync as readdirSync20, readFileSync as readFileSync43, renameSync as renameSync3, rmSync as rmSync6, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
|
|
39552
|
+
import { dirname as dirname23, join as join36 } from "node:path";
|
|
39553
|
+
function routeMatcher(pattern) {
|
|
39554
|
+
const detail = /^\^([A-Za-z0-9_]+)\(\?:\[_\/\]\(\.\+\)\)\?\$$/.exec(pattern);
|
|
39555
|
+
if (detail) {
|
|
39556
|
+
const base = detail[1];
|
|
39557
|
+
return {
|
|
39558
|
+
// `.` never matches a newline, so neither does this.
|
|
39559
|
+
test: (id) => id === base || id.length > base.length + 1 && id.startsWith(base) && (id[base.length] === "_" || id[base.length] === "/") && !id.includes("\n", base.length + 1)
|
|
39560
|
+
};
|
|
39561
|
+
}
|
|
39562
|
+
const suffixed = /^\^([A-Za-z0-9_]+)\(\[A-Za-z0-9\]\{1,32\}\)\$$/.exec(pattern);
|
|
39563
|
+
if (suffixed) {
|
|
39564
|
+
const prefix = suffixed[1];
|
|
39565
|
+
return {
|
|
39566
|
+
test: (id) => {
|
|
39567
|
+
if (!id.startsWith(prefix)) return false;
|
|
39568
|
+
const rest = id.slice(prefix.length);
|
|
39569
|
+
return rest.length >= 1 && rest.length <= 32 && /^[A-Za-z0-9]+$/.test(rest);
|
|
39570
|
+
}
|
|
39571
|
+
};
|
|
39572
|
+
}
|
|
39573
|
+
if (!linearSafePattern(pattern)) return null;
|
|
39574
|
+
let re;
|
|
39575
|
+
try {
|
|
39576
|
+
re = new RegExp(pattern);
|
|
39577
|
+
} catch {
|
|
39578
|
+
return null;
|
|
39579
|
+
}
|
|
39580
|
+
return re;
|
|
39581
|
+
}
|
|
39582
|
+
function linearSafePattern(pattern) {
|
|
39583
|
+
return pattern.length <= 256 && SAFE_ROUTE_PATTERN.test(pattern);
|
|
39584
|
+
}
|
|
39585
|
+
function bundlesOf(block) {
|
|
39586
|
+
const out = /* @__PURE__ */ new Set();
|
|
39587
|
+
const walk2 = (v) => {
|
|
39588
|
+
if (Array.isArray(v)) return v.forEach(walk2);
|
|
39589
|
+
if (!v || typeof v !== "object") return;
|
|
39590
|
+
const lb = v.logicBundle;
|
|
39591
|
+
const name = bundleNameFromUrl(lb?.url);
|
|
39592
|
+
if (name) out.add(name);
|
|
39593
|
+
for (const child of Object.values(v)) walk2(child);
|
|
39594
|
+
};
|
|
39595
|
+
walk2(block);
|
|
39596
|
+
return [...out];
|
|
39597
|
+
}
|
|
39598
|
+
function parseJson(text4, what) {
|
|
39599
|
+
try {
|
|
39600
|
+
const value = JSON.parse(text4);
|
|
39601
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("not an object");
|
|
39602
|
+
return value;
|
|
39603
|
+
} catch (e) {
|
|
39604
|
+
throw new TrimRefusal(
|
|
39605
|
+
`${what} is not a plain JSON object literal (${e.message}) \u2014 trim only rewrites the shape \`himi init\` writes; edit that block back to JSON or trim by hand (\`himi docs trim-a-template\`)`
|
|
39606
|
+
);
|
|
39607
|
+
}
|
|
39608
|
+
}
|
|
39609
|
+
function jsonString(literal, what) {
|
|
39610
|
+
try {
|
|
39611
|
+
return JSON.parse(literal);
|
|
39612
|
+
} catch (e) {
|
|
39613
|
+
throw new TrimRefusal(`${what} ${literal} is not a valid JSON string (${e.message}) \u2014 trim reads the shape \`himi init\` writes; fix the literal or trim by hand (\`himi docs trim-a-template\`)`);
|
|
39614
|
+
}
|
|
39615
|
+
}
|
|
39616
|
+
function bracketEnd(src, open) {
|
|
39617
|
+
let depth = 0;
|
|
39618
|
+
let inString = false;
|
|
39619
|
+
for (let i = open; i < src.length; i += 1) {
|
|
39620
|
+
const c = src[i];
|
|
39621
|
+
if (inString) {
|
|
39622
|
+
if (c === "\\") i += 1;
|
|
39623
|
+
else if (c === '"') inString = false;
|
|
39624
|
+
continue;
|
|
39625
|
+
}
|
|
39626
|
+
if (c === '"') inString = true;
|
|
39627
|
+
else if (c === "[" || c === "{") depth += 1;
|
|
39628
|
+
else if (c === "]" || c === "}") {
|
|
39629
|
+
depth -= 1;
|
|
39630
|
+
if (depth === 0) return i + 1;
|
|
39631
|
+
}
|
|
39632
|
+
}
|
|
39633
|
+
return -1;
|
|
39634
|
+
}
|
|
39635
|
+
function parseSubtree(config) {
|
|
39636
|
+
const KEY = /^[ \t]*["']?workerSubtreeScreens["']?[ \t]*:[ \t]*/gm;
|
|
39637
|
+
const hits = [...config.matchAll(KEY)];
|
|
39638
|
+
if (!hits.length) return void 0;
|
|
39639
|
+
if (hits.length > 1) throw new TrimRefusal("config.ts declares workerSubtreeScreens more than once \u2014 trim cannot tell which one the app uses; keep one and trim again");
|
|
39640
|
+
const start = hits[0].index + hits[0][0].length;
|
|
39641
|
+
const unreadable = 'config.ts: workerSubtreeScreens is not a JSON array literal of screen ids \u2014 trim will not guess at it; write it as `["id", \u2026]` or trim by hand';
|
|
39642
|
+
if (config[start] !== "[") throw new TrimRefusal(unreadable);
|
|
39643
|
+
const end = bracketEnd(config, start);
|
|
39644
|
+
if (end < 0) throw new TrimRefusal(unreadable);
|
|
39645
|
+
let value;
|
|
39646
|
+
try {
|
|
39647
|
+
value = JSON.parse(config.slice(start, end));
|
|
39648
|
+
} catch {
|
|
39649
|
+
throw new TrimRefusal(unreadable);
|
|
39650
|
+
}
|
|
39651
|
+
if (!Array.isArray(value)) throw new TrimRefusal(unreadable);
|
|
39652
|
+
return { start, end, value };
|
|
39653
|
+
}
|
|
39654
|
+
function parseApp(dev, config) {
|
|
39655
|
+
const SCREENS_ANCHOR = "const SCREENS = runtimeSetting({\n";
|
|
39656
|
+
const at = dev.indexOf(SCREENS_ANCHOR);
|
|
39657
|
+
if (at < 0) {
|
|
39658
|
+
throw new TrimRefusal("dev/index.ts has no `const SCREENS = runtimeSetting({` \u2014 trim reads the SCREENS map in the shape `himi init` writes, and this file is not in it");
|
|
39659
|
+
}
|
|
39660
|
+
const routes = [];
|
|
39661
|
+
const exact = /* @__PURE__ */ new Map();
|
|
39662
|
+
let pos = at + SCREENS_ANCHOR.length;
|
|
39663
|
+
const ENTRY = / ("(?:[^"\\\n]|\\.)*"): \{/y;
|
|
39664
|
+
while (!dev.startsWith("})", pos)) {
|
|
39665
|
+
ENTRY.lastIndex = pos;
|
|
39666
|
+
const m = ENTRY.exec(dev);
|
|
39667
|
+
if (!m) throw new TrimRefusal(`dev/index.ts line ${lineOf(dev, pos)}: expected a \`"<screenId>": {\` entry of the SCREENS map`);
|
|
39668
|
+
const id = jsonString(m[1], `dev/index.ts line ${lineOf(dev, pos)}: the SCREENS key`);
|
|
39669
|
+
const open = pos + m[0].length - 1;
|
|
39670
|
+
const close = objectEnd(dev, open);
|
|
39671
|
+
if (close < 0 || dev.slice(close, close + 2) !== ",\n") {
|
|
39672
|
+
throw new TrimRefusal(`dev/index.ts: the SCREENS entry "${id}" does not end in \`},\` on its own line`);
|
|
39673
|
+
}
|
|
39674
|
+
const decl = screenDeclarations();
|
|
39675
|
+
decl.lastIndex = pos;
|
|
39676
|
+
const d = decl.exec(dev);
|
|
39677
|
+
if (!d || d.index !== pos + 2 || d[1] !== id) {
|
|
39678
|
+
throw new TrimRefusal(`dev/index.ts: the SCREENS entry "${id}" does not open with its own \`"screenId": "${id}"\``);
|
|
39679
|
+
}
|
|
39680
|
+
const block = parseJson(dev.slice(open, close), `the screen "${id}" in dev/index.ts`);
|
|
39681
|
+
const route = { kind: "screen", label: id, lineStart: pos, end: close + 2, open, close, block, bundles: bundlesOf(block) };
|
|
39682
|
+
routes.push(route);
|
|
39683
|
+
exact.set(id, route);
|
|
39684
|
+
pos = close + 2;
|
|
39685
|
+
}
|
|
39686
|
+
const tAt = dev.indexOf("const TEMPLATED");
|
|
39687
|
+
const tOpen = tAt < 0 ? -1 : dev.indexOf("= [\n", tAt);
|
|
39688
|
+
if (tOpen < 0) throw new TrimRefusal("dev/index.ts has no `const TEMPLATED \u2026 = [` \u2014 trim reads the templated routes in the shape `himi init` writes");
|
|
39689
|
+
pos = tOpen + "= [\n".length;
|
|
39690
|
+
const templatedStart = pos;
|
|
39691
|
+
const templated = [];
|
|
39692
|
+
const TENTRY = / \{ pattern: ("(?:[^"\\\n]|\\.)*"), display: ("(?:[^"\\\n]|\\.)*"),/y;
|
|
39693
|
+
for (; ; ) {
|
|
39694
|
+
if (dev.startsWith("];", pos) || dev.startsWith("\n];", pos)) break;
|
|
39695
|
+
TENTRY.lastIndex = pos;
|
|
39696
|
+
const m = TENTRY.exec(dev);
|
|
39697
|
+
if (!m) throw new TrimRefusal(`dev/index.ts line ${lineOf(dev, pos)}: expected a \`{ pattern: \u2026, display: \u2026, template: {\u2026} },\` entry of TEMPLATED`);
|
|
39698
|
+
const pattern = jsonString(m[1], `dev/index.ts line ${lineOf(dev, pos)}: the TEMPLATED pattern`);
|
|
39699
|
+
const display = jsonString(m[2], `dev/index.ts line ${lineOf(dev, pos)}: the TEMPLATED display`);
|
|
39700
|
+
const lineEnd = dev.indexOf("\n", pos);
|
|
39701
|
+
const tk = dev.indexOf("template: {", pos);
|
|
39702
|
+
if (tk < 0 || tk > lineEnd) throw new TrimRefusal(`dev/index.ts: the templated route ${display} has no \`template: {\` on its first line`);
|
|
39703
|
+
const open = tk + "template: ".length;
|
|
39704
|
+
const close = objectEnd(dev, open);
|
|
39705
|
+
if (close < 0 || dev.slice(close, close + 4) !== " },\n") {
|
|
39706
|
+
throw new TrimRefusal(`dev/index.ts: the templated route ${display} does not end in \`} },\``);
|
|
39707
|
+
}
|
|
39708
|
+
const re = routeMatcher(pattern);
|
|
39709
|
+
if (!re) {
|
|
39710
|
+
throw new TrimRefusal(`dev/index.ts: the templated route ${display} has a pattern trim does not recognise (${JSON.stringify(pattern)}); trim compiles a route pattern only when it is anchored and cannot backtrack exponentially (no repeated group whose body repeats or alternates, no backreferences or lookarounds)`);
|
|
39711
|
+
}
|
|
39712
|
+
const block = parseJson(dev.slice(open, close), `the templated route ${display} in dev/index.ts`);
|
|
39713
|
+
const label2 = display.replace(/[[{].*$/, "").replace(/[_/]+$/, "") || display;
|
|
39714
|
+
const route = { kind: "templated", label: label2, lineStart: pos, end: close + 4, open, close, block, re, bundles: bundlesOf(block) };
|
|
39715
|
+
routes.push(route);
|
|
39716
|
+
templated.push(route);
|
|
39717
|
+
pos = close + 4;
|
|
39718
|
+
}
|
|
39719
|
+
const templatedRegion = [templatedStart, pos];
|
|
39720
|
+
const hm = /\n {2}homeScreenId: ("(?:[^"\\\n]|\\.)*"),\n/.exec(dev);
|
|
39721
|
+
if (!hm) throw new TrimRefusal('dev/index.ts has no `homeScreenId: "\u2026",` in its default export');
|
|
39722
|
+
const homeId = jsonString(hm[1], "dev/index.ts: homeScreenId");
|
|
39723
|
+
const home = exact.get(homeId);
|
|
39724
|
+
if (!home) throw new TrimRefusal(`dev/index.ts: homeScreenId "${homeId}" is not a screen in the SCREENS map`);
|
|
39725
|
+
const NAV_ANCHOR = "\n navigation: {";
|
|
39726
|
+
const nAt = config.indexOf(NAV_ANCHOR);
|
|
39727
|
+
if (nAt < 0) throw new TrimRefusal("config.ts has no `navigation: {` \u2014 trim rewrites navigation in the shape `himi init` writes");
|
|
39728
|
+
const nOpen = nAt + NAV_ANCHOR.length - 1;
|
|
39729
|
+
const nClose = objectEnd(config, nOpen);
|
|
39730
|
+
if (nClose < 0) throw new TrimRefusal("config.ts: the navigation object never closes");
|
|
39731
|
+
const navValue = parseJson(config.slice(nOpen, nClose), "config.ts navigation");
|
|
39732
|
+
const subtree = parseSubtree(config);
|
|
39733
|
+
return { dev, config, home, routes, exact, templated, templatedRegion, nav: { open: nOpen, close: nClose, value: navValue }, subtree };
|
|
39734
|
+
}
|
|
39735
|
+
function resolveIn(app, id) {
|
|
39736
|
+
return app.exact.get(id) ?? app.templated.find((r) => r.re.test(id));
|
|
39737
|
+
}
|
|
39738
|
+
function openTarget(action) {
|
|
39739
|
+
const a = action;
|
|
39740
|
+
return a?.actionId === "himi.open" && isStatic(a.params?.screenId) ? a.params.screenId : void 0;
|
|
39741
|
+
}
|
|
39742
|
+
function linksOf(route) {
|
|
39743
|
+
const out = [];
|
|
39744
|
+
const walk2 = (v, owner) => {
|
|
39745
|
+
if (Array.isArray(v)) return v.forEach((c) => walk2(c, owner));
|
|
39746
|
+
if (!v || typeof v !== "object") return;
|
|
39747
|
+
const here = typeof v.id === "string" ? entryLabel(v) : owner;
|
|
39748
|
+
const to = openTarget(v);
|
|
39749
|
+
if (to) out.push({ from: route, node: here, to });
|
|
39750
|
+
for (const child of Object.values(v)) walk2(child, here);
|
|
39751
|
+
};
|
|
39752
|
+
walk2(route.block, "(screen)");
|
|
39753
|
+
return out;
|
|
39754
|
+
}
|
|
39755
|
+
function tapTarget(entry) {
|
|
39756
|
+
const e = entry;
|
|
39757
|
+
for (const a of [e.action, e.onTap, e.modifiers?.onTap, e.body?.props?.action, e.body?.props?.onTap]) {
|
|
39758
|
+
const to = openTarget(a);
|
|
39759
|
+
if (to) return to;
|
|
39760
|
+
}
|
|
39761
|
+
return void 0;
|
|
39762
|
+
}
|
|
39763
|
+
function rowTemplateTarget(entry, removed) {
|
|
39764
|
+
if (!isNode3(entry)) return void 0;
|
|
39765
|
+
const props = entry.body.props;
|
|
39766
|
+
if (!props?.itemsPath || !Array.isArray(props.items)) return void 0;
|
|
39767
|
+
for (const row of props.items) {
|
|
39768
|
+
const to = tapTarget(row);
|
|
39769
|
+
if (to && removed(to)) return to;
|
|
39770
|
+
}
|
|
39771
|
+
return void 0;
|
|
39772
|
+
}
|
|
39773
|
+
function emptyDeadCases(root, isDead) {
|
|
39774
|
+
const out = [];
|
|
39775
|
+
const walk2 = (v) => {
|
|
39776
|
+
if (Array.isArray(v)) return v.forEach(walk2);
|
|
39777
|
+
if (!v || typeof v !== "object") return;
|
|
39778
|
+
for (const child of Object.values(v)) walk2(child);
|
|
39779
|
+
if (!isNode3(v) || v.body.type !== "FragmentSlot" || !Array.isArray(v.body.props?.cases)) return;
|
|
39780
|
+
for (const c of v.body.props.cases) {
|
|
39781
|
+
if (!isNode3(c.content) || !pruneTree(c.content, isDead).emptied) continue;
|
|
39782
|
+
const props = c.content.body.props ?? {};
|
|
39783
|
+
for (const key2 of props.itemsPath ? ["children"] : ["children", "items"]) {
|
|
39784
|
+
if (Array.isArray(props[key2]) && props[key2].length) props[key2] = [];
|
|
39785
|
+
}
|
|
39786
|
+
out.push({ id: String(c.id ?? ""), byModuleId: v.body.props.casePath === "$item.id" });
|
|
39787
|
+
}
|
|
39788
|
+
};
|
|
39789
|
+
walk2(root);
|
|
39790
|
+
return out;
|
|
39791
|
+
}
|
|
39792
|
+
function dropModules(block, ids) {
|
|
39793
|
+
const dropped = [];
|
|
39794
|
+
const walk2 = (v) => {
|
|
39795
|
+
if (Array.isArray(v)) return v.forEach(walk2);
|
|
39796
|
+
if (!v || typeof v !== "object") return;
|
|
39797
|
+
const rec = v;
|
|
39798
|
+
if (typeof rec.homeModules === "string") {
|
|
39799
|
+
try {
|
|
39800
|
+
const modules = JSON.parse(rec.homeModules);
|
|
39801
|
+
const kept = Array.isArray(modules) ? modules.filter((m) => !(typeof m?.id === "string" && ids.has(m.id))) : void 0;
|
|
39802
|
+
if (kept && kept.length && kept.length < modules.length) {
|
|
39803
|
+
for (const m of modules) if (!kept.includes(m)) dropped.push(String(m.id));
|
|
39804
|
+
rec.homeModules = JSON.stringify(kept);
|
|
39805
|
+
}
|
|
39806
|
+
} catch {
|
|
39807
|
+
}
|
|
39808
|
+
}
|
|
39809
|
+
for (const child of Object.values(rec)) walk2(child);
|
|
39810
|
+
};
|
|
39811
|
+
walk2(block);
|
|
39812
|
+
return dropped;
|
|
39813
|
+
}
|
|
39814
|
+
function pruneChrome(items, removed, ledger) {
|
|
39815
|
+
const gone = (item) => typeof item.screenId === "string" && removed(item.screenId);
|
|
39816
|
+
const groups = [{ rows: [] }];
|
|
39817
|
+
for (const item of items) {
|
|
39818
|
+
if (item.role === "section") groups.push({ header: item, rows: [] });
|
|
39819
|
+
else groups[groups.length - 1].rows.push(item);
|
|
39820
|
+
}
|
|
39821
|
+
const out = [];
|
|
39822
|
+
for (const g of groups) {
|
|
39823
|
+
const navigable = g.rows.filter((r) => typeof r.screenId === "string");
|
|
39824
|
+
const keptRows = g.rows.filter((r) => !gone(r));
|
|
39825
|
+
const emptied = !!g.header && navigable.length > 0 && !keptRows.some((r) => typeof r.screenId === "string");
|
|
39826
|
+
if (g.header && !emptied) out.push(g.header);
|
|
39827
|
+
for (const r of emptied ? [] : keptRows) out.push(r);
|
|
39828
|
+
}
|
|
39829
|
+
const keptSet = new Set(out);
|
|
39830
|
+
for (const item of items) if (!keptSet.has(item)) ledger.push(typeof item.id === "string" ? item.id : String(item.screenId ?? "(unnamed)"));
|
|
39831
|
+
return out;
|
|
39832
|
+
}
|
|
39833
|
+
function rewriteNav(nav, removed, homeId) {
|
|
39834
|
+
const next = structuredClone(nav);
|
|
39835
|
+
const report2 = { linkable: [], tabs: [], drawer: [], sidebar: [], deepLinkPatterns: [], topBarActions: [], headerActions: [], surfaceDestinations: [], appIconBadgeSources: [], reparented: [] };
|
|
39836
|
+
const tabItems = asItems(next.tabBar);
|
|
39837
|
+
const hadTabs = !!tabItems?.length;
|
|
39838
|
+
if (tabItems) next.tabBar.items = pruneChrome(tabItems, removed, report2.tabs);
|
|
39839
|
+
const drawerItems = asItems(next.drawer);
|
|
39840
|
+
if (drawerItems) next.drawer.items = pruneChrome(drawerItems, removed, report2.drawer);
|
|
39841
|
+
const sidebarItems = asItems(next.sidebar);
|
|
39842
|
+
if (sidebarItems) next.sidebar.items = pruneChrome(sidebarItems, removed, report2.sidebar);
|
|
39843
|
+
if (hadTabs && !asItems(next.tabBar).length) {
|
|
39844
|
+
throw new TrimRefusal(`no tab would remain \u2014 every tabBar item opens a screen this trim removes (${report2.tabs.join(", ")}); keep at least one tab's screen`, { removedTabs: report2.tabs });
|
|
39845
|
+
}
|
|
39846
|
+
const remainingRoots = [...asItems(next.tabBar) ?? [], ...asItems(next.sidebar) ?? []].filter((i) => i.role !== "section");
|
|
39847
|
+
const remainingRootIds = new Set(remainingRoots.map((i) => i.id).filter((id) => typeof id === "string"));
|
|
39848
|
+
const removedRootIds = /* @__PURE__ */ new Set([...report2.tabs, ...report2.sidebar]);
|
|
39849
|
+
if (Array.isArray(next.deepLinkPatterns)) {
|
|
39850
|
+
next.deepLinkPatterns = next.deepLinkPatterns.filter((p) => {
|
|
39851
|
+
const id = p?.params?.screenId ?? p?.screenId;
|
|
39852
|
+
if (typeof id === "string" && removed(id)) {
|
|
39853
|
+
report2.deepLinkPatterns.push(String(p.pattern ?? id));
|
|
39854
|
+
return false;
|
|
39855
|
+
}
|
|
39856
|
+
return true;
|
|
39857
|
+
});
|
|
39858
|
+
}
|
|
39859
|
+
for (const key2 of ["drawer", "sidebar"]) {
|
|
39860
|
+
const actions = next[key2]?.header?.actions;
|
|
39861
|
+
if (!Array.isArray(actions)) continue;
|
|
39862
|
+
next[key2].header.actions = actions.filter((a) => {
|
|
39863
|
+
if (!(typeof a?.screenId === "string" && removed(a.screenId))) return true;
|
|
39864
|
+
report2.headerActions.push(`${key2}:${String(a.icon ?? a.screenId)}`);
|
|
39865
|
+
return false;
|
|
39866
|
+
});
|
|
39867
|
+
}
|
|
39868
|
+
const topActions = next.topBarDefault?.actions;
|
|
39869
|
+
if (Array.isArray(topActions)) {
|
|
39870
|
+
next.topBarDefault.actions = topActions.filter((a) => {
|
|
39871
|
+
const to = openTarget(a?.onTap) ?? openTarget(a?.action);
|
|
39872
|
+
if (to && removed(to)) {
|
|
39873
|
+
report2.topBarActions.push(entryLabel(a));
|
|
39874
|
+
return false;
|
|
39875
|
+
}
|
|
39876
|
+
return true;
|
|
39877
|
+
});
|
|
39878
|
+
}
|
|
39879
|
+
if (next.surfaces && typeof next.surfaces === "object") {
|
|
39880
|
+
for (const [surface, cfg] of Object.entries(next.surfaces)) {
|
|
39881
|
+
if (!cfg || typeof cfg !== "object") continue;
|
|
39882
|
+
const goneDest = (id) => typeof id === "string" && !remainingRootIds.has(id) && (removedRootIds.has(id) || removed(id));
|
|
39883
|
+
const unmapped = /* @__PURE__ */ new Set();
|
|
39884
|
+
if (cfg.screenIds && typeof cfg.screenIds === "object") {
|
|
39885
|
+
for (const [dest, screenId] of Object.entries(cfg.screenIds)) {
|
|
39886
|
+
if (goneDest(dest) || typeof screenId === "string" && removed(screenId)) {
|
|
39887
|
+
delete cfg.screenIds[dest];
|
|
39888
|
+
report2.surfaceDestinations.push(`${surface}:${dest}`);
|
|
39889
|
+
if (!remainingRootIds.has(dest)) unmapped.add(dest);
|
|
39890
|
+
}
|
|
39891
|
+
}
|
|
39892
|
+
}
|
|
39893
|
+
if (Array.isArray(cfg.destinations)) {
|
|
39894
|
+
cfg.destinations = cfg.destinations.filter((id) => {
|
|
39895
|
+
const gone = goneDest(id) || typeof id === "string" && unmapped.has(id);
|
|
39896
|
+
if (!gone) return true;
|
|
39897
|
+
const entry = `${surface}:${String(id)}`;
|
|
39898
|
+
if (!report2.surfaceDestinations.includes(entry)) report2.surfaceDestinations.push(entry);
|
|
39899
|
+
return false;
|
|
39900
|
+
});
|
|
39901
|
+
}
|
|
39902
|
+
}
|
|
39903
|
+
}
|
|
39904
|
+
if (Array.isArray(next.appIconBadgeSources)) {
|
|
39905
|
+
const goneActions = new Set(report2.topBarActions);
|
|
39906
|
+
const idsOf = (items) => new Set((items ?? []).map((i) => i.id).filter((x) => typeof x === "string"));
|
|
39907
|
+
const removedTabs = new Set(report2.tabs);
|
|
39908
|
+
const removedDrawer = new Set(report2.drawer);
|
|
39909
|
+
const remainingTabIds = idsOf(asItems(next.tabBar));
|
|
39910
|
+
const remainingDrawerIds = idsOf(asItems(next.drawer));
|
|
39911
|
+
next.appIconBadgeSources = next.appIconBadgeSources.filter((s) => {
|
|
39912
|
+
if (typeof s !== "string") return true;
|
|
39913
|
+
const [kind, id] = [s.slice(0, s.indexOf(":")), s.slice(s.indexOf(":") + 1)];
|
|
39914
|
+
const gone = kind === "topBarAction" ? goneActions.has(id) : kind === "tab" ? removedTabs.has(id) && !remainingTabIds.has(id) : kind === "drawer" ? removedDrawer.has(id) && !remainingDrawerIds.has(id) : false;
|
|
39915
|
+
if (gone) report2.appIconBadgeSources.push(s);
|
|
39916
|
+
return !gone;
|
|
39917
|
+
});
|
|
39918
|
+
}
|
|
39919
|
+
if (Array.isArray(next.linkableScreens)) {
|
|
39920
|
+
const original = next.linkableScreens;
|
|
39921
|
+
const byId = /* @__PURE__ */ new Map();
|
|
39922
|
+
for (const l of original) if (typeof l.screenId === "string") byId.set(l.screenId, l);
|
|
39923
|
+
const kept = original.filter((l) => {
|
|
39924
|
+
if (typeof l.screenId === "string" && removed(l.screenId)) {
|
|
39925
|
+
report2.linkable.push(l.screenId);
|
|
39926
|
+
return false;
|
|
39927
|
+
}
|
|
39928
|
+
return true;
|
|
39929
|
+
});
|
|
39930
|
+
const keptById = /* @__PURE__ */ new Map();
|
|
39931
|
+
for (const l of kept) if (typeof l.screenId === "string") keptById.set(l.screenId, l);
|
|
39932
|
+
const newParent = (l) => {
|
|
39933
|
+
let p = typeof l.parentScreenId === "string" ? l.parentScreenId : "";
|
|
39934
|
+
const seen = /* @__PURE__ */ new Set();
|
|
39935
|
+
while (p && removed(p) && !seen.has(p)) {
|
|
39936
|
+
seen.add(p);
|
|
39937
|
+
const up = byId.get(p)?.parentScreenId;
|
|
39938
|
+
p = typeof up === "string" ? up : "";
|
|
39939
|
+
}
|
|
39940
|
+
return p;
|
|
39941
|
+
};
|
|
39942
|
+
const tabFor = (screenId) => {
|
|
39943
|
+
const own2 = remainingRoots.find((t) => t.screenId === screenId);
|
|
39944
|
+
return typeof own2?.id === "string" ? own2.id : void 0;
|
|
39945
|
+
};
|
|
39946
|
+
const homeTab = tabFor(homeId) ?? (typeof remainingRoots[0]?.id === "string" ? remainingRoots[0].id : "");
|
|
39947
|
+
const finalTab = /* @__PURE__ */ new Map();
|
|
39948
|
+
const resolveTab = (l, depth = 0) => {
|
|
39949
|
+
if (finalTab.has(l)) return finalTab.get(l);
|
|
39950
|
+
const current = typeof l.tabId === "string" ? l.tabId : "";
|
|
39951
|
+
let tab = current;
|
|
39952
|
+
if (current && removedRootIds.has(current) && !remainingRootIds.has(current)) {
|
|
39953
|
+
const parent = newParent(l);
|
|
39954
|
+
const pl = parent ? keptById.get(parent) : void 0;
|
|
39955
|
+
tab = pl && pl !== l && depth < 64 ? resolveTab(pl, depth + 1) : tabFor(String(l.screenId)) ?? homeTab;
|
|
39956
|
+
}
|
|
39957
|
+
finalTab.set(l, tab);
|
|
39958
|
+
return tab;
|
|
39959
|
+
};
|
|
39960
|
+
for (const l of kept) {
|
|
39961
|
+
const fromParent = typeof l.parentScreenId === "string" ? l.parentScreenId : "";
|
|
39962
|
+
const fromTab = typeof l.tabId === "string" ? l.tabId : "";
|
|
39963
|
+
const toParent = newParent(l);
|
|
39964
|
+
const toTab = resolveTab(l);
|
|
39965
|
+
if (toParent === fromParent && toTab === fromTab) continue;
|
|
39966
|
+
const entry = { screenId: String(l.screenId) };
|
|
39967
|
+
if (toParent !== fromParent) entry.parentScreenId = { from: fromParent, to: toParent };
|
|
39968
|
+
if (toTab !== fromTab) entry.tabId = { from: fromTab, to: toTab };
|
|
39969
|
+
report2.reparented.push(entry);
|
|
39970
|
+
}
|
|
39971
|
+
for (const l of kept) {
|
|
39972
|
+
if (typeof l.parentScreenId === "string") l.parentScreenId = newParent(l);
|
|
39973
|
+
if (typeof l.tabId === "string") l.tabId = resolveTab(l);
|
|
39974
|
+
}
|
|
39975
|
+
next.linkableScreens = kept;
|
|
39976
|
+
}
|
|
39977
|
+
return { nav: next, report: report2 };
|
|
39978
|
+
}
|
|
39979
|
+
function leftoverNavRefs(nav, removedIds) {
|
|
39980
|
+
const gone = new Set(removedIds);
|
|
39981
|
+
const out = [];
|
|
39982
|
+
const walk2 = (v, path2) => {
|
|
39983
|
+
if (Array.isArray(v)) return v.forEach((c, i) => walk2(c, `${path2}[${i}]`));
|
|
39984
|
+
if (!v || typeof v !== "object") return;
|
|
39985
|
+
for (const [k, child] of Object.entries(v)) {
|
|
39986
|
+
const here = path2 ? `${path2}.${k}` : k;
|
|
39987
|
+
if (NAV_SCREEN_KEYS.has(k) && typeof child === "string") {
|
|
39988
|
+
if (gone.has(child)) out.push(`${here}=${child}`);
|
|
39989
|
+
} else if (k === "screenIds" && child && typeof child === "object" && !Array.isArray(child)) {
|
|
39990
|
+
for (const [dest, id] of Object.entries(child)) if (typeof id === "string" && gone.has(id)) out.push(`${here}.${dest}=${id}`);
|
|
39991
|
+
} else walk2(child, here);
|
|
39992
|
+
}
|
|
39993
|
+
};
|
|
39994
|
+
walk2(nav, "");
|
|
39995
|
+
return out;
|
|
39996
|
+
}
|
|
39997
|
+
function navPinnedScreens(nav) {
|
|
39998
|
+
const out = [];
|
|
39999
|
+
const add = (v) => {
|
|
40000
|
+
if (isStatic(v)) out.push(v);
|
|
40001
|
+
};
|
|
40002
|
+
for (const key2 of ["drawer", "sidebar"]) {
|
|
40003
|
+
const block = nav[key2];
|
|
40004
|
+
if (!block || typeof block !== "object") continue;
|
|
40005
|
+
add(block.contentScreenId);
|
|
40006
|
+
add(block.header?.screenId);
|
|
40007
|
+
add(block.footer?.screenId);
|
|
40008
|
+
add(block.footer?.badgeScreenId);
|
|
40009
|
+
}
|
|
40010
|
+
return out;
|
|
40011
|
+
}
|
|
40012
|
+
function planTrim(src, keepIds, links) {
|
|
40013
|
+
const app = parseApp(src.dev, src.config);
|
|
40014
|
+
const kept = /* @__PURE__ */ new Set([app.home]);
|
|
40015
|
+
const unknown = [];
|
|
40016
|
+
for (const id of keepIds) {
|
|
40017
|
+
const hits = [];
|
|
40018
|
+
const ex = app.exact.get(id);
|
|
40019
|
+
if (ex) hits.push(ex);
|
|
40020
|
+
const base = app.templated.find((r) => r.label === id);
|
|
40021
|
+
if (base) hits.push(base);
|
|
40022
|
+
if (!hits.length) {
|
|
40023
|
+
const served = app.templated.find((r) => r.re.test(id));
|
|
40024
|
+
if (served) hits.push(served);
|
|
40025
|
+
}
|
|
40026
|
+
if (!hits.length) unknown.push(id);
|
|
40027
|
+
for (const r of hits) kept.add(r);
|
|
40028
|
+
}
|
|
40029
|
+
if (unknown.length) {
|
|
40030
|
+
throw new TrimRefusal(`unknown screen id${unknown.length > 1 ? "s" : ""} ${unknown.join(", ")} \u2014 --keep takes the ids this app serves`, {
|
|
40031
|
+
unknown,
|
|
40032
|
+
validIds: sorted(app.routes.map((r) => r.label))
|
|
40033
|
+
});
|
|
40034
|
+
}
|
|
40035
|
+
const explicit = new Set([...kept].filter((r) => r !== app.home || keepIds.includes(app.home.label)));
|
|
40036
|
+
const implicit = explicit.has(app.home) ? [] : [app.home];
|
|
40037
|
+
for (const id of navPinnedScreens(app.nav.value)) {
|
|
40038
|
+
const route = resolveIn(app, id);
|
|
40039
|
+
if (!route || kept.has(route)) continue;
|
|
40040
|
+
kept.add(route);
|
|
40041
|
+
implicit.push(route);
|
|
40042
|
+
}
|
|
40043
|
+
const follow = (seed2) => {
|
|
40044
|
+
const set = new Set(seed2);
|
|
40045
|
+
const added = [];
|
|
40046
|
+
const queue = app.routes.filter((r) => set.has(r));
|
|
40047
|
+
while (queue.length) {
|
|
40048
|
+
const r = queue.shift();
|
|
40049
|
+
for (const link of linksOf(r)) {
|
|
40050
|
+
const target = resolveIn(app, link.to);
|
|
40051
|
+
if (!target || set.has(target)) continue;
|
|
40052
|
+
set.add(target);
|
|
40053
|
+
added.push({ screen: r.label, node: link.node, to: target.label });
|
|
40054
|
+
queue.push(target);
|
|
40055
|
+
}
|
|
40056
|
+
}
|
|
40057
|
+
return { set, added };
|
|
40058
|
+
};
|
|
40059
|
+
let addedByLinks;
|
|
40060
|
+
if (links === "follow") {
|
|
40061
|
+
const closed = follow(kept);
|
|
40062
|
+
for (const r of closed.set) kept.add(r);
|
|
40063
|
+
addedByLinks = closed.added;
|
|
40064
|
+
}
|
|
40065
|
+
const isKept = (r) => !r || kept.has(r);
|
|
40066
|
+
const removedRoutes = app.routes.filter((r) => !kept.has(r));
|
|
40067
|
+
const keptRoutes = app.routes.filter((r) => kept.has(r));
|
|
40068
|
+
const removedTarget = (id) => !isKept(resolveIn(app, id));
|
|
40069
|
+
const dropped = [];
|
|
40070
|
+
const unremovable = [];
|
|
40071
|
+
const emptied = [];
|
|
40072
|
+
const emptiedCases = [];
|
|
40073
|
+
const caseModules = [];
|
|
40074
|
+
const edited = /* @__PURE__ */ new Map();
|
|
40075
|
+
for (const r of keptRoutes) {
|
|
40076
|
+
if (!linksOf(r).some((l) => removedTarget(l.to))) continue;
|
|
40077
|
+
const block = structuredClone(r.block);
|
|
40078
|
+
const isDead = (entry) => {
|
|
40079
|
+
const own2 = tapTarget(entry);
|
|
40080
|
+
const to = own2 && removedTarget(own2) ? own2 : rowTemplateTarget(entry, removedTarget);
|
|
40081
|
+
if (!to) return false;
|
|
40082
|
+
dropped.push({ screen: r.label, node: entryLabel(entry), to });
|
|
40083
|
+
return true;
|
|
40084
|
+
};
|
|
40085
|
+
const topBar = block.topBar;
|
|
40086
|
+
if (topBar && Array.isArray(topBar.actions)) topBar.actions = topBar.actions.filter((a) => !isDead(a));
|
|
40087
|
+
const cases = emptyDeadCases(block.payload, isDead);
|
|
40088
|
+
for (const c of cases) emptiedCases.push({ screen: r.label, case: c.id });
|
|
40089
|
+
if (pruneTree(block.payload, isDead).emptied) emptied.push(r.label);
|
|
40090
|
+
const moduleIds = new Set(cases.filter((c) => c.byModuleId).map((c) => c.id));
|
|
40091
|
+
if (moduleIds.size) caseModules.push(...dropModules(block, moduleIds));
|
|
40092
|
+
for (const l of linksOf({ ...r, block })) if (removedTarget(l.to)) unremovable.push({ screen: r.label, to: l.to });
|
|
40093
|
+
edited.set(r, block);
|
|
40094
|
+
}
|
|
40095
|
+
const followWouldAdd = sorted([...follow(kept).set].filter((r) => !kept.has(r)).map((r) => r.label));
|
|
40096
|
+
if (dropped.length || unremovable.length) {
|
|
40097
|
+
if (!links) {
|
|
40098
|
+
throw new TrimRefusal(`kept screens link to screens this trim would remove \u2014 choose what happens to those links with --links`, {
|
|
40099
|
+
droppedLinks: dropped,
|
|
40100
|
+
...emptiedCases.length ? { emptiedCases } : {},
|
|
40101
|
+
...unremovable.length ? { unremovable } : {},
|
|
40102
|
+
...emptied.length ? { dropWouldEmpty: emptied } : {},
|
|
40103
|
+
followWouldAdd,
|
|
40104
|
+
hint: `--links drop removes the ${dropped.length} tapping node(s) listed in droppedLinks; --links follow keeps ${followWouldAdd.join(", ")} as well`
|
|
40105
|
+
});
|
|
40106
|
+
}
|
|
40107
|
+
if (emptied.length) {
|
|
40108
|
+
throw new TrimRefusal(`dropping the links in ${emptied.map((id) => `"${id}"`).join(", ")} would empty the screen's root \u2014 nothing would be left on it; keep what it links to (--links follow) or add those ids to --keep`, {
|
|
40109
|
+
dropWouldEmpty: emptied
|
|
40110
|
+
});
|
|
40111
|
+
}
|
|
40112
|
+
if (unremovable.length) {
|
|
40113
|
+
throw new TrimRefusal(`"${unremovable[0].screen}" links to a removed screen from a position --links drop cannot remove (a screen root, or a slot that is not a child list) \u2014 keep ${sorted(unremovable.map((u) => u.to)).join(", ")}, or edit ${sorted(unremovable.map((u) => u.screen)).join(", ")} by hand first`, {
|
|
40114
|
+
unremovable
|
|
40115
|
+
});
|
|
40116
|
+
}
|
|
40117
|
+
}
|
|
40118
|
+
const removedIds = sorted(removedRoutes.filter((r) => {
|
|
40119
|
+
const res = resolveIn(app, r.label);
|
|
40120
|
+
return !(res && kept.has(res));
|
|
40121
|
+
}).map((r) => r.label));
|
|
40122
|
+
const removedIdSet = new Set(removedIds);
|
|
40123
|
+
const navRemoved = (id) => removedTarget(id) || removedIdSet.has(id);
|
|
40124
|
+
const { nav, report: navReport } = rewriteNav(app.nav.value, navRemoved, app.home.label);
|
|
40125
|
+
const subtreeRemoved = [];
|
|
40126
|
+
const subtreeNext = app.subtree?.value.filter((id) => {
|
|
40127
|
+
if (typeof id !== "string" || id.includes("*") || !app.exact.get(id) || isKept(app.exact.get(id))) return true;
|
|
40128
|
+
subtreeRemoved.push(id);
|
|
40129
|
+
return false;
|
|
40130
|
+
});
|
|
40131
|
+
const configBundles = new Set([...src.config.matchAll(/\/v1\/bundles\/([A-Za-z0-9_-]+)/g)].map((m) => m[1]));
|
|
40132
|
+
const keptWorkers = /* @__PURE__ */ new Set(["_shared", ...configBundles]);
|
|
40133
|
+
for (const r of keptRoutes) for (const b of r.bundles) keptWorkers.add(b);
|
|
40134
|
+
const importsOf = (dir) => {
|
|
40135
|
+
const out = [];
|
|
40136
|
+
for (const [rel, text4] of Object.entries(src.workerFiles)) {
|
|
40137
|
+
if (!rel.startsWith(`tier5-src/${dir}/`)) continue;
|
|
40138
|
+
for (const m of text4.matchAll(/(?:\bfrom\s*|\bimport\s*\(?\s*|\brequire\s*\(\s*)["']\.\.\/([A-Za-z0-9_.-]+)(?:\/|["'])/g)) out.push(m[1]);
|
|
40139
|
+
}
|
|
40140
|
+
return out;
|
|
40141
|
+
};
|
|
40142
|
+
const pending = [...keptWorkers];
|
|
40143
|
+
while (pending.length) {
|
|
40144
|
+
for (const dep of importsOf(pending.pop())) {
|
|
40145
|
+
if (!keptWorkers.has(dep)) {
|
|
40146
|
+
keptWorkers.add(dep);
|
|
40147
|
+
pending.push(dep);
|
|
40148
|
+
}
|
|
40149
|
+
}
|
|
40150
|
+
}
|
|
40151
|
+
const dirs = new Set(src.workerDirs);
|
|
40152
|
+
const removedWorkers = sorted(removedRoutes.flatMap((r) => r.bundles).filter((b) => dirs.has(b) && !keptWorkers.has(b)));
|
|
40153
|
+
const workerRefs = [];
|
|
40154
|
+
const literal = /(["'`])([A-Za-z_][A-Za-z0-9_]*[_/]?)(?=\1|\$\{)/g;
|
|
40155
|
+
for (const rel of Object.keys(src.workerFiles).sort()) {
|
|
40156
|
+
const dir = rel.split("/")[1];
|
|
40157
|
+
if (!keptWorkers.has(dir) || !dirs.has(dir)) continue;
|
|
40158
|
+
const lines = src.workerFiles[rel].split("\n");
|
|
40159
|
+
lines.forEach((line, i) => {
|
|
40160
|
+
for (const m of line.matchAll(literal)) {
|
|
40161
|
+
const token = m[2];
|
|
40162
|
+
const prefix = /[_/]$/.test(token);
|
|
40163
|
+
const route = prefix ? app.templated.find((r) => r.re.test(`${token}x`)) : resolveIn(app, token);
|
|
40164
|
+
if (route && !kept.has(route)) workerRefs.push(`${rel}:${i + 1} \u2192 ${route.label}`);
|
|
40165
|
+
}
|
|
40166
|
+
});
|
|
40167
|
+
}
|
|
40168
|
+
const homeModules = links === "drop" ? homeModulesPass(app, kept, edited) : void 0;
|
|
40169
|
+
let dev = "";
|
|
40170
|
+
let cursor = 0;
|
|
40171
|
+
const cut = (from, to, replacement = "") => {
|
|
40172
|
+
dev += app.dev.slice(cursor, from) + replacement;
|
|
40173
|
+
cursor = to;
|
|
40174
|
+
};
|
|
40175
|
+
const emptyList = (region, list) => list.length > 0 && list.every((r) => !kept.has(r)) ? region : void 0;
|
|
40176
|
+
const templatedEmptied = emptyList(app.templatedRegion, app.templated);
|
|
40177
|
+
for (const r of app.routes) {
|
|
40178
|
+
if (templatedEmptied && r.kind === "templated") continue;
|
|
40179
|
+
if (!kept.has(r)) {
|
|
40180
|
+
cut(r.lineStart, r.end);
|
|
40181
|
+
continue;
|
|
40182
|
+
}
|
|
40183
|
+
const block = edited.get(r);
|
|
40184
|
+
let text4 = block ? serializeAt(block, app.dev, r.open) : void 0;
|
|
40185
|
+
if (r === app.home && homeModules?.text !== void 0) text4 = homeModules.text;
|
|
40186
|
+
if (text4 !== void 0) cut(r.open, r.close, text4);
|
|
40187
|
+
}
|
|
40188
|
+
if (templatedEmptied) cut(templatedEmptied[0], templatedEmptied[1], "\n");
|
|
40189
|
+
dev += app.dev.slice(cursor);
|
|
40190
|
+
let config = app.config;
|
|
40191
|
+
const edits = [];
|
|
40192
|
+
if (JSON.stringify(nav) !== JSON.stringify(app.nav.value)) {
|
|
40193
|
+
edits.push({ start: app.nav.open, end: app.nav.close, text: serializeAt(nav, app.config, app.nav.open) });
|
|
40194
|
+
}
|
|
40195
|
+
if (app.subtree && subtreeRemoved.length) {
|
|
40196
|
+
const wrapped = app.config.slice(app.subtree.start, app.subtree.end).includes("\n");
|
|
40197
|
+
edits.push({ start: app.subtree.start, end: app.subtree.end, text: wrapped ? serializeAt(subtreeNext, app.config, app.subtree.start) : JSON.stringify(subtreeNext) });
|
|
40198
|
+
}
|
|
40199
|
+
for (const e of edits.sort((a, b) => b.start - a.start)) config = config.slice(0, e.start) + e.text + config.slice(e.end);
|
|
40200
|
+
const keptExact = keptRoutes.filter((r) => r.kind === "screen");
|
|
40201
|
+
const keptTemplated = keptRoutes.filter((r) => r.kind === "templated");
|
|
40202
|
+
const report2 = {
|
|
40203
|
+
...links ? { links } : {},
|
|
40204
|
+
kept: { screens: sorted(keptExact.map((r) => r.label)), templated: sorted(keptTemplated.map((r) => r.label)) },
|
|
40205
|
+
implicit: implicit.map((r) => r.label),
|
|
40206
|
+
removed: {
|
|
40207
|
+
screens: sorted(removedRoutes.filter((r) => r.kind === "screen").map((r) => r.label)),
|
|
40208
|
+
templated: sorted(removedRoutes.filter((r) => r.kind === "templated").map((r) => r.label)),
|
|
40209
|
+
workers: removedWorkers,
|
|
40210
|
+
linkable: navReport.linkable,
|
|
40211
|
+
tabs: navReport.tabs,
|
|
40212
|
+
drawer: navReport.drawer,
|
|
40213
|
+
sidebar: navReport.sidebar,
|
|
40214
|
+
deepLinkPatterns: navReport.deepLinkPatterns,
|
|
40215
|
+
topBarActions: navReport.topBarActions,
|
|
40216
|
+
headerActions: navReport.headerActions,
|
|
40217
|
+
surfaceDestinations: navReport.surfaceDestinations,
|
|
40218
|
+
appIconBadgeSources: navReport.appIconBadgeSources,
|
|
40219
|
+
workerSubtreeScreens: subtreeRemoved
|
|
40220
|
+
},
|
|
40221
|
+
reparented: navReport.reparented,
|
|
40222
|
+
...addedByLinks ? { addedByLinks } : {},
|
|
40223
|
+
...links === "drop" ? { droppedLinks: dropped } : {},
|
|
40224
|
+
...links === "drop" && emptiedCases.length ? { emptiedCases } : {},
|
|
40225
|
+
...links === "drop" && (caseModules.length || homeModules?.dropped.length) ? { home: { droppedModules: [...caseModules, ...homeModules?.dropped ?? []] } } : {},
|
|
40226
|
+
warnings: {
|
|
40227
|
+
workerRefs,
|
|
40228
|
+
...workerRefs.length ? { hint: `kept worker code still names ${sorted(workerRefs.map((w) => w.slice(w.lastIndexOf("\u2192 ") + 2))).join(", ")} \u2014 those taps are built at runtime and will open nothing; add the ids to --keep if they should keep working` } : {}
|
|
40229
|
+
},
|
|
40230
|
+
bytes: { before: Buffer.byteLength(app.dev), after: Buffer.byteLength(dev) }
|
|
40231
|
+
};
|
|
40232
|
+
return { dev, config, removedWorkers, removedIds, report: report2 };
|
|
40233
|
+
}
|
|
40234
|
+
function homeModulesPass(app, kept, edited) {
|
|
40235
|
+
const verticals = Object.entries(EXPLORE_CARDS).filter(([, card]) => app.exact.has(card.screenId));
|
|
40236
|
+
const removedVertical = verticals.some(([, card]) => !kept.has(app.exact.get(card.screenId)));
|
|
40237
|
+
if (!removedVertical) return { dropped: [] };
|
|
40238
|
+
const block = edited.get(app.home);
|
|
40239
|
+
const text4 = block ? serializeAt(block, app.dev, app.home.open) : app.dev.slice(app.home.open, app.home.close);
|
|
40240
|
+
const installed = verticals.filter(([, card]) => kept.has(app.exact.get(card.screenId))).map(([v]) => v);
|
|
40241
|
+
const patched = patchHomeModules(text4, installed);
|
|
40242
|
+
if (!patched.droppedModules.length) return { dropped: [] };
|
|
40243
|
+
return { text: patched.src, dropped: patched.droppedModules };
|
|
40244
|
+
}
|
|
40245
|
+
function listWorkers(dir) {
|
|
40246
|
+
const root = join36(dir, "tier5-src");
|
|
40247
|
+
if (!existsSync39(root)) return { dirs: [], files: {} };
|
|
40248
|
+
const dirs = readdirSync20(root).filter((n) => statSync8(join36(root, n)).isDirectory()).sort();
|
|
40249
|
+
const files = {};
|
|
40250
|
+
const walk2 = (abs, rel) => {
|
|
40251
|
+
for (const name of readdirSync20(abs)) {
|
|
40252
|
+
if (name === "node_modules") continue;
|
|
40253
|
+
const p = join36(abs, name);
|
|
40254
|
+
const r = `${rel}/${name}`;
|
|
40255
|
+
if (statSync8(p).isDirectory()) walk2(p, r);
|
|
40256
|
+
else if (/\.(?:[cm]?[jt]sx?|json)$/.test(name)) files[r] = readFileSync43(p, "utf8");
|
|
40257
|
+
}
|
|
40258
|
+
};
|
|
40259
|
+
for (const d of dirs) walk2(join36(root, d), `tier5-src/${d}`);
|
|
40260
|
+
return { dirs, files };
|
|
40261
|
+
}
|
|
40262
|
+
function csv(v) {
|
|
40263
|
+
if (v === void 0 || v === true || v === false) return void 0;
|
|
40264
|
+
const parts = (Array.isArray(v) ? v : [v]).flatMap((s) => s.split(",")).map((s) => s.trim()).filter(Boolean);
|
|
40265
|
+
return parts.length ? [...new Set(parts)] : void 0;
|
|
40266
|
+
}
|
|
40267
|
+
async function runTemplateTrim(req, deps) {
|
|
40268
|
+
const keep = csv(req.keep);
|
|
40269
|
+
if (!keep) {
|
|
40270
|
+
return refuse3(new TrimRefusal("--keep is required \u2014 the screen ids to keep, comma-separated (the home screen is always kept)", {
|
|
40271
|
+
usage: "himi template trim --keep <id,id,\u2026> [--content <dir>] [--links follow|drop] [--dry-run] [--force]"
|
|
40272
|
+
}));
|
|
40273
|
+
}
|
|
40274
|
+
let links;
|
|
40275
|
+
if (req.links !== void 0) {
|
|
40276
|
+
if (req.links !== "follow" && req.links !== "drop") {
|
|
40277
|
+
return refuse3(new TrimRefusal(`--links takes follow or drop (got ${JSON.stringify(req.links)})`));
|
|
40278
|
+
}
|
|
40279
|
+
links = req.links;
|
|
40280
|
+
}
|
|
40281
|
+
const dir = req.dir;
|
|
40282
|
+
const devPath = join36(dir, "dev/index.ts");
|
|
40283
|
+
const configPath = join36(dir, "config.ts");
|
|
40284
|
+
if (!existsSync39(devPath) || !existsSync39(configPath)) {
|
|
40285
|
+
return refuse3(new TrimRefusal(`${dir} has no dev/index.ts + config.ts \u2014 point --content at an app scaffolded with \`himi init --template\``));
|
|
40286
|
+
}
|
|
40287
|
+
if (isTemplateSourceTree(dir)) {
|
|
40288
|
+
return refuse3(new TrimRefusal(`${dir} is a template source tree (its identity is still __HIMI_APP_*__ sentinels) \u2014 trim the app \`himi init --template\` scaffolds from it, not the template itself`));
|
|
40289
|
+
}
|
|
40290
|
+
const dev = readFileSync43(devPath, "utf8");
|
|
40291
|
+
const config = readFileSync43(configPath, "utf8");
|
|
40292
|
+
const workers = listWorkers(dir);
|
|
40293
|
+
let plan;
|
|
40294
|
+
try {
|
|
40295
|
+
plan = planTrim({ dev, config, workerDirs: workers.dirs, workerFiles: workers.files }, keep, links);
|
|
40296
|
+
} catch (e) {
|
|
40297
|
+
if (e instanceof TrimRefusal) return refuse3(e);
|
|
40298
|
+
throw e;
|
|
40299
|
+
}
|
|
40300
|
+
if (req.dryRun) return { code: 0, result: { ok: true, dryRun: true, ...plan.report, validate: null } };
|
|
40301
|
+
const hadHimi = existsSync39(join36(dir, ".himi"));
|
|
40302
|
+
const backupRel = join36(".himi", "trim-backup", (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
|
|
40303
|
+
const backup = join36(dir, backupRel);
|
|
40304
|
+
const originals = [[devPath, "dev/index.ts"], [configPath, "config.ts"]];
|
|
40305
|
+
const moved = [];
|
|
40306
|
+
const restore = () => {
|
|
40307
|
+
for (const [path2, rel] of originals) {
|
|
40308
|
+
const original = readFileSync43(join36(backup, rel));
|
|
40309
|
+
if (!existsSync39(path2) || !readFileSync43(path2).equals(original)) writeFileSync14(path2, original);
|
|
40310
|
+
}
|
|
40311
|
+
for (const name of [...moved].reverse()) renameSync3(join36(backup, "tier5-src", name), join36(dir, "tier5-src", name));
|
|
40312
|
+
};
|
|
40313
|
+
const dropBackup = () => {
|
|
40314
|
+
rmSync6(backup, { recursive: true, force: true });
|
|
40315
|
+
for (const d of [dirname23(backup), join36(dir, ".himi")]) {
|
|
40316
|
+
if (d === join36(dir, ".himi") && hadHimi) break;
|
|
40317
|
+
try {
|
|
40318
|
+
if (!readdirSync20(d).length) rmSync6(d, { recursive: true });
|
|
40319
|
+
} catch {
|
|
40320
|
+
}
|
|
40321
|
+
}
|
|
40322
|
+
};
|
|
40323
|
+
const base = (validate4) => ({
|
|
40324
|
+
dryRun: false,
|
|
40325
|
+
...plan.report,
|
|
40326
|
+
validate: validate4 ? { counts: validate4.counts ?? null, ...validate4.tail ? { tail: validate4.tail } : {} } : null
|
|
40327
|
+
});
|
|
40328
|
+
const abort = (error, cause, validate4) => {
|
|
40329
|
+
const message = cause?.message ?? String(cause);
|
|
40330
|
+
try {
|
|
40331
|
+
restore();
|
|
40332
|
+
} catch (e) {
|
|
40333
|
+
return {
|
|
40334
|
+
code: 1,
|
|
40335
|
+
result: { ok: false, error: `${error} (${message}), and restoring the originals failed too (${e.message})`, rolledBack: false, backup: backupRel, hint: `the originals are in ${backupRel} \u2014 copy dev/index.ts, config.ts and tier5-src/* back by hand`, ...base(validate4) }
|
|
40336
|
+
};
|
|
40337
|
+
}
|
|
40338
|
+
dropBackup();
|
|
40339
|
+
return { code: 1, result: { ok: false, error: `${error} (${message}); every file was restored`, rolledBack: true, ...base(validate4) } };
|
|
40340
|
+
};
|
|
40341
|
+
try {
|
|
40342
|
+
mkdirSync18(join36(backup, "dev"), { recursive: true });
|
|
40343
|
+
for (const [path2, rel] of originals) cpSync(path2, join36(backup, rel));
|
|
40344
|
+
if (plan.removedWorkers.length) mkdirSync18(join36(backup, "tier5-src"), { recursive: true });
|
|
40345
|
+
} catch (e) {
|
|
40346
|
+
dropBackup();
|
|
40347
|
+
return { code: 1, result: { ok: false, error: `could not back up the app before trimming it (${e.message}); nothing was changed`, rolledBack: true, ...base() } };
|
|
40348
|
+
}
|
|
40349
|
+
try {
|
|
40350
|
+
const moveDir = deps.moveDir ?? renameSync3;
|
|
40351
|
+
for (const name of plan.removedWorkers) {
|
|
40352
|
+
moveDir(join36(dir, "tier5-src", name), join36(backup, "tier5-src", name));
|
|
40353
|
+
moved.push(name);
|
|
40354
|
+
}
|
|
40355
|
+
if (plan.dev !== dev) writeFileSync14(devPath, plan.dev);
|
|
40356
|
+
if (plan.config !== config) writeFileSync14(configPath, plan.config);
|
|
40357
|
+
} catch (e) {
|
|
40358
|
+
return abort("the trim failed while writing", e);
|
|
40359
|
+
}
|
|
40360
|
+
let failure;
|
|
40361
|
+
let validate3;
|
|
40362
|
+
try {
|
|
40363
|
+
const written = parseApp(readFileSync43(devPath, "utf8"), readFileSync43(configPath, "utf8"));
|
|
40364
|
+
const leftovers = leftoverNavRefs(written.nav.value, plan.removedIds);
|
|
40365
|
+
if (leftovers.length) failure = { error: "navigation still names screens this trim removed", leftovers };
|
|
40366
|
+
else {
|
|
40367
|
+
validate3 = await deps.validate(dir);
|
|
40368
|
+
if (validate3.code !== 0) failure = { error: "himi validate --strict failed on the trimmed app" };
|
|
40369
|
+
}
|
|
40370
|
+
} catch (e) {
|
|
40371
|
+
return abort("the trim could not be checked", e, validate3);
|
|
40372
|
+
}
|
|
40373
|
+
if (!failure) {
|
|
40374
|
+
dropBackup();
|
|
40375
|
+
return { code: 0, result: { ok: true, ...base(validate3) } };
|
|
40376
|
+
}
|
|
40377
|
+
if (req.force) {
|
|
40378
|
+
return {
|
|
40379
|
+
code: 1,
|
|
40380
|
+
result: { ok: false, ...failure, rolledBack: false, backup: backupRel, hint: `--force kept the trimmed tree; the originals are in ${backupRel}`, ...base(validate3) }
|
|
40381
|
+
};
|
|
40382
|
+
}
|
|
40383
|
+
try {
|
|
40384
|
+
restore();
|
|
40385
|
+
} catch (e) {
|
|
40386
|
+
return abort(String(failure.error), e, validate3);
|
|
40387
|
+
}
|
|
40388
|
+
dropBackup();
|
|
40389
|
+
return {
|
|
40390
|
+
code: 1,
|
|
40391
|
+
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) }
|
|
40392
|
+
};
|
|
40393
|
+
}
|
|
40394
|
+
var TrimRefusal, LIT, ATOM, QUANT, CAP, SAFE_ROUTE_PATTERN, lineOf, isStatic, entryLabel, isNode3, asItems, NAV_SCREEN_KEYS, sorted, refuse3;
|
|
40395
|
+
var init_template_trim = __esm({
|
|
40396
|
+
"src/template-trim.ts"() {
|
|
40397
|
+
init_validate_descriptor();
|
|
40398
|
+
init_scaffold();
|
|
40399
|
+
init_home_descriptor();
|
|
40400
|
+
TrimRefusal = class extends Error {
|
|
40401
|
+
detail;
|
|
40402
|
+
constructor(message, detail = {}) {
|
|
40403
|
+
super(message);
|
|
40404
|
+
this.detail = detail;
|
|
40405
|
+
}
|
|
40406
|
+
};
|
|
40407
|
+
LIT = String.raw`(?:[A-Za-z0-9_/.:-]|\\[./_:-])*`;
|
|
40408
|
+
ATOM = String.raw`(?:\[(?:[^\]\\[]|\\.)+\]|\\[dw]|\.)`;
|
|
40409
|
+
QUANT = String.raw`(?:[+*]|\{\d+(?:,\d*)?\})`;
|
|
40410
|
+
CAP = String.raw`\(${ATOM}${QUANT}\)`;
|
|
40411
|
+
SAFE_ROUTE_PATTERN = new RegExp(
|
|
40412
|
+
String.raw`^\^${LIT}(?:${CAP}${LIT}|\(\?:(?:${LIT}|\[(?:[^\]\\[]|\\.)+\])${CAP}\)\?)?\$$`
|
|
40413
|
+
);
|
|
40414
|
+
lineOf = (src, at) => src.slice(0, at).split("\n").length;
|
|
40415
|
+
isStatic = (id) => typeof id === "string" && id !== "" && !id.startsWith("$");
|
|
40416
|
+
entryLabel = (entry) => {
|
|
40417
|
+
const id = entry?.id;
|
|
40418
|
+
return typeof id === "string" && id ? id : "(unnamed)";
|
|
40419
|
+
};
|
|
40420
|
+
isNode3 = (v) => !!v && typeof v === "object" && !!v.body && typeof v.body === "object";
|
|
40421
|
+
asItems = (block) => {
|
|
40422
|
+
const items = block?.items;
|
|
40423
|
+
return Array.isArray(items) ? items : void 0;
|
|
40424
|
+
};
|
|
40425
|
+
NAV_SCREEN_KEYS = /* @__PURE__ */ new Set(["screenId", "parentScreenId", "contentScreenId", "badgeScreenId"]);
|
|
40426
|
+
sorted = (xs) => [...new Set(xs)].sort();
|
|
40427
|
+
refuse3 = (e) => ({ code: 2, result: { ok: false, error: e.message, ...e.detail } });
|
|
40428
|
+
}
|
|
40429
|
+
});
|
|
40430
|
+
|
|
39149
40431
|
// src/nav-lint.ts
|
|
39150
40432
|
var nav_lint_exports = {};
|
|
39151
40433
|
__export(nav_lint_exports, {
|
|
@@ -39439,7 +40721,7 @@ function packagePathFor(pathname) {
|
|
|
39439
40721
|
}
|
|
39440
40722
|
return UNSUPPORTED;
|
|
39441
40723
|
}
|
|
39442
|
-
function
|
|
40724
|
+
function parseJson2(read, path2, errors) {
|
|
39443
40725
|
const bytes2 = read(path2);
|
|
39444
40726
|
if (!bytes2) return null;
|
|
39445
40727
|
try {
|
|
@@ -39452,7 +40734,7 @@ function parseJson(read, path2, errors) {
|
|
|
39452
40734
|
function validatePackage(read, opts = {}) {
|
|
39453
40735
|
const errors = [];
|
|
39454
40736
|
const warnings = [];
|
|
39455
|
-
const header =
|
|
40737
|
+
const header = parseJson2(read, HIMI_PACKAGE_HEADER_PATH, errors);
|
|
39456
40738
|
if (!header && opts.requireHeader) {
|
|
39457
40739
|
errors.push(`${HIMI_PACKAGE_HEADER_PATH} is missing \u2014 not a .himi package`);
|
|
39458
40740
|
}
|
|
@@ -39480,7 +40762,7 @@ function validatePackage(read, opts = {}) {
|
|
|
39480
40762
|
errors.push(`${HIMI_PACKAGE_SOURCE_PATH} is present in a package whose header declares no source`);
|
|
39481
40763
|
}
|
|
39482
40764
|
}
|
|
39483
|
-
const manifest =
|
|
40765
|
+
const manifest = parseJson2(read, HIMI_PACKAGE_MANIFEST_PATH, errors);
|
|
39484
40766
|
if (!manifest) {
|
|
39485
40767
|
if (!errors.some((e) => e.startsWith(HIMI_PACKAGE_MANIFEST_PATH))) {
|
|
39486
40768
|
errors.push(`${HIMI_PACKAGE_MANIFEST_PATH} is missing`);
|
|
@@ -39772,13 +41054,13 @@ __export(pack_exports, {
|
|
|
39772
41054
|
});
|
|
39773
41055
|
import { createHash as createHash19 } from "node:crypto";
|
|
39774
41056
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
39775
|
-
import { existsSync as
|
|
39776
|
-
import { dirname as
|
|
41057
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync19, readFileSync as readFileSync44, readdirSync as readdirSync21, rmSync as rmSync7, statSync as statSync9, writeFileSync as writeFileSync15 } from "node:fs";
|
|
41058
|
+
import { dirname as dirname24, join as join37, resolve as resolve35 } from "node:path";
|
|
39777
41059
|
function writeZip(entries) {
|
|
39778
|
-
const
|
|
39779
|
-
const total =
|
|
41060
|
+
const sorted2 = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
41061
|
+
const total = sorted2.reduce((n, e) => n + e.bytes.length, 0);
|
|
39780
41062
|
if (total > ZIP32_MAX) {
|
|
39781
|
-
const biggest =
|
|
41063
|
+
const biggest = sorted2.reduce((a, b) => a.bytes.length >= b.bytes.length ? a : b);
|
|
39782
41064
|
throw new Error(
|
|
39783
41065
|
`package content is ${(total / 1e9).toFixed(1)} GB, over the 4 GB limit of the package format (no zip64 support); the largest entry is ${biggest.path} at ${(biggest.bytes.length / 1e9).toFixed(1)} GB`
|
|
39784
41066
|
);
|
|
@@ -39786,7 +41068,7 @@ function writeZip(entries) {
|
|
|
39786
41068
|
const locals = [];
|
|
39787
41069
|
const centrals = [];
|
|
39788
41070
|
let offset = 0;
|
|
39789
|
-
for (const entry of
|
|
41071
|
+
for (const entry of sorted2) {
|
|
39790
41072
|
if (!isSafeEntryName(entry.path)) throw new Error(`unsafe package entry name: ${JSON.stringify(entry.path)}`);
|
|
39791
41073
|
const name = Buffer.from(entry.path, "utf8");
|
|
39792
41074
|
const crc = zipCrc32(entry.bytes);
|
|
@@ -39833,8 +41115,8 @@ function writeZip(entries) {
|
|
|
39833
41115
|
eocd.writeUInt32LE(EOCD_SIG, 0);
|
|
39834
41116
|
eocd.writeUInt16LE(0, 4);
|
|
39835
41117
|
eocd.writeUInt16LE(0, 6);
|
|
39836
|
-
eocd.writeUInt16LE(
|
|
39837
|
-
eocd.writeUInt16LE(
|
|
41118
|
+
eocd.writeUInt16LE(sorted2.length, 8);
|
|
41119
|
+
eocd.writeUInt16LE(sorted2.length, 10);
|
|
39838
41120
|
eocd.writeUInt32LE(centralBuf.length, 12);
|
|
39839
41121
|
eocd.writeUInt32LE(offset, 16);
|
|
39840
41122
|
eocd.writeUInt16LE(0, 20);
|
|
@@ -39867,13 +41149,13 @@ function inflateEntry(buf, entry) {
|
|
|
39867
41149
|
return bytes2;
|
|
39868
41150
|
}
|
|
39869
41151
|
function readIf(path2) {
|
|
39870
|
-
return
|
|
41152
|
+
return existsSync40(path2) && statSync9(path2).isFile() ? readFileSync44(path2) : null;
|
|
39871
41153
|
}
|
|
39872
41154
|
function listDir(dir) {
|
|
39873
|
-
return
|
|
41155
|
+
return existsSync40(dir) ? readdirSync21(dir).filter((f) => statSync9(join37(dir, f)).isFile()) : [];
|
|
39874
41156
|
}
|
|
39875
41157
|
function gatherReleaseEntries(appDir2) {
|
|
39876
|
-
const manifestPath =
|
|
41158
|
+
const manifestPath = join37(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
|
|
39877
41159
|
const manifestBytes = readIf(manifestPath);
|
|
39878
41160
|
if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir2} \u2014 build a release there first`);
|
|
39879
41161
|
const manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
@@ -39897,7 +41179,7 @@ function gatherReleaseEntries(appDir2) {
|
|
|
39897
41179
|
}
|
|
39898
41180
|
const missing = [];
|
|
39899
41181
|
for (const rel of wanted) {
|
|
39900
|
-
const bytes2 = readIf(
|
|
41182
|
+
const bytes2 = readIf(join37(appDir2, rel));
|
|
39901
41183
|
if (bytes2) entries.push({ path: rel, bytes: bytes2 });
|
|
39902
41184
|
else missing.push(rel);
|
|
39903
41185
|
}
|
|
@@ -39908,12 +41190,12 @@ function gatherReleaseEntries(appDir2) {
|
|
|
39908
41190
|
);
|
|
39909
41191
|
}
|
|
39910
41192
|
for (const name of SINGLETONS) {
|
|
39911
|
-
const bytes2 = readIf(
|
|
41193
|
+
const bytes2 = readIf(join37(appDir2, name));
|
|
39912
41194
|
if (bytes2) entries.push({ path: name, bytes: bytes2 });
|
|
39913
41195
|
}
|
|
39914
41196
|
const skipped = [];
|
|
39915
41197
|
for (const sub of ["screens", "bundles", "assets", "widgets"]) {
|
|
39916
|
-
for (const f of listDir(
|
|
41198
|
+
for (const f of listDir(join37(appDir2, sub))) {
|
|
39917
41199
|
if (!wanted.has(`${sub}/${f}`)) skipped.push(`${sub}/${f}`);
|
|
39918
41200
|
}
|
|
39919
41201
|
}
|
|
@@ -39946,18 +41228,18 @@ function buildEntries(appDir2, app, opts) {
|
|
|
39946
41228
|
return { all, header, manifest, skipped };
|
|
39947
41229
|
}
|
|
39948
41230
|
function packRelease(releaseRoot, app, out, opts = {}) {
|
|
39949
|
-
const appDir2 =
|
|
41231
|
+
const appDir2 = join37(resolve35(releaseRoot), app);
|
|
39950
41232
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
39951
41233
|
const buf = writeZip(all);
|
|
39952
|
-
const isDir =
|
|
39953
|
-
const outFile = isDir ?
|
|
39954
|
-
|
|
39955
|
-
|
|
41234
|
+
const isDir = existsSync40(out) && statSync9(out).isDirectory();
|
|
41235
|
+
const outFile = isDir ? join37(resolve35(out), packageFileName(app, header.releaseId)) : resolve35(out);
|
|
41236
|
+
mkdirSync19(dirname24(outFile), { recursive: true });
|
|
41237
|
+
writeFileSync15(outFile, buf);
|
|
39956
41238
|
return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
|
|
39957
41239
|
}
|
|
39958
41240
|
function resolvePackageDirDest(outDir, app, releaseId) {
|
|
39959
41241
|
const packagedApp = (dir) => {
|
|
39960
|
-
const bytes2 = readIf(
|
|
41242
|
+
const bytes2 = readIf(join37(dir, HIMI_PACKAGE_HEADER_PATH));
|
|
39961
41243
|
if (!bytes2) return void 0;
|
|
39962
41244
|
try {
|
|
39963
41245
|
return JSON.parse(bytes2.toString("utf8")).app;
|
|
@@ -39966,15 +41248,15 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
39966
41248
|
}
|
|
39967
41249
|
};
|
|
39968
41250
|
const replaceable = (dir) => {
|
|
39969
|
-
if (!
|
|
39970
|
-
if (!
|
|
39971
|
-
return
|
|
41251
|
+
if (!existsSync40(dir)) return true;
|
|
41252
|
+
if (!statSync9(dir).isDirectory()) return false;
|
|
41253
|
+
return readdirSync21(dir).length === 0 || packagedApp(dir) === app;
|
|
39972
41254
|
};
|
|
39973
|
-
if (
|
|
41255
|
+
if (existsSync40(outDir) && !statSync9(outDir).isDirectory()) {
|
|
39974
41256
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
39975
41257
|
}
|
|
39976
41258
|
if (replaceable(outDir)) return outDir;
|
|
39977
|
-
const child =
|
|
41259
|
+
const child = join37(outDir, packageDirName(app, releaseId));
|
|
39978
41260
|
if (!replaceable(child)) {
|
|
39979
41261
|
throw new Error(
|
|
39980
41262
|
`refusing to replace ${child}: it is not empty and is not a ${app} package (no ${HIMI_PACKAGE_HEADER_PATH}). Pass --out to a new or empty directory.`
|
|
@@ -39988,15 +41270,15 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
|
39988
41270
|
"a package carrying the app's source has no --format dir form: readers that predate the source entry drop it before hashing a directory and refuse the package as tampered. Pack it as a .himi archive."
|
|
39989
41271
|
);
|
|
39990
41272
|
}
|
|
39991
|
-
const appDir2 =
|
|
41273
|
+
const appDir2 = join37(resolve35(releaseRoot), app);
|
|
39992
41274
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
39993
41275
|
const dest = resolvePackageDirDest(resolve35(outDir), app, header.releaseId);
|
|
39994
|
-
|
|
41276
|
+
rmSync7(dest, { recursive: true, force: true });
|
|
39995
41277
|
let bytes2 = 0;
|
|
39996
41278
|
for (const entry of all) {
|
|
39997
|
-
const target =
|
|
39998
|
-
|
|
39999
|
-
|
|
41279
|
+
const target = join37(dest, entry.path);
|
|
41280
|
+
mkdirSync19(dirname24(target), { recursive: true });
|
|
41281
|
+
writeFileSync15(target, entry.bytes);
|
|
40000
41282
|
bytes2 += entry.bytes.length;
|
|
40001
41283
|
}
|
|
40002
41284
|
return { app, releaseId: header.releaseId, header, out: dest, bytes: bytes2, entryCount: all.length, skipped };
|
|
@@ -40017,21 +41299,21 @@ function openPackageBuffer(buf) {
|
|
|
40017
41299
|
return openFromEntries(readZip(buf), { requireHeader: true });
|
|
40018
41300
|
}
|
|
40019
41301
|
function openPackageFile(file) {
|
|
40020
|
-
return openPackageBuffer(
|
|
41302
|
+
return openPackageBuffer(readFileSync44(file));
|
|
40021
41303
|
}
|
|
40022
41304
|
function openPackageDir(dir) {
|
|
40023
41305
|
const root = resolve35(dir);
|
|
40024
41306
|
const entries = /* @__PURE__ */ new Map();
|
|
40025
41307
|
const walk2 = (rel) => {
|
|
40026
|
-
const abs = rel ?
|
|
40027
|
-
for (const name of
|
|
41308
|
+
const abs = rel ? join37(root, rel) : root;
|
|
41309
|
+
for (const name of readdirSync21(abs)) {
|
|
40028
41310
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
40029
|
-
const childAbs =
|
|
40030
|
-
if (
|
|
40031
|
-
else if (isSafeEntryName(childRel)) entries.set(childRel,
|
|
41311
|
+
const childAbs = join37(abs, name);
|
|
41312
|
+
if (statSync9(childAbs).isDirectory()) walk2(childRel);
|
|
41313
|
+
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync44(childAbs));
|
|
40032
41314
|
}
|
|
40033
41315
|
};
|
|
40034
|
-
if (!
|
|
41316
|
+
if (!existsSync40(root)) throw new Error(`no such package directory: ${root}`);
|
|
40035
41317
|
walk2("");
|
|
40036
41318
|
const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
|
|
40037
41319
|
if (manifestBytes) {
|
|
@@ -40073,12 +41355,12 @@ function unpackTo(buf, dest, appFallback) {
|
|
|
40073
41355
|
if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
|
|
40074
41356
|
if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
|
|
40075
41357
|
const root = resolve35(dest);
|
|
40076
|
-
const appDir2 =
|
|
40077
|
-
|
|
41358
|
+
const appDir2 = join37(root, app);
|
|
41359
|
+
rmSync7(appDir2, { recursive: true, force: true });
|
|
40078
41360
|
for (const [rel, bytes2] of entries) {
|
|
40079
|
-
const target =
|
|
40080
|
-
|
|
40081
|
-
|
|
41361
|
+
const target = join37(appDir2, rel);
|
|
41362
|
+
mkdirSync19(dirname24(target), { recursive: true });
|
|
41363
|
+
writeFileSync15(target, bytes2);
|
|
40082
41364
|
}
|
|
40083
41365
|
return { root, appDir: appDir2, app };
|
|
40084
41366
|
}
|
|
@@ -40112,20 +41394,20 @@ __export(app_source_exports, {
|
|
|
40112
41394
|
writeConflicts: () => writeConflicts,
|
|
40113
41395
|
zipAppSource: () => zipAppSource
|
|
40114
41396
|
});
|
|
40115
|
-
import { readdirSync as
|
|
40116
|
-
import { join as
|
|
41397
|
+
import { readdirSync as readdirSync22, lstatSync as lstatSync5, readFileSync as readFileSync45, mkdirSync as mkdirSync20, writeFileSync as writeFileSync16, existsSync as existsSync41, rmSync as rmSync8, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
41398
|
+
import { join as join38, resolve as resolve36, sep as sep8 } from "node:path";
|
|
40117
41399
|
import { deflateRawSync as deflateRawSync2 } from "node:zlib";
|
|
40118
41400
|
function walkSourceTree(dir, file, skip) {
|
|
40119
41401
|
const walk2 = (relDir) => {
|
|
40120
|
-
for (const name of
|
|
40121
|
-
const rel = relDir ?
|
|
40122
|
-
const st = lstatSync5(
|
|
41402
|
+
for (const name of readdirSync22(join38(dir, relDir))) {
|
|
41403
|
+
const rel = relDir ? join38(relDir, name) : name;
|
|
41404
|
+
const st = lstatSync5(join38(dir, rel));
|
|
40123
41405
|
if (st.isSymbolicLink()) {
|
|
40124
41406
|
skip(rel);
|
|
40125
41407
|
continue;
|
|
40126
41408
|
}
|
|
40127
41409
|
if (st.isDirectory()) {
|
|
40128
|
-
if (isDeniedSourceDir(name, relDir) ||
|
|
41410
|
+
if (isDeniedSourceDir(name, relDir) || existsSync41(join38(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
|
|
40129
41411
|
else walk2(rel);
|
|
40130
41412
|
continue;
|
|
40131
41413
|
}
|
|
@@ -40143,7 +41425,7 @@ function collectAppSource(dir) {
|
|
|
40143
41425
|
const skipped = [];
|
|
40144
41426
|
walkSourceTree(
|
|
40145
41427
|
dir,
|
|
40146
|
-
(archivePath, hostRel) => entries.push({ path: archivePath, bytes:
|
|
41428
|
+
(archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync45(join38(dir, hostRel)) }),
|
|
40147
41429
|
(hostRel) => skipped.push(hostRel)
|
|
40148
41430
|
);
|
|
40149
41431
|
entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
@@ -40190,28 +41472,28 @@ function writeAppSource(entries, destDir) {
|
|
|
40190
41472
|
`refusing to restore into ${root}: the destination itself is a symlink, so every file would be written outside it. Remove it, or pass --out/--name somewhere else.`
|
|
40191
41473
|
);
|
|
40192
41474
|
}
|
|
40193
|
-
|
|
41475
|
+
mkdirSync20(root, { recursive: true });
|
|
40194
41476
|
const written = [];
|
|
40195
41477
|
for (const entry of entries) {
|
|
40196
41478
|
if (isDeniedSourcePath(entry.path)) continue;
|
|
40197
41479
|
const segments = entry.path.split("/");
|
|
40198
41480
|
let dir = root;
|
|
40199
41481
|
for (const segment of segments.slice(0, -1)) {
|
|
40200
|
-
dir =
|
|
41482
|
+
dir = join38(dir, segment);
|
|
40201
41483
|
const kind = pathKind(dir);
|
|
40202
41484
|
if (kind?.isSymbolicLink()) unlinkSync3(dir);
|
|
40203
41485
|
else if (kind) continue;
|
|
40204
|
-
|
|
41486
|
+
mkdirSync20(dir);
|
|
40205
41487
|
}
|
|
40206
|
-
const target =
|
|
41488
|
+
const target = join38(root, ...segments);
|
|
40207
41489
|
if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
|
|
40208
|
-
|
|
41490
|
+
writeFileSync16(target, entry.bytes);
|
|
40209
41491
|
written.push(entry.path);
|
|
40210
41492
|
}
|
|
40211
41493
|
return written;
|
|
40212
41494
|
}
|
|
40213
41495
|
function staleSourcePaths(entries, destDir) {
|
|
40214
|
-
if (!
|
|
41496
|
+
if (!existsSync41(destDir)) return [];
|
|
40215
41497
|
const archived = new Set(entries.map((e) => e.path));
|
|
40216
41498
|
const stale = [];
|
|
40217
41499
|
walkSourceTree(destDir, (archivePath) => {
|
|
@@ -40238,7 +41520,7 @@ function writeConflicts(entries, destDir) {
|
|
|
40238
41520
|
let dir = root;
|
|
40239
41521
|
let stop = false;
|
|
40240
41522
|
for (const [i, segment] of segments.slice(0, -1).entries()) {
|
|
40241
|
-
dir =
|
|
41523
|
+
dir = join38(dir, segment);
|
|
40242
41524
|
const kind2 = pathKind(dir);
|
|
40243
41525
|
if (!kind2 || kind2.isSymbolicLink()) {
|
|
40244
41526
|
stop = true;
|
|
@@ -40250,7 +41532,7 @@ function writeConflicts(entries, destDir) {
|
|
|
40250
41532
|
break;
|
|
40251
41533
|
}
|
|
40252
41534
|
if (stop) continue;
|
|
40253
|
-
const kind = pathKind(
|
|
41535
|
+
const kind = pathKind(join38(root, ...segments));
|
|
40254
41536
|
if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
|
|
40255
41537
|
say(entry.path, "is a directory here, but the release has a file at that path");
|
|
40256
41538
|
}
|
|
@@ -40260,22 +41542,22 @@ function writeConflicts(entries, destDir) {
|
|
|
40260
41542
|
function removeStaleSource(entries, destDir) {
|
|
40261
41543
|
const root = resolve36(destDir);
|
|
40262
41544
|
const removed = staleSourcePaths(entries, root);
|
|
40263
|
-
for (const rel of removed)
|
|
41545
|
+
for (const rel of removed) rmSync8(join38(root, ...rel.split("/")), { force: true });
|
|
40264
41546
|
const needed = /* @__PURE__ */ new Set();
|
|
40265
41547
|
for (const entry of entries) {
|
|
40266
41548
|
if (isDeniedSourcePath(entry.path)) continue;
|
|
40267
41549
|
const segments = entry.path.split("/");
|
|
40268
41550
|
for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
|
|
40269
41551
|
}
|
|
40270
|
-
if (
|
|
41552
|
+
if (existsSync41(root)) pruneEmptyDirs(root, "", needed, removed);
|
|
40271
41553
|
return removed.sort();
|
|
40272
41554
|
}
|
|
40273
41555
|
function pruneEmptyDirs(root, rel, needed, removed) {
|
|
40274
41556
|
let empty = true;
|
|
40275
|
-
for (const name of
|
|
40276
|
-
const childRel = rel ?
|
|
41557
|
+
for (const name of readdirSync22(rel ? join38(root, rel) : root)) {
|
|
41558
|
+
const childRel = rel ? join38(rel, name) : name;
|
|
40277
41559
|
const posix3 = childRel.split(sep8).join("/");
|
|
40278
|
-
const kind = lstatSync5(
|
|
41560
|
+
const kind = lstatSync5(join38(root, childRel));
|
|
40279
41561
|
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name, rel)) {
|
|
40280
41562
|
empty = false;
|
|
40281
41563
|
continue;
|
|
@@ -40285,7 +41567,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
40285
41567
|
empty = false;
|
|
40286
41568
|
continue;
|
|
40287
41569
|
}
|
|
40288
|
-
rmdirSync(
|
|
41570
|
+
rmdirSync(join38(root, childRel));
|
|
40289
41571
|
removed.push(`${posix3}/`);
|
|
40290
41572
|
}
|
|
40291
41573
|
return empty;
|
|
@@ -40340,13 +41622,13 @@ __export(eject_exports, {
|
|
|
40340
41622
|
EJECTABLE: () => EJECTABLE,
|
|
40341
41623
|
ejectModule: () => ejectModule
|
|
40342
41624
|
});
|
|
40343
|
-
import { existsSync as
|
|
40344
|
-
import { dirname as
|
|
41625
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync46, writeFileSync as writeFileSync17 } from "node:fs";
|
|
41626
|
+
import { dirname as dirname25, join as join39, relative as relative5, resolve as resolve37, sep as sep9 } from "node:path";
|
|
40345
41627
|
function locate(repoRootOrCwd, mod) {
|
|
40346
41628
|
const inRepo = resolve37(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
40347
|
-
if (
|
|
41629
|
+
if (existsSync42(inRepo)) return { path: inRepo, form: "source" };
|
|
40348
41630
|
const dist = resolve37(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
|
|
40349
|
-
if (
|
|
41631
|
+
if (existsSync42(dist)) return { path: dist, form: "bundle" };
|
|
40350
41632
|
return null;
|
|
40351
41633
|
}
|
|
40352
41634
|
function specifiersFor(mod) {
|
|
@@ -40370,8 +41652,8 @@ function ejectModule(opts) {
|
|
|
40370
41652
|
};
|
|
40371
41653
|
}
|
|
40372
41654
|
const ext = found.form === "source" ? "ts" : "mjs";
|
|
40373
|
-
const target =
|
|
40374
|
-
|
|
41655
|
+
const target = join39(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
|
|
41656
|
+
mkdirSync21(dirname25(target), { recursive: true });
|
|
40375
41657
|
const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
|
|
40376
41658
|
//
|
|
40377
41659
|
// Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
|
|
@@ -40384,17 +41666,17 @@ function ejectModule(opts) {
|
|
|
40384
41666
|
// gate still applies. Ejecting buys layout and flow, never the floor.
|
|
40385
41667
|
|
|
40386
41668
|
`;
|
|
40387
|
-
const normalized =
|
|
41669
|
+
const normalized = readFileSync46(found.path, "utf8").replace(
|
|
40388
41670
|
/(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
|
|
40389
41671
|
(_m, q, sub) => `${q}@wix/himalaya/${sub}${q}`
|
|
40390
41672
|
);
|
|
40391
|
-
|
|
41673
|
+
writeFileSync17(target, banner + normalized);
|
|
40392
41674
|
const rewired = [];
|
|
40393
41675
|
for (const f of files) {
|
|
40394
|
-
if (!
|
|
40395
|
-
const before =
|
|
41676
|
+
if (!existsSync42(f)) continue;
|
|
41677
|
+
const before = readFileSync46(f, "utf8");
|
|
40396
41678
|
let after = before;
|
|
40397
|
-
let rel = relative5(
|
|
41679
|
+
let rel = relative5(dirname25(f), target).split(sep9).join("/").replace(/\.tsx?$/, ".js");
|
|
40398
41680
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
40399
41681
|
for (const spec of specifiersFor(mod)) {
|
|
40400
41682
|
const q = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -40404,7 +41686,7 @@ function ejectModule(opts) {
|
|
|
40404
41686
|
);
|
|
40405
41687
|
}
|
|
40406
41688
|
if (after !== before) {
|
|
40407
|
-
|
|
41689
|
+
writeFileSync17(f, after);
|
|
40408
41690
|
rewired.push(f);
|
|
40409
41691
|
}
|
|
40410
41692
|
}
|
|
@@ -40440,14 +41722,14 @@ __export(test_exports, {
|
|
|
40440
41722
|
scopeDescriptors: () => scopeDescriptors,
|
|
40441
41723
|
writeRecordedMocks: () => writeRecordedMocks
|
|
40442
41724
|
});
|
|
40443
|
-
import { existsSync as
|
|
40444
|
-
import { join as
|
|
41725
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync22, readFileSync as readFileSync47, writeFileSync as writeFileSync18 } from "node:fs";
|
|
41726
|
+
import { join as join40, resolve as resolve38 } from "node:path";
|
|
40445
41727
|
function readTestConfig(dir) {
|
|
40446
41728
|
const p = resolve38(dir, TEST_CONFIG_FILE);
|
|
40447
|
-
if (!
|
|
41729
|
+
if (!existsSync43(p)) return {};
|
|
40448
41730
|
let parsed;
|
|
40449
41731
|
try {
|
|
40450
|
-
parsed = JSON.parse(
|
|
41732
|
+
parsed = JSON.parse(readFileSync47(p, "utf8"));
|
|
40451
41733
|
} catch (e) {
|
|
40452
41734
|
throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e.message}`);
|
|
40453
41735
|
}
|
|
@@ -40490,7 +41772,7 @@ function readTestConfig(dir) {
|
|
|
40490
41772
|
function readNetRules(path2) {
|
|
40491
41773
|
let parsed;
|
|
40492
41774
|
try {
|
|
40493
|
-
parsed = JSON.parse(
|
|
41775
|
+
parsed = JSON.parse(readFileSync47(path2, "utf8"));
|
|
40494
41776
|
} catch (e) {
|
|
40495
41777
|
throw new Error(`--net ${path2} could not be read as JSON \u2014 ${e.message}`);
|
|
40496
41778
|
}
|
|
@@ -40511,7 +41793,7 @@ function readNetRules(path2) {
|
|
|
40511
41793
|
function defaultNetRules(dir) {
|
|
40512
41794
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
40513
41795
|
const p = resolve38(dir, rel);
|
|
40514
|
-
if (
|
|
41796
|
+
if (existsSync43(p)) {
|
|
40515
41797
|
const rules = readNetRules(p);
|
|
40516
41798
|
if (rules.length) return { rules, from: rel };
|
|
40517
41799
|
}
|
|
@@ -40527,7 +41809,7 @@ function readCannedResponses() {
|
|
|
40527
41809
|
];
|
|
40528
41810
|
for (const url of candidates) {
|
|
40529
41811
|
try {
|
|
40530
|
-
const parsed = JSON.parse(
|
|
41812
|
+
const parsed = JSON.parse(readFileSync47(url, "utf8"));
|
|
40531
41813
|
const byKey = {};
|
|
40532
41814
|
for (const [k, v] of Object.entries(parsed)) {
|
|
40533
41815
|
if (!k.startsWith("//")) byKey[k] = v;
|
|
@@ -40616,11 +41898,11 @@ function writeRecordedMocks(opts) {
|
|
|
40616
41898
|
};
|
|
40617
41899
|
}
|
|
40618
41900
|
const fs = opts.io ?? {
|
|
40619
|
-
mkdir: (p) =>
|
|
40620
|
-
write: (p, s) =>
|
|
41901
|
+
mkdir: (p) => mkdirSync22(p, { recursive: true }),
|
|
41902
|
+
write: (p, s) => writeFileSync18(p, s)
|
|
40621
41903
|
};
|
|
40622
|
-
fs.mkdir(
|
|
40623
|
-
fs.write(
|
|
41904
|
+
fs.mkdir(join40(opts.dir, "dev"));
|
|
41905
|
+
fs.write(join40(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
40624
41906
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
40625
41907
|
}
|
|
40626
41908
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -41077,14 +42359,14 @@ var mobile_ux_lint_exports = {};
|
|
|
41077
42359
|
__export(mobile_ux_lint_exports, {
|
|
41078
42360
|
mobileUxIssues: () => mobileUxIssues
|
|
41079
42361
|
});
|
|
41080
|
-
import { existsSync as
|
|
41081
|
-
import { join as
|
|
42362
|
+
import { existsSync as existsSync44, readFileSync as readFileSync48 } from "node:fs";
|
|
42363
|
+
import { join as join41 } from "node:path";
|
|
41082
42364
|
function mobileUxIssues(dir, strict) {
|
|
41083
|
-
const file =
|
|
41084
|
-
if (!
|
|
42365
|
+
const file = join41(dir, "MOBILE-UX.md");
|
|
42366
|
+
if (!existsSync44(file)) return [];
|
|
41085
42367
|
let text4;
|
|
41086
42368
|
try {
|
|
41087
|
-
text4 =
|
|
42369
|
+
text4 = readFileSync48(file, "utf8");
|
|
41088
42370
|
} catch {
|
|
41089
42371
|
return [];
|
|
41090
42372
|
}
|
|
@@ -42759,8 +44041,8 @@ __export(functions_exports, {
|
|
|
42759
44041
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
42760
44042
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
42761
44043
|
});
|
|
42762
|
-
import { readFileSync as
|
|
42763
|
-
import { join as
|
|
44044
|
+
import { readFileSync as readFileSync49, existsSync as existsSync45 } from "node:fs";
|
|
44045
|
+
import { join as join42, resolve as resolve39 } from "node:path";
|
|
42764
44046
|
function resolveFunctionsTarget(input) {
|
|
42765
44047
|
const explicitUrl = input.functionsUrl?.trim();
|
|
42766
44048
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -42779,9 +44061,9 @@ async function loadFunctionsApp(dir) {
|
|
|
42779
44061
|
}
|
|
42780
44062
|
const sources = {};
|
|
42781
44063
|
for (const definition of config.functions.functions) {
|
|
42782
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
44064
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join42(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync45);
|
|
42783
44065
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
42784
|
-
sources[definition.name] =
|
|
44066
|
+
sources[definition.name] = readFileSync49(source, "utf8");
|
|
42785
44067
|
}
|
|
42786
44068
|
const data = config.cms || config.data ? mergeDataResources(config) : void 0;
|
|
42787
44069
|
const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
|
|
@@ -42936,9 +44218,9 @@ __export(native_decode_exports, {
|
|
|
42936
44218
|
runNativeDecode: () => runNativeDecode
|
|
42937
44219
|
});
|
|
42938
44220
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
42939
|
-
import { existsSync as
|
|
44221
|
+
import { existsSync as existsSync46, mkdtempSync as mkdtempSync2, readFileSync as readFileSync50, rmSync as rmSync9, writeFileSync as writeFileSync19 } from "node:fs";
|
|
42940
44222
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
42941
|
-
import { join as
|
|
44223
|
+
import { join as join43 } from "node:path";
|
|
42942
44224
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
42943
44225
|
function nativeDecodePackageDir() {
|
|
42944
44226
|
return fileURLToPath20(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -42948,8 +44230,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
42948
44230
|
}
|
|
42949
44231
|
function nativeOracleShipped() {
|
|
42950
44232
|
return {
|
|
42951
|
-
ios:
|
|
42952
|
-
android:
|
|
44233
|
+
ios: existsSync46(join43(nativeDecodePackageDir(), "Package.swift")),
|
|
44234
|
+
android: existsSync46(join43(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
42953
44235
|
};
|
|
42954
44236
|
}
|
|
42955
44237
|
function detectNativeDecode(options = {}) {
|
|
@@ -42960,7 +44242,7 @@ function detectNativeDecode(options = {}) {
|
|
|
42960
44242
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
42961
44243
|
}
|
|
42962
44244
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
42963
|
-
const packageAvailable = options.packageAvailable ??
|
|
44245
|
+
const packageAvailable = options.packageAvailable ?? existsSync46(join43(packageDir, "Package.swift"));
|
|
42964
44246
|
if (!packageAvailable) {
|
|
42965
44247
|
return {
|
|
42966
44248
|
platform: "ios",
|
|
@@ -42972,7 +44254,7 @@ function detectNativeDecode(options = {}) {
|
|
|
42972
44254
|
}
|
|
42973
44255
|
function localPropertiesSdk(harnessDir) {
|
|
42974
44256
|
try {
|
|
42975
|
-
const match =
|
|
44257
|
+
const match = readFileSync50(join43(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
42976
44258
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
42977
44259
|
} catch {
|
|
42978
44260
|
return null;
|
|
@@ -42980,8 +44262,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
42980
44262
|
}
|
|
42981
44263
|
function detectAndroidNativeDecode(options = {}) {
|
|
42982
44264
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
42983
|
-
const gradlew =
|
|
42984
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
44265
|
+
const gradlew = join43(harnessDir, "gradlew");
|
|
44266
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync46(gradlew);
|
|
42985
44267
|
if (!gradlewAvailable) {
|
|
42986
44268
|
return {
|
|
42987
44269
|
platform: "android",
|
|
@@ -42991,7 +44273,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
42991
44273
|
}
|
|
42992
44274
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
42993
44275
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
42994
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
44276
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync46(sdk));
|
|
42995
44277
|
if (!sdkAvailable) {
|
|
42996
44278
|
return {
|
|
42997
44279
|
platform: "android",
|
|
@@ -43063,14 +44345,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
43063
44345
|
return verdicts;
|
|
43064
44346
|
}
|
|
43065
44347
|
function runNativeDecode(options) {
|
|
43066
|
-
const descriptorDir = mkdtempSync2(
|
|
44348
|
+
const descriptorDir = mkdtempSync2(join43(tmpdir3(), "himi-native-decode-"));
|
|
43067
44349
|
const startedAt = Date.now();
|
|
43068
44350
|
try {
|
|
43069
44351
|
for (const descriptor of options.descriptors) {
|
|
43070
44352
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
43071
44353
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
43072
44354
|
}
|
|
43073
|
-
|
|
44355
|
+
writeFileSync19(join43(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
43074
44356
|
}
|
|
43075
44357
|
options.progress?.("building cached Swift oracle");
|
|
43076
44358
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -43082,7 +44364,7 @@ function runNativeDecode(options) {
|
|
|
43082
44364
|
encoding: "utf8"
|
|
43083
44365
|
}).trim();
|
|
43084
44366
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
43085
|
-
const stdout = execFileSync5(
|
|
44367
|
+
const stdout = execFileSync5(join43(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
43086
44368
|
stdio: ["ignore", "pipe", "pipe"],
|
|
43087
44369
|
encoding: "utf8"
|
|
43088
44370
|
});
|
|
@@ -43096,19 +44378,19 @@ function runNativeDecode(options) {
|
|
|
43096
44378
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
43097
44379
|
throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
|
|
43098
44380
|
} finally {
|
|
43099
|
-
|
|
44381
|
+
rmSync9(descriptorDir, { recursive: true, force: true });
|
|
43100
44382
|
}
|
|
43101
44383
|
}
|
|
43102
44384
|
function runAndroidNativeDecode(options) {
|
|
43103
|
-
const descriptorDir = mkdtempSync2(
|
|
43104
|
-
const outputPath =
|
|
44385
|
+
const descriptorDir = mkdtempSync2(join43(tmpdir3(), "himi-native-decode-android-"));
|
|
44386
|
+
const outputPath = join43(descriptorDir, "verdicts.ndjson");
|
|
43105
44387
|
const startedAt = Date.now();
|
|
43106
44388
|
try {
|
|
43107
44389
|
for (const descriptor of options.descriptors) {
|
|
43108
44390
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
43109
44391
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
43110
44392
|
}
|
|
43111
|
-
|
|
44393
|
+
writeFileSync19(join43(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
43112
44394
|
}
|
|
43113
44395
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
43114
44396
|
execFileSync5(options.gradlew, [
|
|
@@ -43123,7 +44405,7 @@ function runAndroidNativeDecode(options) {
|
|
|
43123
44405
|
stdio: ["ignore", "ignore", "pipe"],
|
|
43124
44406
|
encoding: "utf8"
|
|
43125
44407
|
});
|
|
43126
|
-
const stdout =
|
|
44408
|
+
const stdout = readFileSync50(outputPath, "utf8");
|
|
43127
44409
|
return {
|
|
43128
44410
|
platform: "android",
|
|
43129
44411
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -43134,7 +44416,7 @@ function runAndroidNativeDecode(options) {
|
|
|
43134
44416
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
43135
44417
|
throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
|
|
43136
44418
|
} finally {
|
|
43137
|
-
|
|
44419
|
+
rmSync9(descriptorDir, { recursive: true, force: true });
|
|
43138
44420
|
}
|
|
43139
44421
|
}
|
|
43140
44422
|
function fieldAt(path2) {
|
|
@@ -43194,30 +44476,30 @@ __export(browser_authoring_exports, {
|
|
|
43194
44476
|
import { createServer as createServer3 } from "node:http";
|
|
43195
44477
|
import { createHash as createHash22, randomBytes as randomBytes4 } from "node:crypto";
|
|
43196
44478
|
import { execFile as execFile2 } from "node:child_process";
|
|
43197
|
-
import { existsSync as
|
|
43198
|
-
import { join as
|
|
44479
|
+
import { existsSync as existsSync47, readdirSync as readdirSync23, readFileSync as readFileSync51, realpathSync as realpathSync4, statSync as statSync10 } from "node:fs";
|
|
44480
|
+
import { join as join44, posix, relative as relative6, sep as sep10 } from "node:path";
|
|
43199
44481
|
function humanMs(ms) {
|
|
43200
44482
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
43201
44483
|
}
|
|
43202
44484
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
43203
|
-
const root =
|
|
44485
|
+
const root = join44(tier5SrcDir, bundleName);
|
|
43204
44486
|
const files = {};
|
|
43205
44487
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
43206
44488
|
const walk2 = (abs, rel) => {
|
|
43207
44489
|
const real = realpathSync4(abs);
|
|
43208
44490
|
if (visitedDirs.has(real)) return;
|
|
43209
44491
|
visitedDirs.add(real);
|
|
43210
|
-
for (const name of
|
|
43211
|
-
const childAbs =
|
|
44492
|
+
for (const name of readdirSync23(abs).sort()) {
|
|
44493
|
+
const childAbs = join44(abs, name);
|
|
43212
44494
|
const childRel = posix.join(rel, name);
|
|
43213
|
-
if (
|
|
44495
|
+
if (statSync10(childAbs).isDirectory()) {
|
|
43214
44496
|
walk2(childAbs, childRel);
|
|
43215
44497
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
43216
|
-
files[childRel] =
|
|
44498
|
+
files[childRel] = readFileSync51(childAbs, "utf8");
|
|
43217
44499
|
}
|
|
43218
44500
|
}
|
|
43219
44501
|
};
|
|
43220
|
-
if (!
|
|
44502
|
+
if (!existsSync47(root)) return null;
|
|
43221
44503
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
43222
44504
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
43223
44505
|
if (!entry) return null;
|
|
@@ -43234,20 +44516,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
43234
44516
|
const spec = m[1];
|
|
43235
44517
|
const virtual = posix.normalize(posix.join(dir, spec));
|
|
43236
44518
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
43237
|
-
const onDisk =
|
|
44519
|
+
const onDisk = join44(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
43238
44520
|
const candidates = [
|
|
43239
44521
|
onDisk,
|
|
43240
44522
|
`${onDisk}.ts`,
|
|
43241
44523
|
`${onDisk}.js`,
|
|
43242
44524
|
onDisk.replace(/\.js$/, ".ts"),
|
|
43243
|
-
|
|
43244
|
-
|
|
44525
|
+
join44(onDisk, "index.ts"),
|
|
44526
|
+
join44(onDisk, "index.js")
|
|
43245
44527
|
];
|
|
43246
44528
|
for (const abs of candidates) {
|
|
43247
|
-
if (!
|
|
44529
|
+
if (!existsSync47(abs) || statSync10(abs).isDirectory()) continue;
|
|
43248
44530
|
const key2 = `/tier5-src/${relative6(tier5SrcDir, abs).split(sep10).join(posix.sep)}`;
|
|
43249
44531
|
if (key2 in files) break;
|
|
43250
|
-
files[key2] =
|
|
44532
|
+
files[key2] = readFileSync51(abs, "utf8");
|
|
43251
44533
|
queue.push(key2);
|
|
43252
44534
|
break;
|
|
43253
44535
|
}
|
|
@@ -43282,7 +44564,7 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
43282
44564
|
function sdkSubpathReader(resolve45) {
|
|
43283
44565
|
return (sub) => {
|
|
43284
44566
|
try {
|
|
43285
|
-
return
|
|
44567
|
+
return readFileSync51(resolve45(`@wix/himalaya/${sub}`), "utf8");
|
|
43286
44568
|
} catch {
|
|
43287
44569
|
return null;
|
|
43288
44570
|
}
|
|
@@ -43456,8 +44738,8 @@ __export(coverage_exports, {
|
|
|
43456
44738
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
43457
44739
|
trendAndStore: () => trendAndStore
|
|
43458
44740
|
});
|
|
43459
|
-
import { existsSync as
|
|
43460
|
-
import { dirname as
|
|
44741
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync23, readFileSync as readFileSync52, writeFileSync as writeFileSync20 } from "node:fs";
|
|
44742
|
+
import { dirname as dirname26, join as join45 } from "node:path";
|
|
43461
44743
|
function suppressedNativeKeys(oracle) {
|
|
43462
44744
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
43463
44745
|
}
|
|
@@ -43627,11 +44909,11 @@ function assembleLedger(r, options = {}) {
|
|
|
43627
44909
|
return out;
|
|
43628
44910
|
}
|
|
43629
44911
|
function trendAndStore(dir, entries, suppressed) {
|
|
43630
|
-
const p =
|
|
44912
|
+
const p = join45(dir, LEDGER_FILE);
|
|
43631
44913
|
let previous = null;
|
|
43632
44914
|
try {
|
|
43633
|
-
if (
|
|
43634
|
-
const parsed = JSON.parse(
|
|
44915
|
+
if (existsSync48(p)) {
|
|
44916
|
+
const parsed = JSON.parse(readFileSync52(p, "utf8"));
|
|
43635
44917
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
43636
44918
|
}
|
|
43637
44919
|
} catch {
|
|
@@ -43639,8 +44921,8 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
43639
44921
|
const current = entries.map((e) => e.key);
|
|
43640
44922
|
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
43641
44923
|
try {
|
|
43642
|
-
|
|
43643
|
-
|
|
44924
|
+
mkdirSync23(dirname26(p), { recursive: true });
|
|
44925
|
+
writeFileSync20(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
43644
44926
|
} catch {
|
|
43645
44927
|
return null;
|
|
43646
44928
|
}
|
|
@@ -43670,11 +44952,11 @@ function formatLedger(entries, trend) {
|
|
|
43670
44952
|
return out.join("\n");
|
|
43671
44953
|
}
|
|
43672
44954
|
function diffAndStoreObservations(dir, current) {
|
|
43673
|
-
const p =
|
|
44955
|
+
const p = join45(dir, OBS_FILE);
|
|
43674
44956
|
let previous = null;
|
|
43675
44957
|
try {
|
|
43676
|
-
if (
|
|
43677
|
-
const parsed = JSON.parse(
|
|
44958
|
+
if (existsSync48(p)) {
|
|
44959
|
+
const parsed = JSON.parse(readFileSync52(p, "utf8"));
|
|
43678
44960
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
43679
44961
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
43680
44962
|
)) {
|
|
@@ -43684,8 +44966,8 @@ function diffAndStoreObservations(dir, current) {
|
|
|
43684
44966
|
} catch {
|
|
43685
44967
|
}
|
|
43686
44968
|
try {
|
|
43687
|
-
|
|
43688
|
-
|
|
44969
|
+
mkdirSync23(dirname26(p), { recursive: true });
|
|
44970
|
+
writeFileSync20(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
43689
44971
|
} catch {
|
|
43690
44972
|
return null;
|
|
43691
44973
|
}
|
|
@@ -43723,8 +45005,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
43723
45005
|
var init_coverage = __esm({
|
|
43724
45006
|
"src/coverage.ts"() {
|
|
43725
45007
|
init_native_decode();
|
|
43726
|
-
LEDGER_FILE =
|
|
43727
|
-
OBS_FILE =
|
|
45008
|
+
LEDGER_FILE = join45(".himi", "test-ledger.json");
|
|
45009
|
+
OBS_FILE = join45(".himi", "test-observations.json");
|
|
43728
45010
|
}
|
|
43729
45011
|
});
|
|
43730
45012
|
|
|
@@ -43735,16 +45017,16 @@ __export(design_kits_exports, {
|
|
|
43735
45017
|
kitsDir: () => kitsDir,
|
|
43736
45018
|
listKits: () => listKits2
|
|
43737
45019
|
});
|
|
43738
|
-
import { existsSync as
|
|
43739
|
-
import { join as
|
|
45020
|
+
import { existsSync as existsSync49, readFileSync as readFileSync53, readdirSync as readdirSync24 } from "node:fs";
|
|
45021
|
+
import { join as join46, basename as basename10 } from "node:path";
|
|
43740
45022
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
43741
45023
|
function kitsDir() {
|
|
43742
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
45024
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync49(p));
|
|
43743
45025
|
}
|
|
43744
45026
|
function listKits2() {
|
|
43745
45027
|
const dir = kitsDir();
|
|
43746
45028
|
if (!dir) return [];
|
|
43747
|
-
return
|
|
45029
|
+
return readdirSync24(dir).filter((f) => f.endsWith(".json")).map((f) => basename10(f, ".json")).sort();
|
|
43748
45030
|
}
|
|
43749
45031
|
function kitReport(name) {
|
|
43750
45032
|
const dir = kitsDir();
|
|
@@ -43763,7 +45045,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
43763
45045
|
if (!kits.includes(name)) {
|
|
43764
45046
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
43765
45047
|
}
|
|
43766
|
-
const raw =
|
|
45048
|
+
const raw = readFileSync53(join46(dir, `${name}.json`), "utf8");
|
|
43767
45049
|
let parsed;
|
|
43768
45050
|
try {
|
|
43769
45051
|
parsed = JSON.parse(raw);
|
|
@@ -43787,9 +45069,9 @@ var init_design_kits = __esm({
|
|
|
43787
45069
|
"src/design-kits.ts"() {
|
|
43788
45070
|
KIT_DIR_CANDIDATES = [
|
|
43789
45071
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
43790
|
-
|
|
45072
|
+
join46(fileURLToPath21(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
43791
45073
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
43792
|
-
|
|
45074
|
+
join46(fileURLToPath21(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
43793
45075
|
];
|
|
43794
45076
|
}
|
|
43795
45077
|
});
|
|
@@ -43803,11 +45085,11 @@ __export(assets_exports, {
|
|
|
43803
45085
|
removeAssetPayload: () => removeAssetPayload,
|
|
43804
45086
|
verifyReport: () => verifyReport
|
|
43805
45087
|
});
|
|
43806
|
-
import { readFileSync as
|
|
45088
|
+
import { readFileSync as readFileSync54 } from "node:fs";
|
|
43807
45089
|
import { basename as basename11 } from "node:path";
|
|
43808
45090
|
function declaredAssets(dir) {
|
|
43809
45091
|
return collectAssets(dir).map((a) => {
|
|
43810
|
-
const bytes2 =
|
|
45092
|
+
const bytes2 = readFileSync54(a.path);
|
|
43811
45093
|
return {
|
|
43812
45094
|
name: a.name,
|
|
43813
45095
|
sha256: assetSha256(bytes2),
|
|
@@ -43884,7 +45166,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
43884
45166
|
};
|
|
43885
45167
|
}
|
|
43886
45168
|
function addAssetPayload(manifest, filePath, opts) {
|
|
43887
|
-
const bytes2 =
|
|
45169
|
+
const bytes2 = readFileSync54(filePath);
|
|
43888
45170
|
const name = opts.name ?? basename11(filePath);
|
|
43889
45171
|
const sha2565 = assetSha256(bytes2);
|
|
43890
45172
|
const record2 = {
|
|
@@ -44581,6 +45863,7 @@ ${releaseId}`;
|
|
|
44581
45863
|
if (!isSafeMsid(msid)) return json3(400, { error: "webwix_owner_bad_msid" });
|
|
44582
45864
|
const cookie = request.headers.get("cookie") ?? "";
|
|
44583
45865
|
if (!/wixSession2=/.test(cookie)) return json3(401, { error: "webwix_owner_no_session" });
|
|
45866
|
+
if (url.searchParams.get("renew") === "1") webwixOwnerInstances.invalidate(msid, cookie);
|
|
44584
45867
|
try {
|
|
44585
45868
|
const entry = await webwixOwnerInstances.entry(msid, cookie);
|
|
44586
45869
|
return json3(200, { ...entry, expiresInMs: Math.max(0, entry.expiresAt - Date.now()) }, { "cache-control": "no-store" });
|
|
@@ -45359,19 +46642,19 @@ var init_preview_assets_generated = __esm({
|
|
|
45359
46642
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
45360
46643
|
init_preview_assets_format();
|
|
45361
46644
|
PREVIEW_ASSET_MANIFEST = [
|
|
45362
|
-
{ key: "assets/index-
|
|
45363
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
45364
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
45365
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
45366
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
45367
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
45368
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
45369
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
45370
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
45371
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
45372
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
45373
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
45374
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
46645
|
+
{ key: "assets/index-BKft9wm1.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1012166, sha256: "3a87519baabf67cecf163d20ea1eaaeba288fdeab2fc00cc3d22f09b6a29a194" },
|
|
46646
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1012174, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
46647
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1103098, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
46648
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1194082, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
46649
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1285062, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
46650
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1375934, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
46651
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1466914, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
46652
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 1575550, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
46653
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 1684634, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
46654
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 1793682, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
46655
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 1901382, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
46656
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 1989490, length: 4448, sha256: "71627ade6c0e47a8956b4841c1f6d644fee50a9a4ca9e6d9106b589e84891bd7" },
|
|
46657
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 1993938, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
45375
46658
|
];
|
|
45376
46659
|
}
|
|
45377
46660
|
});
|
|
@@ -45387,9 +46670,9 @@ __export(run_exports, {
|
|
|
45387
46670
|
runPackage: () => runPackage,
|
|
45388
46671
|
withoutProdServe: () => withoutProdServe
|
|
45389
46672
|
});
|
|
45390
|
-
import { cpSync, existsSync as
|
|
46673
|
+
import { cpSync as cpSync2, existsSync as existsSync50, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync3, readFileSync as readFileSync55, rmSync as rmSync10, statSync as statSync11 } from "node:fs";
|
|
45391
46674
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
45392
|
-
import { dirname as
|
|
46675
|
+
import { dirname as dirname27, join as join47 } from "node:path";
|
|
45393
46676
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
45394
46677
|
import { spawn as spawn3 } from "node:child_process";
|
|
45395
46678
|
function makePackageRunHandler(opts) {
|
|
@@ -45408,9 +46691,9 @@ async function fetchBytes(url) {
|
|
|
45408
46691
|
}
|
|
45409
46692
|
async function resolvePackage(source, workDir) {
|
|
45410
46693
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
45411
|
-
if (!isUrl2 &&
|
|
45412
|
-
const appDirManifest =
|
|
45413
|
-
if (
|
|
46694
|
+
if (!isUrl2 && existsSync50(source) && statSync11(source).isDirectory()) {
|
|
46695
|
+
const appDirManifest = join47(source, "release-manifest.json");
|
|
46696
|
+
if (existsSync50(appDirManifest)) {
|
|
45414
46697
|
const opened2 = openPackageDir(source);
|
|
45415
46698
|
if (!opened2.validation.ok) {
|
|
45416
46699
|
throw new Error(`package is not valid:
|
|
@@ -45419,12 +46702,12 @@ async function resolvePackage(source, workDir) {
|
|
|
45419
46702
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
45420
46703
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
45421
46704
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
45422
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
45423
|
-
const target =
|
|
45424
|
-
if (
|
|
45425
|
-
|
|
45426
|
-
|
|
45427
|
-
|
|
46705
|
+
const root2 = workDir ?? mkdtempSync3(join47(tmpdir4(), "himi-run-"));
|
|
46706
|
+
const target = join47(root2, app2);
|
|
46707
|
+
if (join47(source) !== target) {
|
|
46708
|
+
mkdirSync24(root2, { recursive: true });
|
|
46709
|
+
rmSync10(target, { recursive: true, force: true });
|
|
46710
|
+
cpSync2(source, target, { recursive: true });
|
|
45428
46711
|
}
|
|
45429
46712
|
return {
|
|
45430
46713
|
releaseRoot: root2,
|
|
@@ -45438,12 +46721,12 @@ async function resolvePackage(source, workDir) {
|
|
|
45438
46721
|
}
|
|
45439
46722
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
45440
46723
|
}
|
|
45441
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
45442
|
-
const root = workDir ?? mkdtempSync3(
|
|
46724
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync55(source);
|
|
46725
|
+
const root = workDir ?? mkdtempSync3(join47(tmpdir4(), "himi-run-"));
|
|
45443
46726
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
45444
46727
|
const opened = openPackageDir(appDir2);
|
|
45445
46728
|
if (!opened.validation.ok) {
|
|
45446
|
-
|
|
46729
|
+
rmSync10(workDir ? appDir2 : root, { recursive: true, force: true });
|
|
45447
46730
|
throw new Error(`package is not valid:
|
|
45448
46731
|
${opened.validation.errors.join("\n ")}`);
|
|
45449
46732
|
}
|
|
@@ -45460,16 +46743,16 @@ async function resolvePackage(source, workDir) {
|
|
|
45460
46743
|
async function loadPreviewAssets() {
|
|
45461
46744
|
try {
|
|
45462
46745
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
45463
|
-
const here =
|
|
46746
|
+
const here = dirname27(fileURLToPath22(import.meta.url));
|
|
45464
46747
|
const candidates = [
|
|
45465
|
-
|
|
46748
|
+
join47(here, "preview-assets.generated.bin"),
|
|
45466
46749
|
// published: copied next to the bundled CLI
|
|
45467
|
-
|
|
46750
|
+
join47(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
45468
46751
|
// in-repo checkout
|
|
45469
46752
|
];
|
|
45470
46753
|
for (const path2 of candidates) {
|
|
45471
|
-
if (!
|
|
45472
|
-
const blob =
|
|
46754
|
+
if (!existsSync50(path2)) continue;
|
|
46755
|
+
const blob = readFileSync55(path2);
|
|
45473
46756
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
45474
46757
|
}
|
|
45475
46758
|
return /* @__PURE__ */ new Map();
|
|
@@ -45494,7 +46777,7 @@ async function runPackage(source, opts = {}) {
|
|
|
45494
46777
|
const resolved2 = await resolvePackage(source, opts.workDir);
|
|
45495
46778
|
const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
|
|
45496
46779
|
if (!opts.spa && assets.size === 0) {
|
|
45497
|
-
if (resolved2.temp)
|
|
46780
|
+
if (resolved2.temp) rmSync10(resolved2.temp, { recursive: true, force: true });
|
|
45498
46781
|
throw new Error(NO_SPA_MESSAGE);
|
|
45499
46782
|
}
|
|
45500
46783
|
const handler = makePackageRunHandler({
|
|
@@ -45524,7 +46807,7 @@ async function runPackage(source, opts = {}) {
|
|
|
45524
46807
|
warnings: resolved2.warnings,
|
|
45525
46808
|
close: () => new Promise((done) => {
|
|
45526
46809
|
server.close(() => {
|
|
45527
|
-
if (resolved2.temp)
|
|
46810
|
+
if (resolved2.temp) rmSync10(resolved2.temp, { recursive: true, force: true });
|
|
45528
46811
|
done();
|
|
45529
46812
|
});
|
|
45530
46813
|
})
|
|
@@ -45551,15 +46834,15 @@ __export(run_browser_exports, {
|
|
|
45551
46834
|
runInBrowser: () => runInBrowser
|
|
45552
46835
|
});
|
|
45553
46836
|
import { createServer as createServer5 } from "node:http";
|
|
45554
|
-
import { existsSync as
|
|
46837
|
+
import { existsSync as existsSync51, readFileSync as readFileSync56 } from "node:fs";
|
|
45555
46838
|
import { spawnSync as spawnSync3, execFile as execFile3 } from "node:child_process";
|
|
45556
|
-
import { dirname as
|
|
46839
|
+
import { dirname as dirname28, resolve as resolve40 } from "node:path";
|
|
45557
46840
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
45558
46841
|
function stagedDir() {
|
|
45559
46842
|
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve40(process.env.HIMI_BROWSER_PLANE_OUT) : resolve40(REPO, "packages", "serve", "dist", "browser-plane");
|
|
45560
46843
|
}
|
|
45561
46844
|
function missingStaged() {
|
|
45562
|
-
return [...SERVED].filter((f) => !
|
|
46845
|
+
return [...SERVED].filter((f) => !existsSync51(resolve40(stagedDir(), f))).sort();
|
|
45563
46846
|
}
|
|
45564
46847
|
function ensureBrowserPlaneStaged() {
|
|
45565
46848
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
@@ -45649,7 +46932,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
45649
46932
|
}
|
|
45650
46933
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
45651
46934
|
if (SERVED.has(name)) {
|
|
45652
|
-
if (!
|
|
46935
|
+
if (!existsSync51(resolve40(stagedDir(), name))) {
|
|
45653
46936
|
const restaged = ensureBrowserPlaneStaged();
|
|
45654
46937
|
if (!restaged.ok) {
|
|
45655
46938
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -45659,7 +46942,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
45659
46942
|
}
|
|
45660
46943
|
let bytes2;
|
|
45661
46944
|
try {
|
|
45662
|
-
bytes2 =
|
|
46945
|
+
bytes2 = readFileSync56(resolve40(stagedDir(), name));
|
|
45663
46946
|
} catch (e) {
|
|
45664
46947
|
res.writeHead(503, { "content-type": "application/json" });
|
|
45665
46948
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -45702,7 +46985,7 @@ var HERE, REPO, SERVED;
|
|
|
45702
46985
|
var init_run_browser = __esm({
|
|
45703
46986
|
"src/run-browser.ts"() {
|
|
45704
46987
|
init_file_store();
|
|
45705
|
-
HERE =
|
|
46988
|
+
HERE = dirname28(fileURLToPath23(import.meta.url));
|
|
45706
46989
|
REPO = resolve40(HERE, "..", "..", "..");
|
|
45707
46990
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
45708
46991
|
}
|
|
@@ -46122,7 +47405,7 @@ __export(preflight_exports, {
|
|
|
46122
47405
|
parseStoreConfig: () => parseStoreConfig,
|
|
46123
47406
|
requireEnv: () => requireEnv
|
|
46124
47407
|
});
|
|
46125
|
-
import { existsSync as
|
|
47408
|
+
import { existsSync as existsSync52, readFileSync as readFileSync57 } from "node:fs";
|
|
46126
47409
|
import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve41 } from "node:path";
|
|
46127
47410
|
function isInsideRepo(p) {
|
|
46128
47411
|
const rel = relative7(REPO_ROOT3, resolve41(p));
|
|
@@ -46179,10 +47462,10 @@ function parseStoreConfig(text4) {
|
|
|
46179
47462
|
}
|
|
46180
47463
|
function loadStoreConfig(app) {
|
|
46181
47464
|
const p = storeConfigPath(app);
|
|
46182
|
-
if (!
|
|
47465
|
+
if (!existsSync52(p)) {
|
|
46183
47466
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
46184
47467
|
}
|
|
46185
|
-
return parseStoreConfig(
|
|
47468
|
+
return parseStoreConfig(readFileSync57(p, "utf8"));
|
|
46186
47469
|
}
|
|
46187
47470
|
var init_preflight = __esm({
|
|
46188
47471
|
"../store-release/preflight.ts"() {
|
|
@@ -46201,19 +47484,19 @@ __export(credential_profile_exports, {
|
|
|
46201
47484
|
profilePath: () => profilePath,
|
|
46202
47485
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
46203
47486
|
});
|
|
46204
|
-
import { existsSync as
|
|
47487
|
+
import { existsSync as existsSync53, readFileSync as readFileSync58 } from "node:fs";
|
|
46205
47488
|
import { homedir as homedir5 } from "node:os";
|
|
46206
|
-
import { join as
|
|
47489
|
+
import { join as join48 } from "node:path";
|
|
46207
47490
|
function credentialsDir(home = homedir5()) {
|
|
46208
|
-
return
|
|
47491
|
+
return join48(home, ".himalaya", "store-credentials");
|
|
46209
47492
|
}
|
|
46210
47493
|
function profilePath(name, home = homedir5()) {
|
|
46211
47494
|
if (!PROFILE_NAME.test(name)) {
|
|
46212
47495
|
throw new Error(
|
|
46213
|
-
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${
|
|
47496
|
+
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join48(credentialsDir(home), "<name>.json")}; it is never a path.`
|
|
46214
47497
|
);
|
|
46215
47498
|
}
|
|
46216
|
-
return
|
|
47499
|
+
return join48(credentialsDir(home), `${name}.json`);
|
|
46217
47500
|
}
|
|
46218
47501
|
function parseProfile(text4, label2) {
|
|
46219
47502
|
let doc;
|
|
@@ -46244,8 +47527,8 @@ function resolveStoreCredentials(opts) {
|
|
|
46244
47527
|
const { app, cfg } = opts;
|
|
46245
47528
|
const env = opts.env ?? process.env;
|
|
46246
47529
|
const home = opts.home ?? homedir5();
|
|
46247
|
-
const read = opts.readProfile ?? ((p) =>
|
|
46248
|
-
const exists = opts.profileExists ??
|
|
47530
|
+
const read = opts.readProfile ?? ((p) => readFileSync58(p, "utf8"));
|
|
47531
|
+
const exists = opts.profileExists ?? existsSync53;
|
|
46249
47532
|
const ios = cfg.ios ?? {};
|
|
46250
47533
|
const flagName = opts.profileFlag?.trim();
|
|
46251
47534
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -46325,9 +47608,9 @@ __export(preflight_app_exports, {
|
|
|
46325
47608
|
preflightApp: () => preflightApp,
|
|
46326
47609
|
profileAccount: () => profileAccount
|
|
46327
47610
|
});
|
|
46328
|
-
import { readFileSync as
|
|
47611
|
+
import { readFileSync as readFileSync59, existsSync as existsSync54, readdirSync as readdirSync25, statSync as statSync12 } from "node:fs";
|
|
46329
47612
|
import { createHash as createHash23 } from "node:crypto";
|
|
46330
|
-
import { join as
|
|
47613
|
+
import { join as join49 } from "node:path";
|
|
46331
47614
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
46332
47615
|
const f = [];
|
|
46333
47616
|
const has = (re, s) => re.test(s);
|
|
@@ -46391,13 +47674,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
46391
47674
|
}
|
|
46392
47675
|
}
|
|
46393
47676
|
async function preflightApp(app, opts = {}) {
|
|
46394
|
-
const projectYml =
|
|
46395
|
-
const storeConfig =
|
|
47677
|
+
const projectYml = existsSync54(iosProjectYml(app)) ? readFileSync59(iosProjectYml(app), "utf8") : "";
|
|
47678
|
+
const storeConfig = existsSync54(storeConfigPath(app)) ? readFileSync59(storeConfigPath(app), "utf8") : "";
|
|
46396
47679
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
46397
47680
|
const findings = analyze(
|
|
46398
47681
|
projectYml,
|
|
46399
47682
|
storeConfig,
|
|
46400
|
-
await appIconState(
|
|
47683
|
+
await appIconState(join49(appDir(app), "ios")),
|
|
46401
47684
|
profileAccount(app, storeConfig, opts)
|
|
46402
47685
|
);
|
|
46403
47686
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -46426,18 +47709,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
46426
47709
|
return f;
|
|
46427
47710
|
}
|
|
46428
47711
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
46429
|
-
const root =
|
|
47712
|
+
const root = join49(storeDir(app), "metadata");
|
|
46430
47713
|
const out = /* @__PURE__ */ new Set();
|
|
46431
|
-
if (
|
|
46432
|
-
for (const n of
|
|
47714
|
+
if (existsSync54(root)) {
|
|
47715
|
+
for (const n of readdirSync25(root)) if (n.endsWith(".txt")) out.add(n);
|
|
46433
47716
|
}
|
|
46434
|
-
if (
|
|
47717
|
+
if (existsSync54(join49(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
46435
47718
|
return out;
|
|
46436
47719
|
}
|
|
46437
47720
|
function reviewInfoFiles(app) {
|
|
46438
|
-
const dir =
|
|
46439
|
-
if (!
|
|
46440
|
-
return new Set(
|
|
47721
|
+
const dir = join49(storeDir(app), "review_information");
|
|
47722
|
+
if (!existsSync54(dir)) return /* @__PURE__ */ new Set();
|
|
47723
|
+
return new Set(readdirSync25(dir).filter((n) => n.endsWith(".txt")));
|
|
46441
47724
|
}
|
|
46442
47725
|
function isValidAppStoreSize(w, h) {
|
|
46443
47726
|
return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
|
|
@@ -46546,12 +47829,12 @@ function analyzePlayListing(assets) {
|
|
|
46546
47829
|
return f;
|
|
46547
47830
|
}
|
|
46548
47831
|
function playListingAssets(app, locale = "en-US") {
|
|
46549
|
-
const dir =
|
|
47832
|
+
const dir = join49(storeDir(app), "play", locale, "images");
|
|
46550
47833
|
const read = (names) => {
|
|
46551
47834
|
for (const name of names) {
|
|
46552
|
-
const p =
|
|
47835
|
+
const p = join49(dir, name);
|
|
46553
47836
|
try {
|
|
46554
|
-
if (
|
|
47837
|
+
if (statSync12(p).isFile()) return { name, bytes: readFileSync59(p) };
|
|
46555
47838
|
} catch {
|
|
46556
47839
|
}
|
|
46557
47840
|
}
|
|
@@ -46582,26 +47865,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
46582
47865
|
return f;
|
|
46583
47866
|
}
|
|
46584
47867
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
46585
|
-
const dir =
|
|
46586
|
-
if (!
|
|
46587
|
-
return new Set(
|
|
47868
|
+
const dir = join49(storeDir(app), "metadata", locale);
|
|
47869
|
+
if (!existsSync54(dir)) return /* @__PURE__ */ new Set();
|
|
47870
|
+
return new Set(readdirSync25(dir).filter((n) => n.endsWith(".txt")));
|
|
46588
47871
|
}
|
|
46589
47872
|
function listScreenshots(app, locale = "en-US") {
|
|
46590
47873
|
const out = [];
|
|
46591
|
-
const flat =
|
|
46592
|
-
if (
|
|
46593
|
-
for (const png of
|
|
46594
|
-
const sz = pngSize(
|
|
47874
|
+
const flat = join49(storeDir(app), "screenshots", locale);
|
|
47875
|
+
if (existsSync54(flat)) {
|
|
47876
|
+
for (const png of readdirSync25(flat).filter((n) => n.endsWith(".png"))) {
|
|
47877
|
+
const sz = pngSize(readFileSync59(join49(flat, png)));
|
|
46595
47878
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
46596
47879
|
}
|
|
46597
47880
|
}
|
|
46598
|
-
const legacy =
|
|
46599
|
-
if (
|
|
46600
|
-
for (const deviceDir of
|
|
46601
|
-
const d =
|
|
46602
|
-
if (!
|
|
46603
|
-
for (const png of
|
|
46604
|
-
const sz = pngSize(
|
|
47881
|
+
const legacy = join49(storeDir(app), "metadata", locale, "screenshots");
|
|
47882
|
+
if (existsSync54(legacy)) {
|
|
47883
|
+
for (const deviceDir of readdirSync25(legacy)) {
|
|
47884
|
+
const d = join49(legacy, deviceDir);
|
|
47885
|
+
if (!statSync12(d).isDirectory()) continue;
|
|
47886
|
+
for (const png of readdirSync25(d).filter((n) => n.endsWith(".png"))) {
|
|
47887
|
+
const sz = pngSize(readFileSync59(join49(d, png)));
|
|
46605
47888
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
46606
47889
|
}
|
|
46607
47890
|
}
|
|
@@ -46609,13 +47892,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
46609
47892
|
return out;
|
|
46610
47893
|
}
|
|
46611
47894
|
function placeholderHashes2() {
|
|
46612
|
-
const templateIos =
|
|
46613
|
-
if (!
|
|
46614
|
-
for (const target of
|
|
46615
|
-
const p =
|
|
47895
|
+
const templateIos = join49(appDir("_template"), "ios");
|
|
47896
|
+
if (!existsSync54(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
47897
|
+
for (const target of readdirSync25(templateIos)) {
|
|
47898
|
+
const p = join49(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
46616
47899
|
try {
|
|
46617
|
-
if (!
|
|
46618
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(
|
|
47900
|
+
if (!statSync12(p).isFile()) continue;
|
|
47901
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync59(p)).digest("hex")];
|
|
46619
47902
|
} catch {
|
|
46620
47903
|
}
|
|
46621
47904
|
}
|
|
@@ -46646,12 +47929,12 @@ async function pixelIssues(bytes2) {
|
|
|
46646
47929
|
}
|
|
46647
47930
|
}
|
|
46648
47931
|
async function appIconState(iosDir) {
|
|
46649
|
-
if (!
|
|
46650
|
-
for (const target of
|
|
46651
|
-
const p =
|
|
47932
|
+
if (!existsSync54(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
47933
|
+
for (const target of readdirSync25(iosDir)) {
|
|
47934
|
+
const p = join49(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
46652
47935
|
try {
|
|
46653
|
-
if (!
|
|
46654
|
-
const bytes2 =
|
|
47936
|
+
if (!statSync12(p).isFile()) continue;
|
|
47937
|
+
const bytes2 = readFileSync59(p);
|
|
46655
47938
|
const hash = createHash23("sha256").update(bytes2).digest("hex");
|
|
46656
47939
|
const pixels = await pixelIssues(bytes2);
|
|
46657
47940
|
return {
|
|
@@ -46723,7 +48006,7 @@ __export(version_exports, {
|
|
|
46723
48006
|
setAndroidVersion: () => setAndroidVersion,
|
|
46724
48007
|
setIosVersion: () => setIosVersion
|
|
46725
48008
|
});
|
|
46726
|
-
import { readFileSync as
|
|
48009
|
+
import { readFileSync as readFileSync60, writeFileSync as writeFileSync21 } from "node:fs";
|
|
46727
48010
|
function readIosVersion(projectYml) {
|
|
46728
48011
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
46729
48012
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -46781,15 +48064,15 @@ function setAndroidVersion(gradle, v) {
|
|
|
46781
48064
|
function bumpVersion(app, opts) {
|
|
46782
48065
|
const iosPath = iosProjectYml(app);
|
|
46783
48066
|
const gradlePath = androidGradle(app);
|
|
46784
|
-
const iosYml =
|
|
46785
|
-
const gradle =
|
|
48067
|
+
const iosYml = readFileSync60(iosPath, "utf8");
|
|
48068
|
+
const gradle = readFileSync60(gradlePath, "utf8");
|
|
46786
48069
|
const current = readIosVersion(iosYml);
|
|
46787
48070
|
const next = {
|
|
46788
48071
|
marketing: opts.marketing ?? current.marketing,
|
|
46789
48072
|
build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
|
|
46790
48073
|
};
|
|
46791
|
-
|
|
46792
|
-
|
|
48074
|
+
writeFileSync21(iosPath, setIosVersion(iosYml, next));
|
|
48075
|
+
writeFileSync21(gradlePath, setAndroidVersion(gradle, next));
|
|
46793
48076
|
return next;
|
|
46794
48077
|
}
|
|
46795
48078
|
var init_version = __esm({
|
|
@@ -46799,7 +48082,7 @@ var init_version = __esm({
|
|
|
46799
48082
|
});
|
|
46800
48083
|
|
|
46801
48084
|
// ../store-release/register-bundle.ts
|
|
46802
|
-
import { readFileSync as
|
|
48085
|
+
import { readFileSync as readFileSync61 } from "node:fs";
|
|
46803
48086
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
46804
48087
|
function b64url2(b) {
|
|
46805
48088
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -46817,7 +48100,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
46817
48100
|
async function registerBundleId(opts) {
|
|
46818
48101
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
46819
48102
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
46820
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
48103
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync61(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
46821
48104
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
46822
48105
|
method: "POST",
|
|
46823
48106
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -46871,7 +48154,7 @@ __export(asc_status_exports, {
|
|
|
46871
48154
|
ascStatus: () => ascStatus,
|
|
46872
48155
|
buildVerdict: () => buildVerdict
|
|
46873
48156
|
});
|
|
46874
|
-
import { readFileSync as
|
|
48157
|
+
import { readFileSync as readFileSync62 } from "node:fs";
|
|
46875
48158
|
function buildVerdict(builds) {
|
|
46876
48159
|
if (!builds.length) {
|
|
46877
48160
|
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).";
|
|
@@ -46885,7 +48168,7 @@ function buildVerdict(builds) {
|
|
|
46885
48168
|
function client(creds) {
|
|
46886
48169
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
46887
48170
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
46888
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
48171
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync62(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
46889
48172
|
return async (path2) => {
|
|
46890
48173
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
46891
48174
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -46934,7 +48217,7 @@ var init_asc_status = __esm({
|
|
|
46934
48217
|
// ../../core/functions-secrets/src/vault.ts
|
|
46935
48218
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
|
|
46936
48219
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
46937
|
-
import { dirname as
|
|
48220
|
+
import { dirname as dirname29 } from "node:path";
|
|
46938
48221
|
function createJsonSecretStore(filePath) {
|
|
46939
48222
|
const read = async () => {
|
|
46940
48223
|
try {
|
|
@@ -46947,7 +48230,7 @@ function createJsonSecretStore(filePath) {
|
|
|
46947
48230
|
}
|
|
46948
48231
|
};
|
|
46949
48232
|
const write2 = async (records) => {
|
|
46950
|
-
await mkdir(
|
|
48233
|
+
await mkdir(dirname29(filePath), { recursive: true });
|
|
46951
48234
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
46952
48235
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
46953
48236
|
`, { mode: 384 });
|
|
@@ -47045,7 +48328,7 @@ __export(secrets_exports, {
|
|
|
47045
48328
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
47046
48329
|
runSecretsCommand: () => runSecretsCommand
|
|
47047
48330
|
});
|
|
47048
|
-
import { readFileSync as
|
|
48331
|
+
import { readFileSync as readFileSync63 } from "node:fs";
|
|
47049
48332
|
function environment(value) {
|
|
47050
48333
|
if (value === "preview" || value === "production") return value;
|
|
47051
48334
|
throw new Error("--environment must be preview or production");
|
|
@@ -47076,7 +48359,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
47076
48359
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
47077
48360
|
return 0;
|
|
47078
48361
|
}
|
|
47079
|
-
const value = options.readValue ? options.readValue() :
|
|
48362
|
+
const value = options.readValue ? options.readValue() : readFileSync63(0, "utf8").replace(/\r?\n$/, "");
|
|
47080
48363
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
47081
48364
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
47082
48365
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -47105,7 +48388,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
47105
48388
|
}
|
|
47106
48389
|
let body;
|
|
47107
48390
|
if (operation !== "list") {
|
|
47108
|
-
const value = options.readValue ? options.readValue() :
|
|
48391
|
+
const value = options.readValue ? options.readValue() : readFileSync63(0, "utf8").replace(/\r?\n$/, "");
|
|
47109
48392
|
body = JSON.stringify({ value });
|
|
47110
48393
|
}
|
|
47111
48394
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -47141,15 +48424,15 @@ __export(notify_exports, {
|
|
|
47141
48424
|
runNotify: () => runNotify,
|
|
47142
48425
|
saveAdminSession: () => saveAdminSession
|
|
47143
48426
|
});
|
|
47144
|
-
import { chmodSync as chmodSync3, mkdirSync as
|
|
48427
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync25, readFileSync as readFileSync64, writeFileSync as writeFileSync22 } from "node:fs";
|
|
47145
48428
|
import { homedir as homedir6 } from "node:os";
|
|
47146
|
-
import { dirname as
|
|
48429
|
+
import { dirname as dirname30, join as join50 } from "node:path";
|
|
47147
48430
|
function defaultSessionsPath() {
|
|
47148
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
48431
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join50(homedir6(), ".himalaya", "admin-sessions.json");
|
|
47149
48432
|
}
|
|
47150
48433
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
47151
48434
|
try {
|
|
47152
|
-
return JSON.parse(
|
|
48435
|
+
return JSON.parse(readFileSync64(path2, "utf8"));
|
|
47153
48436
|
} catch {
|
|
47154
48437
|
return {};
|
|
47155
48438
|
}
|
|
@@ -47157,10 +48440,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
47157
48440
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
47158
48441
|
const file = loadSessionsFile(path2);
|
|
47159
48442
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
47160
|
-
|
|
47161
|
-
|
|
48443
|
+
mkdirSync25(dirname30(path2), { recursive: true, mode: 448 });
|
|
48444
|
+
writeFileSync22(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
47162
48445
|
try {
|
|
47163
|
-
chmodSync3(
|
|
48446
|
+
chmodSync3(dirname30(path2), 448);
|
|
47164
48447
|
chmodSync3(path2, 384);
|
|
47165
48448
|
} catch {
|
|
47166
48449
|
}
|
|
@@ -47419,56 +48702,6 @@ var init_notify = __esm({
|
|
|
47419
48702
|
}
|
|
47420
48703
|
});
|
|
47421
48704
|
|
|
47422
|
-
// src/site-analyze/types.ts
|
|
47423
|
-
function isRedirectUri(value) {
|
|
47424
|
-
return /^[a-z][a-z0-9+.-]*:\/\/\S*$/i.test(value);
|
|
47425
|
-
}
|
|
47426
|
-
function assertRedirectUri(value) {
|
|
47427
|
-
const trimmed = value.trim();
|
|
47428
|
-
if (!isRedirectUri(trimmed)) {
|
|
47429
|
-
throw new Error(
|
|
47430
|
-
`--redirect-uri must be a URI with a scheme (e.g. myapp://oauth/callback), got: ${JSON.stringify(value)}. It must also be REGISTERED on --client-id; register one with \`himi site client ensure --site <msid> --redirect-uri <uri> --yes\`.`
|
|
47431
|
-
);
|
|
47432
|
-
}
|
|
47433
|
-
return trimmed;
|
|
47434
|
-
}
|
|
47435
|
-
var BOOK_SCHEMA_VERSION, KNOWN_VERTICALS;
|
|
47436
|
-
var init_types2 = __esm({
|
|
47437
|
-
"src/site-analyze/types.ts"() {
|
|
47438
|
-
BOOK_SCHEMA_VERSION = 2;
|
|
47439
|
-
KNOWN_VERTICALS = [
|
|
47440
|
-
"store",
|
|
47441
|
-
"bookings",
|
|
47442
|
-
"restaurants",
|
|
47443
|
-
"programs",
|
|
47444
|
-
"plans",
|
|
47445
|
-
"feed",
|
|
47446
|
-
"members",
|
|
47447
|
-
"forum",
|
|
47448
|
-
"coupons",
|
|
47449
|
-
"notifications",
|
|
47450
|
-
"loyalty",
|
|
47451
|
-
"reviews",
|
|
47452
|
-
"portfolio",
|
|
47453
|
-
"reservations",
|
|
47454
|
-
"invoices",
|
|
47455
|
-
"badges",
|
|
47456
|
-
"notifsettings",
|
|
47457
|
-
"events",
|
|
47458
|
-
"blog",
|
|
47459
|
-
"groups",
|
|
47460
|
-
"cms",
|
|
47461
|
-
"donations",
|
|
47462
|
-
"giftCards",
|
|
47463
|
-
"videos",
|
|
47464
|
-
"podcasts",
|
|
47465
|
-
"forms",
|
|
47466
|
-
"galleries",
|
|
47467
|
-
"inbox"
|
|
47468
|
-
];
|
|
47469
|
-
}
|
|
47470
|
-
});
|
|
47471
|
-
|
|
47472
48705
|
// src/site-analyze/rest.ts
|
|
47473
48706
|
function resolveWixUrl(path2) {
|
|
47474
48707
|
if (/^https?:\/\//i.test(path2)) return path2;
|
|
@@ -49374,30 +50607,30 @@ function sectionsFrom(pages) {
|
|
|
49374
50607
|
const raw = page.sections?.length ? page.sections : page.headings.map((heading) => ({ heading, body: void 0 }));
|
|
49375
50608
|
let fromThisPage = 0;
|
|
49376
50609
|
for (const s of raw) {
|
|
49377
|
-
if (fromThisPage >=
|
|
49378
|
-
const heading = copyOrDrop(s.heading,
|
|
50610
|
+
if (fromThisPage >= CAP2.sectionsPerPage) break;
|
|
50611
|
+
const heading = copyOrDrop(s.heading, CAP2.heading);
|
|
49379
50612
|
if (!heading) continue;
|
|
49380
50613
|
const key2 = heading.toLowerCase();
|
|
49381
50614
|
if (seen.has(key2)) continue;
|
|
49382
50615
|
seen.add(key2);
|
|
49383
|
-
const body = copyOrDrop(s.body,
|
|
50616
|
+
const body = copyOrDrop(s.body, CAP2.body);
|
|
49384
50617
|
out.push({ heading, ...body ? { body } : {}, pageUrl: page.url, role: page.role });
|
|
49385
50618
|
fromThisPage++;
|
|
49386
|
-
if (out.length >=
|
|
50619
|
+
if (out.length >= CAP2.sections) return out;
|
|
49387
50620
|
}
|
|
49388
50621
|
}
|
|
49389
50622
|
return out;
|
|
49390
50623
|
}
|
|
49391
50624
|
function taglineFrom(identity, pages, published) {
|
|
49392
|
-
const owned = copyOrDrop(identity.description,
|
|
50625
|
+
const owned = copyOrDrop(identity.description, CAP2.tagline);
|
|
49393
50626
|
if (owned && identity.source === "owner-api") return { text: owned, source: "site-properties" };
|
|
49394
50627
|
const home = pages.find((p) => p.role === "home") ?? pages[0];
|
|
49395
|
-
const og = copyOrDrop(home?.meta?.ogDescription ?? published?.meta?.ogDescription,
|
|
50628
|
+
const og = copyOrDrop(home?.meta?.ogDescription ?? published?.meta?.ogDescription, CAP2.tagline);
|
|
49396
50629
|
if (og) return { text: og, source: "og" };
|
|
49397
|
-
const meta = copyOrDrop(home?.meta?.description ?? published?.meta?.description,
|
|
50630
|
+
const meta = copyOrDrop(home?.meta?.description ?? published?.meta?.description, CAP2.tagline);
|
|
49398
50631
|
if (meta) return { text: meta, source: "meta" };
|
|
49399
50632
|
if (owned) return { text: owned, source: "hero" };
|
|
49400
|
-
const hero = copyOrDrop(home?.heroCopy,
|
|
50633
|
+
const hero = copyOrDrop(home?.heroCopy, CAP2.tagline);
|
|
49401
50634
|
return hero ? { text: hero, source: "hero" } : null;
|
|
49402
50635
|
}
|
|
49403
50636
|
function suggestKeys(args) {
|
|
@@ -49406,9 +50639,9 @@ function suggestKeys(args) {
|
|
|
49406
50639
|
const installed = new Set(installedVerticals);
|
|
49407
50640
|
const set = (key2, value) => {
|
|
49408
50641
|
if (!key2 || out[key2] || !value) return;
|
|
49409
|
-
if (Object.keys(out).length >=
|
|
50642
|
+
if (Object.keys(out).length >= CAP2.keys) return;
|
|
49410
50643
|
if (key2.length > 120 || !/^[A-Za-z0-9._:-]+$/.test(key2)) return;
|
|
49411
|
-
out[key2] = value.slice(0,
|
|
50644
|
+
out[key2] = value.slice(0, CAP2.value);
|
|
49412
50645
|
};
|
|
49413
50646
|
const allowed2 = (rule) => !rule.vertical || installed.has(rule.vertical);
|
|
49414
50647
|
for (const label2 of nav) {
|
|
@@ -49430,42 +50663,42 @@ function buildCopyChapter(args) {
|
|
|
49430
50663
|
const { look, probes, identity, installedVerticals, published } = args;
|
|
49431
50664
|
const pages = pagesOf(look);
|
|
49432
50665
|
const sections = sectionsFrom(pages);
|
|
49433
|
-
const nav = dedupe2(look.navLabels.map((n) => copyOrDrop(n,
|
|
50666
|
+
const nav = dedupe2(look.navLabels.map((n) => copyOrDrop(n, CAP2.heading)), CAP2.nav);
|
|
49434
50667
|
const tagline = taglineFrom(identity, pages, published);
|
|
49435
50668
|
const ctas = dedupe2(
|
|
49436
50669
|
pages.flatMap((p) => p.ctaLabels?.length ? p.ctaLabels : p.layout.ctas),
|
|
49437
|
-
|
|
50670
|
+
CAP2.ctas
|
|
49438
50671
|
);
|
|
49439
50672
|
const faq = [];
|
|
49440
50673
|
for (const page of pages) {
|
|
49441
50674
|
for (const pair of page.faq ?? []) {
|
|
49442
|
-
if (faq.length >=
|
|
50675
|
+
if (faq.length >= CAP2.faq) break;
|
|
49443
50676
|
if (faq.some((f) => f.q.toLowerCase() === pair.q.toLowerCase())) continue;
|
|
49444
50677
|
faq.push({ ...pair, pageUrl: page.url });
|
|
49445
50678
|
}
|
|
49446
50679
|
}
|
|
49447
50680
|
const about = pages.map((p) => p.about).find(Boolean) ?? sections.find((s) => ABOUT_RULE.re.test(s.heading))?.body ?? null;
|
|
49448
|
-
if (faq.length <
|
|
50681
|
+
if (faq.length < CAP2.faq) {
|
|
49449
50682
|
const candidates = copyPageOrder(pages).flatMap(
|
|
49450
50683
|
(page) => (page.sections ?? []).map((sec) => ({
|
|
49451
|
-
heading: copyOrDrop(sec.heading,
|
|
49452
|
-
body: copyOrDrop(sec.body,
|
|
50684
|
+
heading: copyOrDrop(sec.heading, CAP2.heading),
|
|
50685
|
+
body: copyOrDrop(sec.body, CAP2.body),
|
|
49453
50686
|
pageUrl: page.url
|
|
49454
50687
|
}))
|
|
49455
50688
|
);
|
|
49456
50689
|
for (const section2 of candidates) {
|
|
49457
|
-
if (faq.length >=
|
|
50690
|
+
if (faq.length >= CAP2.faq) break;
|
|
49458
50691
|
if (!section2.heading || !section2.body || !/\?\s*$/.test(section2.heading)) continue;
|
|
49459
50692
|
if (about && section2.body === about) continue;
|
|
49460
50693
|
if (faq.some((f) => f.q.toLowerCase() === section2.heading.toLowerCase())) continue;
|
|
49461
50694
|
faq.push({ q: section2.heading, a: section2.body, pageUrl: section2.pageUrl });
|
|
49462
50695
|
}
|
|
49463
50696
|
}
|
|
49464
|
-
const testimonials = dedupe2(pages.flatMap((p) => p.testimonials ?? []),
|
|
50697
|
+
const testimonials = dedupe2(pages.flatMap((p) => p.testimonials ?? []), CAP2.testimonials);
|
|
49465
50698
|
const blogExcerpts = [];
|
|
49466
50699
|
for (const it of probes.find((p) => p.vertical === "blog")?.items ?? []) {
|
|
49467
|
-
if (blogExcerpts.length >=
|
|
49468
|
-
const title = copyOrDrop(it.title,
|
|
50700
|
+
if (blogExcerpts.length >= CAP2.blogExcerpts) break;
|
|
50701
|
+
const title = copyOrDrop(it.title, CAP2.heading);
|
|
49469
50702
|
if (!title) continue;
|
|
49470
50703
|
blogExcerpts.push({ title, ...it.description ? { excerpt: it.description } : {} });
|
|
49471
50704
|
}
|
|
@@ -49473,8 +50706,8 @@ function buildCopyChapter(args) {
|
|
|
49473
50706
|
for (const probe of probes) {
|
|
49474
50707
|
if (probe.vertical === "members") continue;
|
|
49475
50708
|
for (const item of probe.items) {
|
|
49476
|
-
if (catalog.length >=
|
|
49477
|
-
const title = copyOrDrop(item.title,
|
|
50709
|
+
if (catalog.length >= CAP2.catalog) break;
|
|
50710
|
+
const title = copyOrDrop(item.title, CAP2.heading);
|
|
49478
50711
|
if (!title) continue;
|
|
49479
50712
|
catalog.push({
|
|
49480
50713
|
vertical: probe.vertical,
|
|
@@ -49486,7 +50719,7 @@ function buildCopyChapter(args) {
|
|
|
49486
50719
|
if (!sections.length) {
|
|
49487
50720
|
for (const heading of published?.headings ?? []) {
|
|
49488
50721
|
sections.push({ heading, pageUrl: identity.url.primary ?? "", role: "home" });
|
|
49489
|
-
if (sections.length >=
|
|
50722
|
+
if (sections.length >= CAP2.sections) break;
|
|
49490
50723
|
}
|
|
49491
50724
|
}
|
|
49492
50725
|
const empty = !tagline && !sections.length && !nav.length && !ctas.length && !catalog.length && !faq.length && !testimonials.length && !about && !blogExcerpts.length;
|
|
@@ -49507,11 +50740,11 @@ function buildCopyChapter(args) {
|
|
|
49507
50740
|
suggestedCopyKeys: suggestKeys({ nav, sections, tagline, installedVerticals })
|
|
49508
50741
|
};
|
|
49509
50742
|
}
|
|
49510
|
-
var
|
|
50743
|
+
var CAP2, SYSTEM_PAGE_RE, ROLE_PRIORITY, KEY_RULES, ABOUT_RULE;
|
|
49511
50744
|
var init_copy = __esm({
|
|
49512
50745
|
"src/site-analyze/copy.ts"() {
|
|
49513
50746
|
init_copy_clean();
|
|
49514
|
-
|
|
50747
|
+
CAP2 = {
|
|
49515
50748
|
sections: 40,
|
|
49516
50749
|
sectionsPerPage: 8,
|
|
49517
50750
|
ctas: 24,
|
|
@@ -50734,8 +51967,8 @@ var init_brand_font = __esm({
|
|
|
50734
51967
|
});
|
|
50735
51968
|
|
|
50736
51969
|
// src/site-analyze/write-artifacts.ts
|
|
50737
|
-
import { mkdirSync as
|
|
50738
|
-
import { join as
|
|
51970
|
+
import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync23 } from "node:fs";
|
|
51971
|
+
import { join as join51 } from "node:path";
|
|
50739
51972
|
function attachVeloSources(book, sources, put) {
|
|
50740
51973
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
50741
51974
|
for (const f of book.velo.files) {
|
|
@@ -50890,13 +52123,13 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
50890
52123
|
}
|
|
50891
52124
|
async function writeBusinessBook(result, opts) {
|
|
50892
52125
|
const out = opts.outDir;
|
|
50893
|
-
|
|
50894
|
-
|
|
52126
|
+
mkdirSync26(join51(out, "evidence/pages"), { recursive: true });
|
|
52127
|
+
mkdirSync26(join51(out, "media/catalog"), { recursive: true });
|
|
50895
52128
|
const files = [];
|
|
50896
52129
|
const put = (rel, body) => {
|
|
50897
|
-
const p =
|
|
50898
|
-
|
|
50899
|
-
|
|
52130
|
+
const p = join51(out, rel);
|
|
52131
|
+
mkdirSync26(join51(p, ".."), { recursive: true });
|
|
52132
|
+
writeFileSync23(p, body);
|
|
50900
52133
|
files.push(rel);
|
|
50901
52134
|
};
|
|
50902
52135
|
const book = result.book;
|
|
@@ -50988,336 +52221,9 @@ var init_customer_build = __esm({
|
|
|
50988
52221
|
}
|
|
50989
52222
|
});
|
|
50990
52223
|
|
|
50991
|
-
// src/site-analyze/home-descriptor.ts
|
|
50992
|
-
function objectEnd(src, open) {
|
|
50993
|
-
let depth = 0;
|
|
50994
|
-
let inString = false;
|
|
50995
|
-
for (let i = open; i < src.length; i += 1) {
|
|
50996
|
-
const c = src[i];
|
|
50997
|
-
if (inString) {
|
|
50998
|
-
if (c === "\\") i += 1;
|
|
50999
|
-
else if (c === '"') inString = false;
|
|
51000
|
-
continue;
|
|
51001
|
-
}
|
|
51002
|
-
if (c === '"') inString = true;
|
|
51003
|
-
else if (c === "{") depth += 1;
|
|
51004
|
-
else if (c === "}") {
|
|
51005
|
-
depth -= 1;
|
|
51006
|
-
if (depth === 0) return i + 1;
|
|
51007
|
-
}
|
|
51008
|
-
}
|
|
51009
|
-
return -1;
|
|
51010
|
-
}
|
|
51011
|
-
function hasScreen(src, screenId) {
|
|
51012
|
-
const id = escapeRe2(screenId);
|
|
51013
|
-
return new RegExp(`"${id}": \\{\\s*"screenId": "${id}"`).test(src);
|
|
51014
|
-
}
|
|
51015
|
-
function findNode(root, pred) {
|
|
51016
|
-
if (Array.isArray(root)) {
|
|
51017
|
-
for (const child of root) {
|
|
51018
|
-
const hit = findNode(child, pred);
|
|
51019
|
-
if (hit) return hit;
|
|
51020
|
-
}
|
|
51021
|
-
return void 0;
|
|
51022
|
-
}
|
|
51023
|
-
if (!root || typeof root !== "object") return void 0;
|
|
51024
|
-
const node = root;
|
|
51025
|
-
if (node.body && typeof node.body === "object" && pred(node)) return node;
|
|
51026
|
-
for (const value of Object.values(root)) {
|
|
51027
|
-
const hit = findNode(value, pred);
|
|
51028
|
-
if (hit) return hit;
|
|
51029
|
-
}
|
|
51030
|
-
return void 0;
|
|
51031
|
-
}
|
|
51032
|
-
function cloneCell(template, prefix, vertical, card) {
|
|
51033
|
-
const cell = structuredClone(template);
|
|
51034
|
-
const accent = findNode(cell, (n) => n.body?.type === "Icon" && textProps(n)?.tint === "accentPrimary");
|
|
51035
|
-
const title = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "bodyEmphasis");
|
|
51036
|
-
const body = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "footnote");
|
|
51037
|
-
if (!accent || !title || !body || !cell.modifiers) return void 0;
|
|
51038
|
-
const onTap = cell.modifiers.onTap;
|
|
51039
|
-
if (!onTap?.actionId) return void 0;
|
|
51040
|
-
textProps(accent).name = card.icon;
|
|
51041
|
-
textProps(title).text = card.title;
|
|
51042
|
-
textProps(body).text = card.body;
|
|
51043
|
-
cell.modifiers.onTap = { actionId: onTap.actionId, params: { screenId: card.screenId } };
|
|
51044
|
-
cell.id = `${prefix}.${vertical}`;
|
|
51045
|
-
cell.modifiers.accessibilityLabel = card.title;
|
|
51046
|
-
return cell;
|
|
51047
|
-
}
|
|
51048
|
-
function lineIndent(src, open) {
|
|
51049
|
-
return /^[ \t]*/.exec(src.slice(src.lastIndexOf("\n", open) + 1, open))[0];
|
|
51050
|
-
}
|
|
51051
|
-
function serializeAt(node, src, open) {
|
|
51052
|
-
const indent = lineIndent(src, open);
|
|
51053
|
-
return JSON.stringify(node, null, 2).split("\n").map((line, i) => i === 0 ? line : indent + line).join("\n");
|
|
51054
|
-
}
|
|
51055
|
-
function patchGrids(src, installed, patch) {
|
|
51056
|
-
const OPEN = /"id": "([A-Za-z_0-9]+(?:\.[A-Za-z_0-9]+)*\.verticals)"/g;
|
|
51057
|
-
let out = "";
|
|
51058
|
-
let cursor = 0;
|
|
51059
|
-
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
51060
|
-
const open = src.lastIndexOf("{", m.index);
|
|
51061
|
-
if (open < cursor) continue;
|
|
51062
|
-
const close = objectEnd(src, open);
|
|
51063
|
-
if (close < 0) continue;
|
|
51064
|
-
const blob = src.slice(open, close);
|
|
51065
|
-
let node;
|
|
51066
|
-
try {
|
|
51067
|
-
node = JSON.parse(blob);
|
|
51068
|
-
} catch {
|
|
51069
|
-
continue;
|
|
51070
|
-
}
|
|
51071
|
-
const items = node.body?.type === "Grid" ? node.body.props?.items : void 0;
|
|
51072
|
-
if (!Array.isArray(items) || !items.length) continue;
|
|
51073
|
-
const prefix = m[1].slice(0, -".verticals".length);
|
|
51074
|
-
const baked = /* @__PURE__ */ new Map();
|
|
51075
|
-
const foreignCells = [];
|
|
51076
|
-
for (const item of items) {
|
|
51077
|
-
const id = item.id;
|
|
51078
|
-
const legacy = item.modifiers?.accessibilityLabel;
|
|
51079
|
-
const claim = typeof id === "string" && id ? id : typeof legacy === "string" ? legacy : "";
|
|
51080
|
-
const vertical = claim.startsWith(`${prefix}.`) ? claim.slice(prefix.length + 1) : "";
|
|
51081
|
-
if (isKnown(vertical)) baked.set(vertical, item);
|
|
51082
|
-
else if (!GRID_VERTICAL_LABELS.has(vertical)) foreignCells.push(item);
|
|
51083
|
-
}
|
|
51084
|
-
const wanted = [];
|
|
51085
|
-
for (const vertical of EXPLORE_ORDER) {
|
|
51086
|
-
if (!installed.has(vertical)) continue;
|
|
51087
|
-
if (baked.has(vertical)) {
|
|
51088
|
-
wanted.push(vertical);
|
|
51089
|
-
continue;
|
|
51090
|
-
}
|
|
51091
|
-
const card = EXPLORE_CARDS[vertical];
|
|
51092
|
-
if (!hasScreen(src, card.screenId)) {
|
|
51093
|
-
patch.unreachable.push(vertical);
|
|
51094
|
-
continue;
|
|
51095
|
-
}
|
|
51096
|
-
wanted.push(vertical);
|
|
51097
|
-
}
|
|
51098
|
-
const shape = baked.values().next().value ?? items[0];
|
|
51099
|
-
const next = [...foreignCells];
|
|
51100
|
-
const cells = [];
|
|
51101
|
-
for (const vertical of wanted) {
|
|
51102
|
-
if (next.length >= EXPLORE_MAX_CELLS) break;
|
|
51103
|
-
const bakedCell = baked.get(vertical);
|
|
51104
|
-
if (bakedCell) {
|
|
51105
|
-
next.push(bakedCell);
|
|
51106
|
-
cells.push(vertical);
|
|
51107
|
-
continue;
|
|
51108
|
-
}
|
|
51109
|
-
const made = cloneCell(shape, prefix, vertical, EXPLORE_CARDS[vertical]);
|
|
51110
|
-
if (!made) {
|
|
51111
|
-
patch.unreachable.push(vertical);
|
|
51112
|
-
continue;
|
|
51113
|
-
}
|
|
51114
|
-
next.push(made);
|
|
51115
|
-
cells.push(vertical);
|
|
51116
|
-
patch.added.push(vertical);
|
|
51117
|
-
}
|
|
51118
|
-
if (!cells.length) continue;
|
|
51119
|
-
patch.cells = cells;
|
|
51120
|
-
node.body.props.items = next;
|
|
51121
|
-
out += src.slice(cursor, open) + serializeAt(node, src, open);
|
|
51122
|
-
cursor = close;
|
|
51123
|
-
OPEN.lastIndex = close;
|
|
51124
|
-
}
|
|
51125
|
-
return out + src.slice(cursor);
|
|
51126
|
-
}
|
|
51127
|
-
function patchModules(src, installed, patch) {
|
|
51128
|
-
return src.replace(/"homeModules": "((?:[^"\\]|\\.)*)"/g, (whole, encoded2) => {
|
|
51129
|
-
let modules;
|
|
51130
|
-
try {
|
|
51131
|
-
const parsed = JSON.parse(JSON.parse(`"${encoded2}"`));
|
|
51132
|
-
if (!Array.isArray(parsed)) return whole;
|
|
51133
|
-
modules = parsed;
|
|
51134
|
-
} catch {
|
|
51135
|
-
return whole;
|
|
51136
|
-
}
|
|
51137
|
-
const kept = modules.filter((module) => {
|
|
51138
|
-
const source = module?.dataSource;
|
|
51139
|
-
if (typeof source !== "string") return true;
|
|
51140
|
-
const needs = MODULE_SOURCE_VERTICALS[source];
|
|
51141
|
-
return !needs || needs.some((vertical) => installed.has(vertical));
|
|
51142
|
-
});
|
|
51143
|
-
if (!kept.length || kept.length === modules.length) return whole;
|
|
51144
|
-
for (const module of modules) {
|
|
51145
|
-
if (!kept.includes(module) && typeof module?.id === "string") patch.droppedModules.push(module.id);
|
|
51146
|
-
}
|
|
51147
|
-
return `"homeModules": ${JSON.stringify(JSON.stringify(kept))}`;
|
|
51148
|
-
});
|
|
51149
|
-
}
|
|
51150
|
-
function homeScreenSpan(src, homeActionId) {
|
|
51151
|
-
const OPEN = /"([A-Za-z_0-9]+)": \{\s*"screenId": "\1"/g;
|
|
51152
|
-
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
51153
|
-
const open = src.indexOf("{", m.index);
|
|
51154
|
-
const close = objectEnd(src, open);
|
|
51155
|
-
if (close < 0) continue;
|
|
51156
|
-
if (src.slice(open, close).includes(`"actionId": "${homeActionId}"`)) return { open, close };
|
|
51157
|
-
OPEN.lastIndex = close;
|
|
51158
|
-
}
|
|
51159
|
-
return void 0;
|
|
51160
|
-
}
|
|
51161
|
-
function isDeadStoreCta(node) {
|
|
51162
|
-
if (node.body?.type !== "Button") return false;
|
|
51163
|
-
const action = node.body.props?.action;
|
|
51164
|
-
const screenId = action?.params?.screenId;
|
|
51165
|
-
return typeof screenId === "string" && isStoreScreen(screenId);
|
|
51166
|
-
}
|
|
51167
|
-
function pruneNode(node, dropped) {
|
|
51168
|
-
const props = node.body?.props;
|
|
51169
|
-
if (!props) return true;
|
|
51170
|
-
const lists = props.itemsPath ? ["children"] : ["children", "items"];
|
|
51171
|
-
for (const key2 of lists) {
|
|
51172
|
-
const list = props[key2];
|
|
51173
|
-
if (!Array.isArray(list) || !list.length) continue;
|
|
51174
|
-
const kept = list.filter((child) => {
|
|
51175
|
-
if (!isNode2(child)) return true;
|
|
51176
|
-
if (isDeadStoreCta(child)) {
|
|
51177
|
-
dropped.push(typeof child.id === "string" && child.id ? child.id : "(unnamed CTA)");
|
|
51178
|
-
return false;
|
|
51179
|
-
}
|
|
51180
|
-
return pruneNode(child, dropped);
|
|
51181
|
-
});
|
|
51182
|
-
if (kept.length === list.length) continue;
|
|
51183
|
-
if (!kept.length) return false;
|
|
51184
|
-
props[key2] = kept;
|
|
51185
|
-
}
|
|
51186
|
-
for (const [key2, child] of Object.entries(props)) {
|
|
51187
|
-
if (lists.includes(key2)) continue;
|
|
51188
|
-
pruneWithin(child, dropped);
|
|
51189
|
-
}
|
|
51190
|
-
return true;
|
|
51191
|
-
}
|
|
51192
|
-
function pruneWithin(value, dropped) {
|
|
51193
|
-
if (Array.isArray(value)) {
|
|
51194
|
-
for (const child of value) pruneWithin(child, dropped);
|
|
51195
|
-
return;
|
|
51196
|
-
}
|
|
51197
|
-
if (!value || typeof value !== "object") return;
|
|
51198
|
-
if (isNode2(value)) {
|
|
51199
|
-
pruneNode(value, dropped);
|
|
51200
|
-
return;
|
|
51201
|
-
}
|
|
51202
|
-
for (const child of Object.values(value)) pruneWithin(child, dropped);
|
|
51203
|
-
}
|
|
51204
|
-
function patchStoreCtas(src, verticals, homeActionId) {
|
|
51205
|
-
if (verticals.includes("store")) return { src, dropped: [] };
|
|
51206
|
-
const span = homeScreenSpan(src, homeActionId);
|
|
51207
|
-
if (!span) return { src, dropped: [] };
|
|
51208
|
-
let screen;
|
|
51209
|
-
try {
|
|
51210
|
-
screen = JSON.parse(src.slice(span.open, span.close));
|
|
51211
|
-
} catch {
|
|
51212
|
-
return { src, dropped: [] };
|
|
51213
|
-
}
|
|
51214
|
-
if (!isNode2(screen.payload)) return { src, dropped: [] };
|
|
51215
|
-
const dropped = [];
|
|
51216
|
-
if (!pruneNode(screen.payload, dropped) || !dropped.length) return { src, dropped: [] };
|
|
51217
|
-
return {
|
|
51218
|
-
src: src.slice(0, span.open) + serializeAt(screen, src, span.open) + src.slice(span.close),
|
|
51219
|
-
dropped
|
|
51220
|
-
};
|
|
51221
|
-
}
|
|
51222
|
-
function patchHomeForVerticals(src, verticals, homeActionId) {
|
|
51223
|
-
const installed = new Set(verticals.filter(isKnown));
|
|
51224
|
-
const patch = { src, cells: [], added: [], droppedModules: [], droppedCtas: [], unreachable: [] };
|
|
51225
|
-
if (!installed.size) return patch;
|
|
51226
|
-
const ctas = patchStoreCtas(patchModules(patchGrids(src, installed, patch), installed, patch), [...installed], homeActionId);
|
|
51227
|
-
patch.src = ctas.src;
|
|
51228
|
-
patch.droppedCtas = ctas.dropped;
|
|
51229
|
-
return patch;
|
|
51230
|
-
}
|
|
51231
|
-
var EXPLORE_CARDS, EXPLORE_ORDER, EXPLORE_MAX_CELLS, MODULE_SOURCE_VERTICALS, isKnown, GRID_VERTICAL_LABELS, escapeRe2, textProps, STORE_SCREENS, isStoreScreen, isNode2;
|
|
51232
|
-
var init_home_descriptor = __esm({
|
|
51233
|
-
"src/site-analyze/home-descriptor.ts"() {
|
|
51234
|
-
init_types2();
|
|
51235
|
-
EXPLORE_CARDS = {
|
|
51236
|
-
store: { icon: "bag", screenId: "himi_shop", title: "Shop", body: "Browse products and manage your cart." },
|
|
51237
|
-
bookings: { icon: "calendar", screenId: "himi_services", title: "Book", body: "Find a service and choose a time." },
|
|
51238
|
-
restaurants: { icon: "grid", screenId: "himi_menu", title: "Food", body: "Browse the menu and reserve a table." },
|
|
51239
|
-
events: { icon: "calendar", screenId: "himi_events", title: "Events", body: "Discover events and RSVP." },
|
|
51240
|
-
plans: { icon: "star", screenId: "himi_plans", title: "Plans", body: "Compare membership plans and join." },
|
|
51241
|
-
blog: { icon: "newspaper", screenId: "himi_blog", title: "Blog", body: "Read, save and discuss the latest posts." },
|
|
51242
|
-
groups: { icon: "people", screenId: "himi_groups", title: "Groups", body: "Meet members and join the conversation." },
|
|
51243
|
-
portfolio: { icon: "photo", screenId: "himi_portfolio", title: "Portfolio", body: "A showcase of our work." },
|
|
51244
|
-
galleries: { icon: "image", screenId: "himi_galleries", title: "Galleries", body: "Browse our photo galleries." },
|
|
51245
|
-
videos: { icon: "play", screenId: "himi_videos", title: "Videos", body: "Watch our video channels." },
|
|
51246
|
-
podcasts: { icon: "microphone", screenId: "himi_podcasts", title: "Podcast", body: "Listen to our latest episodes." },
|
|
51247
|
-
programs: { icon: "layers", screenId: "himi_programs", title: "Programs", body: "Follow structured programs at your own pace." },
|
|
51248
|
-
reservations: { icon: "clock", screenId: "himi_reservations", title: "Reservations", body: "Your table reservations." },
|
|
51249
|
-
donations: { icon: "heart", screenId: "himi_donations", title: "Donate", body: "Support the causes we care about." },
|
|
51250
|
-
giftCards: { icon: "tag", screenId: "himi_gift_cards", title: "Gift Cards", body: "Your gift cards and balances." },
|
|
51251
|
-
coupons: { icon: "tag", screenId: "himi_coupons", title: "Offers", body: "Deals and coupons available to you." },
|
|
51252
|
-
loyalty: { icon: "star", screenId: "himi_loyalty", title: "Rewards", body: "Earn points and redeem them for rewards." },
|
|
51253
|
-
forms: { icon: "list", screenId: "himi_forms", title: "Forms", body: "Fill out our forms." },
|
|
51254
|
-
cms: { icon: "grid", screenId: "himi_cms", title: "Content", body: "Explore custom content published by this business." },
|
|
51255
|
-
members: { icon: "people", screenId: "himi_members", title: "Members", body: "Meet the people in this community." },
|
|
51256
|
-
forum: { icon: "chat", screenId: "himi_forum", title: "Forum", body: "Join the discussion with the community." },
|
|
51257
|
-
feed: { icon: "chat", screenId: "himi_feed", title: "Feed", body: "Share updates and react to the latest posts." },
|
|
51258
|
-
reviews: { icon: "star_fill", screenId: "himi_reviews", title: "Reviews", body: "What customers are saying." },
|
|
51259
|
-
inbox: { icon: "chat", screenId: "himi_inbox", title: "Inbox", body: "Your messages with us." },
|
|
51260
|
-
invoices: { icon: "doc", screenId: "himi_invoices", title: "Invoices", body: "Your billing history." },
|
|
51261
|
-
badges: { icon: "star", screenId: "himi_badges", title: "Badges", body: "Achievements you can earn." },
|
|
51262
|
-
notifications: { icon: "bell", screenId: "himi_notifications", title: "Notifications", body: "Your activity and updates." },
|
|
51263
|
-
notifsettings: { icon: "settings", screenId: "himi_notif_settings", title: "Notification Settings", body: "Choose what you hear about." }
|
|
51264
|
-
};
|
|
51265
|
-
EXPLORE_ORDER = [
|
|
51266
|
-
"store",
|
|
51267
|
-
"bookings",
|
|
51268
|
-
"restaurants",
|
|
51269
|
-
"events",
|
|
51270
|
-
"plans",
|
|
51271
|
-
"blog",
|
|
51272
|
-
"groups",
|
|
51273
|
-
"portfolio",
|
|
51274
|
-
"galleries",
|
|
51275
|
-
"videos",
|
|
51276
|
-
"podcasts",
|
|
51277
|
-
"programs",
|
|
51278
|
-
"reservations",
|
|
51279
|
-
"donations",
|
|
51280
|
-
"giftCards",
|
|
51281
|
-
"coupons",
|
|
51282
|
-
"loyalty",
|
|
51283
|
-
"forms",
|
|
51284
|
-
"cms",
|
|
51285
|
-
"members",
|
|
51286
|
-
"forum",
|
|
51287
|
-
"feed",
|
|
51288
|
-
"reviews",
|
|
51289
|
-
"inbox",
|
|
51290
|
-
"invoices",
|
|
51291
|
-
"badges",
|
|
51292
|
-
"notifications",
|
|
51293
|
-
"notifsettings"
|
|
51294
|
-
];
|
|
51295
|
-
EXPLORE_MAX_CELLS = 8;
|
|
51296
|
-
MODULE_SOURCE_VERTICALS = {
|
|
51297
|
-
"member.bookings": ["bookings"],
|
|
51298
|
-
"member.bookings.schedule": ["bookings"],
|
|
51299
|
-
"device.saved_items": ["store", "blog"]
|
|
51300
|
-
};
|
|
51301
|
-
isKnown = (v) => KNOWN_VERTICALS.includes(v);
|
|
51302
|
-
GRID_VERTICAL_LABELS = /* @__PURE__ */ new Set([...KNOWN_VERTICALS, "faq"]);
|
|
51303
|
-
escapeRe2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
51304
|
-
textProps = (n) => n?.body?.props;
|
|
51305
|
-
STORE_SCREENS = /* @__PURE__ */ new Set([
|
|
51306
|
-
"himi_shop",
|
|
51307
|
-
"himi_saved_products",
|
|
51308
|
-
"himi_collections",
|
|
51309
|
-
"himi_collection",
|
|
51310
|
-
"himi_cart",
|
|
51311
|
-
"himi_orders"
|
|
51312
|
-
]);
|
|
51313
|
-
isStoreScreen = (id) => STORE_SCREENS.has(id) || /^himi_(?:product|order)[_/]/.test(id);
|
|
51314
|
-
isNode2 = (v) => !!v && typeof v === "object" && !!v.body && typeof v.body === "object";
|
|
51315
|
-
}
|
|
51316
|
-
});
|
|
51317
|
-
|
|
51318
52224
|
// src/site-analyze/apply.ts
|
|
51319
|
-
import { existsSync as
|
|
51320
|
-
import { dirname as
|
|
52225
|
+
import { existsSync as existsSync55, readFileSync as readFileSync65, writeFileSync as writeFileSync24, copyFileSync as copyFileSync3, mkdirSync as mkdirSync27, realpathSync as realpathSync5, statSync as statSync13 } from "node:fs";
|
|
52226
|
+
import { dirname as dirname31, isAbsolute as isAbsolute4, join as join52, resolve as resolve42, sep as sep11 } from "node:path";
|
|
51321
52227
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
51322
52228
|
function unpairedRedirectNote(overlay) {
|
|
51323
52229
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
@@ -51332,8 +52238,8 @@ function committedShellProvisioning(path2) {
|
|
|
51332
52238
|
function findRepoRoot(cwd) {
|
|
51333
52239
|
let dir = cwd;
|
|
51334
52240
|
for (let i = 0; i < 8; i++) {
|
|
51335
|
-
if (SHELL_NAMES2.some((name) =>
|
|
51336
|
-
const next =
|
|
52241
|
+
if (SHELL_NAMES2.some((name) => existsSync55(join52(dir, shellAppDir(name), "package.json")))) return dir;
|
|
52242
|
+
const next = dirname31(dir);
|
|
51337
52243
|
if (next === dir) break;
|
|
51338
52244
|
dir = next;
|
|
51339
52245
|
}
|
|
@@ -51400,11 +52306,11 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
51400
52306
|
}
|
|
51401
52307
|
function buildMergedContract(options) {
|
|
51402
52308
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
51403
|
-
const committedPath =
|
|
51404
|
-
if (!
|
|
52309
|
+
const committedPath = join52(appDir2, "provisioning.json");
|
|
52310
|
+
if (!existsSync55(committedPath)) {
|
|
51405
52311
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
51406
52312
|
}
|
|
51407
|
-
const committed = JSON.parse(
|
|
52313
|
+
const committed = JSON.parse(readFileSync65(committedPath, "utf8"));
|
|
51408
52314
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
51409
52315
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
51410
52316
|
const branding = merged.branding ?? {};
|
|
@@ -51416,8 +52322,8 @@ function buildMergedContract(options) {
|
|
|
51416
52322
|
};
|
|
51417
52323
|
const stage = (fromRel, toRel) => {
|
|
51418
52324
|
const from = contained(packageDir, fromRel);
|
|
51419
|
-
const to = contained(
|
|
51420
|
-
if (!from || !to || !
|
|
52325
|
+
const to = contained(join52(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
52326
|
+
if (!from || !to || !existsSync55(from)) return void 0;
|
|
51421
52327
|
let real;
|
|
51422
52328
|
let realRoot;
|
|
51423
52329
|
try {
|
|
@@ -51428,8 +52334,8 @@ function buildMergedContract(options) {
|
|
|
51428
52334
|
}
|
|
51429
52335
|
if (!real.startsWith(realRoot + sep11)) return void 0;
|
|
51430
52336
|
try {
|
|
51431
|
-
if (!
|
|
51432
|
-
|
|
52337
|
+
if (!statSync13(real).isFile()) return void 0;
|
|
52338
|
+
mkdirSync27(dirname31(to), { recursive: true });
|
|
51433
52339
|
copyFileSync3(real, to);
|
|
51434
52340
|
} catch {
|
|
51435
52341
|
return void 0;
|
|
@@ -51439,11 +52345,11 @@ function buildMergedContract(options) {
|
|
|
51439
52345
|
};
|
|
51440
52346
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
51441
52347
|
if (icon) branding.appIconPath = icon;
|
|
51442
|
-
const facesPath =
|
|
51443
|
-
if (
|
|
52348
|
+
const facesPath = join52(packageDir, "media/fonts/faces.json");
|
|
52349
|
+
if (existsSync55(facesPath)) {
|
|
51444
52350
|
let faces = [];
|
|
51445
52351
|
try {
|
|
51446
|
-
const parsed = JSON.parse(
|
|
52352
|
+
const parsed = JSON.parse(readFileSync65(facesPath, "utf8"));
|
|
51447
52353
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
51448
52354
|
} catch {
|
|
51449
52355
|
faces = [];
|
|
@@ -51464,11 +52370,11 @@ function buildMergedContract(options) {
|
|
|
51464
52370
|
merged.branding = branding;
|
|
51465
52371
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
51466
52372
|
`;
|
|
51467
|
-
const path2 =
|
|
51468
|
-
|
|
51469
|
-
const localPath =
|
|
51470
|
-
|
|
51471
|
-
|
|
52373
|
+
const path2 = join52(packageDir, "provisioning.contract.json");
|
|
52374
|
+
writeFileSync24(path2, body);
|
|
52375
|
+
const localPath = join52(appDir2, LOCAL_CONTRACT_REL);
|
|
52376
|
+
mkdirSync27(dirname31(localPath), { recursive: true });
|
|
52377
|
+
writeFileSync24(localPath, body);
|
|
51472
52378
|
staged.push(localPath);
|
|
51473
52379
|
return { path: path2, staged };
|
|
51474
52380
|
}
|
|
@@ -51476,8 +52382,8 @@ async function applyOverlays(input) {
|
|
|
51476
52382
|
const cwd = resolve42(input.cwd);
|
|
51477
52383
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
51478
52384
|
assertKnownShell(shell);
|
|
51479
|
-
const overlay = JSON.parse(
|
|
51480
|
-
const tokens = JSON.parse(
|
|
52385
|
+
const overlay = JSON.parse(readFileSync65(input.overlayPath, "utf8"));
|
|
52386
|
+
const tokens = JSON.parse(readFileSync65(input.tokensPath, "utf8"));
|
|
51481
52387
|
const wrote = [];
|
|
51482
52388
|
const notes = [];
|
|
51483
52389
|
const repoRoot2 = findRepoRoot(cwd);
|
|
@@ -51487,8 +52393,8 @@ async function applyOverlays(input) {
|
|
|
51487
52393
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
51488
52394
|
);
|
|
51489
52395
|
}
|
|
51490
|
-
const appDir2 =
|
|
51491
|
-
const packageDir =
|
|
52396
|
+
const appDir2 = join52(repoRoot2, shellAppDir(shell));
|
|
52397
|
+
const packageDir = dirname31(resolve42(input.overlayPath));
|
|
51492
52398
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
51493
52399
|
wrote.push(...staged);
|
|
51494
52400
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -51509,32 +52415,32 @@ async function applyOverlays(input) {
|
|
|
51509
52415
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
51510
52416
|
};
|
|
51511
52417
|
}
|
|
51512
|
-
const pkgProv =
|
|
52418
|
+
const pkgProv = join52(cwd, "provisioning.json");
|
|
51513
52419
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
51514
|
-
if (
|
|
51515
|
-
const cur = JSON.parse(
|
|
52420
|
+
if (existsSync55(pkgProv)) {
|
|
52421
|
+
const cur = JSON.parse(readFileSync65(pkgProv, "utf8"));
|
|
51516
52422
|
const merged = deepMerge4(cur, overlay);
|
|
51517
|
-
|
|
52423
|
+
writeFileSync24(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
51518
52424
|
wrote.push(pkgProv);
|
|
51519
52425
|
} else {
|
|
51520
|
-
|
|
52426
|
+
writeFileSync24(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
51521
52427
|
wrote.push(pkgProv);
|
|
51522
52428
|
}
|
|
51523
|
-
const pkgTokens =
|
|
51524
|
-
if (
|
|
51525
|
-
const cur = JSON.parse(
|
|
52429
|
+
const pkgTokens = join52(cwd, "tokens.json");
|
|
52430
|
+
if (existsSync55(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
52431
|
+
const cur = JSON.parse(readFileSync65(pkgTokens, "utf8"));
|
|
51526
52432
|
const merged = deepMerge4(cur, tokens);
|
|
51527
52433
|
const mergedColors = merged.colors;
|
|
51528
52434
|
if (mergedColors && typeof mergedColors === "object" && !Array.isArray(mergedColors)) {
|
|
51529
52435
|
merged.colors = alignAccentsToSurfaces(mergedColors, tokens.colors);
|
|
51530
52436
|
}
|
|
51531
|
-
|
|
52437
|
+
writeFileSync24(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
51532
52438
|
wrote.push(pkgTokens);
|
|
51533
52439
|
}
|
|
51534
52440
|
const homeAction = homeRefreshActionId(shell);
|
|
51535
|
-
const homeSrc =
|
|
51536
|
-
if (homeAction &&
|
|
51537
|
-
const prev =
|
|
52441
|
+
const homeSrc = join52(cwd, "dev/index.ts");
|
|
52442
|
+
if (homeAction && existsSync55(homeSrc)) {
|
|
52443
|
+
const prev = readFileSync65(homeSrc, "utf8");
|
|
51538
52444
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
51539
52445
|
let next = patched.src;
|
|
51540
52446
|
if (!patched.foreign && overlay.installedVerticals?.length) {
|
|
@@ -51550,20 +52456,20 @@ async function applyOverlays(input) {
|
|
|
51550
52456
|
}
|
|
51551
52457
|
}
|
|
51552
52458
|
if (next !== prev) {
|
|
51553
|
-
|
|
52459
|
+
writeFileSync24(homeSrc, next);
|
|
51554
52460
|
wrote.push(homeSrc);
|
|
51555
52461
|
}
|
|
51556
52462
|
if (patched.unparsed) {
|
|
51557
52463
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
51558
52464
|
}
|
|
51559
52465
|
}
|
|
51560
|
-
if (!input.iconPath || !
|
|
51561
|
-
const book = input.iconPath ?
|
|
52466
|
+
if (!input.iconPath || !existsSync55(input.iconPath)) {
|
|
52467
|
+
const book = input.iconPath ? dirname31(dirname31(resolve42(input.iconPath))) : void 0;
|
|
51562
52468
|
notes.push(
|
|
51563
52469
|
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"
|
|
51564
52470
|
);
|
|
51565
52471
|
}
|
|
51566
|
-
if (input.iconPath &&
|
|
52472
|
+
if (input.iconPath && existsSync55(input.iconPath)) {
|
|
51567
52473
|
try {
|
|
51568
52474
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
51569
52475
|
wrote.push(...installed.wrote);
|
|
@@ -54547,8 +55453,8 @@ var init_dist = __esm({
|
|
|
54547
55453
|
* @param jsonString - A JSON string or object representing the deserialized cookies.
|
|
54548
55454
|
* @param store - The underlying store to persist the deserialized cookies into.
|
|
54549
55455
|
*/
|
|
54550
|
-
static fromJSON(
|
|
54551
|
-
return _CookieJar.deserializeSync(
|
|
55456
|
+
static fromJSON(jsonString2, store) {
|
|
55457
|
+
return _CookieJar.deserializeSync(jsonString2, store);
|
|
54552
55458
|
}
|
|
54553
55459
|
};
|
|
54554
55460
|
}
|
|
@@ -54577,29 +55483,29 @@ function ctasOf(texts) {
|
|
|
54577
55483
|
function copyFromEval(evaled) {
|
|
54578
55484
|
const sections = [];
|
|
54579
55485
|
for (const raw of evaled.sections ?? []) {
|
|
54580
|
-
const heading = copyOrDrop(raw?.heading,
|
|
55486
|
+
const heading = copyOrDrop(raw?.heading, CAP3.heading);
|
|
54581
55487
|
if (!heading) continue;
|
|
54582
|
-
const body = copyOrDrop(raw?.body,
|
|
55488
|
+
const body = copyOrDrop(raw?.body, CAP3.body);
|
|
54583
55489
|
sections.push(body ? { heading, body } : { heading });
|
|
54584
|
-
if (sections.length >=
|
|
55490
|
+
if (sections.length >= CAP3.sections) break;
|
|
54585
55491
|
}
|
|
54586
55492
|
const faq = [];
|
|
54587
55493
|
for (const raw of evaled.faq ?? []) {
|
|
54588
|
-
const q = copyOrDrop(raw?.q,
|
|
54589
|
-
const a = copyOrDrop(raw?.a,
|
|
55494
|
+
const q = copyOrDrop(raw?.q, CAP3.q);
|
|
55495
|
+
const a = copyOrDrop(raw?.a, CAP3.a);
|
|
54590
55496
|
if (q && a && q !== a) faq.push({ q, a });
|
|
54591
|
-
if (faq.length >=
|
|
55497
|
+
if (faq.length >= CAP3.faq) break;
|
|
54592
55498
|
}
|
|
54593
|
-
const ctaLabels = dedupe2((evaled.ctaLabels ?? []).map((c) => copyOrDrop(c,
|
|
55499
|
+
const ctaLabels = dedupe2((evaled.ctaLabels ?? []).map((c) => copyOrDrop(c, CAP3.cta)), CAP3.ctas);
|
|
54594
55500
|
const testimonials = dedupe2(
|
|
54595
|
-
(evaled.testimonials ?? []).map((t) => copyOrDrop(t,
|
|
54596
|
-
|
|
55501
|
+
(evaled.testimonials ?? []).map((t) => copyOrDrop(t, CAP3.testimonial)),
|
|
55502
|
+
CAP3.testimonials
|
|
54597
55503
|
);
|
|
54598
|
-
const about = copyOrDrop(evaled.about,
|
|
55504
|
+
const about = copyOrDrop(evaled.about, CAP3.about);
|
|
54599
55505
|
const meta = {};
|
|
54600
|
-
const description = copyOrDrop(evaled.meta?.description,
|
|
54601
|
-
const ogTitle = copyOrDrop(evaled.meta?.ogTitle,
|
|
54602
|
-
const ogDescription = copyOrDrop(evaled.meta?.ogDescription,
|
|
55506
|
+
const description = copyOrDrop(evaled.meta?.description, CAP3.meta);
|
|
55507
|
+
const ogTitle = copyOrDrop(evaled.meta?.ogTitle, CAP3.meta);
|
|
55508
|
+
const ogDescription = copyOrDrop(evaled.meta?.ogDescription, CAP3.meta);
|
|
54603
55509
|
if (description) meta.description = description;
|
|
54604
55510
|
if (ogTitle) meta.ogTitle = ogTitle;
|
|
54605
55511
|
if (ogDescription) meta.ogDescription = ogDescription;
|
|
@@ -54873,7 +55779,7 @@ async function createPlaywrightBrowser(load = () => import("playwright"), siteFe
|
|
|
54873
55779
|
};
|
|
54874
55780
|
return { port, screenshots, siteFetch, pin };
|
|
54875
55781
|
}
|
|
54876
|
-
var PLAYWRIGHT_HINT, PAGE_EVAL,
|
|
55782
|
+
var PLAYWRIGHT_HINT, PAGE_EVAL, CAP3, DOCUMENT_FETCH_TIMEOUT_MS, MAX_DOCUMENT_BYTES, SUBRESOURCE_PIN_TIMEOUT_MS, NON_NETWORK_SCHEMES, FORWARDED_REQUEST_HEADERS;
|
|
54877
55783
|
var init_crawl_look = __esm({
|
|
54878
55784
|
"src/site-analyze/crawl-look.ts"() {
|
|
54879
55785
|
init_dist();
|
|
@@ -55068,7 +55974,7 @@ var init_crawl_look = __esm({
|
|
|
55068
55974
|
} catch (e4) {}
|
|
55069
55975
|
return { wst, nav, headings, hero, imgs, hrefs, buttons, html, htmlLang, velo, sections, ctaLabels, faq, testimonials, about, meta };
|
|
55070
55976
|
})()`;
|
|
55071
|
-
|
|
55977
|
+
CAP3 = {
|
|
55072
55978
|
heading: 120,
|
|
55073
55979
|
body: 300,
|
|
55074
55980
|
cta: 80,
|
|
@@ -55717,7 +56623,7 @@ __export(cli_exports, {
|
|
|
55717
56623
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
55718
56624
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
55719
56625
|
});
|
|
55720
|
-
import { readFileSync as
|
|
56626
|
+
import { readFileSync as readFileSync66 } from "node:fs";
|
|
55721
56627
|
import { resolve as resolve43 } from "node:path";
|
|
55722
56628
|
function assetFetchFor(_opts) {
|
|
55723
56629
|
return pinnedFetch2;
|
|
@@ -55804,7 +56710,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
55804
56710
|
let source;
|
|
55805
56711
|
if (opts.sourcePath) {
|
|
55806
56712
|
const p = resolve43(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
55807
|
-
source =
|
|
56713
|
+
source = readFileSync66(p, "utf8");
|
|
55808
56714
|
}
|
|
55809
56715
|
let body;
|
|
55810
56716
|
if (opts.bodyRaw != null) {
|
|
@@ -55958,9 +56864,9 @@ var init_wix_account = __esm({
|
|
|
55958
56864
|
});
|
|
55959
56865
|
|
|
55960
56866
|
// src/wix-verticals.ts
|
|
55961
|
-
function resolveVerticals(
|
|
55962
|
-
if (!
|
|
55963
|
-
const names =
|
|
56867
|
+
function resolveVerticals(csv2) {
|
|
56868
|
+
if (!csv2) return [];
|
|
56869
|
+
const names = csv2.split(",").map((s) => s.trim()).filter(Boolean);
|
|
55964
56870
|
const out = [];
|
|
55965
56871
|
const seen = /* @__PURE__ */ new Set();
|
|
55966
56872
|
for (const name of names) {
|
|
@@ -56061,7 +56967,7 @@ __export(site_create_exports, {
|
|
|
56061
56967
|
runSiteList: () => runSiteList,
|
|
56062
56968
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
56063
56969
|
});
|
|
56064
|
-
import { existsSync as
|
|
56970
|
+
import { existsSync as existsSync56, readFileSync as readFileSync67, writeFileSync as writeFileSync25 } from "node:fs";
|
|
56065
56971
|
import { resolve as resolvePath2 } from "node:path";
|
|
56066
56972
|
function oauthClientName(projectName) {
|
|
56067
56973
|
return `${projectName} client`;
|
|
@@ -56210,7 +57116,7 @@ async function runSiteCreate(opts) {
|
|
|
56210
57116
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
56211
57117
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
56212
57118
|
}
|
|
56213
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
57119
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync56, readFileSync: readFileSync67, writeFileSync: writeFileSync25 }) {
|
|
56214
57120
|
const msid = binding2.siteId;
|
|
56215
57121
|
const path2 = resolvePath2(target);
|
|
56216
57122
|
const committed = committedShellProvisioning(path2);
|
|
@@ -56883,11 +57789,11 @@ var init_context = __esm({
|
|
|
56883
57789
|
});
|
|
56884
57790
|
|
|
56885
57791
|
// src/cli.ts
|
|
56886
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
57792
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync68, mkdirSync as mkdirSync28, writeFileSync as writeFileSync26, existsSync as existsSync57, rmSync as rmSync11, readdirSync as readdirSync26, statSync as statSync14, lstatSync as lstatSync6, accessSync, constants } from "node:fs";
|
|
56887
57793
|
import { execFile as execFile4, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn5 } from "node:child_process";
|
|
56888
57794
|
import { createHash as createHash24, randomUUID as randomUUID3 } from "node:crypto";
|
|
56889
57795
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
56890
|
-
import { join as
|
|
57796
|
+
import { join as join53, resolve as resolve44, relative as relative8, basename as basename12, dirname as dirname32 } from "node:path";
|
|
56891
57797
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
56892
57798
|
|
|
56893
57799
|
// ../serve-cli/src/client.ts
|
|
@@ -60165,8 +61071,8 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
|
|
|
60165
61071
|
var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
60166
61072
|
function embeddedTemplateCatalog() {
|
|
60167
61073
|
return availableTemplates().map((name) => {
|
|
60168
|
-
const path2 =
|
|
60169
|
-
const meta = JSON.parse(
|
|
61074
|
+
const path2 = join53(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
61075
|
+
const meta = JSON.parse(readFileSync68(path2, "utf8"));
|
|
60170
61076
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
60171
61077
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
60172
61078
|
}
|
|
@@ -60199,6 +61105,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
60199
61105
|
himi template prompt <name> print the prompt that starts an app from that template
|
|
60200
61106
|
himi template publish [--dir <app>] [--source-dir <dir>] [--name <n>] [--icon <png>] [--visibility public|unlisted]
|
|
60201
61107
|
publish an app AS a himi init --template on the serve plane
|
|
61108
|
+
himi template trim --keep <id,id,\u2026> [--content <dir>] [--links follow|drop] [--dry-run] [--force]
|
|
61109
|
+
cut a scaffolded template to the screens you keep (the home and
|
|
61110
|
+
any drawer body stay): removes the other screens, their navigation rows and
|
|
61111
|
+
unshared tier5-src workers, then proves it with validate --strict
|
|
61112
|
+
(rolled back on failure). Refuses when a kept screen links to a
|
|
61113
|
+
removed one \u2014 --links follow keeps those too, --links drop removes the taps
|
|
60202
61114
|
himi build [--content <dir>] [--binary] compile Tier-5 workers with esbuild
|
|
60203
61115
|
himi eject <auth|checkout|screens> [--content <dir>]
|
|
60204
61116
|
the ladder's escape hatch \u2014 copy a shared flow module's
|
|
@@ -60754,7 +61666,7 @@ WHAT A PATCH DOES NOT CARRY \u2014 all reported in the output, never silent
|
|
|
60754
61666
|
var COMMANDS = [
|
|
60755
61667
|
{ name: "captcha", summary: "create and store native CAPTCHA keys in Serve, or inspect setup status; customer setup verifies Wix site ownership; does not enable member CAPTCHA SDKs", required: "setup|status --app <app> [--content <dir>] [--site <msid>] [--ios-bundle-id <id>] [--android-package-name <id>] [--target <t>]" },
|
|
60756
61668
|
{ name: "init", summary: "scaffold a starter content package (OTA-only; no native shells). --template <t> starts from a full reference app (branded-lite = consumer storefront over a Wix site; owner-lite = owner CRUD/management) instead of the minimal counter; --templates lists bundled ones; --remote fetches the template off the serve plane (falls back to the bundled copy offline)", required: "<name> [--dir] [--template <t>] [--remote] | --templates" },
|
|
60757
|
-
{ name: "template", summary: "starter-template catalog + publishing. Every template is a SHOWCASE APP \u2014 a real published release you can open running before you start from it. `list` prints available templates with metadata (title/description/tags) plus each one's start prompt \u2014 pass --remote to include the serve-plane catalog so an agent can pick one; `prompt <name>` prints just that sentence for one template (the skill URL is the public door, or the plane named by --target/--serve-url); `publish` publishes an app AS a `himi init --template` (needs a himalaya.template.json; builds a previewable release + attaches the scaffold source; --source-dir overrides which tree becomes the source, --name sets the template name; bakes a launcher icon \u2014 --icon <png>, or the committed template-icons/<name>.png \u2014 and extracts accent/palette gallery meta from the scaffold's tokens.json; --visibility unlisted keeps it out of the /v1/templates catalog \u2014 templates default to public)", required: "list [--remote] | prompt <name> | publish [--dir <app>] [--source-dir <dir>] [--name <n>] [--icon <png>] [--visibility public|unlisted] [--target <t>]" },
|
|
61669
|
+
{ name: "template", summary: "starter-template catalog + publishing. Every template is a SHOWCASE APP \u2014 a real published release you can open running before you start from it. `list` prints available templates with metadata (title/description/tags) plus each one's start prompt \u2014 pass --remote to include the serve-plane catalog so an agent can pick one; `prompt <name>` prints just that sentence for one template (the skill URL is the public door, or the plane named by --target/--serve-url); `publish` publishes an app AS a `himi init --template` (needs a himalaya.template.json; builds a previewable release + attaches the scaffold source; --source-dir overrides which tree becomes the source, --name sets the template name; bakes a launcher icon \u2014 --icon <png>, or the committed template-icons/<name>.png \u2014 and extracts accent/palette gallery meta from the scaffold's tokens.json; --visibility unlisted keeps it out of the /v1/templates catalog \u2014 templates default to public); `trim --keep <ids>` cuts an app scaffolded from a template down to those screens (the home, and any screen the navigation pins such as a drawer body, always stays) \u2014 it deletes the other SCREENS/TEMPLATED entries whole, prunes navigation (linkableScreens, tabBar, drawer, deep links, surfaces) and drops tier5-src workers no kept screen uses, then runs validate --strict and rolls everything back if it fails (--force keeps it, --dry-run writes nothing). A kept screen that links to a removed one is refused unless --links follow (keep those too) or --links drop (remove the taps)", required: "list [--remote] | prompt <name> | publish [--dir <app>] [--source-dir <dir>] [--name <n>] [--icon <png>] [--visibility public|unlisted] [--target <t>] | trim --keep <id,id,\u2026> [--content <dir>] [--links follow|drop] [--dry-run] [--force]" },
|
|
60758
61670
|
{ name: "build", summary: "compile tier5-src/<name>/index.ts -> dist/bundles/<name>.bundle.js with esbuild (--binary = resolve published @himalaya/*); semantic TypeScript checking belongs to himi validate", required: "[--content <dir>] [--binary]" },
|
|
60759
61671
|
{ name: "functions", summary: "inspect/invoke server functions and operate durable jobs or schedules", required: "list|describe|openapi|invoke | jobs list|get|cancel|retry|dlq | schedule describe|invoke [--app <a>] [--environment preview|production] [--release <id>]" },
|
|
60760
61672
|
{ name: "eject", summary: "take ownership of a shared flow module (auth|checkout|screens): copies its source into tier5-src/_ejected/ and repoints this package's imports at the copy. The ladder's escape hatch \u2014 for when the factory options cannot express what you need. AFTER EJECTING, CENTRAL FIXES NO LONGER REACH THIS APP, including future corrections to the fail-closed entitlement and confirm-the-session rules. The floor is unaffected: credentials still go only through the native auth actions and money only through the cashier rail.", required: "<auth|checkout|screens> [--content <dir>]" },
|
|
@@ -60809,7 +61721,7 @@ var COMMANDS = [
|
|
|
60809
61721
|
];
|
|
60810
61722
|
function cliVersion() {
|
|
60811
61723
|
try {
|
|
60812
|
-
return JSON.parse(
|
|
61724
|
+
return JSON.parse(readFileSync68(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
60813
61725
|
} catch {
|
|
60814
61726
|
return "unknown";
|
|
60815
61727
|
}
|
|
@@ -60880,6 +61792,10 @@ async function scopedRegistryBefore(lookup2, deadline) {
|
|
|
60880
61792
|
cancel();
|
|
60881
61793
|
}
|
|
60882
61794
|
}
|
|
61795
|
+
function lookupOnce(lookup2) {
|
|
61796
|
+
let first;
|
|
61797
|
+
return (budgetMs) => first ??= Promise.resolve().then(() => lookup2(budgetMs));
|
|
61798
|
+
}
|
|
60883
61799
|
function registryCandidates(env, scoped) {
|
|
60884
61800
|
const ordered = [isTrustedRegistry(scoped) ? normalizeRegistry(scoped) : void 0, trustedConfiguredRegistry(env), PUBLIC_NPM_REGISTRY];
|
|
60885
61801
|
return [...new Set(ordered.filter((r) => r !== void 0))];
|
|
@@ -60923,7 +61839,7 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
60923
61839
|
}
|
|
60924
61840
|
function packageVersion(path2) {
|
|
60925
61841
|
try {
|
|
60926
|
-
const version2 = JSON.parse(
|
|
61842
|
+
const version2 = JSON.parse(readFileSync68(path2, "utf8")).version;
|
|
60927
61843
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
60928
61844
|
} catch {
|
|
60929
61845
|
return void 0;
|
|
@@ -60932,9 +61848,9 @@ function packageVersion(path2) {
|
|
|
60932
61848
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
60933
61849
|
let dir = resolve44(fromDir);
|
|
60934
61850
|
for (; ; ) {
|
|
60935
|
-
const version2 = packageVersion(
|
|
61851
|
+
const version2 = packageVersion(join53(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
60936
61852
|
if (version2) return { version: version2, source: "local" };
|
|
60937
|
-
const parent =
|
|
61853
|
+
const parent = dirname32(dir);
|
|
60938
61854
|
if (parent === dir) break;
|
|
60939
61855
|
dir = parent;
|
|
60940
61856
|
}
|
|
@@ -60942,7 +61858,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
60942
61858
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
60943
61859
|
try {
|
|
60944
61860
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
60945
|
-
const version2 = root ? packageVersion(
|
|
61861
|
+
const version2 = root ? packageVersion(join53(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
60946
61862
|
return version2 ? { version: version2, source: "global" } : {};
|
|
60947
61863
|
} catch {
|
|
60948
61864
|
return {};
|
|
@@ -60989,11 +61905,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
60989
61905
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
60990
61906
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
60991
61907
|
function updateCachePath(env = process.env) {
|
|
60992
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
61908
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join53(homedir7(), ".himalaya", "update-check.json");
|
|
60993
61909
|
}
|
|
60994
61910
|
function readUpdateCache(path2) {
|
|
60995
61911
|
try {
|
|
60996
|
-
const parsed = JSON.parse(
|
|
61912
|
+
const parsed = JSON.parse(readFileSync68(path2, "utf8"));
|
|
60997
61913
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
60998
61914
|
} catch {
|
|
60999
61915
|
return {};
|
|
@@ -61001,8 +61917,8 @@ function readUpdateCache(path2) {
|
|
|
61001
61917
|
}
|
|
61002
61918
|
function writeUpdateCache(path2, cache) {
|
|
61003
61919
|
try {
|
|
61004
|
-
|
|
61005
|
-
|
|
61920
|
+
mkdirSync28(dirname32(path2), { recursive: true, mode: 448 });
|
|
61921
|
+
writeFileSync26(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
61006
61922
|
} catch {
|
|
61007
61923
|
}
|
|
61008
61924
|
}
|
|
@@ -61061,12 +61977,12 @@ function createUpdateRunner(spawn6 = spawnSync5) {
|
|
|
61061
61977
|
},
|
|
61062
61978
|
installedVersion: () => {
|
|
61063
61979
|
const root = globalNodeModulesRoot();
|
|
61064
|
-
return root ? packageVersion(
|
|
61980
|
+
return root ? packageVersion(join53(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
61065
61981
|
},
|
|
61066
61982
|
reexec: (argv) => {
|
|
61067
61983
|
const root = globalNodeModulesRoot();
|
|
61068
|
-
const entry = root ?
|
|
61069
|
-
if (!entry || !
|
|
61984
|
+
const entry = root ? join53(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
61985
|
+
if (!entry || !existsSync57(entry)) return void 0;
|
|
61070
61986
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
61071
61987
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
61072
61988
|
stdio: "inherit",
|
|
@@ -61113,7 +62029,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
61113
62029
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
61114
62030
|
let content;
|
|
61115
62031
|
try {
|
|
61116
|
-
content =
|
|
62032
|
+
content = readFileSync68(path2, "utf8");
|
|
61117
62033
|
} catch {
|
|
61118
62034
|
continue;
|
|
61119
62035
|
}
|
|
@@ -61121,7 +62037,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
61121
62037
|
let since = stamped;
|
|
61122
62038
|
if (!Number.isFinite(since)) {
|
|
61123
62039
|
try {
|
|
61124
|
-
since =
|
|
62040
|
+
since = statSync14(path2).mtimeMs;
|
|
61125
62041
|
} catch {
|
|
61126
62042
|
continue;
|
|
61127
62043
|
}
|
|
@@ -61136,14 +62052,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
61136
62052
|
const mine = lockStamp(now);
|
|
61137
62053
|
const readLock = (path2) => {
|
|
61138
62054
|
try {
|
|
61139
|
-
return
|
|
62055
|
+
return readFileSync68(path2, "utf8");
|
|
61140
62056
|
} catch {
|
|
61141
62057
|
return void 0;
|
|
61142
62058
|
}
|
|
61143
62059
|
};
|
|
61144
62060
|
const tryCreate = (path2) => {
|
|
61145
62061
|
try {
|
|
61146
|
-
|
|
62062
|
+
writeFileSync26(path2, mine, { flag: "wx", mode: 384 });
|
|
61147
62063
|
return true;
|
|
61148
62064
|
} catch {
|
|
61149
62065
|
return false;
|
|
@@ -61151,13 +62067,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
61151
62067
|
};
|
|
61152
62068
|
const removeIfMine = (path2) => {
|
|
61153
62069
|
try {
|
|
61154
|
-
if (readLock(path2) === mine)
|
|
62070
|
+
if (readLock(path2) === mine) rmSync11(path2, { force: true });
|
|
61155
62071
|
} catch {
|
|
61156
62072
|
}
|
|
61157
62073
|
};
|
|
61158
62074
|
const release = () => removeIfMine(lockPath);
|
|
61159
62075
|
try {
|
|
61160
|
-
|
|
62076
|
+
mkdirSync28(dirname32(lockPath), { recursive: true, mode: 448 });
|
|
61161
62077
|
} catch {
|
|
61162
62078
|
return () => {
|
|
61163
62079
|
};
|
|
@@ -61174,7 +62090,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
61174
62090
|
hooks.underBreakLock?.();
|
|
61175
62091
|
if (current === void 0) return tryCreate(lockPath) ? release : void 0;
|
|
61176
62092
|
if (!isAbandoned(current)) return void 0;
|
|
61177
|
-
|
|
62093
|
+
rmSync11(lockPath, { force: true });
|
|
61178
62094
|
return tryCreate(lockPath) ? release : void 0;
|
|
61179
62095
|
} finally {
|
|
61180
62096
|
removeIfMine(breakPath);
|
|
@@ -61674,9 +62590,9 @@ function executableOnPath(name, env = process.env) {
|
|
|
61674
62590
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
61675
62591
|
for (const dir of entries) {
|
|
61676
62592
|
for (const suffix of suffixes) {
|
|
61677
|
-
const candidate =
|
|
62593
|
+
const candidate = join53(dir, `${name}${suffix}`);
|
|
61678
62594
|
try {
|
|
61679
|
-
if (!
|
|
62595
|
+
if (!statSync14(candidate).isFile()) continue;
|
|
61680
62596
|
if (process.platform !== "win32") accessSync(candidate, constants.X_OK);
|
|
61681
62597
|
return true;
|
|
61682
62598
|
} catch {
|
|
@@ -61783,7 +62699,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
61783
62699
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
61784
62700
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
61785
62701
|
const iosYmlPath = iosProjectYml2(app);
|
|
61786
|
-
const iosYml =
|
|
62702
|
+
const iosYml = existsSync57(iosYmlPath) ? readFileSync68(iosYmlPath, "utf8") : "";
|
|
61787
62703
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
61788
62704
|
if (!optedIn) {
|
|
61789
62705
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -61797,19 +62713,19 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
61797
62713
|
}
|
|
61798
62714
|
function readConfigSource(dir) {
|
|
61799
62715
|
try {
|
|
61800
|
-
return
|
|
62716
|
+
return readFileSync68(join53(dir, "config.ts"), "utf8");
|
|
61801
62717
|
} catch {
|
|
61802
62718
|
return null;
|
|
61803
62719
|
}
|
|
61804
62720
|
}
|
|
61805
62721
|
function writePngFile(path2, base64) {
|
|
61806
|
-
|
|
61807
|
-
|
|
62722
|
+
mkdirSync28(dirname32(path2), { recursive: true });
|
|
62723
|
+
writeFileSync26(path2, Buffer.from(base64, "base64"));
|
|
61808
62724
|
return path2;
|
|
61809
62725
|
}
|
|
61810
62726
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
61811
62727
|
const dir = resolve44(parentDir, name);
|
|
61812
|
-
if (
|
|
62728
|
+
if (existsSync57(join53(dir, "himalaya.content.json"))) {
|
|
61813
62729
|
throw new Error(`content package already exists at ${dir}`);
|
|
61814
62730
|
}
|
|
61815
62731
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -61852,11 +62768,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
61852
62768
|
function restoreDestinationIssue(dest, force) {
|
|
61853
62769
|
const link = symlinkDestinationIssue(dest);
|
|
61854
62770
|
if (link) return link;
|
|
61855
|
-
if (!
|
|
61856
|
-
if (!
|
|
62771
|
+
if (!existsSync57(dest)) return null;
|
|
62772
|
+
if (!statSync14(dest).isDirectory()) {
|
|
61857
62773
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
61858
62774
|
}
|
|
61859
|
-
if (
|
|
62775
|
+
if (readdirSync26(dest).length > 0 && !force) {
|
|
61860
62776
|
return {
|
|
61861
62777
|
error: `${dest} already exists and is not empty`,
|
|
61862
62778
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -61867,8 +62783,8 @@ function restoreDestinationIssue(dest, force) {
|
|
|
61867
62783
|
function isHimalayaMonorepoCheckout(start) {
|
|
61868
62784
|
let dir = resolve44(start);
|
|
61869
62785
|
for (; ; ) {
|
|
61870
|
-
if (
|
|
61871
|
-
const parent =
|
|
62786
|
+
if (existsSync57(join53(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync57(join53(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
62787
|
+
const parent = dirname32(dir);
|
|
61872
62788
|
if (parent === dir) return false;
|
|
61873
62789
|
dir = parent;
|
|
61874
62790
|
}
|
|
@@ -61910,7 +62826,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
61910
62826
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
61911
62827
|
);
|
|
61912
62828
|
const repoRoot2 = resolve44(fileURLToPath24(new URL("../../..", import.meta.url)));
|
|
61913
|
-
const root =
|
|
62829
|
+
const root = join53(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
61914
62830
|
const stillRunning = (pid) => {
|
|
61915
62831
|
try {
|
|
61916
62832
|
process.kill(pid, 0);
|
|
@@ -61920,25 +62836,25 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
61920
62836
|
}
|
|
61921
62837
|
};
|
|
61922
62838
|
try {
|
|
61923
|
-
for (const entry of
|
|
62839
|
+
for (const entry of readdirSync26(root, { withFileTypes: true })) {
|
|
61924
62840
|
if (!entry.isDirectory()) continue;
|
|
61925
62841
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
61926
62842
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
61927
|
-
|
|
62843
|
+
rmSync11(join53(root, entry.name), { recursive: true, force: true });
|
|
61928
62844
|
}
|
|
61929
62845
|
}
|
|
61930
62846
|
} catch {
|
|
61931
62847
|
}
|
|
61932
|
-
const dest =
|
|
61933
|
-
|
|
61934
|
-
|
|
62848
|
+
const dest = join53(root, `${slug}-${process.pid}`);
|
|
62849
|
+
rmSync11(dest, { recursive: true, force: true });
|
|
62850
|
+
mkdirSync28(dest, { recursive: true });
|
|
61935
62851
|
materializeSource(forBuild, displayName, dest, slug);
|
|
61936
62852
|
return dest;
|
|
61937
62853
|
}
|
|
61938
62854
|
async function appId(dir) {
|
|
61939
62855
|
try {
|
|
61940
|
-
const { readFileSync:
|
|
61941
|
-
const m = JSON.parse(
|
|
62856
|
+
const { readFileSync: readFileSync69 } = await import("node:fs");
|
|
62857
|
+
const m = JSON.parse(readFileSync69(join53(dir, "himalaya.content.json"), "utf8"));
|
|
61942
62858
|
if (m.name) return m.name;
|
|
61943
62859
|
} catch {
|
|
61944
62860
|
}
|
|
@@ -61946,8 +62862,8 @@ async function appId(dir) {
|
|
|
61946
62862
|
}
|
|
61947
62863
|
async function contentVisibility(dir) {
|
|
61948
62864
|
try {
|
|
61949
|
-
const { readFileSync:
|
|
61950
|
-
const m = JSON.parse(
|
|
62865
|
+
const { readFileSync: readFileSync69 } = await import("node:fs");
|
|
62866
|
+
const m = JSON.parse(readFileSync69(join53(dir, "himalaya.content.json"), "utf8"));
|
|
61951
62867
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
61952
62868
|
} catch {
|
|
61953
62869
|
}
|
|
@@ -62171,7 +63087,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
62171
63087
|
try {
|
|
62172
63088
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
62173
63089
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
62174
|
-
out = mkdtempSync4(
|
|
63090
|
+
out = mkdtempSync4(join53(tmpdir5(), "himi-ux-record-"));
|
|
62175
63091
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62176
63092
|
const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
62177
63093
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -62184,7 +63100,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
62184
63100
|
return null;
|
|
62185
63101
|
} finally {
|
|
62186
63102
|
if (out !== void 0) try {
|
|
62187
|
-
|
|
63103
|
+
rmSync11(out, { recursive: true, force: true });
|
|
62188
63104
|
} catch {
|
|
62189
63105
|
}
|
|
62190
63106
|
}
|
|
@@ -62338,7 +63254,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
62338
63254
|
}
|
|
62339
63255
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
62340
63256
|
try {
|
|
62341
|
-
|
|
63257
|
+
readdirSync26(outDir);
|
|
62342
63258
|
} catch {
|
|
62343
63259
|
return { families: void 0, source: "unbuilt" };
|
|
62344
63260
|
}
|
|
@@ -62349,7 +63265,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
62349
63265
|
let js;
|
|
62350
63266
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
62351
63267
|
try {
|
|
62352
|
-
js =
|
|
63268
|
+
js = readFileSync68(join53(outDir, candidate), "utf8");
|
|
62353
63269
|
break;
|
|
62354
63270
|
} catch {
|
|
62355
63271
|
}
|
|
@@ -62719,12 +63635,34 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62719
63635
|
print({ ok: true, templates: merged, remote: true });
|
|
62720
63636
|
return 0;
|
|
62721
63637
|
}
|
|
63638
|
+
if (sub === "trim") {
|
|
63639
|
+
const { runTemplateTrim: runTemplateTrim2 } = await Promise.resolve().then(() => (init_template_trim(), template_trim_exports));
|
|
63640
|
+
const outcome = await runTemplateTrim2(
|
|
63641
|
+
{ dir: contentDir(flags), keep: flags.keep, links: flags.links, dryRun: flags["dry-run"] === true, force: flags.force === true },
|
|
63642
|
+
{
|
|
63643
|
+
validate: async (dir) => {
|
|
63644
|
+
const out = [];
|
|
63645
|
+
const err = [];
|
|
63646
|
+
const code = await run(["validate", "--content", dir, "--strict"], { log: (l) => out.push(l), error: (l) => err.push(l) }, deps);
|
|
63647
|
+
let counts;
|
|
63648
|
+
try {
|
|
63649
|
+
counts = JSON.parse(out[out.length - 1] ?? "").counts;
|
|
63650
|
+
} catch {
|
|
63651
|
+
}
|
|
63652
|
+
return { code, counts, ...code !== 0 ? { tail: [...out, ...err].join("\n").slice(-4e3) } : {} };
|
|
63653
|
+
}
|
|
63654
|
+
}
|
|
63655
|
+
);
|
|
63656
|
+
if (outcome.code === 2) io.error(JSON.stringify(outcome.result));
|
|
63657
|
+
else print(outcome.result);
|
|
63658
|
+
return outcome.code;
|
|
63659
|
+
}
|
|
62722
63660
|
if (sub === "publish") {
|
|
62723
63661
|
const appDir2 = resolve44(str5(flags.dir) ?? process.cwd());
|
|
62724
63662
|
const sourceDir = resolve44(str5(flags["source-dir"]) ?? appDir2);
|
|
62725
63663
|
let meta;
|
|
62726
63664
|
try {
|
|
62727
|
-
meta = JSON.parse(
|
|
63665
|
+
meta = JSON.parse(readFileSync68(join53(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
62728
63666
|
} catch {
|
|
62729
63667
|
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>)` }));
|
|
62730
63668
|
return 2;
|
|
@@ -62734,7 +63672,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62734
63672
|
return 2;
|
|
62735
63673
|
}
|
|
62736
63674
|
try {
|
|
62737
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
63675
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync68(join53(sourceDir, "tokens.json"), "utf8")));
|
|
62738
63676
|
meta = { ...appearance, ...meta };
|
|
62739
63677
|
} catch {
|
|
62740
63678
|
}
|
|
@@ -62746,7 +63684,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62746
63684
|
const force = flags.force === true;
|
|
62747
63685
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
62748
63686
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
62749
|
-
const out = mkdtempSync4(
|
|
63687
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-template-"));
|
|
62750
63688
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62751
63689
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
62752
63690
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
@@ -62799,7 +63737,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62799
63737
|
let iconHash;
|
|
62800
63738
|
if (iconPath) {
|
|
62801
63739
|
try {
|
|
62802
|
-
const bytes2 =
|
|
63740
|
+
const bytes2 = readFileSync68(iconPath);
|
|
62803
63741
|
payload.icon = bytes2.toString("base64");
|
|
62804
63742
|
iconHash = createHash24("sha256").update(bytes2).digest("hex");
|
|
62805
63743
|
} catch {
|
|
@@ -62968,7 +63906,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62968
63906
|
});
|
|
62969
63907
|
return 0;
|
|
62970
63908
|
}
|
|
62971
|
-
io.error(JSON.stringify({ error: "template needs a subcommand", usage: "himi template list [--remote] | himi template prompt <name> | himi template publish [--dir <app>] [--source-dir <dir>] [--name <n>] [--icon <png>] [--target <t>]" }));
|
|
63909
|
+
io.error(JSON.stringify({ error: "template needs a subcommand", usage: "himi template list [--remote] | himi template prompt <name> | himi template publish [--dir <app>] [--source-dir <dir>] [--name <n>] [--icon <png>] [--target <t>] | himi template trim --keep <id,id,\u2026> [--content <dir>] [--links follow|drop] [--dry-run] [--force]" }));
|
|
62972
63910
|
return 2;
|
|
62973
63911
|
}
|
|
62974
63912
|
case "build": {
|
|
@@ -62995,12 +63933,12 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62995
63933
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
62996
63934
|
return 2;
|
|
62997
63935
|
}
|
|
62998
|
-
const { readdirSync:
|
|
63936
|
+
const { readdirSync: readdirSync27, existsSync: fileExists } = await import("node:fs");
|
|
62999
63937
|
const { join: pathJoin } = await import("node:path");
|
|
63000
63938
|
const targets = [];
|
|
63001
63939
|
const t5 = pathJoin(dir, "tier5-src");
|
|
63002
63940
|
if (fileExists(t5)) {
|
|
63003
|
-
for (const d of
|
|
63941
|
+
for (const d of readdirSync27(t5, { withFileTypes: true })) {
|
|
63004
63942
|
if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
|
|
63005
63943
|
}
|
|
63006
63944
|
}
|
|
@@ -63032,7 +63970,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63032
63970
|
const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
|
|
63033
63971
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
63034
63972
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
63035
|
-
const out = mkdtempSync4(
|
|
63973
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-validate-"));
|
|
63036
63974
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63037
63975
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63038
63976
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63069,7 +64007,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63069
64007
|
const path2 = dpxSessionTokenPath();
|
|
63070
64008
|
let raw;
|
|
63071
64009
|
try {
|
|
63072
|
-
raw =
|
|
64010
|
+
raw = readFileSync68(path2, "utf8");
|
|
63073
64011
|
} catch {
|
|
63074
64012
|
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`);
|
|
63075
64013
|
}
|
|
@@ -63239,7 +64177,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63239
64177
|
case "test": {
|
|
63240
64178
|
const dir = contentDir(flags);
|
|
63241
64179
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
63242
|
-
if (
|
|
64180
|
+
if (existsSync57(join53(dir, "functions"))) {
|
|
63243
64181
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
63244
64182
|
const loaded = await loadFunctionsApp2(dir);
|
|
63245
64183
|
const results = [];
|
|
@@ -63326,7 +64264,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63326
64264
|
}
|
|
63327
64265
|
}
|
|
63328
64266
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
63329
|
-
const out = mkdtempSync4(
|
|
64267
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-test-"));
|
|
63330
64268
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63331
64269
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63332
64270
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63371,7 +64309,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63371
64309
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
63372
64310
|
return 2;
|
|
63373
64311
|
}
|
|
63374
|
-
const sources = collectWorkerSources2(
|
|
64312
|
+
const sources = collectWorkerSources2(join53(dir, "tier5-src"), screen.bundleName);
|
|
63375
64313
|
if (!sources) {
|
|
63376
64314
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
63377
64315
|
return 2;
|
|
@@ -63532,7 +64470,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63532
64470
|
const sp = await runShotsPass2({
|
|
63533
64471
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
63534
64472
|
tokens: outcome.tokens,
|
|
63535
|
-
outDir:
|
|
64473
|
+
outDir: join53(dir, ".himi", "shots"),
|
|
63536
64474
|
width: 390,
|
|
63537
64475
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
63538
64476
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -63542,7 +64480,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63542
64480
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
63543
64481
|
renderPngBatch: renderPngBatch2,
|
|
63544
64482
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
63545
|
-
clearDir: (d) =>
|
|
64483
|
+
clearDir: (d) => rmSync11(d, { recursive: true, force: true })
|
|
63546
64484
|
}
|
|
63547
64485
|
});
|
|
63548
64486
|
writtenShots = sp.written;
|
|
@@ -63570,7 +64508,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63570
64508
|
releaseId: result.releaseId,
|
|
63571
64509
|
releasePayload: release,
|
|
63572
64510
|
descriptors: attestedDescriptors,
|
|
63573
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
64511
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join53(dir, ".himi", "shots", name)])),
|
|
63574
64512
|
coverage: {
|
|
63575
64513
|
screens: crawledScreens.size,
|
|
63576
64514
|
actionsDispatched: result.actions.exercised,
|
|
@@ -63659,7 +64597,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63659
64597
|
return 2;
|
|
63660
64598
|
}
|
|
63661
64599
|
try {
|
|
63662
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
64600
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync68(stateArg.replace(/^@/, ""), "utf8");
|
|
63663
64601
|
injectedState = JSON.parse(raw);
|
|
63664
64602
|
} catch (e) {
|
|
63665
64603
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -63674,7 +64612,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63674
64612
|
return 2;
|
|
63675
64613
|
}
|
|
63676
64614
|
try {
|
|
63677
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
64615
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync68(inputArg.replace(/^@/, ""), "utf8");
|
|
63678
64616
|
const parsed = JSON.parse(raw);
|
|
63679
64617
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
63680
64618
|
injectedInput = parsed;
|
|
@@ -63723,7 +64661,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63723
64661
|
}
|
|
63724
64662
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
63725
64663
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
63726
|
-
const out = mkdtempSync4(
|
|
64664
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-render-"));
|
|
63727
64665
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63728
64666
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63729
64667
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63739,7 +64677,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63739
64677
|
let attestationPngFile;
|
|
63740
64678
|
if (typeof flags.png === "string" && r.pngBase64) {
|
|
63741
64679
|
pngFile = writePngFile(str5(flags.png), r.pngBase64);
|
|
63742
|
-
attestationPngFile = writePngFile(
|
|
64680
|
+
attestationPngFile = writePngFile(join53(dir, ".himi", "shots", `${screenId}.png`), r.pngBase64);
|
|
63743
64681
|
}
|
|
63744
64682
|
if (renderWidth !== void 0 && r.renderable) {
|
|
63745
64683
|
recordRenderWidth(dir, {
|
|
@@ -64071,20 +65009,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64071
65009
|
io.error(JSON.stringify(linked));
|
|
64072
65010
|
return 1;
|
|
64073
65011
|
}
|
|
64074
|
-
if (
|
|
64075
|
-
if (!
|
|
65012
|
+
if (existsSync57(dest)) {
|
|
65013
|
+
if (!statSync14(dest).isDirectory()) {
|
|
64076
65014
|
io.error(JSON.stringify({
|
|
64077
65015
|
error: `${dest} exists and is not a directory`,
|
|
64078
65016
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
64079
65017
|
}));
|
|
64080
65018
|
return 1;
|
|
64081
65019
|
}
|
|
64082
|
-
const occupied =
|
|
65020
|
+
const occupied = readdirSync26(dest).length > 0;
|
|
64083
65021
|
if (occupied && !force) {
|
|
64084
65022
|
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" }));
|
|
64085
65023
|
return 1;
|
|
64086
65024
|
}
|
|
64087
|
-
if (replace && occupied && !
|
|
65025
|
+
if (replace && occupied && !existsSync57(join53(dest, "himalaya.content.json"))) {
|
|
64088
65026
|
io.error(JSON.stringify({
|
|
64089
65027
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
64090
65028
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -64223,7 +65161,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64223
65161
|
const force = flags.force === true;
|
|
64224
65162
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64225
65163
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
64226
|
-
const out = mkdtempSync4(
|
|
65164
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-push-"));
|
|
64227
65165
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64228
65166
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
64229
65167
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -64743,7 +65681,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64743
65681
|
}
|
|
64744
65682
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64745
65683
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
64746
|
-
const built = mkdtempSync4(
|
|
65684
|
+
const built = mkdtempSync4(join53(tmpdir5(), "himi-pack-"));
|
|
64747
65685
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64748
65686
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
64749
65687
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -64760,7 +65698,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64760
65698
|
...await navIssues2(dir, strict)
|
|
64761
65699
|
]);
|
|
64762
65700
|
if (hasErrors && !force) {
|
|
64763
|
-
|
|
65701
|
+
rmSync11(built, { recursive: true, force: true });
|
|
64764
65702
|
print({ ...report2, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
64765
65703
|
return 1;
|
|
64766
65704
|
}
|
|
@@ -64796,7 +65734,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64796
65734
|
io.error(JSON.stringify({ error: e.message }));
|
|
64797
65735
|
return 1;
|
|
64798
65736
|
} finally {
|
|
64799
|
-
|
|
65737
|
+
rmSync11(built, { recursive: true, force: true });
|
|
64800
65738
|
}
|
|
64801
65739
|
}
|
|
64802
65740
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -64946,7 +65884,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64946
65884
|
}));
|
|
64947
65885
|
return 1;
|
|
64948
65886
|
}
|
|
64949
|
-
const archive =
|
|
65887
|
+
const archive = readFileSync68(resolve44(file));
|
|
64950
65888
|
const result = await client2().createPackageShare({
|
|
64951
65889
|
app: opened.header.app,
|
|
64952
65890
|
releaseId: opened.header.releaseId,
|
|
@@ -64983,10 +65921,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64983
65921
|
const app = await appId(dir);
|
|
64984
65922
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64985
65923
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
64986
|
-
temp = mkdtempSync4(
|
|
65924
|
+
temp = mkdtempSync4(join53(tmpdir5(), "himi-run-build-"));
|
|
64987
65925
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64988
65926
|
await buildReleaseFromContent2(dir, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
|
|
64989
|
-
source =
|
|
65927
|
+
source = join53(temp, app);
|
|
64990
65928
|
}
|
|
64991
65929
|
const chromeArg = str5(flags.chrome) ?? "preview";
|
|
64992
65930
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -65049,7 +65987,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65049
65987
|
io.error(JSON.stringify({ error: e.message }));
|
|
65050
65988
|
return 1;
|
|
65051
65989
|
} finally {
|
|
65052
|
-
if (temp)
|
|
65990
|
+
if (temp) rmSync11(temp, { recursive: true, force: true });
|
|
65053
65991
|
}
|
|
65054
65992
|
}
|
|
65055
65993
|
case "preview": {
|
|
@@ -65590,7 +66528,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65590
66528
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
65591
66529
|
return 2;
|
|
65592
66530
|
}
|
|
65593
|
-
if (!
|
|
66531
|
+
if (!existsSync57(file)) {
|
|
65594
66532
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
65595
66533
|
return 2;
|
|
65596
66534
|
}
|
|
@@ -65646,7 +66584,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65646
66584
|
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."
|
|
65647
66585
|
};
|
|
65648
66586
|
if (kind === "tokens" || kind === "app-config") {
|
|
65649
|
-
const body =
|
|
66587
|
+
const body = readFileSync68(file, "utf8");
|
|
65650
66588
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
65651
66589
|
return runReleasePatch({
|
|
65652
66590
|
...common,
|
|
@@ -65661,7 +66599,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65661
66599
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
65662
66600
|
return 2;
|
|
65663
66601
|
}
|
|
65664
|
-
const descriptor =
|
|
66602
|
+
const descriptor = readFileSync68(file, "utf8");
|
|
65665
66603
|
try {
|
|
65666
66604
|
JSON.parse(descriptor);
|
|
65667
66605
|
} catch (e) {
|
|
@@ -65701,7 +66639,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65701
66639
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
65702
66640
|
});
|
|
65703
66641
|
}
|
|
65704
|
-
const bytes2 =
|
|
66642
|
+
const bytes2 = readFileSync68(file);
|
|
65705
66643
|
const sha = createHash24("sha256").update(bytes2).digest("hex");
|
|
65706
66644
|
const forScreens = (str5(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
65707
66645
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -65845,7 +66783,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65845
66783
|
}
|
|
65846
66784
|
let def;
|
|
65847
66785
|
try {
|
|
65848
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
66786
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync68(arg.slice(1), "utf8") : arg);
|
|
65849
66787
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
65850
66788
|
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}`] }));
|
|
65851
66789
|
return 2;
|
|
@@ -66309,7 +67247,7 @@ ${label2}`);
|
|
|
66309
67247
|
const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
66310
67248
|
{
|
|
66311
67249
|
const distDir = contentDir(flags);
|
|
66312
|
-
if (
|
|
67250
|
+
if (existsSync57(join53(distDir, "himalaya.content.json"))) {
|
|
66313
67251
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
66314
67252
|
const errors = issues.filter((i) => i.severity === "error");
|
|
66315
67253
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -66578,7 +67516,7 @@ ${label2}`);
|
|
|
66578
67516
|
const dpxPath = dpxSessionTokenPath();
|
|
66579
67517
|
let dpx;
|
|
66580
67518
|
try {
|
|
66581
|
-
dpx =
|
|
67519
|
+
dpx = readFileSync68(dpxPath, "utf8").trim();
|
|
66582
67520
|
} catch {
|
|
66583
67521
|
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` }));
|
|
66584
67522
|
return 1;
|
|
@@ -66825,9 +67763,10 @@ ${label2}`);
|
|
|
66825
67763
|
return 1;
|
|
66826
67764
|
}
|
|
66827
67765
|
try {
|
|
66828
|
-
const
|
|
67766
|
+
const deadline = Date.now() + UPDATE_EXPLICIT_BUDGET_MS;
|
|
67767
|
+
const scoped = lookupOnce(up.scopedRegistry ?? npmScopedWixRegistry);
|
|
66829
67768
|
const answered = await fetchCliPackument(up.fetchImpl ?? fetch, UPDATE_EXPLICIT_BUDGET_MS, env, scoped);
|
|
66830
|
-
const registry = answered?.registry ?? registryCandidates(env, await scoped
|
|
67769
|
+
const registry = answered?.registry ?? registryCandidates(env, await scopedRegistryBefore(scoped, deadline))[0];
|
|
66831
67770
|
if (answered?.latest && compareVersions2(answered.latest, before) <= 0) {
|
|
66832
67771
|
if (flags.json) print({ ok: true, running: before, installed: before, changed: false, registry, latest: answered.latest });
|
|
66833
67772
|
else io.log(`himi ${before} (unchanged \u2014 ${registry} has nothing newer; its latest is ${answered.latest})`);
|
|
@@ -66979,7 +67918,7 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
|
|
|
66979
67918
|
const path2 = dpxSessionTokenPath();
|
|
66980
67919
|
let raw;
|
|
66981
67920
|
try {
|
|
66982
|
-
raw =
|
|
67921
|
+
raw = readFileSync68(path2, "utf8");
|
|
66983
67922
|
} catch {
|
|
66984
67923
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
66985
67924
|
return 1;
|