@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/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((resolve63, reject) => {
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(() => resolve63({ token, loginUrl, extra }));
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((resolve63, reject) => {
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(() => resolve63(m2[0]));
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(() => resolve63(m2[0]));
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 relative16 = committedProvisioningPath(name);
4164
- return normalized === relative16 || normalized.endsWith(`/${relative16}`);
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 relative16 = statePath(raw);
6880
- if (!info4?.paths.has(relative16)) error(el2, "HHP-BINDING-PATH", `Unknown controller state path ${relative16}.`);
6881
- return `$service:${serviceName}.${relative16}`;
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((resolve63) => {
25437
+ portFree: (port) => new Promise((resolve65) => {
25437
25438
  const s2 = createServer2();
25438
- s2.once("error", () => resolve63(false));
25439
- s2.listen(port, "127.0.0.1", () => s2.close(() => resolve63(true)));
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((resolve63, reject) => {
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
- resolve63(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
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((resolve63) => {
35584
+ await new Promise((resolve65) => {
35584
35585
  let done = false;
35585
35586
  const finish2 = () => {
35586
35587
  if (!done) {
35587
35588
  done = true;
35588
- resolve63();
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((resolve63, reject) => {
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(resolve63, Buffer.concat(out2));
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((resolve63) => {
38035
+ return new Promise((resolve65) => {
38035
38036
  const timer = t2.setTimeout(() => {
38036
38037
  flushes.delete(requestId2);
38037
- resolve63(null);
38038
+ resolve65(null);
38038
38039
  }, flushMs);
38039
- flushes.set(requestId2, { resolve: resolve63, timer });
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((resolve63) => {
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
- resolve63(v2);
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((resolve63, reject) => {
38630
+ return new Promise((resolve65, reject) => {
38630
38631
  const stop = () => reject(new Deadline());
38631
38632
  onExpire.push(stop);
38632
- p2.then(resolve63, reject).finally(() => {
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((resolve63, reject) => {
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
- resolve63(v2);
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
- resolve63(now);
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 select = (i2) => {
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) select(ni2);
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) select(i2);
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: () => select(i2),
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 select = (i2) => {
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) select(ni2);
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: () => select(i2),
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((resolve63, reject) => {
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
- resolve63(new Uint8Array(request.response));
40839
+ resolve65(new Uint8Array(request.response));
40839
40840
  return;
40840
40841
  case "blob":
40841
40842
  case "json":
40842
- resolve63(request.response);
40843
+ resolve65(request.response);
40843
40844
  return;
40844
40845
  }
40845
- resolve63(request.responseText);
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 join86 = uncurryThis([].join);
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 = join86(TEMPLATE, typeof name == "string" ? name : "");
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 resolve63, reject;
43850
+ var resolve65, reject;
43850
43851
  this.promise = new C2(function($$resolve, $$reject) {
43851
- if (resolve63 !== void 0 || reject !== void 0) throw new $TypeError("Bad Promise constructor");
43852
- resolve63 = $$resolve;
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(resolve63);
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 resolve63 = promiseCapability.resolve;
44224
- resolve63(x2);
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 join86 = uncurryThis([].join);
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 join86(result, "");
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 join86 = uncurryThis([].join);
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 join86(result, "");
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((resolve63, reject) => {
48079
+ const imagePromise = new Promise((resolve65, reject) => {
48079
48080
  imageElement.onload = () => {
48080
48081
  data.bitmap = imageElement;
48081
48082
  data.isSvg = true;
48082
- resolve63();
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: resolve63,
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
- resolve63();
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((resolve63) => {
53813
- const request = this._queueLoadingCallback(resolve63);
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((resolve63) => {
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
- resolve63();
70869
+ resolve65();
70869
70870
  }, {
70870
70871
  signal
70871
70872
  });
70872
70873
  input.addEventListener("cancel", () => {
70873
70874
  this.remove();
70874
- resolve63();
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 select = React9.useCallback((next) => {
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
- select(index + 1);
125216
+ select2(index + 1);
125216
125217
  break;
125217
125218
  case "previous":
125218
- select(index - 1);
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, select, toggleFullscreen]);
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
- select(index + 1);
125300
+ select2(index + 1);
125300
125301
  return;
125301
125302
  case "media.previous":
125302
- select(index - 1);
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: () => select(index - 1), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u25C0\u25C0" }),
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: () => select(index + 1), style: { color: "inherit", background: "transparent", border: 0, fontSize: pxToRem(18) }, children: "\u25B6\u25B6" }),
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
- select(index + 1);
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 select = (index) => {
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
- select(next);
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
- select(index);
127745
+ select2(index);
127745
127746
  },
127746
127747
  onScroll: (event) => {
127747
- if (!boundRail && event.currentTarget.clientWidth > 0) select(Math.max(0, Math.min(pages2.length - 1, Math.round(event.currentTarget.scrollLeft / event.currentTarget.clientWidth))));
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, resolve63) {
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 || !resolve63 || typeof v2 !== "string" || !isDynamicValue(v2)) return lit;
129154
- const r2 = resolve63(v2);
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, resolve63);
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, resolve63) {
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 = resolve63 ? resolve63(binding2) : void 0;
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((resolve63) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve63())));
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((resolve63) => setTimeout(resolve63, mocked.delayMs));
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((resolve63) => {
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
- resolve63();
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((resolve63) => setTimeout(resolve63, mocked.delayMs));
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 relative16 = requested.replace(prefix, "").replace(/^\//, "");
133413
- const safe = normalize3(relative16).replace(/^(\.\.[\/\\])+/, "");
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, resolve63) {
134578
- if (typeof v2 === "string") return v2.startsWith("$service:") ? resolve63(v2) : v2;
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 = resolve63(el2);
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, resolve63) {
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, resolve63) : void 0;
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, resolve63, tokens2) {
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, resolve63);
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, resolve63);
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, resolve63);
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 : resolve63(binding2);
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
- const out2 = await base(method, path2, body);
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 bus = hostDispatch(opts.localDbSchema, declaredCapabilitiesOf(opts.descriptor));
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: opts.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((resolve63, reject) => {
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
- resolve63(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
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((resolve63, reject) => {
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(() => resolve63({ value: message.value, durationMs: Date.now() - started }));
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((resolve63) => {
155119
+ return new Promise((resolve65) => {
155060
155120
  let answered = false;
155061
155121
  const answer = () => {
155062
155122
  if (answered) return;
155063
155123
  answered = true;
155064
- resolve63(current);
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((resolve63) => {
155188
- stdin.once("end", resolve63);
155189
- stdin.once("close", resolve63);
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(resolve63) {
155629
+ function sdkSubpathReader(resolve65) {
155570
155630
  return (sub) => {
155571
155631
  try {
155572
- return readFileSync79(resolve63(`@wix/himalaya/${sub}`), "utf8");
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((resolve63, reject) => {
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(() => resolve63({ report: report3, url }));
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((resolve63) => setTimeout(resolve63, ms2)));
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
- function remainingRequirements(observed) {
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
- remainingRequirements: [...input.requirements ?? [], ...remainingRequirements(observed)],
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) plans.set(i2, await planItem(pricing, context.api, manifest.items[i2], products, isoDay(context.now())));
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
- if (!knownShape || !localeOk || !priceOk) throw planError(`plan item ${item.productId} has an unknown operation ${JSON.stringify(op)}`);
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, p2] of plans.entries()) {
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
- OP_KINDS = /* @__PURE__ */ new Set(["createProduct", "createVersion", "createLocalization", "updateLocalization", "setPrice", "changePrice", "setAvailability"]);
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 replanned = await planForProduct(context.api, run2.item, product, context.pricing, context.now().toISOString().slice(0, 10));
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
- return product ? { observed: await observeProduct(context.api, product, context.now().toISOString().slice(0, 10)) } : { failure: "Apple does not return it yet" };
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
- return metadataDiffs(item, planned2.observed, planned2.targetPrice ?? await context.pricing.targetAmount(item.price));
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 context = { ...applyContext, pricing: applyContext.pricing ?? new PriceGrid(applyContext.api) };
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 createHash38 } from "node:crypto";
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:${createHash38("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
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 createHash39 } from "node:crypto";
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) => createHash39("sha256").update(text9).digest("hex");
160830
+ sha = (text9) => createHash40("sha256").update(text9).digest("hex");
160431
160831
  ENTITIES = { "&amp;": "&", "&nbsp;": " ", "&lt;": "<", "&gt;": ">", "&quot;": '"', "&#39;": "'" };
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 basename18, join as join75 } from "node:path";
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: [`${basename18(path2)} is a symlink, so it would not be edited: add the purchases app in the file it points to.`] };
160835
- const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync90(path2, "utf8"), { ...withStoreBundle(dir, options), fileName: basename18(path2) });
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 = basename18(path2);
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(/&nbsp;|&#160;|&#xa0;/gi, "\xA0").replace(/&amp;/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 readFileSync91, realpathSync as realpathSync13, rmSync as rmSync18, writeFileSync as writeFileSync30 } from "node:fs";
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 join76 } from "node:path";
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 = { api: session.api, identity: session.identity, now: deps.now, sleep: deps.sleep, journal: session.journal };
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(readFileSync91(path2, "utf8"));
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 = join76(dir, "apply.lock");
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 = readFileSync91(path2, "utf8");
162583
+ current = readFileSync92(path2, "utf8");
161840
162584
  } catch {
161841
162585
  return;
161842
162586
  }
161843
- if (current === stamp) rmSync18(path2, { force: true });
162587
+ if (current === stamp) rmSync19(path2, { force: true });
161844
162588
  };
161845
162589
  }
161846
162590
  function stateDir(appleAppId) {
161847
- const dir = join76(homedir11(), ".himalaya", "store-iap", appleAppId);
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) => readFileSync91(path2, "utf8"),
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(join76(stateDir(appleAppId), "journal.jsonl")),
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((resolve63) => setTimeout(resolve63, ms2))
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: () => jpegSize,
163087
+ jpegSize: () => jpegSize2,
162340
163088
  playListingAssets: () => playListingAssets,
162341
- pngSize: () => pngSize,
163089
+ pngSize: () => pngSize2,
162342
163090
  preflightApp: () => preflightApp,
162343
163091
  profileAccount: () => profileAccount
162344
163092
  });
162345
- import { readFileSync as readFileSync92, existsSync as existsSync75, readdirSync as readdirSync34, statSync as statSync21 } from "node:fs";
162346
- import { createHash as createHash40 } from "node:crypto";
162347
- import { join as join77 } from "node:path";
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 = existsSync75(iosProjectYml(app)) ? readFileSync92(iosProjectYml(app), "utf8") : "";
162412
- const storeConfig = existsSync75(storeConfigPath(app)) ? readFileSync92(storeConfigPath(app), "utf8") : "";
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(join77(appDir(app), "ios")),
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 = join77(storeDir(app), "metadata");
163194
+ const root = join79(storeDir(app), "metadata");
162447
163195
  const out2 = /* @__PURE__ */ new Set();
162448
- if (existsSync75(root)) {
163196
+ if (existsSync76(root)) {
162449
163197
  for (const n2 of readdirSync34(root)) if (n2.endsWith(".txt")) out2.add(n2);
162450
163198
  }
162451
- if (existsSync75(join77(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
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 = join77(storeDir(app), "review_information");
162456
- if (!existsSync75(dir)) return /* @__PURE__ */ new Set();
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 pngSize(buf) {
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 jpegSize(buf) {
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 ? pngSize(bytes2) : jpegSize(bytes2);
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 = join77(storeDir(app), "play", locale, "images");
163314
+ const dir = join79(storeDir(app), "play", locale, "images");
162567
163315
  const read = (names) => {
162568
163316
  for (const name of names) {
162569
- const p2 = join77(dir, name);
163317
+ const p2 = join79(dir, name);
162570
163318
  try {
162571
- if (statSync21(p2).isFile()) return { name, bytes: readFileSync92(p2) };
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 = join77(storeDir(app), "metadata", locale);
162603
- if (!existsSync75(dir)) return /* @__PURE__ */ new Set();
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 = join77(storeDir(app), "screenshots", locale);
162609
- if (existsSync75(flat)) {
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 = pngSize(readFileSync92(join77(flat, png)));
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 = join77(storeDir(app), "metadata", locale, "screenshots");
162616
- if (existsSync75(legacy)) {
163363
+ const legacy = join79(storeDir(app), "metadata", locale, "screenshots");
163364
+ if (existsSync76(legacy)) {
162617
163365
  for (const deviceDir of readdirSync34(legacy)) {
162618
- const d2 = join77(legacy, deviceDir);
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 = pngSize(readFileSync92(join77(d2, png)));
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 = join77(appDir("_template"), "ios");
162630
- if (!existsSync75(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
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 = join77(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
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, createHash40("sha256").update(readFileSync92(p2)).digest("hex")];
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 (!existsSync75(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
163414
+ if (!existsSync76(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
162667
163415
  for (const target of readdirSync34(iosDir)) {
162668
- const p2 = join77(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
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 = readFileSync92(p2);
162672
- const hash2 = createHash40("sha256").update(bytes2).digest("hex");
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 readFileSync93 } from "node:fs";
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, readFileSync93(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
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 dirname40 } from "node:path";
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(dirname40(filePath), { recursive: true });
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 readFileSync94 } from "node:fs";
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() : readFileSync94(0, "utf8").replace(/\r?\n$/, "");
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() : readFileSync94(0, "utf8").replace(/\r?\n$/, "");
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 createHash41 } from "node:crypto";
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 = createHash41("sha256").update(JSON.stringify(["himi-push-campaign", campaignId, memberId])).digest().subarray(0, 16);
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 resolve56 } from "node:path";
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(resolve56(text8(flags.content) ?? process.cwd())), flags);
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((resolve63) => setTimeout(resolve63, ms2))),
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 readFileSync95, writeFileSync as writeFileSync31 } from "node:fs";
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 dirname41, join as join78 } from "node:path";
164325
+ import { dirname as dirname43, join as join80 } from "node:path";
163578
164326
  function defaultSessionsPath() {
163579
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join78(homedir12(), ".himalaya", "admin-sessions.json");
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(readFileSync95(path2, "utf8"));
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(dirname41(path2), { recursive: true, mode: 448 });
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(dirname41(path2), 448);
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 existsSync76, mkdirSync as mkdirSync36, readFileSync as readFileSync96, rmSync as rmSync19, writeFileSync as writeFileSync32 } from "node:fs";
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 dirname42, join as join79 } from "node:path";
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 join79(home, ".himi", "base44", "session.json");
164715
+ return join81(home, ".himi", "base44", "session.json");
163968
164716
  }
163969
164717
  function readBase44Session(home) {
163970
164718
  const p2 = base44SessionPath(home);
163971
- if (!existsSync76(p2)) return void 0;
164719
+ if (!existsSync77(p2)) return void 0;
163972
164720
  try {
163973
- const s2 = JSON.parse(readFileSync96(p2, "utf8"));
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(dirname42(p2), { recursive: true, mode: 448 });
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 (!existsSync76(p2)) return false;
163990
- rmSync19(p2, { force: true });
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 = join79(home, ".base44", "auth", "auth.json");
164085
- if (!existsSync76(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
164086
- const a2 = JSON.parse(readFileSync96(src, "utf8"));
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((resolve63, reject) => {
165005
+ return new Promise((resolve65, reject) => {
164258
165006
  dnsLookup(hostname3, { all: true, verbatim: true }, (err, addresses) => {
164259
165007
  if (err) reject(err);
164260
- else resolve63(addresses);
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((resolve63, reject) => {
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(resolve63, reject).finally(() => signal.removeEventListener("abort", onAbort));
165019
+ work.then(resolve65, reject).finally(() => signal.removeEventListener("abort", onAbort));
164272
165020
  });
164273
165021
  }
164274
- async function pinAddress(url, resolve63 = resolveAll, signal) {
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(() => resolve63(host), signal, `${host} lookup`);
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((resolve63, reject) => {
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
- resolve63(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
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 join80 } from "node:path";
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(join80(out2, "evidence/pages"), { recursive: true });
166482
- mkdirSync37(join80(out2, "media/catalog"), { recursive: true });
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 = join80(out2, rel);
166486
- mkdirSync37(join80(p2, ".."), { recursive: true });
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 existsSync77, mkdirSync as mkdirSync38, readFileSync as readFileSync97, rmSync as rmSync20, writeFileSync as writeFileSync34 } from "node:fs";
167391
- import { dirname as dirname43, join as join81, resolve as resolve57, sep as sep19 } from "node:path";
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(readFileSync97(join81(dir, "book.json"), "utf8")).kind === "base44-app-book";
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 = resolve57(outDir);
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) => existsSync77(join81(out2, 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"]) rmSync20(join81(out2, d2), { recursive: true, force: true });
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(join81(out2, "book.json"), json6);
167488
- writeFileSync34(join81(out2, "BOOK.md"), md);
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(join81(out2, "screenshots"), { recursive: true });
167492
- writeFileSync34(join81(out2, "screenshots", s2.filename), s2.bytes);
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 = join81(out2, "source");
168243
+ const sourceRoot = join83(out2, "source");
167496
168244
  for (const f2 of result.sourceFiles) {
167497
168245
  if (!safeRel(f2.path)) continue;
167498
- const dest = join81(sourceRoot, ...f2.path.split("/"));
168246
+ const dest = join83(sourceRoot, ...f2.path.split("/"));
167499
168247
  if (!dest.startsWith(sourceRoot + sep19)) continue;
167500
- mkdirSync38(dirname43(dest), { recursive: true });
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 resolve63;
169119
+ let resolve65;
168372
169120
  let reject;
168373
169121
  const promise = new Promise((_resolve, _reject) => {
168374
- resolve63 = _resolve;
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 resolve63(result);
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 mkdtempSync4, rmSync as rmSync21, writeFileSync as writeFileSync35 } from "node:fs";
171043
- import { tmpdir as tmpdir5 } from "node:os";
171044
- import { join as join82, resolve as resolve58 } from "node:path";
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 = mkdtempSync4(join82(tmpdir5(), "himi-base44-"));
171058
- const cleanup = () => rmSync21(root, { recursive: true, force: true });
171805
+ const root = mkdtempSync5(join84(tmpdir6(), "himi-base44-"));
171806
+ const cleanup = () => rmSync22(root, { recursive: true, force: true });
171059
171807
  try {
171060
- const archive = join82(root, "project.tar");
171061
- const dir = join82(root, "project");
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, resolve58(opts.cwd ?? process.cwd(), opts.outDir ?? ".himi/base44-book"), { screenshots });
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 createHash42 } from "node:crypto";
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 createHash42("sha256").update(canonical4(structure, true)).digest("hex");
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 readFileSync98, realpathSync as realpathSync14, writeFileSync as writeFileSync36 } from "node:fs";
171619
- import { createHash as createHash43 } from "node:crypto";
171620
- import { dirname as dirname44, join as join83, parse as parse3, resolve as resolve59 } from "node:path";
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 = resolve59(cwd, flags["prompt-file"]);
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 = readFileSync98(file2, "utf8");
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 = resolve59(cwd, flags.dir ?? ".");
171680
- const workspace = join83(parentDir, name);
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 = dirname44(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 = join83(evidenceDir, name);
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] = createHash43("sha256").update(content).digest("hex");
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(join83(evidenceDir, "progress.jsonl"), JSON.stringify({ stage, at: now() }) + "\n", true);
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 = join83(options.workspace, ".himi", "one-app");
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 existsSync78, readFileSync as readFileSync99, writeFileSync as writeFileSync37, copyFileSync as copyFileSync2, mkdirSync as mkdirSync41, realpathSync as realpathSync15, statSync as statSync22 } from "node:fs";
173586
- import { dirname as dirname45, isAbsolute as isAbsolute8, join as join84, resolve as resolve60, sep as sep20 } from "node:path";
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 resolve60(p2).replace(/\\/g, "/");
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) => existsSync78(join84(dir, shellAppDir(name), "package.json")))) return dir;
173602
- const next = dirname45(dir);
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 && resolve60(path2) === resolve60(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 = join84(appDir3, "provisioning.json");
173705
- if (!existsSync78(committedPath)) {
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(readFileSync99(committedPath, "utf8"));
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 = resolve60(root, rel);
173716
- return full.startsWith(resolve60(root) + sep20) ? full : void 0;
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(join84(appDir3, STAGED), toRel.slice(STAGED.length + 1));
173721
- if (!from || !to2 || !existsSync78(from)) return void 0;
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(dirname45(to2), { recursive: true });
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 = join84(packageDir, "media/fonts/faces.json");
173744
- if (existsSync78(facesPath)) {
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(readFileSync99(facesPath, "utf8"));
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 = join84(packageDir, "provisioning.contract.json");
174516
+ const path2 = join86(packageDir, "provisioning.contract.json");
173769
174517
  writeFileSync37(path2, body);
173770
- const localPath2 = join84(appDir3, LOCAL_CONTRACT_REL);
173771
- mkdirSync41(dirname45(localPath2), { recursive: true });
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 = join84(dirname45(resolve60(overlayPath)), "book.json");
173806
- if (!existsSync78(bookPath)) return void 0;
174553
+ const bookPath = join86(dirname47(resolve62(overlayPath)), "book.json");
174554
+ if (!existsSync79(bookPath)) return void 0;
173807
174555
  try {
173808
- const book = JSON.parse(readFileSync99(bookPath, "utf8"));
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 = join84(dirname45(resolve60(overlayPath)), "book.json");
173823
- if (!existsSync78(bookPath)) return void 0;
174570
+ const bookPath = join86(dirname47(resolve62(overlayPath)), "book.json");
174571
+ if (!existsSync79(bookPath)) return void 0;
173824
174572
  try {
173825
- const book = JSON.parse(readFileSync99(bookPath, "utf8"));
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 = resolve60(input.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(readFileSync99(input.overlayPath, "utf8"));
173838
- const tokens2 = JSON.parse(readFileSync99(input.tokensPath, "utf8"));
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 = join84(repoRoot2, shellAppDir(shell));
173856
- const committedPath = join84(appDir3, "provisioning.json");
173857
- const committedSite = existsSync78(committedPath) ? JSON.parse(readFileSync99(committedPath, "utf8")).site : void 0;
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 = dirname45(resolve60(input.overlayPath));
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 = join84(cwd, "provisioning.json");
174632
+ const pkgProv = join86(cwd, "provisioning.json");
173885
174633
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
173886
- const contentPath = join84(cwd, "himalaya.content.json");
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 (existsSync78(pkgProv)) {
173899
- const cur = JSON.parse(readFileSync99(pkgProv, "utf8"));
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 = join84(cwd, "tokens.json");
173916
- if (existsSync78(pkgTokens) && (tokens2.colors || tokens2.typography)) {
173917
- const cur = JSON.parse(readFileSync99(pkgTokens, "utf8"));
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 = join84(cwd, "dev/index.ts");
173943
- if (homeAction && existsSync78(homeSrc)) {
173944
- const prev = readFileSync99(homeSrc, "utf8");
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 || !existsSync78(input.iconPath)) {
173980
- const book = input.iconPath ? dirname45(dirname45(resolve60(input.iconPath))) : void 0;
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 && existsSync78(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 existsSync79, readFileSync as readFileSync100 } from "node:fs";
174944
- import { resolve as resolve61 } from "node:path";
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 = resolve61(cwd, opts.outDir ?? ".himi/business-book");
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(resolve61(cwd, ".himi/base44-book/book.json"), result.book.input.siteUrl) : void 0;
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 = resolve61(outDir, "provisioning.overlay.json");
175000
- const prevSite = existsSync79(prevOverlayPath) ? (() => {
175747
+ const prevOverlayPath = resolve63(outDir, "provisioning.overlay.json");
175748
+ const prevSite = existsSync80(prevOverlayPath) ? (() => {
175001
175749
  try {
175002
- return JSON.parse(readFileSync100(prevOverlayPath, "utf8")).site;
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 = resolve61(outDir, "provisioning.overlay.json");
175767
+ const previousOverlay = resolve63(outDir, "provisioning.overlay.json");
175020
175768
  carryOverGoals(
175021
- existsSync79(previousOverlay) ? readFileSync100(previousOverlay, "utf8") : void 0,
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: resolve61(outDir, "provisioning.overlay.json"),
175041
- tokensPath: resolve61(outDir, "tokens.overlay.json"),
175042
- iconPath: resolve61(outDir, "media/icon.png"),
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 = resolve61(opts.cwd ?? process.cwd(), opts.sourcePath);
175079
- source = readFileSync100(p2, "utf8");
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 (!existsSync79(bookPath)) return void 0;
175855
+ if (!existsSync80(bookPath)) return void 0;
175108
175856
  try {
175109
- const book = JSON.parse(readFileSync100(bookPath, "utf8"));
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((resolve63, reject) => {
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(() => resolve63(m2[0]));
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 existsSync80, readFileSync as readFileSync101, writeFileSync as writeFileSync38 } from "node:fs";
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: existsSync80, readFileSync: readFileSync101, writeFileSync: writeFileSync38 }) {
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 mkdtempSync5, readFileSync as readFileSync102, mkdirSync as mkdirSync42, writeFileSync as writeFileSync39, existsSync as existsSync81, rmSync as rmSync22, readdirSync as readdirSync35, statSync as statSync23, lstatSync as lstatSync22, accessSync, constants as constants5, renameSync as renameSync12, cpSync as cpSync3 } from "node:fs";
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 createHash44, randomUUID as randomUUID11 } from "node:crypto";
176214
- import { tmpdir as tmpdir6, homedir as homedir14, hostname as hostname2 } from "node:os";
176215
- import { join as join85, resolve as resolve62, relative as relative15, basename as basename19, dirname as dirname46 } from "node:path";
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 = join85(templateSourceDir(name), TEMPLATE_META_FILE);
178298
- const meta = JSON.parse(readFileSync102(path2, "utf8"));
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(readFileSync102(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
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((resolve63, reject) => {
179237
- execFile2(file2, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve63(String(stdout)));
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((resolve63) => {
179999
+ const expired = new Promise((resolve65) => {
179245
180000
  const timer = setTimeout(() => {
179246
180001
  onTimeout?.();
179247
- resolve63(void 0);
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(readFileSync102(path2, "utf8")).version;
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 = resolve62(fromDir);
180072
+ let dir = resolve64(fromDir);
179318
180073
  for (; ; ) {
179319
- const version4 = packageVersion(join85(dir, "node_modules", "@wix", "himalaya", "package.json"));
180074
+ const version4 = packageVersion(join87(dir, "node_modules", "@wix", "himalaya", "package.json"));
179320
180075
  if (version4) return { version: version4, source: "local" };
179321
- const parent = dirname46(dir);
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(join85(root, "@wix", "himalaya", "package.json")) : void 0;
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 ?? join85(homedir14(), ".himalaya", "update-check.json");
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(readFileSync102(path2, "utf8"));
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(dirname46(path2), { recursive: true, mode: 448 });
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(join85(root, "@wix", "himalaya-cli", "package.json")) : void 0;
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 ? join85(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
179454
- if (!entry || !existsSync81(entry)) return void 0;
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 = readFileSync102(path2, "utf8");
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 readFileSync102(path2, "utf8");
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) rmSync22(path2, { force: true });
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(dirname46(lockPath), { recursive: true, mode: 448 });
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
- rmSync22(lockPath, { force: true });
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", resolve62(dir), "--strict", "--skip-version-check"];
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 = join85(dir, `${name}${suffix}`);
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 = existsSync81(iosYmlPath) ? readFileSync102(iosYmlPath, "utf8") : "";
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 readFileSync102(join85(dir, "config.ts"), "utf8");
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(dirname46(path2), { recursive: true });
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 = resolve62(parentDir, name);
180293
- if (existsSync81(join85(dir, "himalaya.content.json"))) {
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 resolve62(str9(flags.content) ?? process.cwd());
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 (!existsSync81(dest)) return null;
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 = resolve62(start);
181107
+ let dir = resolve64(start);
180353
181108
  for (; ; ) {
180354
- if (existsSync81(join85(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync81(join85(dir, "core", "serve", "src", "server.ts"))) return true;
180355
- const parent = dirname46(dir);
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)) ? basename19(sourceDir) : id;
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 = resolve62(fileURLToPath29(new URL("../../..", import.meta.url)));
180415
- const root = join85(repoRoot2, "node_modules", ".cache", "himi-template-preview");
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
- rmSync22(join85(root, entry.name), { recursive: true, force: true });
181184
+ rmSync23(join87(root, entry.name), { recursive: true, force: true });
180430
181185
  }
180431
181186
  }
180432
181187
  } catch {
180433
181188
  }
180434
- const dest = join85(root, `${slug}-${process.pid}`);
180435
- rmSync22(dest, { recursive: true, force: true });
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
- rmSync22(dest, { recursive: true, force: true });
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: readFileSync103 } = await import("node:fs");
180448
- const m2 = JSON.parse(readFileSync103(join85(dir, "himalaya.content.json"), "utf8"));
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 basename19(dir);
181207
+ return basename21(dir);
180453
181208
  }
180454
181209
  async function contentVisibility(dir) {
180455
181210
  try {
180456
- const { readFileSync: readFileSync103 } = await import("node:fs");
180457
- const m2 = JSON.parse(readFileSync103(join85(dir, "himalaya.content.json"), "utf8"));
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 = resolve62(str9(flags.dir) ?? process.cwd());
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
- ...existsSync81(join85(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" } : {},
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 = mkdtempSync5(join85(tmpdir6(), "himi-ux-record-"));
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
- rmSync22(out2, { recursive: true, force: true });
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 = readFileSync102(join85(outDir, candidate), "utf8");
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) => existsSync81(join85(dir, ".himi", "studio", "index.html"));
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 = mkdtempSync5(join85(tmpdir6(), prefix));
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
- rmSync22(dir, { recursive: true, force: true });
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 = resolve62(str9(flags.dir) ?? process.cwd());
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) => existsSync81(join85(parentDir, 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, readFileSync102(from, "utf8"), { parent: str9(flags.parent), tab: str9(flags.tab), displayName: str9(flags["display-name"]) }));
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, readFileSync102(from, "utf8")));
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"]) ?? join85(dir, "SPEC.md"));
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 && existsSync81(join85(adoptDir, adoptBits.ADOPT_FILE))) {
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 = resolve62(str9(flags.dir) ?? process.cwd());
181676
- const sourceDir = resolve62(str9(flags["source-dir"]) ?? appDir3);
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(readFileSync102(join85(sourceDir, TEMPLATE_META_FILE), "utf8"));
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(readFileSync102(join85(sourceDir, "tokens.json"), "utf8")));
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 = mkdtempSync5(join85(tmpdir6(), "himi-template-"));
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 = resolve62(sourceDir) === resolve62(appDir3) ? [] : [
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) ? resolve62(str9(flags.icon)) : templateIconPath(name);
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 = readFileSync102(iconPath);
182523
+ const bytes2 = readFileSync103(iconPath);
181769
182524
  payload.icon = bytes2.toString("base64");
181770
- iconHash = createHash44("sha256").update(bytes2).digest("hex");
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
- rmSync22(dir, { recursive: true, force: true });
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 = readFileSync102(path2, "utf8");
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 = resolve62(out2);
182958
+ const dir = resolve64(out2);
182204
182959
  const files = himiPluginFiles2(skills.skillMd);
182205
182960
  for (const f2 of files) {
182206
- mkdirSync42(dirname46(join85(dir, f2.path)), { recursive: true });
182207
- writeFileSync39(join85(dir, f2.path), f2.text);
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: resolve62(process.env.HIMI_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 (!existsSync81(join85(dir, "himalaya.content.json"))) {
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 = resolve62(str9(flags.out) ?? join85(dir, ".himi", "making-of.html"));
182985
+ const out2 = resolve64(str9(flags.out) ?? join87(dir, ".himi", "making-of.html"));
182231
182986
  const { html, plan } = buildReel2(dir);
182232
- mkdirSync42(dirname46(out2), { recursive: true });
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 ${basename19(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` };
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 = existsSync81(join85(dir, "himalaya.content.json"));
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 (existsSync81(join85(dir, "functions"))) {
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(join85(dir, "tier5-src"), screen.bundleName);
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: join85(dir, ".himi", "shots"),
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) => rmSync22(d2, { recursive: true, force: true })
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$/, ""), join85(dir, ".himi", "shots", name)])),
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 : readFileSync102(stateArg.replace(/^@/, ""), "utf8");
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 : readFileSync102(inputArg.replace(/^@/, ""), "utf8");
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 = join85(dir, ".himi", "shots", `${screenId}.png`);
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 = resolve62(pngTarget) === resolve62(shotPath) ? pngFile : writePngFile(shotPath, r2.pngBase64);
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 = resolve62(str9(flags.out) ?? process.cwd(), renamed ?? wanted);
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 (existsSync81(dest)) {
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 && !existsSync81(join85(dest, "himalaya.content.json"))) {
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 = relative15(process.cwd(), dir) || ".";
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 = createHash44("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
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(resolve62(releaseDir), only, resolve62(str9(flags.out) ?? process.cwd()));
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 = mkdtempSync5(join85(tmpdir6(), "himi-pack-"));
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
- rmSync22(built, { recursive: true, force: true });
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, resolve62(str9(flags.out) ?? dir), sourceArchive);
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
- rmSync22(built, { recursive: true, force: true });
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(resolve62(file2));
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: `${resolve62(file2)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
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 = resolve62(str9(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
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(resolve62(file2));
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: `${resolve62(file2)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
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 = readFileSync102(resolve62(file2));
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 = mkdtempSync5(join85(tmpdir6(), "himi-run-build-"));
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 = join85(temp, app);
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 ?? `${join85(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
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((resolve63) => {
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(() => resolve63()));
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 = mkdtempSync5(join85(tmpdir6(), "himi-run-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 = join85(running.releaseRoot, running.app);
184519
- const manifestOf = (tree) => JSON.parse(readFileSync102(join85(tree, "release-manifest.json"), "utf8"));
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 = mkdtempSync5(join85(tmpdir6(), "himi-run-build-"));
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(join85(next, running.app));
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, join85(next, running.app), diff);
185305
+ const changes = describeChanges2(live3, join87(next, running.app), diff);
184551
185306
  const retired = `${live3}.retired-${Date.now()}`;
184552
- renameSync12(live3, retired);
185307
+ renameSync13(live3, retired);
184553
185308
  try {
184554
- renameSync12(join85(next, running.app), live3);
185309
+ renameSync13(join87(next, running.app), live3);
184555
185310
  } catch {
184556
- cpSync3(join85(next, running.app), live3, { recursive: true });
185311
+ cpSync3(join87(next, running.app), live3, { recursive: true });
184557
185312
  }
184558
- rmSync22(retired, { recursive: true, force: true });
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
- rmSync22(next, { recursive: true, force: true });
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) rmSync22(temp, { recursive: true, force: true });
184640
- if (served) rmSync22(served, { recursive: true, force: true });
184641
- if (browserCopy) rmSync22(browserCopy, { recursive: true, force: true });
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 (!existsSync81(file2)) {
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 = readFileSync102(file2, "utf8");
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 = readFileSync102(file2, "utf8");
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 = readFileSync102(file2);
185295
- const sha2 = createHash44("sha256").update(bytes2).digest("hex");
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("@") ? readFileSync102(arg.slice(1), "utf8") : arg);
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 (!existsSync81(join85(dir, "himalaya.content.json"))) return;
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 (existsSync81(join85(distDir, "himalaya.content.json"))) {
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 = readFileSync102(dpxPath, "utf8").trim();
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 = readFileSync102(path2, "utf8");
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;