@wix/himalaya-cli 0.1386.0 → 0.1387.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/wix-auth.mjs +9 -0
- package/dist/cli.mjs +1244 -489
- package/guides/branded-lite-site-binding.md +12 -5
- package/guides/himi-json-output.md +12 -2
- package/guides/iap-products.md +91 -11
- package/package.json +2 -2
- package/templates/beauty-salon/README.md +8 -3
- package/templates/branded-lite/README.md +8 -3
- package/templates/community-club/README.md +8 -3
- package/templates/events-meetups/README.md +8 -3
- package/templates/gym-fitness/README.md +8 -3
- package/templates/nonprofit-cause/README.md +8 -3
- package/templates/podcast-creator/README.md +8 -3
- package/templates/portfolio-creative/README.md +8 -3
- package/templates/restaurant/README.md +8 -3
- package/templates/retail-store/README.md +8 -3
- package/templates/yoga-studio/README.md +8 -3
package/dist/cli.mjs
CHANGED
|
@@ -3738,7 +3738,7 @@ async function browserLogin(opts) {
|
|
|
3738
3738
|
const log = opts.log ?? (() => {
|
|
3739
3739
|
});
|
|
3740
3740
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3741
|
-
return await new Promise((
|
|
3741
|
+
return await new Promise((resolve65, reject) => {
|
|
3742
3742
|
let settled = false;
|
|
3743
3743
|
let loginUrl = "";
|
|
3744
3744
|
const server = createServer();
|
|
@@ -3804,7 +3804,7 @@ async function browserLogin(opts) {
|
|
|
3804
3804
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(closePage(opts.doneTitle ?? "Signed in to himi"));
|
|
3805
3805
|
const extra = {};
|
|
3806
3806
|
for (const [k2, v2] of params) if (k2 !== "token" && k2 !== "state") extra[k2] = v2;
|
|
3807
|
-
finish2(() =>
|
|
3807
|
+
finish2(() => resolve65({ token, loginUrl, extra }));
|
|
3808
3808
|
});
|
|
3809
3809
|
});
|
|
3810
3810
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -3916,7 +3916,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
3916
3916
|
tokenCache.set(cacheKey, fromEnv);
|
|
3917
3917
|
return fromEnv;
|
|
3918
3918
|
}
|
|
3919
|
-
const token = await new Promise((
|
|
3919
|
+
const token = await new Promise((resolve65, reject) => {
|
|
3920
3920
|
let child;
|
|
3921
3921
|
try {
|
|
3922
3922
|
child = spawnImpl("wix", [...args]);
|
|
@@ -3945,12 +3945,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
3945
3945
|
child.stdout?.on("data", (d2) => {
|
|
3946
3946
|
out2 += String(d2);
|
|
3947
3947
|
const m2 = out2.match(TOKEN_RE);
|
|
3948
|
-
if (m2) done(() =>
|
|
3948
|
+
if (m2) done(() => resolve65(m2[0]));
|
|
3949
3949
|
});
|
|
3950
3950
|
child.stderr?.on("data", (d2) => {
|
|
3951
3951
|
out2 += String(d2);
|
|
3952
3952
|
const m2 = out2.match(TOKEN_RE);
|
|
3953
|
-
if (m2) done(() =>
|
|
3953
|
+
if (m2) done(() => resolve65(m2[0]));
|
|
3954
3954
|
});
|
|
3955
3955
|
child.on("error", (e2) => done(() => reject(new Error(mintHelp(label2, e2.message)))));
|
|
3956
3956
|
child.on("exit", (code) => done(() => reject(new Error(
|
|
@@ -4160,8 +4160,8 @@ function committedProvisioningPath(name) {
|
|
|
4160
4160
|
function committedShellFor(path2) {
|
|
4161
4161
|
const normalized = path2.replace(/\\/g, "/");
|
|
4162
4162
|
return SHELL_NAMES2.find((name) => {
|
|
4163
|
-
const
|
|
4164
|
-
return normalized ===
|
|
4163
|
+
const relative17 = committedProvisioningPath(name);
|
|
4164
|
+
return normalized === relative17 || normalized.endsWith(`/${relative17}`);
|
|
4165
4165
|
});
|
|
4166
4166
|
}
|
|
4167
4167
|
function isBrandable(repoRoot2, name) {
|
|
@@ -6876,9 +6876,9 @@ function compileV2(html, profile, options) {
|
|
|
6876
6876
|
if (!row) error(el2, "HHP-BINDING-SCOPE", "Item bindings require a keyed list template.");
|
|
6877
6877
|
return raw;
|
|
6878
6878
|
}
|
|
6879
|
-
const
|
|
6880
|
-
if (!info4?.paths.has(
|
|
6881
|
-
return `$service:${serviceName}.${
|
|
6879
|
+
const relative17 = statePath(raw);
|
|
6880
|
+
if (!info4?.paths.has(relative17)) error(el2, "HHP-BINDING-PATH", `Unknown controller state path ${relative17}.`);
|
|
6881
|
+
return `$service:${serviceName}.${relative17}`;
|
|
6882
6882
|
}
|
|
6883
6883
|
function coerce(raw, field) {
|
|
6884
6884
|
if (field.schema.type === "boolean") return raw === "" || raw === "true" ? true : raw === "false" ? false : raw;
|
|
@@ -10249,7 +10249,8 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10249
10249
|
}
|
|
10250
10250
|
return value;
|
|
10251
10251
|
});
|
|
10252
|
-
}
|
|
10252
|
+
},
|
|
10253
|
+
...opts.wixApiSession ? { identityBound: opts.wixApiSession.identityBound, session: opts.wixApiSession.session } : {}
|
|
10253
10254
|
};
|
|
10254
10255
|
const dispatchHost = (action, params) => {
|
|
10255
10256
|
if (action === "himi.open" && params && typeof params.screenId === "string") {
|
|
@@ -25433,10 +25434,10 @@ var init_preview = __esm({
|
|
|
25433
25434
|
}
|
|
25434
25435
|
},
|
|
25435
25436
|
kill: (pid, signal) => process.kill(pid, signal),
|
|
25436
|
-
portFree: (port) => new Promise((
|
|
25437
|
+
portFree: (port) => new Promise((resolve65) => {
|
|
25437
25438
|
const s2 = createServer2();
|
|
25438
|
-
s2.once("error", () =>
|
|
25439
|
-
s2.listen(port, "127.0.0.1", () => s2.close(() =>
|
|
25439
|
+
s2.once("error", () => resolve65(false));
|
|
25440
|
+
s2.listen(port, "127.0.0.1", () => s2.close(() => resolve65(true)));
|
|
25440
25441
|
}),
|
|
25441
25442
|
sleep: (ms2) => new Promise((r2) => setTimeout(r2, ms2)),
|
|
25442
25443
|
servingIdentity: async (origin) => {
|
|
@@ -29427,7 +29428,7 @@ async function injectRequest(listener, request) {
|
|
|
29427
29428
|
req.headers.host ??= url.host;
|
|
29428
29429
|
if (body && body.length > 0) req.push(body);
|
|
29429
29430
|
req.push(null);
|
|
29430
|
-
return await new Promise((
|
|
29431
|
+
return await new Promise((resolve65, reject) => {
|
|
29431
29432
|
const streamed = () => {
|
|
29432
29433
|
queueMicrotask(() => {
|
|
29433
29434
|
req.emit("close");
|
|
@@ -29443,7 +29444,7 @@ async function injectRequest(listener, request) {
|
|
|
29443
29444
|
else headers2.set(name, value);
|
|
29444
29445
|
}
|
|
29445
29446
|
const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
|
|
29446
|
-
|
|
29447
|
+
resolve65(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
|
|
29447
29448
|
}, streamed);
|
|
29448
29449
|
res.on("inject-error", reject);
|
|
29449
29450
|
try {
|
|
@@ -35580,12 +35581,12 @@ function finalizeRecording(key2, rec) {
|
|
|
35580
35581
|
if (rec.finalize) return rec.finalize;
|
|
35581
35582
|
rec.finalize = (async () => {
|
|
35582
35583
|
clearTimeout(rec.autoStop);
|
|
35583
|
-
await new Promise((
|
|
35584
|
+
await new Promise((resolve65) => {
|
|
35584
35585
|
let done = false;
|
|
35585
35586
|
const finish2 = () => {
|
|
35586
35587
|
if (!done) {
|
|
35587
35588
|
done = true;
|
|
35588
|
-
|
|
35589
|
+
resolve65();
|
|
35589
35590
|
}
|
|
35590
35591
|
};
|
|
35591
35592
|
rec.child.once("close", finish2);
|
|
@@ -35696,7 +35697,7 @@ var init_preview2 = __esm({
|
|
|
35696
35697
|
DEVICE_LIST_TIMEOUT_MS = 5e3;
|
|
35697
35698
|
defaultRunner2 = {
|
|
35698
35699
|
capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
|
|
35699
|
-
return new Promise((
|
|
35700
|
+
return new Promise((resolve65, reject) => {
|
|
35700
35701
|
const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
35701
35702
|
const out2 = [];
|
|
35702
35703
|
const err = [];
|
|
@@ -35718,7 +35719,7 @@ var init_preview2 = __esm({
|
|
|
35718
35719
|
child.stderr.on("data", (b2) => err.push(b2));
|
|
35719
35720
|
child.on("error", (e2) => settle(reject, e2));
|
|
35720
35721
|
child.on("close", (code) => {
|
|
35721
|
-
if (code === 0) settle(
|
|
35722
|
+
if (code === 0) settle(resolve65, Buffer.concat(out2));
|
|
35722
35723
|
else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
35723
35724
|
});
|
|
35724
35725
|
});
|
|
@@ -38031,12 +38032,12 @@ function createRicosHostSession(o2) {
|
|
|
38031
38032
|
flush() {
|
|
38032
38033
|
if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
|
|
38033
38034
|
const requestId2 = newId();
|
|
38034
|
-
return new Promise((
|
|
38035
|
+
return new Promise((resolve65) => {
|
|
38035
38036
|
const timer = t2.setTimeout(() => {
|
|
38036
38037
|
flushes.delete(requestId2);
|
|
38037
|
-
|
|
38038
|
+
resolve65(null);
|
|
38038
38039
|
}, flushMs);
|
|
38039
|
-
flushes.set(requestId2, { resolve:
|
|
38040
|
+
flushes.set(requestId2, { resolve: resolve65, timer });
|
|
38040
38041
|
o2.send({ v: 1, type: "requestContent", requestId: requestId2 });
|
|
38041
38042
|
});
|
|
38042
38043
|
},
|
|
@@ -38095,7 +38096,7 @@ async function runRicosImageUpload(o2) {
|
|
|
38095
38096
|
};
|
|
38096
38097
|
session.insertMediaPlaceholder(requestId2);
|
|
38097
38098
|
try {
|
|
38098
|
-
const entry = await new Promise((
|
|
38099
|
+
const entry = await new Promise((resolve65) => {
|
|
38099
38100
|
let done = false;
|
|
38100
38101
|
let unsub = () => {
|
|
38101
38102
|
};
|
|
@@ -38104,7 +38105,7 @@ async function runRicosImageUpload(o2) {
|
|
|
38104
38105
|
done = true;
|
|
38105
38106
|
t2.clearTimeout(timer);
|
|
38106
38107
|
queueMicrotask(() => unsub());
|
|
38107
|
-
|
|
38108
|
+
resolve65(v2);
|
|
38108
38109
|
};
|
|
38109
38110
|
const timer = t2.setTimeout(() => finish2(null), o2.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
|
|
38110
38111
|
unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v2) => {
|
|
@@ -38626,10 +38627,10 @@ async function runMediaFieldUpload(o2) {
|
|
|
38626
38627
|
}, o2.timeoutMs ?? MEDIA_FIELD_UPLOAD_TIMEOUT_MS);
|
|
38627
38628
|
const bounded2 = (p2) => {
|
|
38628
38629
|
if (expired) return Promise.reject(new Deadline());
|
|
38629
|
-
return new Promise((
|
|
38630
|
+
return new Promise((resolve65, reject) => {
|
|
38630
38631
|
const stop = () => reject(new Deadline());
|
|
38631
38632
|
onExpire.push(stop);
|
|
38632
|
-
p2.then(
|
|
38633
|
+
p2.then(resolve65, reject).finally(() => {
|
|
38633
38634
|
onExpire = onExpire.filter((f2) => f2 !== stop);
|
|
38634
38635
|
});
|
|
38635
38636
|
});
|
|
@@ -38652,7 +38653,7 @@ async function runMediaFieldUpload(o2) {
|
|
|
38652
38653
|
const before = deps.value(urlPath);
|
|
38653
38654
|
let uploadUrl;
|
|
38654
38655
|
try {
|
|
38655
|
-
uploadUrl = await bounded2(new Promise((
|
|
38656
|
+
uploadUrl = await bounded2(new Promise((resolve65, reject) => {
|
|
38656
38657
|
let done = false;
|
|
38657
38658
|
let unsub = () => {
|
|
38658
38659
|
};
|
|
@@ -38660,7 +38661,7 @@ async function runMediaFieldUpload(o2) {
|
|
|
38660
38661
|
if (done || typeof v2 !== "string" || v2 === "" || v2 === before) return;
|
|
38661
38662
|
done = true;
|
|
38662
38663
|
queueMicrotask(() => unsub());
|
|
38663
|
-
|
|
38664
|
+
resolve65(v2);
|
|
38664
38665
|
});
|
|
38665
38666
|
onExpire.push(() => {
|
|
38666
38667
|
if (!done) {
|
|
@@ -38675,7 +38676,7 @@ async function runMediaFieldUpload(o2) {
|
|
|
38675
38676
|
if (typeof now === "string" && now !== "" && now !== before) {
|
|
38676
38677
|
done = true;
|
|
38677
38678
|
queueMicrotask(() => unsub());
|
|
38678
|
-
|
|
38679
|
+
resolve65(now);
|
|
38679
38680
|
return;
|
|
38680
38681
|
}
|
|
38681
38682
|
}
|
|
@@ -39121,7 +39122,7 @@ var init_controls = __esm({
|
|
|
39121
39122
|
}, [selectedId]);
|
|
39122
39123
|
const current = local != null && tabs.some((t2) => t2.id === local) ? local : selectedId;
|
|
39123
39124
|
const selIdx = Math.max(0, tabs.findIndex((t2) => t2.id === (current ?? tabs[0]?.id)));
|
|
39124
|
-
const
|
|
39125
|
+
const select2 = (i2) => {
|
|
39125
39126
|
if (pages2) setLocal(tabs[i2]?.id);
|
|
39126
39127
|
const act = actOf(tabs[i2], props.onChange ?? props.onSelect);
|
|
39127
39128
|
if (ctx.onAction && act) ctx.onAction(withSelection(act, { selectedId: String(tabs[i2]?.id ?? i2) }));
|
|
@@ -39134,7 +39135,7 @@ var init_controls = __esm({
|
|
|
39134
39135
|
else if (e2.key === "End") ni2 = tabs.length - 1;
|
|
39135
39136
|
else return;
|
|
39136
39137
|
e2.preventDefault();
|
|
39137
|
-
if (ni2 !== selIdx)
|
|
39138
|
+
if (ni2 !== selIdx) select2(ni2);
|
|
39138
39139
|
};
|
|
39139
39140
|
const pagerRef = React5.useRef(null);
|
|
39140
39141
|
const settle = React5.useRef(void 0);
|
|
@@ -39151,7 +39152,7 @@ var init_controls = __esm({
|
|
|
39151
39152
|
const el2 = pagerRef.current;
|
|
39152
39153
|
if (!el2 || !el2.clientWidth) return;
|
|
39153
39154
|
const i2 = Math.round(el2.scrollLeft / el2.clientWidth);
|
|
39154
|
-
if (i2 >= 0 && i2 < tabs.length && i2 !== selIdx)
|
|
39155
|
+
if (i2 >= 0 && i2 < tabs.length && i2 !== selIdx) select2(i2);
|
|
39155
39156
|
}, 120);
|
|
39156
39157
|
};
|
|
39157
39158
|
const accent = C2("accentPrimary", "#116DFF");
|
|
@@ -39166,7 +39167,7 @@ var init_controls = __esm({
|
|
|
39166
39167
|
role: "tab",
|
|
39167
39168
|
"aria-selected": on4,
|
|
39168
39169
|
tabIndex: on4 ? 0 : -1,
|
|
39169
|
-
onClick: () =>
|
|
39170
|
+
onClick: () => select2(i2),
|
|
39170
39171
|
style: { all: "unset", display: "flex", gap: 6, alignItems: "center", minWidth: 44, minHeight: 44, padding: "10px 0", fontFamily: FONT(ctx), fontWeight: 600, fontSize: pxToRem(14), cursor: "pointer", color: on4 ? activeLabel : C2("textSecondary", "#777"), borderBottom: on4 ? `2px solid ${activeTint}` : "2px solid transparent", marginBottom: -1 },
|
|
39171
39172
|
children: [
|
|
39172
39173
|
asText2(t2.label),
|
|
@@ -39209,7 +39210,7 @@ var init_controls = __esm({
|
|
|
39209
39210
|
const awaitingBinding = isBinding(props.selectedId) && resolvedSel == null;
|
|
39210
39211
|
const selId = ctx.empty || awaitingBinding ? null : resolvedSel ?? opts[0]?.id;
|
|
39211
39212
|
const selIdx = Math.max(0, opts.findIndex((o2) => o2.id === selId));
|
|
39212
|
-
const
|
|
39213
|
+
const select2 = (i2) => {
|
|
39213
39214
|
const act = actOf(opts[i2], props.onChange ?? props.onSelect);
|
|
39214
39215
|
if (ctx.onAction && act) ctx.onAction(withSelection(act, { selectedId: String(opts[i2]?.id ?? i2) }));
|
|
39215
39216
|
};
|
|
@@ -39219,7 +39220,7 @@ var init_controls = __esm({
|
|
|
39219
39220
|
else if (e2.key === "ArrowLeft" || e2.key === "ArrowUp") ni2 = (selIdx - 1 + opts.length) % opts.length;
|
|
39220
39221
|
else return;
|
|
39221
39222
|
e2.preventDefault();
|
|
39222
|
-
if (ni2 !== selIdx)
|
|
39223
|
+
if (ni2 !== selIdx) select2(ni2);
|
|
39223
39224
|
};
|
|
39224
39225
|
return /* @__PURE__ */ jsx6("div", { role: "radiogroup", onKeyDown, style: { display: "flex", background: seg.outlined ? "transparent" : C2("surfaceTertiary", "#eee"), borderRadius: radius(seg.trackRadius, "md", 8), padding: seg.trackPadding, width: "100%", boxSizing: "border-box", ...wrap }, children: opts.map((o2, i2) => {
|
|
39225
39226
|
const on4 = o2.id === selId;
|
|
@@ -39236,7 +39237,7 @@ var init_controls = __esm({
|
|
|
39236
39237
|
role: "radio",
|
|
39237
39238
|
"aria-checked": on4,
|
|
39238
39239
|
tabIndex: on4 || selId == null && i2 === 0 ? 0 : -1,
|
|
39239
|
-
onClick: () =>
|
|
39240
|
+
onClick: () => select2(i2),
|
|
39240
39241
|
style: { all: "unset", flex: 1, minWidth: 44, minHeight: seg.height - 2 * seg.trackPadding, textAlign: "center", padding: "7px 4px", borderRadius: outerR, fontFamily: FONT(ctx), fontWeight: 600, fontSize: pxToRem(13), cursor: "pointer", boxSizing: "border-box", background: on4 ? C2("surfacePrimary", "#fff") : seg.outlined ? C2(pickRole(ctx.tokens.colors, seg.roles.inactive), "#eee") : "transparent", color: on4 ? C2("textPrimary", "#111") : C2("textSecondary", "#777"), boxShadow: on4 && !seg.outlined ? "0 1px 3px rgba(0,0,0,.12)" : "none", ...outlinedShape },
|
|
39241
39242
|
children: [
|
|
39242
39243
|
on4 && seg.selectedCheck ? /* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u2713 " }) : null,
|
|
@@ -40824,7 +40825,7 @@ async function fetchData(url, type = "text") {
|
|
|
40824
40825
|
}
|
|
40825
40826
|
return response.text();
|
|
40826
40827
|
}
|
|
40827
|
-
return new Promise((
|
|
40828
|
+
return new Promise((resolve65, reject) => {
|
|
40828
40829
|
const request = new XMLHttpRequest();
|
|
40829
40830
|
request.open("GET", url, true);
|
|
40830
40831
|
request.responseType = type === "bytes" ? "arraybuffer" : type;
|
|
@@ -40835,14 +40836,14 @@ async function fetchData(url, type = "text") {
|
|
|
40835
40836
|
if (request.status === 200 || request.status === 0) {
|
|
40836
40837
|
switch (type) {
|
|
40837
40838
|
case "bytes":
|
|
40838
|
-
|
|
40839
|
+
resolve65(new Uint8Array(request.response));
|
|
40839
40840
|
return;
|
|
40840
40841
|
case "blob":
|
|
40841
40842
|
case "json":
|
|
40842
|
-
|
|
40843
|
+
resolve65(request.response);
|
|
40843
40844
|
return;
|
|
40844
40845
|
}
|
|
40845
|
-
|
|
40846
|
+
resolve65(request.responseText);
|
|
40846
40847
|
return;
|
|
40847
40848
|
}
|
|
40848
40849
|
reject(new Error(request.statusText));
|
|
@@ -43774,7 +43775,7 @@ var init_pdf = __esm({
|
|
|
43774
43775
|
var defineProperty = Object.defineProperty;
|
|
43775
43776
|
var stringSlice = uncurryThis("".slice);
|
|
43776
43777
|
var replace = uncurryThis("".replace);
|
|
43777
|
-
var
|
|
43778
|
+
var join88 = uncurryThis([].join);
|
|
43778
43779
|
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
|
|
43779
43780
|
return defineProperty(function() {
|
|
43780
43781
|
}, "length", { value: 8 }).length !== 8;
|
|
@@ -43801,7 +43802,7 @@ var init_pdf = __esm({
|
|
|
43801
43802
|
}
|
|
43802
43803
|
var state = enforceInternalState(value);
|
|
43803
43804
|
if (!hasOwn(state, "source")) {
|
|
43804
|
-
state.source =
|
|
43805
|
+
state.source = join88(TEMPLATE, typeof name == "string" ? name : "");
|
|
43805
43806
|
}
|
|
43806
43807
|
return value;
|
|
43807
43808
|
};
|
|
@@ -43846,13 +43847,13 @@ var init_pdf = __esm({
|
|
|
43846
43847
|
var aCallable = __webpack_require__3(9306);
|
|
43847
43848
|
var $TypeError = TypeError;
|
|
43848
43849
|
var PromiseCapability = function(C2) {
|
|
43849
|
-
var
|
|
43850
|
+
var resolve65, reject;
|
|
43850
43851
|
this.promise = new C2(function($$resolve, $$reject) {
|
|
43851
|
-
if (
|
|
43852
|
-
|
|
43852
|
+
if (resolve65 !== void 0 || reject !== void 0) throw new $TypeError("Bad Promise constructor");
|
|
43853
|
+
resolve65 = $$resolve;
|
|
43853
43854
|
reject = $$reject;
|
|
43854
43855
|
});
|
|
43855
|
-
this.resolve = aCallable(
|
|
43856
|
+
this.resolve = aCallable(resolve65);
|
|
43856
43857
|
this.reject = aCallable(reject);
|
|
43857
43858
|
};
|
|
43858
43859
|
module.exports.f = function(C2) {
|
|
@@ -44220,8 +44221,8 @@ var init_pdf = __esm({
|
|
|
44220
44221
|
anObject(C2);
|
|
44221
44222
|
if (isObject3(x2) && x2.constructor === C2) return x2;
|
|
44222
44223
|
var promiseCapability = newPromiseCapability.f(C2);
|
|
44223
|
-
var
|
|
44224
|
-
|
|
44224
|
+
var resolve65 = promiseCapability.resolve;
|
|
44225
|
+
resolve65(x2);
|
|
44225
44226
|
return promiseCapability.promise;
|
|
44226
44227
|
};
|
|
44227
44228
|
},
|
|
@@ -46324,7 +46325,7 @@ var init_pdf = __esm({
|
|
|
46324
46325
|
var charAt = uncurryThis("".charAt);
|
|
46325
46326
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
46326
46327
|
var $Array = globalThis2.Array;
|
|
46327
|
-
var
|
|
46328
|
+
var join88 = uncurryThis([].join);
|
|
46328
46329
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
|
|
46329
46330
|
try {
|
|
46330
46331
|
var target = new Uint8Array2();
|
|
@@ -46370,7 +46371,7 @@ var init_pdf = __esm({
|
|
|
46370
46371
|
result[written++] = "=";
|
|
46371
46372
|
}
|
|
46372
46373
|
}
|
|
46373
|
-
return
|
|
46374
|
+
return join88(result, "");
|
|
46374
46375
|
}
|
|
46375
46376
|
});
|
|
46376
46377
|
},
|
|
@@ -46382,7 +46383,7 @@ var init_pdf = __esm({
|
|
|
46382
46383
|
var anUint8Array = __webpack_require__3(4154);
|
|
46383
46384
|
var notDetached = __webpack_require__3(5169);
|
|
46384
46385
|
var numberToString2 = uncurryThis(1.1.toString);
|
|
46385
|
-
var
|
|
46386
|
+
var join88 = uncurryThis([].join);
|
|
46386
46387
|
var $Array = Array;
|
|
46387
46388
|
var Uint8Array2 = globalThis2.Uint8Array;
|
|
46388
46389
|
var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
|
|
@@ -46402,7 +46403,7 @@ var init_pdf = __esm({
|
|
|
46402
46403
|
var hex2 = numberToString2(this[i2], 16);
|
|
46403
46404
|
result[i2] = hex2.length === 1 ? "0" + hex2 : hex2;
|
|
46404
46405
|
}
|
|
46405
|
-
return
|
|
46406
|
+
return join88(result, "");
|
|
46406
46407
|
}
|
|
46407
46408
|
});
|
|
46408
46409
|
},
|
|
@@ -48075,11 +48076,11 @@ var init_pdf = __esm({
|
|
|
48075
48076
|
const mustRemoveAspectRatioPromise = _ImageManager._isSVGFittingCanvas;
|
|
48076
48077
|
const fileReader = new FileReader();
|
|
48077
48078
|
const imageElement = new Image();
|
|
48078
|
-
const imagePromise = new Promise((
|
|
48079
|
+
const imagePromise = new Promise((resolve65, reject) => {
|
|
48079
48080
|
imageElement.onload = () => {
|
|
48080
48081
|
data.bitmap = imageElement;
|
|
48081
48082
|
data.isSvg = true;
|
|
48082
|
-
|
|
48083
|
+
resolve65();
|
|
48083
48084
|
};
|
|
48084
48085
|
fileReader.onload = async () => {
|
|
48085
48086
|
const url = data.svgUrl = fileReader.result;
|
|
@@ -48765,13 +48766,13 @@ var init_pdf = __esm({
|
|
|
48765
48766
|
return;
|
|
48766
48767
|
}
|
|
48767
48768
|
const {
|
|
48768
|
-
resolve:
|
|
48769
|
+
resolve: resolve65,
|
|
48769
48770
|
promise
|
|
48770
48771
|
} = Promise.withResolvers();
|
|
48771
48772
|
const onEditorsRendered = (evt) => {
|
|
48772
48773
|
if (evt.pageNumber === pageNumber) {
|
|
48773
48774
|
this._eventBus.off("editorsrendered", onEditorsRendered);
|
|
48774
|
-
|
|
48775
|
+
resolve65();
|
|
48775
48776
|
}
|
|
48776
48777
|
};
|
|
48777
48778
|
this._eventBus.on("editorsrendered", onEditorsRendered, internalOpt);
|
|
@@ -53809,8 +53810,8 @@ var init_pdf = __esm({
|
|
|
53809
53810
|
if (this.isSyncFontLoadingSupported) {
|
|
53810
53811
|
return;
|
|
53811
53812
|
}
|
|
53812
|
-
await new Promise((
|
|
53813
|
-
const request = this._queueLoadingCallback(
|
|
53813
|
+
await new Promise((resolve65) => {
|
|
53814
|
+
const request = this._queueLoadingCallback(resolve65);
|
|
53814
53815
|
this._prepareFontLoadEvent(font, request);
|
|
53815
53816
|
});
|
|
53816
53817
|
}
|
|
@@ -70850,7 +70851,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
70850
70851
|
input.type = "file";
|
|
70851
70852
|
input.accept = SupportedImageMimeTypes.join(",");
|
|
70852
70853
|
const signal = this._uiManager._signal;
|
|
70853
|
-
this.#bitmapPromise = new Promise((
|
|
70854
|
+
this.#bitmapPromise = new Promise((resolve65) => {
|
|
70854
70855
|
input.addEventListener("change", async () => {
|
|
70855
70856
|
if (!input.files || input.files.length === 0) {
|
|
70856
70857
|
this.remove();
|
|
@@ -70865,13 +70866,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
70865
70866
|
});
|
|
70866
70867
|
this.#getBitmapFetched(data);
|
|
70867
70868
|
}
|
|
70868
|
-
|
|
70869
|
+
resolve65();
|
|
70869
70870
|
}, {
|
|
70870
70871
|
signal
|
|
70871
70872
|
});
|
|
70872
70873
|
input.addEventListener("cancel", () => {
|
|
70873
70874
|
this.remove();
|
|
70874
|
-
|
|
70875
|
+
resolve65();
|
|
70875
70876
|
}, {
|
|
70876
70877
|
signal
|
|
70877
70878
|
});
|
|
@@ -125161,7 +125162,7 @@ var init_renderNode = __esm({
|
|
|
125161
125162
|
media.currentTime = Math.max(0, Math.min(seconds, Number.isFinite(media.duration) ? media.duration : seconds));
|
|
125162
125163
|
setPosition(media.currentTime);
|
|
125163
125164
|
}, []);
|
|
125164
|
-
const
|
|
125165
|
+
const select2 = React9.useCallback((next) => {
|
|
125165
125166
|
if (resolvedItems.length === 0) return;
|
|
125166
125167
|
const normalized = (next % resolvedItems.length + resolvedItems.length) % resolvedItems.length;
|
|
125167
125168
|
const nextItem = resolvedItems[normalized];
|
|
@@ -125212,10 +125213,10 @@ var init_renderNode = __esm({
|
|
|
125212
125213
|
seek(Number(detail.value ?? 0));
|
|
125213
125214
|
break;
|
|
125214
125215
|
case "next":
|
|
125215
|
-
|
|
125216
|
+
select2(index + 1);
|
|
125216
125217
|
break;
|
|
125217
125218
|
case "previous":
|
|
125218
|
-
|
|
125219
|
+
select2(index - 1);
|
|
125219
125220
|
break;
|
|
125220
125221
|
case "setRate": {
|
|
125221
125222
|
const next = Number(detail.value ?? 1);
|
|
@@ -125240,7 +125241,7 @@ var init_renderNode = __esm({
|
|
|
125240
125241
|
};
|
|
125241
125242
|
window.addEventListener("himalaya-media-command", listener);
|
|
125242
125243
|
return () => window.removeEventListener("himalaya-media-command", listener);
|
|
125243
|
-
}, [sessionId, index, play, pause, seek,
|
|
125244
|
+
}, [sessionId, index, play, pause, seek, select2, toggleFullscreen]);
|
|
125244
125245
|
React9.useEffect(() => {
|
|
125245
125246
|
const listener = () => {
|
|
125246
125247
|
const value = document.fullscreenElement === hostRef.current;
|
|
@@ -125296,10 +125297,10 @@ var init_renderNode = __esm({
|
|
|
125296
125297
|
seek(Number(raw.seconds ?? raw.positionSeconds ?? 0));
|
|
125297
125298
|
return;
|
|
125298
125299
|
case "media.next":
|
|
125299
|
-
|
|
125300
|
+
select2(index + 1);
|
|
125300
125301
|
return;
|
|
125301
125302
|
case "media.previous":
|
|
125302
|
-
|
|
125303
|
+
select2(index - 1);
|
|
125303
125304
|
return;
|
|
125304
125305
|
case "media.fullscreen":
|
|
125305
125306
|
void toggleFullscreen();
|
|
@@ -125342,14 +125343,14 @@ var init_renderNode = __esm({
|
|
|
125342
125343
|
return `${Math.floor(safe / 60)}:${String(Math.floor(safe % 60)).padStart(2, "0")}`;
|
|
125343
125344
|
};
|
|
125344
125345
|
const builtInControls = /* @__PURE__ */ jsxs7("div", { "data-media-controls": "builtIn", style: { display: "grid", gridTemplateColumns: "auto auto 1fr auto auto", gap: 10, alignItems: "center", width: "100%", padding: "10px 12px", boxSizing: "border-box", color: foreground, background: "linear-gradient(transparent,rgba(0,0,0,.82))" }, children: [
|
|
125345
|
-
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Previous", onClick: () =>
|
|
125346
|
+
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Previous", onClick: () => select2(index - 1), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u25C0\u25C0" }),
|
|
125346
125347
|
/* @__PURE__ */ jsx10("button", { "aria-label": status === "playing" ? "Pause" : "Play", onClick: () => status === "playing" ? pause() : void play(), style: { width: 38, height: 38, borderRadius: "50%", color: background, background: foreground, border: 0, fontSize: 18 }, children: status === "playing" ? "\u275A\u275A" : "\u25B6" }),
|
|
125347
125348
|
/* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 }, children: [
|
|
125348
125349
|
/* @__PURE__ */ jsx10("span", { style: { fontSize: pxToRem(11), whiteSpace: "nowrap" }, children: time(position) }),
|
|
125349
125350
|
/* @__PURE__ */ jsx10("input", { "aria-label": "Media position", type: "range", min: 0, max: Math.max(duration2, 1), step: 0.1, value: Math.min(position, Math.max(duration2, 1)), onChange: (event) => seek(Number(event.currentTarget.value)), style: { width: "100%", accentColor: accent } }),
|
|
125350
125351
|
/* @__PURE__ */ jsx10("span", { style: { fontSize: pxToRem(11), whiteSpace: "nowrap" }, children: time(duration2) })
|
|
125351
125352
|
] }),
|
|
125352
|
-
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Next", onClick: () =>
|
|
125353
|
+
items.length > 1 && /* @__PURE__ */ jsx10("button", { "aria-label": "Next", onClick: () => select2(index + 1), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u25B6\u25B6" }),
|
|
125353
125354
|
props.fullscreen !== "disabled" && /* @__PURE__ */ jsx10("button", { "aria-label": "Fullscreen", onClick: () => void toggleFullscreen(), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u26F6" })
|
|
125354
125355
|
] });
|
|
125355
125356
|
const customControls = chrome === "custom" ? slot("controls") : null;
|
|
@@ -125391,7 +125392,7 @@ var init_renderNode = __esm({
|
|
|
125391
125392
|
return;
|
|
125392
125393
|
}
|
|
125393
125394
|
if (props.loop === "all" || index + 1 < items.length) {
|
|
125394
|
-
|
|
125395
|
+
select2(index + 1);
|
|
125395
125396
|
return;
|
|
125396
125397
|
}
|
|
125397
125398
|
setStatus("ended");
|
|
@@ -127707,7 +127708,7 @@ var init_renderNode = __esm({
|
|
|
127707
127708
|
const currentRef = React9.useRef(current);
|
|
127708
127709
|
const itemsPath = props.itemsPath ?? props.items_path;
|
|
127709
127710
|
const boundRail = !!itemsPath && !!items[0] && !!ctx.provider;
|
|
127710
|
-
const
|
|
127711
|
+
const select2 = (index) => {
|
|
127711
127712
|
if (index === currentRef.current) return;
|
|
127712
127713
|
currentRef.current = index;
|
|
127713
127714
|
setCurrent(index);
|
|
@@ -127724,7 +127725,7 @@ var init_renderNode = __esm({
|
|
|
127724
127725
|
const timer = setInterval(() => {
|
|
127725
127726
|
const next = (currentRef.current + 1) % pages2.length;
|
|
127726
127727
|
if (rail.current) rail.current.scrollLeft = next * rail.current.clientWidth;
|
|
127727
|
-
|
|
127728
|
+
select2(next);
|
|
127728
127729
|
}, interval);
|
|
127729
127730
|
return () => clearInterval(timer);
|
|
127730
127731
|
}, [props.autoplayIntervalMs, props.__pager, boundRail, pages2.length, props.onChange, ctx]);
|
|
@@ -127741,10 +127742,10 @@ var init_renderNode = __esm({
|
|
|
127741
127742
|
event.preventDefault();
|
|
127742
127743
|
const index = event.key === "Home" ? 0 : event.key === "End" ? pages2.length - 1 : Math.max(0, Math.min(pages2.length - 1, currentRef.current + (event.key === "ArrowRight" ? 1 : -1)));
|
|
127743
127744
|
if (rail.current) rail.current.scrollLeft = index * rail.current.clientWidth;
|
|
127744
|
-
|
|
127745
|
+
select2(index);
|
|
127745
127746
|
},
|
|
127746
127747
|
onScroll: (event) => {
|
|
127747
|
-
if (!boundRail && event.currentTarget.clientWidth > 0)
|
|
127748
|
+
if (!boundRail && event.currentTarget.clientWidth > 0) select2(Math.max(0, Math.min(pages2.length - 1, Math.round(event.currentTarget.scrollLeft / event.currentTarget.clientWidth))));
|
|
127748
127749
|
},
|
|
127749
127750
|
style: { display: "flex", overflowX: "auto", scrollSnapType: boundRail ? void 0 : "x mandatory", gap: boundRail ? 12 : void 0, width: "100%" },
|
|
127750
127751
|
children: boundRail ? /* @__PURE__ */ jsx10(BoundList, { ctx, itemsPath, template: items[0], renderRow: (template, itemCtx) => /* @__PURE__ */ jsx10("div", { style: { flex: "0 0 auto" }, children: renderNode(template, itemCtx) }) }) : pages2.map((page, index) => /* @__PURE__ */ jsx10("div", { style: { minWidth: "100%", scrollSnapAlign: "start" }, children: renderNode(page, ctx) }, page?.id ?? index))
|
|
@@ -129145,13 +129146,13 @@ __export(render_descriptor_exports, {
|
|
|
129145
129146
|
stabilizePngPage: () => stabilizePngPage,
|
|
129146
129147
|
withRetry: () => withRetry2
|
|
129147
129148
|
});
|
|
129148
|
-
function a11ySemantics(type, props, modifiers, ancestorHidden,
|
|
129149
|
+
function a11ySemantics(type, props, modifiers, ancestorHidden, resolve65) {
|
|
129149
129150
|
if (!A11Y_MODIFIER_KEYS.some((k2) => modifiers[k2] !== void 0)) return void 0;
|
|
129150
129151
|
const literal = (v2) => typeof v2 === "string" && v2.trim() !== "" && !isDynamicValue(v2) ? v2 : void 0;
|
|
129151
129152
|
const spoken = (v2) => {
|
|
129152
129153
|
const lit = literal(v2);
|
|
129153
|
-
if (lit !== void 0 || !
|
|
129154
|
-
const r2 =
|
|
129154
|
+
if (lit !== void 0 || !resolve65 || typeof v2 !== "string" || !isDynamicValue(v2)) return lit;
|
|
129155
|
+
const r2 = resolve65(v2);
|
|
129155
129156
|
if (r2 === v2) return void 0;
|
|
129156
129157
|
return typeof r2 === "string" && r2.trim() !== "" ? r2 : typeof r2 === "number" ? String(r2) : void 0;
|
|
129157
129158
|
};
|
|
@@ -129165,7 +129166,7 @@ function a11ySemantics(type, props, modifiers, ancestorHidden, resolve63) {
|
|
|
129165
129166
|
if (name !== void 0 && exposure === "exposed") out2.name = name;
|
|
129166
129167
|
const hint = spoken(modifiers.accessibilityHint);
|
|
129167
129168
|
if (hint !== void 0) out2.hint = hint;
|
|
129168
|
-
const value = spoken(modifiers.accessibilityValue) ?? controlState(role, props,
|
|
129169
|
+
const value = spoken(modifiers.accessibilityValue) ?? controlState(role, props, resolve65);
|
|
129169
129170
|
if (value !== void 0) out2.value = value;
|
|
129170
129171
|
if (typeof modifiers.headingLevel === "number") out2.headingLevel = modifiers.headingLevel;
|
|
129171
129172
|
if (exposure !== "exposed") out2.exposure = exposure;
|
|
@@ -129186,13 +129187,13 @@ function a11ySemantics(type, props, modifiers, ancestorHidden, resolve63) {
|
|
|
129186
129187
|
}
|
|
129187
129188
|
return out2;
|
|
129188
129189
|
}
|
|
129189
|
-
function controlState(role, props,
|
|
129190
|
+
function controlState(role, props, resolve65) {
|
|
129190
129191
|
if (role !== "toggle" && role !== "checkbox" && role !== "radio") return void 0;
|
|
129191
129192
|
if (role === "checkbox" && props.indeterminate === true) return "mixed";
|
|
129192
129193
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && isDynamicValue(props.value) ? props.value : void 0;
|
|
129193
129194
|
let on4;
|
|
129194
129195
|
if (binding2 !== void 0) {
|
|
129195
|
-
const v2 =
|
|
129196
|
+
const v2 = resolve65 ? resolve65(binding2) : void 0;
|
|
129196
129197
|
if (v2 === true || v2 === 1 || v2 === "true" || v2 === "1") on4 = true;
|
|
129197
129198
|
else if (v2 === false || v2 === 0 || v2 === "false" || v2 === "0") on4 = false;
|
|
129198
129199
|
else return void 0;
|
|
@@ -129522,7 +129523,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
129522
129523
|
const browser = globalThis;
|
|
129523
129524
|
browser.document.documentElement.style.colorScheme = selected;
|
|
129524
129525
|
await browser.document.fonts?.ready;
|
|
129525
|
-
await new Promise((
|
|
129526
|
+
await new Promise((resolve65) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve65())));
|
|
129526
129527
|
}, scheme);
|
|
129527
129528
|
}
|
|
129528
129529
|
async function renderPngBatch(items) {
|
|
@@ -132143,7 +132144,7 @@ async function handleWebWix(req, res, state) {
|
|
|
132143
132144
|
}
|
|
132144
132145
|
if (match) {
|
|
132145
132146
|
const mocked = match.rule.response;
|
|
132146
|
-
if (mocked.delayMs) await new Promise((
|
|
132147
|
+
if (mocked.delayMs) await new Promise((resolve65) => setTimeout(resolve65, mocked.delayMs));
|
|
132147
132148
|
const payload = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
132148
132149
|
recordStream("mock", mocked.status, match.rule.id, mocked.headers);
|
|
132149
132150
|
res.statusCode = mocked.status;
|
|
@@ -132208,14 +132209,14 @@ async function handleWebWix(req, res, state) {
|
|
|
132208
132209
|
const chunk = await reader.read();
|
|
132209
132210
|
if (chunk.done) break;
|
|
132210
132211
|
if (chunk.value && !res.write(chunk.value)) {
|
|
132211
|
-
await new Promise((
|
|
132212
|
+
await new Promise((resolve65) => {
|
|
132212
132213
|
let settled = false;
|
|
132213
132214
|
const finish2 = () => {
|
|
132214
132215
|
if (settled) return;
|
|
132215
132216
|
settled = true;
|
|
132216
132217
|
res.off("drain", finish2);
|
|
132217
132218
|
res.off("close", finish2);
|
|
132218
|
-
|
|
132219
|
+
resolve65();
|
|
132219
132220
|
};
|
|
132220
132221
|
if (res.destroyed || !res.writable) finish2();
|
|
132221
132222
|
else {
|
|
@@ -132370,7 +132371,7 @@ async function handleWebWix(req, res, state) {
|
|
|
132370
132371
|
}
|
|
132371
132372
|
if (match) {
|
|
132372
132373
|
const mocked = match.rule.response;
|
|
132373
|
-
if (mocked.delayMs) await new Promise((
|
|
132374
|
+
if (mocked.delayMs) await new Promise((resolve65) => setTimeout(resolve65, mocked.delayMs));
|
|
132374
132375
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
132375
132376
|
record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
|
|
132376
132377
|
return reply(200, { status: mocked.status, body: responseBody ?? "" });
|
|
@@ -133409,8 +133410,8 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
133409
133410
|
}
|
|
133410
133411
|
async function serveStatic(req, res, root, prefix) {
|
|
133411
133412
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
133412
|
-
const
|
|
133413
|
-
const safe = normalize3(
|
|
133413
|
+
const relative17 = requested.replace(prefix, "").replace(/^\//, "");
|
|
133414
|
+
const safe = normalize3(relative17).replace(/^(\.\.[\/\\])+/, "");
|
|
133414
133415
|
const fullPath = resolve38(root, safe);
|
|
133415
133416
|
if (!fullPath.startsWith(root)) {
|
|
133416
133417
|
return send(res, 403, "forbidden");
|
|
@@ -134574,12 +134575,12 @@ var init_query = __esm({
|
|
|
134574
134575
|
});
|
|
134575
134576
|
|
|
134576
134577
|
// ../../core/dev-server/src/crawl-input.ts
|
|
134577
|
-
function resolved(v2,
|
|
134578
|
-
if (typeof v2 === "string") return v2.startsWith("$service:") ?
|
|
134578
|
+
function resolved(v2, resolve65) {
|
|
134579
|
+
if (typeof v2 === "string") return v2.startsWith("$service:") ? resolve65(v2) : v2;
|
|
134579
134580
|
if (Array.isArray(v2)) {
|
|
134580
134581
|
const out2 = v2.flatMap((el2) => {
|
|
134581
134582
|
if (typeof el2 !== "string" || !el2.startsWith("$service:")) return [el2];
|
|
134582
|
-
const r2 =
|
|
134583
|
+
const r2 = resolve65(el2);
|
|
134583
134584
|
return Array.isArray(r2) ? r2 : [r2];
|
|
134584
134585
|
});
|
|
134585
134586
|
return out2;
|
|
@@ -134593,9 +134594,9 @@ function hasRowBinding(props) {
|
|
|
134593
134594
|
return itemToken(v2) || Array.isArray(v2) && v2.some(itemToken);
|
|
134594
134595
|
});
|
|
134595
134596
|
}
|
|
134596
|
-
function declaredOptionIds(props,
|
|
134597
|
+
function declaredOptionIds(props, resolve65) {
|
|
134597
134598
|
const literal = props.options ?? props.tabs ?? props.chips;
|
|
134598
|
-
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath,
|
|
134599
|
+
const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve65) : void 0;
|
|
134599
134600
|
const raw = Array.isArray(bound) ? bound : literal;
|
|
134600
134601
|
if (!Array.isArray(raw)) return [];
|
|
134601
134602
|
const out2 = [];
|
|
@@ -134638,24 +134639,24 @@ function seedTokens(state, limit = 48) {
|
|
|
134638
134639
|
walk2(state, 0);
|
|
134639
134640
|
return out2;
|
|
134640
134641
|
}
|
|
134641
|
-
function synthesizeInput(control,
|
|
134642
|
+
function synthesizeInput(control, resolve65, tokens2) {
|
|
134642
134643
|
const id = `${control.type}.${control.callback}`;
|
|
134643
134644
|
const row = SYNTHESIZED_CONTROLS[id];
|
|
134644
134645
|
if (!row) return null;
|
|
134645
134646
|
const props = control.props;
|
|
134646
134647
|
if (hasRowBinding(props)) return null;
|
|
134647
134648
|
if (row.from === "declared-options") {
|
|
134648
|
-
const ids = declaredOptionIds(props,
|
|
134649
|
+
const ids = declaredOptionIds(props, resolve65);
|
|
134649
134650
|
if (!ids.length) return null;
|
|
134650
134651
|
if (row.encoding === "string-array") {
|
|
134651
|
-
const currentRaw2 = resolved(props.selectedIds,
|
|
134652
|
+
const currentRaw2 = resolved(props.selectedIds, resolve65);
|
|
134652
134653
|
const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x2) => typeof x2 === "string");
|
|
134653
134654
|
const pick4 = ids.find((o2) => !current3.includes(o2));
|
|
134654
134655
|
if (pick4 === void 0) return null;
|
|
134655
134656
|
const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
|
|
134656
134657
|
return { key: row.key, value, from: row.from, current: current3, control: id };
|
|
134657
134658
|
}
|
|
134658
|
-
const currentRaw = resolved(props.selectedId,
|
|
134659
|
+
const currentRaw = resolved(props.selectedId, resolve65);
|
|
134659
134660
|
const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
|
|
134660
134661
|
const pick3 = ids.find((o2) => o2 !== current2);
|
|
134661
134662
|
if (pick3 === void 0) return null;
|
|
@@ -134663,7 +134664,7 @@ function synthesizeInput(control, resolve63, tokens2) {
|
|
|
134663
134664
|
}
|
|
134664
134665
|
if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
|
|
134665
134666
|
const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
|
|
134666
|
-
const bound = binding2 === void 0 ? void 0 :
|
|
134667
|
+
const bound = binding2 === void 0 ? void 0 : resolve65(binding2);
|
|
134667
134668
|
const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
|
|
134668
134669
|
const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
|
|
134669
134670
|
const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
|
|
@@ -137283,6 +137284,7 @@ __export(build_exports2, {
|
|
|
137283
137284
|
bundleNameFromUrl: () => bundleNameFromUrl,
|
|
137284
137285
|
collectComponentTypes: () => collectComponentTypes,
|
|
137285
137286
|
contentReleaseId: () => contentReleaseId,
|
|
137287
|
+
countingHostAnswers: () => countingHostAnswers,
|
|
137286
137288
|
countingWixCall: () => countingWixCall,
|
|
137287
137289
|
declaresHostProvidedIdentity: () => declaresHostProvidedIdentity,
|
|
137288
137290
|
gitSha: () => gitSha,
|
|
@@ -137656,17 +137658,39 @@ async function buildRelease(app, dest, opts = {}) {
|
|
|
137656
137658
|
}
|
|
137657
137659
|
function countingWixCall(base) {
|
|
137658
137660
|
let returned = 0;
|
|
137661
|
+
const failed3 = [];
|
|
137659
137662
|
return {
|
|
137660
137663
|
call: async (method, path2, body) => {
|
|
137661
|
-
|
|
137664
|
+
let out2;
|
|
137665
|
+
try {
|
|
137666
|
+
out2 = await base(method, path2, body);
|
|
137667
|
+
} catch (e2) {
|
|
137668
|
+
failed3.push(`${String(method).toUpperCase()} ${String(path2).split("?")[0]}`);
|
|
137669
|
+
throw e2;
|
|
137670
|
+
}
|
|
137662
137671
|
returned += 1;
|
|
137663
137672
|
return out2;
|
|
137664
137673
|
},
|
|
137665
|
-
returned: () => returned
|
|
137674
|
+
returned: () => returned,
|
|
137675
|
+
failed: () => [...failed3]
|
|
137676
|
+
};
|
|
137677
|
+
}
|
|
137678
|
+
function countingHostAnswers(host) {
|
|
137679
|
+
let answered = 0;
|
|
137680
|
+
const { wixCall } = host;
|
|
137681
|
+
if (!wixCall) return { host, answered: () => answered };
|
|
137682
|
+
return {
|
|
137683
|
+
host: { ...host, wixCall: (method, path2, body) => {
|
|
137684
|
+
const answer = wixCall(method, path2, body);
|
|
137685
|
+
if (answer !== void 0) answered += 1;
|
|
137686
|
+
return answer;
|
|
137687
|
+
} },
|
|
137688
|
+
answered: () => answered
|
|
137666
137689
|
};
|
|
137667
137690
|
}
|
|
137668
137691
|
async function liveRenderServices(bundleJs, opts) {
|
|
137669
|
-
const
|
|
137692
|
+
const declared = declaredCapabilitiesOf(opts.descriptor);
|
|
137693
|
+
const bus = withHostAnswers(hostDispatch(opts.localDbSchema, declared), declared, opts.host);
|
|
137670
137694
|
const appear = rootOnAppear(opts.descriptor);
|
|
137671
137695
|
const fired = appear ? parseWorkerAction(appear.actionId) : null;
|
|
137672
137696
|
if (fired) {
|
|
@@ -137689,16 +137713,46 @@ async function liveRenderServices(bundleJs, opts) {
|
|
|
137689
137713
|
}
|
|
137690
137714
|
}
|
|
137691
137715
|
}
|
|
137716
|
+
if (opts.host) await settleUnawaitedWork();
|
|
137692
137717
|
return { services: snapshot(w2).state, calls: w2.calls, errors: w2.errors };
|
|
137693
137718
|
} finally {
|
|
137694
137719
|
w2.dispose();
|
|
137695
137720
|
}
|
|
137696
137721
|
}
|
|
137722
|
+
if (opts.host) return loadAndSettle(bundleJs, liveBootOptions(opts, bus));
|
|
137697
137723
|
return loadBundleServicesLive(bundleJs, liveBootOptions(opts, bus));
|
|
137698
137724
|
}
|
|
137725
|
+
async function settleUnawaitedWork() {
|
|
137726
|
+
for (let turn = 0; turn < SETTLE_TURNS; turn++) await new Promise((resolve65) => setTimeout(resolve65, 0));
|
|
137727
|
+
}
|
|
137728
|
+
async function loadAndSettle(bundleJs, options) {
|
|
137729
|
+
const w2 = await bootBundleWorker(bundleJs, options);
|
|
137730
|
+
try {
|
|
137731
|
+
await settleUnawaitedWork();
|
|
137732
|
+
return { services: snapshot(w2).state, calls: w2.calls, errors: w2.errors };
|
|
137733
|
+
} finally {
|
|
137734
|
+
w2.dispose();
|
|
137735
|
+
}
|
|
137736
|
+
}
|
|
137737
|
+
function withHostAnswers(bus, declared, host) {
|
|
137738
|
+
if (!host) return bus;
|
|
137739
|
+
return (action, params) => {
|
|
137740
|
+
const capability = /^capability\.([^.]+)\./.exec(action)?.[1];
|
|
137741
|
+
const answer = capability === void 0 || declared.has(capability) ? host.dispatch(action, params) : void 0;
|
|
137742
|
+
return answer === void 0 ? bus(action, params) : Promise.resolve(answer);
|
|
137743
|
+
};
|
|
137744
|
+
}
|
|
137745
|
+
function memoryStorage() {
|
|
137746
|
+
const items = /* @__PURE__ */ new Map();
|
|
137747
|
+
return { getItem: (key2) => items.get(key2) ?? null, setItem: (key2, value) => void items.set(key2, value) };
|
|
137748
|
+
}
|
|
137699
137749
|
function liveBootOptions(opts, bus) {
|
|
137750
|
+
const { host } = opts;
|
|
137751
|
+
const wixCall = host?.wixCall ? async (method, path2, body) => host.wixCall(method, path2, body) ?? opts.wixCall(method, path2, body) : opts.wixCall;
|
|
137700
137752
|
return {
|
|
137701
|
-
wixCall
|
|
137753
|
+
wixCall,
|
|
137754
|
+
...host ? { storage: memoryStorage() } : {},
|
|
137755
|
+
...host?.wixApiSession ? { wixApiSession: host.wixApiSession } : {},
|
|
137702
137756
|
input: opts.input,
|
|
137703
137757
|
budgetMs: opts.budgetMs,
|
|
137704
137758
|
// The capability arms, but NOT the signed-in-member arm. `hostDispatch` answers
|
|
@@ -137816,6 +137870,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137816
137870
|
let base2;
|
|
137817
137871
|
let liveCalls;
|
|
137818
137872
|
let liveReturned;
|
|
137873
|
+
let liveFailed;
|
|
137819
137874
|
let liveErrors;
|
|
137820
137875
|
let mockCalls;
|
|
137821
137876
|
let mockBootFailed;
|
|
@@ -137826,16 +137881,20 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137826
137881
|
base2 = null;
|
|
137827
137882
|
} else {
|
|
137828
137883
|
const counting = countingWixCall(await ensureLiveWixCall());
|
|
137884
|
+
const host = collect2.render.host ? countingHostAnswers(collect2.render.host) : void 0;
|
|
137829
137885
|
const live3 = await liveRenderServices(bundleJs, {
|
|
137830
137886
|
wixCall: counting.call,
|
|
137831
137887
|
input,
|
|
137832
137888
|
budgetMs: collect2.render.loadBudgetMs ?? LIVE_LOAD_BUDGET_MS,
|
|
137833
137889
|
localDbSchema: appLocalDbSchema,
|
|
137834
|
-
descriptor
|
|
137890
|
+
descriptor,
|
|
137891
|
+
...host ? { host: host.host } : {}
|
|
137835
137892
|
});
|
|
137836
137893
|
base2 = live3.services;
|
|
137837
137894
|
liveCalls = [...live3.calls];
|
|
137838
137895
|
liveReturned = counting.returned();
|
|
137896
|
+
if (host) liveReturned += host.answered();
|
|
137897
|
+
liveFailed = counting.failed();
|
|
137839
137898
|
liveErrors = live3.errors;
|
|
137840
137899
|
}
|
|
137841
137900
|
} else if (collect2?.render?.mocks && collect2.render.hydrate !== false && bundleName && readBundle(bundleName)) {
|
|
@@ -137884,7 +137943,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137884
137943
|
services[svc] = { ...services[svc] ?? {}, ...st2 };
|
|
137885
137944
|
}
|
|
137886
137945
|
}
|
|
137887
|
-
return { services, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved: mockUnserved ?? [] } : {}, ...mockBootFailed ? { mockBootFailed } : {} };
|
|
137946
|
+
return { services, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed?.length ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved: mockUnserved ?? [] } : {}, ...mockBootFailed ? { mockBootFailed } : {} };
|
|
137888
137947
|
};
|
|
137889
137948
|
checkRegistry(preloaded.module.actions);
|
|
137890
137949
|
const contentManifestPath2 = join47(preloaded.dir, "himalaya.content.json");
|
|
@@ -138179,9 +138238,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
138179
138238
|
lint.push({ screenId, ok: report3.ok, issues: report3.issues });
|
|
138180
138239
|
}
|
|
138181
138240
|
if (collect2?.render && (!collect2.render.screenId || collect2.render.screenId === screenId)) {
|
|
138182
|
-
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed } = await renderServicesFor(bundleName, descriptor, screenId);
|
|
138241
|
+
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, screenId);
|
|
138183
138242
|
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
138184
|
-
renders.push({ screenId, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138243
|
+
renders.push({ screenId, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138185
138244
|
}
|
|
138186
138245
|
}
|
|
138187
138246
|
const wantedRender = collect2?.render?.screenId;
|
|
@@ -138207,9 +138266,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
138207
138266
|
});
|
|
138208
138267
|
lint.push({ screenId: wantedRender, ok: report3.ok, issues: report3.issues });
|
|
138209
138268
|
}
|
|
138210
|
-
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
|
|
138269
|
+
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
|
|
138211
138270
|
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
138212
|
-
renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138271
|
+
renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
138213
138272
|
}
|
|
138214
138273
|
}
|
|
138215
138274
|
for (const t2 of preloaded.module.screens.templated ?? []) {
|
|
@@ -138580,7 +138639,7 @@ function declaresHostProvidedIdentity(auth) {
|
|
|
138580
138639
|
const config = auth?.config;
|
|
138581
138640
|
return typeof config === "object" && config !== null && config.hostProvided === true;
|
|
138582
138641
|
}
|
|
138583
|
-
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL;
|
|
138642
|
+
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL, SETTLE_TURNS;
|
|
138584
138643
|
var init_build3 = __esm({
|
|
138585
138644
|
"../release-build/build.ts"() {
|
|
138586
138645
|
init_site_view_metadata();
|
|
@@ -138622,6 +138681,7 @@ var init_build3 = __esm({
|
|
|
138622
138681
|
requireFromHere = createRequire2(import.meta.url);
|
|
138623
138682
|
SOURCEMAP_ON_DEMAND_PATH = join47(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
|
|
138624
138683
|
BAKED_SERVER_BASE_URL = "http://baked.himalaya.invalid";
|
|
138684
|
+
SETTLE_TURNS = 20;
|
|
138625
138685
|
}
|
|
138626
138686
|
});
|
|
138627
138687
|
|
|
@@ -152744,7 +152804,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
152744
152804
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
152745
152805
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
152746
152806
|
const hostname3 = url.hostname.replace(/^\[|\]$/g, "");
|
|
152747
|
-
return await new Promise((
|
|
152807
|
+
return await new Promise((resolve65, reject) => {
|
|
152748
152808
|
let settled = false;
|
|
152749
152809
|
const finish2 = (fn2) => {
|
|
152750
152810
|
if (settled) return;
|
|
@@ -152781,7 +152841,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
152781
152841
|
}
|
|
152782
152842
|
const responseHeaders = new Headers();
|
|
152783
152843
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
152784
|
-
|
|
152844
|
+
resolve65(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
152785
152845
|
}));
|
|
152786
152846
|
});
|
|
152787
152847
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -153081,7 +153141,7 @@ function createLocalTestSandbox() {
|
|
|
153081
153141
|
}
|
|
153082
153142
|
})();
|
|
153083
153143
|
`;
|
|
153084
|
-
return await new Promise((
|
|
153144
|
+
return await new Promise((resolve65, reject) => {
|
|
153085
153145
|
const { port1, port2 } = new MessageChannel();
|
|
153086
153146
|
const serializableContext = {
|
|
153087
153147
|
auth: context.auth,
|
|
@@ -153157,7 +153217,7 @@ function createLocalTestSandbox() {
|
|
|
153157
153217
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
153158
153218
|
return;
|
|
153159
153219
|
}
|
|
153160
|
-
if (message.ok) finish2(() =>
|
|
153220
|
+
if (message.ok) finish2(() => resolve65({ value: message.value, durationMs: Date.now() - started }));
|
|
153161
153221
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
153162
153222
|
});
|
|
153163
153223
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -155056,12 +155116,12 @@ function createLoginSession(deps) {
|
|
|
155056
155116
|
current = pending;
|
|
155057
155117
|
const out2 = [];
|
|
155058
155118
|
const err = [];
|
|
155059
|
-
return new Promise((
|
|
155119
|
+
return new Promise((resolve65) => {
|
|
155060
155120
|
let answered = false;
|
|
155061
155121
|
const answer = () => {
|
|
155062
155122
|
if (answered) return;
|
|
155063
155123
|
answered = true;
|
|
155064
|
-
|
|
155124
|
+
resolve65(current);
|
|
155065
155125
|
};
|
|
155066
155126
|
let child;
|
|
155067
155127
|
try {
|
|
@@ -155184,9 +155244,9 @@ async function startMcpServer(opts) {
|
|
|
155184
155244
|
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login }),
|
|
155185
155245
|
...opts.workspace ? { workspaceBoundary: opts.workspace } : {}
|
|
155186
155246
|
};
|
|
155187
|
-
const closed = new Promise((
|
|
155188
|
-
stdin.once("end",
|
|
155189
|
-
stdin.once("close",
|
|
155247
|
+
const closed = new Promise((resolve65) => {
|
|
155248
|
+
stdin.once("end", resolve65);
|
|
155249
|
+
stdin.once("close", resolve65);
|
|
155190
155250
|
});
|
|
155191
155251
|
const handle = serveStdio(
|
|
155192
155252
|
() => {
|
|
@@ -155566,10 +155626,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
155566
155626
|
for (const source of Object.values(files)) visit(source);
|
|
155567
155627
|
return { modules, unsupported };
|
|
155568
155628
|
}
|
|
155569
|
-
function sdkSubpathReader(
|
|
155629
|
+
function sdkSubpathReader(resolve65) {
|
|
155570
155630
|
return (sub) => {
|
|
155571
155631
|
try {
|
|
155572
|
-
return readFileSync79(
|
|
155632
|
+
return readFileSync79(resolve65(`@wix/himalaya/${sub}`), "utf8");
|
|
155573
155633
|
} catch {
|
|
155574
155634
|
return null;
|
|
155575
155635
|
}
|
|
@@ -155647,7 +155707,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
155647
155707
|
const token = mintToken2(payload);
|
|
155648
155708
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
155649
155709
|
if (unusable) throw new Error(unusable);
|
|
155650
|
-
return await new Promise((
|
|
155710
|
+
return await new Promise((resolve65, reject) => {
|
|
155651
155711
|
let settled = false;
|
|
155652
155712
|
let url = "";
|
|
155653
155713
|
const server = createServer5();
|
|
@@ -155699,7 +155759,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
155699
155759
|
}
|
|
155700
155760
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
155701
155761
|
const report3 = body.result;
|
|
155702
|
-
finish2(() =>
|
|
155762
|
+
finish2(() => resolve65({ report: report3, url }));
|
|
155703
155763
|
})();
|
|
155704
155764
|
});
|
|
155705
155765
|
server.on("error", (e2) => finish2(() => reject(e2)));
|
|
@@ -158605,6 +158665,15 @@ function retryAfterMs(header, nowMs) {
|
|
|
158605
158665
|
const ms2 = /^\d+$/.test(trimmed) ? Number(trimmed) * 1e3 : Date.parse(trimmed) - nowMs;
|
|
158606
158666
|
return Number.isFinite(ms2) ? Math.min(Math.max(ms2, 0), MAX_RETRY_WAIT_MS) : void 0;
|
|
158607
158667
|
}
|
|
158668
|
+
function assetUploadUrl(operation, size) {
|
|
158669
|
+
const url = new URL(operation.url);
|
|
158670
|
+
const appleHost = url.hostname === "apple.com" || url.hostname.endsWith(".apple.com");
|
|
158671
|
+
const inFile = Number.isInteger(operation.offset) && Number.isInteger(operation.length) && operation.offset >= 0 && operation.length > 0 && operation.offset + operation.length <= size;
|
|
158672
|
+
if (url.protocol !== "https:" || !appleHost || url.username || url.password || operation.method !== "PUT" || !inFile) {
|
|
158673
|
+
throw new AscError("refused", `refusing an asset upload operation Apple would not issue (${operation.method} ${url.origin})`);
|
|
158674
|
+
}
|
|
158675
|
+
return url;
|
|
158676
|
+
}
|
|
158608
158677
|
function backoffMs(attempt) {
|
|
158609
158678
|
return Math.min(BASE_BACKOFF_MS * 2 ** (attempt - 1), MAX_RETRY_WAIT_MS);
|
|
158610
158679
|
}
|
|
@@ -158667,7 +158736,7 @@ var init_iap_client = __esm({
|
|
|
158667
158736
|
this.options = options;
|
|
158668
158737
|
this.fetchImpl = options.fetchImpl ?? ((input, init) => globalThis.fetch(input, init));
|
|
158669
158738
|
this.now = options.now ?? Date.now;
|
|
158670
|
-
this.sleep = options.sleep ?? ((ms2) => new Promise((
|
|
158739
|
+
this.sleep = options.sleep ?? ((ms2) => new Promise((resolve65) => setTimeout(resolve65, ms2)));
|
|
158671
158740
|
}
|
|
158672
158741
|
fetchImpl;
|
|
158673
158742
|
now;
|
|
@@ -158694,6 +158763,32 @@ var init_iap_client = __esm({
|
|
|
158694
158763
|
async patch(path2, body) {
|
|
158695
158764
|
return this.write("PATCH", this.resolve(path2), body);
|
|
158696
158765
|
}
|
|
158766
|
+
async delete(path2) {
|
|
158767
|
+
await this.write("DELETE", this.resolve(path2));
|
|
158768
|
+
}
|
|
158769
|
+
async uploadParts(operations, bytes2) {
|
|
158770
|
+
for (const [i2, operation] of operations.entries()) {
|
|
158771
|
+
const where = `upload of part ${i2 + 1} of ${operations.length} to Apple's asset storage`;
|
|
158772
|
+
const response = await this.putPart(operation, bytes2, where);
|
|
158773
|
+
if (response.status >= 500) throw new AscError("server", `${where} \u2192 ${response.status}`, response.status);
|
|
158774
|
+
if (!response.ok) throw new AscError("invalid", `${where} \u2192 ${response.status} \u2014 the reserved upload was refused; make a new plan, which reserves a fresh one`, response.status);
|
|
158775
|
+
}
|
|
158776
|
+
}
|
|
158777
|
+
async putPart(operation, bytes2, where) {
|
|
158778
|
+
const url = assetUploadUrl(operation, bytes2.length);
|
|
158779
|
+
const headers2 = Object.fromEntries(operation.requestHeaders.filter((h2) => h2.name.toLowerCase() !== "authorization").map((h2) => [h2.name, h2.value]));
|
|
158780
|
+
try {
|
|
158781
|
+
return await this.fetchImpl(url.href, {
|
|
158782
|
+
method: "PUT",
|
|
158783
|
+
headers: headers2,
|
|
158784
|
+
body: bytes2.slice(operation.offset, operation.offset + operation.length),
|
|
158785
|
+
redirect: "error",
|
|
158786
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
158787
|
+
});
|
|
158788
|
+
} catch (e2) {
|
|
158789
|
+
throw new AscError("network", `${where} failed before a response: ${this.scrub(e2.message)}`);
|
|
158790
|
+
}
|
|
158791
|
+
}
|
|
158697
158792
|
resolve(pathOrUrl) {
|
|
158698
158793
|
const url = new URL(pathOrUrl, ASC_ORIGIN);
|
|
158699
158794
|
const allowed2 = url.origin === ASC_ORIGIN && !url.username && !url.password && /^\/v[12]\//.test(url.pathname);
|
|
@@ -158818,6 +158913,20 @@ function toVersion(resource) {
|
|
|
158818
158913
|
function toLocalization(resource) {
|
|
158819
158914
|
return { id: resource.id, locale: attr(resource, "locale"), name: attr(resource, "name"), description: attr(resource, "description") };
|
|
158820
158915
|
}
|
|
158916
|
+
function toReviewScreenshot(resource) {
|
|
158917
|
+
const attributes = resource.attributes ?? {};
|
|
158918
|
+
const delivery = attributes.assetDeliveryState ?? {};
|
|
158919
|
+
const errors = (delivery.errors ?? []).map((e2) => [e2.code, e2.description].filter((part2) => typeof part2 === "string").join(": "));
|
|
158920
|
+
const checksum = attr(resource, "sourceFileChecksum");
|
|
158921
|
+
return {
|
|
158922
|
+
id: resource.id,
|
|
158923
|
+
fileName: attr(resource, "fileName"),
|
|
158924
|
+
fileSize: typeof attributes.fileSize === "number" ? attributes.fileSize : 0,
|
|
158925
|
+
...checksum ? { checksum } : {},
|
|
158926
|
+
state: typeof delivery.state === "string" ? delivery.state : "",
|
|
158927
|
+
errors
|
|
158928
|
+
};
|
|
158929
|
+
}
|
|
158821
158930
|
function toManualPrice(price, included) {
|
|
158822
158931
|
const point = included.find((r2) => r2.type === "inAppPurchasePricePoints" && r2.id === relatedId(price, "inAppPurchasePricePoint"));
|
|
158823
158932
|
const date = (name) => typeof price.attributes?.[name] === "string" ? price.attributes[name] : null;
|
|
@@ -158839,7 +158948,7 @@ async function readOptional(read) {
|
|
|
158839
158948
|
function createIapApi(client2) {
|
|
158840
158949
|
return new AppStoreConnectIapApi(client2);
|
|
158841
158950
|
}
|
|
158842
|
-
var APPLE_PRODUCT_TYPES, PRICE_POINT_PAGE, INITIAL_PRICE_REF, PAGE, linkage, related, enc, AppStoreConnectIapApi;
|
|
158951
|
+
var APPLE_PRODUCT_TYPES, PRICE_POINT_PAGE, INITIAL_PRICE_REF, PAGE, linkage, related, enc, AppStoreConnectIapApi, SCREENSHOTS, SCREENSHOT_TYPE, ReviewScreenshotEndpoints;
|
|
158843
158952
|
var init_iap_api = __esm({
|
|
158844
158953
|
"../store-release/iap-api.ts"() {
|
|
158845
158954
|
init_iap_client();
|
|
@@ -158853,7 +158962,9 @@ var init_iap_api = __esm({
|
|
|
158853
158962
|
AppStoreConnectIapApi = class {
|
|
158854
158963
|
constructor(client2) {
|
|
158855
158964
|
this.client = client2;
|
|
158965
|
+
this.screenshots = new ReviewScreenshotEndpoints(client2);
|
|
158856
158966
|
}
|
|
158967
|
+
screenshots;
|
|
158857
158968
|
async readApp(appId2) {
|
|
158858
158969
|
const app = requireSingle(await this.client.get(`/v1/apps/${enc(appId2)}?fields[apps]=bundleId`), "app");
|
|
158859
158970
|
return { id: app.id, bundleId: attr(app, "bundleId") };
|
|
@@ -158973,6 +159084,50 @@ var init_iap_api = __esm({
|
|
|
158973
159084
|
}
|
|
158974
159085
|
});
|
|
158975
159086
|
}
|
|
159087
|
+
async readReviewScreenshot(resourceId) {
|
|
159088
|
+
return this.screenshots.read(resourceId);
|
|
159089
|
+
}
|
|
159090
|
+
async reserveReviewScreenshot(resourceId, file2) {
|
|
159091
|
+
return this.screenshots.reserve(resourceId, file2);
|
|
159092
|
+
}
|
|
159093
|
+
async uploadReviewScreenshotParts(reservation, bytes2) {
|
|
159094
|
+
await this.client.uploadParts(reservation.uploadOperations, bytes2);
|
|
159095
|
+
}
|
|
159096
|
+
async commitReviewScreenshot(screenshotId, checksum) {
|
|
159097
|
+
return this.screenshots.commit(screenshotId, checksum);
|
|
159098
|
+
}
|
|
159099
|
+
async deleteReviewScreenshot(screenshotId) {
|
|
159100
|
+
await this.screenshots.delete(screenshotId);
|
|
159101
|
+
}
|
|
159102
|
+
};
|
|
159103
|
+
SCREENSHOTS = "/v1/inAppPurchaseAppStoreReviewScreenshots";
|
|
159104
|
+
SCREENSHOT_TYPE = "inAppPurchaseAppStoreReviewScreenshots";
|
|
159105
|
+
ReviewScreenshotEndpoints = class {
|
|
159106
|
+
constructor(client2) {
|
|
159107
|
+
this.client = client2;
|
|
159108
|
+
}
|
|
159109
|
+
async read(resourceId) {
|
|
159110
|
+
const screenshot = await readOptional(() => this.client.get(`/v2/inAppPurchases/${enc(resourceId)}/appStoreReviewScreenshot`));
|
|
159111
|
+
return screenshot && toReviewScreenshot(screenshot);
|
|
159112
|
+
}
|
|
159113
|
+
async reserve(resourceId, file2) {
|
|
159114
|
+
const doc = await this.client.post(SCREENSHOTS, {
|
|
159115
|
+
data: { type: SCREENSHOT_TYPE, attributes: file2, relationships: { inAppPurchaseV2: related("inAppPurchases", resourceId) } }
|
|
159116
|
+
});
|
|
159117
|
+
const reservation = requireSingle(doc, "review screenshot reservation");
|
|
159118
|
+
const operations = reservation.attributes?.uploadOperations;
|
|
159119
|
+
if (!Array.isArray(operations) || !operations.length) throw new AscError("server", "App Store Connect reserved the review screenshot without upload operations");
|
|
159120
|
+
return { id: reservation.id, uploadOperations: operations };
|
|
159121
|
+
}
|
|
159122
|
+
async commit(screenshotId, checksum) {
|
|
159123
|
+
const doc = await this.client.patch(`${SCREENSHOTS}/${enc(screenshotId)}`, {
|
|
159124
|
+
data: { type: SCREENSHOT_TYPE, id: screenshotId, attributes: { uploaded: true, sourceFileChecksum: checksum } }
|
|
159125
|
+
});
|
|
159126
|
+
return toReviewScreenshot(requireSingle(doc, "review screenshot"));
|
|
159127
|
+
}
|
|
159128
|
+
async delete(screenshotId) {
|
|
159129
|
+
await this.client.delete(`${SCREENSHOTS}/${enc(screenshotId)}`);
|
|
159130
|
+
}
|
|
158976
159131
|
};
|
|
158977
159132
|
}
|
|
158978
159133
|
});
|
|
@@ -159057,6 +159212,7 @@ function readItem(reader, value, index) {
|
|
|
159057
159212
|
const price = readPrice(reader, obj3, path2);
|
|
159058
159213
|
const reviewNote = reader.optionalText(obj3, "reviewNote", path2);
|
|
159059
159214
|
if (reviewNote) reader.maxLength(reviewNote, `${path2}.reviewNote`, APPLE_LIMITS.reviewNote);
|
|
159215
|
+
const reviewScreenshot = obj3.reviewScreenshot === void 0 ? void 0 : reader.text(obj3, "reviewScreenshot", path2, SCREENSHOT_PATH);
|
|
159060
159216
|
return {
|
|
159061
159217
|
...readSubject(reader, obj3, path2, type),
|
|
159062
159218
|
classification: reader.literal(obj3, "classification", path2, "digital", "physical goods and unclassified products are never registered as in-app purchases"),
|
|
@@ -159065,6 +159221,7 @@ function readItem(reader, value, index) {
|
|
|
159065
159221
|
type,
|
|
159066
159222
|
referenceName: limitedText(reader, obj3, "referenceName", path2, APPLE_LIMITS.referenceName),
|
|
159067
159223
|
...reviewNote === void 0 ? {} : { reviewNote },
|
|
159224
|
+
...reviewScreenshot === void 0 ? {} : { reviewScreenshot },
|
|
159068
159225
|
localizations: readLocalizations(reader, obj3, path2),
|
|
159069
159226
|
price,
|
|
159070
159227
|
territories: readTerritories(reader, obj3, path2, price.baseTerritory)
|
|
@@ -159127,7 +159284,7 @@ function sha256Digest(value) {
|
|
|
159127
159284
|
function manifestDigest(manifest) {
|
|
159128
159285
|
return sha256Digest(manifest);
|
|
159129
159286
|
}
|
|
159130
|
-
var IapManifestError, APPLE_APP_ID, TEAM_ID, BUNDLE_ID, PRODUCT_ID, TERRITORY, CURRENCY2, AMOUNT, LOCALE, CREDENTIAL_SHAPES, MANIFEST_KEYS, TARGET_KEYS, ITEM_KEYS, WIX_KEYS, UNLOCK_KEYS, LOCALIZATION_KEYS, PRICE_KEYS, PRODUCT_TYPES, PRICE_RULES, APPLE_LIMITS, childPath, ManifestReader;
|
|
159287
|
+
var IapManifestError, APPLE_APP_ID, TEAM_ID, BUNDLE_ID, PRODUCT_ID, TERRITORY, CURRENCY2, AMOUNT, LOCALE, SCREENSHOT_PATH, CREDENTIAL_SHAPES, MANIFEST_KEYS, TARGET_KEYS, ITEM_KEYS, WIX_KEYS, UNLOCK_KEYS, LOCALIZATION_KEYS, PRICE_KEYS, PRODUCT_TYPES, PRICE_RULES, APPLE_LIMITS, childPath, ManifestReader;
|
|
159131
159288
|
var init_iap_manifest = __esm({
|
|
159132
159289
|
"../store-release/iap-manifest.ts"() {
|
|
159133
159290
|
IapManifestError = class extends Error {
|
|
@@ -159146,6 +159303,7 @@ var init_iap_manifest = __esm({
|
|
|
159146
159303
|
CURRENCY2 = { pattern: /^[A-Z]{3}$/, hint: "an ISO 4217 currency code such as USD" };
|
|
159147
159304
|
AMOUNT = { pattern: /^\d+(\.\d+)?$/, hint: 'an exact decimal string such as "0.99"' };
|
|
159148
159305
|
LOCALE = { pattern: /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/, hint: "a locale such as en-US" };
|
|
159306
|
+
SCREENSHOT_PATH = { pattern: /\.(png|jpe?g)$/i, hint: "a path to a .png, .jpg or .jpeg file" };
|
|
159149
159307
|
CREDENTIAL_SHAPES = [
|
|
159150
159308
|
/-----BEGIN [A-Z ]*PRIVATE KEY-----/,
|
|
159151
159309
|
/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/,
|
|
@@ -159162,6 +159320,7 @@ var init_iap_manifest = __esm({
|
|
|
159162
159320
|
"type",
|
|
159163
159321
|
"referenceName",
|
|
159164
159322
|
"reviewNote",
|
|
159323
|
+
"reviewScreenshot",
|
|
159165
159324
|
"localizations",
|
|
159166
159325
|
"price",
|
|
159167
159326
|
"territories"
|
|
@@ -159311,8 +159470,16 @@ var init_iap_pricing = __esm({
|
|
|
159311
159470
|
});
|
|
159312
159471
|
|
|
159313
159472
|
// ../store-release/iap-result.ts
|
|
159314
|
-
|
|
159473
|
+
import { basename as basename18 } from "node:path";
|
|
159474
|
+
function missingMetadataRequirement(screenshotState, itemNamesFile) {
|
|
159475
|
+
if (screenshotState === void 0) return MISSING_SCREENSHOT;
|
|
159476
|
+
const leftover = LEFTOVER_STATES[screenshotState];
|
|
159477
|
+
if (!leftover) return MISSING_AFTER_SCREENSHOT;
|
|
159478
|
+
return leftover.problem + (itemNamesFile ? leftover.fix : ADD_FILE_FIRST);
|
|
159479
|
+
}
|
|
159480
|
+
function remainingRequirements(observed, itemNamesFile = true) {
|
|
159315
159481
|
if (!observed) return ["the product does not exist in App Store Connect yet"];
|
|
159482
|
+
if (observed.state === "MISSING_METADATA") return [observed.reviewScreenshotRead ? missingMetadataRequirement(observed.reviewScreenshot?.state, itemNamesFile) : MISSING_UNREAD];
|
|
159316
159483
|
const requirement = STATE_REQUIREMENTS[observed.state];
|
|
159317
159484
|
return requirement ? [requirement] : [];
|
|
159318
159485
|
}
|
|
@@ -159333,6 +159500,10 @@ function mappingFor(target, item, appleResourceId) {
|
|
|
159333
159500
|
function metadataVersion(observed) {
|
|
159334
159501
|
return observed?.versions.find((v2) => v2.id === observed.metadataVersionId);
|
|
159335
159502
|
}
|
|
159503
|
+
function screenshotReport(path2, observed) {
|
|
159504
|
+
const held = observed?.reviewScreenshot;
|
|
159505
|
+
return { requested: basename18(path2), ...held ? { observed: { fileName: held.fileName, state: held.state } } : {} };
|
|
159506
|
+
}
|
|
159336
159507
|
function itemResult(input) {
|
|
159337
159508
|
const { target, item, observed } = input;
|
|
159338
159509
|
const version4 = metadataVersion(observed);
|
|
@@ -159351,7 +159522,8 @@ function itemResult(input) {
|
|
|
159351
159522
|
...observed?.availability ? { observed: observed.availability.territories, availableInNewTerritories: observed.availability.availableInNewTerritories } : {}
|
|
159352
159523
|
},
|
|
159353
159524
|
localizations: { requested: item.localizations.map((l2) => l2.locale), observed: observed?.localizations.map((l2) => l2.locale) ?? [] },
|
|
159354
|
-
|
|
159525
|
+
...item.reviewScreenshot ? { reviewScreenshot: screenshotReport(item.reviewScreenshot, observed) } : {},
|
|
159526
|
+
remainingRequirements: [...input.requirements ?? [], ...remainingRequirements(observed, item.reviewScreenshot !== void 0)],
|
|
159355
159527
|
lastReadAt: input.readAt.toISOString()
|
|
159356
159528
|
}
|
|
159357
159529
|
};
|
|
@@ -159368,12 +159540,11 @@ function iapResult(args) {
|
|
|
159368
159540
|
items: args.items
|
|
159369
159541
|
};
|
|
159370
159542
|
}
|
|
159371
|
-
var COMPLETE_OUTCOMES, STATE_REQUIREMENTS;
|
|
159543
|
+
var COMPLETE_OUTCOMES, STATE_REQUIREMENTS, MISSING_SCREENSHOT, MISSING_UNREAD, REFUSED_SCREENSHOT, MISSING_AFTER_SCREENSHOT, UNFINISHED_SCREENSHOT, LEFTOVER_STATES, ADD_FILE_FIRST;
|
|
159372
159544
|
var init_iap_result = __esm({
|
|
159373
159545
|
"../store-release/iap-result.ts"() {
|
|
159374
159546
|
COMPLETE_OUTCOMES = /* @__PURE__ */ new Set(["created", "updated", "reused"]);
|
|
159375
159547
|
STATE_REQUIREMENTS = {
|
|
159376
|
-
MISSING_METADATA: "App Store Connect reports MISSING_METADATA \u2014 usually the App Review screenshot, which this command does not upload",
|
|
159377
159548
|
READY_TO_SUBMIT: "submit the product for App Review with an app version \u2014 this command never submits",
|
|
159378
159549
|
DEVELOPER_ACTION_NEEDED: "resolve the App Review feedback in App Store Connect",
|
|
159379
159550
|
REJECTED: "resolve the App Review rejection in App Store Connect",
|
|
@@ -159385,6 +159556,16 @@ var init_iap_result = __esm({
|
|
|
159385
159556
|
WAITING_FOR_UPLOAD: "waiting for its hosted content to be uploaded",
|
|
159386
159557
|
PROCESSING_CONTENT: "Apple is still processing its hosted content"
|
|
159387
159558
|
};
|
|
159559
|
+
MISSING_SCREENSHOT = 'App Store Connect reports MISSING_METADATA and the product has no App Review screenshot \u2014 add "reviewScreenshot" to the item and apply, or upload one in App Store Connect';
|
|
159560
|
+
MISSING_UNREAD = 'App Store Connect reports MISSING_METADATA \u2014 check the product in App Store Connect; when it lacks the App Review screenshot, add "reviewScreenshot" to the item and apply';
|
|
159561
|
+
REFUSED_SCREENSHOT = "App Store Connect reports MISSING_METADATA \u2014 Apple could not process the review screenshot";
|
|
159562
|
+
MISSING_AFTER_SCREENSHOT = "App Store Connect still reports MISSING_METADATA \u2014 Apple may still be processing the review screenshot; if it stays, check the product in App Store Connect";
|
|
159563
|
+
UNFINISHED_SCREENSHOT = "App Store Connect reports MISSING_METADATA \u2014 the review screenshot upload is unfinished";
|
|
159564
|
+
LEFTOVER_STATES = {
|
|
159565
|
+
FAILED: { problem: REFUSED_SCREENSHOT, fix: "; replace the file and apply again" },
|
|
159566
|
+
AWAITING_UPLOAD: { problem: UNFINISHED_SCREENSHOT, fix: "; rerun plan and apply to replace it" }
|
|
159567
|
+
};
|
|
159568
|
+
ADD_FILE_FIRST = ' \u2014 add "reviewScreenshot" to the item first, then plan and apply';
|
|
159388
159569
|
}
|
|
159389
159570
|
});
|
|
159390
159571
|
|
|
@@ -159428,6 +159609,99 @@ var init_iap_price_status = __esm({
|
|
|
159428
159609
|
}
|
|
159429
159610
|
});
|
|
159430
159611
|
|
|
159612
|
+
// ../store-release/screenshot-display-types.ts
|
|
159613
|
+
function displayTypeForSize(w2, h2) {
|
|
159614
|
+
const key2 = `${Math.min(w2, h2)}x${Math.max(w2, h2)}`;
|
|
159615
|
+
const map = {
|
|
159616
|
+
"1320x2868": "APP_IPHONE_67",
|
|
159617
|
+
// 6.9" → 6.7"/6.9" combined slot
|
|
159618
|
+
"1290x2796": "APP_IPHONE_67",
|
|
159619
|
+
// 6.7"
|
|
159620
|
+
"1242x2688": "APP_IPHONE_65",
|
|
159621
|
+
// 6.5"
|
|
159622
|
+
"1284x2778": "APP_IPHONE_65",
|
|
159623
|
+
"1206x2622": "APP_IPHONE_61",
|
|
159624
|
+
// 6.3"/6.1"
|
|
159625
|
+
"1179x2556": "APP_IPHONE_61",
|
|
159626
|
+
"2048x2732": "APP_IPAD_PRO_129",
|
|
159627
|
+
"2064x2752": "APP_IPAD_PRO_3GEN_129"
|
|
159628
|
+
};
|
|
159629
|
+
return map[key2] ?? null;
|
|
159630
|
+
}
|
|
159631
|
+
var init_screenshot_display_types = __esm({
|
|
159632
|
+
"../store-release/screenshot-display-types.ts"() {
|
|
159633
|
+
}
|
|
159634
|
+
});
|
|
159635
|
+
|
|
159636
|
+
// ../store-release/iap-review-screenshot.ts
|
|
159637
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
159638
|
+
import { basename as basename19, resolve as resolve56 } from "node:path";
|
|
159639
|
+
function pngSize(bytes2) {
|
|
159640
|
+
const signed = PNG_SIGNATURE.every((b2, i2) => bytes2[i2] === b2);
|
|
159641
|
+
if (!signed || bytes2.length < 24 || bytes2.toString("ascii", 12, 16) !== "IHDR") return void 0;
|
|
159642
|
+
return { format: "png", width: bytes2.readUInt32BE(16), height: bytes2.readUInt32BE(20) };
|
|
159643
|
+
}
|
|
159644
|
+
function jpegSize(bytes2) {
|
|
159645
|
+
if (bytes2[0] !== 255 || bytes2[1] !== 216) return void 0;
|
|
159646
|
+
for (let at2 = 2; at2 + 9 <= bytes2.length && bytes2[at2] === 255; at2 += 2 + bytes2.readUInt16BE(at2 + 2)) {
|
|
159647
|
+
if (JPEG_SOF_MARKERS.has(bytes2[at2 + 1])) return { format: "jpeg", height: bytes2.readUInt16BE(at2 + 5), width: bytes2.readUInt16BE(at2 + 7) };
|
|
159648
|
+
}
|
|
159649
|
+
return void 0;
|
|
159650
|
+
}
|
|
159651
|
+
function readImageSize(bytes2) {
|
|
159652
|
+
const buffer = Buffer.from(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
159653
|
+
return pngSize(buffer) ?? jpegSize(buffer);
|
|
159654
|
+
}
|
|
159655
|
+
function md5Hex(bytes2) {
|
|
159656
|
+
return createHash38("md5").update(bytes2).digest("hex");
|
|
159657
|
+
}
|
|
159658
|
+
function isAppStoreScreenshotSize(file2) {
|
|
159659
|
+
return displayTypeForSize(file2.width, file2.height) !== null;
|
|
159660
|
+
}
|
|
159661
|
+
function screenshotNotes(file2) {
|
|
159662
|
+
const size = `${file2.width}\xD7${file2.height}`;
|
|
159663
|
+
const notes = [`review screenshot ${file2.fileName} (${size} ${file2.format.toUpperCase()})`];
|
|
159664
|
+
if (!isAppStoreScreenshotSize(file2)) notes.push(`${size} is not an App Store screenshot size this tool knows \u2014 Apple may refuse it; a full-size iPhone screenshot is safest`);
|
|
159665
|
+
return notes;
|
|
159666
|
+
}
|
|
159667
|
+
function readReviewScreenshot(path2, source) {
|
|
159668
|
+
if (!source.readBytes) throw new Error("this run cannot read files");
|
|
159669
|
+
const absolute = resolve56(source.manifestDir ?? process.cwd(), path2);
|
|
159670
|
+
let bytes2;
|
|
159671
|
+
try {
|
|
159672
|
+
bytes2 = source.readBytes(absolute);
|
|
159673
|
+
} catch (e2) {
|
|
159674
|
+
throw new Error(`cannot read ${absolute}: ${e2.message}`);
|
|
159675
|
+
}
|
|
159676
|
+
const size = readImageSize(bytes2);
|
|
159677
|
+
if (!size) throw new Error(`${absolute} is not a PNG or JPEG image`);
|
|
159678
|
+
return { ...size, path: absolute, fileName: basename19(absolute), bytes: bytes2, checksum: md5Hex(bytes2) };
|
|
159679
|
+
}
|
|
159680
|
+
function loadReviewScreenshots(manifest, source, indices = manifest.items.map((_2, i2) => i2)) {
|
|
159681
|
+
const files = /* @__PURE__ */ new Map();
|
|
159682
|
+
const problems = [];
|
|
159683
|
+
for (const i2 of indices) {
|
|
159684
|
+
const path2 = manifest.items[i2].reviewScreenshot;
|
|
159685
|
+
if (path2 === void 0) continue;
|
|
159686
|
+
try {
|
|
159687
|
+
files.set(i2, readReviewScreenshot(path2, source));
|
|
159688
|
+
} catch (e2) {
|
|
159689
|
+
problems.push(`items[${i2}].reviewScreenshot: ${e2.message}`);
|
|
159690
|
+
}
|
|
159691
|
+
}
|
|
159692
|
+
if (problems.length) throw new IapManifestError("the manifest", problems);
|
|
159693
|
+
return files;
|
|
159694
|
+
}
|
|
159695
|
+
var PNG_SIGNATURE, JPEG_SOF_MARKERS;
|
|
159696
|
+
var init_iap_review_screenshot = __esm({
|
|
159697
|
+
"../store-release/iap-review-screenshot.ts"() {
|
|
159698
|
+
init_iap_manifest();
|
|
159699
|
+
init_screenshot_display_types();
|
|
159700
|
+
PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
159701
|
+
JPEG_SOF_MARKERS = /* @__PURE__ */ new Set([192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207]);
|
|
159702
|
+
}
|
|
159703
|
+
});
|
|
159704
|
+
|
|
159431
159705
|
// ../store-release/iap-plan.ts
|
|
159432
159706
|
function priceNote(price, target) {
|
|
159433
159707
|
if (price.rule !== "atLeast") return CONDITIONAL_PRICE_NOTE;
|
|
@@ -159567,6 +159841,47 @@ function availabilityDiff(item, observed) {
|
|
|
159567
159841
|
function metadataDiffs(item, observed, target = exactTarget(item.price)) {
|
|
159568
159842
|
return [...localizationDiffs(item, observed), ...priceDiff(item, observed, target), ...availabilityDiff(item, observed)];
|
|
159569
159843
|
}
|
|
159844
|
+
function screenshotMatches(observed, checksum) {
|
|
159845
|
+
return observed?.checksum === checksum && observed.state !== "FAILED";
|
|
159846
|
+
}
|
|
159847
|
+
function describeScreenshotGap(observed, fileName) {
|
|
159848
|
+
if (!observed) return "the review screenshot is not uploaded";
|
|
159849
|
+
if (observed.state === "AWAITING_UPLOAD") return "the review screenshot is not uploaded \u2014 an unfinished upload is waiting";
|
|
159850
|
+
if (observed.state === "FAILED") return `Apple could not process the review screenshot: ${observed.errors.join("; ") || "no reason given"}`;
|
|
159851
|
+
return `the review screenshot differs from ${fileName}`;
|
|
159852
|
+
}
|
|
159853
|
+
function screenshotUnmet(planned2, observed) {
|
|
159854
|
+
if (!planned2 || !observed || screenshotMatches(observed.reviewScreenshot, planned2.checksum)) return [];
|
|
159855
|
+
return [describeScreenshotGap(observed.reviewScreenshot, planned2.fileName)];
|
|
159856
|
+
}
|
|
159857
|
+
async function withReviewScreenshot(api2, observed) {
|
|
159858
|
+
if (observed.reviewScreenshotRead) return observed;
|
|
159859
|
+
const reviewScreenshot = await api2.readReviewScreenshot(observed.resourceId);
|
|
159860
|
+
return { ...observed, reviewScreenshotRead: true, ...reviewScreenshot ? { reviewScreenshot } : {} };
|
|
159861
|
+
}
|
|
159862
|
+
function isScreenshotLeftover(held) {
|
|
159863
|
+
return LEFTOVER_SCREENSHOT_STATES.has(held.state);
|
|
159864
|
+
}
|
|
159865
|
+
function screenshotOp(observed, checksum) {
|
|
159866
|
+
return { kind: observed.reviewScreenshot ? "replaceReviewScreenshot" : "uploadReviewScreenshot", checksum };
|
|
159867
|
+
}
|
|
159868
|
+
async function planReviewScreenshot(api2, plan, file2) {
|
|
159869
|
+
if (!file2) return plan;
|
|
159870
|
+
const planned2 = { ...plan, notes: [...plan.notes, ...screenshotNotes(file2)], reviewScreenshot: { fileName: file2.fileName, checksum: file2.checksum } };
|
|
159871
|
+
if (plan.decision === "conflict") return plan.observed ? { ...planned2, observed: await withReviewScreenshot(api2, plan.observed) } : planned2;
|
|
159872
|
+
if (plan.decision === "create") return { ...planned2, ops: [...plan.ops, { kind: "uploadReviewScreenshot", checksum: file2.checksum }] };
|
|
159873
|
+
const observed = await withReviewScreenshot(api2, observationOf(plan));
|
|
159874
|
+
const [gap] = screenshotUnmet(planned2.reviewScreenshot, observed);
|
|
159875
|
+
if (!gap) return { ...planned2, observed };
|
|
159876
|
+
if (isLocked(observed)) {
|
|
159877
|
+
return { ...planned2, observed, decision: "conflict", ops: [], conflicts: [`${plan.productId} is ${observed.state} and this command never changes a live or in-review product: ${gap}`] };
|
|
159878
|
+
}
|
|
159879
|
+
return { ...planned2, observed, decision: "update", ops: [...plan.ops, screenshotOp(observed, file2.checksum)] };
|
|
159880
|
+
}
|
|
159881
|
+
function observationOf(plan) {
|
|
159882
|
+
if (!plan.observed) throw new Error(`internal: the plan for existing product ${plan.productId} has no observation`);
|
|
159883
|
+
return plan.observed;
|
|
159884
|
+
}
|
|
159570
159885
|
function isLocked(observed) {
|
|
159571
159886
|
return !EDITABLE_PRODUCT_STATES.has(observed.state) || observed.versions.some((v2) => LOCKED_VERSION_STATES.has(v2.state));
|
|
159572
159887
|
}
|
|
@@ -159671,11 +159986,15 @@ async function planItem(pricing, api2, item, products, today) {
|
|
|
159671
159986
|
}
|
|
159672
159987
|
async function planItemsAt(context, manifest, indices = manifest.items.map((_2, i2) => i2)) {
|
|
159673
159988
|
const pricing = context.pricing ?? new PriceGrid(context.api);
|
|
159989
|
+
const screenshots = loadReviewScreenshots(manifest, context, indices);
|
|
159674
159990
|
return withAccessContext(context.identity, manifest.target, async () => {
|
|
159675
159991
|
await verifyTarget(context.api, manifest, context.identity);
|
|
159676
159992
|
const products = await discoverProducts(context, manifest);
|
|
159677
159993
|
const plans = /* @__PURE__ */ new Map();
|
|
159678
|
-
for (const i2 of indices)
|
|
159994
|
+
for (const i2 of indices) {
|
|
159995
|
+
const planned2 = await planItem(pricing, context.api, manifest.items[i2], products, isoDay(context.now()));
|
|
159996
|
+
plans.set(i2, await planReviewScreenshot(context.api, planned2, screenshots.get(i2)));
|
|
159997
|
+
}
|
|
159679
159998
|
return plans;
|
|
159680
159999
|
});
|
|
159681
160000
|
}
|
|
@@ -159695,6 +160014,7 @@ async function planIap(manifest, context) {
|
|
|
159695
160014
|
target: manifest.target,
|
|
159696
160015
|
manifestDigest: manifestDigest(manifest),
|
|
159697
160016
|
manifest,
|
|
160017
|
+
...context.manifestDir ? { manifestDir: context.manifestDir } : {},
|
|
159698
160018
|
items
|
|
159699
160019
|
});
|
|
159700
160020
|
}
|
|
@@ -159705,13 +160025,18 @@ function verifyOps(plan, manifest) {
|
|
|
159705
160025
|
if (itemPlan2.productId !== item.productId || !Array.isArray(itemPlan2.ops)) throw planError(`plan item ${i2} does not match manifest product ${item.productId}`);
|
|
159706
160026
|
for (const op of itemPlan2.ops) {
|
|
159707
160027
|
const locales = item.localizations.map((l2) => l2.locale);
|
|
159708
|
-
const knownShape = OP_KINDS.has(op.kind) && Object.keys(op).every((k2) => k2 === "kind" || k2 === "locale" && LOCALE_OPS.has(op.kind) || op.kind === "changePrice" && (k2 === "from" || k2 === "to"));
|
|
160028
|
+
const knownShape = OP_KINDS.has(op.kind) && Object.keys(op).every((k2) => k2 === "kind" || k2 === "locale" && LOCALE_OPS.has(op.kind) || op.kind === "changePrice" && (k2 === "from" || k2 === "to") || k2 === "checksum" && SCREENSHOT_OPS.has(op.kind));
|
|
159709
160029
|
const localeOk = !LOCALE_OPS.has(op.kind) || locales.includes(op.locale);
|
|
159710
160030
|
const priceOk = op.kind !== "changePrice" || item.price.rule === "atLeast" && [op.from, op.to].every((v2) => typeof v2 === "string" && /^\d+(\.\d+)?$/.test(v2) && compareAmounts(v2, "0") > 0) && itemPlan2.observed?.priceSchedule !== void 0 && itemPlan2.targetPrice === op.to;
|
|
159711
|
-
|
|
160031
|
+
const screenshotOk = !SCREENSHOT_OPS.has(op.kind) || screenshotOpOk(op, item, itemPlan2);
|
|
160032
|
+
if (!knownShape || !localeOk || !priceOk || !screenshotOk) throw planError(`plan item ${item.productId} has an unknown operation ${JSON.stringify(op)}`);
|
|
159712
160033
|
}
|
|
159713
160034
|
});
|
|
159714
160035
|
}
|
|
160036
|
+
function screenshotOpOk(op, item, itemPlan2) {
|
|
160037
|
+
const { checksum } = op;
|
|
160038
|
+
return item.reviewScreenshot !== void 0 && typeof checksum === "string" && MD5_HEX.test(checksum) && itemPlan2.reviewScreenshot?.checksum === checksum;
|
|
160039
|
+
}
|
|
159715
160040
|
function verifyPlan2(doc) {
|
|
159716
160041
|
const plan = doc;
|
|
159717
160042
|
if (!plan || typeof plan !== "object" || plan.planVersion !== 1) throw planError("not a himi store iap plan (planVersion 1)");
|
|
@@ -159728,8 +160053,9 @@ async function statusIap(manifest, context, catalog3) {
|
|
|
159728
160053
|
const plans = await planItems({ ...context, pricing }, manifest);
|
|
159729
160054
|
const readAt2 = context.now();
|
|
159730
160055
|
const items = [];
|
|
159731
|
-
for (const [i2,
|
|
160056
|
+
for (const [i2, planned2] of plans.entries()) {
|
|
159732
160057
|
const item = manifest.items[i2];
|
|
160058
|
+
const p2 = planned2.observed ? { ...planned2, observed: await withAccessContext(context.identity, manifest.target, () => withReviewScreenshot(context.api, planned2.observed)) } : planned2;
|
|
159733
160059
|
const target = p2.observed ? await pricing.targetAmount(item.price, p2.observed.resourceId) : void 0;
|
|
159734
160060
|
const result = itemResult({
|
|
159735
160061
|
target: manifest.target,
|
|
@@ -159737,7 +160063,7 @@ async function statusIap(manifest, context, catalog3) {
|
|
|
159737
160063
|
observed: p2.observed,
|
|
159738
160064
|
outcome: STATUS_OUTCOMES[p2.decision],
|
|
159739
160065
|
conflicts: p2.conflicts,
|
|
159740
|
-
unmet: p2.observed ? metadataDiffs(item, p2.observed, target) : [],
|
|
160066
|
+
unmet: p2.observed ? [...metadataDiffs(item, p2.observed, target), ...screenshotUnmet(p2.reviewScreenshot, p2.observed)] : [],
|
|
159741
160067
|
readAt: readAt2
|
|
159742
160068
|
});
|
|
159743
160069
|
Object.assign(result.provisioning, await withAccessContext(context.identity, manifest.target, () => checkStatusPrice(item, p2.observed, pricing, catalog3)));
|
|
@@ -159745,7 +160071,7 @@ async function statusIap(manifest, context, catalog3) {
|
|
|
159745
160071
|
}
|
|
159746
160072
|
return iapResult({ target: manifest.target, identity: context.identity, items, generatedAt: readAt2 });
|
|
159747
160073
|
}
|
|
159748
|
-
var IapProvisionError, EDITABLE_VERSION_STATE, EDITABLE_PRODUCT_STATES, LOCKED_VERSION_STATES, OP_KINDS, LOCALE_OPS, CONDITIONAL_PRICE_NOTE, STATUS_OUTCOMES, isoDay, exactTarget, planError;
|
|
160074
|
+
var IapProvisionError, EDITABLE_VERSION_STATE, EDITABLE_PRODUCT_STATES, LOCKED_VERSION_STATES, SCREENSHOT_OPS, OP_KINDS, MD5_HEX, LOCALE_OPS, CONDITIONAL_PRICE_NOTE, STATUS_OUTCOMES, isoDay, exactTarget, LEFTOVER_SCREENSHOT_STATES, planError;
|
|
159749
160075
|
var init_iap_plan = __esm({
|
|
159750
160076
|
"../store-release/iap-plan.ts"() {
|
|
159751
160077
|
init_iap_api();
|
|
@@ -159754,6 +160080,7 @@ var init_iap_plan = __esm({
|
|
|
159754
160080
|
init_iap_pricing();
|
|
159755
160081
|
init_iap_result();
|
|
159756
160082
|
init_iap_price_status();
|
|
160083
|
+
init_iap_review_screenshot();
|
|
159757
160084
|
IapProvisionError = class extends Error {
|
|
159758
160085
|
constructor(reason, message) {
|
|
159759
160086
|
super(message);
|
|
@@ -159764,12 +160091,15 @@ var init_iap_plan = __esm({
|
|
|
159764
160091
|
EDITABLE_VERSION_STATE = "PREPARE_FOR_SUBMISSION";
|
|
159765
160092
|
EDITABLE_PRODUCT_STATES = /* @__PURE__ */ new Set(["MISSING_METADATA", "READY_TO_SUBMIT", "DEVELOPER_ACTION_NEEDED", "REJECTED"]);
|
|
159766
160093
|
LOCKED_VERSION_STATES = /* @__PURE__ */ new Set(["READY_FOR_REVIEW", "WAITING_FOR_REVIEW", "IN_REVIEW", "ACCEPTED", "APPROVED"]);
|
|
159767
|
-
|
|
160094
|
+
SCREENSHOT_OPS = /* @__PURE__ */ new Set(["uploadReviewScreenshot", "replaceReviewScreenshot"]);
|
|
160095
|
+
OP_KINDS = /* @__PURE__ */ new Set(["createProduct", "createVersion", "createLocalization", "updateLocalization", "setPrice", "changePrice", "setAvailability", ...SCREENSHOT_OPS]);
|
|
160096
|
+
MD5_HEX = /^[0-9a-f]{32}$/;
|
|
159768
160097
|
LOCALE_OPS = /* @__PURE__ */ new Set(["createLocalization", "updateLocalization"]);
|
|
159769
160098
|
CONDITIONAL_PRICE_NOTE = "the exact price point can only be looked up after the product exists \u2014 apply stops with a partial result if Apple has no point of exactly the requested amount";
|
|
159770
160099
|
STATUS_OUTCOMES = { create: "absent", update: "incomplete", reuse: "reused", conflict: "conflict" };
|
|
159771
160100
|
isoDay = (date) => date.toISOString().slice(0, 10);
|
|
159772
160101
|
exactTarget = (price) => price.rule === "atLeast" ? void 0 : price.amount;
|
|
160102
|
+
LEFTOVER_SCREENSHOT_STATES = /* @__PURE__ */ new Set(["AWAITING_UPLOAD", "FAILED"]);
|
|
159773
160103
|
planError = (message) => new IapProvisionError("plan", message);
|
|
159774
160104
|
}
|
|
159775
160105
|
});
|
|
@@ -159777,6 +160107,7 @@ var init_iap_plan = __esm({
|
|
|
159777
160107
|
// ../store-release/iap-apply.ts
|
|
159778
160108
|
function sameOp(a2, b2) {
|
|
159779
160109
|
if (a2.kind === "changePrice" && b2.kind === "changePrice") return a2.from === b2.from && a2.to === b2.to;
|
|
160110
|
+
if ("checksum" in a2 || "checksum" in b2) return "checksum" in a2 && "checksum" in b2 && a2.checksum === b2.checksum;
|
|
159780
160111
|
return a2.kind === b2.kind && ("locale" in a2 ? a2.locale : void 0) === ("locale" in b2 ? b2.locale : void 0);
|
|
159781
160112
|
}
|
|
159782
160113
|
function assertSameAccount(planned2, current) {
|
|
@@ -159797,9 +160128,19 @@ function driftOf(planned2, live3, today) {
|
|
|
159797
160128
|
const scheduleProblem = priceScheduleConflict(live3.observed?.priceSchedule, today);
|
|
159798
160129
|
if (scheduleProblem) return `${live3.productId}: ${scheduleProblem}`;
|
|
159799
160130
|
}
|
|
160131
|
+
const [plannedShot, liveShot] = [planned2.reviewScreenshot, live3.reviewScreenshot];
|
|
160132
|
+
if (plannedShot && liveShot && plannedShot.checksum !== liveShot.checksum) return `${live3.productId}: ${liveShot.fileName} changed since the plan was made`;
|
|
160133
|
+
if (replacesUnplannedScreenshot(planned2, live3)) return `${live3.productId}: a review screenshot was added in App Store Connect after the plan \u2014 make a new plan before replacing it`;
|
|
159800
160134
|
const unplanned = live3.ops.filter((op) => !planned2.ops.some((p2) => sameOp(p2, op)));
|
|
159801
160135
|
return unplanned.length ? `${live3.productId} now needs ${unplanned.map(describeOp).join(", ")}, which the plan did not list` : void 0;
|
|
159802
160136
|
}
|
|
160137
|
+
function replacesUnplannedScreenshot(planned2, live3) {
|
|
160138
|
+
if (!live3.ops.some((op) => op.kind === "replaceReviewScreenshot")) return false;
|
|
160139
|
+
const held = live3.observed?.reviewScreenshot;
|
|
160140
|
+
if (!held || isScreenshotLeftover(held)) return false;
|
|
160141
|
+
const seen = planned2.observed?.reviewScreenshot;
|
|
160142
|
+
return !seen || seen.id !== held.id || isScreenshotLeftover(seen);
|
|
160143
|
+
}
|
|
159803
160144
|
function assertNoDrift(plan, live3, today) {
|
|
159804
160145
|
const drift = [...live3].map(([i2, current]) => driftOf(plan.items[i2], current, today)).filter((d2) => d2 !== void 0);
|
|
159805
160146
|
if (!drift.length) return;
|
|
@@ -159852,6 +160193,50 @@ async function findLocalization(api2, versionId, locale, matchText) {
|
|
|
159852
160193
|
if (!found || matchText && (found.name !== matchText.name || found.description !== matchText.description)) return void 0;
|
|
159853
160194
|
return found;
|
|
159854
160195
|
}
|
|
160196
|
+
function plannedScreenshot(item, op, context) {
|
|
160197
|
+
const file2 = readReviewScreenshot(required(item.reviewScreenshot, "the review screenshot path"), context);
|
|
160198
|
+
if (!("checksum" in op) || file2.checksum !== op.checksum) throw new UnresolvedWriteError(`${file2.fileName} changed after the plan was made \u2014 make a new plan`);
|
|
160199
|
+
return file2;
|
|
160200
|
+
}
|
|
160201
|
+
async function reserveScreenshot(api2, resourceId, file2, overValid) {
|
|
160202
|
+
try {
|
|
160203
|
+
return await api2.reserveReviewScreenshot(resourceId, { fileName: file2.fileName, fileSize: file2.bytes.length });
|
|
160204
|
+
} catch (e2) {
|
|
160205
|
+
if (overValid && e2 instanceof AscError && e2.kind === "conflict") throw new UnresolvedWriteError(KEPT_EXISTING_SCREENSHOT);
|
|
160206
|
+
if (!(e2 instanceof AscError) || !AMBIGUOUS_WRITE_KINDS.has(e2.kind)) throw e2;
|
|
160207
|
+
throw new UnresolvedWriteError(`could not confirm the review screenshot reservation (${e2.message}). Make a new plan \u2014 it replaces an unfinished reservation.`);
|
|
160208
|
+
}
|
|
160209
|
+
}
|
|
160210
|
+
async function settledScreenshot(api2, resourceId, committed, sleep) {
|
|
160211
|
+
if (SETTLED_SCREENSHOT_STATES.has(committed.state)) return committed;
|
|
160212
|
+
const read = async () => {
|
|
160213
|
+
const current = await api2.readReviewScreenshot(resourceId);
|
|
160214
|
+
return current && SETTLED_SCREENSHOT_STATES.has(current.state) ? current : void 0;
|
|
160215
|
+
};
|
|
160216
|
+
return await pollFor(read, sleep) ?? committed;
|
|
160217
|
+
}
|
|
160218
|
+
async function uploadScreenshot(context, resourceId, file2) {
|
|
160219
|
+
const { api: api2, sleep } = context;
|
|
160220
|
+
const current = await api2.readReviewScreenshot(resourceId);
|
|
160221
|
+
if (current && screenshotMatches(current, file2.checksum)) return { state: "reconciled", resourceId: current.id };
|
|
160222
|
+
const reservation = await reserveScreenshot(api2, resourceId, file2, current !== void 0 && !isScreenshotLeftover(current));
|
|
160223
|
+
await api2.uploadReviewScreenshotParts(reservation, file2.bytes);
|
|
160224
|
+
const committed = async () => {
|
|
160225
|
+
const screenshot = await api2.readReviewScreenshot(resourceId);
|
|
160226
|
+
return screenshot?.id === reservation.id && screenshot.checksum === file2.checksum ? screenshot : void 0;
|
|
160227
|
+
};
|
|
160228
|
+
const { value, state } = await ensure({ write: () => api2.commitReviewScreenshot(reservation.id, file2.checksum), find: committed }, sleep);
|
|
160229
|
+
const settled = await settledScreenshot(api2, resourceId, value, sleep);
|
|
160230
|
+
if (settled.state === "FAILED") throw new UnresolvedWriteError(`Apple could not process the review screenshot: ${settled.errors.join("; ") || "no reason given"}`);
|
|
160231
|
+
return { state, resourceId: reservation.id };
|
|
160232
|
+
}
|
|
160233
|
+
async function deleteLeftoverScreenshot(context, resourceId) {
|
|
160234
|
+
const { api: api2, sleep } = context;
|
|
160235
|
+
const stale = await api2.readReviewScreenshot(resourceId);
|
|
160236
|
+
if (!stale || !isScreenshotLeftover(stale)) return;
|
|
160237
|
+
const gone = async () => (await api2.readReviewScreenshot(resourceId))?.id !== stale.id ? true : void 0;
|
|
160238
|
+
await ensure({ write: async () => (await api2.deleteReviewScreenshot(stale.id), true), find: gone }, sleep);
|
|
160239
|
+
}
|
|
159855
160240
|
function operationRunners(context, manifest) {
|
|
159856
160241
|
const { api: api2, sleep, pricing } = context;
|
|
159857
160242
|
const appId2 = manifest.target.appleAppId;
|
|
@@ -159917,6 +160302,13 @@ function operationRunners(context, manifest) {
|
|
|
159917
160302
|
const matches = async () => availabilityMatches(await readObservedAvailability(api2, resourceId), territories) ? true : void 0;
|
|
159918
160303
|
const { state } = await ensure({ write: async () => (await api2.createAvailability(resourceId, territories), true), find: matches }, sleep);
|
|
159919
160304
|
return { state };
|
|
160305
|
+
},
|
|
160306
|
+
uploadReviewScreenshot: async (run2, op) => uploadScreenshot(context, required(run2.resourceId, "the product id"), plannedScreenshot(run2.item, op, context)),
|
|
160307
|
+
replaceReviewScreenshot: async (run2, op) => {
|
|
160308
|
+
const resourceId = required(run2.resourceId, "the product id");
|
|
160309
|
+
const file2 = plannedScreenshot(run2.item, op, context);
|
|
160310
|
+
await deleteLeftoverScreenshot(context, resourceId);
|
|
160311
|
+
return uploadScreenshot(context, resourceId, file2);
|
|
159920
160312
|
}
|
|
159921
160313
|
};
|
|
159922
160314
|
}
|
|
@@ -159943,7 +160335,8 @@ async function runStep(runner2, run2, op, context, manifest) {
|
|
|
159943
160335
|
async function resumeFromApple(run2, remaining, context) {
|
|
159944
160336
|
const product = await context.api.readProduct(required(run2.resourceId, "the product id"));
|
|
159945
160337
|
if (!product) return { reason: "the product exists but cannot be read back yet \u2014 rerun apply later" };
|
|
159946
|
-
const
|
|
160338
|
+
const file2 = run2.item.reviewScreenshot === void 0 ? void 0 : readReviewScreenshot(run2.item.reviewScreenshot, context);
|
|
160339
|
+
const replanned = await planReviewScreenshot(context.api, await planForProduct(context.api, run2.item, product, context.pricing, context.now().toISOString().slice(0, 10)), file2);
|
|
159947
160340
|
if (replanned.decision === "conflict") return { reason: `the product already existed: ${replanned.conflicts.join("; ")}` };
|
|
159948
160341
|
const unplanned = replanned.ops.filter((op) => !remaining.some((r2) => sameOp(r2, op)));
|
|
159949
160342
|
if (unplanned.length) return { reason: `the product already existed and needs ${unplanned.map(describeOp).join(", ")}, which the plan did not list \u2014 make a new plan` };
|
|
@@ -159978,7 +160371,9 @@ async function readBack(run2, context, manifest) {
|
|
|
159978
160371
|
if (!run2.resourceId) return {};
|
|
159979
160372
|
try {
|
|
159980
160373
|
const product = await context.api.readProduct(run2.resourceId);
|
|
159981
|
-
|
|
160374
|
+
if (!product) return { failure: "Apple does not return it yet" };
|
|
160375
|
+
const observed = await observeProduct(context.api, product, context.now().toISOString().slice(0, 10));
|
|
160376
|
+
return { observed: run2.item.reviewScreenshot === void 0 ? observed : await withReviewScreenshot(context.api, observed) };
|
|
159982
160377
|
} catch (e2) {
|
|
159983
160378
|
return { failure: explainFailure(e2, context, manifest) };
|
|
159984
160379
|
}
|
|
@@ -159988,7 +160383,8 @@ async function unmetFor(item, observed, context) {
|
|
|
159988
160383
|
}
|
|
159989
160384
|
async function knownUnmetFor(item, planned2, context) {
|
|
159990
160385
|
if (!planned2.observed) return [];
|
|
159991
|
-
|
|
160386
|
+
const metadata2 = metadataDiffs(item, planned2.observed, planned2.targetPrice ?? await context.pricing.targetAmount(item.price));
|
|
160387
|
+
return [...metadata2, ...screenshotUnmet(planned2.reviewScreenshot, planned2.observed)];
|
|
159992
160388
|
}
|
|
159993
160389
|
async function applyItem(item, live3, context, manifest) {
|
|
159994
160390
|
const base = { target: manifest.target, item, readAt: context.now() };
|
|
@@ -160005,7 +160401,7 @@ async function applyItem(item, live3, context, manifest) {
|
|
|
160005
160401
|
};
|
|
160006
160402
|
const steps = await runOps(run2, live3.ops, context, manifest);
|
|
160007
160403
|
const { observed, failure } = await readBack(run2, context, manifest);
|
|
160008
|
-
const unmet = failure ? [`could not read the product back: ${failure}`] : await unmetFor(item, observed, context);
|
|
160404
|
+
const unmet = failure ? [`could not read the product back: ${failure}`] : [...await unmetFor(item, observed, context), ...screenshotUnmet(live3.reviewScreenshot, observed)];
|
|
160009
160405
|
const outcome = outcomeOf(live3.ops, steps, unmet);
|
|
160010
160406
|
return itemResult({ ...base, readAt: context.now(), observed, outcome, steps, unmet, appleResourceId: run2.resourceId });
|
|
160011
160407
|
}
|
|
@@ -160023,7 +160419,8 @@ function plannedResult(item, planned2, plan, context, manifest) {
|
|
|
160023
160419
|
async function applyIap(planDoc, applyContext) {
|
|
160024
160420
|
const plan = verifyPlan2(planDoc);
|
|
160025
160421
|
assertSameAccount(plan.identity, applyContext.identity);
|
|
160026
|
-
const
|
|
160422
|
+
const manifestDir = plan.manifestDir ?? applyContext.manifestDir;
|
|
160423
|
+
const context = { ...applyContext, ...manifestDir ? { manifestDir } : {}, pricing: applyContext.pricing ?? new PriceGrid(applyContext.api) };
|
|
160027
160424
|
const manifest = plan.manifest;
|
|
160028
160425
|
const refresh = plan.items.flatMap((planned2, i2) => needsRefresh(planned2) ? [i2] : []);
|
|
160029
160426
|
const live3 = await planItemsAt(context, manifest, refresh);
|
|
@@ -160046,23 +160443,26 @@ async function applyIap(planDoc, applyContext) {
|
|
|
160046
160443
|
}
|
|
160047
160444
|
return iapResult({ target: manifest.target, identity: context.identity, items, generatedAt: context.now() });
|
|
160048
160445
|
}
|
|
160049
|
-
var DEFERRED_REQUIREMENT, RECONCILE_READS, RECONCILE_BASE_WAIT_MS, AMBIGUOUS_WRITE_KINDS, UnresolvedWriteError, required;
|
|
160446
|
+
var DEFERRED_REQUIREMENT, RECONCILE_READS, RECONCILE_BASE_WAIT_MS, AMBIGUOUS_WRITE_KINDS, SETTLED_SCREENSHOT_STATES, UnresolvedWriteError, required, KEPT_EXISTING_SCREENSHOT;
|
|
160050
160447
|
var init_iap_apply = __esm({
|
|
160051
160448
|
"../store-release/iap-apply.ts"() {
|
|
160052
160449
|
init_iap_client();
|
|
160053
160450
|
init_iap_plan();
|
|
160054
160451
|
init_iap_pricing();
|
|
160452
|
+
init_iap_review_screenshot();
|
|
160055
160453
|
init_iap_result();
|
|
160056
160454
|
DEFERRED_REQUIREMENT = "deferred by --limit \u2014 rerun apply to continue; nothing was written for this product in this run";
|
|
160057
160455
|
RECONCILE_READS = 4;
|
|
160058
160456
|
RECONCILE_BASE_WAIT_MS = 1e3;
|
|
160059
160457
|
AMBIGUOUS_WRITE_KINDS = /* @__PURE__ */ new Set(["uncertain", "rateLimited", "conflict"]);
|
|
160458
|
+
SETTLED_SCREENSHOT_STATES = /* @__PURE__ */ new Set(["COMPLETE", "FAILED"]);
|
|
160060
160459
|
UnresolvedWriteError = class extends Error {
|
|
160061
160460
|
};
|
|
160062
160461
|
required = (value, what) => {
|
|
160063
160462
|
if (!value) throw new Error(`internal: ${what} is not known yet`);
|
|
160064
160463
|
return value;
|
|
160065
160464
|
};
|
|
160465
|
+
KEPT_EXISTING_SCREENSHOT = "Apple kept the existing review screenshot and refused a second one \u2014 replace it in App Store Connect (a review screenshot can be updated there but not removed)";
|
|
160066
160466
|
}
|
|
160067
160467
|
});
|
|
160068
160468
|
|
|
@@ -160186,11 +160586,11 @@ var init_credential_profile = __esm({
|
|
|
160186
160586
|
});
|
|
160187
160587
|
|
|
160188
160588
|
// ../store-release/iap-credentials.ts
|
|
160189
|
-
import { createHash as
|
|
160589
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
160190
160590
|
import { existsSync as existsSync73, readFileSync as readFileSync88, realpathSync as realpathSync12 } from "node:fs";
|
|
160191
160591
|
import { homedir as homedir10 } from "node:os";
|
|
160192
160592
|
function accountFingerprint(keyId, issuerId) {
|
|
160193
|
-
return `sha256:${
|
|
160593
|
+
return `sha256:${createHash39("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
|
|
160194
160594
|
}
|
|
160195
160595
|
function requireExplicitProfile(profileFlag, target) {
|
|
160196
160596
|
const profile = profileFlag?.trim();
|
|
@@ -160277,7 +160677,7 @@ var init_wix_payments_contract = __esm({
|
|
|
160277
160677
|
});
|
|
160278
160678
|
|
|
160279
160679
|
// ../store-release/iap-draft.ts
|
|
160280
|
-
import { createHash as
|
|
160680
|
+
import { createHash as createHash40 } from "node:crypto";
|
|
160281
160681
|
function fit(text9, max) {
|
|
160282
160682
|
const chars = [...text9];
|
|
160283
160683
|
return chars.length <= max ? text9 : `${chars.slice(0, max - 1).join("").trimEnd()}${ELLIPSIS}`;
|
|
@@ -160427,7 +160827,7 @@ var init_iap_draft = __esm({
|
|
|
160427
160827
|
TIER_DESCRIPTION = "Unlocks one item in the app";
|
|
160428
160828
|
ELLIPSIS = "\u2026";
|
|
160429
160829
|
entityKey = (entityType, entityId) => `${entityType}:${entityId}`;
|
|
160430
|
-
sha = (text9) =>
|
|
160830
|
+
sha = (text9) => createHash40("sha256").update(text9).digest("hex");
|
|
160431
160831
|
ENTITIES = { "&": "&", " ": " ", "<": "<", ">": ">", """: '"', "'": "'" };
|
|
160432
160832
|
MAX_SUFFIX = 24;
|
|
160433
160833
|
ReferenceNames = class {
|
|
@@ -160744,7 +161144,7 @@ var init_store_spec = __esm({
|
|
|
160744
161144
|
|
|
160745
161145
|
// src/iap-config-edit.ts
|
|
160746
161146
|
import { existsSync as existsSync74, readFileSync as readFileSync90 } from "node:fs";
|
|
160747
|
-
import { basename as
|
|
161147
|
+
import { basename as basename20, join as join75 } from "node:path";
|
|
160748
161148
|
import ts8 from "typescript";
|
|
160749
161149
|
function bindPurchasesAppInConfig(source, options) {
|
|
160750
161150
|
const fileName = options.fileName ?? "config.ts";
|
|
@@ -160831,14 +161231,14 @@ function withStoreBundle(dir, options) {
|
|
|
160831
161231
|
function previewIapConfigEdit(dir, options) {
|
|
160832
161232
|
const path2 = configEntry(dir);
|
|
160833
161233
|
if (!path2) return void 0;
|
|
160834
|
-
if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${
|
|
160835
|
-
const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync90(path2, "utf8"), { ...withStoreBundle(dir, options), fileName:
|
|
161234
|
+
if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${basename20(path2)} is a symlink, so it would not be edited: add the purchases app in the file it points to.`] };
|
|
161235
|
+
const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync90(path2, "utf8"), { ...withStoreBundle(dir, options), fileName: basename20(path2) });
|
|
160836
161236
|
return { path: path2, changed, applied, conflicts, instructions };
|
|
160837
161237
|
}
|
|
160838
161238
|
async function applyIapConfigEdit(dir, options, validate4) {
|
|
160839
161239
|
const path2 = configEntry(dir);
|
|
160840
161240
|
if (!path2) return void 0;
|
|
160841
|
-
const fileName =
|
|
161241
|
+
const fileName = basename20(path2);
|
|
160842
161242
|
const refuse7 = (why) => ({ path: path2, changed: false, applied: [], conflicts: [], instructions: [why] });
|
|
160843
161243
|
if (isSymlink2(path2)) return refuse7(`${fileName} is a symlink, so it was not edited: add the purchases app in the file it points to.`);
|
|
160844
161244
|
const original = readFileSync90(path2, "utf8");
|
|
@@ -161297,6 +161697,281 @@ var init_store_iap_connect = __esm({
|
|
|
161297
161697
|
}
|
|
161298
161698
|
});
|
|
161299
161699
|
|
|
161700
|
+
// src/store-iap-screenshots.ts
|
|
161701
|
+
import { dirname as dirname40, join as join76, relative as relative15 } from "node:path";
|
|
161702
|
+
function purchaseScreensFor(item) {
|
|
161703
|
+
const screen = item.wix && PURCHASE_SCREENS[item.wix.entityType];
|
|
161704
|
+
if (!screen || !item.wix) return [];
|
|
161705
|
+
const list = LIST_SCREENS[item.wix.entityType];
|
|
161706
|
+
return [{ screenId: `${screen}_${item.wix.entityId}` }, { screenId: screen, input: { id: item.wix.entityId } }, ...list ? [{ screenId: list }] : []];
|
|
161707
|
+
}
|
|
161708
|
+
function formatApplePrice(amount, currency, locale) {
|
|
161709
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency }).format(Number(amount));
|
|
161710
|
+
}
|
|
161711
|
+
function bindingHost(target, offers) {
|
|
161712
|
+
const appId2 = target.himiApp;
|
|
161713
|
+
const byEntity = new Map(offers.flatMap((offer) => offer.item.wix ? [[offer.item.wix.entityId, offer]] : []));
|
|
161714
|
+
const product = ({ item, displayPrice }) => ({ id: item.productId, type: item.type, displayName: item.localizations[0]?.name ?? item.referenceName, displayPrice });
|
|
161715
|
+
const answers = {
|
|
161716
|
+
"capability.app_info.get": () => ({ appId: appId2, bundleId: target.bundleId, platform: "ios" }),
|
|
161717
|
+
"capability.iap.appBinding": () => ({ status: "bound", binding: { purchasesAppId: RENDER_PURCHASES_APP_ID, himalayaAppId: appId2, bundleId: target.bundleId, siteId: target.wixSiteId } }),
|
|
161718
|
+
"capability.iap.getProducts": (params) => {
|
|
161719
|
+
const asked = new Set(String(params?.productIds ?? "").split(",").map((id) => id.trim()));
|
|
161720
|
+
return { products: offers.filter((offer) => asked.has(offer.item.productId)).map(product) };
|
|
161721
|
+
},
|
|
161722
|
+
"capability.iap.getUnfinishedTransactions": () => ({ status: "ok", transactions: [] })
|
|
161723
|
+
};
|
|
161724
|
+
const member = { generation: 1, kind: "member", memberId: RENDER_MEMBER_ID, siteId: target.wixSiteId, appId: appId2, ready: true };
|
|
161725
|
+
return {
|
|
161726
|
+
dispatch: (action, params) => answers[action]?.(params),
|
|
161727
|
+
wixCall: (method, path2, body) => {
|
|
161728
|
+
if (method === "GET") return MEMBER_OWN_READS.find((read) => read.path.test(path2))?.answer;
|
|
161729
|
+
if (method !== "POST" || !MAPPINGS_PATH.test(path2)) return void 0;
|
|
161730
|
+
const asked = body?.appProductIds;
|
|
161731
|
+
const ids = Array.isArray(asked) ? asked.filter((id) => typeof id === "string" && byEntity.has(id)) : [];
|
|
161732
|
+
return { mappings: ids.map((id) => {
|
|
161733
|
+
const { item } = byEntity.get(id);
|
|
161734
|
+
return { appProductId: id, storeProductId: item.productId, type: item.type === "consumable" ? "CONSUMABLE" : "NON_CONSUMABLE", active: true };
|
|
161735
|
+
}) };
|
|
161736
|
+
},
|
|
161737
|
+
wixApiSession: { identityBound: true, session: { current: () => member, subscribe: () => () => {
|
|
161738
|
+
} } }
|
|
161739
|
+
};
|
|
161740
|
+
}
|
|
161741
|
+
function offersPurchase(fields) {
|
|
161742
|
+
return PURCHASE_FLAGS.some((flag) => fields[`${flag}Disabled`] === false && fields[`${flag}Hidden`] !== true);
|
|
161743
|
+
}
|
|
161744
|
+
function isItemRow(fields, entityId, price) {
|
|
161745
|
+
const values = Object.values(fields).filter((v2) => typeof v2 === "string");
|
|
161746
|
+
return values.some((v2) => v2.toLowerCase() === entityId.toLowerCase()) && values.some((v2) => visibleText2(v2).includes(price));
|
|
161747
|
+
}
|
|
161748
|
+
function rowOffersPurchase(value, entityId, price) {
|
|
161749
|
+
if (Array.isArray(value)) return value.some((row) => rowOffersPurchase(row, entityId, price));
|
|
161750
|
+
if (!value || typeof value !== "object") return false;
|
|
161751
|
+
const fields = value;
|
|
161752
|
+
if (isItemRow(fields, entityId, price)) return offersPurchase(fields);
|
|
161753
|
+
return Object.values(fields).some((child) => rowOffersPurchase(child, entityId, price));
|
|
161754
|
+
}
|
|
161755
|
+
function purchaseEnabled(state, entityId, price) {
|
|
161756
|
+
return Object.values(state).some((service) => {
|
|
161757
|
+
if (!service || typeof service !== "object") return false;
|
|
161758
|
+
return offersPurchase(service) || Object.values(service).some((child) => rowOffersPurchase(child, entityId, price));
|
|
161759
|
+
});
|
|
161760
|
+
}
|
|
161761
|
+
function priceFor2(item, run2) {
|
|
161762
|
+
const amount = run2.applePrice(item) ?? (item.price.rule === "atLeast" ? void 0 : item.price.amount);
|
|
161763
|
+
if (amount === void 0) {
|
|
161764
|
+
return { skipped: run2.appleRead ? "App Store Connect has no price for it yet \u2014 run himi store iap apply first" : "Apple's price for an atLeast item is only known once App Store Connect is read \u2014 pass --profile" };
|
|
161765
|
+
}
|
|
161766
|
+
return formatApplePrice(amount, item.price.currency, item.localizations[0]?.locale ?? "en-US");
|
|
161767
|
+
}
|
|
161768
|
+
function unknownOnlyIds(run2) {
|
|
161769
|
+
const known = new Set(run2.manifest.items.map((item) => item.productId));
|
|
161770
|
+
return [...run2.only ?? []].filter((id) => !known.has(id)).map((productId) => ({ productId, skipped: "not in the manifest" }));
|
|
161771
|
+
}
|
|
161772
|
+
function select(run2) {
|
|
161773
|
+
return run2.manifest.items.flatMap((item, index) => {
|
|
161774
|
+
if (run2.only && !run2.only.has(item.productId)) return [];
|
|
161775
|
+
const screens = purchaseScreensFor(item);
|
|
161776
|
+
const report3 = { productId: item.productId, ...screens[0] ? { screenId: screens[0].screenId } : {} };
|
|
161777
|
+
const selected = (extra) => [{ index, item, screens, report: { ...report3, ...extra } }];
|
|
161778
|
+
if (!screens.length) return selected({ skipped: "no purchase screen: a price tier or an entity type the templates have no detail screen for" });
|
|
161779
|
+
const locked = run2.appleLocked?.(item);
|
|
161780
|
+
if (locked) return selected({ skipped: `is ${locked} \u2014 a live or in-review product's screenshot is never changed` });
|
|
161781
|
+
if (item.reviewScreenshot && !run2.force) return selected({ skipped: `already names ${item.reviewScreenshot} \u2014 pass --force to replace it` });
|
|
161782
|
+
const price = priceFor2(item, run2);
|
|
161783
|
+
return selected(typeof price === "string" ? { price } : price);
|
|
161784
|
+
});
|
|
161785
|
+
}
|
|
161786
|
+
function offersFor(selected, run2) {
|
|
161787
|
+
const others = run2.manifest.items.flatMap((item) => {
|
|
161788
|
+
if (item === selected.item || item.wix?.entityType !== selected.item.wix?.entityType) return [];
|
|
161789
|
+
const price = priceFor2(item, run2);
|
|
161790
|
+
return typeof price === "string" ? [{ item, displayPrice: price }] : [];
|
|
161791
|
+
});
|
|
161792
|
+
return [{ item: selected.item, displayPrice: selected.report.price }, ...others];
|
|
161793
|
+
}
|
|
161794
|
+
function notAPurchase(rendered, entityId, price) {
|
|
161795
|
+
if (rendered.problems.length) return `the screen reported problems while loading: ${rendered.problems.join("; ")}`;
|
|
161796
|
+
if (!visibleText2(rendered.html).includes(price)) return `did not show the Apple price ${price} \u2014 it is not a purchase screen this command knows, or it did not load`;
|
|
161797
|
+
if (!purchaseEnabled(rendered.state, entityId, price)) return "showed the price but no enabled buy or join action for this item";
|
|
161798
|
+
return void 0;
|
|
161799
|
+
}
|
|
161800
|
+
async function renderPurchaseScreen(selected, run2) {
|
|
161801
|
+
const host = bindingHost(run2.manifest.target, offersFor(selected, run2));
|
|
161802
|
+
const price = selected.report.price;
|
|
161803
|
+
const reasons = [];
|
|
161804
|
+
for (const screen of selected.screens) {
|
|
161805
|
+
let rendered;
|
|
161806
|
+
try {
|
|
161807
|
+
rendered = await run2.renderer.render({ contentDir: run2.contentDir, host, entityId: selected.item.wix.entityId, ...screen });
|
|
161808
|
+
} catch (e2) {
|
|
161809
|
+
if (e2 instanceof MissingScreenError) continue;
|
|
161810
|
+
return { skipped: `could not render ${screen.screenId}: ${e2.message}` };
|
|
161811
|
+
}
|
|
161812
|
+
const reason = notAPurchase(rendered, selected.item.wix.entityId, price);
|
|
161813
|
+
if (!reason) return { screenId: screen.screenId, html: rendered.html };
|
|
161814
|
+
reasons.push(`${screen.screenId} ${reason}`);
|
|
161815
|
+
}
|
|
161816
|
+
if (!reasons.length) return { skipped: `the app has none of these screens: ${selected.screens.map((s2) => s2.screenId).join(", ")}` };
|
|
161817
|
+
return { skipped: reasons.join("; ") };
|
|
161818
|
+
}
|
|
161819
|
+
async function shoot(selected, run2, outDir) {
|
|
161820
|
+
const found = await renderPurchaseScreen(selected, run2);
|
|
161821
|
+
if ("skipped" in found) return { ...selected.report, skipped: found.skipped };
|
|
161822
|
+
const report3 = { ...selected.report, screenId: found.screenId };
|
|
161823
|
+
const path2 = join76(outDir, `${selected.item.productId}.png`);
|
|
161824
|
+
try {
|
|
161825
|
+
run2.writeBytes(path2, await run2.renderer.capture(found.html, run2.contentDir));
|
|
161826
|
+
} catch (e2) {
|
|
161827
|
+
return { ...report3, skipped: `could not save the screenshot: ${e2.message}` };
|
|
161828
|
+
}
|
|
161829
|
+
return { ...report3, screenshot: relative15(dirname40(run2.manifestPath), path2) };
|
|
161830
|
+
}
|
|
161831
|
+
function visibleText2(html) {
|
|
161832
|
+
return html.replace(/ | | /gi, "\xA0").replace(/&/g, "&");
|
|
161833
|
+
}
|
|
161834
|
+
function manifestWithScreenshots(text9, shot) {
|
|
161835
|
+
const doc = JSON.parse(text9);
|
|
161836
|
+
for (const [index, path2] of shot) doc.items[index].reviewScreenshot = path2;
|
|
161837
|
+
return `${JSON.stringify(doc, null, 2)}
|
|
161838
|
+
`;
|
|
161839
|
+
}
|
|
161840
|
+
async function takeReviewScreenshots(run2) {
|
|
161841
|
+
const outDir = run2.outDir ?? join76(dirname40(run2.manifestPath), DEFAULT_OUT_DIR);
|
|
161842
|
+
const items = unknownOnlyIds(run2);
|
|
161843
|
+
const shot = /* @__PURE__ */ new Map();
|
|
161844
|
+
try {
|
|
161845
|
+
for (const selected of select(run2)) {
|
|
161846
|
+
const ready = !selected.report.skipped && !run2.dryRun;
|
|
161847
|
+
const report3 = ready ? await shoot(selected, run2, outDir) : selected.report;
|
|
161848
|
+
if (report3.screenshot) shot.set(selected.index, report3.screenshot);
|
|
161849
|
+
items.push(report3);
|
|
161850
|
+
}
|
|
161851
|
+
} finally {
|
|
161852
|
+
if (shot.size) run2.writeText(run2.manifestPath, manifestWithScreenshots(run2.manifestText, shot));
|
|
161853
|
+
}
|
|
161854
|
+
return { complete: items.every((i2) => !i2.skipped), items };
|
|
161855
|
+
}
|
|
161856
|
+
var MissingScreenError, REVIEW_SCREENSHOT_FRAME, DEFAULT_OUT_DIR, PURCHASE_SCREENS, LIST_SCREENS, RENDER_PURCHASES_APP_ID, RENDER_MEMBER_ID, MAPPINGS_PATH, MEMBER_OWN_READS, PURCHASE_FLAGS;
|
|
161857
|
+
var init_store_iap_screenshots = __esm({
|
|
161858
|
+
"src/store-iap-screenshots.ts"() {
|
|
161859
|
+
MissingScreenError = class extends Error {
|
|
161860
|
+
constructor(screenId) {
|
|
161861
|
+
super(`the app has no screen ${screenId}`);
|
|
161862
|
+
this.screenId = screenId;
|
|
161863
|
+
}
|
|
161864
|
+
};
|
|
161865
|
+
REVIEW_SCREENSHOT_FRAME = { width: 430, height: 932, scale: 3 };
|
|
161866
|
+
DEFAULT_OUT_DIR = "review-screenshots";
|
|
161867
|
+
PURCHASE_SCREENS = { storesProduct: "himi_product", onlineProgram: "himi_program", pricingPlan: "himi_plan" };
|
|
161868
|
+
LIST_SCREENS = { pricingPlan: "himi_plans" };
|
|
161869
|
+
RENDER_PURCHASES_APP_ID = "00000000-0000-4000-8000-00000000a99e";
|
|
161870
|
+
RENDER_MEMBER_ID = "00000000-0000-4000-8000-0000000be4e7";
|
|
161871
|
+
MAPPINGS_PATH = /\/v1\/iap\/mappings$/;
|
|
161872
|
+
MEMBER_OWN_READS = [{ path: /^\/pricing-plans\/v2\/member\/orders(\?|$)/, answer: { orders: [] } }];
|
|
161873
|
+
PURCHASE_FLAGS = ["buy", "join"];
|
|
161874
|
+
}
|
|
161875
|
+
});
|
|
161876
|
+
|
|
161877
|
+
// src/store-iap-screenshot-render.ts
|
|
161878
|
+
import { existsSync as existsSync75, mkdtempSync as mkdtempSync4, readFileSync as readFileSync91, rmSync as rmSync18 } from "node:fs";
|
|
161879
|
+
import { tmpdir as tmpdir5 } from "node:os";
|
|
161880
|
+
import { join as join77 } from "node:path";
|
|
161881
|
+
function renderProblems(render, entityId) {
|
|
161882
|
+
const problems = (render.liveErrors ?? []).map((e2) => `${e2.service}: ${e2.message}`);
|
|
161883
|
+
const ofItem = (call) => call.toLowerCase().includes(entityId.toLowerCase());
|
|
161884
|
+
const failed3 = (render.liveFailed ?? []).filter(ofItem);
|
|
161885
|
+
const attempted = (render.liveCalls ?? []).filter(ofItem).length;
|
|
161886
|
+
if (failed3.length > 0 && attempted <= failed3.length) problems.push(`reading the item failed (${failed3[0]}), so the screen could not show it`);
|
|
161887
|
+
return problems;
|
|
161888
|
+
}
|
|
161889
|
+
function workerBundleDir(result, dir) {
|
|
161890
|
+
if (result.compileErrors.length) {
|
|
161891
|
+
const detail = result.compileErrors.map((e2) => `${e2.bundle}: ${e2.errors.map((x2) => x2.text).join("; ")}`).join(" \xB7 ");
|
|
161892
|
+
throw new Error(`the app's screen code does not compile \u2014 fix it first (himi validate): ${detail}`);
|
|
161893
|
+
}
|
|
161894
|
+
return result.built.length > 0 ? dir : void 0;
|
|
161895
|
+
}
|
|
161896
|
+
function createReviewScreenRenderer() {
|
|
161897
|
+
const bundles = /* @__PURE__ */ new Map();
|
|
161898
|
+
let browser;
|
|
161899
|
+
function workerBundles(contentDir2) {
|
|
161900
|
+
let built = bundles.get(contentDir2);
|
|
161901
|
+
if (!built) {
|
|
161902
|
+
built = (async () => {
|
|
161903
|
+
const { buildContentBundles: buildContentBundles2, bundleOutDir: bundleOutDir2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
161904
|
+
return workerBundleDir(await buildContentBundles2(contentDir2, {}), bundleOutDir2(contentDir2));
|
|
161905
|
+
})();
|
|
161906
|
+
bundles.set(contentDir2, built);
|
|
161907
|
+
}
|
|
161908
|
+
return built;
|
|
161909
|
+
}
|
|
161910
|
+
async function launch() {
|
|
161911
|
+
let chromium;
|
|
161912
|
+
try {
|
|
161913
|
+
({ chromium } = await import("playwright"));
|
|
161914
|
+
} catch {
|
|
161915
|
+
throw new Error("taking a screenshot needs Playwright's Chromium: run `npx playwright install chromium`");
|
|
161916
|
+
}
|
|
161917
|
+
return chromium.launch();
|
|
161918
|
+
}
|
|
161919
|
+
return {
|
|
161920
|
+
async render({ contentDir: contentDir2, screenId, input, host, entityId }) {
|
|
161921
|
+
const { buildReleaseFromContent: buildReleaseFromContent2 } = await Promise.resolve().then(() => (init_build3(), build_exports2));
|
|
161922
|
+
const tier5Dir = await workerBundles(contentDir2);
|
|
161923
|
+
const out2 = mkdtempSync4(join77(tmpdir5(), "himi-iap-shot-"));
|
|
161924
|
+
try {
|
|
161925
|
+
const outcome = await buildReleaseFromContent2(contentDir2, out2, {
|
|
161926
|
+
...tier5Dir ? { tier5Dir } : {},
|
|
161927
|
+
collect: { render: { screenId, scheme: "light", png: false, hydrate: true, live: true, dumpState: true, width: REVIEW_SCREENSHOT_FRAME.width, host, ...input ? { input } : {} } }
|
|
161928
|
+
});
|
|
161929
|
+
const render = (outcome.renders ?? [])[0];
|
|
161930
|
+
if (!render) throw new MissingScreenError(screenId);
|
|
161931
|
+
if (!render.renderable || !render.html) throw new Error(render.reason ?? `${screenId} is not an SDUI screen`);
|
|
161932
|
+
return { html: render.html, problems: renderProblems(render, entityId), state: render.serviceState ?? {} };
|
|
161933
|
+
} finally {
|
|
161934
|
+
rmSync18(out2, { recursive: true, force: true });
|
|
161935
|
+
}
|
|
161936
|
+
},
|
|
161937
|
+
async capture(html, contentDir2) {
|
|
161938
|
+
const { pngPageHtml: pngPageHtml2, stabilizePngPage: stabilizePngPage2 } = await Promise.resolve().then(() => (init_render_descriptor(), render_descriptor_exports));
|
|
161939
|
+
const tokensPath = join77(contentDir2, "tokens.json");
|
|
161940
|
+
const tokens2 = existsSync75(tokensPath) ? JSON.parse(readFileSync91(tokensPath, "utf8")) : null;
|
|
161941
|
+
const { width, height, scale } = REVIEW_SCREENSHOT_FRAME;
|
|
161942
|
+
const page = await (await (browser ??= launch())).newPage({ viewport: { width, height }, deviceScaleFactor: scale, colorScheme: "light" });
|
|
161943
|
+
try {
|
|
161944
|
+
await page.setContent(await pngPageHtml2({ html, tokens: tokens2, hasStickyFooter: true }), { waitUntil: "load" });
|
|
161945
|
+
await stabilizePngPage2(page, "light");
|
|
161946
|
+
await page.evaluate(FILL_PAGE_WITH_SCREEN_BACKGROUND);
|
|
161947
|
+
return new Uint8Array(await page.screenshot({ fullPage: false }));
|
|
161948
|
+
} finally {
|
|
161949
|
+
await page.close().catch(() => {
|
|
161950
|
+
});
|
|
161951
|
+
}
|
|
161952
|
+
},
|
|
161953
|
+
async close() {
|
|
161954
|
+
if (browser) await (await browser.catch(() => void 0))?.close().catch(() => {
|
|
161955
|
+
});
|
|
161956
|
+
}
|
|
161957
|
+
};
|
|
161958
|
+
}
|
|
161959
|
+
var FILL_PAGE_WITH_SCREEN_BACKGROUND;
|
|
161960
|
+
var init_store_iap_screenshot_render = __esm({
|
|
161961
|
+
"src/store-iap-screenshot-render.ts"() {
|
|
161962
|
+
init_store_iap_screenshots();
|
|
161963
|
+
FILL_PAGE_WITH_SCREEN_BACKGROUND = `(() => {
|
|
161964
|
+
const root = [...document.body.children].find((el) => el.tagName !== "STYLE");
|
|
161965
|
+
if (!root) return;
|
|
161966
|
+
const style = getComputedStyle(root);
|
|
161967
|
+
for (const el of [document.documentElement, document.body]) {
|
|
161968
|
+
el.style.backgroundColor = style.backgroundColor;
|
|
161969
|
+
el.style.backgroundImage = style.backgroundImage;
|
|
161970
|
+
}
|
|
161971
|
+
})()`;
|
|
161972
|
+
}
|
|
161973
|
+
});
|
|
161974
|
+
|
|
161300
161975
|
// src/serve-preview.ts
|
|
161301
161976
|
function parsePreviewTag(value) {
|
|
161302
161977
|
if (value === void 0 || value === "") return void 0;
|
|
@@ -161338,9 +162013,9 @@ __export(store_iap_exports, {
|
|
|
161338
162013
|
runStoreIap: () => runStoreIap
|
|
161339
162014
|
});
|
|
161340
162015
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
161341
|
-
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync34, readFileSync as
|
|
162016
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync34, readFileSync as readFileSync92, realpathSync as realpathSync13, renameSync as renameSync12, rmSync as rmSync19, writeFileSync as writeFileSync30 } from "node:fs";
|
|
161342
162017
|
import { homedir as homedir11, hostname } from "node:os";
|
|
161343
|
-
import { join as
|
|
162018
|
+
import { dirname as dirname41, join as join78, resolve as resolve57 } from "node:path";
|
|
161344
162019
|
function scrubDeep(value, scrub) {
|
|
161345
162020
|
if (typeof value === "string") return scrub(value);
|
|
161346
162021
|
if (Array.isArray(value)) return value.map((v2) => scrubDeep(v2, scrub));
|
|
@@ -161348,7 +162023,7 @@ function scrubDeep(value, scrub) {
|
|
|
161348
162023
|
return value;
|
|
161349
162024
|
}
|
|
161350
162025
|
function failFrom(error, out2) {
|
|
161351
|
-
if (error instanceof IapManifestError) return out2.fail(`${error.label} is not a valid IAP manifest`, { problems: error.problems });
|
|
162026
|
+
if (error instanceof IapManifestError) return out2.fail(`${error.label} is not a valid IAP manifest`, { code: "manifest_invalid", problems: error.problems });
|
|
161352
162027
|
if (error instanceof IapProvisionError) return out2.fail(error.message, { code: error.reason, reason: error.reason }, error.reason === "drift" ? 1 : 2);
|
|
161353
162028
|
return out2.fail(error instanceof Error ? error.message : String(error));
|
|
161354
162029
|
}
|
|
@@ -161371,6 +162046,9 @@ function readInput(deps, path2, what) {
|
|
|
161371
162046
|
function readManifest2(deps, path2) {
|
|
161372
162047
|
return parseIapManifest(readInput(deps, path2, "manifest"), path2);
|
|
161373
162048
|
}
|
|
162049
|
+
function manifestDirOf(manifestPath) {
|
|
162050
|
+
return dirname41(resolve57(manifestPath));
|
|
162051
|
+
}
|
|
161374
162052
|
function readPlan(deps, path2) {
|
|
161375
162053
|
const text9 = readInput(deps, path2, "plan");
|
|
161376
162054
|
try {
|
|
@@ -161396,7 +162074,7 @@ function openSession(deps, out2, target, profile) {
|
|
|
161396
162074
|
const identity = { profile: creds.profile, team: creds.team, fingerprint: creds.fingerprint };
|
|
161397
162075
|
const api2 = deps.createApi(creds.key);
|
|
161398
162076
|
const journal2 = deps.openJournal(target.appleAppId);
|
|
161399
|
-
return { identity, api: api2, journal: journal2, planContext: { api: api2, identity, now: deps.now } };
|
|
162077
|
+
return { identity, api: api2, journal: journal2, planContext: { api: api2, identity, now: deps.now, readBytes: deps.readBytes } };
|
|
161400
162078
|
}
|
|
161401
162079
|
function printHeader(out2, identity, target) {
|
|
161402
162080
|
out2.line(` ${pad("account")}profile "${identity.profile}" \xB7 team ${identity.team} \xB7 key ${identity.fingerprint}`);
|
|
@@ -161465,6 +162143,7 @@ function printItemResult(out2, item) {
|
|
|
161465
162143
|
out2.line(` price drift: Wix ${wix} \xB7 Apple ${apple} \xB7 target ${wouldBe} ${currency} in ${baseTerritory}`);
|
|
161466
162144
|
}
|
|
161467
162145
|
for (const step of provisioning.steps.filter((s2) => s2.detail)) out2.line(` ${step.kind}${step.locale ? ` ${step.locale}` : ""} ${step.state}: ${step.detail}`);
|
|
162146
|
+
if (provisioning.reviewScreenshot?.observed) out2.line(` review screenshot: ${provisioning.reviewScreenshot.observed.fileName} ${provisioning.reviewScreenshot.observed.state}`);
|
|
161468
162147
|
for (const conflict of provisioning.conflicts) out2.line(` conflict: ${conflict}`);
|
|
161469
162148
|
for (const unmet of provisioning.unmet) out2.line(` unmet: ${unmet}`);
|
|
161470
162149
|
for (const remaining of provisioning.remainingRequirements) out2.line(` remaining: ${remaining}`);
|
|
@@ -161494,7 +162173,7 @@ async function planCommand(flags, deps, out2) {
|
|
|
161494
162173
|
const planPath = requireFlag(flags, "out", "plan");
|
|
161495
162174
|
const manifest = readManifest2(deps, manifestPath);
|
|
161496
162175
|
const session = openSession(deps, out2, manifest.target, profile);
|
|
161497
|
-
const plan = await planIap(manifest, session.planContext);
|
|
162176
|
+
const plan = await planIap(manifest, { ...session.planContext, manifestDir: manifestDirOf(manifestPath) });
|
|
161498
162177
|
writePlan(deps, out2, planPath, plan);
|
|
161499
162178
|
const summary2 = plan.items.map((i2) => ({ productId: i2.productId, decision: i2.decision, ops: i2.ops.length, conflicts: i2.conflicts }));
|
|
161500
162179
|
if (out2.json) out2.print({ ok: true, plan: planPath, items: summary2 });
|
|
@@ -161510,7 +162189,7 @@ function createLimit(flags) {
|
|
|
161510
162189
|
async function applyWithLock(deps, plan, session, limit) {
|
|
161511
162190
|
const release2 = deps.acquireLock(plan.target.appleAppId);
|
|
161512
162191
|
try {
|
|
161513
|
-
const context = {
|
|
162192
|
+
const context = { ...session.planContext, sleep: deps.sleep, journal: session.journal };
|
|
161514
162193
|
return await applyIap(plan, limit === void 0 ? context : { ...context, createLimit: limit });
|
|
161515
162194
|
} finally {
|
|
161516
162195
|
release2();
|
|
@@ -161556,7 +162235,7 @@ async function statusCommand(flags, deps, out2) {
|
|
|
161556
162235
|
return out2.fail("could not read the current Wix catalog \u2014 check owner authentication and site access; no manifest fallback was used", { ok: false, code: "wix_catalog_unavailable" });
|
|
161557
162236
|
}
|
|
161558
162237
|
}
|
|
161559
|
-
const result = await statusIap(manifest, session.planContext, catalog3?.items);
|
|
162238
|
+
const result = await statusIap(manifest, { ...session.planContext, manifestDir: manifestDirOf(manifestPath) }, catalog3?.items);
|
|
161560
162239
|
if (resultPath) writeJson(deps, out2, resultPath, result);
|
|
161561
162240
|
const code = result.complete ? void 0 : result.items.some((i2) => i2.provisioning.priceCheckIssue) ? "price_check_unavailable" : result.items.some((i2) => i2.provisioning.priceDrift) ? "price_drift" : "status_incomplete";
|
|
161562
162241
|
if (out2.json) out2.print({ ok: result.complete, ...code ? { code } : {}, result });
|
|
@@ -161796,6 +162475,71 @@ async function connectWith(flags, deps, out2) {
|
|
|
161796
162475
|
}
|
|
161797
162476
|
return code ? 1 : 0;
|
|
161798
162477
|
}
|
|
162478
|
+
async function appleFacts(flags, deps, out2, manifest) {
|
|
162479
|
+
const profile = textFlag(flags, "profile");
|
|
162480
|
+
if (!profile) return /* @__PURE__ */ new Map();
|
|
162481
|
+
const session = openSession(deps, out2, manifest.target, profile);
|
|
162482
|
+
const unscreenshotted = { ...manifest, items: manifest.items.map(({ reviewScreenshot: _shot, ...item }) => item) };
|
|
162483
|
+
const plans = await planItems(session.planContext, unscreenshotted);
|
|
162484
|
+
return new Map(plans.flatMap((plan, i2) => {
|
|
162485
|
+
const observed = plan.observed;
|
|
162486
|
+
if (!observed) return [];
|
|
162487
|
+
const base = observed.price?.baseTerritory === manifest.items[i2].price.baseTerritory && observed.price.customerPrices.length === 1;
|
|
162488
|
+
return [[plan.productId, { ...base ? { price: observed.price.customerPrices[0] } : {}, ...isLocked(observed) ? { locked: observed.state } : {} }]];
|
|
162489
|
+
}));
|
|
162490
|
+
}
|
|
162491
|
+
function printScreenshots(out2, report3, manifestPath, dryRun) {
|
|
162492
|
+
for (const item of report3.items) {
|
|
162493
|
+
if (item.skipped) out2.line(` \u2717 ${item.productId} ${item.skipped}`);
|
|
162494
|
+
else if (dryRun) out2.line(` \xB7 ${item.productId} would render ${item.screenId} at ${item.price}`);
|
|
162495
|
+
else out2.line(` \u2713 ${item.productId} ${item.screenshot} (${item.screenId}, ${item.price})`);
|
|
162496
|
+
}
|
|
162497
|
+
out2.line();
|
|
162498
|
+
if (dryRun) out2.line(" dry run \u2014 nothing was rendered or written.");
|
|
162499
|
+
else if (report3.items.some((i2) => i2.screenshot)) out2.line(` manifest updated: ${manifestPath} \u2014 next: himi store iap plan --manifest ${manifestPath} \u2026 uploads them.`);
|
|
162500
|
+
}
|
|
162501
|
+
async function screenshotsCommand(flags, deps, out2) {
|
|
162502
|
+
const manifestPath = requireFlag(flags, "manifest", "screenshots");
|
|
162503
|
+
const contentDir2 = requireFlag(flags, "content", "screenshots");
|
|
162504
|
+
const manifestText = readInput(deps, manifestPath, "manifest");
|
|
162505
|
+
const manifest = parseIapManifest(manifestText, manifestPath);
|
|
162506
|
+
const facts = await appleFacts(flags, deps, out2, manifest);
|
|
162507
|
+
const renderer = (deps.reviewScreenRenderer ?? createReviewScreenRenderer)();
|
|
162508
|
+
const only = textFlag(flags, "only");
|
|
162509
|
+
const outDir = textFlag(flags, "out-dir");
|
|
162510
|
+
const dryRun = flags["dry-run"] === true;
|
|
162511
|
+
let report3;
|
|
162512
|
+
try {
|
|
162513
|
+
report3 = await takeReviewScreenshots({
|
|
162514
|
+
manifest,
|
|
162515
|
+
manifestPath,
|
|
162516
|
+
manifestText,
|
|
162517
|
+
contentDir: contentDir2,
|
|
162518
|
+
renderer,
|
|
162519
|
+
applePrice: (item) => facts.get(item.productId)?.price,
|
|
162520
|
+
appleLocked: (item) => facts.get(item.productId)?.locked,
|
|
162521
|
+
appleRead: textFlag(flags, "profile") !== void 0,
|
|
162522
|
+
writeBytes: deps.writeBytes ?? writeBinaryFile,
|
|
162523
|
+
writeText: (path2, text9) => deps.writeFileAtomic(path2, text9),
|
|
162524
|
+
...only ? { only: new Set(only.split(",").map((id) => id.trim()).filter(Boolean)) } : {},
|
|
162525
|
+
...outDir ? { outDir: resolve57(outDir) } : {},
|
|
162526
|
+
force: flags.force === true,
|
|
162527
|
+
dryRun
|
|
162528
|
+
});
|
|
162529
|
+
} finally {
|
|
162530
|
+
await renderer.close?.();
|
|
162531
|
+
}
|
|
162532
|
+
const code = report3.complete ? void 0 : "screenshots_incomplete";
|
|
162533
|
+
if (out2.json) out2.print({ ok: report3.complete, ...code ? { code } : {}, manifest: manifestPath, items: report3.items });
|
|
162534
|
+
else printScreenshots(out2, report3, manifestPath, dryRun);
|
|
162535
|
+
return report3.complete ? 0 : 1;
|
|
162536
|
+
}
|
|
162537
|
+
function writeBinaryFile(path2, bytes2) {
|
|
162538
|
+
mkdirSync34(dirname41(path2), { recursive: true });
|
|
162539
|
+
const partial = `${path2}.${process.pid}.partial`;
|
|
162540
|
+
writeFileSync30(partial, bytes2);
|
|
162541
|
+
renameSync12(partial, path2);
|
|
162542
|
+
}
|
|
161799
162543
|
async function runStoreIap(pos, flags, io2, deps) {
|
|
161800
162544
|
const out2 = new CommandOutput(io2, flags.json === true);
|
|
161801
162545
|
const sub = pos[2];
|
|
@@ -161816,14 +162560,14 @@ function fileJournal(path2) {
|
|
|
161816
162560
|
}
|
|
161817
162561
|
function readLockSummary(path2) {
|
|
161818
162562
|
try {
|
|
161819
|
-
const { pid, host, at: at2 } = JSON.parse(
|
|
162563
|
+
const { pid, host, at: at2 } = JSON.parse(readFileSync92(path2, "utf8"));
|
|
161820
162564
|
return `pid ${pid} on ${host} since ${at2}`;
|
|
161821
162565
|
} catch {
|
|
161822
162566
|
return "unreadable lock";
|
|
161823
162567
|
}
|
|
161824
162568
|
}
|
|
161825
162569
|
function acquireApplyLock(dir, appleAppId) {
|
|
161826
|
-
const path2 =
|
|
162570
|
+
const path2 = join78(dir, "apply.lock");
|
|
161827
162571
|
const stamp = JSON.stringify({ pid: process.pid, host: hostname(), at: (/* @__PURE__ */ new Date()).toISOString(), token: randomUUID8() });
|
|
161828
162572
|
try {
|
|
161829
162573
|
writeFileSync30(path2, stamp, { flag: "wx", mode: 384 });
|
|
@@ -161836,15 +162580,15 @@ function acquireApplyLock(dir, appleAppId) {
|
|
|
161836
162580
|
return () => {
|
|
161837
162581
|
let current = "";
|
|
161838
162582
|
try {
|
|
161839
|
-
current =
|
|
162583
|
+
current = readFileSync92(path2, "utf8");
|
|
161840
162584
|
} catch {
|
|
161841
162585
|
return;
|
|
161842
162586
|
}
|
|
161843
|
-
if (current === stamp)
|
|
162587
|
+
if (current === stamp) rmSync19(path2, { force: true });
|
|
161844
162588
|
};
|
|
161845
162589
|
}
|
|
161846
162590
|
function stateDir(appleAppId) {
|
|
161847
|
-
const dir =
|
|
162591
|
+
const dir = join78(homedir11(), ".himalaya", "store-iap", appleAppId);
|
|
161848
162592
|
mkdirSync34(dir, { recursive: true, mode: 448 });
|
|
161849
162593
|
return dir;
|
|
161850
162594
|
}
|
|
@@ -161860,11 +162604,12 @@ async function confirmOnTerminal(question) {
|
|
|
161860
162604
|
}
|
|
161861
162605
|
function defaultStoreIapDeps() {
|
|
161862
162606
|
return {
|
|
161863
|
-
readFile: (path2) =>
|
|
162607
|
+
readFile: (path2) => readFileSync92(path2, "utf8"),
|
|
162608
|
+
readBytes: (path2) => readFileSync92(path2),
|
|
161864
162609
|
writeFileAtomic,
|
|
161865
162610
|
resolveCredentials: ({ profileFlag, target }) => resolveIapCredentials({ profileFlag, target }),
|
|
161866
162611
|
createApi: (key2) => createIapApi(createAscClient({ key: key2 })),
|
|
161867
|
-
openJournal: (appleAppId) => fileJournal(
|
|
162612
|
+
openJournal: (appleAppId) => fileJournal(join78(stateDir(appleAppId), "journal.jsonl")),
|
|
161868
162613
|
acquireLock: (appleAppId) => acquireApplyLock(stateDir(appleAppId), appleAppId),
|
|
161869
162614
|
canPrompt: () => process.stdin.isTTY === true,
|
|
161870
162615
|
wixTransport: (siteId) => ownerTransport(siteId),
|
|
@@ -161875,7 +162620,7 @@ function defaultStoreIapDeps() {
|
|
|
161875
162620
|
profileTeam: (profile) => resolveStoreCredentials({ app: profile, cfg: {}, profileFlag: profile, env: {} }).team,
|
|
161876
162621
|
confirm: confirmOnTerminal,
|
|
161877
162622
|
now: () => /* @__PURE__ */ new Date(),
|
|
161878
|
-
sleep: (ms2) => new Promise((
|
|
162623
|
+
sleep: (ms2) => new Promise((resolve65) => setTimeout(resolve65, ms2))
|
|
161879
162624
|
};
|
|
161880
162625
|
}
|
|
161881
162626
|
var STORE_IAP_USAGE, SUMMARY_THRESHOLD, SUMMARY_DETAIL_LIMIT, UsageError, CommandOutput, pad, DECISION_ORDER, OUTCOME_ORDER, COMPLETE, DRAFT_MODES, TERRITORY_CODE, LOCALE_CODE, GRID_UNAVAILABLE_NOTE, KeyError, CredentialsError, writesPlanned, COMMANDS;
|
|
@@ -161897,10 +162642,12 @@ var init_store_iap = __esm({
|
|
|
161897
162642
|
init_iap_config_edit();
|
|
161898
162643
|
init_store_iap_catalog();
|
|
161899
162644
|
init_store_iap_connect();
|
|
162645
|
+
init_store_iap_screenshots();
|
|
162646
|
+
init_store_iap_screenshot_render();
|
|
161900
162647
|
init_store_iap_purchases();
|
|
161901
162648
|
init_serve_preview();
|
|
161902
162649
|
init_wix_owner();
|
|
161903
|
-
STORE_IAP_USAGE = "himi store iap draft|plan|apply|status|connect \u2014 draft --site <msid> --profile <name> --apple-app <id> --bundle <id> --base-territory <ISO3> --out <manifest.json> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <manifest.json>] [--report <file>] \xB7 plan --manifest <file> --profile <name> --out <plan.json> \xB7 apply --plan <plan.json> --profile <name> --out <result.json> [--yes] [--limit <n>] \xB7 status --manifest <file> --profile <name> [--out <file>] [--refresh-wix] \xB7 connect --manifest <file> --profile <name> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <report.json>]";
|
|
162650
|
+
STORE_IAP_USAGE = "himi store iap draft|plan|apply|status|connect|screenshots \u2014 draft --site <msid> --profile <name> --apple-app <id> --bundle <id> --base-territory <ISO3> --out <manifest.json> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <manifest.json>] [--report <file>] \xB7 plan --manifest <file> --profile <name> --out <plan.json> \xB7 apply --plan <plan.json> --profile <name> --out <result.json> [--yes] [--limit <n>] \xB7 status --manifest <file> --profile <name> [--out <file>] [--refresh-wix] \xB7 connect --manifest <file> --profile <name> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <report.json>] \xB7 screenshots --manifest <file> --content <app dir> [--profile <name>] [--out-dir <dir>] [--only <productId,\u2026>] [--force] [--dry-run]";
|
|
161904
162651
|
SUMMARY_THRESHOLD = 50;
|
|
161905
162652
|
SUMMARY_DETAIL_LIMIT = 20;
|
|
161906
162653
|
UsageError = class extends Error {
|
|
@@ -161961,7 +162708,8 @@ var init_store_iap = __esm({
|
|
|
161961
162708
|
plan: planCommand,
|
|
161962
162709
|
apply: applyCommand,
|
|
161963
162710
|
status: statusCommand,
|
|
161964
|
-
connect: connectCommand
|
|
162711
|
+
connect: connectCommand,
|
|
162712
|
+
screenshots: screenshotsCommand
|
|
161965
162713
|
};
|
|
161966
162714
|
}
|
|
161967
162715
|
});
|
|
@@ -162336,15 +163084,15 @@ __export(preflight_app_exports, {
|
|
|
162336
163084
|
analyzeSubmissionRecord: () => analyzeSubmissionRecord,
|
|
162337
163085
|
appIconState: () => appIconState,
|
|
162338
163086
|
isValidAppStoreSize: () => isValidAppStoreSize,
|
|
162339
|
-
jpegSize: () =>
|
|
163087
|
+
jpegSize: () => jpegSize2,
|
|
162340
163088
|
playListingAssets: () => playListingAssets,
|
|
162341
|
-
pngSize: () =>
|
|
163089
|
+
pngSize: () => pngSize2,
|
|
162342
163090
|
preflightApp: () => preflightApp,
|
|
162343
163091
|
profileAccount: () => profileAccount
|
|
162344
163092
|
});
|
|
162345
|
-
import { readFileSync as
|
|
162346
|
-
import { createHash as
|
|
162347
|
-
import { join as
|
|
163093
|
+
import { readFileSync as readFileSync93, existsSync as existsSync76, readdirSync as readdirSync34, statSync as statSync21 } from "node:fs";
|
|
163094
|
+
import { createHash as createHash41 } from "node:crypto";
|
|
163095
|
+
import { join as join79 } from "node:path";
|
|
162348
163096
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
162349
163097
|
const f2 = [];
|
|
162350
163098
|
const has = (re2, s2) => re2.test(s2);
|
|
@@ -162408,13 +163156,13 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
162408
163156
|
}
|
|
162409
163157
|
}
|
|
162410
163158
|
async function preflightApp(app, opts = {}) {
|
|
162411
|
-
const projectYml =
|
|
162412
|
-
const storeConfig =
|
|
163159
|
+
const projectYml = existsSync76(iosProjectYml(app)) ? readFileSync93(iosProjectYml(app), "utf8") : "";
|
|
163160
|
+
const storeConfig = existsSync76(storeConfigPath(app)) ? readFileSync93(storeConfigPath(app), "utf8") : "";
|
|
162413
163161
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
162414
163162
|
const findings = analyze(
|
|
162415
163163
|
projectYml,
|
|
162416
163164
|
storeConfig,
|
|
162417
|
-
await appIconState(
|
|
163165
|
+
await appIconState(join79(appDir(app), "ios")),
|
|
162418
163166
|
profileAccount(app, storeConfig, opts)
|
|
162419
163167
|
);
|
|
162420
163168
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
@@ -162443,17 +163191,17 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
162443
163191
|
return f2;
|
|
162444
163192
|
}
|
|
162445
163193
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
162446
|
-
const root =
|
|
163194
|
+
const root = join79(storeDir(app), "metadata");
|
|
162447
163195
|
const out2 = /* @__PURE__ */ new Set();
|
|
162448
|
-
if (
|
|
163196
|
+
if (existsSync76(root)) {
|
|
162449
163197
|
for (const n2 of readdirSync34(root)) if (n2.endsWith(".txt")) out2.add(n2);
|
|
162450
163198
|
}
|
|
162451
|
-
if (
|
|
163199
|
+
if (existsSync76(join79(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
|
|
162452
163200
|
return out2;
|
|
162453
163201
|
}
|
|
162454
163202
|
function reviewInfoFiles(app) {
|
|
162455
|
-
const dir =
|
|
162456
|
-
if (!
|
|
163203
|
+
const dir = join79(storeDir(app), "review_information");
|
|
163204
|
+
if (!existsSync76(dir)) return /* @__PURE__ */ new Set();
|
|
162457
163205
|
return new Set(readdirSync34(dir).filter((n2) => n2.endsWith(".txt")));
|
|
162458
163206
|
}
|
|
162459
163207
|
function isValidAppStoreSize(w2, h2) {
|
|
@@ -162462,7 +163210,7 @@ function isValidAppStoreSize(w2, h2) {
|
|
|
162462
163210
|
function isRequired69(w2, h2) {
|
|
162463
163211
|
return w2 === 1320 && h2 === 2868 || w2 === 1290 && h2 === 2796 || w2 === 2868 && h2 === 1320 || w2 === 2796 && h2 === 1290;
|
|
162464
163212
|
}
|
|
162465
|
-
function
|
|
163213
|
+
function pngSize2(buf) {
|
|
162466
163214
|
if (buf.length < 24 || buf.toString("ascii", 12, 16) !== "IHDR") return null;
|
|
162467
163215
|
return { w: buf.readUInt32BE(16), h: buf.readUInt32BE(20) };
|
|
162468
163216
|
}
|
|
@@ -162487,7 +163235,7 @@ function jpegStructure(bytes2) {
|
|
|
162487
163235
|
}
|
|
162488
163236
|
return null;
|
|
162489
163237
|
}
|
|
162490
|
-
function
|
|
163238
|
+
function jpegSize2(buf) {
|
|
162491
163239
|
if (buf.length < 4 || buf[0] !== 255 || buf[1] !== 216) return null;
|
|
162492
163240
|
let at2 = 2;
|
|
162493
163241
|
while (at2 + 9 < buf.length) {
|
|
@@ -162519,7 +163267,7 @@ function analyzePlayListing(assets) {
|
|
|
162519
163267
|
} else {
|
|
162520
163268
|
const { name, bytes: bytes2 } = assets.featureGraphic;
|
|
162521
163269
|
const isPng = bytes2.length > 8 && bytes2.toString("ascii", 1, 4) === "PNG";
|
|
162522
|
-
const size = isPng ?
|
|
163270
|
+
const size = isPng ? pngSize2(bytes2) : jpegSize2(bytes2);
|
|
162523
163271
|
if (!size) {
|
|
162524
163272
|
f2.push({
|
|
162525
163273
|
level: "error",
|
|
@@ -162563,12 +163311,12 @@ function analyzePlayListing(assets) {
|
|
|
162563
163311
|
return f2;
|
|
162564
163312
|
}
|
|
162565
163313
|
function playListingAssets(app, locale = "en-US") {
|
|
162566
|
-
const dir =
|
|
163314
|
+
const dir = join79(storeDir(app), "play", locale, "images");
|
|
162567
163315
|
const read = (names) => {
|
|
162568
163316
|
for (const name of names) {
|
|
162569
|
-
const p2 =
|
|
163317
|
+
const p2 = join79(dir, name);
|
|
162570
163318
|
try {
|
|
162571
|
-
if (statSync21(p2).isFile()) return { name, bytes:
|
|
163319
|
+
if (statSync21(p2).isFile()) return { name, bytes: readFileSync93(p2) };
|
|
162572
163320
|
} catch {
|
|
162573
163321
|
}
|
|
162574
163322
|
}
|
|
@@ -162599,26 +163347,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
162599
163347
|
return f2;
|
|
162600
163348
|
}
|
|
162601
163349
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
162602
|
-
const dir =
|
|
162603
|
-
if (!
|
|
163350
|
+
const dir = join79(storeDir(app), "metadata", locale);
|
|
163351
|
+
if (!existsSync76(dir)) return /* @__PURE__ */ new Set();
|
|
162604
163352
|
return new Set(readdirSync34(dir).filter((n2) => n2.endsWith(".txt")));
|
|
162605
163353
|
}
|
|
162606
163354
|
function listScreenshots(app, locale = "en-US") {
|
|
162607
163355
|
const out2 = [];
|
|
162608
|
-
const flat =
|
|
162609
|
-
if (
|
|
163356
|
+
const flat = join79(storeDir(app), "screenshots", locale);
|
|
163357
|
+
if (existsSync76(flat)) {
|
|
162610
163358
|
for (const png of readdirSync34(flat).filter((n2) => n2.endsWith(".png"))) {
|
|
162611
|
-
const sz =
|
|
163359
|
+
const sz = pngSize2(readFileSync93(join79(flat, png)));
|
|
162612
163360
|
if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
|
|
162613
163361
|
}
|
|
162614
163362
|
}
|
|
162615
|
-
const legacy =
|
|
162616
|
-
if (
|
|
163363
|
+
const legacy = join79(storeDir(app), "metadata", locale, "screenshots");
|
|
163364
|
+
if (existsSync76(legacy)) {
|
|
162617
163365
|
for (const deviceDir of readdirSync34(legacy)) {
|
|
162618
|
-
const d2 =
|
|
163366
|
+
const d2 = join79(legacy, deviceDir);
|
|
162619
163367
|
if (!statSync21(d2).isDirectory()) continue;
|
|
162620
163368
|
for (const png of readdirSync34(d2).filter((n2) => n2.endsWith(".png"))) {
|
|
162621
|
-
const sz =
|
|
163369
|
+
const sz = pngSize2(readFileSync93(join79(d2, png)));
|
|
162622
163370
|
if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
162623
163371
|
}
|
|
162624
163372
|
}
|
|
@@ -162626,13 +163374,13 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
162626
163374
|
return out2;
|
|
162627
163375
|
}
|
|
162628
163376
|
function placeholderHashes2() {
|
|
162629
|
-
const templateIos =
|
|
162630
|
-
if (!
|
|
163377
|
+
const templateIos = join79(appDir("_template"), "ios");
|
|
163378
|
+
if (!existsSync76(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
162631
163379
|
for (const target of readdirSync34(templateIos)) {
|
|
162632
|
-
const p2 =
|
|
163380
|
+
const p2 = join79(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
162633
163381
|
try {
|
|
162634
163382
|
if (!statSync21(p2).isFile()) continue;
|
|
162635
|
-
return [LEGACY_PLACEHOLDER_SHA2562,
|
|
163383
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash41("sha256").update(readFileSync93(p2)).digest("hex")];
|
|
162636
163384
|
} catch {
|
|
162637
163385
|
}
|
|
162638
163386
|
}
|
|
@@ -162663,13 +163411,13 @@ async function pixelIssues(bytes2) {
|
|
|
162663
163411
|
}
|
|
162664
163412
|
}
|
|
162665
163413
|
async function appIconState(iosDir) {
|
|
162666
|
-
if (!
|
|
163414
|
+
if (!existsSync76(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
162667
163415
|
for (const target of readdirSync34(iosDir)) {
|
|
162668
|
-
const p2 =
|
|
163416
|
+
const p2 = join79(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
162669
163417
|
try {
|
|
162670
163418
|
if (!statSync21(p2).isFile()) continue;
|
|
162671
|
-
const bytes2 =
|
|
162672
|
-
const hash2 =
|
|
163419
|
+
const bytes2 = readFileSync93(p2);
|
|
163420
|
+
const hash2 = createHash41("sha256").update(bytes2).digest("hex");
|
|
162673
163421
|
const pixels = await pixelIssues(bytes2);
|
|
162674
163422
|
return {
|
|
162675
163423
|
exists: true,
|
|
@@ -162735,7 +163483,7 @@ __export(asc_status_exports, {
|
|
|
162735
163483
|
ascStatus: () => ascStatus,
|
|
162736
163484
|
buildVerdict: () => buildVerdict
|
|
162737
163485
|
});
|
|
162738
|
-
import { readFileSync as
|
|
163486
|
+
import { readFileSync as readFileSync94 } from "node:fs";
|
|
162739
163487
|
function buildVerdict(builds) {
|
|
162740
163488
|
if (!builds.length) {
|
|
162741
163489
|
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).";
|
|
@@ -162749,7 +163497,7 @@ function buildVerdict(builds) {
|
|
|
162749
163497
|
function client(creds) {
|
|
162750
163498
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
162751
163499
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
162752
|
-
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID,
|
|
163500
|
+
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync94(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
162753
163501
|
return async (path2) => {
|
|
162754
163502
|
const r2 = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
162755
163503
|
return { status: r2.status, json: await r2.json().catch(() => ({})) };
|
|
@@ -162903,7 +163651,7 @@ var init_connector_token = __esm({
|
|
|
162903
163651
|
// ../../core/functions-secrets/src/vault.ts
|
|
162904
163652
|
import { createCipheriv, createDecipheriv as createDecipheriv2, randomBytes as randomBytes6 } from "node:crypto";
|
|
162905
163653
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
162906
|
-
import { dirname as
|
|
163654
|
+
import { dirname as dirname42 } from "node:path";
|
|
162907
163655
|
function createJsonSecretStore(filePath) {
|
|
162908
163656
|
const read = async () => {
|
|
162909
163657
|
try {
|
|
@@ -162916,7 +163664,7 @@ function createJsonSecretStore(filePath) {
|
|
|
162916
163664
|
}
|
|
162917
163665
|
};
|
|
162918
163666
|
const write2 = async (records) => {
|
|
162919
|
-
await mkdir(
|
|
163667
|
+
await mkdir(dirname42(filePath), { recursive: true });
|
|
162920
163668
|
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
162921
163669
|
await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
|
|
162922
163670
|
`, { mode: 384 });
|
|
@@ -163014,7 +163762,7 @@ __export(secrets_exports, {
|
|
|
163014
163762
|
runRemoteSecretsCommand: () => runRemoteSecretsCommand,
|
|
163015
163763
|
runSecretsCommand: () => runSecretsCommand
|
|
163016
163764
|
});
|
|
163017
|
-
import { readFileSync as
|
|
163765
|
+
import { readFileSync as readFileSync95 } from "node:fs";
|
|
163018
163766
|
function environment(value) {
|
|
163019
163767
|
if (value === "preview" || value === "production") return value;
|
|
163020
163768
|
throw new Error("--environment must be preview or production");
|
|
@@ -163045,7 +163793,7 @@ async function runSecretsCommand(operation, flags, io2, options = {}) {
|
|
|
163045
163793
|
io2.log(JSON.stringify(await vault.list({ app, environment: env })));
|
|
163046
163794
|
return 0;
|
|
163047
163795
|
}
|
|
163048
|
-
const value = options.readValue ? options.readValue() :
|
|
163796
|
+
const value = options.readValue ? options.readValue() : readFileSync95(0, "utf8").replace(/\r?\n$/, "");
|
|
163049
163797
|
if (operation === "set") await vault.set({ app, environment: env, name, value });
|
|
163050
163798
|
else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
|
|
163051
163799
|
else throw new Error(`unknown secrets operation ${operation}`);
|
|
@@ -163074,7 +163822,7 @@ async function runRemoteSecretsCommand(operation, flags, io2, options) {
|
|
|
163074
163822
|
}
|
|
163075
163823
|
let body;
|
|
163076
163824
|
if (operation !== "list") {
|
|
163077
|
-
const value = options.readValue ? options.readValue() :
|
|
163825
|
+
const value = options.readValue ? options.readValue() : readFileSync95(0, "utf8").replace(/\r?\n$/, "");
|
|
163078
163826
|
body = JSON.stringify({ value });
|
|
163079
163827
|
}
|
|
163080
163828
|
const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
|
|
@@ -163268,7 +164016,7 @@ var init_site_member = __esm({
|
|
|
163268
164016
|
});
|
|
163269
164017
|
|
|
163270
164018
|
// src/notify-ping-all.ts
|
|
163271
|
-
import { createHash as
|
|
164019
|
+
import { createHash as createHash42 } from "node:crypto";
|
|
163272
164020
|
async function listApprovedMembers(input) {
|
|
163273
164021
|
const first = await scanMembers(input);
|
|
163274
164022
|
const second = await scanMembers(input);
|
|
@@ -163322,7 +164070,7 @@ async function scanMembers(input) {
|
|
|
163322
164070
|
}
|
|
163323
164071
|
}
|
|
163324
164072
|
function campaignRequestId(campaignId, memberId) {
|
|
163325
|
-
const bytes2 =
|
|
164073
|
+
const bytes2 = createHash42("sha256").update(JSON.stringify(["himi-push-campaign", campaignId, memberId])).digest().subarray(0, 16);
|
|
163326
164074
|
bytes2[6] = bytes2[6] & 15 | 80;
|
|
163327
164075
|
bytes2[8] = bytes2[8] & 63 | 128;
|
|
163328
164076
|
const hex2 = bytes2.toString("hex");
|
|
@@ -163372,7 +164120,7 @@ __export(notify_ping_exports, {
|
|
|
163372
164120
|
runNotifyPing: () => runNotifyPing
|
|
163373
164121
|
});
|
|
163374
164122
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
163375
|
-
import { resolve as
|
|
164123
|
+
import { resolve as resolve58 } from "node:path";
|
|
163376
164124
|
function refuse6(io2, error, hint, exit = 2, extra = {}) {
|
|
163377
164125
|
io2.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
|
|
163378
164126
|
return exit;
|
|
@@ -163383,7 +164131,7 @@ async function runNotifyPing(flags, io2, deps = {}) {
|
|
|
163383
164131
|
const allMembers = flags["all-members"] === true;
|
|
163384
164132
|
if (allMembers && text8(flags["member-email"])) return refuse6(io2, "recipient_conflict", "Choose --all-members or --member-email.");
|
|
163385
164133
|
if (allMembers && flags["dry-run"] !== true && flags.yes !== true) return refuse6(io2, "confirmation_required", "Preview with --dry-run, then add --yes to send to every approved member.");
|
|
163386
|
-
const input = mergePushInputs(pushInputsFromContent(
|
|
164134
|
+
const input = mergePushInputs(pushInputsFromContent(resolve58(text8(flags.content) ?? process.cwd())), flags);
|
|
163387
164135
|
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f2) => !(allMembers && f2 === "member-email") && !text8(flags[f2]))];
|
|
163388
164136
|
if (missing.length) return refuse6(io2, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
|
|
163389
164137
|
const requestId2 = text8(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID9)();
|
|
@@ -163469,7 +164217,7 @@ async function runAllMembers(args) {
|
|
|
163469
164217
|
const result = await sendCampaign({
|
|
163470
164218
|
recipients,
|
|
163471
164219
|
campaignId: requestId2,
|
|
163472
|
-
wait: deps.wait ?? ((ms2) => new Promise((
|
|
164220
|
+
wait: deps.wait ?? ((ms2) => new Promise((resolve65) => setTimeout(resolve65, ms2))),
|
|
163473
164221
|
onProgress: (completed) => {
|
|
163474
164222
|
if (completed % 10 === 0 || completed === recipients.length) {
|
|
163475
164223
|
io2.log(JSON.stringify({ ok: true, state: "progress", campaignId: requestId2, completed, recipients: recipients.length }));
|
|
@@ -163572,15 +164320,15 @@ __export(notify_exports, {
|
|
|
163572
164320
|
runNotify: () => runNotify,
|
|
163573
164321
|
saveAdminSession: () => saveAdminSession
|
|
163574
164322
|
});
|
|
163575
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync35, readFileSync as
|
|
164323
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync35, readFileSync as readFileSync96, writeFileSync as writeFileSync31 } from "node:fs";
|
|
163576
164324
|
import { homedir as homedir12 } from "node:os";
|
|
163577
|
-
import { dirname as
|
|
164325
|
+
import { dirname as dirname43, join as join80 } from "node:path";
|
|
163578
164326
|
function defaultSessionsPath() {
|
|
163579
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
164327
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join80(homedir12(), ".himalaya", "admin-sessions.json");
|
|
163580
164328
|
}
|
|
163581
164329
|
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
163582
164330
|
try {
|
|
163583
|
-
return JSON.parse(
|
|
164331
|
+
return JSON.parse(readFileSync96(path2, "utf8"));
|
|
163584
164332
|
} catch {
|
|
163585
164333
|
return {};
|
|
163586
164334
|
}
|
|
@@ -163588,10 +164336,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
|
163588
164336
|
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
163589
164337
|
const file2 = loadSessionsFile(path2);
|
|
163590
164338
|
file2.sessions = { ...file2.sessions, [adminUrl]: session };
|
|
163591
|
-
mkdirSync35(
|
|
164339
|
+
mkdirSync35(dirname43(path2), { recursive: true, mode: 448 });
|
|
163592
164340
|
writeFileSync31(path2, JSON.stringify(file2, null, 2) + "\n", { mode: 384 });
|
|
163593
164341
|
try {
|
|
163594
|
-
chmodSync3(
|
|
164342
|
+
chmodSync3(dirname43(path2), 448);
|
|
163595
164343
|
chmodSync3(path2, 384);
|
|
163596
164344
|
} catch {
|
|
163597
164345
|
}
|
|
@@ -163957,20 +164705,20 @@ __export(base44_auth_exports, {
|
|
|
163957
164705
|
usableBase44Auth: () => usableBase44Auth,
|
|
163958
164706
|
writeBase44Session: () => writeBase44Session
|
|
163959
164707
|
});
|
|
163960
|
-
import { chmodSync as chmodSync4, existsSync as
|
|
164708
|
+
import { chmodSync as chmodSync4, existsSync as existsSync77, mkdirSync as mkdirSync36, readFileSync as readFileSync97, rmSync as rmSync20, writeFileSync as writeFileSync32 } from "node:fs";
|
|
163961
164709
|
import { homedir as homedir13 } from "node:os";
|
|
163962
|
-
import { dirname as
|
|
164710
|
+
import { dirname as dirname44, join as join81 } from "node:path";
|
|
163963
164711
|
function base44ApiBase(env = process.env) {
|
|
163964
164712
|
return (env.BASE44_API_URL?.trim() || "https://app.base44.com").replace(/\/+$/, "");
|
|
163965
164713
|
}
|
|
163966
164714
|
function base44SessionPath(home = homedir13()) {
|
|
163967
|
-
return
|
|
164715
|
+
return join81(home, ".himi", "base44", "session.json");
|
|
163968
164716
|
}
|
|
163969
164717
|
function readBase44Session(home) {
|
|
163970
164718
|
const p2 = base44SessionPath(home);
|
|
163971
|
-
if (!
|
|
164719
|
+
if (!existsSync77(p2)) return void 0;
|
|
163972
164720
|
try {
|
|
163973
|
-
const s2 = JSON.parse(
|
|
164721
|
+
const s2 = JSON.parse(readFileSync97(p2, "utf8"));
|
|
163974
164722
|
return typeof s2.accessToken === "string" && s2.accessToken ? s2 : void 0;
|
|
163975
164723
|
} catch {
|
|
163976
164724
|
return void 0;
|
|
@@ -163978,7 +164726,7 @@ function readBase44Session(home) {
|
|
|
163978
164726
|
}
|
|
163979
164727
|
function writeBase44Session(session, home) {
|
|
163980
164728
|
const p2 = base44SessionPath(home);
|
|
163981
|
-
mkdirSync36(
|
|
164729
|
+
mkdirSync36(dirname44(p2), { recursive: true, mode: 448 });
|
|
163982
164730
|
writeFileSync32(p2, `${JSON.stringify(session, null, 2)}
|
|
163983
164731
|
`, { mode: 384 });
|
|
163984
164732
|
chmodSync4(p2, 384);
|
|
@@ -163986,8 +164734,8 @@ function writeBase44Session(session, home) {
|
|
|
163986
164734
|
}
|
|
163987
164735
|
function deleteBase44Session(home) {
|
|
163988
164736
|
const p2 = base44SessionPath(home);
|
|
163989
|
-
if (!
|
|
163990
|
-
|
|
164737
|
+
if (!existsSync77(p2)) return false;
|
|
164738
|
+
rmSync20(p2, { force: true });
|
|
163991
164739
|
return true;
|
|
163992
164740
|
}
|
|
163993
164741
|
function jwtClaims(token) {
|
|
@@ -164081,9 +164829,9 @@ async function base44DeviceLogin(opts) {
|
|
|
164081
164829
|
throw new Error("the Base44 sign-in code expired before it was approved \u2014 run `himi base44 login` again");
|
|
164082
164830
|
}
|
|
164083
164831
|
function importBase44CliSession(home = homedir13(), env = process.env) {
|
|
164084
|
-
const src =
|
|
164085
|
-
if (!
|
|
164086
|
-
const a2 = JSON.parse(
|
|
164832
|
+
const src = join81(home, ".base44", "auth", "auth.json");
|
|
164833
|
+
if (!existsSync77(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
|
|
164834
|
+
const a2 = JSON.parse(readFileSync97(src, "utf8"));
|
|
164087
164835
|
if (typeof a2.accessToken !== "string" || !a2.accessToken) throw new Error(`${src} holds no access token`);
|
|
164088
164836
|
const session = {
|
|
164089
164837
|
accessToken: a2.accessToken,
|
|
@@ -164254,10 +165002,10 @@ function assertPublicSiteUrl(raw) {
|
|
|
164254
165002
|
if (refusal) throw new Error(refusal);
|
|
164255
165003
|
}
|
|
164256
165004
|
function resolveAll(hostname3) {
|
|
164257
|
-
return new Promise((
|
|
165005
|
+
return new Promise((resolve65, reject) => {
|
|
164258
165006
|
dnsLookup(hostname3, { all: true, verbatim: true }, (err, addresses) => {
|
|
164259
165007
|
if (err) reject(err);
|
|
164260
|
-
else
|
|
165008
|
+
else resolve65(addresses);
|
|
164261
165009
|
});
|
|
164262
165010
|
});
|
|
164263
165011
|
}
|
|
@@ -164265,13 +165013,13 @@ function withAbort(start, signal, what) {
|
|
|
164265
165013
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
164266
165014
|
const work = start();
|
|
164267
165015
|
if (!signal) return work;
|
|
164268
|
-
return new Promise((
|
|
165016
|
+
return new Promise((resolve65, reject) => {
|
|
164269
165017
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
164270
165018
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
164271
|
-
work.then(
|
|
165019
|
+
work.then(resolve65, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
164272
165020
|
});
|
|
164273
165021
|
}
|
|
164274
|
-
async function pinAddress(url,
|
|
165022
|
+
async function pinAddress(url, resolve65 = resolveAll, signal) {
|
|
164275
165023
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
164276
165024
|
if (ipv4Octets(host)) {
|
|
164277
165025
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -164281,7 +165029,7 @@ async function pinAddress(url, resolve63 = resolveAll, signal) {
|
|
|
164281
165029
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
164282
165030
|
return { address: host, family: 6 };
|
|
164283
165031
|
}
|
|
164284
|
-
const addresses = await withAbort(() =>
|
|
165032
|
+
const addresses = await withAbort(() => resolve65(host), signal, `${host} lookup`);
|
|
164285
165033
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
164286
165034
|
const blocked = addresses.filter((a2) => isBlockedAddress(a2.address)).map((a2) => a2.address);
|
|
164287
165035
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -164321,7 +165069,7 @@ function copyIncomingHeaders(headers2) {
|
|
|
164321
165069
|
return out2;
|
|
164322
165070
|
}
|
|
164323
165071
|
function requestOnce(url, pinned, init) {
|
|
164324
|
-
return new Promise((
|
|
165072
|
+
return new Promise((resolve65, reject) => {
|
|
164325
165073
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
164326
165074
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
164327
165075
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -164351,7 +165099,7 @@ function requestOnce(url, pinned, init) {
|
|
|
164351
165099
|
reject(err);
|
|
164352
165100
|
return;
|
|
164353
165101
|
}
|
|
164354
|
-
|
|
165102
|
+
resolve65(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
|
|
164355
165103
|
}
|
|
164356
165104
|
);
|
|
164357
165105
|
req.on("error", reject);
|
|
@@ -166323,7 +167071,7 @@ var init_brand_font = __esm({
|
|
|
166323
167071
|
|
|
166324
167072
|
// src/site-analyze/write-artifacts.ts
|
|
166325
167073
|
import { mkdirSync as mkdirSync37, writeFileSync as writeFileSync33 } from "node:fs";
|
|
166326
|
-
import { join as
|
|
167074
|
+
import { join as join82 } from "node:path";
|
|
166327
167075
|
function attachVeloSources(book, sources, put) {
|
|
166328
167076
|
const byPath = new Map((sources ?? []).map((s2) => [s2.path, s2.text]));
|
|
166329
167077
|
for (const f2 of book.velo.files) {
|
|
@@ -166478,12 +167226,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
166478
167226
|
}
|
|
166479
167227
|
async function writeBusinessBook(result, opts) {
|
|
166480
167228
|
const out2 = opts.outDir;
|
|
166481
|
-
mkdirSync37(
|
|
166482
|
-
mkdirSync37(
|
|
167229
|
+
mkdirSync37(join82(out2, "evidence/pages"), { recursive: true });
|
|
167230
|
+
mkdirSync37(join82(out2, "media/catalog"), { recursive: true });
|
|
166483
167231
|
const files = [];
|
|
166484
167232
|
const put = (rel, body) => {
|
|
166485
|
-
const p2 =
|
|
166486
|
-
mkdirSync37(
|
|
167233
|
+
const p2 = join82(out2, rel);
|
|
167234
|
+
mkdirSync37(join82(p2, ".."), { recursive: true });
|
|
166487
167235
|
writeFileSync33(p2, body);
|
|
166488
167236
|
files.push(rel);
|
|
166489
167237
|
};
|
|
@@ -167387,11 +168135,11 @@ var init_analyze = __esm({
|
|
|
167387
168135
|
});
|
|
167388
168136
|
|
|
167389
168137
|
// src/base44-analyze/write-artifacts.ts
|
|
167390
|
-
import { existsSync as
|
|
167391
|
-
import { dirname as
|
|
168138
|
+
import { existsSync as existsSync78, mkdirSync as mkdirSync38, readFileSync as readFileSync98, rmSync as rmSync21, writeFileSync as writeFileSync34 } from "node:fs";
|
|
168139
|
+
import { dirname as dirname45, join as join83, resolve as resolve59, sep as sep19 } from "node:path";
|
|
167392
168140
|
function isBookFolder(dir) {
|
|
167393
168141
|
try {
|
|
167394
|
-
return JSON.parse(
|
|
168142
|
+
return JSON.parse(readFileSync98(join83(dir, "book.json"), "utf8")).kind === "base44-app-book";
|
|
167395
168143
|
} catch {
|
|
167396
168144
|
return false;
|
|
167397
168145
|
}
|
|
@@ -167465,7 +168213,7 @@ function renderBookMd(book) {
|
|
|
167465
168213
|
return L2.join("\n");
|
|
167466
168214
|
}
|
|
167467
168215
|
function writeBase44Book(result, outDir, opts = {}) {
|
|
167468
|
-
const out2 =
|
|
168216
|
+
const out2 = resolve59(outDir);
|
|
167469
168217
|
const book = result.book;
|
|
167470
168218
|
const files = [];
|
|
167471
168219
|
const shots = (opts.screenshots ?? []).filter((s2) => safeRel(s2.filename) && !s2.filename.includes("/"));
|
|
@@ -167478,26 +168226,26 @@ function writeBase44Book(result, outDir, opts = {}) {
|
|
|
167478
168226
|
const md = renderBookMd(book);
|
|
167479
168227
|
assertNoSecrets(json6);
|
|
167480
168228
|
assertNoSecrets(md);
|
|
167481
|
-
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) =>
|
|
168229
|
+
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync78(join83(out2, n2)));
|
|
167482
168230
|
if (owned.length) {
|
|
167483
168231
|
if (!isBookFolder(out2)) throw new Error(`refusing to write the app book into ${out2}: it already has ${owned.join(", ")} that ${owned.length === 1 ? "is" : "are"} not from an app book \u2014 pick an empty --out`);
|
|
167484
|
-
for (const d2 of ["source", "screenshots"])
|
|
168232
|
+
for (const d2 of ["source", "screenshots"]) rmSync21(join83(out2, d2), { recursive: true, force: true });
|
|
167485
168233
|
}
|
|
167486
168234
|
mkdirSync38(out2, { recursive: true });
|
|
167487
|
-
writeFileSync34(
|
|
167488
|
-
writeFileSync34(
|
|
168235
|
+
writeFileSync34(join83(out2, "book.json"), json6);
|
|
168236
|
+
writeFileSync34(join83(out2, "BOOK.md"), md);
|
|
167489
168237
|
files.push("book.json", "BOOK.md");
|
|
167490
168238
|
for (const s2 of shots) {
|
|
167491
|
-
mkdirSync38(
|
|
167492
|
-
writeFileSync34(
|
|
168239
|
+
mkdirSync38(join83(out2, "screenshots"), { recursive: true });
|
|
168240
|
+
writeFileSync34(join83(out2, "screenshots", s2.filename), s2.bytes);
|
|
167493
168241
|
files.push(`screenshots/${s2.filename}`);
|
|
167494
168242
|
}
|
|
167495
|
-
const sourceRoot =
|
|
168243
|
+
const sourceRoot = join83(out2, "source");
|
|
167496
168244
|
for (const f2 of result.sourceFiles) {
|
|
167497
168245
|
if (!safeRel(f2.path)) continue;
|
|
167498
|
-
const dest =
|
|
168246
|
+
const dest = join83(sourceRoot, ...f2.path.split("/"));
|
|
167499
168247
|
if (!dest.startsWith(sourceRoot + sep19)) continue;
|
|
167500
|
-
mkdirSync38(
|
|
168248
|
+
mkdirSync38(dirname45(dest), { recursive: true });
|
|
167501
168249
|
writeFileSync34(dest, f2.bytes);
|
|
167502
168250
|
}
|
|
167503
168251
|
if (result.sourceFiles.length) files.push(`source/ (${result.sourceFiles.length} files)`);
|
|
@@ -168368,10 +169116,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
|
|
|
168368
169116
|
}
|
|
168369
169117
|
function createPromiseCallback(cb) {
|
|
168370
169118
|
let callback;
|
|
168371
|
-
let
|
|
169119
|
+
let resolve65;
|
|
168372
169120
|
let reject;
|
|
168373
169121
|
const promise = new Promise((_resolve, _reject) => {
|
|
168374
|
-
|
|
169122
|
+
resolve65 = _resolve;
|
|
168375
169123
|
reject = _reject;
|
|
168376
169124
|
});
|
|
168377
169125
|
if (typeof cb === "function") {
|
|
@@ -168387,7 +169135,7 @@ function createPromiseCallback(cb) {
|
|
|
168387
169135
|
callback = (err, result) => {
|
|
168388
169136
|
try {
|
|
168389
169137
|
if (err) reject(err);
|
|
168390
|
-
else
|
|
169138
|
+
else resolve65(result);
|
|
168391
169139
|
} catch (e2) {
|
|
168392
169140
|
reject(e2 instanceof Error ? e2 : new Error());
|
|
168393
169141
|
}
|
|
@@ -171039,9 +171787,9 @@ __export(cli_exports, {
|
|
|
171039
171787
|
systemTar: () => systemTar
|
|
171040
171788
|
});
|
|
171041
171789
|
import { execFile } from "node:child_process";
|
|
171042
|
-
import { mkdirSync as mkdirSync39, mkdtempSync as
|
|
171043
|
-
import { tmpdir as
|
|
171044
|
-
import { join as
|
|
171790
|
+
import { mkdirSync as mkdirSync39, mkdtempSync as mkdtempSync5, rmSync as rmSync22, writeFileSync as writeFileSync35 } from "node:fs";
|
|
171791
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
171792
|
+
import { join as join84, resolve as resolve60 } from "node:path";
|
|
171045
171793
|
import { promisify } from "node:util";
|
|
171046
171794
|
function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
171047
171795
|
return async (appId2) => {
|
|
@@ -171054,11 +171802,11 @@ function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
|
171054
171802
|
}
|
|
171055
171803
|
const bytes2 = await readCapped(res, MAX_TARBALL_BYTES);
|
|
171056
171804
|
if (!bytes2) throw new Error(`project download is over the ${MAX_TARBALL_BYTES}-byte cap`);
|
|
171057
|
-
const root =
|
|
171058
|
-
const cleanup = () =>
|
|
171805
|
+
const root = mkdtempSync5(join84(tmpdir6(), "himi-base44-"));
|
|
171806
|
+
const cleanup = () => rmSync22(root, { recursive: true, force: true });
|
|
171059
171807
|
try {
|
|
171060
|
-
const archive =
|
|
171061
|
-
const dir =
|
|
171808
|
+
const archive = join84(root, "project.tar");
|
|
171809
|
+
const dir = join84(root, "project");
|
|
171062
171810
|
writeFileSync35(archive, bytes2);
|
|
171063
171811
|
mkdirSync39(dir);
|
|
171064
171812
|
await extract(archive, dir);
|
|
@@ -171096,7 +171844,7 @@ async function runBase44Analyze(opts) {
|
|
|
171096
171844
|
now: opts.now ?? (() => /* @__PURE__ */ new Date())
|
|
171097
171845
|
};
|
|
171098
171846
|
const result = await analyzeBase44({ url: opts.url, appId: opts.appId, sample: opts.sample }, ports);
|
|
171099
|
-
const written = writeBase44Book(result,
|
|
171847
|
+
const written = writeBase44Book(result, resolve60(opts.cwd ?? process.cwd(), opts.outDir ?? ".himi/base44-book"), { screenshots });
|
|
171100
171848
|
return { ok: true, out: written.outDir, files: written.files, mode: result.book.mode, gaps: result.book.gaps, book: result.book };
|
|
171101
171849
|
}
|
|
171102
171850
|
var MAX_TARBALL_BYTES, systemTar;
|
|
@@ -171130,7 +171878,7 @@ var init_errors2 = __esm({
|
|
|
171130
171878
|
});
|
|
171131
171879
|
|
|
171132
171880
|
// src/one-app/collect.ts
|
|
171133
|
-
import { createHash as
|
|
171881
|
+
import { createHash as createHash43 } from "node:crypto";
|
|
171134
171882
|
function isObject2(value) {
|
|
171135
171883
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
171136
171884
|
}
|
|
@@ -171202,7 +171950,7 @@ function semanticFingerprint(structure) {
|
|
|
171202
171950
|
}
|
|
171203
171951
|
return JSON.stringify(value);
|
|
171204
171952
|
};
|
|
171205
|
-
return
|
|
171953
|
+
return createHash43("sha256").update(canonical4(structure, true)).digest("hex");
|
|
171206
171954
|
}
|
|
171207
171955
|
async function collectOneApp(input, deps = {}) {
|
|
171208
171956
|
if (typeof input.metaSiteId !== "string" || !UUID.test(input.metaSiteId)) {
|
|
@@ -171615,9 +172363,9 @@ __export(cli_exports2, {
|
|
|
171615
172363
|
ONE_APP_WORKFLOW: () => ONE_APP_WORKFLOW,
|
|
171616
172364
|
runOneAppCommand: () => runOneAppCommand
|
|
171617
172365
|
});
|
|
171618
|
-
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync40, openSync as openSync6, readFileSync as
|
|
171619
|
-
import { createHash as
|
|
171620
|
-
import { dirname as
|
|
172366
|
+
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync40, openSync as openSync6, readFileSync as readFileSync99, realpathSync as realpathSync14, writeFileSync as writeFileSync36 } from "node:fs";
|
|
172367
|
+
import { createHash as createHash44 } from "node:crypto";
|
|
172368
|
+
import { dirname as dirname46, join as join85, parse as parse3, resolve as resolve61 } from "node:path";
|
|
171621
172369
|
function readOptions(argv, cwd, commandIncluded) {
|
|
171622
172370
|
let cursor = 0;
|
|
171623
172371
|
const skipGlobalSwitches = () => {
|
|
@@ -171658,10 +172406,10 @@ function readOptions(argv, cwd, commandIncluded) {
|
|
|
171658
172406
|
let prompt = flags.prompt ?? "";
|
|
171659
172407
|
if (flags["prompt-file"] !== void 0) {
|
|
171660
172408
|
try {
|
|
171661
|
-
const file2 =
|
|
172409
|
+
const file2 = resolve61(cwd, flags["prompt-file"]);
|
|
171662
172410
|
const stat2 = lstatSync21(file2);
|
|
171663
172411
|
if (!stat2.isFile() || stat2.size > MAX_PROMPT_BYTES) throw new Error("invalid prompt file");
|
|
171664
|
-
prompt =
|
|
172412
|
+
prompt = readFileSync99(file2, "utf8");
|
|
171665
172413
|
} catch {
|
|
171666
172414
|
throw new OneAppError("invalid_prompt", "Use a readable text file of at most 64 KiB for --prompt-file.");
|
|
171667
172415
|
}
|
|
@@ -171676,8 +172424,8 @@ function readOptions(argv, cwd, commandIncluded) {
|
|
|
171676
172424
|
if (flags.dir !== void 0 && !flags.dir.trim()) {
|
|
171677
172425
|
throw new OneAppError("invalid_output_path", "Pass a parent directory with --dir.");
|
|
171678
172426
|
}
|
|
171679
|
-
const parentDir =
|
|
171680
|
-
const workspace =
|
|
172427
|
+
const parentDir = resolve61(cwd, flags.dir ?? ".");
|
|
172428
|
+
const workspace = join85(parentDir, name);
|
|
171681
172429
|
assertSafeParents(parentDir);
|
|
171682
172430
|
if (pathExists(workspace)) throw new OneAppError("output_exists", "The destination already exists. Choose a new --name or --dir.");
|
|
171683
172431
|
return { metaSiteId, appInstance, prompt, name, parentDir, workspace, target };
|
|
@@ -171706,7 +172454,7 @@ function assertSafeParents(path2) {
|
|
|
171706
172454
|
throw new OneAppError("invalid_output_path", "The output parent cannot be inspected.");
|
|
171707
172455
|
}
|
|
171708
172456
|
}
|
|
171709
|
-
current =
|
|
172457
|
+
current = dirname46(current);
|
|
171710
172458
|
}
|
|
171711
172459
|
}
|
|
171712
172460
|
function writePrivate(path2, contents, append) {
|
|
@@ -171734,7 +172482,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171734
172482
|
const hashes = {};
|
|
171735
172483
|
const diskWrite = deps.writeFile ?? writePrivate;
|
|
171736
172484
|
const put = (name, content) => {
|
|
171737
|
-
const path2 =
|
|
172485
|
+
const path2 = join85(evidenceDir, name);
|
|
171738
172486
|
try {
|
|
171739
172487
|
assertSafeParents(evidenceDir);
|
|
171740
172488
|
diskWrite(path2, content, false);
|
|
@@ -171742,7 +172490,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171742
172490
|
throw new OneAppError("artifact_write_failed", "Could not save the migration evidence. Existing files were kept.", { stage });
|
|
171743
172491
|
}
|
|
171744
172492
|
artifacts[name] = path2;
|
|
171745
|
-
hashes[name] =
|
|
172493
|
+
hashes[name] = createHash44("sha256").update(content).digest("hex");
|
|
171746
172494
|
return path2;
|
|
171747
172495
|
};
|
|
171748
172496
|
const progress = (nextStage) => {
|
|
@@ -171750,7 +172498,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171750
172498
|
if (!evidenceDir) return;
|
|
171751
172499
|
try {
|
|
171752
172500
|
assertSafeParents(evidenceDir);
|
|
171753
|
-
diskWrite(
|
|
172501
|
+
diskWrite(join85(evidenceDir, "progress.jsonl"), JSON.stringify({ stage, at: now() }) + "\n", true);
|
|
171754
172502
|
} catch {
|
|
171755
172503
|
throw new OneAppError("artifact_write_failed", "Could not record migration progress. Existing files were kept.", { stage });
|
|
171756
172504
|
}
|
|
@@ -171766,7 +172514,7 @@ Collect the source mobile app and hand it to the current coding agent. The agent
|
|
|
171766
172514
|
assertSafeParents(options.parentDir);
|
|
171767
172515
|
mkdirSync40(options.workspace, { mode: 448 });
|
|
171768
172516
|
if (realpathSync14(options.workspace) !== options.workspace) throw new Error("destination changed");
|
|
171769
|
-
evidenceDir =
|
|
172517
|
+
evidenceDir = join85(options.workspace, ".himi", "one-app");
|
|
171770
172518
|
mkdirSync40(evidenceDir, { recursive: true, mode: 448 });
|
|
171771
172519
|
} catch (error) {
|
|
171772
172520
|
if (error.code === "EEXIST") {
|
|
@@ -173582,15 +174330,15 @@ var init_customer_build = __esm({
|
|
|
173582
174330
|
});
|
|
173583
174331
|
|
|
173584
174332
|
// src/site-analyze/apply.ts
|
|
173585
|
-
import { existsSync as
|
|
173586
|
-
import { dirname as
|
|
174333
|
+
import { existsSync as existsSync79, readFileSync as readFileSync100, writeFileSync as writeFileSync37, copyFileSync as copyFileSync2, mkdirSync as mkdirSync41, realpathSync as realpathSync15, statSync as statSync22 } from "node:fs";
|
|
174334
|
+
import { dirname as dirname47, isAbsolute as isAbsolute8, join as join86, resolve as resolve62, sep as sep20 } from "node:path";
|
|
173587
174335
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
173588
174336
|
function unpairedRedirectNote(overlay) {
|
|
173589
174337
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
173590
174338
|
return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
|
|
173591
174339
|
}
|
|
173592
174340
|
function posix4(p2) {
|
|
173593
|
-
return
|
|
174341
|
+
return resolve62(p2).replace(/\\/g, "/");
|
|
173594
174342
|
}
|
|
173595
174343
|
function committedShellProvisioning(path2) {
|
|
173596
174344
|
return committedShellFor(posix4(path2));
|
|
@@ -173598,8 +174346,8 @@ function committedShellProvisioning(path2) {
|
|
|
173598
174346
|
function findRepoRoot(cwd) {
|
|
173599
174347
|
let dir = cwd;
|
|
173600
174348
|
for (let i2 = 0; i2 < 8; i2++) {
|
|
173601
|
-
if (SHELL_NAMES2.some((name) =>
|
|
173602
|
-
const next =
|
|
174349
|
+
if (SHELL_NAMES2.some((name) => existsSync79(join86(dir, shellAppDir(name), "package.json")))) return dir;
|
|
174350
|
+
const next = dirname47(dir);
|
|
173603
174351
|
if (next === dir) break;
|
|
173604
174352
|
dir = next;
|
|
173605
174353
|
}
|
|
@@ -173624,7 +174372,7 @@ function assertNotCommitted(path2, forbidden2) {
|
|
|
173624
174372
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
173625
174373
|
);
|
|
173626
174374
|
}
|
|
173627
|
-
if (forbidden2 &&
|
|
174375
|
+
if (forbidden2 && resolve62(path2) === resolve62(forbidden2)) {
|
|
173628
174376
|
const named = committedShellProvisioning(forbidden2);
|
|
173629
174377
|
throw new Error(
|
|
173630
174378
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden2} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -173701,24 +174449,24 @@ function sameKnownSite(previous, next) {
|
|
|
173701
174449
|
}
|
|
173702
174450
|
function buildMergedContract(options) {
|
|
173703
174451
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
173704
|
-
const committedPath =
|
|
173705
|
-
if (!
|
|
174452
|
+
const committedPath = join86(appDir3, "provisioning.json");
|
|
174453
|
+
if (!existsSync79(committedPath)) {
|
|
173706
174454
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
173707
174455
|
}
|
|
173708
|
-
const committed = JSON.parse(
|
|
174456
|
+
const committed = JSON.parse(readFileSync100(committedPath, "utf8"));
|
|
173709
174457
|
const merged = mergeCustomerOwned(committed, overlay);
|
|
173710
174458
|
const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
|
|
173711
174459
|
const branding = merged.branding ?? {};
|
|
173712
174460
|
const staged = [];
|
|
173713
174461
|
const contained = (root, rel) => {
|
|
173714
174462
|
if (isAbsolute8(rel)) return void 0;
|
|
173715
|
-
const full =
|
|
173716
|
-
return full.startsWith(
|
|
174463
|
+
const full = resolve62(root, rel);
|
|
174464
|
+
return full.startsWith(resolve62(root) + sep20) ? full : void 0;
|
|
173717
174465
|
};
|
|
173718
174466
|
const stage = (fromRel, toRel) => {
|
|
173719
174467
|
const from = contained(packageDir, fromRel);
|
|
173720
|
-
const to2 = contained(
|
|
173721
|
-
if (!from || !to2 || !
|
|
174468
|
+
const to2 = contained(join86(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
174469
|
+
if (!from || !to2 || !existsSync79(from)) return void 0;
|
|
173722
174470
|
let real;
|
|
173723
174471
|
let realRoot;
|
|
173724
174472
|
try {
|
|
@@ -173730,7 +174478,7 @@ function buildMergedContract(options) {
|
|
|
173730
174478
|
if (!real.startsWith(realRoot + sep20)) return void 0;
|
|
173731
174479
|
try {
|
|
173732
174480
|
if (!statSync22(real).isFile()) return void 0;
|
|
173733
|
-
mkdirSync41(
|
|
174481
|
+
mkdirSync41(dirname47(to2), { recursive: true });
|
|
173734
174482
|
copyFileSync2(real, to2);
|
|
173735
174483
|
} catch {
|
|
173736
174484
|
return void 0;
|
|
@@ -173740,11 +174488,11 @@ function buildMergedContract(options) {
|
|
|
173740
174488
|
};
|
|
173741
174489
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
173742
174490
|
if (icon) branding.appIconPath = icon;
|
|
173743
|
-
const facesPath =
|
|
173744
|
-
if (
|
|
174491
|
+
const facesPath = join86(packageDir, "media/fonts/faces.json");
|
|
174492
|
+
if (existsSync79(facesPath)) {
|
|
173745
174493
|
let faces = [];
|
|
173746
174494
|
try {
|
|
173747
|
-
const parsed = JSON.parse(
|
|
174495
|
+
const parsed = JSON.parse(readFileSync100(facesPath, "utf8"));
|
|
173748
174496
|
faces = Array.isArray(parsed) ? parsed : [];
|
|
173749
174497
|
} catch {
|
|
173750
174498
|
faces = [];
|
|
@@ -173765,10 +174513,10 @@ function buildMergedContract(options) {
|
|
|
173765
174513
|
merged.branding = branding;
|
|
173766
174514
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
173767
174515
|
`;
|
|
173768
|
-
const path2 =
|
|
174516
|
+
const path2 = join86(packageDir, "provisioning.contract.json");
|
|
173769
174517
|
writeFileSync37(path2, body);
|
|
173770
|
-
const localPath2 =
|
|
173771
|
-
mkdirSync41(
|
|
174518
|
+
const localPath2 = join86(appDir3, LOCAL_CONTRACT_REL);
|
|
174519
|
+
mkdirSync41(dirname47(localPath2), { recursive: true });
|
|
173772
174520
|
writeFileSync37(localPath2, body);
|
|
173773
174521
|
staged.push(localPath2);
|
|
173774
174522
|
return { path: path2, staged };
|
|
@@ -173802,10 +174550,10 @@ function catalogTypography(overlay, template) {
|
|
|
173802
174550
|
function staticFaqFor(overlay, overlayPath) {
|
|
173803
174551
|
const own5 = overlay.faq;
|
|
173804
174552
|
if (own5 !== void 0) return deriveStaticFaq(own5);
|
|
173805
|
-
const bookPath =
|
|
173806
|
-
if (!
|
|
174553
|
+
const bookPath = join86(dirname47(resolve62(overlayPath)), "book.json");
|
|
174554
|
+
if (!existsSync79(bookPath)) return void 0;
|
|
173807
174555
|
try {
|
|
173808
|
-
const book = JSON.parse(
|
|
174556
|
+
const book = JSON.parse(readFileSync100(bookPath, "utf8"));
|
|
173809
174557
|
const copy = book?.copy;
|
|
173810
174558
|
if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
|
|
173811
174559
|
const pairs = deriveStaticFaq(copy.faq);
|
|
@@ -173819,10 +174567,10 @@ function staticGalleriesFor(overlay, overlayPath) {
|
|
|
173819
174567
|
if (overlay.galleries !== void 0) return deriveStaticGalleries(
|
|
173820
174568
|
overlay.galleries.map((gallery) => ({ role: "gallery", title: gallery.title, galleryImageUrls: gallery.photos }))
|
|
173821
174569
|
);
|
|
173822
|
-
const bookPath =
|
|
173823
|
-
if (!
|
|
174570
|
+
const bookPath = join86(dirname47(resolve62(overlayPath)), "book.json");
|
|
174571
|
+
if (!existsSync79(bookPath)) return void 0;
|
|
173824
174572
|
try {
|
|
173825
|
-
const book = JSON.parse(
|
|
174573
|
+
const book = JSON.parse(readFileSync100(bookPath, "utf8"));
|
|
173826
174574
|
if (!book.look || book.look.unavailable || !Array.isArray(book.look.pages)) return void 0;
|
|
173827
174575
|
const galleries = deriveStaticGalleries(book.look.pages);
|
|
173828
174576
|
return galleries.length || book.look.complete === true ? galleries : void 0;
|
|
@@ -173831,11 +174579,11 @@ function staticGalleriesFor(overlay, overlayPath) {
|
|
|
173831
174579
|
}
|
|
173832
174580
|
}
|
|
173833
174581
|
async function applyOverlays(input) {
|
|
173834
|
-
const cwd =
|
|
174582
|
+
const cwd = resolve62(input.cwd);
|
|
173835
174583
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
173836
174584
|
assertKnownShell(shell);
|
|
173837
|
-
const overlay = JSON.parse(
|
|
173838
|
-
const tokens2 = JSON.parse(
|
|
174585
|
+
const overlay = JSON.parse(readFileSync100(input.overlayPath, "utf8"));
|
|
174586
|
+
const tokens2 = JSON.parse(readFileSync100(input.tokensPath, "utf8"));
|
|
173839
174587
|
const faq = staticFaqFor(overlay, input.overlayPath);
|
|
173840
174588
|
if (faq !== void 0) overlay.faq = faq;
|
|
173841
174589
|
const galleries = staticGalleriesFor(overlay, input.overlayPath);
|
|
@@ -173852,15 +174600,15 @@ async function applyOverlays(input) {
|
|
|
173852
174600
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
173853
174601
|
);
|
|
173854
174602
|
}
|
|
173855
|
-
const appDir3 =
|
|
173856
|
-
const committedPath =
|
|
173857
|
-
const committedSite =
|
|
174603
|
+
const appDir3 = join86(repoRoot2, shellAppDir(shell));
|
|
174604
|
+
const committedPath = join86(appDir3, "provisioning.json");
|
|
174605
|
+
const committedSite = existsSync79(committedPath) ? JSON.parse(readFileSync100(committedPath, "utf8")).site : void 0;
|
|
173858
174606
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
173859
174607
|
throw new Error(
|
|
173860
174608
|
`shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
|
|
173861
174609
|
);
|
|
173862
174610
|
}
|
|
173863
|
-
const packageDir =
|
|
174611
|
+
const packageDir = dirname47(resolve62(input.overlayPath));
|
|
173864
174612
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
|
|
173865
174613
|
wrote.push(...staged);
|
|
173866
174614
|
const r2 = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -173881,9 +174629,9 @@ async function applyOverlays(input) {
|
|
|
173881
174629
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
173882
174630
|
};
|
|
173883
174631
|
}
|
|
173884
|
-
const pkgProv =
|
|
174632
|
+
const pkgProv = join86(cwd, "provisioning.json");
|
|
173885
174633
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
173886
|
-
const contentPath =
|
|
174634
|
+
const contentPath = join86(cwd, "himalaya.content.json");
|
|
173887
174635
|
const syncViewNames = (before, after) => {
|
|
173888
174636
|
const content = readContentManifest(cwd);
|
|
173889
174637
|
if (!content) return;
|
|
@@ -173895,8 +174643,8 @@ async function applyOverlays(input) {
|
|
|
173895
174643
|
};
|
|
173896
174644
|
let packageFaq = faq;
|
|
173897
174645
|
let packageGalleries = galleries;
|
|
173898
|
-
if (
|
|
173899
|
-
const cur = JSON.parse(
|
|
174646
|
+
if (existsSync79(pkgProv)) {
|
|
174647
|
+
const cur = JSON.parse(readFileSync100(pkgProv, "utf8"));
|
|
173900
174648
|
if (galleries === void 0 && !sameKnownSite(cur, overlay)) overlay.galleries = [];
|
|
173901
174649
|
const merged = deepMerge4(cur, overlay);
|
|
173902
174650
|
packageFaq = merged.faq;
|
|
@@ -173912,9 +174660,9 @@ async function applyOverlays(input) {
|
|
|
173912
174660
|
if (Array.isArray(packageGalleries) && packageGalleries.length && !overlay.installedVerticals.includes("galleries")) {
|
|
173913
174661
|
overlay.installedVerticals.push("galleries");
|
|
173914
174662
|
}
|
|
173915
|
-
const pkgTokens =
|
|
173916
|
-
if (
|
|
173917
|
-
const cur = JSON.parse(
|
|
174663
|
+
const pkgTokens = join86(cwd, "tokens.json");
|
|
174664
|
+
if (existsSync79(pkgTokens) && (tokens2.colors || tokens2.typography)) {
|
|
174665
|
+
const cur = JSON.parse(readFileSync100(pkgTokens, "utf8"));
|
|
173918
174666
|
let tokensIn = tokens2;
|
|
173919
174667
|
if (tokens2.typography) {
|
|
173920
174668
|
const fonts = catalogTypography(tokens2.typography, cur.typography);
|
|
@@ -173939,9 +174687,9 @@ async function applyOverlays(input) {
|
|
|
173939
174687
|
wrote.push(pkgTokens);
|
|
173940
174688
|
}
|
|
173941
174689
|
const homeAction = homeRefreshActionId(shell);
|
|
173942
|
-
const homeSrc =
|
|
173943
|
-
if (homeAction &&
|
|
173944
|
-
const prev =
|
|
174690
|
+
const homeSrc = join86(cwd, "dev/index.ts");
|
|
174691
|
+
if (homeAction && existsSync79(homeSrc)) {
|
|
174692
|
+
const prev = readFileSync100(homeSrc, "utf8");
|
|
173945
174693
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
173946
174694
|
let next = patched.src;
|
|
173947
174695
|
if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
|
|
@@ -173976,13 +174724,13 @@ async function applyOverlays(input) {
|
|
|
173976
174724
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
173977
174725
|
}
|
|
173978
174726
|
}
|
|
173979
|
-
if (!input.iconPath || !
|
|
173980
|
-
const book = input.iconPath ?
|
|
174727
|
+
if (!input.iconPath || !existsSync79(input.iconPath)) {
|
|
174728
|
+
const book = input.iconPath ? dirname47(dirname47(resolve62(input.iconPath))) : void 0;
|
|
173981
174729
|
notes.push(
|
|
173982
174730
|
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"
|
|
173983
174731
|
);
|
|
173984
174732
|
}
|
|
173985
|
-
if (input.iconPath &&
|
|
174733
|
+
if (input.iconPath && existsSync79(input.iconPath)) {
|
|
173986
174734
|
try {
|
|
173987
174735
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
173988
174736
|
wrote.push(...installed.wrote);
|
|
@@ -174940,8 +175688,8 @@ __export(cli_exports3, {
|
|
|
174940
175688
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
174941
175689
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
174942
175690
|
});
|
|
174943
|
-
import { existsSync as
|
|
174944
|
-
import { resolve as
|
|
175691
|
+
import { existsSync as existsSync80, readFileSync as readFileSync101 } from "node:fs";
|
|
175692
|
+
import { resolve as resolve63 } from "node:path";
|
|
174945
175693
|
function applyNeedsClient(shell) {
|
|
174946
175694
|
if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
|
|
174947
175695
|
return !isSiteShell(shell);
|
|
@@ -174965,7 +175713,7 @@ async function runSiteAnalyze(opts) {
|
|
|
174965
175713
|
const assetFetch = assetFetchFor(opts);
|
|
174966
175714
|
const siteFetch = guardedSiteFetch;
|
|
174967
175715
|
const cwd = opts.cwd ?? process.cwd();
|
|
174968
|
-
const outDir =
|
|
175716
|
+
const outDir = resolve63(cwd, opts.outDir ?? ".himi/business-book");
|
|
174969
175717
|
let ownerAuth;
|
|
174970
175718
|
let msid;
|
|
174971
175719
|
const ownerSite = ownerSiteFor(opts);
|
|
@@ -174992,14 +175740,14 @@ async function runSiteAnalyze(opts) {
|
|
|
174992
175740
|
if (opts.shell !== void 0 && isSiteShell(opts.shell)) {
|
|
174993
175741
|
try {
|
|
174994
175742
|
const kind = siteKindForOrigin(result.book.input.siteUrl);
|
|
174995
|
-
const book = kind === "base44" ? base44BookRoutes(
|
|
175743
|
+
const book = kind === "base44" ? base44BookRoutes(resolve63(cwd, ".himi/base44-book/book.json"), result.book.input.siteUrl) : void 0;
|
|
174996
175744
|
const routes = book?.routes;
|
|
174997
175745
|
if (book?.skipped) result.warnings = [...result.warnings ?? [], book.skipped];
|
|
174998
175746
|
const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look, kind, routes });
|
|
174999
|
-
const prevOverlayPath =
|
|
175000
|
-
const prevSite =
|
|
175747
|
+
const prevOverlayPath = resolve63(outDir, "provisioning.overlay.json");
|
|
175748
|
+
const prevSite = existsSync80(prevOverlayPath) ? (() => {
|
|
175001
175749
|
try {
|
|
175002
|
-
return JSON.parse(
|
|
175750
|
+
return JSON.parse(readFileSync101(prevOverlayPath, "utf8")).site;
|
|
175003
175751
|
} catch {
|
|
175004
175752
|
return void 0;
|
|
175005
175753
|
}
|
|
@@ -175016,9 +175764,9 @@ async function runSiteAnalyze(opts) {
|
|
|
175016
175764
|
];
|
|
175017
175765
|
}
|
|
175018
175766
|
}
|
|
175019
|
-
const previousOverlay =
|
|
175767
|
+
const previousOverlay = resolve63(outDir, "provisioning.overlay.json");
|
|
175020
175768
|
carryOverGoals(
|
|
175021
|
-
|
|
175769
|
+
existsSync80(previousOverlay) ? readFileSync101(previousOverlay, "utf8") : void 0,
|
|
175022
175770
|
result.provisioningOverlay
|
|
175023
175771
|
);
|
|
175024
175772
|
const ownerCall = ownerAuth ? ownerTransportFrom(fetchImpl, ownerAuth) : void 0;
|
|
@@ -175037,9 +175785,9 @@ async function runSiteAnalyze(opts) {
|
|
|
175037
175785
|
if (opts.apply) {
|
|
175038
175786
|
applied = await applyOverlays({
|
|
175039
175787
|
cwd,
|
|
175040
|
-
overlayPath:
|
|
175041
|
-
tokensPath:
|
|
175042
|
-
iconPath:
|
|
175788
|
+
overlayPath: resolve63(outDir, "provisioning.overlay.json"),
|
|
175789
|
+
tokensPath: resolve63(outDir, "tokens.overlay.json"),
|
|
175790
|
+
iconPath: resolve63(outDir, "media/icon.png"),
|
|
175043
175791
|
shell: opts.shell
|
|
175044
175792
|
});
|
|
175045
175793
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -175075,8 +175823,8 @@ async function runSiteFunctionCli(opts) {
|
|
|
175075
175823
|
const token = opts.token ?? await siteToken(msid);
|
|
175076
175824
|
let source;
|
|
175077
175825
|
if (opts.sourcePath) {
|
|
175078
|
-
const p2 =
|
|
175079
|
-
source =
|
|
175826
|
+
const p2 = resolve63(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
175827
|
+
source = readFileSync101(p2, "utf8");
|
|
175080
175828
|
}
|
|
175081
175829
|
let body;
|
|
175082
175830
|
if (opts.bodyRaw != null) {
|
|
@@ -175104,9 +175852,9 @@ async function runSiteFunctionCli(opts) {
|
|
|
175104
175852
|
});
|
|
175105
175853
|
}
|
|
175106
175854
|
function base44BookRoutes(bookPath, siteUrl) {
|
|
175107
|
-
if (!
|
|
175855
|
+
if (!existsSync80(bookPath)) return void 0;
|
|
175108
175856
|
try {
|
|
175109
|
-
const book = JSON.parse(
|
|
175857
|
+
const book = JSON.parse(readFileSync101(bookPath, "utf8"));
|
|
175110
175858
|
if (book.kind !== "base44-app-book" || !Array.isArray(book.routes)) return void 0;
|
|
175111
175859
|
const host = (u2) => {
|
|
175112
175860
|
try {
|
|
@@ -175155,7 +175903,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
175155
175903
|
cached2 = fromEnv;
|
|
175156
175904
|
return fromEnv;
|
|
175157
175905
|
}
|
|
175158
|
-
const token = await new Promise((
|
|
175906
|
+
const token = await new Promise((resolve65, reject) => {
|
|
175159
175907
|
let child;
|
|
175160
175908
|
try {
|
|
175161
175909
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -175184,7 +175932,7 @@ async function accountToken2(spawnImpl = spawn6) {
|
|
|
175184
175932
|
const scan = (d2) => {
|
|
175185
175933
|
out2 += String(d2);
|
|
175186
175934
|
const m2 = out2.match(TOKEN_RE2);
|
|
175187
|
-
if (m2) done(() =>
|
|
175935
|
+
if (m2) done(() => resolve65(m2[0]));
|
|
175188
175936
|
};
|
|
175189
175937
|
child.stdout?.on("data", scan);
|
|
175190
175938
|
child.stderr?.on("data", scan);
|
|
@@ -175361,7 +176109,7 @@ __export(site_create_exports, {
|
|
|
175361
176109
|
runSiteList: () => runSiteList,
|
|
175362
176110
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
175363
176111
|
});
|
|
175364
|
-
import { existsSync as
|
|
176112
|
+
import { existsSync as existsSync81, readFileSync as readFileSync102, writeFileSync as writeFileSync38 } from "node:fs";
|
|
175365
176113
|
import { resolve as resolvePath2 } from "node:path";
|
|
175366
176114
|
function oauthClientName(projectName) {
|
|
175367
176115
|
return `${projectName} client`;
|
|
@@ -175510,7 +176258,7 @@ async function runSiteCreate(opts) {
|
|
|
175510
176258
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
175511
176259
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
175512
176260
|
}
|
|
175513
|
-
function writeProvisioningBinding(target, binding2, fs2 = { existsSync:
|
|
176261
|
+
function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync81, readFileSync: readFileSync102, writeFileSync: writeFileSync38 }) {
|
|
175514
176262
|
const msid = binding2.siteId;
|
|
175515
176263
|
const path2 = resolvePath2(target);
|
|
175516
176264
|
const committed = committedShellProvisioning(path2);
|
|
@@ -176207,12 +176955,12 @@ var init_context = __esm({
|
|
|
176207
176955
|
});
|
|
176208
176956
|
|
|
176209
176957
|
// src/cli.ts
|
|
176210
|
-
import { mkdtempSync as
|
|
176958
|
+
import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync103, mkdirSync as mkdirSync42, writeFileSync as writeFileSync39, existsSync as existsSync82, rmSync as rmSync23, readdirSync as readdirSync35, statSync as statSync23, lstatSync as lstatSync22, accessSync, constants as constants5, renameSync as renameSync13, cpSync as cpSync3 } from "node:fs";
|
|
176211
176959
|
import { execFile as execFile2, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
176212
176960
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
176213
|
-
import { createHash as
|
|
176214
|
-
import { tmpdir as
|
|
176215
|
-
import { join as
|
|
176961
|
+
import { createHash as createHash45, randomUUID as randomUUID11 } from "node:crypto";
|
|
176962
|
+
import { tmpdir as tmpdir7, homedir as homedir14, hostname as hostname2 } from "node:os";
|
|
176963
|
+
import { join as join87, resolve as resolve64, relative as relative16, basename as basename21, dirname as dirname48 } from "node:path";
|
|
176216
176964
|
import { fileURLToPath as fileURLToPath29 } from "node:url";
|
|
176217
176965
|
|
|
176218
176966
|
// ../serve-cli/src/client.ts
|
|
@@ -178294,8 +179042,8 @@ var str9 = (v2) => typeof v2 === "string" ? v2 : void 0;
|
|
|
178294
179042
|
var num3 = (v2) => typeof v2 === "string" && v2 !== "" && Number.isFinite(Number(v2)) ? Number(v2) : void 0;
|
|
178295
179043
|
function embeddedTemplateCatalog() {
|
|
178296
179044
|
return availableTemplates().map((name) => {
|
|
178297
|
-
const path2 =
|
|
178298
|
-
const meta = JSON.parse(
|
|
179045
|
+
const path2 = join87(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
179046
|
+
const meta = JSON.parse(readFileSync103(path2, "utf8"));
|
|
178299
179047
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
178300
179048
|
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
178301
179049
|
}
|
|
@@ -178855,6 +179603,13 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
178855
179603
|
conflict, never overwritten. --content records the
|
|
178856
179604
|
purchases app as wixIap in the app's config.ts.
|
|
178857
179605
|
No build, signing or repo checkout. Guide: himi docs iap-products
|
|
179606
|
+
himi store iap screenshots --manifest <file> --content <app dir> [--profile <name>] [--out-dir <dir>]
|
|
179607
|
+
[--only <productId,\u2026>] [--force] [--dry-run] [--json]
|
|
179608
|
+
render each product's purchase screen from the app, as a
|
|
179609
|
+
signed-in member sees it on a bound iPhone (Apple price, buy
|
|
179610
|
+
button), save it at 1290\xD72796 and name it as the item's
|
|
179611
|
+
reviewScreenshot. --profile reads Apple's price (read-only)
|
|
179612
|
+
and skips live products. Guide: himi docs iap-products
|
|
178858
179613
|
himi logout [--target <t>] clear the stored control token for a target
|
|
178859
179614
|
himi notify setup --content <dir> [--target wix] [--yes] [--no-push-setup]
|
|
178860
179615
|
Optional Branded/Ping setup. Prompts for site, native IDs and APNs key file.
|
|
@@ -179165,7 +179920,7 @@ var COMMANDS2 = [
|
|
|
179165
179920
|
{ name: "visibility", summary: "read (no value) or set whether the public registry (/v1/apps + the Himi Player picker) LISTS the app. `public` lists it for everyone; `unlisted` hides it from listings while direct reads by app id \u2014 deep links, previews \u2014 keep working. App from --app or the content dir. Setting it needs no republish.", required: "[public|unlisted] [--app <a>] [--content <dir>] (--control-token)" },
|
|
179166
179921
|
{ name: "dist", summary: "build an INSTALLABLE QA binary (signed IPA / APK) on the Wix Job Service Mac pool and return an install link \u2014 the serve plane brokers the job, the pool builds it. WAITS for the build by default (~4 min) and prints the install link; `--no-wait` returns a jobId immediately instead. Omitting `--release` builds whatever is LIVE for the app. A named draft is refused unless `--allow-draft` makes that exceptional build explicit. `status <jobId>` / `watch <jobId>` / `list --app <a>` / `cancel <jobId>` inspect and stop builds (`watch` reports up front whether the job mints its own signing identity or borrows one, so a doomed iOS build is cancellable in seconds rather than after the archive). Off-repo, name a target \u2014 `--target wix` for a self-serve Wix login or `--target bo` for the internal employee path (the in-repo default is a local dev plane that isn't reachable off-repo); self-serve callers may build their OWN apps under a tighter budget (2 in flight / 5 per 24h), while a manage-only owner-role credential is refused. `--shell` picks the native host to sign into (branded-lite | owner-lite | brandy | base44 | player | demo-app) and defaults to the content package's himalaya.content.json `shell` (templates carry the one they were written for), else branded-lite. The per-app shells ADD the release's declared capabilities to the binary, while Himi Player and demo-app refuse a release declaring one they lack; `--plan` previews it without building; `brandy` is the site shell \u2014 the customer's own website as native-framed tabs. `--signing` defaults to `wix-managed` \u2014 the Wix Apple account mints a per-app signing identity for the build, so the caller provisions no Apple credentials of their own; `--signing byo --site <id>` reuses an existing customer ad-hoc profile and certificate for iOS; requires an owned site and a completed personal signing binding. `--android-signing` is the Android counterpart and a SEPARATE axis (a keystore, not an Apple account): `qa-keystore` (default \u2014 the repo's committed QA key, identical on every pool machine, so a build installs over the previous one), `wix-keystore` (the Wix key the pool machine carries; the build FAILS naming the paths searched if it carries none, rather than quietly signing with something else), or `debug` (the old per-machine key \u2014 QA must uninstall any previous build first). NOT the normal way to ship: screens, Tier-5 bundles, tokens and app-config all go over the air with `himi push` in seconds \u2014 a binary trip is only needed for a NATIVE delta (a new SDUI component, a new declared capability/entitlement, a new bundle id, or a minBinaryVersion floor bump). Refuses to build an app whose launcher icon is missing, a placeholder, or one a store would reject \u2014 the one thing a binary carries that no later OTA push can fix; `--force` builds anyway", required: "[--app <a>] [--platform ios,android] [--release <id>] [--allow-draft] [--target <t>] [--shell branded-lite|owner-lite|brandy|base44|player|demo-app] [--signing wix-managed|byo] [--site <id>] [--android-signing qa-keystore|wix-keystore|debug] [--borrow-ios-id <bundleId>] [--no-wait] [--force] [--plan] | status <jobId> [--target <t>] | watch <jobId> [--target <t>] [--interval <ms>] | list --app <a> [--target <t>] | cancel <jobId> [--target <t>]" },
|
|
179167
179922
|
{ name: "testflight", summary: 'build, sign and upload an app to TestFlight (internal testers \u2014 no Beta App Review), then WAIT until App Store Connect finishes processing it. Sugar for `store upload --track testflight`. Prompts first: a build number is consumed permanently on a real Apple account and cannot be reused \u2014 `--yes` for CI, `--dry-run` to see the plan without touching anything. The wait is the real check, not a nicety: fastlane prints "Successfully uploaded" for a binary App Store Connect then rejects in processing, and a rejected binary leaves NO build record at all (the reason is emailed). Public App Store review is deliberately NOT automatable here \u2014 `--track appstore` is refused; use /submit-ios-app when you mean to go public', required: "<app> [--track testflight|internal] [--profile <name>] [--yes] [--dry-run] [--skip-build] [--no-wait] [--json]" },
|
|
179168
|
-
{ name: "store", summary: "the App Store Connect group behind `testflight`. `preflight <app>` checks readiness offline (icon, entitlements, encryption flag, version, store.config ids, listing + review record); `upload <app>` is what `testflight` runs; `status <app>` reads live build + processing state. `--profile` selects WHICH App Store Connect account: an app built for a Wix customer ships under the CUSTOMER's Apple team (Apple guideline 4.2.6 forbids an app-generation service submitting on a client's behalf), declared per-app as ios.credentialProfile in store.config.yaml and resolved from ~/.himalaya/store-credentials/<name>.json \u2014 the .p8 itself never enters the repo. `iap draft|plan|apply|status|connect` registers an app owner's digital products as in-app purchases (non-consumables, or consumable price tiers): draft reads the Wix catalog and writes the manifest, plan and status only read, apply is the one App Store mutation boundary, connect readies the Wix site to sell them (purchases app, In-App Purchase key, appleIAP provider, product mappings; --preview-tag routes only its Serve calls to a deploy preview), and none of them builds, signs or needs a checkout (`himi docs iap-products`)", required: "preflight <app> [--profile <n>] | upload <app> [--track <t>] [--profile <n>] [--yes] [--dry-run] | status <app> [--profile <n>] | iap draft --site <msid> --profile <n> --apple-app <id> --bundle <id> --base-territory <t> --out <f> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <f>] [--report <f>] [--json] | iap plan --manifest <f> --profile <n> --out <f> [--json] | iap apply --plan <f> --profile <n> --out <f> [--yes] [--limit <n>] [--json] | iap status --manifest <f> --profile <n> [--out <f>] [--json] | iap connect --manifest <f> --profile <n> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <f>] [--json]" },
|
|
179923
|
+
{ name: "store", summary: "the App Store Connect group behind `testflight`. `preflight <app>` checks readiness offline (icon, entitlements, encryption flag, version, store.config ids, listing + review record); `upload <app>` is what `testflight` runs; `status <app>` reads live build + processing state. `--profile` selects WHICH App Store Connect account: an app built for a Wix customer ships under the CUSTOMER's Apple team (Apple guideline 4.2.6 forbids an app-generation service submitting on a client's behalf), declared per-app as ios.credentialProfile in store.config.yaml and resolved from ~/.himalaya/store-credentials/<name>.json \u2014 the .p8 itself never enters the repo. `iap draft|plan|apply|status|connect|screenshots` registers an app owner's digital products as in-app purchases (non-consumables, or consumable price tiers): draft reads the Wix catalog and writes the manifest, plan and status only read, apply is the one App Store mutation boundary, connect readies the Wix site to sell them (purchases app, In-App Purchase key, appleIAP provider, product mappings; --preview-tag routes only its Serve calls to a deploy preview), screenshots renders each product's purchase screen from the app (--content) as a bound iPhone shows it to a signed-in member and names the 1290\xD72796 PNG as the item's App Review screenshot, and none of them builds, signs or needs a checkout (`himi docs iap-products`)", required: "preflight <app> [--profile <n>] | upload <app> [--track <t>] [--profile <n>] [--yes] [--dry-run] | status <app> [--profile <n>] | iap draft --site <msid> --profile <n> --apple-app <id> --bundle <id> --base-territory <t> --out <f> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <f>] [--report <f>] [--json] | iap plan --manifest <f> --profile <n> --out <f> [--json] | iap apply --plan <f> --profile <n> --out <f> [--yes] [--limit <n>] [--json] | iap status --manifest <f> --profile <n> [--out <f>] [--json] | iap connect --manifest <f> --profile <n> [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <f>] [--json] | iap screenshots --manifest <f> --content <dir> [--profile <n>] [--out-dir <d>] [--only <id,\u2026>] [--force] [--dry-run] [--json]" },
|
|
179169
179924
|
{ name: "guide", summary: "print the Himalaya overview + headless dev loop + available topics (offline)", required: "[--json]" },
|
|
179170
179925
|
{ name: "docs", summary: "print bundled/verified cached guides offline; status reports kit identity; refresh downloads compatible reference content independently of CLI without changing app source", required: "[<topic>|catalog [kind]|status|refresh] [--pin <version|digest>] [--unpin] [--no-network] [--json]" },
|
|
179171
179926
|
{ name: "components", summary: "print the SDUI component vocabulary + props; a name = that component (offline)", required: "[<Name>] [--json]" },
|
|
@@ -179182,7 +179937,7 @@ var COMMANDS2 = [
|
|
|
179182
179937
|
];
|
|
179183
179938
|
function cliVersion() {
|
|
179184
179939
|
try {
|
|
179185
|
-
return JSON.parse(
|
|
179940
|
+
return JSON.parse(readFileSync103(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
|
|
179186
179941
|
} catch {
|
|
179187
179942
|
return "unknown";
|
|
179188
179943
|
}
|
|
@@ -179233,18 +179988,18 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
|
|
|
179233
179988
|
}
|
|
179234
179989
|
var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
|
|
179235
179990
|
function execNpmConfig(file2, args, options) {
|
|
179236
|
-
return new Promise((
|
|
179237
|
-
execFile2(file2, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) :
|
|
179991
|
+
return new Promise((resolve65, reject) => {
|
|
179992
|
+
execFile2(file2, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve65(String(stdout)));
|
|
179238
179993
|
});
|
|
179239
179994
|
}
|
|
179240
179995
|
var npmScopedWixRegistry = createScopedRegistryResolver();
|
|
179241
179996
|
async function scopedRegistryBefore(lookup3, deadline, onTimeout) {
|
|
179242
179997
|
let cancel = () => {
|
|
179243
179998
|
};
|
|
179244
|
-
const expired = new Promise((
|
|
179999
|
+
const expired = new Promise((resolve65) => {
|
|
179245
180000
|
const timer = setTimeout(() => {
|
|
179246
180001
|
onTimeout?.();
|
|
179247
|
-
|
|
180002
|
+
resolve65(void 0);
|
|
179248
180003
|
}, Math.max(0, deadline - Date.now()));
|
|
179249
180004
|
cancel = () => clearTimeout(timer);
|
|
179250
180005
|
});
|
|
@@ -179307,18 +180062,18 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
179307
180062
|
}
|
|
179308
180063
|
function packageVersion(path2) {
|
|
179309
180064
|
try {
|
|
179310
|
-
const version4 = JSON.parse(
|
|
180065
|
+
const version4 = JSON.parse(readFileSync103(path2, "utf8")).version;
|
|
179311
180066
|
return typeof version4 === "string" && version4 ? version4 : void 0;
|
|
179312
180067
|
} catch {
|
|
179313
180068
|
return void 0;
|
|
179314
180069
|
}
|
|
179315
180070
|
}
|
|
179316
180071
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
179317
|
-
let dir =
|
|
180072
|
+
let dir = resolve64(fromDir);
|
|
179318
180073
|
for (; ; ) {
|
|
179319
|
-
const version4 = packageVersion(
|
|
180074
|
+
const version4 = packageVersion(join87(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
179320
180075
|
if (version4) return { version: version4, source: "local" };
|
|
179321
|
-
const parent =
|
|
180076
|
+
const parent = dirname48(dir);
|
|
179322
180077
|
if (parent === dir) break;
|
|
179323
180078
|
dir = parent;
|
|
179324
180079
|
}
|
|
@@ -179326,7 +180081,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
179326
180081
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
179327
180082
|
try {
|
|
179328
180083
|
const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
179329
|
-
const version4 = root ? packageVersion(
|
|
180084
|
+
const version4 = root ? packageVersion(join87(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
179330
180085
|
return version4 ? { version: version4, source: "global" } : {};
|
|
179331
180086
|
} catch {
|
|
179332
180087
|
return {};
|
|
@@ -179373,11 +180128,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
|
|
|
179373
180128
|
var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
|
|
179374
180129
|
var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
179375
180130
|
function updateCachePath(env = process.env) {
|
|
179376
|
-
return env.HIMI_UPDATE_CACHE_FILE ??
|
|
180131
|
+
return env.HIMI_UPDATE_CACHE_FILE ?? join87(homedir14(), ".himalaya", "update-check.json");
|
|
179377
180132
|
}
|
|
179378
180133
|
function readUpdateCache(path2) {
|
|
179379
180134
|
try {
|
|
179380
|
-
const parsed = JSON.parse(
|
|
180135
|
+
const parsed = JSON.parse(readFileSync103(path2, "utf8"));
|
|
179381
180136
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
179382
180137
|
} catch {
|
|
179383
180138
|
return {};
|
|
@@ -179385,7 +180140,7 @@ function readUpdateCache(path2) {
|
|
|
179385
180140
|
}
|
|
179386
180141
|
function writeUpdateCache(path2, cache) {
|
|
179387
180142
|
try {
|
|
179388
|
-
mkdirSync42(
|
|
180143
|
+
mkdirSync42(dirname48(path2), { recursive: true, mode: 448 });
|
|
179389
180144
|
writeFileSync39(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
179390
180145
|
} catch {
|
|
179391
180146
|
}
|
|
@@ -179446,12 +180201,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
|
|
|
179446
180201
|
},
|
|
179447
180202
|
installedVersion: () => {
|
|
179448
180203
|
const root = globalNodeModulesRoot();
|
|
179449
|
-
return root ? packageVersion(
|
|
180204
|
+
return root ? packageVersion(join87(root, "@wix", "himalaya-cli", "package.json")) : void 0;
|
|
179450
180205
|
},
|
|
179451
180206
|
reexec: (argv) => {
|
|
179452
180207
|
const root = globalNodeModulesRoot();
|
|
179453
|
-
const entry = root ?
|
|
179454
|
-
if (!entry || !
|
|
180208
|
+
const entry = root ? join87(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
|
|
180209
|
+
if (!entry || !existsSync82(entry)) return void 0;
|
|
179455
180210
|
const result = spawnSync5(process.execPath, [entry, ...argv], {
|
|
179456
180211
|
// inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
|
|
179457
180212
|
stdio: "inherit",
|
|
@@ -179498,7 +180253,7 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
179498
180253
|
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
179499
180254
|
let content;
|
|
179500
180255
|
try {
|
|
179501
|
-
content =
|
|
180256
|
+
content = readFileSync103(path2, "utf8");
|
|
179502
180257
|
} catch {
|
|
179503
180258
|
continue;
|
|
179504
180259
|
}
|
|
@@ -179521,7 +180276,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
179521
180276
|
const mine = lockStamp(now);
|
|
179522
180277
|
const readLock = (path2) => {
|
|
179523
180278
|
try {
|
|
179524
|
-
return
|
|
180279
|
+
return readFileSync103(path2, "utf8");
|
|
179525
180280
|
} catch {
|
|
179526
180281
|
return void 0;
|
|
179527
180282
|
}
|
|
@@ -179536,13 +180291,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
179536
180291
|
};
|
|
179537
180292
|
const removeIfMine = (path2) => {
|
|
179538
180293
|
try {
|
|
179539
|
-
if (readLock(path2) === mine)
|
|
180294
|
+
if (readLock(path2) === mine) rmSync23(path2, { force: true });
|
|
179540
180295
|
} catch {
|
|
179541
180296
|
}
|
|
179542
180297
|
};
|
|
179543
180298
|
const release2 = () => removeIfMine(lockPath);
|
|
179544
180299
|
try {
|
|
179545
|
-
mkdirSync42(
|
|
180300
|
+
mkdirSync42(dirname48(lockPath), { recursive: true, mode: 448 });
|
|
179546
180301
|
} catch {
|
|
179547
180302
|
return () => {
|
|
179548
180303
|
};
|
|
@@ -179559,7 +180314,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
179559
180314
|
hooks.underBreakLock?.();
|
|
179560
180315
|
if (current === void 0) return tryCreate(lockPath) ? release2 : void 0;
|
|
179561
180316
|
if (!isAbandoned(current)) return void 0;
|
|
179562
|
-
|
|
180317
|
+
rmSync23(lockPath, { force: true });
|
|
179563
180318
|
return tryCreate(lockPath) ? release2 : void 0;
|
|
179564
180319
|
} finally {
|
|
179565
180320
|
removeIfMine(breakPath);
|
|
@@ -179655,7 +180410,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
|
|
|
179655
180410
|
return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
|
|
179656
180411
|
};
|
|
179657
180412
|
return async (dir, opts = {}) => {
|
|
179658
|
-
const argv = ["validate", "--content",
|
|
180413
|
+
const argv = ["validate", "--content", resolve64(dir), "--strict", "--skip-version-check"];
|
|
179659
180414
|
if (!opts.fresh) {
|
|
179660
180415
|
const out2 = [];
|
|
179661
180416
|
const err = [];
|
|
@@ -180113,7 +180868,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
180113
180868
|
const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
180114
180869
|
for (const dir of entries) {
|
|
180115
180870
|
for (const suffix of suffixes) {
|
|
180116
|
-
const candidate =
|
|
180871
|
+
const candidate = join87(dir, `${name}${suffix}`);
|
|
180117
180872
|
try {
|
|
180118
180873
|
if (!statSync23(candidate).isFile()) continue;
|
|
180119
180874
|
if (process.platform !== "win32") accessSync(candidate, constants5.X_OK);
|
|
@@ -180222,7 +180977,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
180222
180977
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
|
|
180223
180978
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
180224
180979
|
const iosYmlPath = iosProjectYml2(app);
|
|
180225
|
-
const iosYml =
|
|
180980
|
+
const iosYml = existsSync82(iosYmlPath) ? readFileSync103(iosYmlPath, "utf8") : "";
|
|
180226
180981
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
180227
180982
|
if (!optedIn) {
|
|
180228
180983
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -180236,13 +180991,13 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
180236
180991
|
}
|
|
180237
180992
|
function readConfigSource(dir) {
|
|
180238
180993
|
try {
|
|
180239
|
-
return
|
|
180994
|
+
return readFileSync103(join87(dir, "config.ts"), "utf8");
|
|
180240
180995
|
} catch {
|
|
180241
180996
|
return null;
|
|
180242
180997
|
}
|
|
180243
180998
|
}
|
|
180244
180999
|
function writePngFile(path2, base64) {
|
|
180245
|
-
mkdirSync42(
|
|
181000
|
+
mkdirSync42(dirname48(path2), { recursive: true });
|
|
180246
181001
|
writeFileSync39(path2, Buffer.from(base64, "base64"));
|
|
180247
181002
|
return path2;
|
|
180248
181003
|
}
|
|
@@ -180289,8 +181044,8 @@ function keptPlan(kept) {
|
|
|
180289
181044
|
var NoBase44SlotError = class extends Error {
|
|
180290
181045
|
};
|
|
180291
181046
|
async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {}) {
|
|
180292
|
-
const dir =
|
|
180293
|
-
if (
|
|
181047
|
+
const dir = resolve64(parentDir, name);
|
|
181048
|
+
if (existsSync82(join87(dir, "himalaya.content.json"))) {
|
|
180294
181049
|
throw new Error(`content package already exists at ${dir}`);
|
|
180295
181050
|
}
|
|
180296
181051
|
const r2 = await c2.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -180305,7 +181060,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {})
|
|
|
180305
181060
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
180306
181061
|
}
|
|
180307
181062
|
function contentDir(flags) {
|
|
180308
|
-
return
|
|
181063
|
+
return resolve64(str9(flags.content) ?? process.cwd());
|
|
180309
181064
|
}
|
|
180310
181065
|
function renameRestoredSource(restored, declaredApp, renamed) {
|
|
180311
181066
|
const text9 = {};
|
|
@@ -180336,7 +181091,7 @@ function symlinkDestinationIssue(dest) {
|
|
|
180336
181091
|
function restoreDestinationIssue(dest, force) {
|
|
180337
181092
|
const link = symlinkDestinationIssue(dest);
|
|
180338
181093
|
if (link) return link;
|
|
180339
|
-
if (!
|
|
181094
|
+
if (!existsSync82(dest)) return null;
|
|
180340
181095
|
if (!statSync23(dest).isDirectory()) {
|
|
180341
181096
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
180342
181097
|
}
|
|
@@ -180349,10 +181104,10 @@ function restoreDestinationIssue(dest, force) {
|
|
|
180349
181104
|
return null;
|
|
180350
181105
|
}
|
|
180351
181106
|
function isHimalayaMonorepoCheckout(start) {
|
|
180352
|
-
let dir =
|
|
181107
|
+
let dir = resolve64(start);
|
|
180353
181108
|
for (; ; ) {
|
|
180354
|
-
if (
|
|
180355
|
-
const parent =
|
|
181109
|
+
if (existsSync82(join87(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync82(join87(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
181110
|
+
const parent = dirname48(dir);
|
|
180356
181111
|
if (parent === dir) return false;
|
|
180357
181112
|
dir = parent;
|
|
180358
181113
|
}
|
|
@@ -180389,7 +181144,7 @@ function shellShaDivergenceWarnings(jobs) {
|
|
|
180389
181144
|
}
|
|
180390
181145
|
async function templatePublishName(sourceDir) {
|
|
180391
181146
|
const id = await appId(sourceDir);
|
|
180392
|
-
return IDENTITY_SENTINELS.some((s2) => id.includes(s2)) ?
|
|
181147
|
+
return IDENTITY_SENTINELS.some((s2) => id.includes(s2)) ? basename21(sourceDir) : id;
|
|
180393
181148
|
}
|
|
180394
181149
|
function templateNameError(name, from) {
|
|
180395
181150
|
if (name.startsWith(TEMPLATE_APP_PREFIX)) {
|
|
@@ -180411,8 +181166,8 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
180411
181166
|
const forBuild = Object.fromEntries(
|
|
180412
181167
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
180413
181168
|
);
|
|
180414
|
-
const repoRoot2 =
|
|
180415
|
-
const root =
|
|
181169
|
+
const repoRoot2 = resolve64(fileURLToPath29(new URL("../../..", import.meta.url)));
|
|
181170
|
+
const root = join87(repoRoot2, "node_modules", ".cache", "himi-template-preview");
|
|
180416
181171
|
const stillRunning = (pid) => {
|
|
180417
181172
|
try {
|
|
180418
181173
|
process.kill(pid, 0);
|
|
@@ -180426,35 +181181,35 @@ function materializeForPreview(appDir3, slug, displayName2) {
|
|
|
180426
181181
|
if (!entry.isDirectory()) continue;
|
|
180427
181182
|
const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
|
|
180428
181183
|
if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
|
|
180429
|
-
|
|
181184
|
+
rmSync23(join87(root, entry.name), { recursive: true, force: true });
|
|
180430
181185
|
}
|
|
180431
181186
|
}
|
|
180432
181187
|
} catch {
|
|
180433
181188
|
}
|
|
180434
|
-
const dest =
|
|
180435
|
-
|
|
181189
|
+
const dest = join87(root, `${slug}-${process.pid}`);
|
|
181190
|
+
rmSync23(dest, { recursive: true, force: true });
|
|
180436
181191
|
mkdirSync42(dest, { recursive: true });
|
|
180437
181192
|
try {
|
|
180438
181193
|
materializeSource(forBuild, displayName2, dest, slug);
|
|
180439
181194
|
} catch (e2) {
|
|
180440
|
-
|
|
181195
|
+
rmSync23(dest, { recursive: true, force: true });
|
|
180441
181196
|
throw e2;
|
|
180442
181197
|
}
|
|
180443
181198
|
return dest;
|
|
180444
181199
|
}
|
|
180445
181200
|
async function appId(dir) {
|
|
180446
181201
|
try {
|
|
180447
|
-
const { readFileSync:
|
|
180448
|
-
const m2 = JSON.parse(
|
|
181202
|
+
const { readFileSync: readFileSync104 } = await import("node:fs");
|
|
181203
|
+
const m2 = JSON.parse(readFileSync104(join87(dir, "himalaya.content.json"), "utf8"));
|
|
180449
181204
|
if (m2.name) return m2.name;
|
|
180450
181205
|
} catch {
|
|
180451
181206
|
}
|
|
180452
|
-
return
|
|
181207
|
+
return basename21(dir);
|
|
180453
181208
|
}
|
|
180454
181209
|
async function contentVisibility(dir) {
|
|
180455
181210
|
try {
|
|
180456
|
-
const { readFileSync:
|
|
180457
|
-
const m2 = JSON.parse(
|
|
181211
|
+
const { readFileSync: readFileSync104 } = await import("node:fs");
|
|
181212
|
+
const m2 = JSON.parse(readFileSync104(join87(dir, "himalaya.content.json"), "utf8"));
|
|
180458
181213
|
if (m2.visibility === "public" || m2.visibility === "unlisted") return m2.visibility;
|
|
180459
181214
|
} catch {
|
|
180460
181215
|
}
|
|
@@ -180724,7 +181479,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
180724
181479
|
return 0;
|
|
180725
181480
|
}
|
|
180726
181481
|
case "agent-init": {
|
|
180727
|
-
const dir =
|
|
181482
|
+
const dir = resolve64(str9(flags.dir) ?? process.cwd());
|
|
180728
181483
|
const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
|
|
180729
181484
|
let res;
|
|
180730
181485
|
try {
|
|
@@ -180746,7 +181501,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
180746
181501
|
...res.removed.length ? { removed: res.removed, note: "older copies at the app root, moved to .himi/legacy-agent-files/ (a backup, in case one became app code) \u2014 the current ones live in .agents/skills/himalaya/" } : {},
|
|
180747
181502
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
180748
181503
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
180749
|
-
...
|
|
181504
|
+
...existsSync82(join87(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
|
|
180750
181505
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
180751
181506
|
portalUrl: idx.portalUrl
|
|
180752
181507
|
});
|
|
@@ -180769,7 +181524,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
180769
181524
|
try {
|
|
180770
181525
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
180771
181526
|
const bres = await buildContentForValidation2(dir, { resolution });
|
|
180772
|
-
out2 =
|
|
181527
|
+
out2 = mkdtempSync6(join87(tmpdir7(), "himi-ux-record-"));
|
|
180773
181528
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
180774
181529
|
const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
|
|
180775
181530
|
const releaseId = outcome.manifest.releaseId;
|
|
@@ -180782,7 +181537,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
|
|
|
180782
181537
|
return null;
|
|
180783
181538
|
} finally {
|
|
180784
181539
|
if (out2 !== void 0) try {
|
|
180785
|
-
|
|
181540
|
+
rmSync23(out2, { recursive: true, force: true });
|
|
180786
181541
|
} catch {
|
|
180787
181542
|
}
|
|
180788
181543
|
}
|
|
@@ -180948,7 +181703,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
180948
181703
|
let js2;
|
|
180949
181704
|
for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
|
|
180950
181705
|
try {
|
|
180951
|
-
js2 =
|
|
181706
|
+
js2 = readFileSync103(join87(outDir, candidate), "utf8");
|
|
180952
181707
|
break;
|
|
180953
181708
|
} catch {
|
|
180954
181709
|
}
|
|
@@ -180979,7 +181734,7 @@ async function producedWidgetFamilies(dir) {
|
|
|
180979
181734
|
}
|
|
180980
181735
|
return { families, source: "dist/bundles" };
|
|
180981
181736
|
}
|
|
180982
|
-
var boardOpen = (dir) =>
|
|
181737
|
+
var boardOpen = (dir) => existsSync82(join87(dir, ".himi", "studio", "index.html"));
|
|
180983
181738
|
var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
|
|
180984
181739
|
async function leaveForBoard(dir, record2, value) {
|
|
180985
181740
|
if (!boardOpen(dir)) return;
|
|
@@ -181003,7 +181758,7 @@ async function liveMapFor(dir) {
|
|
|
181003
181758
|
}
|
|
181004
181759
|
var commandScratch = new AsyncLocalStorage2();
|
|
181005
181760
|
function commandScratchDir(prefix) {
|
|
181006
|
-
const dir =
|
|
181761
|
+
const dir = mkdtempSync6(join87(tmpdir7(), prefix));
|
|
181007
181762
|
commandScratch.getStore()?.push(dir);
|
|
181008
181763
|
return dir;
|
|
181009
181764
|
}
|
|
@@ -181014,7 +181769,7 @@ async function run(argv, io2 = defaultIO, deps = {}) {
|
|
|
181014
181769
|
code = await commandScratch.run(scratch, () => runCommand(argv, io2, deps));
|
|
181015
181770
|
} finally {
|
|
181016
181771
|
for (const dir of scratch) try {
|
|
181017
|
-
|
|
181772
|
+
rmSync23(dir, { recursive: true, force: true });
|
|
181018
181773
|
} catch {
|
|
181019
181774
|
}
|
|
181020
181775
|
}
|
|
@@ -181314,7 +182069,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
181314
182069
|
return 2;
|
|
181315
182070
|
}
|
|
181316
182071
|
const template = str9(flags.template);
|
|
181317
|
-
const parentDir =
|
|
182072
|
+
const parentDir = resolve64(str9(flags.dir) ?? process.cwd());
|
|
181318
182073
|
const base44AppId = flags["base44-app-id"] === void 0 ? void 0 : String(flags["base44-app-id"]);
|
|
181319
182074
|
const base44AppUrl = flags["base44-app-url"] === void 0 ? void 0 : String(flags["base44-app-url"]);
|
|
181320
182075
|
if (base44AppUrl !== void 0) {
|
|
@@ -181357,7 +182112,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
181357
182112
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
181358
182113
|
next.push(`carried the planning journal into the app (${carried.join(", ")}${owed ? `; ${owed} approval${owed === 1 ? "" : "s"} still owed` : ""}) \u2014 \`himi progress --brief\` there shows it`);
|
|
181359
182114
|
}
|
|
181360
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) =>
|
|
182115
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync82(join87(parentDir, f2)));
|
|
181361
182116
|
if (planInParent.length) {
|
|
181362
182117
|
next.push(`${planInParent.join(" and ")} in ${parentDir} ${planInParent.length > 1 ? "are" : "is"} not the app's \u2014 if that is the approved plan, move it over the template's boilerplate in ${dir}`);
|
|
181363
182118
|
}
|
|
@@ -181518,13 +182273,13 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181518
182273
|
if (adding) {
|
|
181519
182274
|
const from = str9(flags.from);
|
|
181520
182275
|
if (!from) throw new TrimRefusal2('--add <id> needs --from <file> holding the whole new SCREENS entry (` "<id>": { "screenId": "<id>", \u2026 },`)');
|
|
181521
|
-
print(adopt.addScreen(dir, adding,
|
|
182276
|
+
print(adopt.addScreen(dir, adding, readFileSync103(from, "utf8"), { parent: str9(flags.parent), tab: str9(flags.tab), displayName: str9(flags["display-name"]) }));
|
|
181522
182277
|
return 0;
|
|
181523
182278
|
}
|
|
181524
182279
|
if (target) {
|
|
181525
182280
|
const from = str9(flags.from);
|
|
181526
182281
|
if (!from) throw new TrimRefusal2("--write <id> needs --from <file> holding the whole entry, as --show prints it");
|
|
181527
|
-
print(adopt.replaceScreen(dir, target,
|
|
182282
|
+
print(adopt.replaceScreen(dir, target, readFileSync103(from, "utf8")));
|
|
181528
182283
|
return 0;
|
|
181529
182284
|
}
|
|
181530
182285
|
if (show) {
|
|
@@ -181606,7 +182361,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181606
182361
|
const { keepFromSpec: keepFromSpec2 } = await Promise.resolve().then(() => (init_template_adopt(), template_adopt_exports));
|
|
181607
182362
|
const dir = contentDir(flags);
|
|
181608
182363
|
try {
|
|
181609
|
-
const spec = keepFromSpec2(dir, str9(flags["from-spec"]) ??
|
|
182364
|
+
const spec = keepFromSpec2(dir, str9(flags["from-spec"]) ?? join87(dir, "SPEC.md"));
|
|
181610
182365
|
const own5 = typeof keep === "string" ? keep.split(",").map((k2) => k2.trim()).filter(Boolean) : [];
|
|
181611
182366
|
keep = [.../* @__PURE__ */ new Set([...spec.keep, ...own5])].join(",");
|
|
181612
182367
|
fromSpec = { fromSpec: {
|
|
@@ -181647,7 +182402,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181647
182402
|
const result = { ...outcome.result, ...fromSpec };
|
|
181648
182403
|
const adoptDir = contentDir(flags);
|
|
181649
182404
|
const kept = flags["dry-run"] !== true && (outcome.code === 0 || outcome.result.forcedKeep === true);
|
|
181650
|
-
if (kept &&
|
|
182405
|
+
if (kept && existsSync82(join87(adoptDir, adoptBits.ADOPT_FILE))) {
|
|
181651
182406
|
try {
|
|
181652
182407
|
const inv = adoptBits.inspectApp(adoptDir);
|
|
181653
182408
|
adoptBits.writeInventory(adoptDir, inv, { companions: "if-missing" });
|
|
@@ -181672,11 +182427,11 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181672
182427
|
return 2;
|
|
181673
182428
|
}
|
|
181674
182429
|
}
|
|
181675
|
-
const appDir3 =
|
|
181676
|
-
const sourceDir =
|
|
182430
|
+
const appDir3 = resolve64(str9(flags.dir) ?? process.cwd());
|
|
182431
|
+
const sourceDir = resolve64(str9(flags["source-dir"]) ?? appDir3);
|
|
181677
182432
|
let meta;
|
|
181678
182433
|
try {
|
|
181679
|
-
meta = JSON.parse(
|
|
182434
|
+
meta = JSON.parse(readFileSync103(join87(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
181680
182435
|
} catch {
|
|
181681
182436
|
io2.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>)` }));
|
|
181682
182437
|
return 2;
|
|
@@ -181686,7 +182441,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181686
182441
|
return 2;
|
|
181687
182442
|
}
|
|
181688
182443
|
try {
|
|
181689
|
-
const appearance = extractTemplateAppearance(JSON.parse(
|
|
182444
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync103(join87(sourceDir, "tokens.json"), "utf8")));
|
|
181690
182445
|
meta = { ...appearance, ...meta };
|
|
181691
182446
|
} catch {
|
|
181692
182447
|
}
|
|
@@ -181708,14 +182463,14 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181708
182463
|
const force = flags.force === true;
|
|
181709
182464
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
181710
182465
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
181711
|
-
const out2 =
|
|
182466
|
+
const out2 = mkdtempSync6(join87(tmpdir7(), "himi-template-"));
|
|
181712
182467
|
publishScratch.push(out2);
|
|
181713
182468
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
181714
182469
|
const outcome = await buildReleaseFromContent2(buildDir, out2, {
|
|
181715
182470
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
181716
182471
|
collect: { lint: true, strict }
|
|
181717
182472
|
});
|
|
181718
|
-
const scaffoldSourceFindings =
|
|
182473
|
+
const scaffoldSourceFindings = resolve64(sourceDir) === resolve64(appDir3) ? [] : [
|
|
181719
182474
|
...(await Promise.resolve().then(() => (init_capabilities(), capabilities_exports))).capabilityConfigFindings(sourceDir, buildDir),
|
|
181720
182475
|
...tokenColorIssues(sourceDir),
|
|
181721
182476
|
...surfaceIssues(sourceDir, void 0, strict),
|
|
@@ -181761,13 +182516,13 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181761
182516
|
}));
|
|
181762
182517
|
return 1;
|
|
181763
182518
|
}
|
|
181764
|
-
const iconPath = str9(flags.icon) ?
|
|
182519
|
+
const iconPath = str9(flags.icon) ? resolve64(str9(flags.icon)) : templateIconPath(name);
|
|
181765
182520
|
let iconHash;
|
|
181766
182521
|
if (iconPath) {
|
|
181767
182522
|
try {
|
|
181768
|
-
const bytes2 =
|
|
182523
|
+
const bytes2 = readFileSync103(iconPath);
|
|
181769
182524
|
payload.icon = bytes2.toString("base64");
|
|
181770
|
-
iconHash =
|
|
182525
|
+
iconHash = createHash45("sha256").update(bytes2).digest("hex");
|
|
181771
182526
|
} catch {
|
|
181772
182527
|
}
|
|
181773
182528
|
}
|
|
@@ -181943,7 +182698,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
181943
182698
|
} finally {
|
|
181944
182699
|
for (const dir of publishScratch) {
|
|
181945
182700
|
try {
|
|
181946
|
-
|
|
182701
|
+
rmSync23(dir, { recursive: true, force: true });
|
|
181947
182702
|
} catch (e2) {
|
|
181948
182703
|
io2.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e2.message}` }));
|
|
181949
182704
|
}
|
|
@@ -182069,7 +182824,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182069
182824
|
const path2 = dpxSessionTokenPath();
|
|
182070
182825
|
let raw;
|
|
182071
182826
|
try {
|
|
182072
|
-
raw =
|
|
182827
|
+
raw = readFileSync103(path2, "utf8");
|
|
182073
182828
|
} catch {
|
|
182074
182829
|
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`);
|
|
182075
182830
|
}
|
|
@@ -182200,11 +182955,11 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182200
182955
|
return 1;
|
|
182201
182956
|
}
|
|
182202
182957
|
const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
|
|
182203
|
-
const dir =
|
|
182958
|
+
const dir = resolve64(out2);
|
|
182204
182959
|
const files = himiPluginFiles2(skills.skillMd);
|
|
182205
182960
|
for (const f2 of files) {
|
|
182206
|
-
mkdirSync42(
|
|
182207
|
-
writeFileSync39(
|
|
182961
|
+
mkdirSync42(dirname48(join87(dir, f2.path)), { recursive: true });
|
|
182962
|
+
writeFileSync39(join87(dir, f2.path), f2.text);
|
|
182208
182963
|
}
|
|
182209
182964
|
print({ ok: true, dir, files: files.map((f2) => f2.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
182210
182965
|
return 0;
|
|
@@ -182214,22 +182969,22 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182214
182969
|
run,
|
|
182215
182970
|
version: cliVersion(),
|
|
182216
182971
|
withFiles: flags["with-files"] === true,
|
|
182217
|
-
...process.env.HIMI_WORKSPACE ? { workspace:
|
|
182972
|
+
...process.env.HIMI_WORKSPACE ? { workspace: resolve64(process.env.HIMI_WORKSPACE) } : {}
|
|
182218
182973
|
});
|
|
182219
182974
|
return 0;
|
|
182220
182975
|
}
|
|
182221
182976
|
case "studio": {
|
|
182222
182977
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
182223
182978
|
const dir = contentDir(flags);
|
|
182224
|
-
if (!
|
|
182979
|
+
if (!existsSync82(join87(dir, "himalaya.content.json"))) {
|
|
182225
182980
|
io2.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
|
|
182226
182981
|
return 2;
|
|
182227
182982
|
}
|
|
182228
182983
|
if (pos[1] === "reel") {
|
|
182229
182984
|
const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
|
|
182230
|
-
const out2 =
|
|
182985
|
+
const out2 = resolve64(str9(flags.out) ?? join87(dir, ".himi", "making-of.html"));
|
|
182231
182986
|
const { html, plan } = buildReel2(dir);
|
|
182232
|
-
mkdirSync42(
|
|
182987
|
+
mkdirSync42(dirname48(out2), { recursive: true });
|
|
182233
182988
|
writeFileSync39(out2, html);
|
|
182234
182989
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
182235
182990
|
const url2 = pathToFileURL9(out2).href;
|
|
@@ -182238,7 +182993,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
182238
182993
|
const { openUrl: openUrl2 } = await Promise.resolve().then(() => (init_open_url(), open_url_exports));
|
|
182239
182994
|
openUrl2(url2);
|
|
182240
182995
|
}
|
|
182241
|
-
const handover = { file: out2, hint: `hand ${
|
|
182996
|
+
const handover = { file: out2, hint: `hand ${basename21(out2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` };
|
|
182242
182997
|
const report3 = {
|
|
182243
182998
|
ok: true,
|
|
182244
182999
|
file: out2,
|
|
@@ -182299,7 +183054,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182299
183054
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
182300
183055
|
const dir = contentDir(flags);
|
|
182301
183056
|
const journal2 = journalPath2(dir);
|
|
182302
|
-
const isContentPackage =
|
|
183057
|
+
const isContentPackage = existsSync82(join87(dir, "himalaya.content.json"));
|
|
182303
183058
|
const hint = isContentPackage ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
|
|
182304
183059
|
const message = pos.slice(1).join(" ").trim();
|
|
182305
183060
|
const approvalFlags = ["approve", "done", "drop"].filter((f2) => flags[f2] !== void 0);
|
|
@@ -182451,7 +183206,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182451
183206
|
case "test": {
|
|
182452
183207
|
const dir = contentDir(flags);
|
|
182453
183208
|
const structuredOutput = flags.json === true || io2.isTTY !== true;
|
|
182454
|
-
if (
|
|
183209
|
+
if (existsSync82(join87(dir, "functions"))) {
|
|
182455
183210
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
182456
183211
|
const loaded = await loadFunctionsApp2(dir);
|
|
182457
183212
|
const results = [];
|
|
@@ -182583,7 +183338,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182583
183338
|
io2.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
182584
183339
|
return 2;
|
|
182585
183340
|
}
|
|
182586
|
-
const sources = collectWorkerSources2(
|
|
183341
|
+
const sources = collectWorkerSources2(join87(dir, "tier5-src"), screen.bundleName);
|
|
182587
183342
|
if (!sources) {
|
|
182588
183343
|
io2.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
182589
183344
|
return 2;
|
|
@@ -182761,7 +183516,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182761
183516
|
const sp = await runShotsPass2({
|
|
182762
183517
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
182763
183518
|
tokens: outcome.tokens,
|
|
182764
|
-
outDir:
|
|
183519
|
+
outDir: join87(dir, ".himi", "shots"),
|
|
182765
183520
|
width: 390,
|
|
182766
183521
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
182767
183522
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -182772,7 +183527,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182772
183527
|
renderPngBatch: renderPngBatch2,
|
|
182773
183528
|
isUnserved: isUnservedRequest2,
|
|
182774
183529
|
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
182775
|
-
clearDir: (d2) =>
|
|
183530
|
+
clearDir: (d2) => rmSync23(d2, { recursive: true, force: true })
|
|
182776
183531
|
}
|
|
182777
183532
|
});
|
|
182778
183533
|
writtenShots = sp.written;
|
|
@@ -182801,7 +183556,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
182801
183556
|
releaseId: result.releaseId,
|
|
182802
183557
|
releasePayload: release2,
|
|
182803
183558
|
descriptors: attestedDescriptors,
|
|
182804
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
183559
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join87(dir, ".himi", "shots", name)])),
|
|
182805
183560
|
coverage: {
|
|
182806
183561
|
screens: crawledScreens.size,
|
|
182807
183562
|
actionsDispatched: result.actions.exercised,
|
|
@@ -182926,7 +183681,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
182926
183681
|
return 2;
|
|
182927
183682
|
}
|
|
182928
183683
|
try {
|
|
182929
|
-
const raw = stateArg.trim().startsWith("{") ? stateArg :
|
|
183684
|
+
const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync103(stateArg.replace(/^@/, ""), "utf8");
|
|
182930
183685
|
injectedState = JSON.parse(raw);
|
|
182931
183686
|
} catch (e2) {
|
|
182932
183687
|
io2.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e2.message}` }));
|
|
@@ -182941,7 +183696,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
182941
183696
|
return 2;
|
|
182942
183697
|
}
|
|
182943
183698
|
try {
|
|
182944
|
-
const raw = inputArg.trim().startsWith("{") ? inputArg :
|
|
183699
|
+
const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync103(inputArg.replace(/^@/, ""), "utf8");
|
|
182945
183700
|
const parsed = JSON.parse(raw);
|
|
182946
183701
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
|
|
182947
183702
|
injectedInput = parsed;
|
|
@@ -183023,11 +183778,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
183023
183778
|
const diagnostics = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
|
|
183024
183779
|
let pngFile;
|
|
183025
183780
|
let attestationPngFile;
|
|
183026
|
-
const shotPath =
|
|
183781
|
+
const shotPath = join87(dir, ".himi", "shots", `${screenId}.png`);
|
|
183027
183782
|
const pngTarget = typeof flags.png === "string" ? str9(flags.png) : flags.png === true ? shotPath : void 0;
|
|
183028
183783
|
if (pngTarget && r2.pngBase64) {
|
|
183029
183784
|
pngFile = writePngFile(pngTarget, r2.pngBase64);
|
|
183030
|
-
attestationPngFile =
|
|
183785
|
+
attestationPngFile = resolve64(pngTarget) === resolve64(shotPath) ? pngFile : writePngFile(shotPath, r2.pngBase64);
|
|
183031
183786
|
}
|
|
183032
183787
|
if (renderWidth !== void 0 && r2.renderable) {
|
|
183033
183788
|
recordRenderWidth(dir, {
|
|
@@ -183374,7 +184129,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183374
184129
|
return 2;
|
|
183375
184130
|
}
|
|
183376
184131
|
const renamed = str9(flags.name);
|
|
183377
|
-
const dest =
|
|
184132
|
+
const dest = resolve64(str9(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
183378
184133
|
const replace = flags.replace === true;
|
|
183379
184134
|
const force = replace || flags.force === true;
|
|
183380
184135
|
const linked = symlinkDestinationIssue(dest);
|
|
@@ -183382,7 +184137,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183382
184137
|
io2.error(JSON.stringify(linked));
|
|
183383
184138
|
return 1;
|
|
183384
184139
|
}
|
|
183385
|
-
if (
|
|
184140
|
+
if (existsSync82(dest)) {
|
|
183386
184141
|
if (!statSync23(dest).isDirectory()) {
|
|
183387
184142
|
io2.error(JSON.stringify({
|
|
183388
184143
|
error: `${dest} exists and is not a directory`,
|
|
@@ -183395,7 +184150,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183395
184150
|
io2.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" }));
|
|
183396
184151
|
return 1;
|
|
183397
184152
|
}
|
|
183398
|
-
if (replace && occupied && !
|
|
184153
|
+
if (replace && occupied && !existsSync82(join87(dest, "himalaya.content.json"))) {
|
|
183399
184154
|
io2.error(JSON.stringify({
|
|
183400
184155
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
183401
184156
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -183564,7 +184319,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183564
184319
|
const manifest = outcome.manifest;
|
|
183565
184320
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
183566
184321
|
const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
|
|
183567
|
-
const contentRel =
|
|
184322
|
+
const contentRel = relative16(process.cwd(), dir) || ".";
|
|
183568
184323
|
const contentArg2 = shellQuote3(contentRel);
|
|
183569
184324
|
if (onlyRaw !== void 0) {
|
|
183570
184325
|
const onlyDraft = flags.draft === true;
|
|
@@ -183626,7 +184381,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
183626
184381
|
let localSourceHash;
|
|
183627
184382
|
try {
|
|
183628
184383
|
const { collectAppSource: collectAppSource2, zipAppSource: zipAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
183629
|
-
localSourceHash =
|
|
184384
|
+
localSourceHash = createHash45("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
|
|
183630
184385
|
} catch {
|
|
183631
184386
|
}
|
|
183632
184387
|
return runReleasePatch({
|
|
@@ -184054,7 +184809,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184054
184809
|
return 2;
|
|
184055
184810
|
}
|
|
184056
184811
|
try {
|
|
184057
|
-
const res = writePack(
|
|
184812
|
+
const res = writePack(resolve64(releaseDir), only, resolve64(str9(flags.out) ?? process.cwd()));
|
|
184058
184813
|
print({
|
|
184059
184814
|
ok: true,
|
|
184060
184815
|
app: res.app,
|
|
@@ -184103,7 +184858,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184103
184858
|
}
|
|
184104
184859
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
184105
184860
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
184106
|
-
const built =
|
|
184861
|
+
const built = mkdtempSync6(join87(tmpdir7(), "himi-pack-"));
|
|
184107
184862
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
184108
184863
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
184109
184864
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -184122,12 +184877,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184122
184877
|
...await navIssues2(dir, strict)
|
|
184123
184878
|
]);
|
|
184124
184879
|
if (hasErrors && !force) {
|
|
184125
|
-
|
|
184880
|
+
rmSync23(built, { recursive: true, force: true });
|
|
184126
184881
|
print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
184127
184882
|
return 1;
|
|
184128
184883
|
}
|
|
184129
184884
|
try {
|
|
184130
|
-
const res = writePack(built, app,
|
|
184885
|
+
const res = writePack(built, app, resolve64(str9(flags.out) ?? dir), sourceArchive);
|
|
184131
184886
|
print({
|
|
184132
184887
|
ok: true,
|
|
184133
184888
|
app: res.app,
|
|
@@ -184158,7 +184913,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184158
184913
|
io2.error(JSON.stringify({ error: e2.message }));
|
|
184159
184914
|
return 1;
|
|
184160
184915
|
} finally {
|
|
184161
|
-
|
|
184916
|
+
rmSync23(built, { recursive: true, force: true });
|
|
184162
184917
|
}
|
|
184163
184918
|
}
|
|
184164
184919
|
// ---- himi import — turn a dev .himi back into an editable content package ----
|
|
@@ -184172,7 +184927,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184172
184927
|
const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
|
|
184173
184928
|
let opened;
|
|
184174
184929
|
try {
|
|
184175
|
-
opened = openPackageFile2(
|
|
184930
|
+
opened = openPackageFile2(resolve64(file2));
|
|
184176
184931
|
} catch (e2) {
|
|
184177
184932
|
io2.error(JSON.stringify({ error: e2.message }));
|
|
184178
184933
|
return 1;
|
|
@@ -184185,7 +184940,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184185
184940
|
io2.error(JSON.stringify({
|
|
184186
184941
|
ok: false,
|
|
184187
184942
|
error: "app_source_not_in_package",
|
|
184188
|
-
detail: `${
|
|
184943
|
+
detail: `${resolve64(file2)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
|
|
184189
184944
|
hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
|
|
184190
184945
|
}));
|
|
184191
184946
|
return 1;
|
|
@@ -184208,7 +184963,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184208
184963
|
return 1;
|
|
184209
184964
|
}
|
|
184210
184965
|
}
|
|
184211
|
-
const dest =
|
|
184966
|
+
const dest = resolve64(str9(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
|
|
184212
184967
|
const issue2 = restoreDestinationIssue(dest, flags.force === true);
|
|
184213
184968
|
if (issue2) {
|
|
184214
184969
|
io2.error(JSON.stringify(issue2));
|
|
@@ -184295,7 +185050,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184295
185050
|
}
|
|
184296
185051
|
try {
|
|
184297
185052
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
184298
|
-
const opened = openPackageFile2(
|
|
185053
|
+
const opened = openPackageFile2(resolve64(file2));
|
|
184299
185054
|
if (!opened.validation.ok || !opened.header) {
|
|
184300
185055
|
io2.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
184301
185056
|
return 1;
|
|
@@ -184305,12 +185060,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184305
185060
|
io2.error(JSON.stringify({
|
|
184306
185061
|
ok: false,
|
|
184307
185062
|
error: "refusing to share a package that carries the app's source",
|
|
184308
|
-
detail: `${
|
|
185063
|
+
detail: `${resolve64(file2)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
|
|
184309
185064
|
hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
|
|
184310
185065
|
}));
|
|
184311
185066
|
return 1;
|
|
184312
185067
|
}
|
|
184313
|
-
const archive =
|
|
185068
|
+
const archive = readFileSync103(resolve64(file2));
|
|
184314
185069
|
const result = await client2().createPackageShare({
|
|
184315
185070
|
app: opened.header.app,
|
|
184316
185071
|
releaseId: opened.header.releaseId,
|
|
@@ -184407,11 +185162,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184407
185162
|
const app = await appId(dir2);
|
|
184408
185163
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
184409
185164
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
184410
|
-
temp =
|
|
185165
|
+
temp = mkdtempSync6(join87(tmpdir7(), "himi-run-build-"));
|
|
184411
185166
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
184412
185167
|
const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
|
|
184413
185168
|
servedMissing = initial.missingBundles;
|
|
184414
|
-
source =
|
|
185169
|
+
source = join87(temp, app);
|
|
184415
185170
|
}
|
|
184416
185171
|
const chromeArg = str9(flags.chrome) ?? "preview";
|
|
184417
185172
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -184450,7 +185205,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184450
185205
|
if (!recordKit) return;
|
|
184451
185206
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
184452
185207
|
const failure = record2(served2, { ok: true, at: startedAt });
|
|
184453
|
-
if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${
|
|
185208
|
+
if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join87(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
|
|
184454
185209
|
await refreshBoard();
|
|
184455
185210
|
};
|
|
184456
185211
|
const retract = async () => {
|
|
@@ -184473,9 +185228,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184473
185228
|
});
|
|
184474
185229
|
await announce(run2);
|
|
184475
185230
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
184476
|
-
await new Promise((
|
|
185231
|
+
await new Promise((resolve65) => {
|
|
184477
185232
|
const stop = () => {
|
|
184478
|
-
void retract().catch((e2) => io2.error(JSON.stringify({ run: "stop_cleanup_failed", message: e2.message }))).finally(() => run2.close().finally(() =>
|
|
185233
|
+
void retract().catch((e2) => io2.error(JSON.stringify({ run: "stop_cleanup_failed", message: e2.message }))).finally(() => run2.close().finally(() => resolve65()));
|
|
184479
185234
|
};
|
|
184480
185235
|
dropEarlySignals?.();
|
|
184481
185236
|
process.once("SIGINT", stop);
|
|
@@ -184486,7 +185241,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184486
185241
|
const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
|
|
184487
185242
|
const hhpPreviewRoute = watch2 ? (await Promise.resolve().then(() => (init_hhp_preview(), hhp_preview_exports))).hhpPreviewResponse : null;
|
|
184488
185243
|
const bus = watchKit ? new watchKit.ReloadBus() : void 0;
|
|
184489
|
-
if (watch2) served =
|
|
185244
|
+
if (watch2) served = mkdtempSync6(join87(tmpdir7(), "himi-run-served-"));
|
|
184490
185245
|
const running = await runPackage2(source, {
|
|
184491
185246
|
port,
|
|
184492
185247
|
chrome: chromeArg,
|
|
@@ -184515,8 +185270,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184515
185270
|
await announce(running);
|
|
184516
185271
|
if (watchKit && bus) {
|
|
184517
185272
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
184518
|
-
const live3 =
|
|
184519
|
-
const manifestOf = (tree) => JSON.parse(
|
|
185273
|
+
const live3 = join87(running.releaseRoot, running.app);
|
|
185274
|
+
const manifestOf = (tree) => JSON.parse(readFileSync103(join87(tree, "release-manifest.json"), "utf8"));
|
|
184520
185275
|
let current = manifestOf(live3);
|
|
184521
185276
|
const failed3 = async (message) => {
|
|
184522
185277
|
if (stopping) return;
|
|
@@ -184527,7 +185282,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184527
185282
|
};
|
|
184528
185283
|
rebuild = watchKit.serialize(async () => {
|
|
184529
185284
|
const t0 = Date.now();
|
|
184530
|
-
const next =
|
|
185285
|
+
const next = mkdtempSync6(join87(tmpdir7(), "himi-run-build-"));
|
|
184531
185286
|
try {
|
|
184532
185287
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
184533
185288
|
if (bres.compileErrors.length) {
|
|
@@ -184544,18 +185299,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184544
185299
|
return;
|
|
184545
185300
|
}
|
|
184546
185301
|
if (stopping) return;
|
|
184547
|
-
const fresh = manifestOf(
|
|
185302
|
+
const fresh = manifestOf(join87(next, running.app));
|
|
184548
185303
|
const diff = watchKit.diffReleases(current, fresh);
|
|
184549
185304
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
184550
|
-
const changes = describeChanges2(live3,
|
|
185305
|
+
const changes = describeChanges2(live3, join87(next, running.app), diff);
|
|
184551
185306
|
const retired = `${live3}.retired-${Date.now()}`;
|
|
184552
|
-
|
|
185307
|
+
renameSync13(live3, retired);
|
|
184553
185308
|
try {
|
|
184554
|
-
|
|
185309
|
+
renameSync13(join87(next, running.app), live3);
|
|
184555
185310
|
} catch {
|
|
184556
|
-
cpSync3(
|
|
185311
|
+
cpSync3(join87(next, running.app), live3, { recursive: true });
|
|
184557
185312
|
}
|
|
184558
|
-
|
|
185313
|
+
rmSync23(retired, { recursive: true, force: true });
|
|
184559
185314
|
current = fresh;
|
|
184560
185315
|
servedMissing = outcome.missingBundles;
|
|
184561
185316
|
for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
|
|
@@ -184565,7 +185320,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184565
185320
|
} catch (e2) {
|
|
184566
185321
|
await failed3(e2.message.split("\n")[0]);
|
|
184567
185322
|
} finally {
|
|
184568
|
-
|
|
185323
|
+
rmSync23(next, { recursive: true, force: true });
|
|
184569
185324
|
}
|
|
184570
185325
|
});
|
|
184571
185326
|
watcher2 = watchKit.watchContent(dir, () => {
|
|
@@ -184636,9 +185391,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
184636
185391
|
} finally {
|
|
184637
185392
|
dropEarlySignals?.();
|
|
184638
185393
|
dropInitRecord?.();
|
|
184639
|
-
if (temp)
|
|
184640
|
-
if (served)
|
|
184641
|
-
if (browserCopy)
|
|
185394
|
+
if (temp) rmSync23(temp, { recursive: true, force: true });
|
|
185395
|
+
if (served) rmSync23(served, { recursive: true, force: true });
|
|
185396
|
+
if (browserCopy) rmSync23(browserCopy, { recursive: true, force: true });
|
|
184642
185397
|
}
|
|
184643
185398
|
}
|
|
184644
185399
|
case "preview": {
|
|
@@ -185180,7 +185935,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185180
185935
|
io2.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
185181
185936
|
return 2;
|
|
185182
185937
|
}
|
|
185183
|
-
if (!
|
|
185938
|
+
if (!existsSync82(file2)) {
|
|
185184
185939
|
io2.error(JSON.stringify({ error: `no such file: ${file2}` }));
|
|
185185
185940
|
return 2;
|
|
185186
185941
|
}
|
|
@@ -185236,7 +185991,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185236
185991
|
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."
|
|
185237
185992
|
};
|
|
185238
185993
|
if (kind === "tokens" || kind === "app-config") {
|
|
185239
|
-
const body =
|
|
185994
|
+
const body = readFileSync103(file2, "utf8");
|
|
185240
185995
|
const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
|
|
185241
185996
|
return runReleasePatch({
|
|
185242
185997
|
...common,
|
|
@@ -185251,7 +186006,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185251
186006
|
io2.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
|
|
185252
186007
|
return 2;
|
|
185253
186008
|
}
|
|
185254
|
-
const descriptor =
|
|
186009
|
+
const descriptor = readFileSync103(file2, "utf8");
|
|
185255
186010
|
try {
|
|
185256
186011
|
JSON.parse(descriptor);
|
|
185257
186012
|
} catch (e2) {
|
|
@@ -185291,8 +186046,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185291
186046
|
extra: { kind, screen: id, file: { path: file2, bytes: Buffer.byteLength(descriptor, "utf8") } }
|
|
185292
186047
|
});
|
|
185293
186048
|
}
|
|
185294
|
-
const bytes2 =
|
|
185295
|
-
const sha2 =
|
|
186049
|
+
const bytes2 = readFileSync103(file2);
|
|
186050
|
+
const sha2 = createHash45("sha256").update(bytes2).digest("hex");
|
|
185296
186051
|
const forScreens = (str9(flags["for-screen"]) ?? "").split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
185297
186052
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
185298
186053
|
io2.error(JSON.stringify({ ok: false, error: "no_rebind_takes_no_value", message: "--no-rebind is a switch and takes no value; pass it bare.", usage: PATCH_USAGE }));
|
|
@@ -185435,7 +186190,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185435
186190
|
}
|
|
185436
186191
|
let def;
|
|
185437
186192
|
try {
|
|
185438
|
-
const parsed = JSON.parse(arg.startsWith("@") ?
|
|
186193
|
+
const parsed = JSON.parse(arg.startsWith("@") ? readFileSync103(arg.slice(1), "utf8") : arg);
|
|
185439
186194
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
185440
186195
|
io2.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
|
|
185441
186196
|
return 2;
|
|
@@ -185717,7 +186472,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
185717
186472
|
const rememberLastDist = async (jobs2) => {
|
|
185718
186473
|
try {
|
|
185719
186474
|
const dir = contentDir(flags);
|
|
185720
|
-
if (!
|
|
186475
|
+
if (!existsSync82(join87(dir, "himalaya.content.json"))) return;
|
|
185721
186476
|
const { lastDistFromJob: lastDistFromJob2, writeLastDist: writeLastDist2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
|
|
185722
186477
|
const own5 = await appId(dir);
|
|
185723
186478
|
for (const job of jobs2) {
|
|
@@ -185957,7 +186712,7 @@ ${label2}`);
|
|
|
185957
186712
|
const platform = str9(flags.platform)?.split(",").map((p2) => p2.trim()).filter(Boolean);
|
|
185958
186713
|
{
|
|
185959
186714
|
const distDir = contentDir(flags);
|
|
185960
|
-
if (
|
|
186715
|
+
if (existsSync82(join87(distDir, "himalaya.content.json"))) {
|
|
185961
186716
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
185962
186717
|
const errors = issues.filter((i2) => i2.severity === "error");
|
|
185963
186718
|
for (const i2 of issues.filter((i3) => i3.severity === "warning")) {
|
|
@@ -186297,7 +187052,7 @@ ${label2}`);
|
|
|
186297
187052
|
const dpxPath = dpxSessionTokenPath();
|
|
186298
187053
|
let dpx;
|
|
186299
187054
|
try {
|
|
186300
|
-
dpx =
|
|
187055
|
+
dpx = readFileSync103(dpxPath, "utf8").trim();
|
|
186301
187056
|
} catch {
|
|
186302
187057
|
io2.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` }));
|
|
186303
187058
|
return 1;
|
|
@@ -186760,7 +187515,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
186760
187515
|
const path2 = dpxSessionTokenPath();
|
|
186761
187516
|
let raw;
|
|
186762
187517
|
try {
|
|
186763
|
-
raw =
|
|
187518
|
+
raw = readFileSync103(path2, "utf8");
|
|
186764
187519
|
} catch {
|
|
186765
187520
|
io2.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
186766
187521
|
return 1;
|