@wix/himalaya-cli 0.1007.0 → 0.1009.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/cli.mjs +1846 -871
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/component-reference.json +2 -1
- package/guides/component-reference.md +8 -5
- 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
|
});
|
|
@@ -5343,6 +5344,7 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
5343
5344
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
5344
5345
|
var init_bindings = __esm({
|
|
5345
5346
|
"../../core/ts/src/bindings.ts"() {
|
|
5347
|
+
"use strict";
|
|
5346
5348
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
5347
5349
|
BINDING_SIGIL_RE = new RegExp(
|
|
5348
5350
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -8581,6 +8583,7 @@ var init_validate_descriptor_core = __esm({
|
|
|
8581
8583
|
action: "any",
|
|
8582
8584
|
cornerRadius: "number",
|
|
8583
8585
|
disabled: "boolean",
|
|
8586
|
+
disabledPath: "string",
|
|
8584
8587
|
fullWidth: "boolean",
|
|
8585
8588
|
iconOnly: "boolean",
|
|
8586
8589
|
leadingIcon: "string",
|
|
@@ -12015,11 +12018,11 @@ function facesFor(family, weights, catalog = loadCatalog()) {
|
|
|
12015
12018
|
}
|
|
12016
12019
|
function matchWeightCss(available, desired) {
|
|
12017
12020
|
if (available.length === 0) return void 0;
|
|
12018
|
-
const
|
|
12019
|
-
const upFrom = (n) =>
|
|
12020
|
-
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);
|
|
12021
12024
|
if (desired >= 400 && desired <= 500) {
|
|
12022
|
-
const within =
|
|
12025
|
+
const within = sorted2.find((w) => w >= desired && w <= 500);
|
|
12023
12026
|
return within ?? downFrom(desired) ?? upFrom(desired);
|
|
12024
12027
|
}
|
|
12025
12028
|
if (desired < 400) return downFrom(desired) ?? upFrom(desired);
|
|
@@ -16871,7 +16874,7 @@ function wixClientIdOf(appConfigJson) {
|
|
|
16871
16874
|
if (typeof clientId !== "string" || !clientId) return { error: "no_client_id" };
|
|
16872
16875
|
return { clientId };
|
|
16873
16876
|
}
|
|
16874
|
-
var WIX_API, ONE_APP_SESSION, OWNER_SCOPED_WIX_HOST, VisitorTokenCache, OWNER_REFRESH_MARGIN_MS, OwnerInstanceCache, OWNER_SITES_QUERY_PATH, OWNER_SITES_COUNT_PATH, OwnerSitesCache;
|
|
16877
|
+
var WIX_API, ONE_APP_SESSION, OWNER_SCOPED_WIX_HOST, VisitorTokenCache, OWNER_REFRESH_MARGIN_MS, OWNER_RENEW_MIN_AGE_MS, OWNER_MINT_TIMEOUT_MS, OwnerInstanceCache, OWNER_SITES_QUERY_PATH, OWNER_SITES_COUNT_PATH, OwnerSitesCache;
|
|
16875
16878
|
var init_wix_bridge = __esm({
|
|
16876
16879
|
"../../core/serve-runtime/src/wix-bridge.ts"() {
|
|
16877
16880
|
init_sha256();
|
|
@@ -16909,12 +16912,19 @@ var init_wix_bridge = __esm({
|
|
|
16909
16912
|
}
|
|
16910
16913
|
};
|
|
16911
16914
|
OWNER_REFRESH_MARGIN_MS = 6e4;
|
|
16915
|
+
OWNER_RENEW_MIN_AGE_MS = 5e3;
|
|
16916
|
+
OWNER_MINT_TIMEOUT_MS = 8e3;
|
|
16912
16917
|
OwnerInstanceCache = class {
|
|
16913
|
-
constructor(fetchImpl = fetch, ttlMs = 5 * 6e4) {
|
|
16918
|
+
constructor(fetchImpl = fetch, ttlMs = 5 * 6e4, mintTimeoutMs = OWNER_MINT_TIMEOUT_MS, elapsedClock = () => performance.now()) {
|
|
16914
16919
|
this.fetchImpl = fetchImpl;
|
|
16915
16920
|
this.ttlMs = ttlMs;
|
|
16921
|
+
this.mintTimeoutMs = mintTimeoutMs;
|
|
16922
|
+
this.elapsedClock = elapsedClock;
|
|
16916
16923
|
}
|
|
16917
16924
|
cache = /* @__PURE__ */ new Map();
|
|
16925
|
+
/** The one mint on its way per (business, session). Every caller, plain or renewing, joins it:
|
|
16926
|
+
* it started after whatever is cached was minted, so it is the fresh instance. */
|
|
16927
|
+
inflight = /* @__PURE__ */ new Map();
|
|
16918
16928
|
/** Keyed on the SESSION (`wixSession2`), not the whole cookie header: manage.wix.com's jar churns
|
|
16919
16929
|
* (analytics, experiments), and keying on all of it re-minted on nearly every call (#3044). A
|
|
16920
16930
|
* header with no session cookie falls back to itself — callers refuse that case before here. */
|
|
@@ -16926,28 +16936,62 @@ ${session}`);
|
|
|
16926
16936
|
async instance(msid, cookieHeader, now = Date.now()) {
|
|
16927
16937
|
return (await this.entry(msid, cookieHeader, now)).instance;
|
|
16928
16938
|
}
|
|
16929
|
-
/** The instance and the time this cache stops trusting it (#3044: the web host caches until then).
|
|
16930
|
-
|
|
16939
|
+
/** The instance and the time this cache stops trusting it (#3044: the web host caches until then).
|
|
16940
|
+
* `renew`: Wix refused the instance this cache handed out (the route's `renew=1`, #3140) — mint a
|
|
16941
|
+
* new one, unless the cached one is younger than OWNER_RENEW_MIN_AGE_MS or a mint is already on
|
|
16942
|
+
* its way, in which case that IS the new one. */
|
|
16943
|
+
async entry(msid, cookieHeader, now = Date.now(), opts = {}) {
|
|
16931
16944
|
const key2 = this.key(msid, cookieHeader);
|
|
16932
|
-
const
|
|
16945
|
+
const pending = this.inflight.get(key2);
|
|
16946
|
+
if (pending) return { ...await pending };
|
|
16947
|
+
let hit = this.cache.get(key2);
|
|
16948
|
+
if (opts.renew && hit && now - hit.mintedAt >= OWNER_RENEW_MIN_AGE_MS) hit = void 0;
|
|
16933
16949
|
if (hit && hit.expiresAt - OWNER_REFRESH_MARGIN_MS > now) return { instance: hit.instance, expiresAt: hit.expiresAt };
|
|
16934
|
-
const
|
|
16935
|
-
|
|
16936
|
-
|
|
16950
|
+
const mint = this.mint(key2, msid, cookieHeader, now).finally(() => this.inflight.delete(key2));
|
|
16951
|
+
this.inflight.set(key2, mint);
|
|
16952
|
+
return { ...await mint };
|
|
16953
|
+
}
|
|
16954
|
+
async mint(key2, msid, cookieHeader, now) {
|
|
16955
|
+
const startedAt = this.elapsedClock();
|
|
16956
|
+
const abort = new AbortController();
|
|
16957
|
+
let timer;
|
|
16958
|
+
const timedOut = new Promise((_, reject) => {
|
|
16959
|
+
timer = setTimeout(() => {
|
|
16960
|
+
abort.abort();
|
|
16961
|
+
reject(new Error(`owner mint timed out after ${this.mintTimeoutMs}ms`));
|
|
16962
|
+
}, this.mintTimeoutMs);
|
|
16937
16963
|
});
|
|
16938
|
-
const text4 = await res.text();
|
|
16939
|
-
let j = {};
|
|
16940
16964
|
try {
|
|
16941
|
-
|
|
16942
|
-
|
|
16965
|
+
const res = await Promise.race([
|
|
16966
|
+
this.fetchImpl(`${ONE_APP_SESSION}/${msid}/signed-instance?signed_instance_type=User`, {
|
|
16967
|
+
method: "GET",
|
|
16968
|
+
headers: { Cookie: cookieHeader },
|
|
16969
|
+
signal: abort.signal
|
|
16970
|
+
}),
|
|
16971
|
+
timedOut
|
|
16972
|
+
]);
|
|
16973
|
+
const text4 = await Promise.race([res.text(), timedOut]);
|
|
16974
|
+
let j = {};
|
|
16975
|
+
try {
|
|
16976
|
+
j = text4 ? JSON.parse(text4) : {};
|
|
16977
|
+
} catch {
|
|
16978
|
+
}
|
|
16979
|
+
if (res.status < 200 || res.status >= 300 || !j.signedInstance)
|
|
16980
|
+
throw new Error(`owner mint failed (${res.status})`);
|
|
16981
|
+
const elapsed = Math.max(0, this.elapsedClock() - startedAt);
|
|
16982
|
+
const mintedAt = now + elapsed;
|
|
16983
|
+
const entry = { instance: j.signedInstance, expiresAt: now + Math.floor(elapsed / 1e3) * 1e3 + this.ttlMs };
|
|
16984
|
+
this.cache.set(key2, { ...entry, mintedAt });
|
|
16985
|
+
return entry;
|
|
16986
|
+
} catch (e) {
|
|
16987
|
+
this.cache.delete(key2);
|
|
16988
|
+
throw e;
|
|
16989
|
+
} finally {
|
|
16990
|
+
clearTimeout(timer);
|
|
16943
16991
|
}
|
|
16944
|
-
if (res.status < 200 || res.status >= 300 || !j.signedInstance)
|
|
16945
|
-
throw new Error(`owner mint failed (${res.status})`);
|
|
16946
|
-
const entry = { instance: j.signedInstance, expiresAt: now + this.ttlMs };
|
|
16947
|
-
this.cache.set(key2, entry);
|
|
16948
|
-
return { ...entry };
|
|
16949
16992
|
}
|
|
16950
|
-
/** Drop a cached instance
|
|
16993
|
+
/** Drop a cached instance so the next call re-mints. The envelope owner branch's own 401 retry;
|
|
16994
|
+
* the route's `renew=1` goes through `entry(…, { renew: true })` instead. */
|
|
16951
16995
|
invalidate(msid, cookieHeader) {
|
|
16952
16996
|
this.cache.delete(this.key(msid, cookieHeader));
|
|
16953
16997
|
}
|
|
@@ -24036,7 +24080,7 @@ function daysForMode(anchor, mode, firstWeekday) {
|
|
|
24036
24080
|
return Array.from({ length: n }, (_, i) => new Date(anchor.getFullYear(), anchor.getMonth(), anchor.getDate() + i));
|
|
24037
24081
|
}
|
|
24038
24082
|
function packOverlaps(items) {
|
|
24039
|
-
const
|
|
24083
|
+
const sorted2 = [...items].sort((a, b) => a.startMin - b.startMin || a.endMin - b.endMin);
|
|
24040
24084
|
const result = [];
|
|
24041
24085
|
let cluster = [];
|
|
24042
24086
|
let clusterEnd = -Infinity;
|
|
@@ -24057,7 +24101,7 @@ function packOverlaps(items) {
|
|
|
24057
24101
|
cluster = [];
|
|
24058
24102
|
clusterEnd = -Infinity;
|
|
24059
24103
|
};
|
|
24060
|
-
for (const item of
|
|
24104
|
+
for (const item of sorted2) {
|
|
24061
24105
|
if (cluster.length && item.startMin >= clusterEnd) flush();
|
|
24062
24106
|
cluster.push(item);
|
|
24063
24107
|
clusterEnd = Math.max(clusterEnd, item.endMin);
|
|
@@ -26707,7 +26751,8 @@ var init_renderNode = __esm({
|
|
|
26707
26751
|
const primary = buttonStyle === "primary" || destructive;
|
|
26708
26752
|
const outlined = buttonStyle === "secondary";
|
|
26709
26753
|
const accent = destructive ? C("danger", "#E62214") : C("accentPrimary", "#116DFF");
|
|
26710
|
-
const
|
|
26754
|
+
const boundDisabled = useResolvedScalar(props.disabledPath, ctx);
|
|
26755
|
+
const disabled = props.disabled === true || props.loading === true || hiddenBool(boundDisabled);
|
|
26711
26756
|
const onClick = ctx.onAction && props.action && !disabled ? (e) => {
|
|
26712
26757
|
e?.stopPropagation?.();
|
|
26713
26758
|
ctx.onAction(resolveItemDeep2(props.action, ctx));
|
|
@@ -30546,9 +30591,9 @@ function freezeCaptured(def, widgetId, opts = {}) {
|
|
|
30546
30591
|
}
|
|
30547
30592
|
const raw = def.timeline.frames;
|
|
30548
30593
|
if (Array.isArray(raw) && raw.length) {
|
|
30549
|
-
const
|
|
30550
|
-
if (
|
|
30551
|
-
frames =
|
|
30594
|
+
const sorted2 = [...raw].filter((f) => f && typeof f.startsAt === "number" && f.component).sort((a, b) => a.startsAt - b.startsAt).slice(0, MAX_TIMELINE_FRAMES);
|
|
30595
|
+
if (sorted2.length) {
|
|
30596
|
+
frames = sorted2.map((f) => ({ startsAt: f.startsAt, payload: f.component }));
|
|
30552
30597
|
payload = frames[0].payload;
|
|
30553
30598
|
}
|
|
30554
30599
|
}
|
|
@@ -38552,16 +38597,16 @@ function pushSetupBodyBytes(body) {
|
|
|
38552
38597
|
return Buffer.byteLength(JSON.stringify(body), "utf8");
|
|
38553
38598
|
}
|
|
38554
38599
|
async function pushSetupRequest(options) {
|
|
38555
|
-
const
|
|
38556
|
-
if (!options.target.controlToken) return
|
|
38557
|
-
if (!options.wixToken) return
|
|
38558
|
-
if (credentialHostRefusal(options.target.control)) return
|
|
38559
|
-
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return
|
|
38600
|
+
const refuse4 = (error) => ({ ok: false, status: 0, body: null, error });
|
|
38601
|
+
if (!options.target.controlToken) return refuse4("control_token_required");
|
|
38602
|
+
if (!options.wixToken) return refuse4("wix_account_token_required");
|
|
38603
|
+
if (credentialHostRefusal(options.target.control)) return refuse4("insecure_target");
|
|
38604
|
+
if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse4("invalid_preview_tag");
|
|
38560
38605
|
const setup = options.operation === "setup";
|
|
38561
|
-
if (setup && !options.body) return
|
|
38562
|
-
if (!setup && (!options.query?.app || !options.query?.site)) return
|
|
38606
|
+
if (setup && !options.body) return refuse4("push_setup_body_required");
|
|
38607
|
+
if (!setup && (!options.query?.app || !options.query?.site)) return refuse4("push_setup_query_required");
|
|
38563
38608
|
if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
|
|
38564
|
-
return
|
|
38609
|
+
return refuse4("push_setup_body_too_large");
|
|
38565
38610
|
}
|
|
38566
38611
|
const base = options.target.control.replace(/\/+$/, "");
|
|
38567
38612
|
let path2 = "/v1/admin/push/setup";
|
|
@@ -39143,6 +39188,1285 @@ var init_notify_setup = __esm({
|
|
|
39143
39188
|
}
|
|
39144
39189
|
});
|
|
39145
39190
|
|
|
39191
|
+
// src/site-analyze/types.ts
|
|
39192
|
+
function isRedirectUri(value) {
|
|
39193
|
+
return /^[a-z][a-z0-9+.-]*:\/\/\S*$/i.test(value);
|
|
39194
|
+
}
|
|
39195
|
+
function assertRedirectUri(value) {
|
|
39196
|
+
const trimmed = value.trim();
|
|
39197
|
+
if (!isRedirectUri(trimmed)) {
|
|
39198
|
+
throw new Error(
|
|
39199
|
+
`--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\`.`
|
|
39200
|
+
);
|
|
39201
|
+
}
|
|
39202
|
+
return trimmed;
|
|
39203
|
+
}
|
|
39204
|
+
var BOOK_SCHEMA_VERSION, KNOWN_VERTICALS;
|
|
39205
|
+
var init_types2 = __esm({
|
|
39206
|
+
"src/site-analyze/types.ts"() {
|
|
39207
|
+
BOOK_SCHEMA_VERSION = 2;
|
|
39208
|
+
KNOWN_VERTICALS = [
|
|
39209
|
+
"store",
|
|
39210
|
+
"bookings",
|
|
39211
|
+
"restaurants",
|
|
39212
|
+
"programs",
|
|
39213
|
+
"plans",
|
|
39214
|
+
"feed",
|
|
39215
|
+
"members",
|
|
39216
|
+
"forum",
|
|
39217
|
+
"coupons",
|
|
39218
|
+
"notifications",
|
|
39219
|
+
"loyalty",
|
|
39220
|
+
"reviews",
|
|
39221
|
+
"portfolio",
|
|
39222
|
+
"reservations",
|
|
39223
|
+
"invoices",
|
|
39224
|
+
"badges",
|
|
39225
|
+
"notifsettings",
|
|
39226
|
+
"events",
|
|
39227
|
+
"blog",
|
|
39228
|
+
"groups",
|
|
39229
|
+
"cms",
|
|
39230
|
+
"donations",
|
|
39231
|
+
"giftCards",
|
|
39232
|
+
"videos",
|
|
39233
|
+
"podcasts",
|
|
39234
|
+
"forms",
|
|
39235
|
+
"galleries",
|
|
39236
|
+
"inbox"
|
|
39237
|
+
];
|
|
39238
|
+
}
|
|
39239
|
+
});
|
|
39240
|
+
|
|
39241
|
+
// src/site-analyze/home-descriptor.ts
|
|
39242
|
+
function objectEnd(src, open) {
|
|
39243
|
+
let depth = 0;
|
|
39244
|
+
let inString = false;
|
|
39245
|
+
for (let i = open; i < src.length; i += 1) {
|
|
39246
|
+
const c = src[i];
|
|
39247
|
+
if (inString) {
|
|
39248
|
+
if (c === "\\") i += 1;
|
|
39249
|
+
else if (c === '"') inString = false;
|
|
39250
|
+
continue;
|
|
39251
|
+
}
|
|
39252
|
+
if (c === '"') inString = true;
|
|
39253
|
+
else if (c === "{") depth += 1;
|
|
39254
|
+
else if (c === "}") {
|
|
39255
|
+
depth -= 1;
|
|
39256
|
+
if (depth === 0) return i + 1;
|
|
39257
|
+
}
|
|
39258
|
+
}
|
|
39259
|
+
return -1;
|
|
39260
|
+
}
|
|
39261
|
+
function hasScreen(src, screenId) {
|
|
39262
|
+
const id = escapeRe2(screenId);
|
|
39263
|
+
return new RegExp(`"${id}": \\{\\s*"screenId": "${id}"`).test(src);
|
|
39264
|
+
}
|
|
39265
|
+
function findNode(root, pred) {
|
|
39266
|
+
if (Array.isArray(root)) {
|
|
39267
|
+
for (const child of root) {
|
|
39268
|
+
const hit = findNode(child, pred);
|
|
39269
|
+
if (hit) return hit;
|
|
39270
|
+
}
|
|
39271
|
+
return void 0;
|
|
39272
|
+
}
|
|
39273
|
+
if (!root || typeof root !== "object") return void 0;
|
|
39274
|
+
const node = root;
|
|
39275
|
+
if (node.body && typeof node.body === "object" && pred(node)) return node;
|
|
39276
|
+
for (const value of Object.values(root)) {
|
|
39277
|
+
const hit = findNode(value, pred);
|
|
39278
|
+
if (hit) return hit;
|
|
39279
|
+
}
|
|
39280
|
+
return void 0;
|
|
39281
|
+
}
|
|
39282
|
+
function cloneCell(template, prefix, vertical, card) {
|
|
39283
|
+
const cell = structuredClone(template);
|
|
39284
|
+
const accent = findNode(cell, (n) => n.body?.type === "Icon" && textProps(n)?.tint === "accentPrimary");
|
|
39285
|
+
const title = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "bodyEmphasis");
|
|
39286
|
+
const body = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "footnote");
|
|
39287
|
+
if (!accent || !title || !body || !cell.modifiers) return void 0;
|
|
39288
|
+
const onTap = cell.modifiers.onTap;
|
|
39289
|
+
if (!onTap?.actionId) return void 0;
|
|
39290
|
+
textProps(accent).name = card.icon;
|
|
39291
|
+
textProps(title).text = card.title;
|
|
39292
|
+
textProps(body).text = card.body;
|
|
39293
|
+
cell.modifiers.onTap = { actionId: onTap.actionId, params: { screenId: card.screenId } };
|
|
39294
|
+
cell.id = `${prefix}.${vertical}`;
|
|
39295
|
+
cell.modifiers.accessibilityLabel = card.title;
|
|
39296
|
+
return cell;
|
|
39297
|
+
}
|
|
39298
|
+
function lineIndent(src, open) {
|
|
39299
|
+
return /^[ \t]*/.exec(src.slice(src.lastIndexOf("\n", open) + 1, open))[0];
|
|
39300
|
+
}
|
|
39301
|
+
function serializeAt(node, src, open) {
|
|
39302
|
+
const indent = lineIndent(src, open);
|
|
39303
|
+
return JSON.stringify(node, null, 2).split("\n").map((line, i) => i === 0 ? line : indent + line).join("\n");
|
|
39304
|
+
}
|
|
39305
|
+
function patchGrids(src, installed, patch) {
|
|
39306
|
+
const OPEN = /"id": "([A-Za-z_0-9]+(?:\.[A-Za-z_0-9]+)*\.verticals)"/g;
|
|
39307
|
+
let out = "";
|
|
39308
|
+
let cursor = 0;
|
|
39309
|
+
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
39310
|
+
const open = src.lastIndexOf("{", m.index);
|
|
39311
|
+
if (open < cursor) continue;
|
|
39312
|
+
const close = objectEnd(src, open);
|
|
39313
|
+
if (close < 0) continue;
|
|
39314
|
+
const blob = src.slice(open, close);
|
|
39315
|
+
let node;
|
|
39316
|
+
try {
|
|
39317
|
+
node = JSON.parse(blob);
|
|
39318
|
+
} catch {
|
|
39319
|
+
continue;
|
|
39320
|
+
}
|
|
39321
|
+
const items = node.body?.type === "Grid" ? node.body.props?.items : void 0;
|
|
39322
|
+
if (!Array.isArray(items) || !items.length) continue;
|
|
39323
|
+
const prefix = m[1].slice(0, -".verticals".length);
|
|
39324
|
+
const baked = /* @__PURE__ */ new Map();
|
|
39325
|
+
const foreignCells = [];
|
|
39326
|
+
for (const item of items) {
|
|
39327
|
+
const id = item.id;
|
|
39328
|
+
const legacy = item.modifiers?.accessibilityLabel;
|
|
39329
|
+
const claim = typeof id === "string" && id ? id : typeof legacy === "string" ? legacy : "";
|
|
39330
|
+
const vertical = claim.startsWith(`${prefix}.`) ? claim.slice(prefix.length + 1) : "";
|
|
39331
|
+
if (isKnown(vertical)) baked.set(vertical, item);
|
|
39332
|
+
else if (!GRID_VERTICAL_LABELS.has(vertical)) foreignCells.push(item);
|
|
39333
|
+
}
|
|
39334
|
+
const wanted = [];
|
|
39335
|
+
for (const vertical of EXPLORE_ORDER) {
|
|
39336
|
+
if (!installed.has(vertical)) continue;
|
|
39337
|
+
if (baked.has(vertical)) {
|
|
39338
|
+
wanted.push(vertical);
|
|
39339
|
+
continue;
|
|
39340
|
+
}
|
|
39341
|
+
const card = EXPLORE_CARDS[vertical];
|
|
39342
|
+
if (!hasScreen(src, card.screenId)) {
|
|
39343
|
+
patch.unreachable.push(vertical);
|
|
39344
|
+
continue;
|
|
39345
|
+
}
|
|
39346
|
+
wanted.push(vertical);
|
|
39347
|
+
}
|
|
39348
|
+
const shape = baked.values().next().value ?? items[0];
|
|
39349
|
+
const next = [...foreignCells];
|
|
39350
|
+
const cells = [];
|
|
39351
|
+
for (const vertical of wanted) {
|
|
39352
|
+
if (next.length >= EXPLORE_MAX_CELLS) break;
|
|
39353
|
+
const bakedCell = baked.get(vertical);
|
|
39354
|
+
if (bakedCell) {
|
|
39355
|
+
next.push(bakedCell);
|
|
39356
|
+
cells.push(vertical);
|
|
39357
|
+
continue;
|
|
39358
|
+
}
|
|
39359
|
+
const made = cloneCell(shape, prefix, vertical, EXPLORE_CARDS[vertical]);
|
|
39360
|
+
if (!made) {
|
|
39361
|
+
patch.unreachable.push(vertical);
|
|
39362
|
+
continue;
|
|
39363
|
+
}
|
|
39364
|
+
next.push(made);
|
|
39365
|
+
cells.push(vertical);
|
|
39366
|
+
patch.added.push(vertical);
|
|
39367
|
+
}
|
|
39368
|
+
if (!cells.length) continue;
|
|
39369
|
+
patch.cells = cells;
|
|
39370
|
+
node.body.props.items = next;
|
|
39371
|
+
out += src.slice(cursor, open) + serializeAt(node, src, open);
|
|
39372
|
+
cursor = close;
|
|
39373
|
+
OPEN.lastIndex = close;
|
|
39374
|
+
}
|
|
39375
|
+
return out + src.slice(cursor);
|
|
39376
|
+
}
|
|
39377
|
+
function patchHomeModules(src, verticals) {
|
|
39378
|
+
const patch = { src, cells: [], added: [], droppedModules: [], droppedCtas: [], unreachable: [] };
|
|
39379
|
+
const next = patchModules(src, new Set(verticals.filter(isKnown)), patch);
|
|
39380
|
+
return { src: next, droppedModules: patch.droppedModules };
|
|
39381
|
+
}
|
|
39382
|
+
function patchModules(src, installed, patch) {
|
|
39383
|
+
return src.replace(/"homeModules": "((?:[^"\\]|\\.)*)"/g, (whole, encoded2) => {
|
|
39384
|
+
let modules;
|
|
39385
|
+
try {
|
|
39386
|
+
const parsed = JSON.parse(JSON.parse(`"${encoded2}"`));
|
|
39387
|
+
if (!Array.isArray(parsed)) return whole;
|
|
39388
|
+
modules = parsed;
|
|
39389
|
+
} catch {
|
|
39390
|
+
return whole;
|
|
39391
|
+
}
|
|
39392
|
+
const kept = modules.filter((module) => {
|
|
39393
|
+
const source = module?.dataSource;
|
|
39394
|
+
if (typeof source !== "string") return true;
|
|
39395
|
+
const needs = MODULE_SOURCE_VERTICALS[source];
|
|
39396
|
+
return !needs || needs.some((vertical) => installed.has(vertical));
|
|
39397
|
+
});
|
|
39398
|
+
if (!kept.length || kept.length === modules.length) return whole;
|
|
39399
|
+
for (const module of modules) {
|
|
39400
|
+
if (!kept.includes(module) && typeof module?.id === "string") patch.droppedModules.push(module.id);
|
|
39401
|
+
}
|
|
39402
|
+
return `"homeModules": ${JSON.stringify(JSON.stringify(kept))}`;
|
|
39403
|
+
});
|
|
39404
|
+
}
|
|
39405
|
+
function homeScreenSpan(src, homeActionId) {
|
|
39406
|
+
const OPEN = screenDeclarations();
|
|
39407
|
+
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
39408
|
+
const open = src.indexOf("{", m.index);
|
|
39409
|
+
const close = objectEnd(src, open);
|
|
39410
|
+
if (close < 0) continue;
|
|
39411
|
+
if (src.slice(open, close).includes(`"actionId": "${homeActionId}"`)) return { open, close };
|
|
39412
|
+
OPEN.lastIndex = close;
|
|
39413
|
+
}
|
|
39414
|
+
return void 0;
|
|
39415
|
+
}
|
|
39416
|
+
function isDeadStoreCta(node) {
|
|
39417
|
+
if (node.body?.type !== "Button") return false;
|
|
39418
|
+
const action = node.body.props?.action;
|
|
39419
|
+
const screenId = action?.params?.screenId;
|
|
39420
|
+
return typeof screenId === "string" && isStoreScreen(screenId);
|
|
39421
|
+
}
|
|
39422
|
+
function pruneTree(root, isDead) {
|
|
39423
|
+
const dropped = [];
|
|
39424
|
+
if (!isNode2(root)) return { emptied: false, dropped };
|
|
39425
|
+
return { emptied: !pruneNode(root, dropped, isDead), dropped };
|
|
39426
|
+
}
|
|
39427
|
+
function pruneNode(node, dropped, isDead = isDeadStoreCta) {
|
|
39428
|
+
const props = node.body?.props;
|
|
39429
|
+
if (!props) return true;
|
|
39430
|
+
const lists = props.itemsPath ? ["children"] : ["children", "items"];
|
|
39431
|
+
for (const key2 of lists) {
|
|
39432
|
+
const list = props[key2];
|
|
39433
|
+
if (!Array.isArray(list) || !list.length) continue;
|
|
39434
|
+
const kept = list.filter((child) => {
|
|
39435
|
+
if (child && typeof child === "object" && isDead(child)) {
|
|
39436
|
+
dropped.push(typeof child.id === "string" && child.id ? child.id : "(unnamed CTA)");
|
|
39437
|
+
return false;
|
|
39438
|
+
}
|
|
39439
|
+
if (!isNode2(child)) return true;
|
|
39440
|
+
return pruneNode(child, dropped, isDead);
|
|
39441
|
+
});
|
|
39442
|
+
if (kept.length === list.length) continue;
|
|
39443
|
+
if (!kept.length) return false;
|
|
39444
|
+
props[key2] = kept;
|
|
39445
|
+
}
|
|
39446
|
+
for (const [key2, child] of Object.entries(props)) {
|
|
39447
|
+
if (lists.includes(key2)) continue;
|
|
39448
|
+
pruneWithin(child, dropped, isDead);
|
|
39449
|
+
}
|
|
39450
|
+
return true;
|
|
39451
|
+
}
|
|
39452
|
+
function pruneWithin(value, dropped, isDead) {
|
|
39453
|
+
if (Array.isArray(value)) {
|
|
39454
|
+
for (const child of value) pruneWithin(child, dropped, isDead);
|
|
39455
|
+
return;
|
|
39456
|
+
}
|
|
39457
|
+
if (!value || typeof value !== "object") return;
|
|
39458
|
+
if (isNode2(value)) {
|
|
39459
|
+
pruneNode(value, dropped, isDead);
|
|
39460
|
+
return;
|
|
39461
|
+
}
|
|
39462
|
+
for (const child of Object.values(value)) pruneWithin(child, dropped, isDead);
|
|
39463
|
+
}
|
|
39464
|
+
function patchStoreCtas(src, verticals, homeActionId) {
|
|
39465
|
+
if (verticals.includes("store")) return { src, dropped: [] };
|
|
39466
|
+
const span = homeScreenSpan(src, homeActionId);
|
|
39467
|
+
if (!span) return { src, dropped: [] };
|
|
39468
|
+
let screen;
|
|
39469
|
+
try {
|
|
39470
|
+
screen = JSON.parse(src.slice(span.open, span.close));
|
|
39471
|
+
} catch {
|
|
39472
|
+
return { src, dropped: [] };
|
|
39473
|
+
}
|
|
39474
|
+
if (!isNode2(screen.payload)) return { src, dropped: [] };
|
|
39475
|
+
const dropped = [];
|
|
39476
|
+
if (!pruneNode(screen.payload, dropped) || !dropped.length) return { src, dropped: [] };
|
|
39477
|
+
return {
|
|
39478
|
+
src: src.slice(0, span.open) + serializeAt(screen, src, span.open) + src.slice(span.close),
|
|
39479
|
+
dropped
|
|
39480
|
+
};
|
|
39481
|
+
}
|
|
39482
|
+
function patchHomeForVerticals(src, verticals, homeActionId) {
|
|
39483
|
+
const installed = new Set(verticals.filter(isKnown));
|
|
39484
|
+
const patch = { src, cells: [], added: [], droppedModules: [], droppedCtas: [], unreachable: [] };
|
|
39485
|
+
if (!installed.size) return patch;
|
|
39486
|
+
const ctas = patchStoreCtas(patchModules(patchGrids(src, installed, patch), installed, patch), [...installed], homeActionId);
|
|
39487
|
+
patch.src = ctas.src;
|
|
39488
|
+
patch.droppedCtas = ctas.dropped;
|
|
39489
|
+
return patch;
|
|
39490
|
+
}
|
|
39491
|
+
var EXPLORE_CARDS, EXPLORE_ORDER, EXPLORE_MAX_CELLS, MODULE_SOURCE_VERTICALS, isKnown, GRID_VERTICAL_LABELS, escapeRe2, textProps, STORE_SCREENS, isStoreScreen, screenDeclarations, isNode2;
|
|
39492
|
+
var init_home_descriptor = __esm({
|
|
39493
|
+
"src/site-analyze/home-descriptor.ts"() {
|
|
39494
|
+
init_types2();
|
|
39495
|
+
EXPLORE_CARDS = {
|
|
39496
|
+
store: { icon: "bag", screenId: "himi_shop", title: "Shop", body: "Browse products and manage your cart." },
|
|
39497
|
+
bookings: { icon: "calendar", screenId: "himi_services", title: "Book", body: "Find a service and choose a time." },
|
|
39498
|
+
restaurants: { icon: "grid", screenId: "himi_menu", title: "Food", body: "Browse the menu and reserve a table." },
|
|
39499
|
+
events: { icon: "calendar", screenId: "himi_events", title: "Events", body: "Discover events and RSVP." },
|
|
39500
|
+
plans: { icon: "star", screenId: "himi_plans", title: "Plans", body: "Compare membership plans and join." },
|
|
39501
|
+
blog: { icon: "newspaper", screenId: "himi_blog", title: "Blog", body: "Read, save and discuss the latest posts." },
|
|
39502
|
+
groups: { icon: "people", screenId: "himi_groups", title: "Groups", body: "Meet members and join the conversation." },
|
|
39503
|
+
portfolio: { icon: "photo", screenId: "himi_portfolio", title: "Portfolio", body: "A showcase of our work." },
|
|
39504
|
+
galleries: { icon: "image", screenId: "himi_galleries", title: "Galleries", body: "Browse our photo galleries." },
|
|
39505
|
+
videos: { icon: "play", screenId: "himi_videos", title: "Videos", body: "Watch our video channels." },
|
|
39506
|
+
podcasts: { icon: "microphone", screenId: "himi_podcasts", title: "Podcast", body: "Listen to our latest episodes." },
|
|
39507
|
+
programs: { icon: "layers", screenId: "himi_programs", title: "Programs", body: "Follow structured programs at your own pace." },
|
|
39508
|
+
reservations: { icon: "clock", screenId: "himi_reservations", title: "Reservations", body: "Your table reservations." },
|
|
39509
|
+
donations: { icon: "heart", screenId: "himi_donations", title: "Donate", body: "Support the causes we care about." },
|
|
39510
|
+
giftCards: { icon: "tag", screenId: "himi_gift_cards", title: "Gift Cards", body: "Your gift cards and balances." },
|
|
39511
|
+
coupons: { icon: "tag", screenId: "himi_coupons", title: "Offers", body: "Deals and coupons available to you." },
|
|
39512
|
+
loyalty: { icon: "star", screenId: "himi_loyalty", title: "Rewards", body: "Earn points and redeem them for rewards." },
|
|
39513
|
+
forms: { icon: "list", screenId: "himi_forms", title: "Forms", body: "Fill out our forms." },
|
|
39514
|
+
cms: { icon: "grid", screenId: "himi_cms", title: "Content", body: "Explore custom content published by this business." },
|
|
39515
|
+
members: { icon: "people", screenId: "himi_members", title: "Members", body: "Meet the people in this community." },
|
|
39516
|
+
forum: { icon: "chat", screenId: "himi_forum", title: "Forum", body: "Join the discussion with the community." },
|
|
39517
|
+
feed: { icon: "chat", screenId: "himi_feed", title: "Feed", body: "Share updates and react to the latest posts." },
|
|
39518
|
+
reviews: { icon: "star_fill", screenId: "himi_reviews", title: "Reviews", body: "What customers are saying." },
|
|
39519
|
+
inbox: { icon: "chat", screenId: "himi_inbox", title: "Inbox", body: "Your messages with us." },
|
|
39520
|
+
invoices: { icon: "doc", screenId: "himi_invoices", title: "Invoices", body: "Your billing history." },
|
|
39521
|
+
badges: { icon: "star", screenId: "himi_badges", title: "Badges", body: "Achievements you can earn." },
|
|
39522
|
+
notifications: { icon: "bell", screenId: "himi_notifications", title: "Notifications", body: "Your activity and updates." },
|
|
39523
|
+
notifsettings: { icon: "settings", screenId: "himi_notif_settings", title: "Notification Settings", body: "Choose what you hear about." }
|
|
39524
|
+
};
|
|
39525
|
+
EXPLORE_ORDER = [
|
|
39526
|
+
"store",
|
|
39527
|
+
"bookings",
|
|
39528
|
+
"restaurants",
|
|
39529
|
+
"events",
|
|
39530
|
+
"plans",
|
|
39531
|
+
"blog",
|
|
39532
|
+
"groups",
|
|
39533
|
+
"portfolio",
|
|
39534
|
+
"galleries",
|
|
39535
|
+
"videos",
|
|
39536
|
+
"podcasts",
|
|
39537
|
+
"programs",
|
|
39538
|
+
"reservations",
|
|
39539
|
+
"donations",
|
|
39540
|
+
"giftCards",
|
|
39541
|
+
"coupons",
|
|
39542
|
+
"loyalty",
|
|
39543
|
+
"forms",
|
|
39544
|
+
"cms",
|
|
39545
|
+
"members",
|
|
39546
|
+
"forum",
|
|
39547
|
+
"feed",
|
|
39548
|
+
"reviews",
|
|
39549
|
+
"inbox",
|
|
39550
|
+
"invoices",
|
|
39551
|
+
"badges",
|
|
39552
|
+
"notifications",
|
|
39553
|
+
"notifsettings"
|
|
39554
|
+
];
|
|
39555
|
+
EXPLORE_MAX_CELLS = 8;
|
|
39556
|
+
MODULE_SOURCE_VERTICALS = {
|
|
39557
|
+
"member.bookings": ["bookings"],
|
|
39558
|
+
"member.bookings.schedule": ["bookings"],
|
|
39559
|
+
"device.saved_items": ["store", "blog"]
|
|
39560
|
+
};
|
|
39561
|
+
isKnown = (v) => KNOWN_VERTICALS.includes(v);
|
|
39562
|
+
GRID_VERTICAL_LABELS = /* @__PURE__ */ new Set([...KNOWN_VERTICALS, "faq"]);
|
|
39563
|
+
escapeRe2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
39564
|
+
textProps = (n) => n?.body?.props;
|
|
39565
|
+
STORE_SCREENS = /* @__PURE__ */ new Set([
|
|
39566
|
+
"himi_shop",
|
|
39567
|
+
"himi_saved_products",
|
|
39568
|
+
"himi_collections",
|
|
39569
|
+
"himi_collection",
|
|
39570
|
+
"himi_cart",
|
|
39571
|
+
"himi_orders"
|
|
39572
|
+
]);
|
|
39573
|
+
isStoreScreen = (id) => STORE_SCREENS.has(id) || /^himi_(?:product|order)[_/]/.test(id);
|
|
39574
|
+
screenDeclarations = () => /"([A-Za-z_0-9]+)": \{\s*"screenId": "\1"/g;
|
|
39575
|
+
isNode2 = (v) => !!v && typeof v === "object" && !!v.body && typeof v.body === "object";
|
|
39576
|
+
}
|
|
39577
|
+
});
|
|
39578
|
+
|
|
39579
|
+
// src/template-trim.ts
|
|
39580
|
+
var template_trim_exports = {};
|
|
39581
|
+
__export(template_trim_exports, {
|
|
39582
|
+
TrimRefusal: () => TrimRefusal,
|
|
39583
|
+
leftoverNavRefs: () => leftoverNavRefs,
|
|
39584
|
+
linearSafePattern: () => linearSafePattern,
|
|
39585
|
+
parseApp: () => parseApp,
|
|
39586
|
+
planTrim: () => planTrim,
|
|
39587
|
+
routeMatcher: () => routeMatcher,
|
|
39588
|
+
runTemplateTrim: () => runTemplateTrim
|
|
39589
|
+
});
|
|
39590
|
+
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";
|
|
39591
|
+
import { dirname as dirname23, join as join36 } from "node:path";
|
|
39592
|
+
function routeMatcher(pattern) {
|
|
39593
|
+
const detail = /^\^([A-Za-z0-9_]+)\(\?:\[_\/\]\(\.\+\)\)\?\$$/.exec(pattern);
|
|
39594
|
+
if (detail) {
|
|
39595
|
+
const base = detail[1];
|
|
39596
|
+
return {
|
|
39597
|
+
// `.` never matches a newline, so neither does this.
|
|
39598
|
+
test: (id) => id === base || id.length > base.length + 1 && id.startsWith(base) && (id[base.length] === "_" || id[base.length] === "/") && !id.includes("\n", base.length + 1)
|
|
39599
|
+
};
|
|
39600
|
+
}
|
|
39601
|
+
const suffixed = /^\^([A-Za-z0-9_]+)\(\[A-Za-z0-9\]\{1,32\}\)\$$/.exec(pattern);
|
|
39602
|
+
if (suffixed) {
|
|
39603
|
+
const prefix = suffixed[1];
|
|
39604
|
+
return {
|
|
39605
|
+
test: (id) => {
|
|
39606
|
+
if (!id.startsWith(prefix)) return false;
|
|
39607
|
+
const rest = id.slice(prefix.length);
|
|
39608
|
+
return rest.length >= 1 && rest.length <= 32 && /^[A-Za-z0-9]+$/.test(rest);
|
|
39609
|
+
}
|
|
39610
|
+
};
|
|
39611
|
+
}
|
|
39612
|
+
if (!linearSafePattern(pattern)) return null;
|
|
39613
|
+
let re;
|
|
39614
|
+
try {
|
|
39615
|
+
re = new RegExp(pattern);
|
|
39616
|
+
} catch {
|
|
39617
|
+
return null;
|
|
39618
|
+
}
|
|
39619
|
+
return re;
|
|
39620
|
+
}
|
|
39621
|
+
function linearSafePattern(pattern) {
|
|
39622
|
+
return pattern.length <= 256 && SAFE_ROUTE_PATTERN.test(pattern);
|
|
39623
|
+
}
|
|
39624
|
+
function bundlesOf(block) {
|
|
39625
|
+
const out = /* @__PURE__ */ new Set();
|
|
39626
|
+
const walk2 = (v) => {
|
|
39627
|
+
if (Array.isArray(v)) return v.forEach(walk2);
|
|
39628
|
+
if (!v || typeof v !== "object") return;
|
|
39629
|
+
const lb = v.logicBundle;
|
|
39630
|
+
const name = bundleNameFromUrl(lb?.url);
|
|
39631
|
+
if (name) out.add(name);
|
|
39632
|
+
for (const child of Object.values(v)) walk2(child);
|
|
39633
|
+
};
|
|
39634
|
+
walk2(block);
|
|
39635
|
+
return [...out];
|
|
39636
|
+
}
|
|
39637
|
+
function parseJson(text4, what) {
|
|
39638
|
+
try {
|
|
39639
|
+
const value = JSON.parse(text4);
|
|
39640
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("not an object");
|
|
39641
|
+
return value;
|
|
39642
|
+
} catch (e) {
|
|
39643
|
+
throw new TrimRefusal(
|
|
39644
|
+
`${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\`)`
|
|
39645
|
+
);
|
|
39646
|
+
}
|
|
39647
|
+
}
|
|
39648
|
+
function jsonString(literal, what) {
|
|
39649
|
+
try {
|
|
39650
|
+
return JSON.parse(literal);
|
|
39651
|
+
} catch (e) {
|
|
39652
|
+
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\`)`);
|
|
39653
|
+
}
|
|
39654
|
+
}
|
|
39655
|
+
function bracketEnd(src, open) {
|
|
39656
|
+
let depth = 0;
|
|
39657
|
+
let inString = false;
|
|
39658
|
+
for (let i = open; i < src.length; i += 1) {
|
|
39659
|
+
const c = src[i];
|
|
39660
|
+
if (inString) {
|
|
39661
|
+
if (c === "\\") i += 1;
|
|
39662
|
+
else if (c === '"') inString = false;
|
|
39663
|
+
continue;
|
|
39664
|
+
}
|
|
39665
|
+
if (c === '"') inString = true;
|
|
39666
|
+
else if (c === "[" || c === "{") depth += 1;
|
|
39667
|
+
else if (c === "]" || c === "}") {
|
|
39668
|
+
depth -= 1;
|
|
39669
|
+
if (depth === 0) return i + 1;
|
|
39670
|
+
}
|
|
39671
|
+
}
|
|
39672
|
+
return -1;
|
|
39673
|
+
}
|
|
39674
|
+
function parseSubtree(config) {
|
|
39675
|
+
const KEY = /^[ \t]*["']?workerSubtreeScreens["']?[ \t]*:[ \t]*/gm;
|
|
39676
|
+
const hits = [...config.matchAll(KEY)];
|
|
39677
|
+
if (!hits.length) return void 0;
|
|
39678
|
+
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");
|
|
39679
|
+
const start = hits[0].index + hits[0][0].length;
|
|
39680
|
+
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';
|
|
39681
|
+
if (config[start] !== "[") throw new TrimRefusal(unreadable);
|
|
39682
|
+
const end = bracketEnd(config, start);
|
|
39683
|
+
if (end < 0) throw new TrimRefusal(unreadable);
|
|
39684
|
+
let value;
|
|
39685
|
+
try {
|
|
39686
|
+
value = JSON.parse(config.slice(start, end));
|
|
39687
|
+
} catch {
|
|
39688
|
+
throw new TrimRefusal(unreadable);
|
|
39689
|
+
}
|
|
39690
|
+
if (!Array.isArray(value)) throw new TrimRefusal(unreadable);
|
|
39691
|
+
return { start, end, value };
|
|
39692
|
+
}
|
|
39693
|
+
function parseApp(dev, config) {
|
|
39694
|
+
const SCREENS_ANCHOR = "const SCREENS = runtimeSetting({\n";
|
|
39695
|
+
const at = dev.indexOf(SCREENS_ANCHOR);
|
|
39696
|
+
if (at < 0) {
|
|
39697
|
+
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");
|
|
39698
|
+
}
|
|
39699
|
+
const routes = [];
|
|
39700
|
+
const exact = /* @__PURE__ */ new Map();
|
|
39701
|
+
let pos = at + SCREENS_ANCHOR.length;
|
|
39702
|
+
const ENTRY = / ("(?:[^"\\\n]|\\.)*"): \{/y;
|
|
39703
|
+
while (!dev.startsWith("})", pos)) {
|
|
39704
|
+
ENTRY.lastIndex = pos;
|
|
39705
|
+
const m = ENTRY.exec(dev);
|
|
39706
|
+
if (!m) throw new TrimRefusal(`dev/index.ts line ${lineOf(dev, pos)}: expected a \`"<screenId>": {\` entry of the SCREENS map`);
|
|
39707
|
+
const id = jsonString(m[1], `dev/index.ts line ${lineOf(dev, pos)}: the SCREENS key`);
|
|
39708
|
+
const open = pos + m[0].length - 1;
|
|
39709
|
+
const close = objectEnd(dev, open);
|
|
39710
|
+
if (close < 0 || dev.slice(close, close + 2) !== ",\n") {
|
|
39711
|
+
throw new TrimRefusal(`dev/index.ts: the SCREENS entry "${id}" does not end in \`},\` on its own line`);
|
|
39712
|
+
}
|
|
39713
|
+
const decl = screenDeclarations();
|
|
39714
|
+
decl.lastIndex = pos;
|
|
39715
|
+
const d = decl.exec(dev);
|
|
39716
|
+
if (!d || d.index !== pos + 2 || d[1] !== id) {
|
|
39717
|
+
throw new TrimRefusal(`dev/index.ts: the SCREENS entry "${id}" does not open with its own \`"screenId": "${id}"\``);
|
|
39718
|
+
}
|
|
39719
|
+
const block = parseJson(dev.slice(open, close), `the screen "${id}" in dev/index.ts`);
|
|
39720
|
+
const route = { kind: "screen", label: id, lineStart: pos, end: close + 2, open, close, block, bundles: bundlesOf(block) };
|
|
39721
|
+
routes.push(route);
|
|
39722
|
+
exact.set(id, route);
|
|
39723
|
+
pos = close + 2;
|
|
39724
|
+
}
|
|
39725
|
+
const tAt = dev.indexOf("const TEMPLATED");
|
|
39726
|
+
const tOpen = tAt < 0 ? -1 : dev.indexOf("= [\n", tAt);
|
|
39727
|
+
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");
|
|
39728
|
+
pos = tOpen + "= [\n".length;
|
|
39729
|
+
const templatedStart = pos;
|
|
39730
|
+
const templated = [];
|
|
39731
|
+
const TENTRY = / \{ pattern: ("(?:[^"\\\n]|\\.)*"), display: ("(?:[^"\\\n]|\\.)*"),/y;
|
|
39732
|
+
for (; ; ) {
|
|
39733
|
+
if (dev.startsWith("];", pos) || dev.startsWith("\n];", pos)) break;
|
|
39734
|
+
TENTRY.lastIndex = pos;
|
|
39735
|
+
const m = TENTRY.exec(dev);
|
|
39736
|
+
if (!m) throw new TrimRefusal(`dev/index.ts line ${lineOf(dev, pos)}: expected a \`{ pattern: \u2026, display: \u2026, template: {\u2026} },\` entry of TEMPLATED`);
|
|
39737
|
+
const pattern = jsonString(m[1], `dev/index.ts line ${lineOf(dev, pos)}: the TEMPLATED pattern`);
|
|
39738
|
+
const display = jsonString(m[2], `dev/index.ts line ${lineOf(dev, pos)}: the TEMPLATED display`);
|
|
39739
|
+
const lineEnd = dev.indexOf("\n", pos);
|
|
39740
|
+
const tk = dev.indexOf("template: {", pos);
|
|
39741
|
+
if (tk < 0 || tk > lineEnd) throw new TrimRefusal(`dev/index.ts: the templated route ${display} has no \`template: {\` on its first line`);
|
|
39742
|
+
const open = tk + "template: ".length;
|
|
39743
|
+
const close = objectEnd(dev, open);
|
|
39744
|
+
if (close < 0 || dev.slice(close, close + 4) !== " },\n") {
|
|
39745
|
+
throw new TrimRefusal(`dev/index.ts: the templated route ${display} does not end in \`} },\``);
|
|
39746
|
+
}
|
|
39747
|
+
const re = routeMatcher(pattern);
|
|
39748
|
+
if (!re) {
|
|
39749
|
+
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)`);
|
|
39750
|
+
}
|
|
39751
|
+
const block = parseJson(dev.slice(open, close), `the templated route ${display} in dev/index.ts`);
|
|
39752
|
+
const label2 = display.replace(/[[{].*$/, "").replace(/[_/]+$/, "") || display;
|
|
39753
|
+
const route = { kind: "templated", label: label2, lineStart: pos, end: close + 4, open, close, block, re, bundles: bundlesOf(block) };
|
|
39754
|
+
routes.push(route);
|
|
39755
|
+
templated.push(route);
|
|
39756
|
+
pos = close + 4;
|
|
39757
|
+
}
|
|
39758
|
+
const templatedRegion = [templatedStart, pos];
|
|
39759
|
+
const hm = /\n {2}homeScreenId: ("(?:[^"\\\n]|\\.)*"),\n/.exec(dev);
|
|
39760
|
+
if (!hm) throw new TrimRefusal('dev/index.ts has no `homeScreenId: "\u2026",` in its default export');
|
|
39761
|
+
const homeId = jsonString(hm[1], "dev/index.ts: homeScreenId");
|
|
39762
|
+
const home = exact.get(homeId);
|
|
39763
|
+
if (!home) throw new TrimRefusal(`dev/index.ts: homeScreenId "${homeId}" is not a screen in the SCREENS map`);
|
|
39764
|
+
const NAV_ANCHOR = "\n navigation: {";
|
|
39765
|
+
const nAt = config.indexOf(NAV_ANCHOR);
|
|
39766
|
+
if (nAt < 0) throw new TrimRefusal("config.ts has no `navigation: {` \u2014 trim rewrites navigation in the shape `himi init` writes");
|
|
39767
|
+
const nOpen = nAt + NAV_ANCHOR.length - 1;
|
|
39768
|
+
const nClose = objectEnd(config, nOpen);
|
|
39769
|
+
if (nClose < 0) throw new TrimRefusal("config.ts: the navigation object never closes");
|
|
39770
|
+
const navValue = parseJson(config.slice(nOpen, nClose), "config.ts navigation");
|
|
39771
|
+
const subtree = parseSubtree(config);
|
|
39772
|
+
return { dev, config, home, routes, exact, templated, templatedRegion, nav: { open: nOpen, close: nClose, value: navValue }, subtree };
|
|
39773
|
+
}
|
|
39774
|
+
function resolveIn(app, id) {
|
|
39775
|
+
return app.exact.get(id) ?? app.templated.find((r) => r.re.test(id));
|
|
39776
|
+
}
|
|
39777
|
+
function openTarget(action) {
|
|
39778
|
+
const a = action;
|
|
39779
|
+
return a?.actionId === "himi.open" && isStatic(a.params?.screenId) ? a.params.screenId : void 0;
|
|
39780
|
+
}
|
|
39781
|
+
function linksOf(route) {
|
|
39782
|
+
const out = [];
|
|
39783
|
+
const walk2 = (v, owner) => {
|
|
39784
|
+
if (Array.isArray(v)) return v.forEach((c) => walk2(c, owner));
|
|
39785
|
+
if (!v || typeof v !== "object") return;
|
|
39786
|
+
const here = typeof v.id === "string" ? entryLabel(v) : owner;
|
|
39787
|
+
const to = openTarget(v);
|
|
39788
|
+
if (to) out.push({ from: route, node: here, to });
|
|
39789
|
+
for (const child of Object.values(v)) walk2(child, here);
|
|
39790
|
+
};
|
|
39791
|
+
walk2(route.block, "(screen)");
|
|
39792
|
+
return out;
|
|
39793
|
+
}
|
|
39794
|
+
function tapTarget(entry) {
|
|
39795
|
+
const e = entry;
|
|
39796
|
+
for (const a of [e.action, e.onTap, e.modifiers?.onTap, e.body?.props?.action, e.body?.props?.onTap]) {
|
|
39797
|
+
const to = openTarget(a);
|
|
39798
|
+
if (to) return to;
|
|
39799
|
+
}
|
|
39800
|
+
return void 0;
|
|
39801
|
+
}
|
|
39802
|
+
function rowTemplateTarget(entry, removed) {
|
|
39803
|
+
if (!isNode3(entry)) return void 0;
|
|
39804
|
+
const props = entry.body.props;
|
|
39805
|
+
if (!props?.itemsPath || !Array.isArray(props.items)) return void 0;
|
|
39806
|
+
for (const row of props.items) {
|
|
39807
|
+
const to = tapTarget(row);
|
|
39808
|
+
if (to && removed(to)) return to;
|
|
39809
|
+
}
|
|
39810
|
+
return void 0;
|
|
39811
|
+
}
|
|
39812
|
+
function emptyDeadCases(root, isDead) {
|
|
39813
|
+
const out = [];
|
|
39814
|
+
const walk2 = (v) => {
|
|
39815
|
+
if (Array.isArray(v)) return v.forEach(walk2);
|
|
39816
|
+
if (!v || typeof v !== "object") return;
|
|
39817
|
+
for (const child of Object.values(v)) walk2(child);
|
|
39818
|
+
if (!isNode3(v) || v.body.type !== "FragmentSlot" || !Array.isArray(v.body.props?.cases)) return;
|
|
39819
|
+
for (const c of v.body.props.cases) {
|
|
39820
|
+
if (!isNode3(c.content) || !pruneTree(c.content, isDead).emptied) continue;
|
|
39821
|
+
const props = c.content.body.props ?? {};
|
|
39822
|
+
for (const key2 of props.itemsPath ? ["children"] : ["children", "items"]) {
|
|
39823
|
+
if (Array.isArray(props[key2]) && props[key2].length) props[key2] = [];
|
|
39824
|
+
}
|
|
39825
|
+
out.push({ id: String(c.id ?? ""), byModuleId: v.body.props.casePath === "$item.id" });
|
|
39826
|
+
}
|
|
39827
|
+
};
|
|
39828
|
+
walk2(root);
|
|
39829
|
+
return out;
|
|
39830
|
+
}
|
|
39831
|
+
function dropModules(block, ids) {
|
|
39832
|
+
const dropped = [];
|
|
39833
|
+
const walk2 = (v) => {
|
|
39834
|
+
if (Array.isArray(v)) return v.forEach(walk2);
|
|
39835
|
+
if (!v || typeof v !== "object") return;
|
|
39836
|
+
const rec = v;
|
|
39837
|
+
if (typeof rec.homeModules === "string") {
|
|
39838
|
+
try {
|
|
39839
|
+
const modules = JSON.parse(rec.homeModules);
|
|
39840
|
+
const kept = Array.isArray(modules) ? modules.filter((m) => !(typeof m?.id === "string" && ids.has(m.id))) : void 0;
|
|
39841
|
+
if (kept && kept.length && kept.length < modules.length) {
|
|
39842
|
+
for (const m of modules) if (!kept.includes(m)) dropped.push(String(m.id));
|
|
39843
|
+
rec.homeModules = JSON.stringify(kept);
|
|
39844
|
+
}
|
|
39845
|
+
} catch {
|
|
39846
|
+
}
|
|
39847
|
+
}
|
|
39848
|
+
for (const child of Object.values(rec)) walk2(child);
|
|
39849
|
+
};
|
|
39850
|
+
walk2(block);
|
|
39851
|
+
return dropped;
|
|
39852
|
+
}
|
|
39853
|
+
function pruneChrome(items, removed, ledger) {
|
|
39854
|
+
const gone = (item) => typeof item.screenId === "string" && removed(item.screenId);
|
|
39855
|
+
const groups = [{ rows: [] }];
|
|
39856
|
+
for (const item of items) {
|
|
39857
|
+
if (item.role === "section") groups.push({ header: item, rows: [] });
|
|
39858
|
+
else groups[groups.length - 1].rows.push(item);
|
|
39859
|
+
}
|
|
39860
|
+
const out = [];
|
|
39861
|
+
for (const g of groups) {
|
|
39862
|
+
const navigable = g.rows.filter((r) => typeof r.screenId === "string");
|
|
39863
|
+
const keptRows = g.rows.filter((r) => !gone(r));
|
|
39864
|
+
const emptied = !!g.header && navigable.length > 0 && !keptRows.some((r) => typeof r.screenId === "string");
|
|
39865
|
+
if (g.header && !emptied) out.push(g.header);
|
|
39866
|
+
for (const r of emptied ? [] : keptRows) out.push(r);
|
|
39867
|
+
}
|
|
39868
|
+
const keptSet = new Set(out);
|
|
39869
|
+
for (const item of items) if (!keptSet.has(item)) ledger.push(typeof item.id === "string" ? item.id : String(item.screenId ?? "(unnamed)"));
|
|
39870
|
+
return out;
|
|
39871
|
+
}
|
|
39872
|
+
function rewriteNav(nav, removed, homeId) {
|
|
39873
|
+
const next = structuredClone(nav);
|
|
39874
|
+
const report2 = { linkable: [], tabs: [], drawer: [], sidebar: [], deepLinkPatterns: [], topBarActions: [], headerActions: [], surfaceDestinations: [], appIconBadgeSources: [], reparented: [] };
|
|
39875
|
+
const tabItems = asItems(next.tabBar);
|
|
39876
|
+
const hadTabs = !!tabItems?.length;
|
|
39877
|
+
if (tabItems) next.tabBar.items = pruneChrome(tabItems, removed, report2.tabs);
|
|
39878
|
+
const drawerItems = asItems(next.drawer);
|
|
39879
|
+
if (drawerItems) next.drawer.items = pruneChrome(drawerItems, removed, report2.drawer);
|
|
39880
|
+
const sidebarItems = asItems(next.sidebar);
|
|
39881
|
+
if (sidebarItems) next.sidebar.items = pruneChrome(sidebarItems, removed, report2.sidebar);
|
|
39882
|
+
if (hadTabs && !asItems(next.tabBar).length) {
|
|
39883
|
+
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 });
|
|
39884
|
+
}
|
|
39885
|
+
const remainingRoots = [...asItems(next.tabBar) ?? [], ...asItems(next.sidebar) ?? []].filter((i) => i.role !== "section");
|
|
39886
|
+
const remainingRootIds = new Set(remainingRoots.map((i) => i.id).filter((id) => typeof id === "string"));
|
|
39887
|
+
const removedRootIds = /* @__PURE__ */ new Set([...report2.tabs, ...report2.sidebar]);
|
|
39888
|
+
if (Array.isArray(next.deepLinkPatterns)) {
|
|
39889
|
+
next.deepLinkPatterns = next.deepLinkPatterns.filter((p) => {
|
|
39890
|
+
const id = p?.params?.screenId ?? p?.screenId;
|
|
39891
|
+
if (typeof id === "string" && removed(id)) {
|
|
39892
|
+
report2.deepLinkPatterns.push(String(p.pattern ?? id));
|
|
39893
|
+
return false;
|
|
39894
|
+
}
|
|
39895
|
+
return true;
|
|
39896
|
+
});
|
|
39897
|
+
}
|
|
39898
|
+
for (const key2 of ["drawer", "sidebar"]) {
|
|
39899
|
+
const actions = next[key2]?.header?.actions;
|
|
39900
|
+
if (!Array.isArray(actions)) continue;
|
|
39901
|
+
next[key2].header.actions = actions.filter((a) => {
|
|
39902
|
+
if (!(typeof a?.screenId === "string" && removed(a.screenId))) return true;
|
|
39903
|
+
report2.headerActions.push(`${key2}:${String(a.icon ?? a.screenId)}`);
|
|
39904
|
+
return false;
|
|
39905
|
+
});
|
|
39906
|
+
}
|
|
39907
|
+
const topActions = next.topBarDefault?.actions;
|
|
39908
|
+
if (Array.isArray(topActions)) {
|
|
39909
|
+
next.topBarDefault.actions = topActions.filter((a) => {
|
|
39910
|
+
const to = openTarget(a?.onTap) ?? openTarget(a?.action);
|
|
39911
|
+
if (to && removed(to)) {
|
|
39912
|
+
report2.topBarActions.push(entryLabel(a));
|
|
39913
|
+
return false;
|
|
39914
|
+
}
|
|
39915
|
+
return true;
|
|
39916
|
+
});
|
|
39917
|
+
}
|
|
39918
|
+
if (next.surfaces && typeof next.surfaces === "object") {
|
|
39919
|
+
for (const [surface, cfg] of Object.entries(next.surfaces)) {
|
|
39920
|
+
if (!cfg || typeof cfg !== "object") continue;
|
|
39921
|
+
const goneDest = (id) => typeof id === "string" && !remainingRootIds.has(id) && (removedRootIds.has(id) || removed(id));
|
|
39922
|
+
const unmapped = /* @__PURE__ */ new Set();
|
|
39923
|
+
if (cfg.screenIds && typeof cfg.screenIds === "object") {
|
|
39924
|
+
for (const [dest, screenId] of Object.entries(cfg.screenIds)) {
|
|
39925
|
+
if (goneDest(dest) || typeof screenId === "string" && removed(screenId)) {
|
|
39926
|
+
delete cfg.screenIds[dest];
|
|
39927
|
+
report2.surfaceDestinations.push(`${surface}:${dest}`);
|
|
39928
|
+
if (!remainingRootIds.has(dest)) unmapped.add(dest);
|
|
39929
|
+
}
|
|
39930
|
+
}
|
|
39931
|
+
}
|
|
39932
|
+
if (Array.isArray(cfg.destinations)) {
|
|
39933
|
+
cfg.destinations = cfg.destinations.filter((id) => {
|
|
39934
|
+
const gone = goneDest(id) || typeof id === "string" && unmapped.has(id);
|
|
39935
|
+
if (!gone) return true;
|
|
39936
|
+
const entry = `${surface}:${String(id)}`;
|
|
39937
|
+
if (!report2.surfaceDestinations.includes(entry)) report2.surfaceDestinations.push(entry);
|
|
39938
|
+
return false;
|
|
39939
|
+
});
|
|
39940
|
+
}
|
|
39941
|
+
}
|
|
39942
|
+
}
|
|
39943
|
+
if (Array.isArray(next.appIconBadgeSources)) {
|
|
39944
|
+
const goneActions = new Set(report2.topBarActions);
|
|
39945
|
+
const idsOf = (items) => new Set((items ?? []).map((i) => i.id).filter((x) => typeof x === "string"));
|
|
39946
|
+
const removedTabs = new Set(report2.tabs);
|
|
39947
|
+
const removedDrawer = new Set(report2.drawer);
|
|
39948
|
+
const remainingTabIds = idsOf(asItems(next.tabBar));
|
|
39949
|
+
const remainingDrawerIds = idsOf(asItems(next.drawer));
|
|
39950
|
+
next.appIconBadgeSources = next.appIconBadgeSources.filter((s) => {
|
|
39951
|
+
if (typeof s !== "string") return true;
|
|
39952
|
+
const [kind, id] = [s.slice(0, s.indexOf(":")), s.slice(s.indexOf(":") + 1)];
|
|
39953
|
+
const gone = kind === "topBarAction" ? goneActions.has(id) : kind === "tab" ? removedTabs.has(id) && !remainingTabIds.has(id) : kind === "drawer" ? removedDrawer.has(id) && !remainingDrawerIds.has(id) : false;
|
|
39954
|
+
if (gone) report2.appIconBadgeSources.push(s);
|
|
39955
|
+
return !gone;
|
|
39956
|
+
});
|
|
39957
|
+
}
|
|
39958
|
+
if (Array.isArray(next.linkableScreens)) {
|
|
39959
|
+
const original = next.linkableScreens;
|
|
39960
|
+
const byId = /* @__PURE__ */ new Map();
|
|
39961
|
+
for (const l of original) if (typeof l.screenId === "string") byId.set(l.screenId, l);
|
|
39962
|
+
const kept = original.filter((l) => {
|
|
39963
|
+
if (typeof l.screenId === "string" && removed(l.screenId)) {
|
|
39964
|
+
report2.linkable.push(l.screenId);
|
|
39965
|
+
return false;
|
|
39966
|
+
}
|
|
39967
|
+
return true;
|
|
39968
|
+
});
|
|
39969
|
+
const keptById = /* @__PURE__ */ new Map();
|
|
39970
|
+
for (const l of kept) if (typeof l.screenId === "string") keptById.set(l.screenId, l);
|
|
39971
|
+
const newParent = (l) => {
|
|
39972
|
+
let p = typeof l.parentScreenId === "string" ? l.parentScreenId : "";
|
|
39973
|
+
const seen = /* @__PURE__ */ new Set();
|
|
39974
|
+
while (p && removed(p) && !seen.has(p)) {
|
|
39975
|
+
seen.add(p);
|
|
39976
|
+
const up = byId.get(p)?.parentScreenId;
|
|
39977
|
+
p = typeof up === "string" ? up : "";
|
|
39978
|
+
}
|
|
39979
|
+
return p;
|
|
39980
|
+
};
|
|
39981
|
+
const tabFor = (screenId) => {
|
|
39982
|
+
const own2 = remainingRoots.find((t) => t.screenId === screenId);
|
|
39983
|
+
return typeof own2?.id === "string" ? own2.id : void 0;
|
|
39984
|
+
};
|
|
39985
|
+
const homeTab = tabFor(homeId) ?? (typeof remainingRoots[0]?.id === "string" ? remainingRoots[0].id : "");
|
|
39986
|
+
const finalTab = /* @__PURE__ */ new Map();
|
|
39987
|
+
const resolveTab = (l, depth = 0) => {
|
|
39988
|
+
if (finalTab.has(l)) return finalTab.get(l);
|
|
39989
|
+
const current = typeof l.tabId === "string" ? l.tabId : "";
|
|
39990
|
+
let tab = current;
|
|
39991
|
+
if (current && removedRootIds.has(current) && !remainingRootIds.has(current)) {
|
|
39992
|
+
const parent = newParent(l);
|
|
39993
|
+
const pl = parent ? keptById.get(parent) : void 0;
|
|
39994
|
+
tab = pl && pl !== l && depth < 64 ? resolveTab(pl, depth + 1) : tabFor(String(l.screenId)) ?? homeTab;
|
|
39995
|
+
}
|
|
39996
|
+
finalTab.set(l, tab);
|
|
39997
|
+
return tab;
|
|
39998
|
+
};
|
|
39999
|
+
for (const l of kept) {
|
|
40000
|
+
const fromParent = typeof l.parentScreenId === "string" ? l.parentScreenId : "";
|
|
40001
|
+
const fromTab = typeof l.tabId === "string" ? l.tabId : "";
|
|
40002
|
+
const toParent = newParent(l);
|
|
40003
|
+
const toTab = resolveTab(l);
|
|
40004
|
+
if (toParent === fromParent && toTab === fromTab) continue;
|
|
40005
|
+
const entry = { screenId: String(l.screenId) };
|
|
40006
|
+
if (toParent !== fromParent) entry.parentScreenId = { from: fromParent, to: toParent };
|
|
40007
|
+
if (toTab !== fromTab) entry.tabId = { from: fromTab, to: toTab };
|
|
40008
|
+
report2.reparented.push(entry);
|
|
40009
|
+
}
|
|
40010
|
+
for (const l of kept) {
|
|
40011
|
+
if (typeof l.parentScreenId === "string") l.parentScreenId = newParent(l);
|
|
40012
|
+
if (typeof l.tabId === "string") l.tabId = resolveTab(l);
|
|
40013
|
+
}
|
|
40014
|
+
next.linkableScreens = kept;
|
|
40015
|
+
}
|
|
40016
|
+
return { nav: next, report: report2 };
|
|
40017
|
+
}
|
|
40018
|
+
function leftoverNavRefs(nav, removedIds) {
|
|
40019
|
+
const gone = new Set(removedIds);
|
|
40020
|
+
const out = [];
|
|
40021
|
+
const walk2 = (v, path2) => {
|
|
40022
|
+
if (Array.isArray(v)) return v.forEach((c, i) => walk2(c, `${path2}[${i}]`));
|
|
40023
|
+
if (!v || typeof v !== "object") return;
|
|
40024
|
+
for (const [k, child] of Object.entries(v)) {
|
|
40025
|
+
const here = path2 ? `${path2}.${k}` : k;
|
|
40026
|
+
if (NAV_SCREEN_KEYS.has(k) && typeof child === "string") {
|
|
40027
|
+
if (gone.has(child)) out.push(`${here}=${child}`);
|
|
40028
|
+
} else if (k === "screenIds" && child && typeof child === "object" && !Array.isArray(child)) {
|
|
40029
|
+
for (const [dest, id] of Object.entries(child)) if (typeof id === "string" && gone.has(id)) out.push(`${here}.${dest}=${id}`);
|
|
40030
|
+
} else walk2(child, here);
|
|
40031
|
+
}
|
|
40032
|
+
};
|
|
40033
|
+
walk2(nav, "");
|
|
40034
|
+
return out;
|
|
40035
|
+
}
|
|
40036
|
+
function navPinnedScreens(nav) {
|
|
40037
|
+
const out = [];
|
|
40038
|
+
const add = (v) => {
|
|
40039
|
+
if (isStatic(v)) out.push(v);
|
|
40040
|
+
};
|
|
40041
|
+
for (const key2 of ["drawer", "sidebar"]) {
|
|
40042
|
+
const block = nav[key2];
|
|
40043
|
+
if (!block || typeof block !== "object") continue;
|
|
40044
|
+
add(block.contentScreenId);
|
|
40045
|
+
add(block.header?.screenId);
|
|
40046
|
+
add(block.footer?.screenId);
|
|
40047
|
+
add(block.footer?.badgeScreenId);
|
|
40048
|
+
}
|
|
40049
|
+
return out;
|
|
40050
|
+
}
|
|
40051
|
+
function planTrim(src, keepIds, links) {
|
|
40052
|
+
const app = parseApp(src.dev, src.config);
|
|
40053
|
+
const kept = /* @__PURE__ */ new Set([app.home]);
|
|
40054
|
+
const unknown = [];
|
|
40055
|
+
for (const id of keepIds) {
|
|
40056
|
+
const hits = [];
|
|
40057
|
+
const ex = app.exact.get(id);
|
|
40058
|
+
if (ex) hits.push(ex);
|
|
40059
|
+
const base = app.templated.find((r) => r.label === id);
|
|
40060
|
+
if (base) hits.push(base);
|
|
40061
|
+
if (!hits.length) {
|
|
40062
|
+
const served = app.templated.find((r) => r.re.test(id));
|
|
40063
|
+
if (served) hits.push(served);
|
|
40064
|
+
}
|
|
40065
|
+
if (!hits.length) unknown.push(id);
|
|
40066
|
+
for (const r of hits) kept.add(r);
|
|
40067
|
+
}
|
|
40068
|
+
if (unknown.length) {
|
|
40069
|
+
throw new TrimRefusal(`unknown screen id${unknown.length > 1 ? "s" : ""} ${unknown.join(", ")} \u2014 --keep takes the ids this app serves`, {
|
|
40070
|
+
unknown,
|
|
40071
|
+
validIds: sorted(app.routes.map((r) => r.label))
|
|
40072
|
+
});
|
|
40073
|
+
}
|
|
40074
|
+
const explicit = new Set([...kept].filter((r) => r !== app.home || keepIds.includes(app.home.label)));
|
|
40075
|
+
const implicit = explicit.has(app.home) ? [] : [app.home];
|
|
40076
|
+
for (const id of navPinnedScreens(app.nav.value)) {
|
|
40077
|
+
const route = resolveIn(app, id);
|
|
40078
|
+
if (!route || kept.has(route)) continue;
|
|
40079
|
+
kept.add(route);
|
|
40080
|
+
implicit.push(route);
|
|
40081
|
+
}
|
|
40082
|
+
const follow = (seed2) => {
|
|
40083
|
+
const set = new Set(seed2);
|
|
40084
|
+
const added = [];
|
|
40085
|
+
const queue = app.routes.filter((r) => set.has(r));
|
|
40086
|
+
while (queue.length) {
|
|
40087
|
+
const r = queue.shift();
|
|
40088
|
+
for (const link of linksOf(r)) {
|
|
40089
|
+
const target = resolveIn(app, link.to);
|
|
40090
|
+
if (!target || set.has(target)) continue;
|
|
40091
|
+
set.add(target);
|
|
40092
|
+
added.push({ screen: r.label, node: link.node, to: target.label });
|
|
40093
|
+
queue.push(target);
|
|
40094
|
+
}
|
|
40095
|
+
}
|
|
40096
|
+
return { set, added };
|
|
40097
|
+
};
|
|
40098
|
+
let addedByLinks;
|
|
40099
|
+
if (links === "follow") {
|
|
40100
|
+
const closed = follow(kept);
|
|
40101
|
+
for (const r of closed.set) kept.add(r);
|
|
40102
|
+
addedByLinks = closed.added;
|
|
40103
|
+
}
|
|
40104
|
+
const isKept = (r) => !r || kept.has(r);
|
|
40105
|
+
const removedRoutes = app.routes.filter((r) => !kept.has(r));
|
|
40106
|
+
const keptRoutes = app.routes.filter((r) => kept.has(r));
|
|
40107
|
+
const removedTarget = (id) => !isKept(resolveIn(app, id));
|
|
40108
|
+
const dropped = [];
|
|
40109
|
+
const unremovable = [];
|
|
40110
|
+
const emptied = [];
|
|
40111
|
+
const emptiedCases = [];
|
|
40112
|
+
const caseModules = [];
|
|
40113
|
+
const edited = /* @__PURE__ */ new Map();
|
|
40114
|
+
for (const r of keptRoutes) {
|
|
40115
|
+
if (!linksOf(r).some((l) => removedTarget(l.to))) continue;
|
|
40116
|
+
const block = structuredClone(r.block);
|
|
40117
|
+
const isDead = (entry) => {
|
|
40118
|
+
const own2 = tapTarget(entry);
|
|
40119
|
+
const to = own2 && removedTarget(own2) ? own2 : rowTemplateTarget(entry, removedTarget);
|
|
40120
|
+
if (!to) return false;
|
|
40121
|
+
dropped.push({ screen: r.label, node: entryLabel(entry), to });
|
|
40122
|
+
return true;
|
|
40123
|
+
};
|
|
40124
|
+
const topBar = block.topBar;
|
|
40125
|
+
if (topBar && Array.isArray(topBar.actions)) topBar.actions = topBar.actions.filter((a) => !isDead(a));
|
|
40126
|
+
const cases = emptyDeadCases(block.payload, isDead);
|
|
40127
|
+
for (const c of cases) emptiedCases.push({ screen: r.label, case: c.id });
|
|
40128
|
+
if (pruneTree(block.payload, isDead).emptied) emptied.push(r.label);
|
|
40129
|
+
const moduleIds = new Set(cases.filter((c) => c.byModuleId).map((c) => c.id));
|
|
40130
|
+
if (moduleIds.size) caseModules.push(...dropModules(block, moduleIds));
|
|
40131
|
+
for (const l of linksOf({ ...r, block })) if (removedTarget(l.to)) unremovable.push({ screen: r.label, to: l.to });
|
|
40132
|
+
edited.set(r, block);
|
|
40133
|
+
}
|
|
40134
|
+
const followWouldAdd = sorted([...follow(kept).set].filter((r) => !kept.has(r)).map((r) => r.label));
|
|
40135
|
+
if (dropped.length || unremovable.length) {
|
|
40136
|
+
if (!links) {
|
|
40137
|
+
throw new TrimRefusal(`kept screens link to screens this trim would remove \u2014 choose what happens to those links with --links`, {
|
|
40138
|
+
droppedLinks: dropped,
|
|
40139
|
+
...emptiedCases.length ? { emptiedCases } : {},
|
|
40140
|
+
...unremovable.length ? { unremovable } : {},
|
|
40141
|
+
...emptied.length ? { dropWouldEmpty: emptied } : {},
|
|
40142
|
+
followWouldAdd,
|
|
40143
|
+
hint: `--links drop removes the ${dropped.length} tapping node(s) listed in droppedLinks; --links follow keeps ${followWouldAdd.join(", ")} as well`
|
|
40144
|
+
});
|
|
40145
|
+
}
|
|
40146
|
+
if (emptied.length) {
|
|
40147
|
+
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`, {
|
|
40148
|
+
dropWouldEmpty: emptied
|
|
40149
|
+
});
|
|
40150
|
+
}
|
|
40151
|
+
if (unremovable.length) {
|
|
40152
|
+
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`, {
|
|
40153
|
+
unremovable
|
|
40154
|
+
});
|
|
40155
|
+
}
|
|
40156
|
+
}
|
|
40157
|
+
const removedIds = sorted(removedRoutes.filter((r) => {
|
|
40158
|
+
const res = resolveIn(app, r.label);
|
|
40159
|
+
return !(res && kept.has(res));
|
|
40160
|
+
}).map((r) => r.label));
|
|
40161
|
+
const removedIdSet = new Set(removedIds);
|
|
40162
|
+
const navRemoved = (id) => removedTarget(id) || removedIdSet.has(id);
|
|
40163
|
+
const { nav, report: navReport } = rewriteNav(app.nav.value, navRemoved, app.home.label);
|
|
40164
|
+
const subtreeRemoved = [];
|
|
40165
|
+
const subtreeNext = app.subtree?.value.filter((id) => {
|
|
40166
|
+
if (typeof id !== "string" || id.includes("*") || !app.exact.get(id) || isKept(app.exact.get(id))) return true;
|
|
40167
|
+
subtreeRemoved.push(id);
|
|
40168
|
+
return false;
|
|
40169
|
+
});
|
|
40170
|
+
const configBundles = new Set([...src.config.matchAll(/\/v1\/bundles\/([A-Za-z0-9_-]+)/g)].map((m) => m[1]));
|
|
40171
|
+
const keptWorkers = /* @__PURE__ */ new Set(["_shared", ...configBundles]);
|
|
40172
|
+
for (const r of keptRoutes) for (const b of r.bundles) keptWorkers.add(b);
|
|
40173
|
+
const importsOf = (dir) => {
|
|
40174
|
+
const out = [];
|
|
40175
|
+
for (const [rel, text4] of Object.entries(src.workerFiles)) {
|
|
40176
|
+
if (!rel.startsWith(`tier5-src/${dir}/`)) continue;
|
|
40177
|
+
for (const m of text4.matchAll(/(?:\bfrom\s*|\bimport\s*\(?\s*|\brequire\s*\(\s*)["']\.\.\/([A-Za-z0-9_.-]+)(?:\/|["'])/g)) out.push(m[1]);
|
|
40178
|
+
}
|
|
40179
|
+
return out;
|
|
40180
|
+
};
|
|
40181
|
+
const pending = [...keptWorkers];
|
|
40182
|
+
while (pending.length) {
|
|
40183
|
+
for (const dep of importsOf(pending.pop())) {
|
|
40184
|
+
if (!keptWorkers.has(dep)) {
|
|
40185
|
+
keptWorkers.add(dep);
|
|
40186
|
+
pending.push(dep);
|
|
40187
|
+
}
|
|
40188
|
+
}
|
|
40189
|
+
}
|
|
40190
|
+
const dirs = new Set(src.workerDirs);
|
|
40191
|
+
const removedWorkers = sorted(removedRoutes.flatMap((r) => r.bundles).filter((b) => dirs.has(b) && !keptWorkers.has(b)));
|
|
40192
|
+
const workerRefs = [];
|
|
40193
|
+
const literal = /(["'`])([A-Za-z_][A-Za-z0-9_]*[_/]?)(?=\1|\$\{)/g;
|
|
40194
|
+
for (const rel of Object.keys(src.workerFiles).sort()) {
|
|
40195
|
+
const dir = rel.split("/")[1];
|
|
40196
|
+
if (!keptWorkers.has(dir) || !dirs.has(dir)) continue;
|
|
40197
|
+
const lines = src.workerFiles[rel].split("\n");
|
|
40198
|
+
lines.forEach((line, i) => {
|
|
40199
|
+
for (const m of line.matchAll(literal)) {
|
|
40200
|
+
const token = m[2];
|
|
40201
|
+
const prefix = /[_/]$/.test(token);
|
|
40202
|
+
const route = prefix ? app.templated.find((r) => r.re.test(`${token}x`)) : resolveIn(app, token);
|
|
40203
|
+
if (route && !kept.has(route)) workerRefs.push(`${rel}:${i + 1} \u2192 ${route.label}`);
|
|
40204
|
+
}
|
|
40205
|
+
});
|
|
40206
|
+
}
|
|
40207
|
+
const homeModules = links === "drop" ? homeModulesPass(app, kept, edited) : void 0;
|
|
40208
|
+
let dev = "";
|
|
40209
|
+
let cursor = 0;
|
|
40210
|
+
const cut = (from, to, replacement = "") => {
|
|
40211
|
+
dev += app.dev.slice(cursor, from) + replacement;
|
|
40212
|
+
cursor = to;
|
|
40213
|
+
};
|
|
40214
|
+
const emptyList = (region, list) => list.length > 0 && list.every((r) => !kept.has(r)) ? region : void 0;
|
|
40215
|
+
const templatedEmptied = emptyList(app.templatedRegion, app.templated);
|
|
40216
|
+
for (const r of app.routes) {
|
|
40217
|
+
if (templatedEmptied && r.kind === "templated") continue;
|
|
40218
|
+
if (!kept.has(r)) {
|
|
40219
|
+
cut(r.lineStart, r.end);
|
|
40220
|
+
continue;
|
|
40221
|
+
}
|
|
40222
|
+
const block = edited.get(r);
|
|
40223
|
+
let text4 = block ? serializeAt(block, app.dev, r.open) : void 0;
|
|
40224
|
+
if (r === app.home && homeModules?.text !== void 0) text4 = homeModules.text;
|
|
40225
|
+
if (text4 !== void 0) cut(r.open, r.close, text4);
|
|
40226
|
+
}
|
|
40227
|
+
if (templatedEmptied) cut(templatedEmptied[0], templatedEmptied[1], "\n");
|
|
40228
|
+
dev += app.dev.slice(cursor);
|
|
40229
|
+
let config = app.config;
|
|
40230
|
+
const edits = [];
|
|
40231
|
+
if (JSON.stringify(nav) !== JSON.stringify(app.nav.value)) {
|
|
40232
|
+
edits.push({ start: app.nav.open, end: app.nav.close, text: serializeAt(nav, app.config, app.nav.open) });
|
|
40233
|
+
}
|
|
40234
|
+
if (app.subtree && subtreeRemoved.length) {
|
|
40235
|
+
const wrapped = app.config.slice(app.subtree.start, app.subtree.end).includes("\n");
|
|
40236
|
+
edits.push({ start: app.subtree.start, end: app.subtree.end, text: wrapped ? serializeAt(subtreeNext, app.config, app.subtree.start) : JSON.stringify(subtreeNext) });
|
|
40237
|
+
}
|
|
40238
|
+
for (const e of edits.sort((a, b) => b.start - a.start)) config = config.slice(0, e.start) + e.text + config.slice(e.end);
|
|
40239
|
+
const keptExact = keptRoutes.filter((r) => r.kind === "screen");
|
|
40240
|
+
const keptTemplated = keptRoutes.filter((r) => r.kind === "templated");
|
|
40241
|
+
const report2 = {
|
|
40242
|
+
...links ? { links } : {},
|
|
40243
|
+
kept: { screens: sorted(keptExact.map((r) => r.label)), templated: sorted(keptTemplated.map((r) => r.label)) },
|
|
40244
|
+
implicit: implicit.map((r) => r.label),
|
|
40245
|
+
removed: {
|
|
40246
|
+
screens: sorted(removedRoutes.filter((r) => r.kind === "screen").map((r) => r.label)),
|
|
40247
|
+
templated: sorted(removedRoutes.filter((r) => r.kind === "templated").map((r) => r.label)),
|
|
40248
|
+
workers: removedWorkers,
|
|
40249
|
+
linkable: navReport.linkable,
|
|
40250
|
+
tabs: navReport.tabs,
|
|
40251
|
+
drawer: navReport.drawer,
|
|
40252
|
+
sidebar: navReport.sidebar,
|
|
40253
|
+
deepLinkPatterns: navReport.deepLinkPatterns,
|
|
40254
|
+
topBarActions: navReport.topBarActions,
|
|
40255
|
+
headerActions: navReport.headerActions,
|
|
40256
|
+
surfaceDestinations: navReport.surfaceDestinations,
|
|
40257
|
+
appIconBadgeSources: navReport.appIconBadgeSources,
|
|
40258
|
+
workerSubtreeScreens: subtreeRemoved
|
|
40259
|
+
},
|
|
40260
|
+
reparented: navReport.reparented,
|
|
40261
|
+
...addedByLinks ? { addedByLinks } : {},
|
|
40262
|
+
...links === "drop" ? { droppedLinks: dropped } : {},
|
|
40263
|
+
...links === "drop" && emptiedCases.length ? { emptiedCases } : {},
|
|
40264
|
+
...links === "drop" && (caseModules.length || homeModules?.dropped.length) ? { home: { droppedModules: [...caseModules, ...homeModules?.dropped ?? []] } } : {},
|
|
40265
|
+
warnings: {
|
|
40266
|
+
workerRefs,
|
|
40267
|
+
...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` } : {}
|
|
40268
|
+
},
|
|
40269
|
+
bytes: { before: Buffer.byteLength(app.dev), after: Buffer.byteLength(dev) }
|
|
40270
|
+
};
|
|
40271
|
+
return { dev, config, removedWorkers, removedIds, report: report2 };
|
|
40272
|
+
}
|
|
40273
|
+
function homeModulesPass(app, kept, edited) {
|
|
40274
|
+
const verticals = Object.entries(EXPLORE_CARDS).filter(([, card]) => app.exact.has(card.screenId));
|
|
40275
|
+
const removedVertical = verticals.some(([, card]) => !kept.has(app.exact.get(card.screenId)));
|
|
40276
|
+
if (!removedVertical) return { dropped: [] };
|
|
40277
|
+
const block = edited.get(app.home);
|
|
40278
|
+
const text4 = block ? serializeAt(block, app.dev, app.home.open) : app.dev.slice(app.home.open, app.home.close);
|
|
40279
|
+
const installed = verticals.filter(([, card]) => kept.has(app.exact.get(card.screenId))).map(([v]) => v);
|
|
40280
|
+
const patched = patchHomeModules(text4, installed);
|
|
40281
|
+
if (!patched.droppedModules.length) return { dropped: [] };
|
|
40282
|
+
return { text: patched.src, dropped: patched.droppedModules };
|
|
40283
|
+
}
|
|
40284
|
+
function listWorkers(dir) {
|
|
40285
|
+
const root = join36(dir, "tier5-src");
|
|
40286
|
+
if (!existsSync39(root)) return { dirs: [], files: {} };
|
|
40287
|
+
const dirs = readdirSync20(root).filter((n) => statSync8(join36(root, n)).isDirectory()).sort();
|
|
40288
|
+
const files = {};
|
|
40289
|
+
const walk2 = (abs, rel) => {
|
|
40290
|
+
for (const name of readdirSync20(abs)) {
|
|
40291
|
+
if (name === "node_modules") continue;
|
|
40292
|
+
const p = join36(abs, name);
|
|
40293
|
+
const r = `${rel}/${name}`;
|
|
40294
|
+
if (statSync8(p).isDirectory()) walk2(p, r);
|
|
40295
|
+
else if (/\.(?:[cm]?[jt]sx?|json)$/.test(name)) files[r] = readFileSync43(p, "utf8");
|
|
40296
|
+
}
|
|
40297
|
+
};
|
|
40298
|
+
for (const d of dirs) walk2(join36(root, d), `tier5-src/${d}`);
|
|
40299
|
+
return { dirs, files };
|
|
40300
|
+
}
|
|
40301
|
+
function csv(v) {
|
|
40302
|
+
if (v === void 0 || v === true || v === false) return void 0;
|
|
40303
|
+
const parts = (Array.isArray(v) ? v : [v]).flatMap((s) => s.split(",")).map((s) => s.trim()).filter(Boolean);
|
|
40304
|
+
return parts.length ? [...new Set(parts)] : void 0;
|
|
40305
|
+
}
|
|
40306
|
+
async function runTemplateTrim(req, deps) {
|
|
40307
|
+
const keep = csv(req.keep);
|
|
40308
|
+
if (!keep) {
|
|
40309
|
+
return refuse3(new TrimRefusal("--keep is required \u2014 the screen ids to keep, comma-separated (the home screen is always kept)", {
|
|
40310
|
+
usage: "himi template trim --keep <id,id,\u2026> [--content <dir>] [--links follow|drop] [--dry-run] [--force]"
|
|
40311
|
+
}));
|
|
40312
|
+
}
|
|
40313
|
+
let links;
|
|
40314
|
+
if (req.links !== void 0) {
|
|
40315
|
+
if (req.links !== "follow" && req.links !== "drop") {
|
|
40316
|
+
return refuse3(new TrimRefusal(`--links takes follow or drop (got ${JSON.stringify(req.links)})`));
|
|
40317
|
+
}
|
|
40318
|
+
links = req.links;
|
|
40319
|
+
}
|
|
40320
|
+
const dir = req.dir;
|
|
40321
|
+
const devPath = join36(dir, "dev/index.ts");
|
|
40322
|
+
const configPath = join36(dir, "config.ts");
|
|
40323
|
+
if (!existsSync39(devPath) || !existsSync39(configPath)) {
|
|
40324
|
+
return refuse3(new TrimRefusal(`${dir} has no dev/index.ts + config.ts \u2014 point --content at an app scaffolded with \`himi init --template\``));
|
|
40325
|
+
}
|
|
40326
|
+
if (isTemplateSourceTree(dir)) {
|
|
40327
|
+
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`));
|
|
40328
|
+
}
|
|
40329
|
+
const dev = readFileSync43(devPath, "utf8");
|
|
40330
|
+
const config = readFileSync43(configPath, "utf8");
|
|
40331
|
+
const workers = listWorkers(dir);
|
|
40332
|
+
let plan;
|
|
40333
|
+
try {
|
|
40334
|
+
plan = planTrim({ dev, config, workerDirs: workers.dirs, workerFiles: workers.files }, keep, links);
|
|
40335
|
+
} catch (e) {
|
|
40336
|
+
if (e instanceof TrimRefusal) return refuse3(e);
|
|
40337
|
+
throw e;
|
|
40338
|
+
}
|
|
40339
|
+
if (req.dryRun) return { code: 0, result: { ok: true, dryRun: true, ...plan.report, validate: null } };
|
|
40340
|
+
const hadHimi = existsSync39(join36(dir, ".himi"));
|
|
40341
|
+
const backupRel = join36(".himi", "trim-backup", (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
|
|
40342
|
+
const backup = join36(dir, backupRel);
|
|
40343
|
+
const originals = [[devPath, "dev/index.ts"], [configPath, "config.ts"]];
|
|
40344
|
+
const moved = [];
|
|
40345
|
+
const restore = () => {
|
|
40346
|
+
for (const [path2, rel] of originals) {
|
|
40347
|
+
const original = readFileSync43(join36(backup, rel));
|
|
40348
|
+
if (!existsSync39(path2) || !readFileSync43(path2).equals(original)) writeFileSync14(path2, original);
|
|
40349
|
+
}
|
|
40350
|
+
for (const name of [...moved].reverse()) renameSync3(join36(backup, "tier5-src", name), join36(dir, "tier5-src", name));
|
|
40351
|
+
};
|
|
40352
|
+
const dropBackup = () => {
|
|
40353
|
+
rmSync6(backup, { recursive: true, force: true });
|
|
40354
|
+
for (const d of [dirname23(backup), join36(dir, ".himi")]) {
|
|
40355
|
+
if (d === join36(dir, ".himi") && hadHimi) break;
|
|
40356
|
+
try {
|
|
40357
|
+
if (!readdirSync20(d).length) rmSync6(d, { recursive: true });
|
|
40358
|
+
} catch {
|
|
40359
|
+
}
|
|
40360
|
+
}
|
|
40361
|
+
};
|
|
40362
|
+
const base = (validate4) => ({
|
|
40363
|
+
dryRun: false,
|
|
40364
|
+
...plan.report,
|
|
40365
|
+
validate: validate4 ? { counts: validate4.counts ?? null, ...validate4.tail ? { tail: validate4.tail } : {} } : null
|
|
40366
|
+
});
|
|
40367
|
+
const abort = (error, cause, validate4) => {
|
|
40368
|
+
const message = cause?.message ?? String(cause);
|
|
40369
|
+
try {
|
|
40370
|
+
restore();
|
|
40371
|
+
} catch (e) {
|
|
40372
|
+
return {
|
|
40373
|
+
code: 1,
|
|
40374
|
+
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) }
|
|
40375
|
+
};
|
|
40376
|
+
}
|
|
40377
|
+
dropBackup();
|
|
40378
|
+
return { code: 1, result: { ok: false, error: `${error} (${message}); every file was restored`, rolledBack: true, ...base(validate4) } };
|
|
40379
|
+
};
|
|
40380
|
+
try {
|
|
40381
|
+
mkdirSync18(join36(backup, "dev"), { recursive: true });
|
|
40382
|
+
for (const [path2, rel] of originals) cpSync(path2, join36(backup, rel));
|
|
40383
|
+
if (plan.removedWorkers.length) mkdirSync18(join36(backup, "tier5-src"), { recursive: true });
|
|
40384
|
+
} catch (e) {
|
|
40385
|
+
dropBackup();
|
|
40386
|
+
return { code: 1, result: { ok: false, error: `could not back up the app before trimming it (${e.message}); nothing was changed`, rolledBack: true, ...base() } };
|
|
40387
|
+
}
|
|
40388
|
+
try {
|
|
40389
|
+
const moveDir = deps.moveDir ?? renameSync3;
|
|
40390
|
+
for (const name of plan.removedWorkers) {
|
|
40391
|
+
moveDir(join36(dir, "tier5-src", name), join36(backup, "tier5-src", name));
|
|
40392
|
+
moved.push(name);
|
|
40393
|
+
}
|
|
40394
|
+
if (plan.dev !== dev) writeFileSync14(devPath, plan.dev);
|
|
40395
|
+
if (plan.config !== config) writeFileSync14(configPath, plan.config);
|
|
40396
|
+
} catch (e) {
|
|
40397
|
+
return abort("the trim failed while writing", e);
|
|
40398
|
+
}
|
|
40399
|
+
let failure;
|
|
40400
|
+
let validate3;
|
|
40401
|
+
try {
|
|
40402
|
+
const written = parseApp(readFileSync43(devPath, "utf8"), readFileSync43(configPath, "utf8"));
|
|
40403
|
+
const leftovers = leftoverNavRefs(written.nav.value, plan.removedIds);
|
|
40404
|
+
if (leftovers.length) failure = { error: "navigation still names screens this trim removed", leftovers };
|
|
40405
|
+
else {
|
|
40406
|
+
validate3 = await deps.validate(dir);
|
|
40407
|
+
if (validate3.code !== 0) failure = { error: "himi validate --strict failed on the trimmed app" };
|
|
40408
|
+
}
|
|
40409
|
+
} catch (e) {
|
|
40410
|
+
return abort("the trim could not be checked", e, validate3);
|
|
40411
|
+
}
|
|
40412
|
+
if (!failure) {
|
|
40413
|
+
dropBackup();
|
|
40414
|
+
return { code: 0, result: { ok: true, ...base(validate3) } };
|
|
40415
|
+
}
|
|
40416
|
+
if (req.force) {
|
|
40417
|
+
return {
|
|
40418
|
+
code: 1,
|
|
40419
|
+
result: { ok: false, ...failure, rolledBack: false, backup: backupRel, hint: `--force kept the trimmed tree; the originals are in ${backupRel}`, ...base(validate3) }
|
|
40420
|
+
};
|
|
40421
|
+
}
|
|
40422
|
+
try {
|
|
40423
|
+
restore();
|
|
40424
|
+
} catch (e) {
|
|
40425
|
+
return abort(String(failure.error), e, validate3);
|
|
40426
|
+
}
|
|
40427
|
+
dropBackup();
|
|
40428
|
+
return {
|
|
40429
|
+
code: 1,
|
|
40430
|
+
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) }
|
|
40431
|
+
};
|
|
40432
|
+
}
|
|
40433
|
+
var TrimRefusal, LIT, ATOM, QUANT, CAP, SAFE_ROUTE_PATTERN, lineOf, isStatic, entryLabel, isNode3, asItems, NAV_SCREEN_KEYS, sorted, refuse3;
|
|
40434
|
+
var init_template_trim = __esm({
|
|
40435
|
+
"src/template-trim.ts"() {
|
|
40436
|
+
init_validate_descriptor();
|
|
40437
|
+
init_scaffold();
|
|
40438
|
+
init_home_descriptor();
|
|
40439
|
+
TrimRefusal = class extends Error {
|
|
40440
|
+
detail;
|
|
40441
|
+
constructor(message, detail = {}) {
|
|
40442
|
+
super(message);
|
|
40443
|
+
this.detail = detail;
|
|
40444
|
+
}
|
|
40445
|
+
};
|
|
40446
|
+
LIT = String.raw`(?:[A-Za-z0-9_/.:-]|\\[./_:-])*`;
|
|
40447
|
+
ATOM = String.raw`(?:\[(?:[^\]\\[]|\\.)+\]|\\[dw]|\.)`;
|
|
40448
|
+
QUANT = String.raw`(?:[+*]|\{\d+(?:,\d*)?\})`;
|
|
40449
|
+
CAP = String.raw`\(${ATOM}${QUANT}\)`;
|
|
40450
|
+
SAFE_ROUTE_PATTERN = new RegExp(
|
|
40451
|
+
String.raw`^\^${LIT}(?:${CAP}${LIT}|\(\?:(?:${LIT}|\[(?:[^\]\\[]|\\.)+\])${CAP}\)\?)?\$$`
|
|
40452
|
+
);
|
|
40453
|
+
lineOf = (src, at) => src.slice(0, at).split("\n").length;
|
|
40454
|
+
isStatic = (id) => typeof id === "string" && id !== "" && !id.startsWith("$");
|
|
40455
|
+
entryLabel = (entry) => {
|
|
40456
|
+
const id = entry?.id;
|
|
40457
|
+
return typeof id === "string" && id ? id : "(unnamed)";
|
|
40458
|
+
};
|
|
40459
|
+
isNode3 = (v) => !!v && typeof v === "object" && !!v.body && typeof v.body === "object";
|
|
40460
|
+
asItems = (block) => {
|
|
40461
|
+
const items = block?.items;
|
|
40462
|
+
return Array.isArray(items) ? items : void 0;
|
|
40463
|
+
};
|
|
40464
|
+
NAV_SCREEN_KEYS = /* @__PURE__ */ new Set(["screenId", "parentScreenId", "contentScreenId", "badgeScreenId"]);
|
|
40465
|
+
sorted = (xs) => [...new Set(xs)].sort();
|
|
40466
|
+
refuse3 = (e) => ({ code: 2, result: { ok: false, error: e.message, ...e.detail } });
|
|
40467
|
+
}
|
|
40468
|
+
});
|
|
40469
|
+
|
|
39146
40470
|
// src/nav-lint.ts
|
|
39147
40471
|
var nav_lint_exports = {};
|
|
39148
40472
|
__export(nav_lint_exports, {
|
|
@@ -39436,7 +40760,7 @@ function packagePathFor(pathname) {
|
|
|
39436
40760
|
}
|
|
39437
40761
|
return UNSUPPORTED;
|
|
39438
40762
|
}
|
|
39439
|
-
function
|
|
40763
|
+
function parseJson2(read, path2, errors) {
|
|
39440
40764
|
const bytes2 = read(path2);
|
|
39441
40765
|
if (!bytes2) return null;
|
|
39442
40766
|
try {
|
|
@@ -39449,7 +40773,7 @@ function parseJson(read, path2, errors) {
|
|
|
39449
40773
|
function validatePackage(read, opts = {}) {
|
|
39450
40774
|
const errors = [];
|
|
39451
40775
|
const warnings = [];
|
|
39452
|
-
const header =
|
|
40776
|
+
const header = parseJson2(read, HIMI_PACKAGE_HEADER_PATH, errors);
|
|
39453
40777
|
if (!header && opts.requireHeader) {
|
|
39454
40778
|
errors.push(`${HIMI_PACKAGE_HEADER_PATH} is missing \u2014 not a .himi package`);
|
|
39455
40779
|
}
|
|
@@ -39477,7 +40801,7 @@ function validatePackage(read, opts = {}) {
|
|
|
39477
40801
|
errors.push(`${HIMI_PACKAGE_SOURCE_PATH} is present in a package whose header declares no source`);
|
|
39478
40802
|
}
|
|
39479
40803
|
}
|
|
39480
|
-
const manifest =
|
|
40804
|
+
const manifest = parseJson2(read, HIMI_PACKAGE_MANIFEST_PATH, errors);
|
|
39481
40805
|
if (!manifest) {
|
|
39482
40806
|
if (!errors.some((e) => e.startsWith(HIMI_PACKAGE_MANIFEST_PATH))) {
|
|
39483
40807
|
errors.push(`${HIMI_PACKAGE_MANIFEST_PATH} is missing`);
|
|
@@ -39769,13 +41093,13 @@ __export(pack_exports, {
|
|
|
39769
41093
|
});
|
|
39770
41094
|
import { createHash as createHash19 } from "node:crypto";
|
|
39771
41095
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
39772
|
-
import { existsSync as
|
|
39773
|
-
import { dirname as
|
|
41096
|
+
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";
|
|
41097
|
+
import { dirname as dirname24, join as join37, resolve as resolve35 } from "node:path";
|
|
39774
41098
|
function writeZip(entries) {
|
|
39775
|
-
const
|
|
39776
|
-
const total =
|
|
41099
|
+
const sorted2 = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
41100
|
+
const total = sorted2.reduce((n, e) => n + e.bytes.length, 0);
|
|
39777
41101
|
if (total > ZIP32_MAX) {
|
|
39778
|
-
const biggest =
|
|
41102
|
+
const biggest = sorted2.reduce((a, b) => a.bytes.length >= b.bytes.length ? a : b);
|
|
39779
41103
|
throw new Error(
|
|
39780
41104
|
`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`
|
|
39781
41105
|
);
|
|
@@ -39783,7 +41107,7 @@ function writeZip(entries) {
|
|
|
39783
41107
|
const locals = [];
|
|
39784
41108
|
const centrals = [];
|
|
39785
41109
|
let offset = 0;
|
|
39786
|
-
for (const entry of
|
|
41110
|
+
for (const entry of sorted2) {
|
|
39787
41111
|
if (!isSafeEntryName(entry.path)) throw new Error(`unsafe package entry name: ${JSON.stringify(entry.path)}`);
|
|
39788
41112
|
const name = Buffer.from(entry.path, "utf8");
|
|
39789
41113
|
const crc = zipCrc32(entry.bytes);
|
|
@@ -39830,8 +41154,8 @@ function writeZip(entries) {
|
|
|
39830
41154
|
eocd.writeUInt32LE(EOCD_SIG, 0);
|
|
39831
41155
|
eocd.writeUInt16LE(0, 4);
|
|
39832
41156
|
eocd.writeUInt16LE(0, 6);
|
|
39833
|
-
eocd.writeUInt16LE(
|
|
39834
|
-
eocd.writeUInt16LE(
|
|
41157
|
+
eocd.writeUInt16LE(sorted2.length, 8);
|
|
41158
|
+
eocd.writeUInt16LE(sorted2.length, 10);
|
|
39835
41159
|
eocd.writeUInt32LE(centralBuf.length, 12);
|
|
39836
41160
|
eocd.writeUInt32LE(offset, 16);
|
|
39837
41161
|
eocd.writeUInt16LE(0, 20);
|
|
@@ -39864,13 +41188,13 @@ function inflateEntry(buf, entry) {
|
|
|
39864
41188
|
return bytes2;
|
|
39865
41189
|
}
|
|
39866
41190
|
function readIf(path2) {
|
|
39867
|
-
return
|
|
41191
|
+
return existsSync40(path2) && statSync9(path2).isFile() ? readFileSync44(path2) : null;
|
|
39868
41192
|
}
|
|
39869
41193
|
function listDir(dir) {
|
|
39870
|
-
return
|
|
41194
|
+
return existsSync40(dir) ? readdirSync21(dir).filter((f) => statSync9(join37(dir, f)).isFile()) : [];
|
|
39871
41195
|
}
|
|
39872
41196
|
function gatherReleaseEntries(appDir2) {
|
|
39873
|
-
const manifestPath =
|
|
41197
|
+
const manifestPath = join37(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
|
|
39874
41198
|
const manifestBytes = readIf(manifestPath);
|
|
39875
41199
|
if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir2} \u2014 build a release there first`);
|
|
39876
41200
|
const manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
@@ -39894,7 +41218,7 @@ function gatherReleaseEntries(appDir2) {
|
|
|
39894
41218
|
}
|
|
39895
41219
|
const missing = [];
|
|
39896
41220
|
for (const rel of wanted) {
|
|
39897
|
-
const bytes2 = readIf(
|
|
41221
|
+
const bytes2 = readIf(join37(appDir2, rel));
|
|
39898
41222
|
if (bytes2) entries.push({ path: rel, bytes: bytes2 });
|
|
39899
41223
|
else missing.push(rel);
|
|
39900
41224
|
}
|
|
@@ -39905,12 +41229,12 @@ function gatherReleaseEntries(appDir2) {
|
|
|
39905
41229
|
);
|
|
39906
41230
|
}
|
|
39907
41231
|
for (const name of SINGLETONS) {
|
|
39908
|
-
const bytes2 = readIf(
|
|
41232
|
+
const bytes2 = readIf(join37(appDir2, name));
|
|
39909
41233
|
if (bytes2) entries.push({ path: name, bytes: bytes2 });
|
|
39910
41234
|
}
|
|
39911
41235
|
const skipped = [];
|
|
39912
41236
|
for (const sub of ["screens", "bundles", "assets", "widgets"]) {
|
|
39913
|
-
for (const f of listDir(
|
|
41237
|
+
for (const f of listDir(join37(appDir2, sub))) {
|
|
39914
41238
|
if (!wanted.has(`${sub}/${f}`)) skipped.push(`${sub}/${f}`);
|
|
39915
41239
|
}
|
|
39916
41240
|
}
|
|
@@ -39943,18 +41267,18 @@ function buildEntries(appDir2, app, opts) {
|
|
|
39943
41267
|
return { all, header, manifest, skipped };
|
|
39944
41268
|
}
|
|
39945
41269
|
function packRelease(releaseRoot, app, out, opts = {}) {
|
|
39946
|
-
const appDir2 =
|
|
41270
|
+
const appDir2 = join37(resolve35(releaseRoot), app);
|
|
39947
41271
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
39948
41272
|
const buf = writeZip(all);
|
|
39949
|
-
const isDir =
|
|
39950
|
-
const outFile = isDir ?
|
|
39951
|
-
|
|
39952
|
-
|
|
41273
|
+
const isDir = existsSync40(out) && statSync9(out).isDirectory();
|
|
41274
|
+
const outFile = isDir ? join37(resolve35(out), packageFileName(app, header.releaseId)) : resolve35(out);
|
|
41275
|
+
mkdirSync19(dirname24(outFile), { recursive: true });
|
|
41276
|
+
writeFileSync15(outFile, buf);
|
|
39953
41277
|
return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
|
|
39954
41278
|
}
|
|
39955
41279
|
function resolvePackageDirDest(outDir, app, releaseId) {
|
|
39956
41280
|
const packagedApp = (dir) => {
|
|
39957
|
-
const bytes2 = readIf(
|
|
41281
|
+
const bytes2 = readIf(join37(dir, HIMI_PACKAGE_HEADER_PATH));
|
|
39958
41282
|
if (!bytes2) return void 0;
|
|
39959
41283
|
try {
|
|
39960
41284
|
return JSON.parse(bytes2.toString("utf8")).app;
|
|
@@ -39963,15 +41287,15 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
39963
41287
|
}
|
|
39964
41288
|
};
|
|
39965
41289
|
const replaceable = (dir) => {
|
|
39966
|
-
if (!
|
|
39967
|
-
if (!
|
|
39968
|
-
return
|
|
41290
|
+
if (!existsSync40(dir)) return true;
|
|
41291
|
+
if (!statSync9(dir).isDirectory()) return false;
|
|
41292
|
+
return readdirSync21(dir).length === 0 || packagedApp(dir) === app;
|
|
39969
41293
|
};
|
|
39970
|
-
if (
|
|
41294
|
+
if (existsSync40(outDir) && !statSync9(outDir).isDirectory()) {
|
|
39971
41295
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
39972
41296
|
}
|
|
39973
41297
|
if (replaceable(outDir)) return outDir;
|
|
39974
|
-
const child =
|
|
41298
|
+
const child = join37(outDir, packageDirName(app, releaseId));
|
|
39975
41299
|
if (!replaceable(child)) {
|
|
39976
41300
|
throw new Error(
|
|
39977
41301
|
`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.`
|
|
@@ -39985,15 +41309,15 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
|
39985
41309
|
"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."
|
|
39986
41310
|
);
|
|
39987
41311
|
}
|
|
39988
|
-
const appDir2 =
|
|
41312
|
+
const appDir2 = join37(resolve35(releaseRoot), app);
|
|
39989
41313
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
39990
41314
|
const dest = resolvePackageDirDest(resolve35(outDir), app, header.releaseId);
|
|
39991
|
-
|
|
41315
|
+
rmSync7(dest, { recursive: true, force: true });
|
|
39992
41316
|
let bytes2 = 0;
|
|
39993
41317
|
for (const entry of all) {
|
|
39994
|
-
const target =
|
|
39995
|
-
|
|
39996
|
-
|
|
41318
|
+
const target = join37(dest, entry.path);
|
|
41319
|
+
mkdirSync19(dirname24(target), { recursive: true });
|
|
41320
|
+
writeFileSync15(target, entry.bytes);
|
|
39997
41321
|
bytes2 += entry.bytes.length;
|
|
39998
41322
|
}
|
|
39999
41323
|
return { app, releaseId: header.releaseId, header, out: dest, bytes: bytes2, entryCount: all.length, skipped };
|
|
@@ -40014,21 +41338,21 @@ function openPackageBuffer(buf) {
|
|
|
40014
41338
|
return openFromEntries(readZip(buf), { requireHeader: true });
|
|
40015
41339
|
}
|
|
40016
41340
|
function openPackageFile(file) {
|
|
40017
|
-
return openPackageBuffer(
|
|
41341
|
+
return openPackageBuffer(readFileSync44(file));
|
|
40018
41342
|
}
|
|
40019
41343
|
function openPackageDir(dir) {
|
|
40020
41344
|
const root = resolve35(dir);
|
|
40021
41345
|
const entries = /* @__PURE__ */ new Map();
|
|
40022
41346
|
const walk2 = (rel) => {
|
|
40023
|
-
const abs = rel ?
|
|
40024
|
-
for (const name of
|
|
41347
|
+
const abs = rel ? join37(root, rel) : root;
|
|
41348
|
+
for (const name of readdirSync21(abs)) {
|
|
40025
41349
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
40026
|
-
const childAbs =
|
|
40027
|
-
if (
|
|
40028
|
-
else if (isSafeEntryName(childRel)) entries.set(childRel,
|
|
41350
|
+
const childAbs = join37(abs, name);
|
|
41351
|
+
if (statSync9(childAbs).isDirectory()) walk2(childRel);
|
|
41352
|
+
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync44(childAbs));
|
|
40029
41353
|
}
|
|
40030
41354
|
};
|
|
40031
|
-
if (!
|
|
41355
|
+
if (!existsSync40(root)) throw new Error(`no such package directory: ${root}`);
|
|
40032
41356
|
walk2("");
|
|
40033
41357
|
const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
|
|
40034
41358
|
if (manifestBytes) {
|
|
@@ -40070,12 +41394,12 @@ function unpackTo(buf, dest, appFallback) {
|
|
|
40070
41394
|
if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
|
|
40071
41395
|
if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
|
|
40072
41396
|
const root = resolve35(dest);
|
|
40073
|
-
const appDir2 =
|
|
40074
|
-
|
|
41397
|
+
const appDir2 = join37(root, app);
|
|
41398
|
+
rmSync7(appDir2, { recursive: true, force: true });
|
|
40075
41399
|
for (const [rel, bytes2] of entries) {
|
|
40076
|
-
const target =
|
|
40077
|
-
|
|
40078
|
-
|
|
41400
|
+
const target = join37(appDir2, rel);
|
|
41401
|
+
mkdirSync19(dirname24(target), { recursive: true });
|
|
41402
|
+
writeFileSync15(target, bytes2);
|
|
40079
41403
|
}
|
|
40080
41404
|
return { root, appDir: appDir2, app };
|
|
40081
41405
|
}
|
|
@@ -40109,20 +41433,20 @@ __export(app_source_exports, {
|
|
|
40109
41433
|
writeConflicts: () => writeConflicts,
|
|
40110
41434
|
zipAppSource: () => zipAppSource
|
|
40111
41435
|
});
|
|
40112
|
-
import { readdirSync as
|
|
40113
|
-
import { join as
|
|
41436
|
+
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";
|
|
41437
|
+
import { join as join38, resolve as resolve36, sep as sep8 } from "node:path";
|
|
40114
41438
|
import { deflateRawSync as deflateRawSync2 } from "node:zlib";
|
|
40115
41439
|
function walkSourceTree(dir, file, skip) {
|
|
40116
41440
|
const walk2 = (relDir) => {
|
|
40117
|
-
for (const name of
|
|
40118
|
-
const rel = relDir ?
|
|
40119
|
-
const st = lstatSync5(
|
|
41441
|
+
for (const name of readdirSync22(join38(dir, relDir))) {
|
|
41442
|
+
const rel = relDir ? join38(relDir, name) : name;
|
|
41443
|
+
const st = lstatSync5(join38(dir, rel));
|
|
40120
41444
|
if (st.isSymbolicLink()) {
|
|
40121
41445
|
skip(rel);
|
|
40122
41446
|
continue;
|
|
40123
41447
|
}
|
|
40124
41448
|
if (st.isDirectory()) {
|
|
40125
|
-
if (isDeniedSourceDir(name, relDir) ||
|
|
41449
|
+
if (isDeniedSourceDir(name, relDir) || existsSync41(join38(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
|
|
40126
41450
|
else walk2(rel);
|
|
40127
41451
|
continue;
|
|
40128
41452
|
}
|
|
@@ -40140,7 +41464,7 @@ function collectAppSource(dir) {
|
|
|
40140
41464
|
const skipped = [];
|
|
40141
41465
|
walkSourceTree(
|
|
40142
41466
|
dir,
|
|
40143
|
-
(archivePath, hostRel) => entries.push({ path: archivePath, bytes:
|
|
41467
|
+
(archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync45(join38(dir, hostRel)) }),
|
|
40144
41468
|
(hostRel) => skipped.push(hostRel)
|
|
40145
41469
|
);
|
|
40146
41470
|
entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
@@ -40187,28 +41511,28 @@ function writeAppSource(entries, destDir) {
|
|
|
40187
41511
|
`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.`
|
|
40188
41512
|
);
|
|
40189
41513
|
}
|
|
40190
|
-
|
|
41514
|
+
mkdirSync20(root, { recursive: true });
|
|
40191
41515
|
const written = [];
|
|
40192
41516
|
for (const entry of entries) {
|
|
40193
41517
|
if (isDeniedSourcePath(entry.path)) continue;
|
|
40194
41518
|
const segments = entry.path.split("/");
|
|
40195
41519
|
let dir = root;
|
|
40196
41520
|
for (const segment of segments.slice(0, -1)) {
|
|
40197
|
-
dir =
|
|
41521
|
+
dir = join38(dir, segment);
|
|
40198
41522
|
const kind = pathKind(dir);
|
|
40199
41523
|
if (kind?.isSymbolicLink()) unlinkSync3(dir);
|
|
40200
41524
|
else if (kind) continue;
|
|
40201
|
-
|
|
41525
|
+
mkdirSync20(dir);
|
|
40202
41526
|
}
|
|
40203
|
-
const target =
|
|
41527
|
+
const target = join38(root, ...segments);
|
|
40204
41528
|
if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
|
|
40205
|
-
|
|
41529
|
+
writeFileSync16(target, entry.bytes);
|
|
40206
41530
|
written.push(entry.path);
|
|
40207
41531
|
}
|
|
40208
41532
|
return written;
|
|
40209
41533
|
}
|
|
40210
41534
|
function staleSourcePaths(entries, destDir) {
|
|
40211
|
-
if (!
|
|
41535
|
+
if (!existsSync41(destDir)) return [];
|
|
40212
41536
|
const archived = new Set(entries.map((e) => e.path));
|
|
40213
41537
|
const stale = [];
|
|
40214
41538
|
walkSourceTree(destDir, (archivePath) => {
|
|
@@ -40235,7 +41559,7 @@ function writeConflicts(entries, destDir) {
|
|
|
40235
41559
|
let dir = root;
|
|
40236
41560
|
let stop = false;
|
|
40237
41561
|
for (const [i, segment] of segments.slice(0, -1).entries()) {
|
|
40238
|
-
dir =
|
|
41562
|
+
dir = join38(dir, segment);
|
|
40239
41563
|
const kind2 = pathKind(dir);
|
|
40240
41564
|
if (!kind2 || kind2.isSymbolicLink()) {
|
|
40241
41565
|
stop = true;
|
|
@@ -40247,7 +41571,7 @@ function writeConflicts(entries, destDir) {
|
|
|
40247
41571
|
break;
|
|
40248
41572
|
}
|
|
40249
41573
|
if (stop) continue;
|
|
40250
|
-
const kind = pathKind(
|
|
41574
|
+
const kind = pathKind(join38(root, ...segments));
|
|
40251
41575
|
if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
|
|
40252
41576
|
say(entry.path, "is a directory here, but the release has a file at that path");
|
|
40253
41577
|
}
|
|
@@ -40257,22 +41581,22 @@ function writeConflicts(entries, destDir) {
|
|
|
40257
41581
|
function removeStaleSource(entries, destDir) {
|
|
40258
41582
|
const root = resolve36(destDir);
|
|
40259
41583
|
const removed = staleSourcePaths(entries, root);
|
|
40260
|
-
for (const rel of removed)
|
|
41584
|
+
for (const rel of removed) rmSync8(join38(root, ...rel.split("/")), { force: true });
|
|
40261
41585
|
const needed = /* @__PURE__ */ new Set();
|
|
40262
41586
|
for (const entry of entries) {
|
|
40263
41587
|
if (isDeniedSourcePath(entry.path)) continue;
|
|
40264
41588
|
const segments = entry.path.split("/");
|
|
40265
41589
|
for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
|
|
40266
41590
|
}
|
|
40267
|
-
if (
|
|
41591
|
+
if (existsSync41(root)) pruneEmptyDirs(root, "", needed, removed);
|
|
40268
41592
|
return removed.sort();
|
|
40269
41593
|
}
|
|
40270
41594
|
function pruneEmptyDirs(root, rel, needed, removed) {
|
|
40271
41595
|
let empty = true;
|
|
40272
|
-
for (const name of
|
|
40273
|
-
const childRel = rel ?
|
|
41596
|
+
for (const name of readdirSync22(rel ? join38(root, rel) : root)) {
|
|
41597
|
+
const childRel = rel ? join38(rel, name) : name;
|
|
40274
41598
|
const posix3 = childRel.split(sep8).join("/");
|
|
40275
|
-
const kind = lstatSync5(
|
|
41599
|
+
const kind = lstatSync5(join38(root, childRel));
|
|
40276
41600
|
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name, rel)) {
|
|
40277
41601
|
empty = false;
|
|
40278
41602
|
continue;
|
|
@@ -40282,7 +41606,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
|
|
|
40282
41606
|
empty = false;
|
|
40283
41607
|
continue;
|
|
40284
41608
|
}
|
|
40285
|
-
rmdirSync(
|
|
41609
|
+
rmdirSync(join38(root, childRel));
|
|
40286
41610
|
removed.push(`${posix3}/`);
|
|
40287
41611
|
}
|
|
40288
41612
|
return empty;
|
|
@@ -40337,13 +41661,13 @@ __export(eject_exports, {
|
|
|
40337
41661
|
EJECTABLE: () => EJECTABLE,
|
|
40338
41662
|
ejectModule: () => ejectModule
|
|
40339
41663
|
});
|
|
40340
|
-
import { existsSync as
|
|
40341
|
-
import { dirname as
|
|
41664
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync46, writeFileSync as writeFileSync17 } from "node:fs";
|
|
41665
|
+
import { dirname as dirname25, join as join39, relative as relative5, resolve as resolve37, sep as sep9 } from "node:path";
|
|
40342
41666
|
function locate(repoRootOrCwd, mod) {
|
|
40343
41667
|
const inRepo = resolve37(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
40344
|
-
if (
|
|
41668
|
+
if (existsSync42(inRepo)) return { path: inRepo, form: "source" };
|
|
40345
41669
|
const dist = resolve37(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
|
|
40346
|
-
if (
|
|
41670
|
+
if (existsSync42(dist)) return { path: dist, form: "bundle" };
|
|
40347
41671
|
return null;
|
|
40348
41672
|
}
|
|
40349
41673
|
function specifiersFor(mod) {
|
|
@@ -40367,8 +41691,8 @@ function ejectModule(opts) {
|
|
|
40367
41691
|
};
|
|
40368
41692
|
}
|
|
40369
41693
|
const ext = found.form === "source" ? "ts" : "mjs";
|
|
40370
|
-
const target =
|
|
40371
|
-
|
|
41694
|
+
const target = join39(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
|
|
41695
|
+
mkdirSync21(dirname25(target), { recursive: true });
|
|
40372
41696
|
const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
|
|
40373
41697
|
//
|
|
40374
41698
|
// Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
|
|
@@ -40381,17 +41705,17 @@ function ejectModule(opts) {
|
|
|
40381
41705
|
// gate still applies. Ejecting buys layout and flow, never the floor.
|
|
40382
41706
|
|
|
40383
41707
|
`;
|
|
40384
|
-
const normalized =
|
|
41708
|
+
const normalized = readFileSync46(found.path, "utf8").replace(
|
|
40385
41709
|
/(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
|
|
40386
41710
|
(_m, q, sub) => `${q}@wix/himalaya/${sub}${q}`
|
|
40387
41711
|
);
|
|
40388
|
-
|
|
41712
|
+
writeFileSync17(target, banner + normalized);
|
|
40389
41713
|
const rewired = [];
|
|
40390
41714
|
for (const f of files) {
|
|
40391
|
-
if (!
|
|
40392
|
-
const before =
|
|
41715
|
+
if (!existsSync42(f)) continue;
|
|
41716
|
+
const before = readFileSync46(f, "utf8");
|
|
40393
41717
|
let after = before;
|
|
40394
|
-
let rel = relative5(
|
|
41718
|
+
let rel = relative5(dirname25(f), target).split(sep9).join("/").replace(/\.tsx?$/, ".js");
|
|
40395
41719
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
40396
41720
|
for (const spec of specifiersFor(mod)) {
|
|
40397
41721
|
const q = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -40401,7 +41725,7 @@ function ejectModule(opts) {
|
|
|
40401
41725
|
);
|
|
40402
41726
|
}
|
|
40403
41727
|
if (after !== before) {
|
|
40404
|
-
|
|
41728
|
+
writeFileSync17(f, after);
|
|
40405
41729
|
rewired.push(f);
|
|
40406
41730
|
}
|
|
40407
41731
|
}
|
|
@@ -40437,14 +41761,14 @@ __export(test_exports, {
|
|
|
40437
41761
|
scopeDescriptors: () => scopeDescriptors,
|
|
40438
41762
|
writeRecordedMocks: () => writeRecordedMocks
|
|
40439
41763
|
});
|
|
40440
|
-
import { existsSync as
|
|
40441
|
-
import { join as
|
|
41764
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync22, readFileSync as readFileSync47, writeFileSync as writeFileSync18 } from "node:fs";
|
|
41765
|
+
import { join as join40, resolve as resolve38 } from "node:path";
|
|
40442
41766
|
function readTestConfig(dir) {
|
|
40443
41767
|
const p = resolve38(dir, TEST_CONFIG_FILE);
|
|
40444
|
-
if (!
|
|
41768
|
+
if (!existsSync43(p)) return {};
|
|
40445
41769
|
let parsed;
|
|
40446
41770
|
try {
|
|
40447
|
-
parsed = JSON.parse(
|
|
41771
|
+
parsed = JSON.parse(readFileSync47(p, "utf8"));
|
|
40448
41772
|
} catch (e) {
|
|
40449
41773
|
throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e.message}`);
|
|
40450
41774
|
}
|
|
@@ -40487,7 +41811,7 @@ function readTestConfig(dir) {
|
|
|
40487
41811
|
function readNetRules(path2) {
|
|
40488
41812
|
let parsed;
|
|
40489
41813
|
try {
|
|
40490
|
-
parsed = JSON.parse(
|
|
41814
|
+
parsed = JSON.parse(readFileSync47(path2, "utf8"));
|
|
40491
41815
|
} catch (e) {
|
|
40492
41816
|
throw new Error(`--net ${path2} could not be read as JSON \u2014 ${e.message}`);
|
|
40493
41817
|
}
|
|
@@ -40508,7 +41832,7 @@ function readNetRules(path2) {
|
|
|
40508
41832
|
function defaultNetRules(dir) {
|
|
40509
41833
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
40510
41834
|
const p = resolve38(dir, rel);
|
|
40511
|
-
if (
|
|
41835
|
+
if (existsSync43(p)) {
|
|
40512
41836
|
const rules = readNetRules(p);
|
|
40513
41837
|
if (rules.length) return { rules, from: rel };
|
|
40514
41838
|
}
|
|
@@ -40524,7 +41848,7 @@ function readCannedResponses() {
|
|
|
40524
41848
|
];
|
|
40525
41849
|
for (const url of candidates) {
|
|
40526
41850
|
try {
|
|
40527
|
-
const parsed = JSON.parse(
|
|
41851
|
+
const parsed = JSON.parse(readFileSync47(url, "utf8"));
|
|
40528
41852
|
const byKey = {};
|
|
40529
41853
|
for (const [k, v] of Object.entries(parsed)) {
|
|
40530
41854
|
if (!k.startsWith("//")) byKey[k] = v;
|
|
@@ -40613,11 +41937,11 @@ function writeRecordedMocks(opts) {
|
|
|
40613
41937
|
};
|
|
40614
41938
|
}
|
|
40615
41939
|
const fs = opts.io ?? {
|
|
40616
|
-
mkdir: (p) =>
|
|
40617
|
-
write: (p, s) =>
|
|
41940
|
+
mkdir: (p) => mkdirSync22(p, { recursive: true }),
|
|
41941
|
+
write: (p, s) => writeFileSync18(p, s)
|
|
40618
41942
|
};
|
|
40619
|
-
fs.mkdir(
|
|
40620
|
-
fs.write(
|
|
41943
|
+
fs.mkdir(join40(opts.dir, "dev"));
|
|
41944
|
+
fs.write(join40(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
40621
41945
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
40622
41946
|
}
|
|
40623
41947
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -41074,14 +42398,14 @@ var mobile_ux_lint_exports = {};
|
|
|
41074
42398
|
__export(mobile_ux_lint_exports, {
|
|
41075
42399
|
mobileUxIssues: () => mobileUxIssues
|
|
41076
42400
|
});
|
|
41077
|
-
import { existsSync as
|
|
41078
|
-
import { join as
|
|
42401
|
+
import { existsSync as existsSync44, readFileSync as readFileSync48 } from "node:fs";
|
|
42402
|
+
import { join as join41 } from "node:path";
|
|
41079
42403
|
function mobileUxIssues(dir, strict) {
|
|
41080
|
-
const file =
|
|
41081
|
-
if (!
|
|
42404
|
+
const file = join41(dir, "MOBILE-UX.md");
|
|
42405
|
+
if (!existsSync44(file)) return [];
|
|
41082
42406
|
let text4;
|
|
41083
42407
|
try {
|
|
41084
|
-
text4 =
|
|
42408
|
+
text4 = readFileSync48(file, "utf8");
|
|
41085
42409
|
} catch {
|
|
41086
42410
|
return [];
|
|
41087
42411
|
}
|
|
@@ -42756,8 +44080,8 @@ __export(functions_exports, {
|
|
|
42756
44080
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
42757
44081
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
42758
44082
|
});
|
|
42759
|
-
import { readFileSync as
|
|
42760
|
-
import { join as
|
|
44083
|
+
import { readFileSync as readFileSync49, existsSync as existsSync45 } from "node:fs";
|
|
44084
|
+
import { join as join42, resolve as resolve39 } from "node:path";
|
|
42761
44085
|
function resolveFunctionsTarget(input) {
|
|
42762
44086
|
const explicitUrl = input.functionsUrl?.trim();
|
|
42763
44087
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -42776,9 +44100,9 @@ async function loadFunctionsApp(dir) {
|
|
|
42776
44100
|
}
|
|
42777
44101
|
const sources = {};
|
|
42778
44102
|
for (const definition of config.functions.functions) {
|
|
42779
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
44103
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join42(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync45);
|
|
42780
44104
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
42781
|
-
sources[definition.name] =
|
|
44105
|
+
sources[definition.name] = readFileSync49(source, "utf8");
|
|
42782
44106
|
}
|
|
42783
44107
|
const data = config.cms || config.data ? mergeDataResources(config) : void 0;
|
|
42784
44108
|
const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
|
|
@@ -42933,9 +44257,9 @@ __export(native_decode_exports, {
|
|
|
42933
44257
|
runNativeDecode: () => runNativeDecode
|
|
42934
44258
|
});
|
|
42935
44259
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
42936
|
-
import { existsSync as
|
|
44260
|
+
import { existsSync as existsSync46, mkdtempSync as mkdtempSync2, readFileSync as readFileSync50, rmSync as rmSync9, writeFileSync as writeFileSync19 } from "node:fs";
|
|
42937
44261
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
42938
|
-
import { join as
|
|
44262
|
+
import { join as join43 } from "node:path";
|
|
42939
44263
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
42940
44264
|
function nativeDecodePackageDir() {
|
|
42941
44265
|
return fileURLToPath20(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -42945,8 +44269,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
42945
44269
|
}
|
|
42946
44270
|
function nativeOracleShipped() {
|
|
42947
44271
|
return {
|
|
42948
|
-
ios:
|
|
42949
|
-
android:
|
|
44272
|
+
ios: existsSync46(join43(nativeDecodePackageDir(), "Package.swift")),
|
|
44273
|
+
android: existsSync46(join43(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
42950
44274
|
};
|
|
42951
44275
|
}
|
|
42952
44276
|
function detectNativeDecode(options = {}) {
|
|
@@ -42957,7 +44281,7 @@ function detectNativeDecode(options = {}) {
|
|
|
42957
44281
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
42958
44282
|
}
|
|
42959
44283
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
42960
|
-
const packageAvailable = options.packageAvailable ??
|
|
44284
|
+
const packageAvailable = options.packageAvailable ?? existsSync46(join43(packageDir, "Package.swift"));
|
|
42961
44285
|
if (!packageAvailable) {
|
|
42962
44286
|
return {
|
|
42963
44287
|
platform: "ios",
|
|
@@ -42969,7 +44293,7 @@ function detectNativeDecode(options = {}) {
|
|
|
42969
44293
|
}
|
|
42970
44294
|
function localPropertiesSdk(harnessDir) {
|
|
42971
44295
|
try {
|
|
42972
|
-
const match =
|
|
44296
|
+
const match = readFileSync50(join43(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
42973
44297
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
42974
44298
|
} catch {
|
|
42975
44299
|
return null;
|
|
@@ -42977,8 +44301,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
42977
44301
|
}
|
|
42978
44302
|
function detectAndroidNativeDecode(options = {}) {
|
|
42979
44303
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
42980
|
-
const gradlew =
|
|
42981
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
44304
|
+
const gradlew = join43(harnessDir, "gradlew");
|
|
44305
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync46(gradlew);
|
|
42982
44306
|
if (!gradlewAvailable) {
|
|
42983
44307
|
return {
|
|
42984
44308
|
platform: "android",
|
|
@@ -42988,7 +44312,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
42988
44312
|
}
|
|
42989
44313
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
42990
44314
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
42991
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
44315
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync46(sdk));
|
|
42992
44316
|
if (!sdkAvailable) {
|
|
42993
44317
|
return {
|
|
42994
44318
|
platform: "android",
|
|
@@ -43060,14 +44384,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
43060
44384
|
return verdicts;
|
|
43061
44385
|
}
|
|
43062
44386
|
function runNativeDecode(options) {
|
|
43063
|
-
const descriptorDir = mkdtempSync2(
|
|
44387
|
+
const descriptorDir = mkdtempSync2(join43(tmpdir3(), "himi-native-decode-"));
|
|
43064
44388
|
const startedAt = Date.now();
|
|
43065
44389
|
try {
|
|
43066
44390
|
for (const descriptor of options.descriptors) {
|
|
43067
44391
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
43068
44392
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
43069
44393
|
}
|
|
43070
|
-
|
|
44394
|
+
writeFileSync19(join43(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
43071
44395
|
}
|
|
43072
44396
|
options.progress?.("building cached Swift oracle");
|
|
43073
44397
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -43079,7 +44403,7 @@ function runNativeDecode(options) {
|
|
|
43079
44403
|
encoding: "utf8"
|
|
43080
44404
|
}).trim();
|
|
43081
44405
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
43082
|
-
const stdout = execFileSync5(
|
|
44406
|
+
const stdout = execFileSync5(join43(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
43083
44407
|
stdio: ["ignore", "pipe", "pipe"],
|
|
43084
44408
|
encoding: "utf8"
|
|
43085
44409
|
});
|
|
@@ -43093,19 +44417,19 @@ function runNativeDecode(options) {
|
|
|
43093
44417
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
43094
44418
|
throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
|
|
43095
44419
|
} finally {
|
|
43096
|
-
|
|
44420
|
+
rmSync9(descriptorDir, { recursive: true, force: true });
|
|
43097
44421
|
}
|
|
43098
44422
|
}
|
|
43099
44423
|
function runAndroidNativeDecode(options) {
|
|
43100
|
-
const descriptorDir = mkdtempSync2(
|
|
43101
|
-
const outputPath =
|
|
44424
|
+
const descriptorDir = mkdtempSync2(join43(tmpdir3(), "himi-native-decode-android-"));
|
|
44425
|
+
const outputPath = join43(descriptorDir, "verdicts.ndjson");
|
|
43102
44426
|
const startedAt = Date.now();
|
|
43103
44427
|
try {
|
|
43104
44428
|
for (const descriptor of options.descriptors) {
|
|
43105
44429
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
43106
44430
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
43107
44431
|
}
|
|
43108
|
-
|
|
44432
|
+
writeFileSync19(join43(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
43109
44433
|
}
|
|
43110
44434
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
43111
44435
|
execFileSync5(options.gradlew, [
|
|
@@ -43120,7 +44444,7 @@ function runAndroidNativeDecode(options) {
|
|
|
43120
44444
|
stdio: ["ignore", "ignore", "pipe"],
|
|
43121
44445
|
encoding: "utf8"
|
|
43122
44446
|
});
|
|
43123
|
-
const stdout =
|
|
44447
|
+
const stdout = readFileSync50(outputPath, "utf8");
|
|
43124
44448
|
return {
|
|
43125
44449
|
platform: "android",
|
|
43126
44450
|
verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
|
|
@@ -43131,7 +44455,7 @@ function runAndroidNativeDecode(options) {
|
|
|
43131
44455
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
43132
44456
|
throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
|
|
43133
44457
|
} finally {
|
|
43134
|
-
|
|
44458
|
+
rmSync9(descriptorDir, { recursive: true, force: true });
|
|
43135
44459
|
}
|
|
43136
44460
|
}
|
|
43137
44461
|
function fieldAt(path2) {
|
|
@@ -43191,30 +44515,30 @@ __export(browser_authoring_exports, {
|
|
|
43191
44515
|
import { createServer as createServer3 } from "node:http";
|
|
43192
44516
|
import { createHash as createHash22, randomBytes as randomBytes4 } from "node:crypto";
|
|
43193
44517
|
import { execFile as execFile2 } from "node:child_process";
|
|
43194
|
-
import { existsSync as
|
|
43195
|
-
import { join as
|
|
44518
|
+
import { existsSync as existsSync47, readdirSync as readdirSync23, readFileSync as readFileSync51, realpathSync as realpathSync4, statSync as statSync10 } from "node:fs";
|
|
44519
|
+
import { join as join44, posix, relative as relative6, sep as sep10 } from "node:path";
|
|
43196
44520
|
function humanMs(ms) {
|
|
43197
44521
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
43198
44522
|
}
|
|
43199
44523
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
43200
|
-
const root =
|
|
44524
|
+
const root = join44(tier5SrcDir, bundleName);
|
|
43201
44525
|
const files = {};
|
|
43202
44526
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
43203
44527
|
const walk2 = (abs, rel) => {
|
|
43204
44528
|
const real = realpathSync4(abs);
|
|
43205
44529
|
if (visitedDirs.has(real)) return;
|
|
43206
44530
|
visitedDirs.add(real);
|
|
43207
|
-
for (const name of
|
|
43208
|
-
const childAbs =
|
|
44531
|
+
for (const name of readdirSync23(abs).sort()) {
|
|
44532
|
+
const childAbs = join44(abs, name);
|
|
43209
44533
|
const childRel = posix.join(rel, name);
|
|
43210
|
-
if (
|
|
44534
|
+
if (statSync10(childAbs).isDirectory()) {
|
|
43211
44535
|
walk2(childAbs, childRel);
|
|
43212
44536
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
43213
|
-
files[childRel] =
|
|
44537
|
+
files[childRel] = readFileSync51(childAbs, "utf8");
|
|
43214
44538
|
}
|
|
43215
44539
|
}
|
|
43216
44540
|
};
|
|
43217
|
-
if (!
|
|
44541
|
+
if (!existsSync47(root)) return null;
|
|
43218
44542
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
43219
44543
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
43220
44544
|
if (!entry) return null;
|
|
@@ -43231,20 +44555,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
43231
44555
|
const spec = m[1];
|
|
43232
44556
|
const virtual = posix.normalize(posix.join(dir, spec));
|
|
43233
44557
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
43234
|
-
const onDisk =
|
|
44558
|
+
const onDisk = join44(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
43235
44559
|
const candidates = [
|
|
43236
44560
|
onDisk,
|
|
43237
44561
|
`${onDisk}.ts`,
|
|
43238
44562
|
`${onDisk}.js`,
|
|
43239
44563
|
onDisk.replace(/\.js$/, ".ts"),
|
|
43240
|
-
|
|
43241
|
-
|
|
44564
|
+
join44(onDisk, "index.ts"),
|
|
44565
|
+
join44(onDisk, "index.js")
|
|
43242
44566
|
];
|
|
43243
44567
|
for (const abs of candidates) {
|
|
43244
|
-
if (!
|
|
44568
|
+
if (!existsSync47(abs) || statSync10(abs).isDirectory()) continue;
|
|
43245
44569
|
const key2 = `/tier5-src/${relative6(tier5SrcDir, abs).split(sep10).join(posix.sep)}`;
|
|
43246
44570
|
if (key2 in files) break;
|
|
43247
|
-
files[key2] =
|
|
44571
|
+
files[key2] = readFileSync51(abs, "utf8");
|
|
43248
44572
|
queue.push(key2);
|
|
43249
44573
|
break;
|
|
43250
44574
|
}
|
|
@@ -43279,7 +44603,7 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
43279
44603
|
function sdkSubpathReader(resolve45) {
|
|
43280
44604
|
return (sub) => {
|
|
43281
44605
|
try {
|
|
43282
|
-
return
|
|
44606
|
+
return readFileSync51(resolve45(`@wix/himalaya/${sub}`), "utf8");
|
|
43283
44607
|
} catch {
|
|
43284
44608
|
return null;
|
|
43285
44609
|
}
|
|
@@ -43453,8 +44777,8 @@ __export(coverage_exports, {
|
|
|
43453
44777
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
43454
44778
|
trendAndStore: () => trendAndStore
|
|
43455
44779
|
});
|
|
43456
|
-
import { existsSync as
|
|
43457
|
-
import { dirname as
|
|
44780
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync23, readFileSync as readFileSync52, writeFileSync as writeFileSync20 } from "node:fs";
|
|
44781
|
+
import { dirname as dirname26, join as join45 } from "node:path";
|
|
43458
44782
|
function suppressedNativeKeys(oracle) {
|
|
43459
44783
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
43460
44784
|
}
|
|
@@ -43624,11 +44948,11 @@ function assembleLedger(r, options = {}) {
|
|
|
43624
44948
|
return out;
|
|
43625
44949
|
}
|
|
43626
44950
|
function trendAndStore(dir, entries, suppressed) {
|
|
43627
|
-
const p =
|
|
44951
|
+
const p = join45(dir, LEDGER_FILE);
|
|
43628
44952
|
let previous = null;
|
|
43629
44953
|
try {
|
|
43630
|
-
if (
|
|
43631
|
-
const parsed = JSON.parse(
|
|
44954
|
+
if (existsSync48(p)) {
|
|
44955
|
+
const parsed = JSON.parse(readFileSync52(p, "utf8"));
|
|
43632
44956
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
43633
44957
|
}
|
|
43634
44958
|
} catch {
|
|
@@ -43636,8 +44960,8 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
43636
44960
|
const current = entries.map((e) => e.key);
|
|
43637
44961
|
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
43638
44962
|
try {
|
|
43639
|
-
|
|
43640
|
-
|
|
44963
|
+
mkdirSync23(dirname26(p), { recursive: true });
|
|
44964
|
+
writeFileSync20(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
43641
44965
|
} catch {
|
|
43642
44966
|
return null;
|
|
43643
44967
|
}
|
|
@@ -43667,11 +44991,11 @@ function formatLedger(entries, trend) {
|
|
|
43667
44991
|
return out.join("\n");
|
|
43668
44992
|
}
|
|
43669
44993
|
function diffAndStoreObservations(dir, current) {
|
|
43670
|
-
const p =
|
|
44994
|
+
const p = join45(dir, OBS_FILE);
|
|
43671
44995
|
let previous = null;
|
|
43672
44996
|
try {
|
|
43673
|
-
if (
|
|
43674
|
-
const parsed = JSON.parse(
|
|
44997
|
+
if (existsSync48(p)) {
|
|
44998
|
+
const parsed = JSON.parse(readFileSync52(p, "utf8"));
|
|
43675
44999
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
43676
45000
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
43677
45001
|
)) {
|
|
@@ -43681,8 +45005,8 @@ function diffAndStoreObservations(dir, current) {
|
|
|
43681
45005
|
} catch {
|
|
43682
45006
|
}
|
|
43683
45007
|
try {
|
|
43684
|
-
|
|
43685
|
-
|
|
45008
|
+
mkdirSync23(dirname26(p), { recursive: true });
|
|
45009
|
+
writeFileSync20(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
43686
45010
|
} catch {
|
|
43687
45011
|
return null;
|
|
43688
45012
|
}
|
|
@@ -43720,8 +45044,8 @@ var LEDGER_FILE, OBS_FILE;
|
|
|
43720
45044
|
var init_coverage = __esm({
|
|
43721
45045
|
"src/coverage.ts"() {
|
|
43722
45046
|
init_native_decode();
|
|
43723
|
-
LEDGER_FILE =
|
|
43724
|
-
OBS_FILE =
|
|
45047
|
+
LEDGER_FILE = join45(".himi", "test-ledger.json");
|
|
45048
|
+
OBS_FILE = join45(".himi", "test-observations.json");
|
|
43725
45049
|
}
|
|
43726
45050
|
});
|
|
43727
45051
|
|
|
@@ -43732,16 +45056,16 @@ __export(design_kits_exports, {
|
|
|
43732
45056
|
kitsDir: () => kitsDir,
|
|
43733
45057
|
listKits: () => listKits2
|
|
43734
45058
|
});
|
|
43735
|
-
import { existsSync as
|
|
43736
|
-
import { join as
|
|
45059
|
+
import { existsSync as existsSync49, readFileSync as readFileSync53, readdirSync as readdirSync24 } from "node:fs";
|
|
45060
|
+
import { join as join46, basename as basename10 } from "node:path";
|
|
43737
45061
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
43738
45062
|
function kitsDir() {
|
|
43739
|
-
return KIT_DIR_CANDIDATES.find((p) =>
|
|
45063
|
+
return KIT_DIR_CANDIDATES.find((p) => existsSync49(p));
|
|
43740
45064
|
}
|
|
43741
45065
|
function listKits2() {
|
|
43742
45066
|
const dir = kitsDir();
|
|
43743
45067
|
if (!dir) return [];
|
|
43744
|
-
return
|
|
45068
|
+
return readdirSync24(dir).filter((f) => f.endsWith(".json")).map((f) => basename10(f, ".json")).sort();
|
|
43745
45069
|
}
|
|
43746
45070
|
function kitReport(name) {
|
|
43747
45071
|
const dir = kitsDir();
|
|
@@ -43760,7 +45084,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
|
|
|
43760
45084
|
if (!kits.includes(name)) {
|
|
43761
45085
|
return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
|
|
43762
45086
|
}
|
|
43763
|
-
const raw =
|
|
45087
|
+
const raw = readFileSync53(join46(dir, `${name}.json`), "utf8");
|
|
43764
45088
|
let parsed;
|
|
43765
45089
|
try {
|
|
43766
45090
|
parsed = JSON.parse(raw);
|
|
@@ -43784,9 +45108,9 @@ var init_design_kits = __esm({
|
|
|
43784
45108
|
"src/design-kits.ts"() {
|
|
43785
45109
|
KIT_DIR_CANDIDATES = [
|
|
43786
45110
|
// in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
|
|
43787
|
-
|
|
45111
|
+
join46(fileURLToPath21(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
|
|
43788
45112
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
|
|
43789
|
-
|
|
45113
|
+
join46(fileURLToPath21(new URL("..", import.meta.url)), "stdlib", "design-kits")
|
|
43790
45114
|
];
|
|
43791
45115
|
}
|
|
43792
45116
|
});
|
|
@@ -43800,11 +45124,11 @@ __export(assets_exports, {
|
|
|
43800
45124
|
removeAssetPayload: () => removeAssetPayload,
|
|
43801
45125
|
verifyReport: () => verifyReport
|
|
43802
45126
|
});
|
|
43803
|
-
import { readFileSync as
|
|
45127
|
+
import { readFileSync as readFileSync54 } from "node:fs";
|
|
43804
45128
|
import { basename as basename11 } from "node:path";
|
|
43805
45129
|
function declaredAssets(dir) {
|
|
43806
45130
|
return collectAssets(dir).map((a) => {
|
|
43807
|
-
const bytes2 =
|
|
45131
|
+
const bytes2 = readFileSync54(a.path);
|
|
43808
45132
|
return {
|
|
43809
45133
|
name: a.name,
|
|
43810
45134
|
sha256: assetSha256(bytes2),
|
|
@@ -43881,7 +45205,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
43881
45205
|
};
|
|
43882
45206
|
}
|
|
43883
45207
|
function addAssetPayload(manifest, filePath, opts) {
|
|
43884
|
-
const bytes2 =
|
|
45208
|
+
const bytes2 = readFileSync54(filePath);
|
|
43885
45209
|
const name = opts.name ?? basename11(filePath);
|
|
43886
45210
|
const sha2565 = assetSha256(bytes2);
|
|
43887
45211
|
const record2 = {
|
|
@@ -44578,9 +45902,9 @@ ${releaseId}`;
|
|
|
44578
45902
|
if (!isSafeMsid(msid)) return json3(400, { error: "webwix_owner_bad_msid" });
|
|
44579
45903
|
const cookie = request.headers.get("cookie") ?? "";
|
|
44580
45904
|
if (!/wixSession2=/.test(cookie)) return json3(401, { error: "webwix_owner_no_session" });
|
|
44581
|
-
|
|
45905
|
+
const renew = url.searchParams.get("renew") === "1";
|
|
44582
45906
|
try {
|
|
44583
|
-
const entry = await webwixOwnerInstances.entry(msid, cookie);
|
|
45907
|
+
const entry = await webwixOwnerInstances.entry(msid, cookie, Date.now(), { renew });
|
|
44584
45908
|
return json3(200, { ...entry, expiresInMs: Math.max(0, entry.expiresAt - Date.now()) }, { "cache-control": "no-store" });
|
|
44585
45909
|
} catch (e) {
|
|
44586
45910
|
const msg = String(e?.message ?? e);
|
|
@@ -45357,19 +46681,19 @@ var init_preview_assets_generated = __esm({
|
|
|
45357
46681
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
45358
46682
|
init_preview_assets_format();
|
|
45359
46683
|
PREVIEW_ASSET_MANIFEST = [
|
|
45360
|
-
{ key: "assets/index-
|
|
45361
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
45362
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
45363
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
45364
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
45365
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
45366
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
45367
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
45368
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
45369
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
45370
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
45371
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
45372
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
46684
|
+
{ key: "assets/index-BKft9wm1.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1012166, sha256: "3a87519baabf67cecf163d20ea1eaaeba288fdeab2fc00cc3d22f09b6a29a194" },
|
|
46685
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1012174, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
46686
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1103098, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
46687
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1194082, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
46688
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1285062, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
46689
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1375934, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
46690
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1466914, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
46691
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 1575550, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
46692
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 1684634, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
46693
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 1793682, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
46694
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 1901382, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
46695
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 1989490, length: 4448, sha256: "71627ade6c0e47a8956b4841c1f6d644fee50a9a4ca9e6d9106b589e84891bd7" },
|
|
46696
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 1993938, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
45373
46697
|
];
|
|
45374
46698
|
}
|
|
45375
46699
|
});
|
|
@@ -45385,9 +46709,9 @@ __export(run_exports, {
|
|
|
45385
46709
|
runPackage: () => runPackage,
|
|
45386
46710
|
withoutProdServe: () => withoutProdServe
|
|
45387
46711
|
});
|
|
45388
|
-
import { cpSync, existsSync as
|
|
46712
|
+
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";
|
|
45389
46713
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
45390
|
-
import { dirname as
|
|
46714
|
+
import { dirname as dirname27, join as join47 } from "node:path";
|
|
45391
46715
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
45392
46716
|
import { spawn as spawn3 } from "node:child_process";
|
|
45393
46717
|
function makePackageRunHandler(opts) {
|
|
@@ -45406,9 +46730,9 @@ async function fetchBytes(url) {
|
|
|
45406
46730
|
}
|
|
45407
46731
|
async function resolvePackage(source, workDir) {
|
|
45408
46732
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
45409
|
-
if (!isUrl2 &&
|
|
45410
|
-
const appDirManifest =
|
|
45411
|
-
if (
|
|
46733
|
+
if (!isUrl2 && existsSync50(source) && statSync11(source).isDirectory()) {
|
|
46734
|
+
const appDirManifest = join47(source, "release-manifest.json");
|
|
46735
|
+
if (existsSync50(appDirManifest)) {
|
|
45412
46736
|
const opened2 = openPackageDir(source);
|
|
45413
46737
|
if (!opened2.validation.ok) {
|
|
45414
46738
|
throw new Error(`package is not valid:
|
|
@@ -45417,12 +46741,12 @@ async function resolvePackage(source, workDir) {
|
|
|
45417
46741
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
45418
46742
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
45419
46743
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
45420
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
45421
|
-
const target =
|
|
45422
|
-
if (
|
|
45423
|
-
|
|
45424
|
-
|
|
45425
|
-
|
|
46744
|
+
const root2 = workDir ?? mkdtempSync3(join47(tmpdir4(), "himi-run-"));
|
|
46745
|
+
const target = join47(root2, app2);
|
|
46746
|
+
if (join47(source) !== target) {
|
|
46747
|
+
mkdirSync24(root2, { recursive: true });
|
|
46748
|
+
rmSync10(target, { recursive: true, force: true });
|
|
46749
|
+
cpSync2(source, target, { recursive: true });
|
|
45426
46750
|
}
|
|
45427
46751
|
return {
|
|
45428
46752
|
releaseRoot: root2,
|
|
@@ -45436,12 +46760,12 @@ async function resolvePackage(source, workDir) {
|
|
|
45436
46760
|
}
|
|
45437
46761
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
45438
46762
|
}
|
|
45439
|
-
const bytes2 = isUrl2 ? await fetchBytes(source) :
|
|
45440
|
-
const root = workDir ?? mkdtempSync3(
|
|
46763
|
+
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync55(source);
|
|
46764
|
+
const root = workDir ?? mkdtempSync3(join47(tmpdir4(), "himi-run-"));
|
|
45441
46765
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
45442
46766
|
const opened = openPackageDir(appDir2);
|
|
45443
46767
|
if (!opened.validation.ok) {
|
|
45444
|
-
|
|
46768
|
+
rmSync10(workDir ? appDir2 : root, { recursive: true, force: true });
|
|
45445
46769
|
throw new Error(`package is not valid:
|
|
45446
46770
|
${opened.validation.errors.join("\n ")}`);
|
|
45447
46771
|
}
|
|
@@ -45458,16 +46782,16 @@ async function resolvePackage(source, workDir) {
|
|
|
45458
46782
|
async function loadPreviewAssets() {
|
|
45459
46783
|
try {
|
|
45460
46784
|
const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
|
|
45461
|
-
const here =
|
|
46785
|
+
const here = dirname27(fileURLToPath22(import.meta.url));
|
|
45462
46786
|
const candidates = [
|
|
45463
|
-
|
|
46787
|
+
join47(here, "preview-assets.generated.bin"),
|
|
45464
46788
|
// published: copied next to the bundled CLI
|
|
45465
|
-
|
|
46789
|
+
join47(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
45466
46790
|
// in-repo checkout
|
|
45467
46791
|
];
|
|
45468
46792
|
for (const path2 of candidates) {
|
|
45469
|
-
if (!
|
|
45470
|
-
const blob =
|
|
46793
|
+
if (!existsSync50(path2)) continue;
|
|
46794
|
+
const blob = readFileSync55(path2);
|
|
45471
46795
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
45472
46796
|
}
|
|
45473
46797
|
return /* @__PURE__ */ new Map();
|
|
@@ -45492,7 +46816,7 @@ async function runPackage(source, opts = {}) {
|
|
|
45492
46816
|
const resolved2 = await resolvePackage(source, opts.workDir);
|
|
45493
46817
|
const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
|
|
45494
46818
|
if (!opts.spa && assets.size === 0) {
|
|
45495
|
-
if (resolved2.temp)
|
|
46819
|
+
if (resolved2.temp) rmSync10(resolved2.temp, { recursive: true, force: true });
|
|
45496
46820
|
throw new Error(NO_SPA_MESSAGE);
|
|
45497
46821
|
}
|
|
45498
46822
|
const handler = makePackageRunHandler({
|
|
@@ -45522,7 +46846,7 @@ async function runPackage(source, opts = {}) {
|
|
|
45522
46846
|
warnings: resolved2.warnings,
|
|
45523
46847
|
close: () => new Promise((done) => {
|
|
45524
46848
|
server.close(() => {
|
|
45525
|
-
if (resolved2.temp)
|
|
46849
|
+
if (resolved2.temp) rmSync10(resolved2.temp, { recursive: true, force: true });
|
|
45526
46850
|
done();
|
|
45527
46851
|
});
|
|
45528
46852
|
})
|
|
@@ -45549,15 +46873,15 @@ __export(run_browser_exports, {
|
|
|
45549
46873
|
runInBrowser: () => runInBrowser
|
|
45550
46874
|
});
|
|
45551
46875
|
import { createServer as createServer5 } from "node:http";
|
|
45552
|
-
import { existsSync as
|
|
46876
|
+
import { existsSync as existsSync51, readFileSync as readFileSync56 } from "node:fs";
|
|
45553
46877
|
import { spawnSync as spawnSync3, execFile as execFile3 } from "node:child_process";
|
|
45554
|
-
import { dirname as
|
|
46878
|
+
import { dirname as dirname28, resolve as resolve40 } from "node:path";
|
|
45555
46879
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
45556
46880
|
function stagedDir() {
|
|
45557
46881
|
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve40(process.env.HIMI_BROWSER_PLANE_OUT) : resolve40(REPO, "packages", "serve", "dist", "browser-plane");
|
|
45558
46882
|
}
|
|
45559
46883
|
function missingStaged() {
|
|
45560
|
-
return [...SERVED].filter((f) => !
|
|
46884
|
+
return [...SERVED].filter((f) => !existsSync51(resolve40(stagedDir(), f))).sort();
|
|
45561
46885
|
}
|
|
45562
46886
|
function ensureBrowserPlaneStaged() {
|
|
45563
46887
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
@@ -45647,7 +46971,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
45647
46971
|
}
|
|
45648
46972
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
45649
46973
|
if (SERVED.has(name)) {
|
|
45650
|
-
if (!
|
|
46974
|
+
if (!existsSync51(resolve40(stagedDir(), name))) {
|
|
45651
46975
|
const restaged = ensureBrowserPlaneStaged();
|
|
45652
46976
|
if (!restaged.ok) {
|
|
45653
46977
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -45657,7 +46981,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
45657
46981
|
}
|
|
45658
46982
|
let bytes2;
|
|
45659
46983
|
try {
|
|
45660
|
-
bytes2 =
|
|
46984
|
+
bytes2 = readFileSync56(resolve40(stagedDir(), name));
|
|
45661
46985
|
} catch (e) {
|
|
45662
46986
|
res.writeHead(503, { "content-type": "application/json" });
|
|
45663
46987
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -45700,7 +47024,7 @@ var HERE, REPO, SERVED;
|
|
|
45700
47024
|
var init_run_browser = __esm({
|
|
45701
47025
|
"src/run-browser.ts"() {
|
|
45702
47026
|
init_file_store();
|
|
45703
|
-
HERE =
|
|
47027
|
+
HERE = dirname28(fileURLToPath23(import.meta.url));
|
|
45704
47028
|
REPO = resolve40(HERE, "..", "..", "..");
|
|
45705
47029
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
45706
47030
|
}
|
|
@@ -46120,7 +47444,7 @@ __export(preflight_exports, {
|
|
|
46120
47444
|
parseStoreConfig: () => parseStoreConfig,
|
|
46121
47445
|
requireEnv: () => requireEnv
|
|
46122
47446
|
});
|
|
46123
|
-
import { existsSync as
|
|
47447
|
+
import { existsSync as existsSync52, readFileSync as readFileSync57 } from "node:fs";
|
|
46124
47448
|
import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve41 } from "node:path";
|
|
46125
47449
|
function isInsideRepo(p) {
|
|
46126
47450
|
const rel = relative7(REPO_ROOT3, resolve41(p));
|
|
@@ -46177,10 +47501,10 @@ function parseStoreConfig(text4) {
|
|
|
46177
47501
|
}
|
|
46178
47502
|
function loadStoreConfig(app) {
|
|
46179
47503
|
const p = storeConfigPath(app);
|
|
46180
|
-
if (!
|
|
47504
|
+
if (!existsSync52(p)) {
|
|
46181
47505
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
46182
47506
|
}
|
|
46183
|
-
return parseStoreConfig(
|
|
47507
|
+
return parseStoreConfig(readFileSync57(p, "utf8"));
|
|
46184
47508
|
}
|
|
46185
47509
|
var init_preflight = __esm({
|
|
46186
47510
|
"../store-release/preflight.ts"() {
|
|
@@ -46199,19 +47523,19 @@ __export(credential_profile_exports, {
|
|
|
46199
47523
|
profilePath: () => profilePath,
|
|
46200
47524
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
46201
47525
|
});
|
|
46202
|
-
import { existsSync as
|
|
47526
|
+
import { existsSync as existsSync53, readFileSync as readFileSync58 } from "node:fs";
|
|
46203
47527
|
import { homedir as homedir5 } from "node:os";
|
|
46204
|
-
import { join as
|
|
47528
|
+
import { join as join48 } from "node:path";
|
|
46205
47529
|
function credentialsDir(home = homedir5()) {
|
|
46206
|
-
return
|
|
47530
|
+
return join48(home, ".himalaya", "store-credentials");
|
|
46207
47531
|
}
|
|
46208
47532
|
function profilePath(name, home = homedir5()) {
|
|
46209
47533
|
if (!PROFILE_NAME.test(name)) {
|
|
46210
47534
|
throw new Error(
|
|
46211
|
-
`credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${
|
|
47535
|
+
`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.`
|
|
46212
47536
|
);
|
|
46213
47537
|
}
|
|
46214
|
-
return
|
|
47538
|
+
return join48(credentialsDir(home), `${name}.json`);
|
|
46215
47539
|
}
|
|
46216
47540
|
function parseProfile(text4, label2) {
|
|
46217
47541
|
let doc;
|
|
@@ -46242,8 +47566,8 @@ function resolveStoreCredentials(opts) {
|
|
|
46242
47566
|
const { app, cfg } = opts;
|
|
46243
47567
|
const env = opts.env ?? process.env;
|
|
46244
47568
|
const home = opts.home ?? homedir5();
|
|
46245
|
-
const read = opts.readProfile ?? ((p) =>
|
|
46246
|
-
const exists = opts.profileExists ??
|
|
47569
|
+
const read = opts.readProfile ?? ((p) => readFileSync58(p, "utf8"));
|
|
47570
|
+
const exists = opts.profileExists ?? existsSync53;
|
|
46247
47571
|
const ios = cfg.ios ?? {};
|
|
46248
47572
|
const flagName = opts.profileFlag?.trim();
|
|
46249
47573
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -46323,9 +47647,9 @@ __export(preflight_app_exports, {
|
|
|
46323
47647
|
preflightApp: () => preflightApp,
|
|
46324
47648
|
profileAccount: () => profileAccount
|
|
46325
47649
|
});
|
|
46326
|
-
import { readFileSync as
|
|
47650
|
+
import { readFileSync as readFileSync59, existsSync as existsSync54, readdirSync as readdirSync25, statSync as statSync12 } from "node:fs";
|
|
46327
47651
|
import { createHash as createHash23 } from "node:crypto";
|
|
46328
|
-
import { join as
|
|
47652
|
+
import { join as join49 } from "node:path";
|
|
46329
47653
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
46330
47654
|
const f = [];
|
|
46331
47655
|
const has = (re, s) => re.test(s);
|
|
@@ -46389,13 +47713,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
46389
47713
|
}
|
|
46390
47714
|
}
|
|
46391
47715
|
async function preflightApp(app, opts = {}) {
|
|
46392
|
-
const projectYml =
|
|
46393
|
-
const storeConfig =
|
|
47716
|
+
const projectYml = existsSync54(iosProjectYml(app)) ? readFileSync59(iosProjectYml(app), "utf8") : "";
|
|
47717
|
+
const storeConfig = existsSync54(storeConfigPath(app)) ? readFileSync59(storeConfigPath(app), "utf8") : "";
|
|
46394
47718
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
46395
47719
|
const findings = analyze(
|
|
46396
47720
|
projectYml,
|
|
46397
47721
|
storeConfig,
|
|
46398
|
-
await appIconState(
|
|
47722
|
+
await appIconState(join49(appDir(app), "ios")),
|
|
46399
47723
|
profileAccount(app, storeConfig, opts)
|
|
46400
47724
|
);
|
|
46401
47725
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -46424,18 +47748,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
46424
47748
|
return f;
|
|
46425
47749
|
}
|
|
46426
47750
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
46427
|
-
const root =
|
|
47751
|
+
const root = join49(storeDir(app), "metadata");
|
|
46428
47752
|
const out = /* @__PURE__ */ new Set();
|
|
46429
|
-
if (
|
|
46430
|
-
for (const n of
|
|
47753
|
+
if (existsSync54(root)) {
|
|
47754
|
+
for (const n of readdirSync25(root)) if (n.endsWith(".txt")) out.add(n);
|
|
46431
47755
|
}
|
|
46432
|
-
if (
|
|
47756
|
+
if (existsSync54(join49(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
46433
47757
|
return out;
|
|
46434
47758
|
}
|
|
46435
47759
|
function reviewInfoFiles(app) {
|
|
46436
|
-
const dir =
|
|
46437
|
-
if (!
|
|
46438
|
-
return new Set(
|
|
47760
|
+
const dir = join49(storeDir(app), "review_information");
|
|
47761
|
+
if (!existsSync54(dir)) return /* @__PURE__ */ new Set();
|
|
47762
|
+
return new Set(readdirSync25(dir).filter((n) => n.endsWith(".txt")));
|
|
46439
47763
|
}
|
|
46440
47764
|
function isValidAppStoreSize(w, h) {
|
|
46441
47765
|
return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
|
|
@@ -46544,12 +47868,12 @@ function analyzePlayListing(assets) {
|
|
|
46544
47868
|
return f;
|
|
46545
47869
|
}
|
|
46546
47870
|
function playListingAssets(app, locale = "en-US") {
|
|
46547
|
-
const dir =
|
|
47871
|
+
const dir = join49(storeDir(app), "play", locale, "images");
|
|
46548
47872
|
const read = (names) => {
|
|
46549
47873
|
for (const name of names) {
|
|
46550
|
-
const p =
|
|
47874
|
+
const p = join49(dir, name);
|
|
46551
47875
|
try {
|
|
46552
|
-
if (
|
|
47876
|
+
if (statSync12(p).isFile()) return { name, bytes: readFileSync59(p) };
|
|
46553
47877
|
} catch {
|
|
46554
47878
|
}
|
|
46555
47879
|
}
|
|
@@ -46580,26 +47904,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
46580
47904
|
return f;
|
|
46581
47905
|
}
|
|
46582
47906
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
46583
|
-
const dir =
|
|
46584
|
-
if (!
|
|
46585
|
-
return new Set(
|
|
47907
|
+
const dir = join49(storeDir(app), "metadata", locale);
|
|
47908
|
+
if (!existsSync54(dir)) return /* @__PURE__ */ new Set();
|
|
47909
|
+
return new Set(readdirSync25(dir).filter((n) => n.endsWith(".txt")));
|
|
46586
47910
|
}
|
|
46587
47911
|
function listScreenshots(app, locale = "en-US") {
|
|
46588
47912
|
const out = [];
|
|
46589
|
-
const flat =
|
|
46590
|
-
if (
|
|
46591
|
-
for (const png of
|
|
46592
|
-
const sz = pngSize(
|
|
47913
|
+
const flat = join49(storeDir(app), "screenshots", locale);
|
|
47914
|
+
if (existsSync54(flat)) {
|
|
47915
|
+
for (const png of readdirSync25(flat).filter((n) => n.endsWith(".png"))) {
|
|
47916
|
+
const sz = pngSize(readFileSync59(join49(flat, png)));
|
|
46593
47917
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
46594
47918
|
}
|
|
46595
47919
|
}
|
|
46596
|
-
const legacy =
|
|
46597
|
-
if (
|
|
46598
|
-
for (const deviceDir of
|
|
46599
|
-
const d =
|
|
46600
|
-
if (!
|
|
46601
|
-
for (const png of
|
|
46602
|
-
const sz = pngSize(
|
|
47920
|
+
const legacy = join49(storeDir(app), "metadata", locale, "screenshots");
|
|
47921
|
+
if (existsSync54(legacy)) {
|
|
47922
|
+
for (const deviceDir of readdirSync25(legacy)) {
|
|
47923
|
+
const d = join49(legacy, deviceDir);
|
|
47924
|
+
if (!statSync12(d).isDirectory()) continue;
|
|
47925
|
+
for (const png of readdirSync25(d).filter((n) => n.endsWith(".png"))) {
|
|
47926
|
+
const sz = pngSize(readFileSync59(join49(d, png)));
|
|
46603
47927
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
46604
47928
|
}
|
|
46605
47929
|
}
|
|
@@ -46607,13 +47931,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
46607
47931
|
return out;
|
|
46608
47932
|
}
|
|
46609
47933
|
function placeholderHashes2() {
|
|
46610
|
-
const templateIos =
|
|
46611
|
-
if (!
|
|
46612
|
-
for (const target of
|
|
46613
|
-
const p =
|
|
47934
|
+
const templateIos = join49(appDir("_template"), "ios");
|
|
47935
|
+
if (!existsSync54(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
47936
|
+
for (const target of readdirSync25(templateIos)) {
|
|
47937
|
+
const p = join49(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
46614
47938
|
try {
|
|
46615
|
-
if (!
|
|
46616
|
-
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(
|
|
47939
|
+
if (!statSync12(p).isFile()) continue;
|
|
47940
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync59(p)).digest("hex")];
|
|
46617
47941
|
} catch {
|
|
46618
47942
|
}
|
|
46619
47943
|
}
|
|
@@ -46644,12 +47968,12 @@ async function pixelIssues(bytes2) {
|
|
|
46644
47968
|
}
|
|
46645
47969
|
}
|
|
46646
47970
|
async function appIconState(iosDir) {
|
|
46647
|
-
if (!
|
|
46648
|
-
for (const target of
|
|
46649
|
-
const p =
|
|
47971
|
+
if (!existsSync54(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
47972
|
+
for (const target of readdirSync25(iosDir)) {
|
|
47973
|
+
const p = join49(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
46650
47974
|
try {
|
|
46651
|
-
if (!
|
|
46652
|
-
const bytes2 =
|
|
47975
|
+
if (!statSync12(p).isFile()) continue;
|
|
47976
|
+
const bytes2 = readFileSync59(p);
|
|
46653
47977
|
const hash = createHash23("sha256").update(bytes2).digest("hex");
|
|
46654
47978
|
const pixels = await pixelIssues(bytes2);
|
|
46655
47979
|
return {
|
|
@@ -46721,7 +48045,7 @@ __export(version_exports, {
|
|
|
46721
48045
|
setAndroidVersion: () => setAndroidVersion,
|
|
46722
48046
|
setIosVersion: () => setIosVersion
|
|
46723
48047
|
});
|
|
46724
|
-
import { readFileSync as
|
|
48048
|
+
import { readFileSync as readFileSync60, writeFileSync as writeFileSync21 } from "node:fs";
|
|
46725
48049
|
function readIosVersion(projectYml) {
|
|
46726
48050
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
46727
48051
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -46779,15 +48103,15 @@ function setAndroidVersion(gradle, v) {
|
|
|
46779
48103
|
function bumpVersion(app, opts) {
|
|
46780
48104
|
const iosPath = iosProjectYml(app);
|
|
46781
48105
|
const gradlePath = androidGradle(app);
|
|
46782
|
-
const iosYml =
|
|
46783
|
-
const gradle =
|
|
48106
|
+
const iosYml = readFileSync60(iosPath, "utf8");
|
|
48107
|
+
const gradle = readFileSync60(gradlePath, "utf8");
|
|
46784
48108
|
const current = readIosVersion(iosYml);
|
|
46785
48109
|
const next = {
|
|
46786
48110
|
marketing: opts.marketing ?? current.marketing,
|
|
46787
48111
|
build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
|
|
46788
48112
|
};
|
|
46789
|
-
|
|
46790
|
-
|
|
48113
|
+
writeFileSync21(iosPath, setIosVersion(iosYml, next));
|
|
48114
|
+
writeFileSync21(gradlePath, setAndroidVersion(gradle, next));
|
|
46791
48115
|
return next;
|
|
46792
48116
|
}
|
|
46793
48117
|
var init_version = __esm({
|
|
@@ -46797,7 +48121,7 @@ var init_version = __esm({
|
|
|
46797
48121
|
});
|
|
46798
48122
|
|
|
46799
48123
|
// ../store-release/register-bundle.ts
|
|
46800
|
-
import { readFileSync as
|
|
48124
|
+
import { readFileSync as readFileSync61 } from "node:fs";
|
|
46801
48125
|
import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
|
|
46802
48126
|
function b64url2(b) {
|
|
46803
48127
|
return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -46815,7 +48139,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
|
|
|
46815
48139
|
async function registerBundleId(opts) {
|
|
46816
48140
|
const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
46817
48141
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
46818
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
48142
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync61(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
46819
48143
|
const res = await fetch(`${ASC_API}/v1/bundleIds`, {
|
|
46820
48144
|
method: "POST",
|
|
46821
48145
|
headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
|
|
@@ -46869,7 +48193,7 @@ __export(asc_status_exports, {
|
|
|
46869
48193
|
ascStatus: () => ascStatus,
|
|
46870
48194
|
buildVerdict: () => buildVerdict
|
|
46871
48195
|
});
|
|
46872
|
-
import { readFileSync as
|
|
48196
|
+
import { readFileSync as readFileSync62 } from "node:fs";
|
|
46873
48197
|
function buildVerdict(builds) {
|
|
46874
48198
|
if (!builds.length) {
|
|
46875
48199
|
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).";
|
|
@@ -46883,7 +48207,7 @@ function buildVerdict(builds) {
|
|
|
46883
48207
|
function client(creds) {
|
|
46884
48208
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
46885
48209
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
46886
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
48210
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync62(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
46887
48211
|
return async (path2) => {
|
|
46888
48212
|
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
46889
48213
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
@@ -46932,7 +48256,7 @@ var init_asc_status = __esm({
|
|
|
46932
48256
|
// ../../core/functions-secrets/src/vault.ts
|
|
46933
48257
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
|
|
46934
48258
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
46935
|
-
import { dirname as
|
|
48259
|
+
import { dirname as dirname29 } from "node:path";
|
|
46936
48260
|
function createJsonSecretStore(filePath) {
|
|
46937
48261
|
const read = async () => {
|
|
46938
48262
|
try {
|
|
@@ -46945,7 +48269,7 @@ function createJsonSecretStore(filePath) {
|
|
|
46945
48269
|
}
|
|
46946
48270
|
};
|
|
46947
48271
|
const write2 = async (records) => {
|
|
46948
|
-
await mkdir(
|
|
48272
|
+
await mkdir(dirname29(filePath), { recursive: true });
|
|
46949
48273
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
46950
48274
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
46951
48275
|
`, { mode: 384 });
|
|
@@ -47043,7 +48367,7 @@ __export(secrets_exports, {
|
|
|
47043
48367
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
47044
48368
|
runSecretsCommand: () => runSecretsCommand
|
|
47045
48369
|
});
|
|
47046
|
-
import { readFileSync as
|
|
48370
|
+
import { readFileSync as readFileSync63 } from "node:fs";
|
|
47047
48371
|
function environment(value) {
|
|
47048
48372
|
if (value === "preview" || value === "production") return value;
|
|
47049
48373
|
throw new Error("--environment must be preview or production");
|
|
@@ -47074,7 +48398,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
|
|
|
47074
48398
|
io.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
47075
48399
|
return 0;
|
|
47076
48400
|
}
|
|
47077
|
-
const value = options.readValue ? options.readValue() :
|
|
48401
|
+
const value = options.readValue ? options.readValue() : readFileSync63(0, "utf8").replace(/\r?\n$/, "");
|
|
47078
48402
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
47079
48403
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
47080
48404
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -47103,7 +48427,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
47103
48427
|
}
|
|
47104
48428
|
let body;
|
|
47105
48429
|
if (operation !== "list") {
|
|
47106
|
-
const value = options.readValue ? options.readValue() :
|
|
48430
|
+
const value = options.readValue ? options.readValue() : readFileSync63(0, "utf8").replace(/\r?\n$/, "");
|
|
47107
48431
|
body = JSON.stringify({ value });
|
|
47108
48432
|
}
|
|
47109
48433
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -47139,15 +48463,15 @@ __export(notify_exports, {
|
|
|
47139
48463
|
runNotify: () => runNotify,
|
|
47140
48464
|
saveAdminSession: () => saveAdminSession
|
|
47141
48465
|
});
|
|
47142
|
-
import { chmodSync as chmodSync3, mkdirSync as
|
|
48466
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync25, readFileSync as readFileSync64, writeFileSync as writeFileSync22 } from "node:fs";
|
|
47143
48467
|
import { homedir as homedir6 } from "node:os";
|
|
47144
|
-
import { dirname as
|
|
48468
|
+
import { dirname as dirname30, join as join50 } from "node:path";
|
|
47145
48469
|
function defaultSessionsPath() {
|
|
47146
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
48470
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join50(homedir6(), ".himalaya", "admin-sessions.json");
|
|
47147
48471
|
}
|
|
47148
48472
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
47149
48473
|
try {
|
|
47150
|
-
return JSON.parse(
|
|
48474
|
+
return JSON.parse(readFileSync64(path2, "utf8"));
|
|
47151
48475
|
} catch {
|
|
47152
48476
|
return {};
|
|
47153
48477
|
}
|
|
@@ -47155,10 +48479,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
47155
48479
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
47156
48480
|
const file = loadSessionsFile(path2);
|
|
47157
48481
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
47158
|
-
|
|
47159
|
-
|
|
48482
|
+
mkdirSync25(dirname30(path2), { recursive: true, mode: 448 });
|
|
48483
|
+
writeFileSync22(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
47160
48484
|
try {
|
|
47161
|
-
chmodSync3(
|
|
48485
|
+
chmodSync3(dirname30(path2), 448);
|
|
47162
48486
|
chmodSync3(path2, 384);
|
|
47163
48487
|
} catch {
|
|
47164
48488
|
}
|
|
@@ -47417,56 +48741,6 @@ var init_notify = __esm({
|
|
|
47417
48741
|
}
|
|
47418
48742
|
});
|
|
47419
48743
|
|
|
47420
|
-
// src/site-analyze/types.ts
|
|
47421
|
-
function isRedirectUri(value) {
|
|
47422
|
-
return /^[a-z][a-z0-9+.-]*:\/\/\S*$/i.test(value);
|
|
47423
|
-
}
|
|
47424
|
-
function assertRedirectUri(value) {
|
|
47425
|
-
const trimmed = value.trim();
|
|
47426
|
-
if (!isRedirectUri(trimmed)) {
|
|
47427
|
-
throw new Error(
|
|
47428
|
-
`--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\`.`
|
|
47429
|
-
);
|
|
47430
|
-
}
|
|
47431
|
-
return trimmed;
|
|
47432
|
-
}
|
|
47433
|
-
var BOOK_SCHEMA_VERSION, KNOWN_VERTICALS;
|
|
47434
|
-
var init_types2 = __esm({
|
|
47435
|
-
"src/site-analyze/types.ts"() {
|
|
47436
|
-
BOOK_SCHEMA_VERSION = 2;
|
|
47437
|
-
KNOWN_VERTICALS = [
|
|
47438
|
-
"store",
|
|
47439
|
-
"bookings",
|
|
47440
|
-
"restaurants",
|
|
47441
|
-
"programs",
|
|
47442
|
-
"plans",
|
|
47443
|
-
"feed",
|
|
47444
|
-
"members",
|
|
47445
|
-
"forum",
|
|
47446
|
-
"coupons",
|
|
47447
|
-
"notifications",
|
|
47448
|
-
"loyalty",
|
|
47449
|
-
"reviews",
|
|
47450
|
-
"portfolio",
|
|
47451
|
-
"reservations",
|
|
47452
|
-
"invoices",
|
|
47453
|
-
"badges",
|
|
47454
|
-
"notifsettings",
|
|
47455
|
-
"events",
|
|
47456
|
-
"blog",
|
|
47457
|
-
"groups",
|
|
47458
|
-
"cms",
|
|
47459
|
-
"donations",
|
|
47460
|
-
"giftCards",
|
|
47461
|
-
"videos",
|
|
47462
|
-
"podcasts",
|
|
47463
|
-
"forms",
|
|
47464
|
-
"galleries",
|
|
47465
|
-
"inbox"
|
|
47466
|
-
];
|
|
47467
|
-
}
|
|
47468
|
-
});
|
|
47469
|
-
|
|
47470
48744
|
// src/site-analyze/rest.ts
|
|
47471
48745
|
function resolveWixUrl(path2) {
|
|
47472
48746
|
if (/^https?:\/\//i.test(path2)) return path2;
|
|
@@ -49372,30 +50646,30 @@ function sectionsFrom(pages) {
|
|
|
49372
50646
|
const raw = page.sections?.length ? page.sections : page.headings.map((heading) => ({ heading, body: void 0 }));
|
|
49373
50647
|
let fromThisPage = 0;
|
|
49374
50648
|
for (const s of raw) {
|
|
49375
|
-
if (fromThisPage >=
|
|
49376
|
-
const heading = copyOrDrop(s.heading,
|
|
50649
|
+
if (fromThisPage >= CAP2.sectionsPerPage) break;
|
|
50650
|
+
const heading = copyOrDrop(s.heading, CAP2.heading);
|
|
49377
50651
|
if (!heading) continue;
|
|
49378
50652
|
const key2 = heading.toLowerCase();
|
|
49379
50653
|
if (seen.has(key2)) continue;
|
|
49380
50654
|
seen.add(key2);
|
|
49381
|
-
const body = copyOrDrop(s.body,
|
|
50655
|
+
const body = copyOrDrop(s.body, CAP2.body);
|
|
49382
50656
|
out.push({ heading, ...body ? { body } : {}, pageUrl: page.url, role: page.role });
|
|
49383
50657
|
fromThisPage++;
|
|
49384
|
-
if (out.length >=
|
|
50658
|
+
if (out.length >= CAP2.sections) return out;
|
|
49385
50659
|
}
|
|
49386
50660
|
}
|
|
49387
50661
|
return out;
|
|
49388
50662
|
}
|
|
49389
50663
|
function taglineFrom(identity, pages, published) {
|
|
49390
|
-
const owned = copyOrDrop(identity.description,
|
|
50664
|
+
const owned = copyOrDrop(identity.description, CAP2.tagline);
|
|
49391
50665
|
if (owned && identity.source === "owner-api") return { text: owned, source: "site-properties" };
|
|
49392
50666
|
const home = pages.find((p) => p.role === "home") ?? pages[0];
|
|
49393
|
-
const og = copyOrDrop(home?.meta?.ogDescription ?? published?.meta?.ogDescription,
|
|
50667
|
+
const og = copyOrDrop(home?.meta?.ogDescription ?? published?.meta?.ogDescription, CAP2.tagline);
|
|
49394
50668
|
if (og) return { text: og, source: "og" };
|
|
49395
|
-
const meta = copyOrDrop(home?.meta?.description ?? published?.meta?.description,
|
|
50669
|
+
const meta = copyOrDrop(home?.meta?.description ?? published?.meta?.description, CAP2.tagline);
|
|
49396
50670
|
if (meta) return { text: meta, source: "meta" };
|
|
49397
50671
|
if (owned) return { text: owned, source: "hero" };
|
|
49398
|
-
const hero = copyOrDrop(home?.heroCopy,
|
|
50672
|
+
const hero = copyOrDrop(home?.heroCopy, CAP2.tagline);
|
|
49399
50673
|
return hero ? { text: hero, source: "hero" } : null;
|
|
49400
50674
|
}
|
|
49401
50675
|
function suggestKeys(args) {
|
|
@@ -49404,9 +50678,9 @@ function suggestKeys(args) {
|
|
|
49404
50678
|
const installed = new Set(installedVerticals);
|
|
49405
50679
|
const set = (key2, value) => {
|
|
49406
50680
|
if (!key2 || out[key2] || !value) return;
|
|
49407
|
-
if (Object.keys(out).length >=
|
|
50681
|
+
if (Object.keys(out).length >= CAP2.keys) return;
|
|
49408
50682
|
if (key2.length > 120 || !/^[A-Za-z0-9._:-]+$/.test(key2)) return;
|
|
49409
|
-
out[key2] = value.slice(0,
|
|
50683
|
+
out[key2] = value.slice(0, CAP2.value);
|
|
49410
50684
|
};
|
|
49411
50685
|
const allowed2 = (rule) => !rule.vertical || installed.has(rule.vertical);
|
|
49412
50686
|
for (const label2 of nav) {
|
|
@@ -49428,42 +50702,42 @@ function buildCopyChapter(args) {
|
|
|
49428
50702
|
const { look, probes, identity, installedVerticals, published } = args;
|
|
49429
50703
|
const pages = pagesOf(look);
|
|
49430
50704
|
const sections = sectionsFrom(pages);
|
|
49431
|
-
const nav = dedupe2(look.navLabels.map((n) => copyOrDrop(n,
|
|
50705
|
+
const nav = dedupe2(look.navLabels.map((n) => copyOrDrop(n, CAP2.heading)), CAP2.nav);
|
|
49432
50706
|
const tagline = taglineFrom(identity, pages, published);
|
|
49433
50707
|
const ctas = dedupe2(
|
|
49434
50708
|
pages.flatMap((p) => p.ctaLabels?.length ? p.ctaLabels : p.layout.ctas),
|
|
49435
|
-
|
|
50709
|
+
CAP2.ctas
|
|
49436
50710
|
);
|
|
49437
50711
|
const faq = [];
|
|
49438
50712
|
for (const page of pages) {
|
|
49439
50713
|
for (const pair of page.faq ?? []) {
|
|
49440
|
-
if (faq.length >=
|
|
50714
|
+
if (faq.length >= CAP2.faq) break;
|
|
49441
50715
|
if (faq.some((f) => f.q.toLowerCase() === pair.q.toLowerCase())) continue;
|
|
49442
50716
|
faq.push({ ...pair, pageUrl: page.url });
|
|
49443
50717
|
}
|
|
49444
50718
|
}
|
|
49445
50719
|
const about = pages.map((p) => p.about).find(Boolean) ?? sections.find((s) => ABOUT_RULE.re.test(s.heading))?.body ?? null;
|
|
49446
|
-
if (faq.length <
|
|
50720
|
+
if (faq.length < CAP2.faq) {
|
|
49447
50721
|
const candidates = copyPageOrder(pages).flatMap(
|
|
49448
50722
|
(page) => (page.sections ?? []).map((sec) => ({
|
|
49449
|
-
heading: copyOrDrop(sec.heading,
|
|
49450
|
-
body: copyOrDrop(sec.body,
|
|
50723
|
+
heading: copyOrDrop(sec.heading, CAP2.heading),
|
|
50724
|
+
body: copyOrDrop(sec.body, CAP2.body),
|
|
49451
50725
|
pageUrl: page.url
|
|
49452
50726
|
}))
|
|
49453
50727
|
);
|
|
49454
50728
|
for (const section2 of candidates) {
|
|
49455
|
-
if (faq.length >=
|
|
50729
|
+
if (faq.length >= CAP2.faq) break;
|
|
49456
50730
|
if (!section2.heading || !section2.body || !/\?\s*$/.test(section2.heading)) continue;
|
|
49457
50731
|
if (about && section2.body === about) continue;
|
|
49458
50732
|
if (faq.some((f) => f.q.toLowerCase() === section2.heading.toLowerCase())) continue;
|
|
49459
50733
|
faq.push({ q: section2.heading, a: section2.body, pageUrl: section2.pageUrl });
|
|
49460
50734
|
}
|
|
49461
50735
|
}
|
|
49462
|
-
const testimonials = dedupe2(pages.flatMap((p) => p.testimonials ?? []),
|
|
50736
|
+
const testimonials = dedupe2(pages.flatMap((p) => p.testimonials ?? []), CAP2.testimonials);
|
|
49463
50737
|
const blogExcerpts = [];
|
|
49464
50738
|
for (const it of probes.find((p) => p.vertical === "blog")?.items ?? []) {
|
|
49465
|
-
if (blogExcerpts.length >=
|
|
49466
|
-
const title = copyOrDrop(it.title,
|
|
50739
|
+
if (blogExcerpts.length >= CAP2.blogExcerpts) break;
|
|
50740
|
+
const title = copyOrDrop(it.title, CAP2.heading);
|
|
49467
50741
|
if (!title) continue;
|
|
49468
50742
|
blogExcerpts.push({ title, ...it.description ? { excerpt: it.description } : {} });
|
|
49469
50743
|
}
|
|
@@ -49471,8 +50745,8 @@ function buildCopyChapter(args) {
|
|
|
49471
50745
|
for (const probe of probes) {
|
|
49472
50746
|
if (probe.vertical === "members") continue;
|
|
49473
50747
|
for (const item of probe.items) {
|
|
49474
|
-
if (catalog.length >=
|
|
49475
|
-
const title = copyOrDrop(item.title,
|
|
50748
|
+
if (catalog.length >= CAP2.catalog) break;
|
|
50749
|
+
const title = copyOrDrop(item.title, CAP2.heading);
|
|
49476
50750
|
if (!title) continue;
|
|
49477
50751
|
catalog.push({
|
|
49478
50752
|
vertical: probe.vertical,
|
|
@@ -49484,7 +50758,7 @@ function buildCopyChapter(args) {
|
|
|
49484
50758
|
if (!sections.length) {
|
|
49485
50759
|
for (const heading of published?.headings ?? []) {
|
|
49486
50760
|
sections.push({ heading, pageUrl: identity.url.primary ?? "", role: "home" });
|
|
49487
|
-
if (sections.length >=
|
|
50761
|
+
if (sections.length >= CAP2.sections) break;
|
|
49488
50762
|
}
|
|
49489
50763
|
}
|
|
49490
50764
|
const empty = !tagline && !sections.length && !nav.length && !ctas.length && !catalog.length && !faq.length && !testimonials.length && !about && !blogExcerpts.length;
|
|
@@ -49505,11 +50779,11 @@ function buildCopyChapter(args) {
|
|
|
49505
50779
|
suggestedCopyKeys: suggestKeys({ nav, sections, tagline, installedVerticals })
|
|
49506
50780
|
};
|
|
49507
50781
|
}
|
|
49508
|
-
var
|
|
50782
|
+
var CAP2, SYSTEM_PAGE_RE, ROLE_PRIORITY, KEY_RULES, ABOUT_RULE;
|
|
49509
50783
|
var init_copy = __esm({
|
|
49510
50784
|
"src/site-analyze/copy.ts"() {
|
|
49511
50785
|
init_copy_clean();
|
|
49512
|
-
|
|
50786
|
+
CAP2 = {
|
|
49513
50787
|
sections: 40,
|
|
49514
50788
|
sectionsPerPage: 8,
|
|
49515
50789
|
ctas: 24,
|
|
@@ -50732,8 +52006,8 @@ var init_brand_font = __esm({
|
|
|
50732
52006
|
});
|
|
50733
52007
|
|
|
50734
52008
|
// src/site-analyze/write-artifacts.ts
|
|
50735
|
-
import { mkdirSync as
|
|
50736
|
-
import { join as
|
|
52009
|
+
import { mkdirSync as mkdirSync26, writeFileSync as writeFileSync23 } from "node:fs";
|
|
52010
|
+
import { join as join51 } from "node:path";
|
|
50737
52011
|
function attachVeloSources(book, sources, put) {
|
|
50738
52012
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
50739
52013
|
for (const f of book.velo.files) {
|
|
@@ -50888,13 +52162,13 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
50888
52162
|
}
|
|
50889
52163
|
async function writeBusinessBook(result, opts) {
|
|
50890
52164
|
const out = opts.outDir;
|
|
50891
|
-
|
|
50892
|
-
|
|
52165
|
+
mkdirSync26(join51(out, "evidence/pages"), { recursive: true });
|
|
52166
|
+
mkdirSync26(join51(out, "media/catalog"), { recursive: true });
|
|
50893
52167
|
const files = [];
|
|
50894
52168
|
const put = (rel, body) => {
|
|
50895
|
-
const p =
|
|
50896
|
-
|
|
50897
|
-
|
|
52169
|
+
const p = join51(out, rel);
|
|
52170
|
+
mkdirSync26(join51(p, ".."), { recursive: true });
|
|
52171
|
+
writeFileSync23(p, body);
|
|
50898
52172
|
files.push(rel);
|
|
50899
52173
|
};
|
|
50900
52174
|
const book = result.book;
|
|
@@ -50986,336 +52260,9 @@ var init_customer_build = __esm({
|
|
|
50986
52260
|
}
|
|
50987
52261
|
});
|
|
50988
52262
|
|
|
50989
|
-
// src/site-analyze/home-descriptor.ts
|
|
50990
|
-
function objectEnd(src, open) {
|
|
50991
|
-
let depth = 0;
|
|
50992
|
-
let inString = false;
|
|
50993
|
-
for (let i = open; i < src.length; i += 1) {
|
|
50994
|
-
const c = src[i];
|
|
50995
|
-
if (inString) {
|
|
50996
|
-
if (c === "\\") i += 1;
|
|
50997
|
-
else if (c === '"') inString = false;
|
|
50998
|
-
continue;
|
|
50999
|
-
}
|
|
51000
|
-
if (c === '"') inString = true;
|
|
51001
|
-
else if (c === "{") depth += 1;
|
|
51002
|
-
else if (c === "}") {
|
|
51003
|
-
depth -= 1;
|
|
51004
|
-
if (depth === 0) return i + 1;
|
|
51005
|
-
}
|
|
51006
|
-
}
|
|
51007
|
-
return -1;
|
|
51008
|
-
}
|
|
51009
|
-
function hasScreen(src, screenId) {
|
|
51010
|
-
const id = escapeRe2(screenId);
|
|
51011
|
-
return new RegExp(`"${id}": \\{\\s*"screenId": "${id}"`).test(src);
|
|
51012
|
-
}
|
|
51013
|
-
function findNode(root, pred) {
|
|
51014
|
-
if (Array.isArray(root)) {
|
|
51015
|
-
for (const child of root) {
|
|
51016
|
-
const hit = findNode(child, pred);
|
|
51017
|
-
if (hit) return hit;
|
|
51018
|
-
}
|
|
51019
|
-
return void 0;
|
|
51020
|
-
}
|
|
51021
|
-
if (!root || typeof root !== "object") return void 0;
|
|
51022
|
-
const node = root;
|
|
51023
|
-
if (node.body && typeof node.body === "object" && pred(node)) return node;
|
|
51024
|
-
for (const value of Object.values(root)) {
|
|
51025
|
-
const hit = findNode(value, pred);
|
|
51026
|
-
if (hit) return hit;
|
|
51027
|
-
}
|
|
51028
|
-
return void 0;
|
|
51029
|
-
}
|
|
51030
|
-
function cloneCell(template, prefix, vertical, card) {
|
|
51031
|
-
const cell = structuredClone(template);
|
|
51032
|
-
const accent = findNode(cell, (n) => n.body?.type === "Icon" && textProps(n)?.tint === "accentPrimary");
|
|
51033
|
-
const title = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "bodyEmphasis");
|
|
51034
|
-
const body = findNode(cell, (n) => n.body?.type === "Text" && textProps(n)?.style === "footnote");
|
|
51035
|
-
if (!accent || !title || !body || !cell.modifiers) return void 0;
|
|
51036
|
-
const onTap = cell.modifiers.onTap;
|
|
51037
|
-
if (!onTap?.actionId) return void 0;
|
|
51038
|
-
textProps(accent).name = card.icon;
|
|
51039
|
-
textProps(title).text = card.title;
|
|
51040
|
-
textProps(body).text = card.body;
|
|
51041
|
-
cell.modifiers.onTap = { actionId: onTap.actionId, params: { screenId: card.screenId } };
|
|
51042
|
-
cell.id = `${prefix}.${vertical}`;
|
|
51043
|
-
cell.modifiers.accessibilityLabel = card.title;
|
|
51044
|
-
return cell;
|
|
51045
|
-
}
|
|
51046
|
-
function lineIndent(src, open) {
|
|
51047
|
-
return /^[ \t]*/.exec(src.slice(src.lastIndexOf("\n", open) + 1, open))[0];
|
|
51048
|
-
}
|
|
51049
|
-
function serializeAt(node, src, open) {
|
|
51050
|
-
const indent = lineIndent(src, open);
|
|
51051
|
-
return JSON.stringify(node, null, 2).split("\n").map((line, i) => i === 0 ? line : indent + line).join("\n");
|
|
51052
|
-
}
|
|
51053
|
-
function patchGrids(src, installed, patch) {
|
|
51054
|
-
const OPEN = /"id": "([A-Za-z_0-9]+(?:\.[A-Za-z_0-9]+)*\.verticals)"/g;
|
|
51055
|
-
let out = "";
|
|
51056
|
-
let cursor = 0;
|
|
51057
|
-
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
51058
|
-
const open = src.lastIndexOf("{", m.index);
|
|
51059
|
-
if (open < cursor) continue;
|
|
51060
|
-
const close = objectEnd(src, open);
|
|
51061
|
-
if (close < 0) continue;
|
|
51062
|
-
const blob = src.slice(open, close);
|
|
51063
|
-
let node;
|
|
51064
|
-
try {
|
|
51065
|
-
node = JSON.parse(blob);
|
|
51066
|
-
} catch {
|
|
51067
|
-
continue;
|
|
51068
|
-
}
|
|
51069
|
-
const items = node.body?.type === "Grid" ? node.body.props?.items : void 0;
|
|
51070
|
-
if (!Array.isArray(items) || !items.length) continue;
|
|
51071
|
-
const prefix = m[1].slice(0, -".verticals".length);
|
|
51072
|
-
const baked = /* @__PURE__ */ new Map();
|
|
51073
|
-
const foreignCells = [];
|
|
51074
|
-
for (const item of items) {
|
|
51075
|
-
const id = item.id;
|
|
51076
|
-
const legacy = item.modifiers?.accessibilityLabel;
|
|
51077
|
-
const claim = typeof id === "string" && id ? id : typeof legacy === "string" ? legacy : "";
|
|
51078
|
-
const vertical = claim.startsWith(`${prefix}.`) ? claim.slice(prefix.length + 1) : "";
|
|
51079
|
-
if (isKnown(vertical)) baked.set(vertical, item);
|
|
51080
|
-
else if (!GRID_VERTICAL_LABELS.has(vertical)) foreignCells.push(item);
|
|
51081
|
-
}
|
|
51082
|
-
const wanted = [];
|
|
51083
|
-
for (const vertical of EXPLORE_ORDER) {
|
|
51084
|
-
if (!installed.has(vertical)) continue;
|
|
51085
|
-
if (baked.has(vertical)) {
|
|
51086
|
-
wanted.push(vertical);
|
|
51087
|
-
continue;
|
|
51088
|
-
}
|
|
51089
|
-
const card = EXPLORE_CARDS[vertical];
|
|
51090
|
-
if (!hasScreen(src, card.screenId)) {
|
|
51091
|
-
patch.unreachable.push(vertical);
|
|
51092
|
-
continue;
|
|
51093
|
-
}
|
|
51094
|
-
wanted.push(vertical);
|
|
51095
|
-
}
|
|
51096
|
-
const shape = baked.values().next().value ?? items[0];
|
|
51097
|
-
const next = [...foreignCells];
|
|
51098
|
-
const cells = [];
|
|
51099
|
-
for (const vertical of wanted) {
|
|
51100
|
-
if (next.length >= EXPLORE_MAX_CELLS) break;
|
|
51101
|
-
const bakedCell = baked.get(vertical);
|
|
51102
|
-
if (bakedCell) {
|
|
51103
|
-
next.push(bakedCell);
|
|
51104
|
-
cells.push(vertical);
|
|
51105
|
-
continue;
|
|
51106
|
-
}
|
|
51107
|
-
const made = cloneCell(shape, prefix, vertical, EXPLORE_CARDS[vertical]);
|
|
51108
|
-
if (!made) {
|
|
51109
|
-
patch.unreachable.push(vertical);
|
|
51110
|
-
continue;
|
|
51111
|
-
}
|
|
51112
|
-
next.push(made);
|
|
51113
|
-
cells.push(vertical);
|
|
51114
|
-
patch.added.push(vertical);
|
|
51115
|
-
}
|
|
51116
|
-
if (!cells.length) continue;
|
|
51117
|
-
patch.cells = cells;
|
|
51118
|
-
node.body.props.items = next;
|
|
51119
|
-
out += src.slice(cursor, open) + serializeAt(node, src, open);
|
|
51120
|
-
cursor = close;
|
|
51121
|
-
OPEN.lastIndex = close;
|
|
51122
|
-
}
|
|
51123
|
-
return out + src.slice(cursor);
|
|
51124
|
-
}
|
|
51125
|
-
function patchModules(src, installed, patch) {
|
|
51126
|
-
return src.replace(/"homeModules": "((?:[^"\\]|\\.)*)"/g, (whole, encoded2) => {
|
|
51127
|
-
let modules;
|
|
51128
|
-
try {
|
|
51129
|
-
const parsed = JSON.parse(JSON.parse(`"${encoded2}"`));
|
|
51130
|
-
if (!Array.isArray(parsed)) return whole;
|
|
51131
|
-
modules = parsed;
|
|
51132
|
-
} catch {
|
|
51133
|
-
return whole;
|
|
51134
|
-
}
|
|
51135
|
-
const kept = modules.filter((module) => {
|
|
51136
|
-
const source = module?.dataSource;
|
|
51137
|
-
if (typeof source !== "string") return true;
|
|
51138
|
-
const needs = MODULE_SOURCE_VERTICALS[source];
|
|
51139
|
-
return !needs || needs.some((vertical) => installed.has(vertical));
|
|
51140
|
-
});
|
|
51141
|
-
if (!kept.length || kept.length === modules.length) return whole;
|
|
51142
|
-
for (const module of modules) {
|
|
51143
|
-
if (!kept.includes(module) && typeof module?.id === "string") patch.droppedModules.push(module.id);
|
|
51144
|
-
}
|
|
51145
|
-
return `"homeModules": ${JSON.stringify(JSON.stringify(kept))}`;
|
|
51146
|
-
});
|
|
51147
|
-
}
|
|
51148
|
-
function homeScreenSpan(src, homeActionId) {
|
|
51149
|
-
const OPEN = /"([A-Za-z_0-9]+)": \{\s*"screenId": "\1"/g;
|
|
51150
|
-
for (let m = OPEN.exec(src); m; m = OPEN.exec(src)) {
|
|
51151
|
-
const open = src.indexOf("{", m.index);
|
|
51152
|
-
const close = objectEnd(src, open);
|
|
51153
|
-
if (close < 0) continue;
|
|
51154
|
-
if (src.slice(open, close).includes(`"actionId": "${homeActionId}"`)) return { open, close };
|
|
51155
|
-
OPEN.lastIndex = close;
|
|
51156
|
-
}
|
|
51157
|
-
return void 0;
|
|
51158
|
-
}
|
|
51159
|
-
function isDeadStoreCta(node) {
|
|
51160
|
-
if (node.body?.type !== "Button") return false;
|
|
51161
|
-
const action = node.body.props?.action;
|
|
51162
|
-
const screenId = action?.params?.screenId;
|
|
51163
|
-
return typeof screenId === "string" && isStoreScreen(screenId);
|
|
51164
|
-
}
|
|
51165
|
-
function pruneNode(node, dropped) {
|
|
51166
|
-
const props = node.body?.props;
|
|
51167
|
-
if (!props) return true;
|
|
51168
|
-
const lists = props.itemsPath ? ["children"] : ["children", "items"];
|
|
51169
|
-
for (const key2 of lists) {
|
|
51170
|
-
const list = props[key2];
|
|
51171
|
-
if (!Array.isArray(list) || !list.length) continue;
|
|
51172
|
-
const kept = list.filter((child) => {
|
|
51173
|
-
if (!isNode2(child)) return true;
|
|
51174
|
-
if (isDeadStoreCta(child)) {
|
|
51175
|
-
dropped.push(typeof child.id === "string" && child.id ? child.id : "(unnamed CTA)");
|
|
51176
|
-
return false;
|
|
51177
|
-
}
|
|
51178
|
-
return pruneNode(child, dropped);
|
|
51179
|
-
});
|
|
51180
|
-
if (kept.length === list.length) continue;
|
|
51181
|
-
if (!kept.length) return false;
|
|
51182
|
-
props[key2] = kept;
|
|
51183
|
-
}
|
|
51184
|
-
for (const [key2, child] of Object.entries(props)) {
|
|
51185
|
-
if (lists.includes(key2)) continue;
|
|
51186
|
-
pruneWithin(child, dropped);
|
|
51187
|
-
}
|
|
51188
|
-
return true;
|
|
51189
|
-
}
|
|
51190
|
-
function pruneWithin(value, dropped) {
|
|
51191
|
-
if (Array.isArray(value)) {
|
|
51192
|
-
for (const child of value) pruneWithin(child, dropped);
|
|
51193
|
-
return;
|
|
51194
|
-
}
|
|
51195
|
-
if (!value || typeof value !== "object") return;
|
|
51196
|
-
if (isNode2(value)) {
|
|
51197
|
-
pruneNode(value, dropped);
|
|
51198
|
-
return;
|
|
51199
|
-
}
|
|
51200
|
-
for (const child of Object.values(value)) pruneWithin(child, dropped);
|
|
51201
|
-
}
|
|
51202
|
-
function patchStoreCtas(src, verticals, homeActionId) {
|
|
51203
|
-
if (verticals.includes("store")) return { src, dropped: [] };
|
|
51204
|
-
const span = homeScreenSpan(src, homeActionId);
|
|
51205
|
-
if (!span) return { src, dropped: [] };
|
|
51206
|
-
let screen;
|
|
51207
|
-
try {
|
|
51208
|
-
screen = JSON.parse(src.slice(span.open, span.close));
|
|
51209
|
-
} catch {
|
|
51210
|
-
return { src, dropped: [] };
|
|
51211
|
-
}
|
|
51212
|
-
if (!isNode2(screen.payload)) return { src, dropped: [] };
|
|
51213
|
-
const dropped = [];
|
|
51214
|
-
if (!pruneNode(screen.payload, dropped) || !dropped.length) return { src, dropped: [] };
|
|
51215
|
-
return {
|
|
51216
|
-
src: src.slice(0, span.open) + serializeAt(screen, src, span.open) + src.slice(span.close),
|
|
51217
|
-
dropped
|
|
51218
|
-
};
|
|
51219
|
-
}
|
|
51220
|
-
function patchHomeForVerticals(src, verticals, homeActionId) {
|
|
51221
|
-
const installed = new Set(verticals.filter(isKnown));
|
|
51222
|
-
const patch = { src, cells: [], added: [], droppedModules: [], droppedCtas: [], unreachable: [] };
|
|
51223
|
-
if (!installed.size) return patch;
|
|
51224
|
-
const ctas = patchStoreCtas(patchModules(patchGrids(src, installed, patch), installed, patch), [...installed], homeActionId);
|
|
51225
|
-
patch.src = ctas.src;
|
|
51226
|
-
patch.droppedCtas = ctas.dropped;
|
|
51227
|
-
return patch;
|
|
51228
|
-
}
|
|
51229
|
-
var EXPLORE_CARDS, EXPLORE_ORDER, EXPLORE_MAX_CELLS, MODULE_SOURCE_VERTICALS, isKnown, GRID_VERTICAL_LABELS, escapeRe2, textProps, STORE_SCREENS, isStoreScreen, isNode2;
|
|
51230
|
-
var init_home_descriptor = __esm({
|
|
51231
|
-
"src/site-analyze/home-descriptor.ts"() {
|
|
51232
|
-
init_types2();
|
|
51233
|
-
EXPLORE_CARDS = {
|
|
51234
|
-
store: { icon: "bag", screenId: "himi_shop", title: "Shop", body: "Browse products and manage your cart." },
|
|
51235
|
-
bookings: { icon: "calendar", screenId: "himi_services", title: "Book", body: "Find a service and choose a time." },
|
|
51236
|
-
restaurants: { icon: "grid", screenId: "himi_menu", title: "Food", body: "Browse the menu and reserve a table." },
|
|
51237
|
-
events: { icon: "calendar", screenId: "himi_events", title: "Events", body: "Discover events and RSVP." },
|
|
51238
|
-
plans: { icon: "star", screenId: "himi_plans", title: "Plans", body: "Compare membership plans and join." },
|
|
51239
|
-
blog: { icon: "newspaper", screenId: "himi_blog", title: "Blog", body: "Read, save and discuss the latest posts." },
|
|
51240
|
-
groups: { icon: "people", screenId: "himi_groups", title: "Groups", body: "Meet members and join the conversation." },
|
|
51241
|
-
portfolio: { icon: "photo", screenId: "himi_portfolio", title: "Portfolio", body: "A showcase of our work." },
|
|
51242
|
-
galleries: { icon: "image", screenId: "himi_galleries", title: "Galleries", body: "Browse our photo galleries." },
|
|
51243
|
-
videos: { icon: "play", screenId: "himi_videos", title: "Videos", body: "Watch our video channels." },
|
|
51244
|
-
podcasts: { icon: "microphone", screenId: "himi_podcasts", title: "Podcast", body: "Listen to our latest episodes." },
|
|
51245
|
-
programs: { icon: "layers", screenId: "himi_programs", title: "Programs", body: "Follow structured programs at your own pace." },
|
|
51246
|
-
reservations: { icon: "clock", screenId: "himi_reservations", title: "Reservations", body: "Your table reservations." },
|
|
51247
|
-
donations: { icon: "heart", screenId: "himi_donations", title: "Donate", body: "Support the causes we care about." },
|
|
51248
|
-
giftCards: { icon: "tag", screenId: "himi_gift_cards", title: "Gift Cards", body: "Your gift cards and balances." },
|
|
51249
|
-
coupons: { icon: "tag", screenId: "himi_coupons", title: "Offers", body: "Deals and coupons available to you." },
|
|
51250
|
-
loyalty: { icon: "star", screenId: "himi_loyalty", title: "Rewards", body: "Earn points and redeem them for rewards." },
|
|
51251
|
-
forms: { icon: "list", screenId: "himi_forms", title: "Forms", body: "Fill out our forms." },
|
|
51252
|
-
cms: { icon: "grid", screenId: "himi_cms", title: "Content", body: "Explore custom content published by this business." },
|
|
51253
|
-
members: { icon: "people", screenId: "himi_members", title: "Members", body: "Meet the people in this community." },
|
|
51254
|
-
forum: { icon: "chat", screenId: "himi_forum", title: "Forum", body: "Join the discussion with the community." },
|
|
51255
|
-
feed: { icon: "chat", screenId: "himi_feed", title: "Feed", body: "Share updates and react to the latest posts." },
|
|
51256
|
-
reviews: { icon: "star_fill", screenId: "himi_reviews", title: "Reviews", body: "What customers are saying." },
|
|
51257
|
-
inbox: { icon: "chat", screenId: "himi_inbox", title: "Inbox", body: "Your messages with us." },
|
|
51258
|
-
invoices: { icon: "doc", screenId: "himi_invoices", title: "Invoices", body: "Your billing history." },
|
|
51259
|
-
badges: { icon: "star", screenId: "himi_badges", title: "Badges", body: "Achievements you can earn." },
|
|
51260
|
-
notifications: { icon: "bell", screenId: "himi_notifications", title: "Notifications", body: "Your activity and updates." },
|
|
51261
|
-
notifsettings: { icon: "settings", screenId: "himi_notif_settings", title: "Notification Settings", body: "Choose what you hear about." }
|
|
51262
|
-
};
|
|
51263
|
-
EXPLORE_ORDER = [
|
|
51264
|
-
"store",
|
|
51265
|
-
"bookings",
|
|
51266
|
-
"restaurants",
|
|
51267
|
-
"events",
|
|
51268
|
-
"plans",
|
|
51269
|
-
"blog",
|
|
51270
|
-
"groups",
|
|
51271
|
-
"portfolio",
|
|
51272
|
-
"galleries",
|
|
51273
|
-
"videos",
|
|
51274
|
-
"podcasts",
|
|
51275
|
-
"programs",
|
|
51276
|
-
"reservations",
|
|
51277
|
-
"donations",
|
|
51278
|
-
"giftCards",
|
|
51279
|
-
"coupons",
|
|
51280
|
-
"loyalty",
|
|
51281
|
-
"forms",
|
|
51282
|
-
"cms",
|
|
51283
|
-
"members",
|
|
51284
|
-
"forum",
|
|
51285
|
-
"feed",
|
|
51286
|
-
"reviews",
|
|
51287
|
-
"inbox",
|
|
51288
|
-
"invoices",
|
|
51289
|
-
"badges",
|
|
51290
|
-
"notifications",
|
|
51291
|
-
"notifsettings"
|
|
51292
|
-
];
|
|
51293
|
-
EXPLORE_MAX_CELLS = 8;
|
|
51294
|
-
MODULE_SOURCE_VERTICALS = {
|
|
51295
|
-
"member.bookings": ["bookings"],
|
|
51296
|
-
"member.bookings.schedule": ["bookings"],
|
|
51297
|
-
"device.saved_items": ["store", "blog"]
|
|
51298
|
-
};
|
|
51299
|
-
isKnown = (v) => KNOWN_VERTICALS.includes(v);
|
|
51300
|
-
GRID_VERTICAL_LABELS = /* @__PURE__ */ new Set([...KNOWN_VERTICALS, "faq"]);
|
|
51301
|
-
escapeRe2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
51302
|
-
textProps = (n) => n?.body?.props;
|
|
51303
|
-
STORE_SCREENS = /* @__PURE__ */ new Set([
|
|
51304
|
-
"himi_shop",
|
|
51305
|
-
"himi_saved_products",
|
|
51306
|
-
"himi_collections",
|
|
51307
|
-
"himi_collection",
|
|
51308
|
-
"himi_cart",
|
|
51309
|
-
"himi_orders"
|
|
51310
|
-
]);
|
|
51311
|
-
isStoreScreen = (id) => STORE_SCREENS.has(id) || /^himi_(?:product|order)[_/]/.test(id);
|
|
51312
|
-
isNode2 = (v) => !!v && typeof v === "object" && !!v.body && typeof v.body === "object";
|
|
51313
|
-
}
|
|
51314
|
-
});
|
|
51315
|
-
|
|
51316
52263
|
// src/site-analyze/apply.ts
|
|
51317
|
-
import { existsSync as
|
|
51318
|
-
import { dirname as
|
|
52264
|
+
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";
|
|
52265
|
+
import { dirname as dirname31, isAbsolute as isAbsolute4, join as join52, resolve as resolve42, sep as sep11 } from "node:path";
|
|
51319
52266
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
51320
52267
|
function unpairedRedirectNote(overlay) {
|
|
51321
52268
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
@@ -51330,8 +52277,8 @@ function committedShellProvisioning(path2) {
|
|
|
51330
52277
|
function findRepoRoot(cwd) {
|
|
51331
52278
|
let dir = cwd;
|
|
51332
52279
|
for (let i = 0; i < 8; i++) {
|
|
51333
|
-
if (SHELL_NAMES2.some((name) =>
|
|
51334
|
-
const next =
|
|
52280
|
+
if (SHELL_NAMES2.some((name) => existsSync55(join52(dir, shellAppDir(name), "package.json")))) return dir;
|
|
52281
|
+
const next = dirname31(dir);
|
|
51335
52282
|
if (next === dir) break;
|
|
51336
52283
|
dir = next;
|
|
51337
52284
|
}
|
|
@@ -51398,11 +52345,11 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
51398
52345
|
}
|
|
51399
52346
|
function buildMergedContract(options) {
|
|
51400
52347
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
51401
|
-
const committedPath =
|
|
51402
|
-
if (!
|
|
52348
|
+
const committedPath = join52(appDir2, "provisioning.json");
|
|
52349
|
+
if (!existsSync55(committedPath)) {
|
|
51403
52350
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
51404
52351
|
}
|
|
51405
|
-
const committed = JSON.parse(
|
|
52352
|
+
const committed = JSON.parse(readFileSync65(committedPath, "utf8"));
|
|
51406
52353
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
51407
52354
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
51408
52355
|
const branding = merged.branding ?? {};
|
|
@@ -51414,8 +52361,8 @@ function buildMergedContract(options) {
|
|
|
51414
52361
|
};
|
|
51415
52362
|
const stage = (fromRel, toRel) => {
|
|
51416
52363
|
const from = contained(packageDir, fromRel);
|
|
51417
|
-
const to = contained(
|
|
51418
|
-
if (!from || !to || !
|
|
52364
|
+
const to = contained(join52(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
52365
|
+
if (!from || !to || !existsSync55(from)) return void 0;
|
|
51419
52366
|
let real;
|
|
51420
52367
|
let realRoot;
|
|
51421
52368
|
try {
|
|
@@ -51426,8 +52373,8 @@ function buildMergedContract(options) {
|
|
|
51426
52373
|
}
|
|
51427
52374
|
if (!real.startsWith(realRoot + sep11)) return void 0;
|
|
51428
52375
|
try {
|
|
51429
|
-
if (!
|
|
51430
|
-
|
|
52376
|
+
if (!statSync13(real).isFile()) return void 0;
|
|
52377
|
+
mkdirSync27(dirname31(to), { recursive: true });
|
|
51431
52378
|
copyFileSync3(real, to);
|
|
51432
52379
|
} catch {
|
|
51433
52380
|
return void 0;
|
|
@@ -51437,11 +52384,11 @@ function buildMergedContract(options) {
|
|
|
51437
52384
|
};
|
|
51438
52385
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
51439
52386
|
if (icon) branding.appIconPath = icon;
|
|
51440
|
-
const facesPath =
|
|
51441
|
-
if (
|
|
52387
|
+
const facesPath = join52(packageDir, "media/fonts/faces.json");
|
|
52388
|
+
if (existsSync55(facesPath)) {
|
|
51442
52389
|
let faces = [];
|
|
51443
52390
|
try {
|
|
51444
|
-
const parsed = JSON.parse(
|
|
52391
|
+
const parsed = JSON.parse(readFileSync65(facesPath, "utf8"));
|
|
51445
52392
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
51446
52393
|
} catch {
|
|
51447
52394
|
faces = [];
|
|
@@ -51462,11 +52409,11 @@ function buildMergedContract(options) {
|
|
|
51462
52409
|
merged.branding = branding;
|
|
51463
52410
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
51464
52411
|
`;
|
|
51465
|
-
const path2 =
|
|
51466
|
-
|
|
51467
|
-
const localPath =
|
|
51468
|
-
|
|
51469
|
-
|
|
52412
|
+
const path2 = join52(packageDir, "provisioning.contract.json");
|
|
52413
|
+
writeFileSync24(path2, body);
|
|
52414
|
+
const localPath = join52(appDir2, LOCAL_CONTRACT_REL);
|
|
52415
|
+
mkdirSync27(dirname31(localPath), { recursive: true });
|
|
52416
|
+
writeFileSync24(localPath, body);
|
|
51470
52417
|
staged.push(localPath);
|
|
51471
52418
|
return { path: path2, staged };
|
|
51472
52419
|
}
|
|
@@ -51474,8 +52421,8 @@ async function applyOverlays(input) {
|
|
|
51474
52421
|
const cwd = resolve42(input.cwd);
|
|
51475
52422
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
51476
52423
|
assertKnownShell(shell);
|
|
51477
|
-
const overlay = JSON.parse(
|
|
51478
|
-
const tokens = JSON.parse(
|
|
52424
|
+
const overlay = JSON.parse(readFileSync65(input.overlayPath, "utf8"));
|
|
52425
|
+
const tokens = JSON.parse(readFileSync65(input.tokensPath, "utf8"));
|
|
51479
52426
|
const wrote = [];
|
|
51480
52427
|
const notes = [];
|
|
51481
52428
|
const repoRoot2 = findRepoRoot(cwd);
|
|
@@ -51485,8 +52432,8 @@ async function applyOverlays(input) {
|
|
|
51485
52432
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
51486
52433
|
);
|
|
51487
52434
|
}
|
|
51488
|
-
const appDir2 =
|
|
51489
|
-
const packageDir =
|
|
52435
|
+
const appDir2 = join52(repoRoot2, shellAppDir(shell));
|
|
52436
|
+
const packageDir = dirname31(resolve42(input.overlayPath));
|
|
51490
52437
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
51491
52438
|
wrote.push(...staged);
|
|
51492
52439
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -51507,32 +52454,32 @@ async function applyOverlays(input) {
|
|
|
51507
52454
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
51508
52455
|
};
|
|
51509
52456
|
}
|
|
51510
|
-
const pkgProv =
|
|
52457
|
+
const pkgProv = join52(cwd, "provisioning.json");
|
|
51511
52458
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
51512
|
-
if (
|
|
51513
|
-
const cur = JSON.parse(
|
|
52459
|
+
if (existsSync55(pkgProv)) {
|
|
52460
|
+
const cur = JSON.parse(readFileSync65(pkgProv, "utf8"));
|
|
51514
52461
|
const merged = deepMerge4(cur, overlay);
|
|
51515
|
-
|
|
52462
|
+
writeFileSync24(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
51516
52463
|
wrote.push(pkgProv);
|
|
51517
52464
|
} else {
|
|
51518
|
-
|
|
52465
|
+
writeFileSync24(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
51519
52466
|
wrote.push(pkgProv);
|
|
51520
52467
|
}
|
|
51521
|
-
const pkgTokens =
|
|
51522
|
-
if (
|
|
51523
|
-
const cur = JSON.parse(
|
|
52468
|
+
const pkgTokens = join52(cwd, "tokens.json");
|
|
52469
|
+
if (existsSync55(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
52470
|
+
const cur = JSON.parse(readFileSync65(pkgTokens, "utf8"));
|
|
51524
52471
|
const merged = deepMerge4(cur, tokens);
|
|
51525
52472
|
const mergedColors = merged.colors;
|
|
51526
52473
|
if (mergedColors && typeof mergedColors === "object" && !Array.isArray(mergedColors)) {
|
|
51527
52474
|
merged.colors = alignAccentsToSurfaces(mergedColors, tokens.colors);
|
|
51528
52475
|
}
|
|
51529
|
-
|
|
52476
|
+
writeFileSync24(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
51530
52477
|
wrote.push(pkgTokens);
|
|
51531
52478
|
}
|
|
51532
52479
|
const homeAction = homeRefreshActionId(shell);
|
|
51533
|
-
const homeSrc =
|
|
51534
|
-
if (homeAction &&
|
|
51535
|
-
const prev =
|
|
52480
|
+
const homeSrc = join52(cwd, "dev/index.ts");
|
|
52481
|
+
if (homeAction && existsSync55(homeSrc)) {
|
|
52482
|
+
const prev = readFileSync65(homeSrc, "utf8");
|
|
51536
52483
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
51537
52484
|
let next = patched.src;
|
|
51538
52485
|
if (!patched.foreign && overlay.installedVerticals?.length) {
|
|
@@ -51548,20 +52495,20 @@ async function applyOverlays(input) {
|
|
|
51548
52495
|
}
|
|
51549
52496
|
}
|
|
51550
52497
|
if (next !== prev) {
|
|
51551
|
-
|
|
52498
|
+
writeFileSync24(homeSrc, next);
|
|
51552
52499
|
wrote.push(homeSrc);
|
|
51553
52500
|
}
|
|
51554
52501
|
if (patched.unparsed) {
|
|
51555
52502
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
51556
52503
|
}
|
|
51557
52504
|
}
|
|
51558
|
-
if (!input.iconPath || !
|
|
51559
|
-
const book = input.iconPath ?
|
|
52505
|
+
if (!input.iconPath || !existsSync55(input.iconPath)) {
|
|
52506
|
+
const book = input.iconPath ? dirname31(dirname31(resolve42(input.iconPath))) : void 0;
|
|
51560
52507
|
notes.push(
|
|
51561
52508
|
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"
|
|
51562
52509
|
);
|
|
51563
52510
|
}
|
|
51564
|
-
if (input.iconPath &&
|
|
52511
|
+
if (input.iconPath && existsSync55(input.iconPath)) {
|
|
51565
52512
|
try {
|
|
51566
52513
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
51567
52514
|
wrote.push(...installed.wrote);
|
|
@@ -54545,8 +55492,8 @@ var init_dist = __esm({
|
|
|
54545
55492
|
* @param jsonString - A JSON string or object representing the deserialized cookies.
|
|
54546
55493
|
* @param store - The underlying store to persist the deserialized cookies into.
|
|
54547
55494
|
*/
|
|
54548
|
-
static fromJSON(
|
|
54549
|
-
return _CookieJar.deserializeSync(
|
|
55495
|
+
static fromJSON(jsonString2, store) {
|
|
55496
|
+
return _CookieJar.deserializeSync(jsonString2, store);
|
|
54550
55497
|
}
|
|
54551
55498
|
};
|
|
54552
55499
|
}
|
|
@@ -54575,29 +55522,29 @@ function ctasOf(texts) {
|
|
|
54575
55522
|
function copyFromEval(evaled) {
|
|
54576
55523
|
const sections = [];
|
|
54577
55524
|
for (const raw of evaled.sections ?? []) {
|
|
54578
|
-
const heading = copyOrDrop(raw?.heading,
|
|
55525
|
+
const heading = copyOrDrop(raw?.heading, CAP3.heading);
|
|
54579
55526
|
if (!heading) continue;
|
|
54580
|
-
const body = copyOrDrop(raw?.body,
|
|
55527
|
+
const body = copyOrDrop(raw?.body, CAP3.body);
|
|
54581
55528
|
sections.push(body ? { heading, body } : { heading });
|
|
54582
|
-
if (sections.length >=
|
|
55529
|
+
if (sections.length >= CAP3.sections) break;
|
|
54583
55530
|
}
|
|
54584
55531
|
const faq = [];
|
|
54585
55532
|
for (const raw of evaled.faq ?? []) {
|
|
54586
|
-
const q = copyOrDrop(raw?.q,
|
|
54587
|
-
const a = copyOrDrop(raw?.a,
|
|
55533
|
+
const q = copyOrDrop(raw?.q, CAP3.q);
|
|
55534
|
+
const a = copyOrDrop(raw?.a, CAP3.a);
|
|
54588
55535
|
if (q && a && q !== a) faq.push({ q, a });
|
|
54589
|
-
if (faq.length >=
|
|
55536
|
+
if (faq.length >= CAP3.faq) break;
|
|
54590
55537
|
}
|
|
54591
|
-
const ctaLabels = dedupe2((evaled.ctaLabels ?? []).map((c) => copyOrDrop(c,
|
|
55538
|
+
const ctaLabels = dedupe2((evaled.ctaLabels ?? []).map((c) => copyOrDrop(c, CAP3.cta)), CAP3.ctas);
|
|
54592
55539
|
const testimonials = dedupe2(
|
|
54593
|
-
(evaled.testimonials ?? []).map((t) => copyOrDrop(t,
|
|
54594
|
-
|
|
55540
|
+
(evaled.testimonials ?? []).map((t) => copyOrDrop(t, CAP3.testimonial)),
|
|
55541
|
+
CAP3.testimonials
|
|
54595
55542
|
);
|
|
54596
|
-
const about = copyOrDrop(evaled.about,
|
|
55543
|
+
const about = copyOrDrop(evaled.about, CAP3.about);
|
|
54597
55544
|
const meta = {};
|
|
54598
|
-
const description = copyOrDrop(evaled.meta?.description,
|
|
54599
|
-
const ogTitle = copyOrDrop(evaled.meta?.ogTitle,
|
|
54600
|
-
const ogDescription = copyOrDrop(evaled.meta?.ogDescription,
|
|
55545
|
+
const description = copyOrDrop(evaled.meta?.description, CAP3.meta);
|
|
55546
|
+
const ogTitle = copyOrDrop(evaled.meta?.ogTitle, CAP3.meta);
|
|
55547
|
+
const ogDescription = copyOrDrop(evaled.meta?.ogDescription, CAP3.meta);
|
|
54601
55548
|
if (description) meta.description = description;
|
|
54602
55549
|
if (ogTitle) meta.ogTitle = ogTitle;
|
|
54603
55550
|
if (ogDescription) meta.ogDescription = ogDescription;
|
|
@@ -54871,7 +55818,7 @@ async function createPlaywrightBrowser(load = () => import("playwright"), siteFe
|
|
|
54871
55818
|
};
|
|
54872
55819
|
return { port, screenshots, siteFetch, pin };
|
|
54873
55820
|
}
|
|
54874
|
-
var PLAYWRIGHT_HINT, PAGE_EVAL,
|
|
55821
|
+
var PLAYWRIGHT_HINT, PAGE_EVAL, CAP3, DOCUMENT_FETCH_TIMEOUT_MS, MAX_DOCUMENT_BYTES, SUBRESOURCE_PIN_TIMEOUT_MS, NON_NETWORK_SCHEMES, FORWARDED_REQUEST_HEADERS;
|
|
54875
55822
|
var init_crawl_look = __esm({
|
|
54876
55823
|
"src/site-analyze/crawl-look.ts"() {
|
|
54877
55824
|
init_dist();
|
|
@@ -55066,7 +56013,7 @@ var init_crawl_look = __esm({
|
|
|
55066
56013
|
} catch (e4) {}
|
|
55067
56014
|
return { wst, nav, headings, hero, imgs, hrefs, buttons, html, htmlLang, velo, sections, ctaLabels, faq, testimonials, about, meta };
|
|
55068
56015
|
})()`;
|
|
55069
|
-
|
|
56016
|
+
CAP3 = {
|
|
55070
56017
|
heading: 120,
|
|
55071
56018
|
body: 300,
|
|
55072
56019
|
cta: 80,
|
|
@@ -55715,7 +56662,7 @@ __export(cli_exports, {
|
|
|
55715
56662
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
55716
56663
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
55717
56664
|
});
|
|
55718
|
-
import { readFileSync as
|
|
56665
|
+
import { readFileSync as readFileSync66 } from "node:fs";
|
|
55719
56666
|
import { resolve as resolve43 } from "node:path";
|
|
55720
56667
|
function assetFetchFor(_opts) {
|
|
55721
56668
|
return pinnedFetch2;
|
|
@@ -55802,7 +56749,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
55802
56749
|
let source;
|
|
55803
56750
|
if (opts.sourcePath) {
|
|
55804
56751
|
const p = resolve43(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
55805
|
-
source =
|
|
56752
|
+
source = readFileSync66(p, "utf8");
|
|
55806
56753
|
}
|
|
55807
56754
|
let body;
|
|
55808
56755
|
if (opts.bodyRaw != null) {
|
|
@@ -55956,9 +56903,9 @@ var init_wix_account = __esm({
|
|
|
55956
56903
|
});
|
|
55957
56904
|
|
|
55958
56905
|
// src/wix-verticals.ts
|
|
55959
|
-
function resolveVerticals(
|
|
55960
|
-
if (!
|
|
55961
|
-
const names =
|
|
56906
|
+
function resolveVerticals(csv2) {
|
|
56907
|
+
if (!csv2) return [];
|
|
56908
|
+
const names = csv2.split(",").map((s) => s.trim()).filter(Boolean);
|
|
55962
56909
|
const out = [];
|
|
55963
56910
|
const seen = /* @__PURE__ */ new Set();
|
|
55964
56911
|
for (const name of names) {
|
|
@@ -56059,7 +57006,7 @@ __export(site_create_exports, {
|
|
|
56059
57006
|
runSiteList: () => runSiteList,
|
|
56060
57007
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
56061
57008
|
});
|
|
56062
|
-
import { existsSync as
|
|
57009
|
+
import { existsSync as existsSync56, readFileSync as readFileSync67, writeFileSync as writeFileSync25 } from "node:fs";
|
|
56063
57010
|
import { resolve as resolvePath2 } from "node:path";
|
|
56064
57011
|
function oauthClientName(projectName) {
|
|
56065
57012
|
return `${projectName} client`;
|
|
@@ -56208,7 +57155,7 @@ async function runSiteCreate(opts) {
|
|
|
56208
57155
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
56209
57156
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
56210
57157
|
}
|
|
56211
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
57158
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync56, readFileSync: readFileSync67, writeFileSync: writeFileSync25 }) {
|
|
56212
57159
|
const msid = binding2.siteId;
|
|
56213
57160
|
const path2 = resolvePath2(target);
|
|
56214
57161
|
const committed = committedShellProvisioning(path2);
|
|
@@ -56881,11 +57828,11 @@ var init_context = __esm({
|
|
|
56881
57828
|
});
|
|
56882
57829
|
|
|
56883
57830
|
// src/cli.ts
|
|
56884
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as
|
|
57831
|
+
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";
|
|
56885
57832
|
import { execFile as execFile4, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn5 } from "node:child_process";
|
|
56886
57833
|
import { createHash as createHash24, randomUUID as randomUUID3 } from "node:crypto";
|
|
56887
57834
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
56888
|
-
import { join as
|
|
57835
|
+
import { join as join53, resolve as resolve44, relative as relative8, basename as basename12, dirname as dirname32 } from "node:path";
|
|
56889
57836
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
56890
57837
|
|
|
56891
57838
|
// ../serve-cli/src/client.ts
|
|
@@ -60163,8 +61110,8 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
|
|
|
60163
61110
|
var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
60164
61111
|
function embeddedTemplateCatalog() {
|
|
60165
61112
|
return availableTemplates().map((name) => {
|
|
60166
|
-
const path2 =
|
|
60167
|
-
const meta = JSON.parse(
|
|
61113
|
+
const path2 = join53(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
61114
|
+
const meta = JSON.parse(readFileSync68(path2, "utf8"));
|
|
60168
61115
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
60169
61116
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
60170
61117
|
}
|
|
@@ -60197,6 +61144,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
60197
61144
|
himi template prompt <name> print the prompt that starts an app from that template
|
|
60198
61145
|
himi template publish [--dir <app>] [--source-dir <dir>] [--name <n>] [--icon <png>] [--visibility public|unlisted]
|
|
60199
61146
|
publish an app AS a himi init --template on the serve plane
|
|
61147
|
+
himi template trim --keep <id,id,\u2026> [--content <dir>] [--links follow|drop] [--dry-run] [--force]
|
|
61148
|
+
cut a scaffolded template to the screens you keep (the home and
|
|
61149
|
+
any drawer body stay): removes the other screens, their navigation rows and
|
|
61150
|
+
unshared tier5-src workers, then proves it with validate --strict
|
|
61151
|
+
(rolled back on failure). Refuses when a kept screen links to a
|
|
61152
|
+
removed one \u2014 --links follow keeps those too, --links drop removes the taps
|
|
60200
61153
|
himi build [--content <dir>] [--binary] compile Tier-5 workers with esbuild
|
|
60201
61154
|
himi eject <auth|checkout|screens> [--content <dir>]
|
|
60202
61155
|
the ladder's escape hatch \u2014 copy a shared flow module's
|
|
@@ -60752,7 +61705,7 @@ WHAT A PATCH DOES NOT CARRY \u2014 all reported in the output, never silent
|
|
|
60752
61705
|
var COMMANDS = [
|
|
60753
61706
|
{ 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>]" },
|
|
60754
61707
|
{ 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" },
|
|
60755
|
-
{ 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>]" },
|
|
61708
|
+
{ 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]" },
|
|
60756
61709
|
{ 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]" },
|
|
60757
61710
|
{ 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>]" },
|
|
60758
61711
|
{ 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>]" },
|
|
@@ -60807,7 +61760,7 @@ var COMMANDS = [
|
|
|
60807
61760
|
];
|
|
60808
61761
|
function cliVersion() {
|
|
60809
61762
|
try {
|
|
60810
|
-
return JSON.parse(
|
|
61763
|
+
return JSON.parse(readFileSync68(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
60811
61764
|
} catch {
|
|
60812
61765
|
return "unknown";
|
|
60813
61766
|
}
|
|
@@ -60925,7 +61878,7 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
60925
61878
|
}
|
|
60926
61879
|
function packageVersion(path2) {
|
|
60927
61880
|
try {
|
|
60928
|
-
const version2 = JSON.parse(
|
|
61881
|
+
const version2 = JSON.parse(readFileSync68(path2, "utf8")).version;
|
|
60929
61882
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
60930
61883
|
} catch {
|
|
60931
61884
|
return void 0;
|
|
@@ -60934,9 +61887,9 @@ function packageVersion(path2) {
|
|
|
60934
61887
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
60935
61888
|
let dir = resolve44(fromDir);
|
|
60936
61889
|
for (; ; ) {
|
|
60937
|
-
const version2 = packageVersion(
|
|
61890
|
+
const version2 = packageVersion(join53(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
60938
61891
|
if (version2) return { version: version2, source: "local" };
|
|
60939
|
-
const parent =
|
|
61892
|
+
const parent = dirname32(dir);
|
|
60940
61893
|
if (parent === dir) break;
|
|
60941
61894
|
dir = parent;
|
|
60942
61895
|
}
|
|
@@ -60944,7 +61897,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
60944
61897
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
60945
61898
|
try {
|
|
60946
61899
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
60947
|
-
const version2 = root ? packageVersion(
|
|
61900
|
+
const version2 = root ? packageVersion(join53(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
60948
61901
|
return version2 ? { version: version2, source: "global" } : {};
|
|
60949
61902
|
} catch {
|
|
60950
61903
|
return {};
|
|
@@ -60991,11 +61944,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
60991
61944
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
60992
61945
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
60993
61946
|
function updateCachePath(env = process.env) {
|
|
60994
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
61947
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join53(homedir7(), ".himalaya", "update-check.json");
|
|
60995
61948
|
}
|
|
60996
61949
|
function readUpdateCache(path2) {
|
|
60997
61950
|
try {
|
|
60998
|
-
const parsed = JSON.parse(
|
|
61951
|
+
const parsed = JSON.parse(readFileSync68(path2, "utf8"));
|
|
60999
61952
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
61000
61953
|
} catch {
|
|
61001
61954
|
return {};
|
|
@@ -61003,8 +61956,8 @@ function readUpdateCache(path2) {
|
|
|
61003
61956
|
}
|
|
61004
61957
|
function writeUpdateCache(path2, cache) {
|
|
61005
61958
|
try {
|
|
61006
|
-
|
|
61007
|
-
|
|
61959
|
+
mkdirSync28(dirname32(path2), { recursive: true, mode: 448 });
|
|
61960
|
+
writeFileSync26(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
61008
61961
|
} catch {
|
|
61009
61962
|
}
|
|
61010
61963
|
}
|
|
@@ -61063,12 +62016,12 @@ function createUpdateRunner(spawn6 = spawnSync5) {
|
|
|
61063
62016
|
},
|
|
61064
62017
|
installedVersion: () => {
|
|
61065
62018
|
const root = globalNodeModulesRoot();
|
|
61066
|
-
return root ? packageVersion(
|
|
62019
|
+
return root ? packageVersion(join53(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
61067
62020
|
},
|
|
61068
62021
|
reexec: (argv) => {
|
|
61069
62022
|
const root = globalNodeModulesRoot();
|
|
61070
|
-
const entry = root ?
|
|
61071
|
-
if (!entry || !
|
|
62023
|
+
const entry = root ? join53(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
62024
|
+
if (!entry || !existsSync57(entry)) return void 0;
|
|
61072
62025
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
61073
62026
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
61074
62027
|
stdio: "inherit",
|
|
@@ -61115,7 +62068,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
61115
62068
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
61116
62069
|
let content;
|
|
61117
62070
|
try {
|
|
61118
|
-
content =
|
|
62071
|
+
content = readFileSync68(path2, "utf8");
|
|
61119
62072
|
} catch {
|
|
61120
62073
|
continue;
|
|
61121
62074
|
}
|
|
@@ -61123,7 +62076,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
61123
62076
|
let since = stamped;
|
|
61124
62077
|
if (!Number.isFinite(since)) {
|
|
61125
62078
|
try {
|
|
61126
|
-
since =
|
|
62079
|
+
since = statSync14(path2).mtimeMs;
|
|
61127
62080
|
} catch {
|
|
61128
62081
|
continue;
|
|
61129
62082
|
}
|
|
@@ -61138,14 +62091,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
61138
62091
|
const mine = lockStamp(now);
|
|
61139
62092
|
const readLock = (path2) => {
|
|
61140
62093
|
try {
|
|
61141
|
-
return
|
|
62094
|
+
return readFileSync68(path2, "utf8");
|
|
61142
62095
|
} catch {
|
|
61143
62096
|
return void 0;
|
|
61144
62097
|
}
|
|
61145
62098
|
};
|
|
61146
62099
|
const tryCreate = (path2) => {
|
|
61147
62100
|
try {
|
|
61148
|
-
|
|
62101
|
+
writeFileSync26(path2, mine, { flag: "wx", mode: 384 });
|
|
61149
62102
|
return true;
|
|
61150
62103
|
} catch {
|
|
61151
62104
|
return false;
|
|
@@ -61153,13 +62106,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
61153
62106
|
};
|
|
61154
62107
|
const removeIfMine = (path2) => {
|
|
61155
62108
|
try {
|
|
61156
|
-
if (readLock(path2) === mine)
|
|
62109
|
+
if (readLock(path2) === mine) rmSync11(path2, { force: true });
|
|
61157
62110
|
} catch {
|
|
61158
62111
|
}
|
|
61159
62112
|
};
|
|
61160
62113
|
const release = () => removeIfMine(lockPath);
|
|
61161
62114
|
try {
|
|
61162
|
-
|
|
62115
|
+
mkdirSync28(dirname32(lockPath), { recursive: true, mode: 448 });
|
|
61163
62116
|
} catch {
|
|
61164
62117
|
return () => {
|
|
61165
62118
|
};
|
|
@@ -61176,7 +62129,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
61176
62129
|
hooks.underBreakLock?.();
|
|
61177
62130
|
if (current === void 0) return tryCreate(lockPath) ? release : void 0;
|
|
61178
62131
|
if (!isAbandoned(current)) return void 0;
|
|
61179
|
-
|
|
62132
|
+
rmSync11(lockPath, { force: true });
|
|
61180
62133
|
return tryCreate(lockPath) ? release : void 0;
|
|
61181
62134
|
} finally {
|
|
61182
62135
|
removeIfMine(breakPath);
|
|
@@ -61676,9 +62629,9 @@ function executableOnPath(name, env = process.env) {
|
|
|
61676
62629
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
61677
62630
|
for (const dir of entries) {
|
|
61678
62631
|
for (const suffix of suffixes) {
|
|
61679
|
-
const candidate =
|
|
62632
|
+
const candidate = join53(dir, `${name}${suffix}`);
|
|
61680
62633
|
try {
|
|
61681
|
-
if (!
|
|
62634
|
+
if (!statSync14(candidate).isFile()) continue;
|
|
61682
62635
|
if (process.platform !== "win32") accessSync(candidate, constants.X_OK);
|
|
61683
62636
|
return true;
|
|
61684
62637
|
} catch {
|
|
@@ -61785,7 +62738,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
61785
62738
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
61786
62739
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
61787
62740
|
const iosYmlPath = iosProjectYml2(app);
|
|
61788
|
-
const iosYml =
|
|
62741
|
+
const iosYml = existsSync57(iosYmlPath) ? readFileSync68(iosYmlPath, "utf8") : "";
|
|
61789
62742
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
61790
62743
|
if (!optedIn) {
|
|
61791
62744
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -61799,19 +62752,19 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
61799
62752
|
}
|
|
61800
62753
|
function readConfigSource(dir) {
|
|
61801
62754
|
try {
|
|
61802
|
-
return
|
|
62755
|
+
return readFileSync68(join53(dir, "config.ts"), "utf8");
|
|
61803
62756
|
} catch {
|
|
61804
62757
|
return null;
|
|
61805
62758
|
}
|
|
61806
62759
|
}
|
|
61807
62760
|
function writePngFile(path2, base64) {
|
|
61808
|
-
|
|
61809
|
-
|
|
62761
|
+
mkdirSync28(dirname32(path2), { recursive: true });
|
|
62762
|
+
writeFileSync26(path2, Buffer.from(base64, "base64"));
|
|
61810
62763
|
return path2;
|
|
61811
62764
|
}
|
|
61812
62765
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
61813
62766
|
const dir = resolve44(parentDir, name);
|
|
61814
|
-
if (
|
|
62767
|
+
if (existsSync57(join53(dir, "himalaya.content.json"))) {
|
|
61815
62768
|
throw new Error(`content package already exists at ${dir}`);
|
|
61816
62769
|
}
|
|
61817
62770
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -61854,11 +62807,11 @@ function symlinkDestinationIssue(dest) {
|
|
|
61854
62807
|
function restoreDestinationIssue(dest, force) {
|
|
61855
62808
|
const link = symlinkDestinationIssue(dest);
|
|
61856
62809
|
if (link) return link;
|
|
61857
|
-
if (!
|
|
61858
|
-
if (!
|
|
62810
|
+
if (!existsSync57(dest)) return null;
|
|
62811
|
+
if (!statSync14(dest).isDirectory()) {
|
|
61859
62812
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
61860
62813
|
}
|
|
61861
|
-
if (
|
|
62814
|
+
if (readdirSync26(dest).length > 0 && !force) {
|
|
61862
62815
|
return {
|
|
61863
62816
|
error: `${dest} already exists and is not empty`,
|
|
61864
62817
|
hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
|
|
@@ -61869,8 +62822,8 @@ function restoreDestinationIssue(dest, force) {
|
|
|
61869
62822
|
function isHimalayaMonorepoCheckout(start) {
|
|
61870
62823
|
let dir = resolve44(start);
|
|
61871
62824
|
for (; ; ) {
|
|
61872
|
-
if (
|
|
61873
|
-
const parent =
|
|
62825
|
+
if (existsSync57(join53(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync57(join53(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
62826
|
+
const parent = dirname32(dir);
|
|
61874
62827
|
if (parent === dir) return false;
|
|
61875
62828
|
dir = parent;
|
|
61876
62829
|
}
|
|
@@ -61912,7 +62865,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
61912
62865
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
61913
62866
|
);
|
|
61914
62867
|
const repoRoot2 = resolve44(fileURLToPath24(new URL("../../..", import.meta.url)));
|
|
61915
|
-
const root =
|
|
62868
|
+
const root = join53(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
61916
62869
|
const stillRunning = (pid) => {
|
|
61917
62870
|
try {
|
|
61918
62871
|
process.kill(pid, 0);
|
|
@@ -61922,25 +62875,25 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
61922
62875
|
}
|
|
61923
62876
|
};
|
|
61924
62877
|
try {
|
|
61925
|
-
for (const entry of
|
|
62878
|
+
for (const entry of readdirSync26(root, { withFileTypes: true })) {
|
|
61926
62879
|
if (!entry.isDirectory()) continue;
|
|
61927
62880
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
61928
62881
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
61929
|
-
|
|
62882
|
+
rmSync11(join53(root, entry.name), { recursive: true, force: true });
|
|
61930
62883
|
}
|
|
61931
62884
|
}
|
|
61932
62885
|
} catch {
|
|
61933
62886
|
}
|
|
61934
|
-
const dest =
|
|
61935
|
-
|
|
61936
|
-
|
|
62887
|
+
const dest = join53(root, `${slug}-${process.pid}`);
|
|
62888
|
+
rmSync11(dest, { recursive: true, force: true });
|
|
62889
|
+
mkdirSync28(dest, { recursive: true });
|
|
61937
62890
|
materializeSource(forBuild, displayName, dest, slug);
|
|
61938
62891
|
return dest;
|
|
61939
62892
|
}
|
|
61940
62893
|
async function appId(dir) {
|
|
61941
62894
|
try {
|
|
61942
|
-
const { readFileSync:
|
|
61943
|
-
const m = JSON.parse(
|
|
62895
|
+
const { readFileSync: readFileSync69 } = await import("node:fs");
|
|
62896
|
+
const m = JSON.parse(readFileSync69(join53(dir, "himalaya.content.json"), "utf8"));
|
|
61944
62897
|
if (m.name) return m.name;
|
|
61945
62898
|
} catch {
|
|
61946
62899
|
}
|
|
@@ -61948,8 +62901,8 @@ async function appId(dir) {
|
|
|
61948
62901
|
}
|
|
61949
62902
|
async function contentVisibility(dir) {
|
|
61950
62903
|
try {
|
|
61951
|
-
const { readFileSync:
|
|
61952
|
-
const m = JSON.parse(
|
|
62904
|
+
const { readFileSync: readFileSync69 } = await import("node:fs");
|
|
62905
|
+
const m = JSON.parse(readFileSync69(join53(dir, "himalaya.content.json"), "utf8"));
|
|
61953
62906
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
61954
62907
|
} catch {
|
|
61955
62908
|
}
|
|
@@ -62173,7 +63126,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
62173
63126
|
try {
|
|
62174
63127
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
62175
63128
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
62176
|
-
out = mkdtempSync4(
|
|
63129
|
+
out = mkdtempSync4(join53(tmpdir5(), "himi-ux-record-"));
|
|
62177
63130
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62178
63131
|
const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
62179
63132
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -62186,7 +63139,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
62186
63139
|
return null;
|
|
62187
63140
|
} finally {
|
|
62188
63141
|
if (out !== void 0) try {
|
|
62189
|
-
|
|
63142
|
+
rmSync11(out, { recursive: true, force: true });
|
|
62190
63143
|
} catch {
|
|
62191
63144
|
}
|
|
62192
63145
|
}
|
|
@@ -62340,7 +63293,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
62340
63293
|
}
|
|
62341
63294
|
const outDir = tier5Dir.bundleOutDir(dir);
|
|
62342
63295
|
try {
|
|
62343
|
-
|
|
63296
|
+
readdirSync26(outDir);
|
|
62344
63297
|
} catch {
|
|
62345
63298
|
return { families: void 0, source: "unbuilt" };
|
|
62346
63299
|
}
|
|
@@ -62351,7 +63304,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
62351
63304
|
let js;
|
|
62352
63305
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
62353
63306
|
try {
|
|
62354
|
-
js =
|
|
63307
|
+
js = readFileSync68(join53(outDir, candidate), "utf8");
|
|
62355
63308
|
break;
|
|
62356
63309
|
} catch {
|
|
62357
63310
|
}
|
|
@@ -62721,12 +63674,34 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62721
63674
|
print({ ok: true, templates: merged, remote: true });
|
|
62722
63675
|
return 0;
|
|
62723
63676
|
}
|
|
63677
|
+
if (sub === "trim") {
|
|
63678
|
+
const { runTemplateTrim: runTemplateTrim2 } = await Promise.resolve().then(() => (init_template_trim(), template_trim_exports));
|
|
63679
|
+
const outcome = await runTemplateTrim2(
|
|
63680
|
+
{ dir: contentDir(flags), keep: flags.keep, links: flags.links, dryRun: flags["dry-run"] === true, force: flags.force === true },
|
|
63681
|
+
{
|
|
63682
|
+
validate: async (dir) => {
|
|
63683
|
+
const out = [];
|
|
63684
|
+
const err = [];
|
|
63685
|
+
const code = await run(["validate", "--content", dir, "--strict"], { log: (l) => out.push(l), error: (l) => err.push(l) }, deps);
|
|
63686
|
+
let counts;
|
|
63687
|
+
try {
|
|
63688
|
+
counts = JSON.parse(out[out.length - 1] ?? "").counts;
|
|
63689
|
+
} catch {
|
|
63690
|
+
}
|
|
63691
|
+
return { code, counts, ...code !== 0 ? { tail: [...out, ...err].join("\n").slice(-4e3) } : {} };
|
|
63692
|
+
}
|
|
63693
|
+
}
|
|
63694
|
+
);
|
|
63695
|
+
if (outcome.code === 2) io.error(JSON.stringify(outcome.result));
|
|
63696
|
+
else print(outcome.result);
|
|
63697
|
+
return outcome.code;
|
|
63698
|
+
}
|
|
62724
63699
|
if (sub === "publish") {
|
|
62725
63700
|
const appDir2 = resolve44(str5(flags.dir) ?? process.cwd());
|
|
62726
63701
|
const sourceDir = resolve44(str5(flags["source-dir"]) ?? appDir2);
|
|
62727
63702
|
let meta;
|
|
62728
63703
|
try {
|
|
62729
|
-
meta = JSON.parse(
|
|
63704
|
+
meta = JSON.parse(readFileSync68(join53(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
62730
63705
|
} catch {
|
|
62731
63706
|
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>)` }));
|
|
62732
63707
|
return 2;
|
|
@@ -62736,7 +63711,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62736
63711
|
return 2;
|
|
62737
63712
|
}
|
|
62738
63713
|
try {
|
|
62739
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
63714
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync68(join53(sourceDir, "tokens.json"), "utf8")));
|
|
62740
63715
|
meta = { ...appearance, ...meta };
|
|
62741
63716
|
} catch {
|
|
62742
63717
|
}
|
|
@@ -62748,7 +63723,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62748
63723
|
const force = flags.force === true;
|
|
62749
63724
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
62750
63725
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
62751
|
-
const out = mkdtempSync4(
|
|
63726
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-template-"));
|
|
62752
63727
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
62753
63728
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
62754
63729
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
@@ -62801,7 +63776,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62801
63776
|
let iconHash;
|
|
62802
63777
|
if (iconPath) {
|
|
62803
63778
|
try {
|
|
62804
|
-
const bytes2 =
|
|
63779
|
+
const bytes2 = readFileSync68(iconPath);
|
|
62805
63780
|
payload.icon = bytes2.toString("base64");
|
|
62806
63781
|
iconHash = createHash24("sha256").update(bytes2).digest("hex");
|
|
62807
63782
|
} catch {
|
|
@@ -62970,7 +63945,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62970
63945
|
});
|
|
62971
63946
|
return 0;
|
|
62972
63947
|
}
|
|
62973
|
-
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>]" }));
|
|
63948
|
+
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]" }));
|
|
62974
63949
|
return 2;
|
|
62975
63950
|
}
|
|
62976
63951
|
case "build": {
|
|
@@ -62997,12 +63972,12 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62997
63972
|
print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
|
|
62998
63973
|
return 2;
|
|
62999
63974
|
}
|
|
63000
|
-
const { readdirSync:
|
|
63975
|
+
const { readdirSync: readdirSync27, existsSync: fileExists } = await import("node:fs");
|
|
63001
63976
|
const { join: pathJoin } = await import("node:path");
|
|
63002
63977
|
const targets = [];
|
|
63003
63978
|
const t5 = pathJoin(dir, "tier5-src");
|
|
63004
63979
|
if (fileExists(t5)) {
|
|
63005
|
-
for (const d of
|
|
63980
|
+
for (const d of readdirSync27(t5, { withFileTypes: true })) {
|
|
63006
63981
|
if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
|
|
63007
63982
|
}
|
|
63008
63983
|
}
|
|
@@ -63034,7 +64009,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63034
64009
|
const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
|
|
63035
64010
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
63036
64011
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
63037
|
-
const out = mkdtempSync4(
|
|
64012
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-validate-"));
|
|
63038
64013
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63039
64014
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63040
64015
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63071,7 +64046,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63071
64046
|
const path2 = dpxSessionTokenPath();
|
|
63072
64047
|
let raw;
|
|
63073
64048
|
try {
|
|
63074
|
-
raw =
|
|
64049
|
+
raw = readFileSync68(path2, "utf8");
|
|
63075
64050
|
} catch {
|
|
63076
64051
|
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`);
|
|
63077
64052
|
}
|
|
@@ -63241,7 +64216,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63241
64216
|
case "test": {
|
|
63242
64217
|
const dir = contentDir(flags);
|
|
63243
64218
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
63244
|
-
if (
|
|
64219
|
+
if (existsSync57(join53(dir, "functions"))) {
|
|
63245
64220
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
63246
64221
|
const loaded = await loadFunctionsApp2(dir);
|
|
63247
64222
|
const results = [];
|
|
@@ -63328,7 +64303,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63328
64303
|
}
|
|
63329
64304
|
}
|
|
63330
64305
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
63331
|
-
const out = mkdtempSync4(
|
|
64306
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-test-"));
|
|
63332
64307
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63333
64308
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63334
64309
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63373,7 +64348,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63373
64348
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
63374
64349
|
return 2;
|
|
63375
64350
|
}
|
|
63376
|
-
const sources = collectWorkerSources2(
|
|
64351
|
+
const sources = collectWorkerSources2(join53(dir, "tier5-src"), screen.bundleName);
|
|
63377
64352
|
if (!sources) {
|
|
63378
64353
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
63379
64354
|
return 2;
|
|
@@ -63534,7 +64509,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63534
64509
|
const sp = await runShotsPass2({
|
|
63535
64510
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
63536
64511
|
tokens: outcome.tokens,
|
|
63537
|
-
outDir:
|
|
64512
|
+
outDir: join53(dir, ".himi", "shots"),
|
|
63538
64513
|
width: 390,
|
|
63539
64514
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
63540
64515
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -63544,7 +64519,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63544
64519
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
63545
64520
|
renderPngBatch: renderPngBatch2,
|
|
63546
64521
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
63547
|
-
clearDir: (d) =>
|
|
64522
|
+
clearDir: (d) => rmSync11(d, { recursive: true, force: true })
|
|
63548
64523
|
}
|
|
63549
64524
|
});
|
|
63550
64525
|
writtenShots = sp.written;
|
|
@@ -63572,7 +64547,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63572
64547
|
releaseId: result.releaseId,
|
|
63573
64548
|
releasePayload: release,
|
|
63574
64549
|
descriptors: attestedDescriptors,
|
|
63575
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
64550
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join53(dir, ".himi", "shots", name)])),
|
|
63576
64551
|
coverage: {
|
|
63577
64552
|
screens: crawledScreens.size,
|
|
63578
64553
|
actionsDispatched: result.actions.exercised,
|
|
@@ -63661,7 +64636,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63661
64636
|
return 2;
|
|
63662
64637
|
}
|
|
63663
64638
|
try {
|
|
63664
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
64639
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync68(stateArg.replace(/^@/, ""), "utf8");
|
|
63665
64640
|
injectedState = JSON.parse(raw);
|
|
63666
64641
|
} catch (e) {
|
|
63667
64642
|
io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
|
|
@@ -63676,7 +64651,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63676
64651
|
return 2;
|
|
63677
64652
|
}
|
|
63678
64653
|
try {
|
|
63679
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
64654
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync68(inputArg.replace(/^@/, ""), "utf8");
|
|
63680
64655
|
const parsed = JSON.parse(raw);
|
|
63681
64656
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
63682
64657
|
injectedInput = parsed;
|
|
@@ -63725,7 +64700,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63725
64700
|
}
|
|
63726
64701
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
63727
64702
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
63728
|
-
const out = mkdtempSync4(
|
|
64703
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-render-"));
|
|
63729
64704
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
63730
64705
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
63731
64706
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -63741,7 +64716,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63741
64716
|
let attestationPngFile;
|
|
63742
64717
|
if (typeof flags.png === "string" && r.pngBase64) {
|
|
63743
64718
|
pngFile = writePngFile(str5(flags.png), r.pngBase64);
|
|
63744
|
-
attestationPngFile = writePngFile(
|
|
64719
|
+
attestationPngFile = writePngFile(join53(dir, ".himi", "shots", `${screenId}.png`), r.pngBase64);
|
|
63745
64720
|
}
|
|
63746
64721
|
if (renderWidth !== void 0 && r.renderable) {
|
|
63747
64722
|
recordRenderWidth(dir, {
|
|
@@ -64073,20 +65048,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64073
65048
|
io.error(JSON.stringify(linked));
|
|
64074
65049
|
return 1;
|
|
64075
65050
|
}
|
|
64076
|
-
if (
|
|
64077
|
-
if (!
|
|
65051
|
+
if (existsSync57(dest)) {
|
|
65052
|
+
if (!statSync14(dest).isDirectory()) {
|
|
64078
65053
|
io.error(JSON.stringify({
|
|
64079
65054
|
error: `${dest} exists and is not a directory`,
|
|
64080
65055
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
64081
65056
|
}));
|
|
64082
65057
|
return 1;
|
|
64083
65058
|
}
|
|
64084
|
-
const occupied =
|
|
65059
|
+
const occupied = readdirSync26(dest).length > 0;
|
|
64085
65060
|
if (occupied && !force) {
|
|
64086
65061
|
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" }));
|
|
64087
65062
|
return 1;
|
|
64088
65063
|
}
|
|
64089
|
-
if (replace && occupied && !
|
|
65064
|
+
if (replace && occupied && !existsSync57(join53(dest, "himalaya.content.json"))) {
|
|
64090
65065
|
io.error(JSON.stringify({
|
|
64091
65066
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
64092
65067
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -64225,7 +65200,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64225
65200
|
const force = flags.force === true;
|
|
64226
65201
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64227
65202
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
64228
|
-
const out = mkdtempSync4(
|
|
65203
|
+
const out = mkdtempSync4(join53(tmpdir5(), "himi-push-"));
|
|
64229
65204
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64230
65205
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
64231
65206
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -64745,7 +65720,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64745
65720
|
}
|
|
64746
65721
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64747
65722
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
64748
|
-
const built = mkdtempSync4(
|
|
65723
|
+
const built = mkdtempSync4(join53(tmpdir5(), "himi-pack-"));
|
|
64749
65724
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64750
65725
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
64751
65726
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -64762,7 +65737,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64762
65737
|
...await navIssues2(dir, strict)
|
|
64763
65738
|
]);
|
|
64764
65739
|
if (hasErrors && !force) {
|
|
64765
|
-
|
|
65740
|
+
rmSync11(built, { recursive: true, force: true });
|
|
64766
65741
|
print({ ...report2, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
64767
65742
|
return 1;
|
|
64768
65743
|
}
|
|
@@ -64798,7 +65773,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64798
65773
|
io.error(JSON.stringify({ error: e.message }));
|
|
64799
65774
|
return 1;
|
|
64800
65775
|
} finally {
|
|
64801
|
-
|
|
65776
|
+
rmSync11(built, { recursive: true, force: true });
|
|
64802
65777
|
}
|
|
64803
65778
|
}
|
|
64804
65779
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -64948,7 +65923,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64948
65923
|
}));
|
|
64949
65924
|
return 1;
|
|
64950
65925
|
}
|
|
64951
|
-
const archive =
|
|
65926
|
+
const archive = readFileSync68(resolve44(file));
|
|
64952
65927
|
const result = await client2().createPackageShare({
|
|
64953
65928
|
app: opened.header.app,
|
|
64954
65929
|
releaseId: opened.header.releaseId,
|
|
@@ -64985,10 +65960,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
64985
65960
|
const app = await appId(dir);
|
|
64986
65961
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
64987
65962
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
64988
|
-
temp = mkdtempSync4(
|
|
65963
|
+
temp = mkdtempSync4(join53(tmpdir5(), "himi-run-build-"));
|
|
64989
65964
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
64990
65965
|
await buildReleaseFromContent2(dir, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
|
|
64991
|
-
source =
|
|
65966
|
+
source = join53(temp, app);
|
|
64992
65967
|
}
|
|
64993
65968
|
const chromeArg = str5(flags.chrome) ?? "preview";
|
|
64994
65969
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -65051,7 +66026,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65051
66026
|
io.error(JSON.stringify({ error: e.message }));
|
|
65052
66027
|
return 1;
|
|
65053
66028
|
} finally {
|
|
65054
|
-
if (temp)
|
|
66029
|
+
if (temp) rmSync11(temp, { recursive: true, force: true });
|
|
65055
66030
|
}
|
|
65056
66031
|
}
|
|
65057
66032
|
case "preview": {
|
|
@@ -65592,7 +66567,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65592
66567
|
io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
65593
66568
|
return 2;
|
|
65594
66569
|
}
|
|
65595
|
-
if (!
|
|
66570
|
+
if (!existsSync57(file)) {
|
|
65596
66571
|
io.error(JSON.stringify({ error: `no such file: ${file}` }));
|
|
65597
66572
|
return 2;
|
|
65598
66573
|
}
|
|
@@ -65648,7 +66623,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65648
66623
|
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."
|
|
65649
66624
|
};
|
|
65650
66625
|
if (kind === "tokens" || kind === "app-config") {
|
|
65651
|
-
const body =
|
|
66626
|
+
const body = readFileSync68(file, "utf8");
|
|
65652
66627
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
65653
66628
|
return runReleasePatch({
|
|
65654
66629
|
...common,
|
|
@@ -65663,7 +66638,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65663
66638
|
io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
65664
66639
|
return 2;
|
|
65665
66640
|
}
|
|
65666
|
-
const descriptor =
|
|
66641
|
+
const descriptor = readFileSync68(file, "utf8");
|
|
65667
66642
|
try {
|
|
65668
66643
|
JSON.parse(descriptor);
|
|
65669
66644
|
} catch (e) {
|
|
@@ -65703,7 +66678,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65703
66678
|
extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
65704
66679
|
});
|
|
65705
66680
|
}
|
|
65706
|
-
const bytes2 =
|
|
66681
|
+
const bytes2 = readFileSync68(file);
|
|
65707
66682
|
const sha = createHash24("sha256").update(bytes2).digest("hex");
|
|
65708
66683
|
const forScreens = (str5(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
65709
66684
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
@@ -65847,7 +66822,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65847
66822
|
}
|
|
65848
66823
|
let def;
|
|
65849
66824
|
try {
|
|
65850
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
66825
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync68(arg.slice(1), "utf8") : arg);
|
|
65851
66826
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
65852
66827
|
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}`] }));
|
|
65853
66828
|
return 2;
|
|
@@ -66311,7 +67286,7 @@ ${label2}`);
|
|
|
66311
67286
|
const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
66312
67287
|
{
|
|
66313
67288
|
const distDir = contentDir(flags);
|
|
66314
|
-
if (
|
|
67289
|
+
if (existsSync57(join53(distDir, "himalaya.content.json"))) {
|
|
66315
67290
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
66316
67291
|
const errors = issues.filter((i) => i.severity === "error");
|
|
66317
67292
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|
|
@@ -66580,7 +67555,7 @@ ${label2}`);
|
|
|
66580
67555
|
const dpxPath = dpxSessionTokenPath();
|
|
66581
67556
|
let dpx;
|
|
66582
67557
|
try {
|
|
66583
|
-
dpx =
|
|
67558
|
+
dpx = readFileSync68(dpxPath, "utf8").trim();
|
|
66584
67559
|
} catch {
|
|
66585
67560
|
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` }));
|
|
66586
67561
|
return 1;
|
|
@@ -66982,7 +67957,7 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
|
|
|
66982
67957
|
const path2 = dpxSessionTokenPath();
|
|
66983
67958
|
let raw;
|
|
66984
67959
|
try {
|
|
66985
|
-
raw =
|
|
67960
|
+
raw = readFileSync68(path2, "utf8");
|
|
66986
67961
|
} catch {
|
|
66987
67962
|
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
66988
67963
|
return 1;
|