@wix/himalaya-cli 0.1113.0 → 0.1115.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
@@ -1456,7 +1456,7 @@ function sentinelizeIdentity(body, identity) {
1456
1456
  }
1457
1457
  if (identity.name) {
1458
1458
  const re = new RegExp(`\\b(${NAME_FIELDS.join("|")})(["']?\\s*[:=]\\s*)(["'])${escapeRe(identity.name)}\\3`, "g");
1459
- out2 = out2.replace(re, (_m, key2, sep17, q) => `${key2}${sep17}${q}__HIMI_APP_NAME__${q}`);
1459
+ out2 = out2.replace(re, (_m, key2, sep18, q) => `${key2}${sep18}${q}__HIMI_APP_NAME__${q}`);
1460
1460
  }
1461
1461
  return out2;
1462
1462
  }
@@ -2513,14 +2513,14 @@ function commitChange(repo, base, branch, rel, body) {
2513
2513
  function runSelfTest() {
2514
2514
  let failed2 = 0;
2515
2515
  for (const testCase of SELF_TEST_CASES) {
2516
- let ok = false;
2516
+ let ok2 = false;
2517
2517
  let thrown = null;
2518
2518
  try {
2519
- ok = testCase.run() === true;
2519
+ ok2 = testCase.run() === true;
2520
2520
  } catch (error) {
2521
2521
  thrown = error?.message || String(error);
2522
2522
  }
2523
- if (ok) {
2523
+ if (ok2) {
2524
2524
  process.stdout.write(` \u2713 ${testCase.name}
2525
2525
  `);
2526
2526
  continue;
@@ -3742,7 +3742,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
3742
3742
  tokenCache.set(cacheKey, fromEnv);
3743
3743
  return fromEnv;
3744
3744
  }
3745
- const token = await new Promise((resolve53, reject) => {
3745
+ const token = await new Promise((resolve54, reject) => {
3746
3746
  let child;
3747
3747
  try {
3748
3748
  child = spawnImpl("wix", [...args]);
@@ -3771,12 +3771,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
3771
3771
  child.stdout?.on("data", (d) => {
3772
3772
  out2 += String(d);
3773
3773
  const m = out2.match(TOKEN_RE);
3774
- if (m) done(() => resolve53(m[0]));
3774
+ if (m) done(() => resolve54(m[0]));
3775
3775
  });
3776
3776
  child.stderr?.on("data", (d) => {
3777
3777
  out2 += String(d);
3778
3778
  const m = out2.match(TOKEN_RE);
3779
- if (m) done(() => resolve53(m[0]));
3779
+ if (m) done(() => resolve54(m[0]));
3780
3780
  });
3781
3781
  child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
3782
3782
  child.on("exit", (code) => done(() => reject(new Error(
@@ -3965,8 +3965,8 @@ function committedProvisioningPath(name) {
3965
3965
  function committedShellFor(path2) {
3966
3966
  const normalized = path2.replace(/\\/g, "/");
3967
3967
  return SHELL_NAMES2.find((name) => {
3968
- const relative14 = committedProvisioningPath(name);
3969
- return normalized === relative14 || normalized.endsWith(`/${relative14}`);
3968
+ const relative15 = committedProvisioningPath(name);
3969
+ return normalized === relative15 || normalized.endsWith(`/${relative15}`);
3970
3970
  });
3971
3971
  }
3972
3972
  function isBrandable(repoRoot2, name) {
@@ -4486,7 +4486,7 @@ function confinementPlugin(contentRoot) {
4486
4486
  }
4487
4487
  function assertConfinedTsconfig(entry, contentRoot, allows) {
4488
4488
  const seen = /* @__PURE__ */ new Set();
4489
- const refuse5 = (p, why) => {
4489
+ const refuse6 = (p, why) => {
4490
4490
  throw new Error(
4491
4491
  `refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
4492
4492
  );
@@ -4552,7 +4552,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4552
4552
  try {
4553
4553
  manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
4554
4554
  } catch {
4555
- refuse5(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
4555
+ refuse6(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
4556
4556
  }
4557
4557
  const field = manifest?.tsconfig;
4558
4558
  if (typeof field === "string" && field) {
@@ -4568,7 +4568,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4568
4568
  const real = realpathOrSelf(file);
4569
4569
  if (seen.has(real)) return;
4570
4570
  seen.add(real);
4571
- if (!allows(real)) refuse5(file, "it is outside this content package");
4571
+ if (!allows(real)) refuse6(file, "it is outside this content package");
4572
4572
  let raw;
4573
4573
  try {
4574
4574
  raw = readFileSync10(real, "utf8");
@@ -4579,7 +4579,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4579
4579
  try {
4580
4580
  parsed = JSON.parse(stripJsonc(raw));
4581
4581
  } catch {
4582
- refuse5(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
4582
+ refuse6(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
4583
4583
  }
4584
4584
  const ext = parsed?.extends;
4585
4585
  for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
@@ -8472,8 +8472,8 @@ function textOf(node) {
8472
8472
  function plainText(node) {
8473
8473
  if (typeOf(node) === "TEXT") return str(at(node, "textData", "text"));
8474
8474
  const children = kids(node).filter(isObj);
8475
- const sep17 = children.every((c) => typeOf(c) === "TEXT") ? "" : "\n";
8476
- return children.map(plainText).join(sep17);
8475
+ const sep18 = children.every((c) => typeOf(c) === "TEXT") ? "" : "\n";
8476
+ return children.map(plainText).join(sep18);
8477
8477
  }
8478
8478
  function alignOf(v) {
8479
8479
  switch (v) {
@@ -13140,6 +13140,7 @@ function resolveIdiom(tokens, ctx = {}) {
13140
13140
  var IDIOM_CONTEXTS, UNSAFE_KEYS;
13141
13141
  var init_idiom = __esm({
13142
13142
  "../../core/ts/src/idiom.ts"() {
13143
+ "use strict";
13143
13144
  IDIOM_CONTEXTS = {
13144
13145
  ios: { native: ["ios"] },
13145
13146
  android: { native: ["material"] },
@@ -14806,8 +14807,8 @@ function matchWeightCss(available, desired) {
14806
14807
  const upFrom = (n) => sorted2.find((w) => w >= n);
14807
14808
  const downFrom = (n) => [...sorted2].reverse().find((w) => w <= n);
14808
14809
  if (desired >= 400 && desired <= 500) {
14809
- const within = sorted2.find((w) => w >= desired && w <= 500);
14810
- return within ?? downFrom(desired) ?? upFrom(desired);
14810
+ const within2 = sorted2.find((w) => w >= desired && w <= 500);
14811
+ return within2 ?? downFrom(desired) ?? upFrom(desired);
14811
14812
  }
14812
14813
  if (desired < 400) return downFrom(desired) ?? upFrom(desired);
14813
14814
  return upFrom(desired) ?? downFrom(desired);
@@ -15930,29 +15931,29 @@ function matchRuleEx(rules, method, path2, ctx = {}) {
15930
15931
  }
15931
15932
  if (m.query) {
15932
15933
  const q = ctx.query ?? {};
15933
- let ok = true;
15934
+ let ok2 = true;
15934
15935
  for (const [k, v] of Object.entries(m.query)) {
15935
15936
  if (q[k] !== v) {
15936
- ok = false;
15937
+ ok2 = false;
15937
15938
  break;
15938
15939
  }
15939
15940
  captures[`query.${k}`] = q[k];
15940
15941
  }
15941
- if (!ok) continue;
15942
+ if (!ok2) continue;
15942
15943
  for (const [k, v] of Object.entries(q)) captures[`query.${k}`] = v;
15943
15944
  } else if (ctx.query) {
15944
15945
  for (const [k, v] of Object.entries(ctx.query)) captures[`query.${k}`] = v;
15945
15946
  }
15946
15947
  if (m.headers) {
15947
15948
  const hh = lc(ctx.headers);
15948
- let ok = true;
15949
+ let ok2 = true;
15949
15950
  for (const [k, v] of Object.entries(m.headers)) {
15950
15951
  if (hh[k.toLowerCase()] !== v) {
15951
- ok = false;
15952
+ ok2 = false;
15952
15953
  break;
15953
15954
  }
15954
15955
  }
15955
- if (!ok) continue;
15956
+ if (!ok2) continue;
15956
15957
  }
15957
15958
  if (m.bodyContains && !(ctx.body ?? "").includes(m.bodyContains)) continue;
15958
15959
  return { rule: r, captures };
@@ -18574,11 +18575,11 @@ function appleScriptString(s) {
18574
18575
  function runNotifier(cmd, args) {
18575
18576
  return new Promise((done) => {
18576
18577
  let settled = false;
18577
- const finish2 = (ok) => {
18578
+ const finish2 = (ok2) => {
18578
18579
  if (!settled) {
18579
18580
  settled = true;
18580
18581
  clearTimeout(timer);
18581
- done(ok);
18582
+ done(ok2);
18582
18583
  }
18583
18584
  };
18584
18585
  const child = spawn3(cmd, args, { stdio: "ignore" });
@@ -19465,10 +19466,10 @@ var init_preview = __esm({
19465
19466
  }
19466
19467
  },
19467
19468
  kill: (pid, signal) => process.kill(pid, signal),
19468
- portFree: (port) => new Promise((resolve53) => {
19469
+ portFree: (port) => new Promise((resolve54) => {
19469
19470
  const s = createServer2();
19470
- s.once("error", () => resolve53(false));
19471
- s.listen(port, "127.0.0.1", () => s.close(() => resolve53(true)));
19471
+ s.once("error", () => resolve54(false));
19472
+ s.listen(port, "127.0.0.1", () => s.close(() => resolve54(true)));
19472
19473
  }),
19473
19474
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
19474
19475
  servingIdentity: async (origin) => {
@@ -20612,7 +20613,7 @@ async function injectRequest(listener, request) {
20612
20613
  req.headers.host ??= url.host;
20613
20614
  if (body && body.length > 0) req.push(body);
20614
20615
  req.push(null);
20615
- return await new Promise((resolve53, reject) => {
20616
+ return await new Promise((resolve54, reject) => {
20616
20617
  const streamed = () => {
20617
20618
  queueMicrotask(() => {
20618
20619
  req.emit("close");
@@ -20628,7 +20629,7 @@ async function injectRequest(listener, request) {
20628
20629
  else headers2.set(name, value);
20629
20630
  }
20630
20631
  const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
20631
- resolve53(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20632
+ resolve54(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20632
20633
  }, streamed);
20633
20634
  res.on("inject-error", reject);
20634
20635
  try {
@@ -21334,7 +21335,7 @@ function redactBodyString(body) {
21334
21335
  } catch {
21335
21336
  }
21336
21337
  }
21337
- return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep17) => isSensitiveBodyName(name) ? `"${name}"${sep17}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep17) => isSensitiveBodyName(name) ? `"${name}"${sep17}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
21338
+ return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep18) => isSensitiveBodyName(name) ? `"${name}"${sep18}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep18) => isSensitiveBodyName(name) ? `"${name}"${sep18}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
21338
21339
  }
21339
21340
  function createWixGatewayState() {
21340
21341
  return { mode: "record", rules: [], traffic: [], clients: /* @__PURE__ */ new Set(), seq: 0, ruleSeq: 0 };
@@ -23080,10 +23081,10 @@ function recordDeviceLayout(payload) {
23080
23081
  }
23081
23082
  async function handleDeviceLayoutReport(res, payload) {
23082
23083
  const screenId = recordDeviceLayout(payload);
23083
- const ok = screenId !== null;
23084
- res.statusCode = ok ? 200 : 400;
23084
+ const ok2 = screenId !== null;
23085
+ res.statusCode = ok2 ? 200 : 400;
23085
23086
  res.setHeader("content-type", "application/json");
23086
- res.end(JSON.stringify(ok ? { status: "ok", screenId } : { error: "invalid_layout" }));
23087
+ res.end(JSON.stringify(ok2 ? { status: "ok", screenId } : { error: "invalid_layout" }));
23087
23088
  return screenId;
23088
23089
  }
23089
23090
  async function handlePreviewHitTest(res, payload) {
@@ -23162,12 +23163,12 @@ function finalizeRecording(key2, rec) {
23162
23163
  if (rec.finalize) return rec.finalize;
23163
23164
  rec.finalize = (async () => {
23164
23165
  clearTimeout(rec.autoStop);
23165
- await new Promise((resolve53) => {
23166
+ await new Promise((resolve54) => {
23166
23167
  let done = false;
23167
23168
  const finish2 = () => {
23168
23169
  if (!done) {
23169
23170
  done = true;
23170
- resolve53();
23171
+ resolve54();
23171
23172
  }
23172
23173
  };
23173
23174
  rec.child.once("close", finish2);
@@ -23278,7 +23279,7 @@ var init_preview2 = __esm({
23278
23279
  DEVICE_LIST_TIMEOUT_MS = 5e3;
23279
23280
  defaultRunner2 = {
23280
23281
  capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
23281
- return new Promise((resolve53, reject) => {
23282
+ return new Promise((resolve54, reject) => {
23282
23283
  const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
23283
23284
  const out2 = [];
23284
23285
  const err = [];
@@ -23300,7 +23301,7 @@ var init_preview2 = __esm({
23300
23301
  child.stderr.on("data", (b) => err.push(b));
23301
23302
  child.on("error", (e) => settle(reject, e));
23302
23303
  child.on("close", (code) => {
23303
- if (code === 0) settle(resolve53, Buffer.concat(out2));
23304
+ if (code === 0) settle(resolve54, Buffer.concat(out2));
23304
23305
  else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
23305
23306
  });
23306
23307
  });
@@ -24632,13 +24633,13 @@ function validate(rule, rawValue) {
24632
24633
  return { rule: "type", type: rule.type };
24633
24634
  }
24634
24635
  if (rule.regex) {
24635
- let ok;
24636
+ let ok2;
24636
24637
  try {
24637
- ok = new RegExp(`^(?:${rule.regex})$`).test(value);
24638
+ ok2 = new RegExp(`^(?:${rule.regex})$`).test(value);
24638
24639
  } catch {
24639
- ok = true;
24640
+ ok2 = true;
24640
24641
  }
24641
- if (!ok) return { rule: "regex" };
24642
+ if (!ok2) return { rule: "regex" };
24642
24643
  }
24643
24644
  if (typeof rule.minLength === "number" && rule.minLength > 0 && value.length < rule.minLength) {
24644
24645
  return { rule: "minLength", limit: rule.minLength };
@@ -27553,12 +27554,12 @@ function createRicosHostSession(o) {
27553
27554
  flush() {
27554
27555
  if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
27555
27556
  const requestId2 = newId();
27556
- return new Promise((resolve53) => {
27557
+ return new Promise((resolve54) => {
27557
27558
  const timer = t.setTimeout(() => {
27558
27559
  flushes.delete(requestId2);
27559
- resolve53(null);
27560
+ resolve54(null);
27560
27561
  }, flushMs);
27561
- flushes.set(requestId2, { resolve: resolve53, timer });
27562
+ flushes.set(requestId2, { resolve: resolve54, timer });
27562
27563
  o.send({ v: 1, type: "requestContent", requestId: requestId2 });
27563
27564
  });
27564
27565
  },
@@ -27611,7 +27612,7 @@ async function runRicosImageUpload(o) {
27611
27612
  };
27612
27613
  session.insertMediaPlaceholder(requestId2);
27613
27614
  try {
27614
- const entry = await new Promise((resolve53) => {
27615
+ const entry = await new Promise((resolve54) => {
27615
27616
  let done = false;
27616
27617
  let unsub = () => {
27617
27618
  };
@@ -27620,7 +27621,7 @@ async function runRicosImageUpload(o) {
27620
27621
  done = true;
27621
27622
  t.clearTimeout(timer);
27622
27623
  queueMicrotask(() => unsub());
27623
- resolve53(v);
27624
+ resolve54(v);
27624
27625
  };
27625
27626
  const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
27626
27627
  unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
@@ -27639,10 +27640,10 @@ async function runRicosImageUpload(o) {
27639
27640
  } catch {
27640
27641
  return fail2("read");
27641
27642
  }
27642
- const sep17 = entry.uploadUrl.includes("?") ? "&" : "?";
27643
+ const sep18 = entry.uploadUrl.includes("?") ? "&" : "?";
27643
27644
  let res;
27644
27645
  try {
27645
- res = await deps.fetch(`${entry.uploadUrl}${sep17}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
27646
+ res = await deps.fetch(`${entry.uploadUrl}${sep18}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
27646
27647
  } catch {
27647
27648
  return fail2("put");
27648
27649
  }
@@ -27657,14 +27658,14 @@ async function runRicosImageUpload(o) {
27657
27658
  const d = root.file && typeof root.file === "object" ? root.file : root;
27658
27659
  const id = typeof d.id === "string" ? d.id : "";
27659
27660
  if (!id) return fail2("bad_descriptor");
27660
- const ok = session.resolveMedia(requestId2, {
27661
+ const ok2 = session.resolveMedia(requestId2, {
27661
27662
  id,
27662
27663
  url: typeof d.url === "string" ? d.url : "",
27663
27664
  ...typeof d.width === "number" ? { width: d.width } : {},
27664
27665
  ...typeof d.height === "number" ? { height: d.height } : {},
27665
27666
  mimeType: file.mimeType
27666
27667
  });
27667
- return ok ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
27668
+ return ok2 ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
27668
27669
  } finally {
27669
27670
  deps.dispatch({ actionId: `tier5.${svc}.clearUpload`, args: { requestId: requestId2 } });
27670
27671
  }
@@ -29552,8 +29553,8 @@ function ensureCountUpRuntime() {
29552
29553
  const neg = fixed.startsWith("-");
29553
29554
  const body = neg ? fixed.slice(1) : fixed;
29554
29555
  const [int2, frac] = body.split(".");
29555
- const sep17 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
29556
- return (neg ? "-" : "") + sep17 + (frac ? "." + frac : "");
29556
+ const sep18 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
29557
+ return (neg ? "-" : "") + sep18 + (frac ? "." + frac : "");
29557
29558
  };
29558
29559
  const animateEl = (el) => {
29559
29560
  const node = el;
@@ -30374,24 +30375,24 @@ function usesSchematicRoute(props) {
30374
30375
  const hasRouteFeed = typeof props.routePath === "string" && props.routePath !== "";
30375
30376
  return hasFeed && !hasRoute && !hasRouteFeed;
30376
30377
  }
30377
- function longitudeAt(x, z2) {
30378
- return x / (TILE_PX * Math.pow(2, z2)) * 360 - 180;
30378
+ function longitudeAt(x, z3) {
30379
+ return x / (TILE_PX * Math.pow(2, z3)) * 360 - 180;
30379
30380
  }
30380
- function latitudeAt(y, z2) {
30381
- const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z2));
30381
+ function latitudeAt(y, z3) {
30382
+ const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z3));
30382
30383
  return 180 / Math.PI * Math.atan(Math.sinh(n));
30383
30384
  }
30384
- function regionArgs(centerLat, centerLng, z2, w, h) {
30385
- const cx = mercatorX(centerLng, z2);
30386
- const cy = mercatorY(centerLat, z2);
30385
+ function regionArgs(centerLat, centerLng, z3, w, h) {
30386
+ const cx = mercatorX(centerLng, z3);
30387
+ const cy = mercatorY(centerLat, z3);
30387
30388
  return {
30388
30389
  latitude: centerLat,
30389
30390
  longitude: centerLng,
30390
- zoom: z2,
30391
- north: latitudeAt(cy - h / 2, z2),
30392
- south: latitudeAt(cy + h / 2, z2),
30393
- east: longitudeAt(cx + w / 2, z2),
30394
- west: longitudeAt(cx - w / 2, z2)
30391
+ zoom: z3,
30392
+ north: latitudeAt(cy - h / 2, z3),
30393
+ south: latitudeAt(cy + h / 2, z3),
30394
+ east: longitudeAt(cx + w / 2, z3),
30395
+ west: longitudeAt(cx - w / 2, z3)
30395
30396
  };
30396
30397
  }
30397
30398
  function decodeCamera(v) {
@@ -30421,9 +30422,9 @@ function resolveTileSource(source) {
30421
30422
  const maxZoom = typeof s.maxZoom === "number" && s.maxZoom > 0 ? s.maxZoom : DEFAULT_TILE_MAX_ZOOM;
30422
30423
  return { urlTemplate, attribution, maxZoom };
30423
30424
  }
30424
- function tileUrl(source, z2, x, y) {
30425
- if (!source) return `https://tile.openstreetmap.org/${z2}/${x}/${y}.png`;
30426
- return source.urlTemplate.replace("{z}", String(z2)).replace("{x}", String(x)).replace("{y}", String(y));
30425
+ function tileUrl(source, z3, x, y) {
30426
+ if (!source) return `https://tile.openstreetmap.org/${z3}/${x}/${y}.png`;
30427
+ return source.urlTemplate.replace("{z}", String(z3)).replace("{x}", String(x)).replace("{y}", String(y));
30427
30428
  }
30428
30429
  function parseShapeKind(raw) {
30429
30430
  const k = typeof raw === "string" ? raw.toLowerCase() : "";
@@ -30440,12 +30441,12 @@ function circleRing(centreLat, centreLng, radiusM, segments = CIRCLE_SEGMENTS) {
30440
30441
  return { latitude: centreLat + dLat * Math.sin(theta), longitude: centreLng + dLng * Math.cos(theta) };
30441
30442
  });
30442
30443
  }
30443
- function distanceToPolylinePx(px, py, points, z2, originX, originY) {
30444
+ function distanceToPolylinePx(px, py, points, z3, originX, originY) {
30444
30445
  if (points.length < 2) return null;
30445
30446
  let best = Infinity;
30446
30447
  for (let i = 0; i < points.length - 1; i++) {
30447
- const ax = mercatorX(points[i].longitude, z2) - originX, ay = mercatorY(points[i].latitude, z2) - originY;
30448
- const bx = mercatorX(points[i + 1].longitude, z2) - originX, by = mercatorY(points[i + 1].latitude, z2) - originY;
30448
+ const ax = mercatorX(points[i].longitude, z3) - originX, ay = mercatorY(points[i].latitude, z3) - originY;
30449
+ const bx = mercatorX(points[i + 1].longitude, z3) - originX, by = mercatorY(points[i + 1].latitude, z3) - originY;
30449
30450
  const dx = bx - ax, dy = by - ay;
30450
30451
  const lenSq = dx * dx + dy * dy;
30451
30452
  const t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
@@ -30455,22 +30456,22 @@ function distanceToPolylinePx(px, py, points, z2, originX, originY) {
30455
30456
  }
30456
30457
  return best;
30457
30458
  }
30458
- function polygonContainsPx(px, py, points, z2, originX, originY) {
30459
+ function polygonContainsPx(px, py, points, z3, originX, originY) {
30459
30460
  if (points.length < 3) return false;
30460
30461
  let inside2 = false;
30461
30462
  for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
30462
- const xi = mercatorX(points[i].longitude, z2) - originX, yi = mercatorY(points[i].latitude, z2) - originY;
30463
- const xj = mercatorX(points[j].longitude, z2) - originX, yj = mercatorY(points[j].latitude, z2) - originY;
30463
+ const xi = mercatorX(points[i].longitude, z3) - originX, yi = mercatorY(points[i].latitude, z3) - originY;
30464
+ const xj = mercatorX(points[j].longitude, z3) - originX, yj = mercatorY(points[j].latitude, z3) - originY;
30464
30465
  if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) inside2 = !inside2;
30465
30466
  }
30466
30467
  return inside2;
30467
30468
  }
30468
- function markerHit(px, py, markers, z2, originX, originY) {
30469
+ function markerHit(px, py, markers, z3, originX, originY) {
30469
30470
  let best = null;
30470
30471
  let bestDistance = MARKER_HIT_RADIUS;
30471
30472
  markers.forEach((m, i) => {
30472
- const dx = mercatorX(m.longitude, z2) - originX - px;
30473
- const dy = mercatorY(m.latitude, z2) - originY - py;
30473
+ const dx = mercatorX(m.longitude, z3) - originX - px;
30474
+ const dy = mercatorY(m.latitude, z3) - originY - py;
30474
30475
  const d = Math.sqrt(dx * dx + dy * dy);
30475
30476
  if (d <= bestDistance) {
30476
30477
  bestDistance = d;
@@ -30479,22 +30480,22 @@ function markerHit(px, py, markers, z2, originX, originY) {
30479
30480
  });
30480
30481
  return best;
30481
30482
  }
30482
- function mercatorX(lng, z2) {
30483
- return (lng + 180) / 360 * TILE_PX * Math.pow(2, z2);
30483
+ function mercatorX(lng, z3) {
30484
+ return (lng + 180) / 360 * TILE_PX * Math.pow(2, z3);
30484
30485
  }
30485
- function mercatorY(lat, z2) {
30486
+ function mercatorY(lat, z3) {
30486
30487
  const s = Math.max(-85.05112878, Math.min(85.05112878, lat)) * Math.PI / 180;
30487
- return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z2);
30488
+ return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z3);
30488
30489
  }
30489
30490
  function fitZoom(pts, w, h, fallback) {
30490
30491
  if (pts.length < 2 || w <= 0 || h <= 0) return fallback;
30491
30492
  const lats = pts.map((p) => p.latitude), lngs = pts.map((p) => p.longitude);
30492
30493
  const minLa = Math.min(...lats), maxLa = Math.max(...lats);
30493
30494
  const minLo = Math.min(...lngs), maxLo = Math.max(...lngs);
30494
- for (let z2 = 19; z2 >= 1; z2--) {
30495
- const dx = Math.abs(mercatorX(maxLo, z2) - mercatorX(minLo, z2));
30496
- const dy = Math.abs(mercatorY(maxLa, z2) - mercatorY(minLa, z2));
30497
- if (dx <= w && dy <= h) return z2;
30495
+ for (let z3 = 19; z3 >= 1; z3--) {
30496
+ const dx = Math.abs(mercatorX(maxLo, z3) - mercatorX(minLo, z3));
30497
+ const dy = Math.abs(mercatorY(maxLa, z3) - mercatorY(minLa, z3));
30498
+ if (dx <= w && dy <= h) return z3;
30498
30499
  }
30499
30500
  return 1;
30500
30501
  }
@@ -34613,20 +34614,20 @@ var init_renderNode = __esm({
34613
34614
  const fitted = shouldFit ? fitZoom(all, W - 48, H - 48, declared) : declared;
34614
34615
  const baseLat = all.length && shouldFit ? (Math.min(...all.map((p) => p.latitude)) + Math.max(...all.map((p) => p.latitude))) / 2 : typeof props.latitude === "number" ? props.latitude : 37.7749;
34615
34616
  const baseLng = all.length && shouldFit ? (Math.min(...all.map((p) => p.longitude)) + Math.max(...all.map((p) => p.longitude))) / 2 : typeof props.longitude === "number" ? props.longitude : -122.4194;
34616
- const z2 = userCam?.z ?? fitted;
34617
+ const z3 = userCam?.z ?? fitted;
34617
34618
  const cLat = userCam?.lat ?? baseLat;
34618
34619
  const cLng = userCam?.lng ?? baseLng;
34619
34620
  React7.useEffect(() => {
34620
- const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z2);
34621
+ const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z3);
34621
34622
  if (!resolved2) return;
34622
34623
  setUserCam({
34623
34624
  lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
34624
34625
  lng: resolved2.longitude,
34625
- z: Math.max(1, Math.min(19, resolved2.zoom ?? z2))
34626
+ z: Math.max(1, Math.min(19, resolved2.zoom ?? z3))
34626
34627
  });
34627
34628
  }, [commandedCamera]);
34628
- const originX = mercatorX(cLng, z2) - W / 2;
34629
- const originY = mercatorY(cLat, z2) - H / 2;
34629
+ const originX = mercatorX(cLng, z3) - W / 2;
34630
+ const originY = mercatorY(cLat, z3) - H / 2;
34630
34631
  const interactive = pinsOnly ? props.interactive === true : props.interactive !== false;
34631
34632
  const resolvedTileSource = resolveTileSource(props.tileSource);
34632
34633
  const fireMapEvent = (action, payload) => {
@@ -34644,7 +34645,7 @@ var init_renderNode = __esm({
34644
34645
  const { kx, ky } = layoutScale(el);
34645
34646
  const px = (e.clientX - r.left) * kx - el.clientLeft;
34646
34647
  const py = (e.clientY - r.top) * ky - el.clientTop;
34647
- const hit = markerHit(px, py, markers, z2, originX, originY);
34648
+ const hit = markerHit(px, py, markers, z3, originX, originY);
34648
34649
  if (hit !== null) {
34649
34650
  const m = markers[hit];
34650
34651
  const payload = { index: hit, latitude: m.latitude, longitude: m.longitude };
@@ -34655,10 +34656,10 @@ var init_renderNode = __esm({
34655
34656
  const shapeIndex = shapes.findIndex((sh) => {
34656
34657
  if (sh.kind === "unknown" || sh.points.length < 2) return false;
34657
34658
  if (sh.kind === "line") {
34658
- const d2 = distanceToPolylinePx(px, py, sh.points, z2, originX, originY);
34659
+ const d2 = distanceToPolylinePx(px, py, sh.points, z3, originX, originY);
34659
34660
  return d2 !== null && d2 <= SHAPE_HIT_RADIUS;
34660
34661
  }
34661
- return polygonContainsPx(px, py, sh.points, z2, originX, originY);
34662
+ return polygonContainsPx(px, py, sh.points, z3, originX, originY);
34662
34663
  });
34663
34664
  if (shapeIndex >= 0 && props.onShapeTap) {
34664
34665
  const sh = shapes[shapeIndex];
@@ -34667,15 +34668,15 @@ var init_renderNode = __esm({
34667
34668
  fireMapEvent(props.onShapeTap, payload);
34668
34669
  } else {
34669
34670
  fireMapEvent(props.onMapTap, {
34670
- latitude: latitudeAt(originY + py, z2),
34671
- longitude: longitudeAt(originX + px, z2)
34671
+ latitude: latitudeAt(originY + py, z3),
34672
+ longitude: longitudeAt(originX + px, z3)
34672
34673
  });
34673
34674
  }
34674
34675
  }
34675
34676
  };
34676
34677
  const onPointerDown = (e) => {
34677
34678
  if (!interactive) return;
34678
- dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z2, ...layoutScale(e.currentTarget) };
34679
+ dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z3, ...layoutScale(e.currentTarget) };
34679
34680
  dragMovedRef.current = false;
34680
34681
  };
34681
34682
  const onPointerMove = (e) => {
@@ -34699,8 +34700,8 @@ var init_renderNode = __esm({
34699
34700
  const onWheel = (e) => {
34700
34701
  if (!interactive) return;
34701
34702
  e.preventDefault();
34702
- const next = Math.max(1, Math.min(19, z2 + (e.deltaY < 0 ? 1 : -1)));
34703
- if (next !== z2) setUserCam({ lat: cLat, lng: cLng, z: next });
34703
+ const next = Math.max(1, Math.min(19, z3 + (e.deltaY < 0 ? 1 : -1)));
34704
+ if (next !== z3) setUserCam({ lat: cLat, lng: cLng, z: next });
34704
34705
  };
34705
34706
  React7.useEffect(() => {
34706
34707
  const action = props.onRegionChange;
@@ -34711,22 +34712,22 @@ var init_renderNode = __esm({
34711
34712
  regionReportedRef.current = true;
34712
34713
  return;
34713
34714
  }
34714
- fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z2, W, H) } });
34715
+ fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z3, W, H) } });
34715
34716
  }, 250);
34716
34717
  return () => clearTimeout(t);
34717
- }, [cLat, cLng, z2, W, H, props.onRegionChange]);
34718
- const sx = (p) => mercatorX(p.longitude, z2) - originX;
34719
- const sy = (p) => mercatorY(p.latitude, z2) - originY;
34718
+ }, [cLat, cLng, z3, W, H, props.onRegionChange]);
34719
+ const sx = (p) => mercatorX(p.longitude, z3) - originX;
34720
+ const sy = (p) => mercatorY(p.latitude, z3) - originY;
34720
34721
  const accent = C("accentPrimary", "#116DFF");
34721
- const n = Math.pow(2, z2);
34722
+ const n = Math.pow(2, z3);
34722
34723
  const tiles = [];
34723
34724
  for (let tx = Math.floor(originX / TILE_PX); tx <= Math.floor((originX + W) / TILE_PX); tx++) {
34724
34725
  for (let ty = Math.floor(originY / TILE_PX); ty <= Math.floor((originY + H) / TILE_PX); ty++) {
34725
34726
  if (ty < 0 || ty >= n) continue;
34726
34727
  const wrapX = (tx % n + n) % n;
34727
34728
  tiles.push({
34728
- key: `${z2}/${wrapX}/${ty}`,
34729
- src: tileUrl(resolvedTileSource, z2, wrapX, ty),
34729
+ key: `${z3}/${wrapX}/${ty}`,
34730
+ src: tileUrl(resolvedTileSource, z3, wrapX, ty),
34730
34731
  left: tx * TILE_PX - originX,
34731
34732
  top: ty * TILE_PX - originY
34732
34733
  });
@@ -34738,7 +34739,7 @@ var init_renderNode = __esm({
34738
34739
  ref: attachBox,
34739
34740
  "data-map-mode": "tile",
34740
34741
  "data-route-points": route.length,
34741
- "data-map-zoom": z2,
34742
+ "data-map-zoom": z3,
34742
34743
  onClick: onSurfaceClick,
34743
34744
  onPointerDown,
34744
34745
  onPointerMove,
@@ -35904,7 +35905,7 @@ async function stabilizePngPage(page, scheme) {
35904
35905
  const browser = globalThis;
35905
35906
  browser.document.documentElement.style.colorScheme = selected;
35906
35907
  await browser.document.fonts?.ready;
35907
- await new Promise((resolve53) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve53())));
35908
+ await new Promise((resolve54) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve54())));
35908
35909
  }, scheme);
35909
35910
  }
35910
35911
  async function renderPngBatch(items) {
@@ -39545,7 +39546,7 @@ async function handleWebWix(req, res, state) {
39545
39546
  }
39546
39547
  if (match) {
39547
39548
  const mocked = match.rule.response;
39548
- if (mocked.delayMs) await new Promise((resolve53) => setTimeout(resolve53, mocked.delayMs));
39549
+ if (mocked.delayMs) await new Promise((resolve54) => setTimeout(resolve54, mocked.delayMs));
39549
39550
  const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
39550
39551
  record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
39551
39552
  return reply(200, { status: mocked.status, body: responseBody ?? "" });
@@ -40539,8 +40540,8 @@ async function handleActionHandlerBundleGet(res, app) {
40539
40540
  }
40540
40541
  async function serveStatic(req, res, root, prefix) {
40541
40542
  const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
40542
- const relative14 = requested.replace(prefix, "").replace(/^\//, "");
40543
- const safe = normalize3(relative14).replace(/^(\.\.[\/\\])+/, "");
40543
+ const relative15 = requested.replace(prefix, "").replace(/^\//, "");
40544
+ const safe = normalize3(relative15).replace(/^(\.\.[\/\\])+/, "");
40544
40545
  const fullPath = resolve33(root, safe);
40545
40546
  if (!fullPath.startsWith(root)) {
40546
40547
  return send(res, 403, "forbidden");
@@ -41271,8 +41272,8 @@ function sha256hex(b) {
41271
41272
  function stableStringify(value) {
41272
41273
  if (value === null || typeof value !== "object") return JSON.stringify(value);
41273
41274
  if (Array.isArray(value)) return "[" + value.map(stableStringify).join(",") + "]";
41274
- const object2 = value;
41275
- return "{" + Object.keys(object2).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object2[key2])).join(",") + "}";
41275
+ const object3 = value;
41276
+ return "{" + Object.keys(object3).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object3[key2])).join(",") + "}";
41276
41277
  }
41277
41278
  function manifestContent(m) {
41278
41279
  const {
@@ -41644,12 +41645,12 @@ var init_query = __esm({
41644
41645
  });
41645
41646
 
41646
41647
  // ../../core/dev-server/src/crawl-input.ts
41647
- function resolved(v, resolve53) {
41648
- if (typeof v === "string") return v.startsWith("$service:") ? resolve53(v) : v;
41648
+ function resolved(v, resolve54) {
41649
+ if (typeof v === "string") return v.startsWith("$service:") ? resolve54(v) : v;
41649
41650
  if (Array.isArray(v)) {
41650
41651
  const out2 = v.flatMap((el) => {
41651
41652
  if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
41652
- const r = resolve53(el);
41653
+ const r = resolve54(el);
41653
41654
  return Array.isArray(r) ? r : [r];
41654
41655
  });
41655
41656
  return out2;
@@ -41663,9 +41664,9 @@ function hasRowBinding(props) {
41663
41664
  return itemToken(v) || Array.isArray(v) && v.some(itemToken);
41664
41665
  });
41665
41666
  }
41666
- function declaredOptionIds(props, resolve53) {
41667
+ function declaredOptionIds(props, resolve54) {
41667
41668
  const literal = props.options ?? props.tabs ?? props.chips;
41668
- const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve53) : void 0;
41669
+ const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve54) : void 0;
41669
41670
  const raw = Array.isArray(bound) ? bound : literal;
41670
41671
  if (!Array.isArray(raw)) return [];
41671
41672
  const out2 = [];
@@ -41708,24 +41709,24 @@ function seedTokens(state, limit = 48) {
41708
41709
  walk2(state, 0);
41709
41710
  return out2;
41710
41711
  }
41711
- function synthesizeInput(control, resolve53, tokens) {
41712
+ function synthesizeInput(control, resolve54, tokens) {
41712
41713
  const id = `${control.type}.${control.callback}`;
41713
41714
  const row = SYNTHESIZED_CONTROLS[id];
41714
41715
  if (!row) return null;
41715
41716
  const props = control.props;
41716
41717
  if (hasRowBinding(props)) return null;
41717
41718
  if (row.from === "declared-options") {
41718
- const ids = declaredOptionIds(props, resolve53);
41719
+ const ids = declaredOptionIds(props, resolve54);
41719
41720
  if (!ids.length) return null;
41720
41721
  if (row.encoding === "string-array") {
41721
- const currentRaw2 = resolved(props.selectedIds, resolve53);
41722
+ const currentRaw2 = resolved(props.selectedIds, resolve54);
41722
41723
  const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
41723
41724
  const pick4 = ids.find((o) => !current3.includes(o));
41724
41725
  if (pick4 === void 0) return null;
41725
41726
  const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
41726
41727
  return { key: row.key, value, from: row.from, current: current3, control: id };
41727
41728
  }
41728
- const currentRaw = resolved(props.selectedId, resolve53);
41729
+ const currentRaw = resolved(props.selectedId, resolve54);
41729
41730
  const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
41730
41731
  const pick3 = ids.find((o) => o !== current2);
41731
41732
  if (pick3 === void 0) return null;
@@ -41733,7 +41734,7 @@ function synthesizeInput(control, resolve53, tokens) {
41733
41734
  }
41734
41735
  if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
41735
41736
  const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
41736
- const bound = binding2 === void 0 ? void 0 : resolve53(binding2);
41737
+ const bound = binding2 === void 0 ? void 0 : resolve54(binding2);
41737
41738
  const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
41738
41739
  const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
41739
41740
  const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
@@ -43218,8 +43219,8 @@ async function crawlScreenInner(opts) {
43218
43219
  if (linkable.has(target)) return true;
43219
43220
  for (const base of linkable) {
43220
43221
  if (target.length > base.length + 1 && target.startsWith(base)) {
43221
- const sep17 = target[base.length];
43222
- if (sep17 === "_" || sep17 === "/") return true;
43222
+ const sep18 = target[base.length];
43223
+ if (sep18 === "_" || sep18 === "/") return true;
43223
43224
  }
43224
43225
  }
43225
43226
  return false;
@@ -46246,7 +46247,7 @@ var init_studio_timeline = __esm({
46246
46247
  isStr = (x) => typeof x === "string";
46247
46248
  isObj2 = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
46248
46249
  strs = (x) => Array.isArray(x) && x.every(isStr);
46249
- nullOr = (x, ok) => x === null || isObj2(x) && ok(x);
46250
+ nullOr = (x, ok2) => x === null || isObj2(x) && ok2(x);
46250
46251
  accentOf = (palette2) => {
46251
46252
  for (const p of palette2 ?? []) {
46252
46253
  const [name, hex2] = Array.isArray(p) ? p : [p.name, p.hex];
@@ -47196,16 +47197,16 @@ function pushSetupBodyBytes(body) {
47196
47197
  return Buffer.byteLength(JSON.stringify(body), "utf8");
47197
47198
  }
47198
47199
  async function pushSetupRequest(options) {
47199
- const refuse5 = (error) => ({ ok: false, status: 0, body: null, error });
47200
- if (!options.target.controlToken) return refuse5("control_token_required");
47201
- if (!options.wixToken) return refuse5("wix_account_token_required");
47202
- if (credentialHostRefusal(options.target.control)) return refuse5("insecure_target");
47203
- if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse5("invalid_preview_tag");
47200
+ const refuse6 = (error) => ({ ok: false, status: 0, body: null, error });
47201
+ if (!options.target.controlToken) return refuse6("control_token_required");
47202
+ if (!options.wixToken) return refuse6("wix_account_token_required");
47203
+ if (credentialHostRefusal(options.target.control)) return refuse6("insecure_target");
47204
+ if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse6("invalid_preview_tag");
47204
47205
  const setup = options.operation === "setup";
47205
- if (setup && !options.body) return refuse5("push_setup_body_required");
47206
- if (!setup && (!options.query?.app || !options.query?.site)) return refuse5("push_setup_query_required");
47206
+ if (setup && !options.body) return refuse6("push_setup_body_required");
47207
+ if (!setup && (!options.query?.app || !options.query?.site)) return refuse6("push_setup_query_required");
47207
47208
  if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
47208
- return refuse5("push_setup_body_too_large");
47209
+ return refuse6("push_setup_body_too_large");
47209
47210
  }
47210
47211
  const base = options.target.control.replace(/\/+$/, "");
47211
47212
  let path2 = "/v1/admin/push/setup";
@@ -51023,8 +51024,8 @@ function baseOf(target, linkable, known) {
51023
51024
  let best = null;
51024
51025
  for (const base of linkable ?? []) {
51025
51026
  if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
51026
- const sep17 = target[base.length];
51027
- if ((sep17 === "_" || sep17 === "/") && (!best || base.length > best.length)) best = base;
51027
+ const sep18 = target[base.length];
51028
+ if ((sep18 === "_" || sep18 === "/") && (!best || base.length > best.length)) best = base;
51028
51029
  }
51029
51030
  return best;
51030
51031
  }
@@ -52265,7 +52266,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52265
52266
  const headers2 = Object.fromEntries(new Headers(init.headers).entries());
52266
52267
  const request = url.protocol === "https:" ? httpsRequest : httpRequest;
52267
52268
  const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
52268
- return await new Promise((resolve53, reject) => {
52269
+ return await new Promise((resolve54, reject) => {
52269
52270
  let settled = false;
52270
52271
  const finish2 = (fn) => {
52271
52272
  if (settled) return;
@@ -52302,7 +52303,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52302
52303
  }
52303
52304
  const responseHeaders = new Headers();
52304
52305
  for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
52305
- resolve53(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52306
+ resolve54(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52306
52307
  }));
52307
52308
  });
52308
52309
  req.once("error", (error) => finish2(() => reject(error)));
@@ -52602,7 +52603,7 @@ function createLocalTestSandbox() {
52602
52603
  }
52603
52604
  })();
52604
52605
  `;
52605
- return await new Promise((resolve53, reject) => {
52606
+ return await new Promise((resolve54, reject) => {
52606
52607
  const { port1, port2 } = new MessageChannel();
52607
52608
  const serializableContext = {
52608
52609
  auth: context.auth,
@@ -52678,7 +52679,7 @@ function createLocalTestSandbox() {
52678
52679
  timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
52679
52680
  return;
52680
52681
  }
52681
- if (message.ok) finish2(() => resolve53({ value: message.value, durationMs: Date.now() - started }));
52682
+ if (message.ok) finish2(() => resolve54({ value: message.value, durationMs: Date.now() - started }));
52682
52683
  else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
52683
52684
  });
52684
52685
  worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
@@ -53855,9 +53856,187 @@ var init_cli_bridge = __esm({
53855
53856
  }
53856
53857
  });
53857
53858
 
53858
- // src/mcp/tools.ts
53859
+ // src/mcp/file-tools.ts
53860
+ import { lstatSync as lstatSync12, mkdirSync as mkdirSync26, readdirSync as readdirSync27, readFileSync as readFileSync59, realpathSync as realpathSync7, rmSync as rmSync12, statSync as statSync13, writeFileSync as writeFileSync21, existsSync as existsSync54 } from "node:fs";
53861
+ import { dirname as dirname30, isAbsolute as isAbsolute5, join as join53, relative as relative11, resolve as resolve45, sep as sep14 } from "node:path";
53859
53862
  import * as z from "zod";
53860
- import { resolve as resolve45 } from "node:path";
53863
+ function within(root, p) {
53864
+ return p === root || p.startsWith(root.endsWith(sep14) ? root : root + sep14);
53865
+ }
53866
+ function realish(p) {
53867
+ let cur = p;
53868
+ const tail = [];
53869
+ while (!existsSync54(cur)) {
53870
+ const up = dirname30(cur);
53871
+ if (up === cur) break;
53872
+ tail.unshift(cur.slice(up.length + (up.endsWith(sep14) ? 0 : 1)));
53873
+ cur = up;
53874
+ }
53875
+ return join53(realpathSync7(cur), ...tail);
53876
+ }
53877
+ async function confinedAppDir(args, deps) {
53878
+ const root = resolve45(await deps.defaultDir());
53879
+ const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
53880
+ if (!existsSync54(root)) return refuse4("no_workspace", `the workspace folder ${root} does not exist`);
53881
+ if (!within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
53882
+ return dir;
53883
+ }
53884
+ function confinedPath(appDir3, rel) {
53885
+ if (typeof rel !== "string" || !rel.trim()) return { error: "a path is required" };
53886
+ if (rel.includes("\0")) return { error: "a path may not contain NUL" };
53887
+ if (isAbsolute5(rel)) return { error: `"${rel}" is absolute \u2014 give a path inside the app folder` };
53888
+ const abs = resolve45(appDir3, rel);
53889
+ const real = realish(abs);
53890
+ const base = existsSync54(appDir3) ? realpathSync7(appDir3) : realish(appDir3);
53891
+ if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
53892
+ const first = relative11(base, real).split(sep14)[0];
53893
+ if (RESERVED.has(first)) return { error: `"${rel}" is inside ${first}/, which this tool does not touch` };
53894
+ return abs;
53895
+ }
53896
+ function listFiles(appDir3) {
53897
+ const files = [];
53898
+ const walk2 = (d) => {
53899
+ for (const e of readdirSync27(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
53900
+ if (RESERVED.has(e.name)) continue;
53901
+ if (e.isSymbolicLink()) continue;
53902
+ const p = join53(d, e.name);
53903
+ if (e.isDirectory()) {
53904
+ if (!walk2(p)) return false;
53905
+ } else if (e.isFile()) {
53906
+ if (files.length >= MAX_LISTED) return false;
53907
+ files.push({ path: relative11(appDir3, p).split(sep14).join("/"), bytes: statSync13(p).size });
53908
+ }
53909
+ }
53910
+ return true;
53911
+ };
53912
+ const complete = walk2(appDir3);
53913
+ return { files, truncated: !complete };
53914
+ }
53915
+ function fileTools() {
53916
+ return [
53917
+ {
53918
+ name: "himi_list_apps",
53919
+ title: "List apps in the workspace",
53920
+ description: "The apps (content packages) in the workspace folder: the folder itself if it is one, and each sub-folder that is. Pass an app's `dir` to the other tools.",
53921
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53922
+ inputSchema: z.object({}),
53923
+ handler: async (_a, d) => {
53924
+ const root = resolve45(await d.defaultDir());
53925
+ if (!existsSync54(root)) return ok({ ok: true, workspace: root, apps: [] });
53926
+ const apps = [];
53927
+ if (existsSync54(join53(root, CONTENT_MARKER))) apps.push(".");
53928
+ for (const e of readdirSync27(root, { withFileTypes: true })) {
53929
+ if (e.isDirectory() && !e.name.startsWith(".") && existsSync54(join53(root, e.name, CONTENT_MARKER))) apps.push(e.name);
53930
+ }
53931
+ return ok({ ok: true, workspace: root, apps: apps.sort() });
53932
+ }
53933
+ },
53934
+ {
53935
+ name: "himi_list_files",
53936
+ title: "List app files",
53937
+ description: `Every file in an app folder with its size (skips ${[...RESERVED].join(", ")}; at most ${MAX_LISTED}).`,
53938
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53939
+ inputSchema: z.object({ dir: DIR }),
53940
+ handler: async (a, d) => {
53941
+ const app = await confinedAppDir(a, d);
53942
+ if (typeof app !== "string") return app;
53943
+ if (!existsSync54(app) || !statSync13(app).isDirectory()) return refuse4("no_app", `no folder at ${app}`);
53944
+ return ok({ ok: true, dir: app, ...listFiles(app) });
53945
+ }
53946
+ },
53947
+ {
53948
+ name: "himi_read_file",
53949
+ title: "Read an app file",
53950
+ description: `One file of an app folder, as UTF-8 text (at most ${MAX_FILE_BYTES / 1024} KiB).`,
53951
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53952
+ inputSchema: z.object({ dir: DIR, path: z.string().min(1).describe('Path inside the app folder, e.g. "screens/home.ts".') }),
53953
+ handler: async (a, d) => {
53954
+ const app = await confinedAppDir(a, d);
53955
+ if (typeof app !== "string") return app;
53956
+ const p = confinedPath(app, a.path);
53957
+ if (typeof p !== "string") return refuse4("bad_path", p.error);
53958
+ if (!existsSync54(p) || !lstatSync12(p).isFile()) return refuse4("not_found", `no file "${String(a.path)}"`);
53959
+ const size = statSync13(p).size;
53960
+ if (size > MAX_FILE_BYTES) return refuse4("too_large", `"${String(a.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
53961
+ return ok({ ok: true, path: a.path, bytes: size, content: readFileSync59(p, "utf8") });
53962
+ }
53963
+ },
53964
+ {
53965
+ name: "himi_write_files",
53966
+ title: "Write app files",
53967
+ description: `Create or REPLACE files in an app folder (parent folders are created). At most ${MAX_FILES_PER_WRITE} files and ${MAX_FILE_BYTES / 1024} KiB each per call. Nothing is written if any path is refused.`,
53968
+ annotations: WRITE_ANN,
53969
+ inputSchema: z.object({
53970
+ dir: DIR,
53971
+ files: z.array(z.object({ path: z.string().min(1), content: z.string() })).min(1).max(MAX_FILES_PER_WRITE)
53972
+ }),
53973
+ handler: async (a, d) => {
53974
+ const app = await confinedAppDir(a, d);
53975
+ if (typeof app !== "string") return app;
53976
+ const files = Array.isArray(a.files) ? a.files : [];
53977
+ if (!files.length || files.length > MAX_FILES_PER_WRITE) return refuse4("bad_request", `between 1 and ${MAX_FILES_PER_WRITE} files per call`);
53978
+ const planned = [];
53979
+ const refused2 = [];
53980
+ for (const f of files) {
53981
+ const p = confinedPath(app, f.path);
53982
+ if (typeof p !== "string") refused2.push({ path: f.path, error: p.error });
53983
+ else if (typeof f.content !== "string") refused2.push({ path: f.path, error: "content must be text" });
53984
+ else if (Buffer.byteLength(f.content) > MAX_FILE_BYTES) refused2.push({ path: f.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
53985
+ else if (existsSync54(p) && !lstatSync12(p).isFile()) refused2.push({ path: f.path, error: "not a regular file" });
53986
+ else planned.push({ abs: p, rel: String(f.path), content: f.content });
53987
+ }
53988
+ if (refused2.length) return { ...ok({ ok: false, error: "refused", written: [], refused: refused2 }), isError: true };
53989
+ for (const f of planned) {
53990
+ mkdirSync26(dirname30(f.abs), { recursive: true });
53991
+ writeFileSync21(f.abs, f.content);
53992
+ }
53993
+ return ok({ ok: true, dir: app, written: planned.map((f) => f.rel) });
53994
+ }
53995
+ },
53996
+ {
53997
+ name: "himi_delete_files",
53998
+ title: "Delete app files",
53999
+ description: "Delete files (not folders) from an app folder. Nothing is deleted if any path is refused.",
54000
+ annotations: { ...WRITE_ANN, idempotentHint: false },
54001
+ inputSchema: z.object({ dir: DIR, paths: z.array(z.string().min(1)).min(1).max(MAX_FILES_PER_WRITE) }),
54002
+ handler: async (a, d) => {
54003
+ const app = await confinedAppDir(a, d);
54004
+ if (typeof app !== "string") return app;
54005
+ const paths = Array.isArray(a.paths) ? a.paths : [];
54006
+ const planned = [];
54007
+ const refused2 = [];
54008
+ for (const rel of paths) {
54009
+ const p = confinedPath(app, rel);
54010
+ if (typeof p !== "string") refused2.push({ path: rel, error: p.error });
54011
+ else if (!existsSync54(p)) refused2.push({ path: rel, error: "no such file" });
54012
+ else if (!lstatSync12(p).isFile()) refused2.push({ path: rel, error: "not a regular file" });
54013
+ else planned.push(p);
54014
+ }
54015
+ if (refused2.length) return { ...ok({ ok: false, error: "refused", deleted: [], refused: refused2 }), isError: true };
54016
+ for (const p of planned) rmSync12(p);
54017
+ return ok({ ok: true, dir: app, deleted: paths });
54018
+ }
54019
+ }
54020
+ ];
54021
+ }
54022
+ var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED, RESERVED, CONTENT_MARKER, ok, refuse4, DIR, WRITE_ANN;
54023
+ var init_file_tools = __esm({
54024
+ "src/mcp/file-tools.ts"() {
54025
+ MAX_FILE_BYTES = 1024 * 1024;
54026
+ MAX_FILES_PER_WRITE = 100;
54027
+ MAX_LISTED = 2e3;
54028
+ RESERVED = /* @__PURE__ */ new Set([".git", "node_modules", "dist"]);
54029
+ CONTENT_MARKER = "himalaya.content.json";
54030
+ ok = (o) => ({ content: [{ type: "text", text: JSON.stringify(o, null, 2) }] });
54031
+ refuse4 = (error, message) => ({ content: [{ type: "text", text: JSON.stringify({ ok: false, error, message }, null, 2) }], isError: true });
54032
+ DIR = z.string().optional().describe("The app folder, relative to the workspace folder. Default: the workspace folder itself.");
54033
+ WRITE_ANN = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
54034
+ }
54035
+ });
54036
+
54037
+ // src/mcp/tools.ts
54038
+ import * as z2 from "zod";
54039
+ import { resolve as resolve46 } from "node:path";
53861
54040
  function fromCli(r, extra = []) {
53862
54041
  const body = r.json !== void 0 ? JSON.stringify(r.json, null, 2) : r.text.trim();
53863
54042
  const content = [];
@@ -53869,10 +54048,27 @@ ${r.stderr.trim()}`) });
53869
54048
  }
53870
54049
  async function appDir2(args, deps) {
53871
54050
  const base = await deps.defaultDir();
53872
- return typeof args.dir === "string" && args.dir ? resolve45(base, args.dir) : base;
54051
+ return typeof args.dir === "string" && args.dir ? resolve46(base, args.dir) : base;
54052
+ }
54053
+ function loginResult(s) {
54054
+ switch (s.state) {
54055
+ case "pending":
54056
+ return json3({
54057
+ ok: true,
54058
+ state: "pending",
54059
+ ...s.loginUrl ? { loginUrl: s.loginUrl } : {},
54060
+ message: "A browser window opened for the user to sign in to Wix. If it did not open, give them `loginUrl`. Once they have signed in, call himi_login again to confirm, or just retry the push."
54061
+ });
54062
+ case "signed_in":
54063
+ return json3({ ok: true, state: "signed_in", account: s.account, scope: s.scope, expiresAt: s.expiresAt });
54064
+ case "failed":
54065
+ return { ...json3({ ok: false, state: "failed", error: s.error, hint: "Call himi_login again to retry, or ask the user to run `himi login --browser` in a terminal." }), isError: true };
54066
+ default:
54067
+ return json3({ ok: true, state: "idle" });
54068
+ }
53873
54069
  }
53874
54070
  async function requireLogin(deps) {
53875
- const who = await deps.runCli(["whoami"]);
54071
+ const who = await deps.runCli(["whoami", ...opt("--target", deps.login.target())]);
53876
54072
  if (who.code === 0) return null;
53877
54073
  return { content: [{ type: "text", text: LOGIN_HINT }, ...who.stderr.trim() ? [{ type: "text", text: who.stderr.trim() }] : []], isError: true };
53878
54074
  }
@@ -53891,8 +54087,8 @@ function guarded(h) {
53891
54087
  return h(args, deps);
53892
54088
  };
53893
54089
  }
53894
- function himiTools() {
53895
- return rawTools().map((t) => ({ ...t, handler: guarded(t.handler) }));
54090
+ function himiTools(opts = {}) {
54091
+ return [...rawTools(), ...opts.withFiles ? fileTools() : []].map((t) => ({ ...t, handler: guarded(t.handler) }));
53896
54092
  }
53897
54093
  function rawTools() {
53898
54094
  return [
@@ -53901,7 +54097,7 @@ function rawTools() {
53901
54097
  title: "Read a himi authoring guide",
53902
54098
  description: "List the Himalaya authoring guides, or read one by topic id. Offline \u2014 the guides ship with this CLI. Start here before authoring.",
53903
54099
  annotations: LEARN,
53904
- inputSchema: z.object({ topic: z.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
54100
+ inputSchema: z2.object({ topic: z2.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
53905
54101
  handler: async (a, d) => fromCli(await d.runCli(["docs", ...typeof a.topic === "string" && a.topic ? [a.topic] : [], "--json"]))
53906
54102
  },
53907
54103
  {
@@ -53909,7 +54105,7 @@ function rawTools() {
53909
54105
  title: "SDUI component vocabulary",
53910
54106
  description: "The SDUI component vocabulary and props a descriptor may use; a name returns that one component. Offline.",
53911
54107
  annotations: LEARN,
53912
- inputSchema: z.object({ name: z.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
54108
+ inputSchema: z2.object({ name: z2.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
53913
54109
  handler: async (a, d) => fromCli(await d.runCli(["components", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
53914
54110
  },
53915
54111
  {
@@ -53917,7 +54113,7 @@ function rawTools() {
53917
54113
  title: "Importable @himalaya SDKs",
53918
54114
  description: "The @himalaya/* SDKs a Tier-5 worker may import; a name returns that SDK's typed API. Offline.",
53919
54115
  annotations: LEARN,
53920
- inputSchema: z.object({ name: z.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
54116
+ inputSchema: z2.object({ name: z2.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
53921
54117
  handler: async (a, d) => fromCli(await d.runCli(["sdk", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
53922
54118
  },
53923
54119
  {
@@ -53925,7 +54121,7 @@ function rawTools() {
53925
54121
  title: "Icon name vocabulary",
53926
54122
  description: "The valid Icon.name values. An unknown name renders a fallback glyph and `himi_validate` warns. Offline.",
53927
54123
  annotations: LEARN,
53928
- inputSchema: z.object({}),
54124
+ inputSchema: z2.object({}),
53929
54125
  handler: async (_a, d) => fromCli(await d.runCli(["icons", "--json"]))
53930
54126
  },
53931
54127
  {
@@ -53933,14 +54129,14 @@ function rawTools() {
53933
54129
  title: "Create a new himi app",
53934
54130
  description: "Scaffold a new content package `<parentDir>/<name>` (optionally from a reference template), with its agent files and this MCP server already configured for Claude Code, Cursor, Codex and VS Code. Refuses a directory that already exists.",
53935
54131
  annotations: LOCAL_WRITE,
53936
- inputSchema: z.object({
53937
- name: z.string().min(1).describe("The app name \u2014 also its folder name."),
53938
- parentDir: z.string().optional().describe("Where to create the folder. Default: the workspace root."),
53939
- template: z.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
54132
+ inputSchema: z2.object({
54133
+ name: z2.string().min(1).describe("The app name \u2014 also its folder name."),
54134
+ parentDir: z2.string().optional().describe("Where to create the folder. Default: the workspace root."),
54135
+ template: z2.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
53940
54136
  }),
53941
54137
  handler: async (a, d) => {
53942
54138
  const base = await d.defaultDir();
53943
- const parent = typeof a.parentDir === "string" && a.parentDir ? resolve45(base, a.parentDir) : base;
54139
+ const parent = typeof a.parentDir === "string" && a.parentDir ? resolve46(base, a.parentDir) : base;
53944
54140
  return fromCli(await d.runCli(["init", String(a.name), "--dir", parent, ...opt("--template", a.template)]));
53945
54141
  }
53946
54142
  },
@@ -53949,7 +54145,7 @@ function rawTools() {
53949
54145
  title: "Build the app's worker bundles",
53950
54146
  description: "Compile every tier5-src/<name>/index.ts to dist/bundles/<name>.bundle.js with esbuild. Writes dist/ only.",
53951
54147
  annotations: LOCAL_WRITE,
53952
- inputSchema: z.object({ dir: DIR }),
54148
+ inputSchema: z2.object({ dir: DIR2 }),
53953
54149
  handler: async (a, d) => fromCli(await d.runCli(["build", "--content", await appDir2(a, d)]))
53954
54150
  },
53955
54151
  {
@@ -53957,7 +54153,7 @@ function rawTools() {
53957
54153
  title: "Validate the app",
53958
54154
  description: "Lint the content package without publishing: worker type-checking, schema/proto, token refs, the component allowlist, $service bindings. Run before every preview or push.",
53959
54155
  annotations: CHECK,
53960
- inputSchema: z.object({ dir: DIR, strict: z.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
54156
+ inputSchema: z2.object({ dir: DIR2, strict: z2.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
53961
54157
  handler: async (a, d) => fromCli(await d.runCli(["validate", "--content", await appDir2(a, d), ...sw("--strict", a.strict)]))
53962
54158
  },
53963
54159
  {
@@ -53965,10 +54161,10 @@ function rawTools() {
53965
54161
  title: "Behavioral crawl",
53966
54162
  description: "The derived behavioral crawl: boots each screen's real worker and dispatches every action its descriptor declares, against the app's mocked network (dev/net-mocks.json). Hermetic \u2014 never reaches live Wix. Catches the wrong-reducer class validate and render pass clean.",
53967
54163
  annotations: CHECK,
53968
- inputSchema: z.object({
53969
- dir: DIR,
53970
- screens: z.array(z.string()).optional().describe("Only these screen ids. Omit for all."),
53971
- deep: z.boolean().optional().describe("Also follow navigation into the screens actions open.")
54164
+ inputSchema: z2.object({
54165
+ dir: DIR2,
54166
+ screens: z2.array(z2.string()).optional().describe("Only these screen ids. Omit for all."),
54167
+ deep: z2.boolean().optional().describe("Also follow navigation into the screens actions open.")
53972
54168
  }),
53973
54169
  handler: async (a, d) => {
53974
54170
  const screens = Array.isArray(a.screens) ? a.screens.filter((s) => typeof s === "string") : [];
@@ -53980,13 +54176,13 @@ function rawTools() {
53980
54176
  title: "Render a screen to PNG",
53981
54177
  description: "Headless-render one screen with the web renderer and return the PNG plus the render diagnostics. The PNG is also written to .himi/shots/<screen>.png, which the build board shows. Needs Playwright's Chromium; without it the result says how to install it and still returns the diagnostics.",
53982
54178
  annotations: CHECK,
53983
- inputSchema: z.object({
53984
- screen: z.string().min(1).describe("The screen id."),
53985
- dir: DIR,
53986
- scheme: z.enum(["light", "dark"]).optional(),
53987
- width: z.number().int().positive().optional().describe("Viewport width in px."),
53988
- device: z.string().optional().describe("A named device (overrides width)."),
53989
- rtl: z.boolean().optional()
54179
+ inputSchema: z2.object({
54180
+ screen: z2.string().min(1).describe("The screen id."),
54181
+ dir: DIR2,
54182
+ scheme: z2.enum(["light", "dark"]).optional(),
54183
+ width: z2.number().int().positive().optional().describe("Viewport width in px."),
54184
+ device: z2.string().optional().describe("A named device (overrides width)."),
54185
+ rtl: z2.boolean().optional()
53990
54186
  }),
53991
54187
  handler: async (a, d) => {
53992
54188
  const r = await d.runCli([
@@ -54016,12 +54212,12 @@ function rawTools() {
54016
54212
  title: "Build journal",
54017
54213
  description: "Read or append the owner-facing build journal (.himi/progress.jsonl). With `message`, append one postcard for a journey step; without, print the journal \u2014 `brief` gives the short session-start summary (current step, open approvals).",
54018
54214
  annotations: { ...LOCAL_WRITE, idempotentHint: false },
54019
- inputSchema: z.object({
54020
- dir: DIR,
54021
- message: z.string().optional().describe("What changed, one or two lines, for the owner."),
54022
- step: z.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
54023
- noImage: z.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
54024
- brief: z.boolean().optional()
54215
+ inputSchema: z2.object({
54216
+ dir: DIR2,
54217
+ message: z2.string().optional().describe("What changed, one or two lines, for the owner."),
54218
+ step: z2.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
54219
+ noImage: z2.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
54220
+ brief: z2.boolean().optional()
54025
54221
  }),
54026
54222
  handler: async (a, d) => {
54027
54223
  const dir = await appDir2(a, d);
@@ -54034,7 +54230,7 @@ function rawTools() {
54034
54230
  title: "Start the live preview",
54035
54231
  description: "Serve the app on localhost and keep it live (`himi run --watch`): every save rebuilds and repaints the open tab. Returns the URL. Reuses a preview that is already running for this app. " + PREVIEW_HINT,
54036
54232
  annotations: LOCAL_WRITE,
54037
- inputSchema: z.object({ dir: DIR }),
54233
+ inputSchema: z2.object({ dir: DIR2 }),
54038
54234
  handler: async (a, d) => {
54039
54235
  try {
54040
54236
  return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
@@ -54051,7 +54247,7 @@ ${log}` : ""}`, true);
54051
54247
  title: "Live preview status",
54052
54248
  description: "Whether this app's live preview is running, and its URL and last build result.",
54053
54249
  annotations: CHECK,
54054
- inputSchema: z.object({ dir: DIR }),
54250
+ inputSchema: z2.object({ dir: DIR2 }),
54055
54251
  handler: async (a, d) => json3(await d.preview.status(await appDir2(a, d)))
54056
54252
  },
54057
54253
  {
@@ -54059,7 +54255,7 @@ ${log}` : ""}`, true);
54059
54255
  title: "Stop the live preview",
54060
54256
  description: "Stop this app's live preview (the `himi run --watch` a `himi_preview_start` started).",
54061
54257
  annotations: { ...LOCAL_WRITE, destructiveHint: false },
54062
- inputSchema: z.object({ dir: DIR }),
54258
+ inputSchema: z2.object({ dir: DIR2 }),
54063
54259
  handler: async (a, d) => json3(await d.preview.stop(await appDir2(a, d)))
54064
54260
  },
54065
54261
  {
@@ -54067,38 +54263,60 @@ ${log}` : ""}`, true);
54067
54263
  title: "Signed-in identity",
54068
54264
  description: "The identity the stored serve-plane credential carries (account, scope, expiry). Local \u2014 decodes the stored token, no network.",
54069
54265
  annotations: LEARN,
54070
- inputSchema: z.object({ target: z.string().optional().describe("Serve target. Default: the CLI's default.") }),
54071
- handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target)]))
54266
+ inputSchema: z2.object({ target: z2.string().optional().describe("Serve target. Default: the CLI's default.") }),
54267
+ handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target ?? d.login.target())]))
54268
+ },
54269
+ {
54270
+ name: "himi_login",
54271
+ title: "Sign in to Wix",
54272
+ description: "Open a browser window where the USER signs in to Wix, so himi_push and himi_share can publish. Returns at once with the sign-in link; call again to see whether the sign-in finished. Already signed in: says who, and opens nothing unless `switchAccount` is true. This server never sees the credential \u2014 the sign-in stores a scoped token on this machine.",
54273
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
54274
+ inputSchema: z2.object({
54275
+ target: z2.string().optional().describe("Serve target. Default: the CLI's default."),
54276
+ switchAccount: z2.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
54277
+ }),
54278
+ handler: async (a, d) => {
54279
+ const s = d.login.status();
54280
+ if (s.state === "pending") return loginResult(s);
54281
+ if (!a.switchAccount) {
54282
+ const who = await d.runCli(["whoami", ...opt("--target", a.target)]);
54283
+ if (who.code === 0) {
54284
+ d.login.adopt(typeof a.target === "string" && a.target ? a.target : void 0);
54285
+ return json3({ ok: true, state: "signed_in", ...who.json && typeof who.json === "object" ? who.json : {} });
54286
+ }
54287
+ }
54288
+ return loginResult(await d.login.start(typeof a.target === "string" && a.target ? a.target : void 0));
54289
+ }
54072
54290
  },
54073
54291
  {
54074
54292
  name: "himi_push",
54075
54293
  title: "Publish a draft",
54076
- description: "Lint, build and publish the app as a DRAFT release: owner-private, servable by preview link and in Himi Player, NOT live. Returns the preview links and the universal link that opens it in Himi Player. Never promotes \u2014 going live is a human command. Refuses on any validation error. Needs `himi login --browser` first.",
54294
+ description: "Lint, build and publish the app as a DRAFT release: owner-private, servable by preview link and in Himi Player, NOT live. Returns the preview links and the universal link that opens it in Himi Player. Never promotes \u2014 going live is a human command. Refuses on any validation error. Needs a sign-in first (himi_login).",
54077
54295
  annotations: PUBLISH,
54078
- inputSchema: z.object({
54079
- dir: DIR,
54080
- label: z.string().optional().describe("A short label for this draft."),
54081
- notes: z.string().optional().describe("Release notes for this draft.")
54296
+ inputSchema: z2.object({
54297
+ dir: DIR2,
54298
+ label: z2.string().optional().describe("A short label for this draft."),
54299
+ notes: z2.string().optional().describe("Release notes for this draft.")
54082
54300
  }),
54083
54301
  handler: async (a, d) => {
54084
54302
  const gate = await requireLogin(d);
54085
54303
  if (gate) return gate;
54086
- return fromCli(await d.runCli(["push", "--content", await appDir2(a, d), "--draft", ...opt("--label", a.label), ...opt("--notes", a.notes)]));
54304
+ return fromCli(await d.runCli(["push", "--content", await appDir2(a, d), "--draft", ...opt("--label", a.label), ...opt("--notes", a.notes), ...opt("--target", d.login.target())]));
54087
54305
  }
54088
54306
  },
54089
54307
  {
54090
54308
  name: "himi_share",
54091
54309
  title: "Share a .himi package link",
54092
- description: "Publish a content-addressed share link for a validated `.himi` package of an already-published release. Needs `himi login --browser` first.",
54310
+ description: "Publish a content-addressed share link for a validated `.himi` package of an already-published release. Needs a sign-in first (himi_login).",
54093
54311
  annotations: PUBLISH,
54094
- inputSchema: z.object({
54095
- file: z.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
54096
- expiresAt: z.string().optional().describe("ISO timestamp the link stops working.")
54312
+ inputSchema: z2.object({
54313
+ file: z2.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
54314
+ expiresAt: z2.string().optional().describe("ISO timestamp the link stops working.")
54097
54315
  }),
54098
54316
  handler: async (a, d) => {
54099
54317
  const gate = await requireLogin(d);
54100
54318
  if (gate) return gate;
54101
- return fromCli(await d.runCli(["share", "--file", resolve45(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt)]));
54319
+ return fromCli(await d.runCli(["share", "--file", resolve46(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt), ...opt("--target", d.login.target())]));
54102
54320
  }
54103
54321
  },
54104
54322
  {
@@ -54108,19 +54326,20 @@ ${log}` : ""}`, true);
54108
54326
  // Not idempotent: with credentials, each `himi preview` mints a fresh single-use handover —
54109
54327
  // the same reason the hosted connector's tool of this name says false (RFC 0064 §5).
54110
54328
  annotations: { ...PUBLISH, readOnlyHint: true, idempotentHint: false },
54111
- inputSchema: z.object({
54112
- app: z.string().min(1),
54113
- release: z.string().min(1),
54114
- screen: z.string().optional(),
54115
- surface: z.string().optional()
54329
+ inputSchema: z2.object({
54330
+ app: z2.string().min(1),
54331
+ release: z2.string().min(1),
54332
+ screen: z2.string().optional(),
54333
+ surface: z2.string().optional()
54116
54334
  }),
54117
- handler: async (a, d) => fromCli(await d.runCli(["preview", "--app", String(a.app), "--release", String(a.release), ...opt("--screen", a.screen), ...opt("--surface", a.surface)]))
54335
+ handler: async (a, d) => fromCli(await d.runCli(["preview", "--app", String(a.app), "--release", String(a.release), ...opt("--screen", a.screen), ...opt("--surface", a.surface), ...opt("--target", d.login.target())]))
54118
54336
  }
54119
54337
  ];
54120
54338
  }
54121
- var MAX_TEXT2, clip, text6, json3, opt, sw, DIR, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54339
+ var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54122
54340
  var init_tools = __esm({
54123
54341
  "src/mcp/tools.ts"() {
54342
+ init_file_tools();
54124
54343
  MAX_TEXT2 = 8e4;
54125
54344
  clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
54126
54345
  \u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
@@ -54128,13 +54347,88 @@ var init_tools = __esm({
54128
54347
  json3 = (o) => text6(JSON.stringify(o, null, 2));
54129
54348
  opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
54130
54349
  sw = (flag, v) => v === true ? [flag] : [];
54131
- DIR = z.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
54350
+ DIR2 = z2.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
54132
54351
  LEARN = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54133
54352
  CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54134
54353
  LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54135
54354
  PUBLISH = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
54136
54355
  PREVIEW_HINT = "The preview is already running: open `url` in your built-in browser \u2014 Claude Code desktop's browser pane, Cursor's Browser tool, the Browser in Codex inside the ChatGPT desktop app, VS Code's integrated browser. Do not also start the `himi-preview` launch configuration: it serves the same port, and is the way to start a preview only when none is running. A terminal-only agent should show the owner `himi_render` PNGs instead. `board` (when present) is the build board on the same origin.";
54137
- LOGIN_HINT = "Not signed in to the himi serve plane. Ask the user to run `himi login --browser` in a terminal (this server never handles credentials), then retry.";
54356
+ LOGIN_HINT = "Not signed in to the himi serve plane. Call himi_login: it opens a browser window where the user signs in to Wix (this server never sees the credential). A user with a terminal can run `himi login --browser` instead. Then retry.";
54357
+ }
54358
+ });
54359
+
54360
+ // src/mcp/login.ts
54361
+ import { spawn as nodeSpawn2 } from "node:child_process";
54362
+ function createLoginSession(deps) {
54363
+ let current = { state: "idle" };
54364
+ let signedInTarget;
54365
+ return {
54366
+ status: () => current,
54367
+ target: () => signedInTarget,
54368
+ adopt: (target) => {
54369
+ signedInTarget = target;
54370
+ },
54371
+ start(target) {
54372
+ if (current.state === "pending") return Promise.resolve(current);
54373
+ const self = deps.selfCommand();
54374
+ const args = [...self.args, "login", "--browser", "--skip-version-check", ...target ? ["--target", target] : []];
54375
+ const pending = { state: "pending", startedAt: deps.now() };
54376
+ current = pending;
54377
+ const out2 = [];
54378
+ const err = [];
54379
+ return new Promise((resolve54) => {
54380
+ let answered = false;
54381
+ const answer = () => {
54382
+ if (answered) return;
54383
+ answered = true;
54384
+ resolve54(current);
54385
+ };
54386
+ let child;
54387
+ try {
54388
+ child = deps.spawn(self.cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, HIMI_NO_UPDATE_CHECK: "1" } });
54389
+ } catch (e) {
54390
+ current = { state: "failed", error: `could not start himi login: ${e.message}` };
54391
+ answer();
54392
+ return;
54393
+ }
54394
+ child.stdout?.on("data", (c) => out2.push(String(c)));
54395
+ child.stderr?.on("data", (c) => {
54396
+ err.push(String(c));
54397
+ const link = LINK2.exec(err.join(""))?.[0];
54398
+ if (link && !pending.loginUrl && current === pending) {
54399
+ pending.loginUrl = link;
54400
+ answer();
54401
+ }
54402
+ });
54403
+ child.once("error", (e) => {
54404
+ current = { state: "failed", error: `could not start himi login: ${e.message}` };
54405
+ answer();
54406
+ });
54407
+ child.once("exit", (code) => {
54408
+ if (code === 0) {
54409
+ const r = lastJson([out2.join("")]) ?? {};
54410
+ current = { state: "signed_in", account: r.sub, scope: r.scope, expiresAt: r.exp };
54411
+ signedInTarget = target;
54412
+ } else {
54413
+ const e = lastJson(err.join("").split("\n"));
54414
+ current = { state: "failed", error: e?.error ?? (err.join("").trim().slice(-500) || `himi login exited ${code}`) };
54415
+ }
54416
+ answer();
54417
+ });
54418
+ setTimeout(answer, deps.linkWaitMs ?? 5e3).unref?.();
54419
+ });
54420
+ }
54421
+ };
54422
+ }
54423
+ var defaultLoginDeps, LINK2;
54424
+ var init_login = __esm({
54425
+ "src/mcp/login.ts"() {
54426
+ init_cli_bridge();
54427
+ defaultLoginDeps = {
54428
+ spawn: (cmd, args, opts) => nodeSpawn2(cmd, args, opts),
54429
+ now: () => Date.now()
54430
+ };
54431
+ LINK2 = /https?:\/\/[^\s)]+/;
54138
54432
  }
54139
54433
  });
54140
54434
 
@@ -54146,7 +54440,7 @@ __export(server_exports, {
54146
54440
  protectStdout: () => protectStdout,
54147
54441
  startMcpServer: () => startMcpServer
54148
54442
  });
54149
- import { readFileSync as readFileSync59 } from "node:fs";
54443
+ import { readFileSync as readFileSync60 } from "node:fs";
54150
54444
  import { fileURLToPath as fileURLToPath21 } from "node:url";
54151
54445
  import { McpServer } from "@modelcontextprotocol/server";
54152
54446
  import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
@@ -54156,9 +54450,9 @@ function protectStdout() {
54156
54450
  console.info = toErr;
54157
54451
  console.debug = toErr;
54158
54452
  }
54159
- function buildServer(deps, version2) {
54453
+ function buildServer(deps, version2, tools = {}) {
54160
54454
  const server = new McpServer({ name: "himi", version: version2 }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
54161
- for (const tool of himiTools()) {
54455
+ for (const tool of himiTools(tools)) {
54162
54456
  server.registerTool(
54163
54457
  tool.name,
54164
54458
  { title: tool.title, description: tool.description, inputSchema: tool.inputSchema, annotations: { title: tool.title, ...tool.annotations } },
@@ -54192,22 +54486,23 @@ async function startMcpServer(opts) {
54192
54486
  // next call rather than pinning every later tool to the server's cwd (often $HOME for a GUI host).
54193
54487
  defaultDir: async () => {
54194
54488
  if (!rootDir && pinned) rootDir = await firstRoot(pinned);
54195
- return rootDir || process.cwd();
54489
+ return rootDir || opts.workspace || process.cwd();
54196
54490
  },
54197
54491
  preview: {
54198
54492
  start: (dir) => startPreview(dir, { port: previewPortForDir(dir) }, previewDeps),
54199
54493
  status: (dir) => previewStatus(dir, previewDeps),
54200
54494
  stop: (dir) => stopPreview(dir, previewDeps)
54201
54495
  },
54202
- readFile: (p) => readFileSync59(p)
54496
+ readFile: (p) => readFileSync60(p),
54497
+ login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
54203
54498
  };
54204
- const closed = new Promise((resolve53) => {
54205
- stdin.once("end", resolve53);
54206
- stdin.once("close", resolve53);
54499
+ const closed = new Promise((resolve54) => {
54500
+ stdin.once("end", resolve54);
54501
+ stdin.once("close", resolve54);
54207
54502
  });
54208
54503
  const handle = serveStdio(
54209
54504
  () => {
54210
- pinned = buildServer(deps, opts.version);
54505
+ pinned = buildServer(deps, opts.version, { withFiles: opts.withFiles });
54211
54506
  return pinned;
54212
54507
  },
54213
54508
  { transport: new StdioServerTransport(stdin, stdout), onerror: (e) => console.error(`[himi mcp] ${e.message}`) }
@@ -54221,6 +54516,7 @@ var init_server = __esm({
54221
54516
  init_cli_bridge();
54222
54517
  init_tools();
54223
54518
  init_preview();
54519
+ init_login();
54224
54520
  SERVER_INSTRUCTIONS = "himi builds native mobile apps (iOS + Android + web) from a content package: SDUI descriptors plus Tier-5 JS workers. The loop: himi_docs (read `headless-loop` first) \u2192 edit files \u2192 himi_validate \u2192 himi_test \u2192 himi_render (show the owner the PNG) \u2192 himi_preview_start (live preview in your IDE's browser) \u2192 himi_push (a DRAFT the owner opens in Himi Player; never live). Tools act on the workspace root unless given `dir`.";
54225
54521
  }
54226
54522
  });
@@ -54240,9 +54536,9 @@ __export(native_decode_exports, {
54240
54536
  runNativeDecode: () => runNativeDecode
54241
54537
  });
54242
54538
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
54243
- import { existsSync as existsSync54, mkdtempSync as mkdtempSync2, readFileSync as readFileSync60, rmSync as rmSync12, writeFileSync as writeFileSync21 } from "node:fs";
54539
+ import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync22 } from "node:fs";
54244
54540
  import { tmpdir as tmpdir3 } from "node:os";
54245
- import { join as join53 } from "node:path";
54541
+ import { join as join54 } from "node:path";
54246
54542
  import { fileURLToPath as fileURLToPath22 } from "node:url";
54247
54543
  function nativeDecodePackageDir() {
54248
54544
  return fileURLToPath22(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
@@ -54252,8 +54548,8 @@ function nativeDecodeAndroidHarnessDir() {
54252
54548
  }
54253
54549
  function nativeOracleShipped() {
54254
54550
  return {
54255
- ios: existsSync54(join53(nativeDecodePackageDir(), "Package.swift")),
54256
- android: existsSync54(join53(nativeDecodeAndroidHarnessDir(), "gradlew"))
54551
+ ios: existsSync55(join54(nativeDecodePackageDir(), "Package.swift")),
54552
+ android: existsSync55(join54(nativeDecodeAndroidHarnessDir(), "gradlew"))
54257
54553
  };
54258
54554
  }
54259
54555
  function detectNativeDecode(options = {}) {
@@ -54264,7 +54560,7 @@ function detectNativeDecode(options = {}) {
54264
54560
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
54265
54561
  }
54266
54562
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
54267
- const packageAvailable = options.packageAvailable ?? existsSync54(join53(packageDir, "Package.swift"));
54563
+ const packageAvailable = options.packageAvailable ?? existsSync55(join54(packageDir, "Package.swift"));
54268
54564
  if (!packageAvailable) {
54269
54565
  return {
54270
54566
  platform: "ios",
@@ -54276,7 +54572,7 @@ function detectNativeDecode(options = {}) {
54276
54572
  }
54277
54573
  function localPropertiesSdk(harnessDir) {
54278
54574
  try {
54279
- const match = readFileSync60(join53(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
54575
+ const match = readFileSync61(join54(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
54280
54576
  return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
54281
54577
  } catch {
54282
54578
  return null;
@@ -54284,8 +54580,8 @@ function localPropertiesSdk(harnessDir) {
54284
54580
  }
54285
54581
  function detectAndroidNativeDecode(options = {}) {
54286
54582
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
54287
- const gradlew = join53(harnessDir, "gradlew");
54288
- const gradlewAvailable = options.gradlewAvailable ?? existsSync54(gradlew);
54583
+ const gradlew = join54(harnessDir, "gradlew");
54584
+ const gradlewAvailable = options.gradlewAvailable ?? existsSync55(gradlew);
54289
54585
  if (!gradlewAvailable) {
54290
54586
  return {
54291
54587
  platform: "android",
@@ -54295,7 +54591,7 @@ function detectAndroidNativeDecode(options = {}) {
54295
54591
  }
54296
54592
  const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
54297
54593
  const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
54298
- const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync54(sdk));
54594
+ const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync55(sdk));
54299
54595
  if (!sdkAvailable) {
54300
54596
  return {
54301
54597
  platform: "android",
@@ -54367,14 +54663,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
54367
54663
  return verdicts;
54368
54664
  }
54369
54665
  function runNativeDecode(options) {
54370
- const descriptorDir = mkdtempSync2(join53(tmpdir3(), "himi-native-decode-"));
54666
+ const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-"));
54371
54667
  const startedAt = Date.now();
54372
54668
  try {
54373
54669
  for (const descriptor of options.descriptors) {
54374
54670
  if (typeof descriptor.descriptorJson !== "string") {
54375
54671
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
54376
54672
  }
54377
- writeFileSync21(join53(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54673
+ writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54378
54674
  }
54379
54675
  options.progress?.("building cached Swift oracle");
54380
54676
  execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
@@ -54386,7 +54682,7 @@ function runNativeDecode(options) {
54386
54682
  encoding: "utf8"
54387
54683
  }).trim();
54388
54684
  options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
54389
- const stdout = execFileSync5(join53(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
54685
+ const stdout = execFileSync5(join54(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
54390
54686
  stdio: ["ignore", "pipe", "pipe"],
54391
54687
  encoding: "utf8"
54392
54688
  });
@@ -54400,19 +54696,19 @@ function runNativeDecode(options) {
54400
54696
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
54401
54697
  throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
54402
54698
  } finally {
54403
- rmSync12(descriptorDir, { recursive: true, force: true });
54699
+ rmSync13(descriptorDir, { recursive: true, force: true });
54404
54700
  }
54405
54701
  }
54406
54702
  function runAndroidNativeDecode(options) {
54407
- const descriptorDir = mkdtempSync2(join53(tmpdir3(), "himi-native-decode-android-"));
54408
- const outputPath = join53(descriptorDir, "verdicts.ndjson");
54703
+ const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-android-"));
54704
+ const outputPath = join54(descriptorDir, "verdicts.ndjson");
54409
54705
  const startedAt = Date.now();
54410
54706
  try {
54411
54707
  for (const descriptor of options.descriptors) {
54412
54708
  if (typeof descriptor.descriptorJson !== "string") {
54413
54709
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
54414
54710
  }
54415
- writeFileSync21(join53(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54711
+ writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54416
54712
  }
54417
54713
  options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
54418
54714
  execFileSync5(options.gradlew, [
@@ -54427,7 +54723,7 @@ function runAndroidNativeDecode(options) {
54427
54723
  stdio: ["ignore", "ignore", "pipe"],
54428
54724
  encoding: "utf8"
54429
54725
  });
54430
- const stdout = readFileSync60(outputPath, "utf8");
54726
+ const stdout = readFileSync61(outputPath, "utf8");
54431
54727
  return {
54432
54728
  platform: "android",
54433
54729
  verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
@@ -54438,7 +54734,7 @@ function runAndroidNativeDecode(options) {
54438
54734
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
54439
54735
  throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
54440
54736
  } finally {
54441
- rmSync12(descriptorDir, { recursive: true, force: true });
54737
+ rmSync13(descriptorDir, { recursive: true, force: true });
54442
54738
  }
54443
54739
  }
54444
54740
  function fieldAt(path2) {
@@ -54497,30 +54793,30 @@ __export(browser_authoring_exports, {
54497
54793
  });
54498
54794
  import { createServer as createServer5 } from "node:http";
54499
54795
  import { createHash as createHash29, randomBytes as randomBytes4 } from "node:crypto";
54500
- import { existsSync as existsSync55, readdirSync as readdirSync27, readFileSync as readFileSync61, realpathSync as realpathSync7, statSync as statSync13 } from "node:fs";
54501
- import { join as join54, posix as posix2, relative as relative11, sep as sep14 } from "node:path";
54796
+ import { existsSync as existsSync56, readdirSync as readdirSync28, readFileSync as readFileSync62, realpathSync as realpathSync8, statSync as statSync14 } from "node:fs";
54797
+ import { join as join55, posix as posix2, relative as relative12, sep as sep15 } from "node:path";
54502
54798
  function humanMs(ms) {
54503
54799
  return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
54504
54800
  }
54505
54801
  function collectWorkerSources(tier5SrcDir, bundleName) {
54506
- const root = join54(tier5SrcDir, bundleName);
54802
+ const root = join55(tier5SrcDir, bundleName);
54507
54803
  const files = {};
54508
54804
  const visitedDirs = /* @__PURE__ */ new Set();
54509
54805
  const walk2 = (abs, rel) => {
54510
- const real = realpathSync7(abs);
54806
+ const real = realpathSync8(abs);
54511
54807
  if (visitedDirs.has(real)) return;
54512
54808
  visitedDirs.add(real);
54513
- for (const name of readdirSync27(abs).sort()) {
54514
- const childAbs = join54(abs, name);
54809
+ for (const name of readdirSync28(abs).sort()) {
54810
+ const childAbs = join55(abs, name);
54515
54811
  const childRel = posix2.join(rel, name);
54516
- if (statSync13(childAbs).isDirectory()) {
54812
+ if (statSync14(childAbs).isDirectory()) {
54517
54813
  walk2(childAbs, childRel);
54518
54814
  } else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
54519
- files[childRel] = readFileSync61(childAbs, "utf8");
54815
+ files[childRel] = readFileSync62(childAbs, "utf8");
54520
54816
  }
54521
54817
  }
54522
54818
  };
54523
- if (!existsSync55(root)) return null;
54819
+ if (!existsSync56(root)) return null;
54524
54820
  walk2(root, `/tier5-src/${bundleName}`);
54525
54821
  const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
54526
54822
  if (!entry) return null;
@@ -54537,20 +54833,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
54537
54833
  const spec = m[1];
54538
54834
  const virtual = posix2.normalize(posix2.join(dir, spec));
54539
54835
  if (!virtual.startsWith("/tier5-src/")) continue;
54540
- const onDisk = join54(tier5SrcDir, virtual.slice("/tier5-src/".length));
54836
+ const onDisk = join55(tier5SrcDir, virtual.slice("/tier5-src/".length));
54541
54837
  const candidates = [
54542
54838
  onDisk,
54543
54839
  `${onDisk}.ts`,
54544
54840
  `${onDisk}.js`,
54545
54841
  onDisk.replace(/\.js$/, ".ts"),
54546
- join54(onDisk, "index.ts"),
54547
- join54(onDisk, "index.js")
54842
+ join55(onDisk, "index.ts"),
54843
+ join55(onDisk, "index.js")
54548
54844
  ];
54549
54845
  for (const abs of candidates) {
54550
- if (!existsSync55(abs) || statSync13(abs).isDirectory()) continue;
54551
- const key2 = `/tier5-src/${relative11(tier5SrcDir, abs).split(sep14).join(posix2.sep)}`;
54846
+ if (!existsSync56(abs) || statSync14(abs).isDirectory()) continue;
54847
+ const key2 = `/tier5-src/${relative12(tier5SrcDir, abs).split(sep15).join(posix2.sep)}`;
54552
54848
  if (key2 in files) break;
54553
- files[key2] = readFileSync61(abs, "utf8");
54849
+ files[key2] = readFileSync62(abs, "utf8");
54554
54850
  queue.push(key2);
54555
54851
  break;
54556
54852
  }
@@ -54582,10 +54878,10 @@ function collectSdkModules(files, resolveSubpath) {
54582
54878
  for (const source of Object.values(files)) visit(source);
54583
54879
  return { modules, unsupported };
54584
54880
  }
54585
- function sdkSubpathReader(resolve53) {
54881
+ function sdkSubpathReader(resolve54) {
54586
54882
  return (sub) => {
54587
54883
  try {
54588
- return readFileSync61(resolve53(`@wix/himalaya/${sub}`), "utf8");
54884
+ return readFileSync62(resolve54(`@wix/himalaya/${sub}`), "utf8");
54589
54885
  } catch {
54590
54886
  return null;
54591
54887
  }
@@ -54663,7 +54959,7 @@ async function runBrowserAuthoring(opts) {
54663
54959
  const token = mintToken2(payload);
54664
54960
  const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
54665
54961
  if (unusable) throw new Error(unusable);
54666
- return await new Promise((resolve53, reject) => {
54962
+ return await new Promise((resolve54, reject) => {
54667
54963
  let settled = false;
54668
54964
  let url = "";
54669
54965
  const server = createServer5();
@@ -54715,7 +55011,7 @@ async function runBrowserAuthoring(opts) {
54715
55011
  }
54716
55012
  res.writeHead(200, { "content-type": "text/plain" }).end("ok");
54717
55013
  const report3 = body.result;
54718
- finish2(() => resolve53({ report: report3, url }));
55014
+ finish2(() => resolve54({ report: report3, url }));
54719
55015
  })();
54720
55016
  });
54721
55017
  server.on("error", (e) => finish2(() => reject(e)));
@@ -54757,8 +55053,8 @@ __export(coverage_exports, {
54757
55053
  suppressedNativeKeys: () => suppressedNativeKeys,
54758
55054
  trendAndStore: () => trendAndStore
54759
55055
  });
54760
- import { existsSync as existsSync56, mkdirSync as mkdirSync26, readFileSync as readFileSync62, writeFileSync as writeFileSync22 } from "node:fs";
54761
- import { dirname as dirname30, join as join55 } from "node:path";
55056
+ import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as writeFileSync23 } from "node:fs";
55057
+ import { dirname as dirname31, join as join56 } from "node:path";
54762
55058
  function suppressedNativeKeys(oracle) {
54763
55059
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
54764
55060
  }
@@ -54938,11 +55234,11 @@ function assembleLedger(r, options = {}) {
54938
55234
  return out2;
54939
55235
  }
54940
55236
  function trendAndStore(dir, entries, suppressed) {
54941
- const p = join55(dir, LEDGER_FILE);
55237
+ const p = join56(dir, LEDGER_FILE);
54942
55238
  let previous = null;
54943
55239
  try {
54944
- if (existsSync56(p)) {
54945
- const parsed = JSON.parse(readFileSync62(p, "utf8"));
55240
+ if (existsSync57(p)) {
55241
+ const parsed = JSON.parse(readFileSync63(p, "utf8"));
54946
55242
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
54947
55243
  }
54948
55244
  } catch {
@@ -54950,8 +55246,8 @@ function trendAndStore(dir, entries, suppressed) {
54950
55246
  const current = entries.map((e) => e.key);
54951
55247
  const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
54952
55248
  try {
54953
- mkdirSync26(dirname30(p), { recursive: true });
54954
- writeFileSync22(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55249
+ mkdirSync27(dirname31(p), { recursive: true });
55250
+ writeFileSync23(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
54955
55251
  } catch {
54956
55252
  return null;
54957
55253
  }
@@ -54981,11 +55277,11 @@ function formatLedger(entries, trend) {
54981
55277
  return out2.join("\n");
54982
55278
  }
54983
55279
  function diffAndStoreObservations(dir, current) {
54984
- const p = join55(dir, OBS_FILE);
55280
+ const p = join56(dir, OBS_FILE);
54985
55281
  let previous = null;
54986
55282
  try {
54987
- if (existsSync56(p)) {
54988
- const parsed = JSON.parse(readFileSync62(p, "utf8"));
55283
+ if (existsSync57(p)) {
55284
+ const parsed = JSON.parse(readFileSync63(p, "utf8"));
54989
55285
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
54990
55286
  (v) => Array.isArray(v) && v.every((l) => typeof l === "string")
54991
55287
  )) {
@@ -54995,8 +55291,8 @@ function diffAndStoreObservations(dir, current) {
54995
55291
  } catch {
54996
55292
  }
54997
55293
  try {
54998
- mkdirSync26(dirname30(p), { recursive: true });
54999
- writeFileSync22(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55294
+ mkdirSync27(dirname31(p), { recursive: true });
55295
+ writeFileSync23(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55000
55296
  } catch {
55001
55297
  return null;
55002
55298
  }
@@ -55034,8 +55330,8 @@ var LEDGER_FILE, OBS_FILE;
55034
55330
  var init_coverage = __esm({
55035
55331
  "src/coverage.ts"() {
55036
55332
  init_native_decode();
55037
- LEDGER_FILE = join55(".himi", "test-ledger.json");
55038
- OBS_FILE = join55(".himi", "test-observations.json");
55333
+ LEDGER_FILE = join56(".himi", "test-ledger.json");
55334
+ OBS_FILE = join56(".himi", "test-observations.json");
55039
55335
  }
55040
55336
  });
55041
55337
 
@@ -55046,16 +55342,16 @@ __export(design_kits_exports, {
55046
55342
  kitsDir: () => kitsDir,
55047
55343
  listKits: () => listKits2
55048
55344
  });
55049
- import { existsSync as existsSync57, readFileSync as readFileSync63, readdirSync as readdirSync28 } from "node:fs";
55050
- import { join as join56, basename as basename15 } from "node:path";
55345
+ import { existsSync as existsSync58, readFileSync as readFileSync64, readdirSync as readdirSync29 } from "node:fs";
55346
+ import { join as join57, basename as basename15 } from "node:path";
55051
55347
  import { fileURLToPath as fileURLToPath23 } from "node:url";
55052
55348
  function kitsDir() {
55053
- return KIT_DIR_CANDIDATES.find((p) => existsSync57(p));
55349
+ return KIT_DIR_CANDIDATES.find((p) => existsSync58(p));
55054
55350
  }
55055
55351
  function listKits2() {
55056
55352
  const dir = kitsDir();
55057
55353
  if (!dir) return [];
55058
- return readdirSync28(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
55354
+ return readdirSync29(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
55059
55355
  }
55060
55356
  function kitReport(name) {
55061
55357
  const dir = kitsDir();
@@ -55074,7 +55370,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
55074
55370
  if (!kits.includes(name)) {
55075
55371
  return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
55076
55372
  }
55077
- const raw = readFileSync63(join56(dir, `${name}.json`), "utf8");
55373
+ const raw = readFileSync64(join57(dir, `${name}.json`), "utf8");
55078
55374
  let parsed;
55079
55375
  try {
55080
55376
  parsed = JSON.parse(raw);
@@ -55098,9 +55394,9 @@ var init_design_kits = __esm({
55098
55394
  "src/design-kits.ts"() {
55099
55395
  KIT_DIR_CANDIDATES = [
55100
55396
  // in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
55101
- join56(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
55397
+ join57(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
55102
55398
  // published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
55103
- join56(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
55399
+ join57(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
55104
55400
  ];
55105
55401
  }
55106
55402
  });
@@ -55114,11 +55410,11 @@ __export(assets_exports, {
55114
55410
  removeAssetPayload: () => removeAssetPayload,
55115
55411
  verifyReport: () => verifyReport
55116
55412
  });
55117
- import { readFileSync as readFileSync64 } from "node:fs";
55413
+ import { readFileSync as readFileSync65 } from "node:fs";
55118
55414
  import { basename as basename16 } from "node:path";
55119
55415
  function declaredAssets(dir) {
55120
55416
  return collectAssets(dir).map((a) => {
55121
- const bytes2 = readFileSync64(a.path);
55417
+ const bytes2 = readFileSync65(a.path);
55122
55418
  return {
55123
55419
  name: a.name,
55124
55420
  sha256: assetSha256(bytes2),
@@ -55195,7 +55491,7 @@ function verifyReport(dir, app, manifest) {
55195
55491
  };
55196
55492
  }
55197
55493
  function addAssetPayload(manifest, filePath, opts) {
55198
- const bytes2 = readFileSync64(filePath);
55494
+ const bytes2 = readFileSync65(filePath);
55199
55495
  const name = opts.name ?? basename16(filePath);
55200
55496
  const sha2565 = assetSha256(bytes2);
55201
55497
  const record2 = {
@@ -56919,9 +57215,9 @@ __export(run_exports, {
56919
57215
  runPackage: () => runPackage,
56920
57216
  withoutProdServe: () => withoutProdServe
56921
57217
  });
56922
- import { cpSync as cpSync2, existsSync as existsSync58, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync3, readFileSync as readFileSync65, rmSync as rmSync13, statSync as statSync14 } from "node:fs";
57218
+ import { cpSync as cpSync2, existsSync as existsSync59, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, readFileSync as readFileSync66, rmSync as rmSync14, statSync as statSync15 } from "node:fs";
56923
57219
  import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
56924
- import { dirname as dirname31, join as join57 } from "node:path";
57220
+ import { dirname as dirname32, join as join58 } from "node:path";
56925
57221
  import { fileURLToPath as fileURLToPath24 } from "node:url";
56926
57222
  function makePackageRunHandler(opts) {
56927
57223
  const store = new FileReleaseStore(opts.releaseRoot);
@@ -56949,9 +57245,9 @@ async function fetchBytes(url) {
56949
57245
  }
56950
57246
  async function resolvePackage(source, workDir) {
56951
57247
  const isUrl2 = /^https?:\/\//i.test(source);
56952
- if (!isUrl2 && existsSync58(source) && statSync14(source).isDirectory()) {
56953
- const appDirManifest = join57(source, "release-manifest.json");
56954
- if (existsSync58(appDirManifest)) {
57248
+ if (!isUrl2 && existsSync59(source) && statSync15(source).isDirectory()) {
57249
+ const appDirManifest = join58(source, "release-manifest.json");
57250
+ if (existsSync59(appDirManifest)) {
56955
57251
  const opened2 = openPackageDir(source);
56956
57252
  if (!opened2.validation.ok) {
56957
57253
  throw new Error(`package is not valid:
@@ -56960,11 +57256,11 @@ async function resolvePackage(source, workDir) {
56960
57256
  const app2 = opened2.header?.app ?? opened2.manifest?.app;
56961
57257
  if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
56962
57258
  if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
56963
- const root2 = workDir ?? mkdtempSync3(join57(tmpdir4(), "himi-run-"));
56964
- const target = join57(root2, app2);
56965
- if (join57(source) !== target) {
56966
- mkdirSync27(root2, { recursive: true });
56967
- rmSync13(target, { recursive: true, force: true });
57259
+ const root2 = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
57260
+ const target = join58(root2, app2);
57261
+ if (join58(source) !== target) {
57262
+ mkdirSync28(root2, { recursive: true });
57263
+ rmSync14(target, { recursive: true, force: true });
56968
57264
  cpSync2(source, target, { recursive: true });
56969
57265
  }
56970
57266
  return {
@@ -56979,12 +57275,12 @@ async function resolvePackage(source, workDir) {
56979
57275
  }
56980
57276
  throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
56981
57277
  }
56982
- const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync65(source);
56983
- const root = workDir ?? mkdtempSync3(join57(tmpdir4(), "himi-run-"));
57278
+ const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync66(source);
57279
+ const root = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
56984
57280
  const { app, appDir: appDir3 } = unpackTo(bytes2, root);
56985
57281
  const opened = openPackageDir(appDir3);
56986
57282
  if (!opened.validation.ok) {
56987
- rmSync13(workDir ? appDir3 : root, { recursive: true, force: true });
57283
+ rmSync14(workDir ? appDir3 : root, { recursive: true, force: true });
56988
57284
  throw new Error(`package is not valid:
56989
57285
  ${opened.validation.errors.join("\n ")}`);
56990
57286
  }
@@ -57001,16 +57297,16 @@ async function resolvePackage(source, workDir) {
57001
57297
  async function loadPreviewAssets() {
57002
57298
  try {
57003
57299
  const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
57004
- const here = dirname31(fileURLToPath24(import.meta.url));
57300
+ const here = dirname32(fileURLToPath24(import.meta.url));
57005
57301
  const candidates = [
57006
- join57(here, "preview-assets.generated.bin"),
57302
+ join58(here, "preview-assets.generated.bin"),
57007
57303
  // published: copied next to the bundled CLI
57008
- join57(here, "../../../packages/serve/src/preview-assets.generated.bin")
57304
+ join58(here, "../../../packages/serve/src/preview-assets.generated.bin")
57009
57305
  // in-repo checkout
57010
57306
  ];
57011
57307
  for (const path2 of candidates) {
57012
- if (!existsSync58(path2)) continue;
57013
- const blob = readFileSync65(path2);
57308
+ if (!existsSync59(path2)) continue;
57309
+ const blob = readFileSync66(path2);
57014
57310
  return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
57015
57311
  }
57016
57312
  return /* @__PURE__ */ new Map();
@@ -57058,7 +57354,7 @@ async function runPackage(source, opts = {}) {
57058
57354
  const resolved2 = await resolvePackage(source, opts.workDir);
57059
57355
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
57060
57356
  if (!opts.spa && assets.size === 0) {
57061
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57357
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57062
57358
  throw new Error(NO_SPA_MESSAGE);
57063
57359
  }
57064
57360
  const plane = makePackageRunHandler({
@@ -57096,7 +57392,7 @@ async function runPackage(source, opts = {}) {
57096
57392
  lanBound = (await listen(lanServer, port, lanHost)).address;
57097
57393
  } catch (e) {
57098
57394
  await closeServer(server);
57099
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57395
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57100
57396
  throw new Error(`himi run --lan could not listen on ${lanHost}:${port} (${e.message}); drop --lan, or pass --port for a free one`);
57101
57397
  }
57102
57398
  bound.push(lanBound);
@@ -57118,7 +57414,7 @@ async function runPackage(source, opts = {}) {
57118
57414
  warnings: resolved2.warnings,
57119
57415
  close: async () => {
57120
57416
  await Promise.all(servers.map(closeServer));
57121
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57417
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57122
57418
  }
57123
57419
  };
57124
57420
  }
@@ -57157,9 +57453,9 @@ __export(run_watch_exports, {
57157
57453
  watchedContentDir: () => watchedContentDir,
57158
57454
  writeRunRecord: () => writeRunRecord
57159
57455
  });
57160
- import { closeSync as closeSync4, constants, existsSync as existsSync59, fstatSync, lstatSync as lstatSync12, statSync as statSync15, mkdirSync as mkdirSync28, openSync as openSync3, readFileSync as readFileSync66, realpathSync as realpathSync8, renameSync as renameSync6, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
57456
+ import { closeSync as closeSync4, constants, existsSync as existsSync60, fstatSync, lstatSync as lstatSync13, statSync as statSync16, mkdirSync as mkdirSync29, openSync as openSync3, readFileSync as readFileSync67, realpathSync as realpathSync9, renameSync as renameSync6, rmSync as rmSync15, writeFileSync as writeFileSync24, watch as fsWatch } from "node:fs";
57161
57457
  import { randomUUID as randomUUID4 } from "node:crypto";
57162
- import { extname as extname4, join as join58, resolve as resolve46, sep as sep15 } from "node:path";
57458
+ import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
57163
57459
  function diffReleases(prev, next) {
57164
57460
  const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
57165
57461
  const changedBundles = new Set(bundles);
@@ -57200,7 +57496,7 @@ function watchContent(dir, onChange, opts = {}) {
57200
57496
  let timer = null;
57201
57497
  const pending = /* @__PURE__ */ new Set();
57202
57498
  const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
57203
- if (!file || ignoredChange(file, (rel) => isDir(join58(dir, rel)))) return;
57499
+ if (!file || ignoredChange(file, (rel) => isDir(join59(dir, rel)))) return;
57204
57500
  pending.add(file);
57205
57501
  if (timer) clearTimeout(timer);
57206
57502
  timer = setTimeout(() => {
@@ -57219,9 +57515,9 @@ function watchContent(dir, onChange, opts = {}) {
57219
57515
  }
57220
57516
  function watchedContentDir(source) {
57221
57517
  if (!source || /^https?:\/\//i.test(source)) return null;
57222
- const dir = resolve46(source);
57518
+ const dir = resolve47(source);
57223
57519
  try {
57224
- return statSync15(dir).isDirectory() && existsSync59(join58(dir, "himalaya.content.json")) ? dir : null;
57520
+ return statSync16(dir).isDirectory() && existsSync60(join59(dir, "himalaya.content.json")) ? dir : null;
57225
57521
  } catch {
57226
57522
  return null;
57227
57523
  }
@@ -57278,33 +57574,33 @@ function serialize(task) {
57278
57574
  });
57279
57575
  }
57280
57576
  function himiDir(dir) {
57281
- const root = join58(dir, ".himi");
57577
+ const root = join59(dir, ".himi");
57282
57578
  try {
57283
- return lstatSync12(root).isDirectory() ? root : null;
57579
+ return lstatSync13(root).isDirectory() ? root : null;
57284
57580
  } catch (e) {
57285
57581
  if (e.code !== "ENOENT") return null;
57286
- mkdirSync28(root, { recursive: true });
57287
- return lstatSync12(root).isDirectory() ? root : null;
57582
+ mkdirSync29(root, { recursive: true });
57583
+ return lstatSync13(root).isDirectory() ? root : null;
57288
57584
  }
57289
57585
  }
57290
57586
  function writeRunRecord(dir, record2) {
57291
57587
  const root = himiDir(dir);
57292
57588
  if (!root) return false;
57293
- const tmp = join58(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
57589
+ const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
57294
57590
  try {
57295
- writeFileSync23(tmp, `${JSON.stringify(record2, null, 2)}
57591
+ writeFileSync24(tmp, `${JSON.stringify(record2, null, 2)}
57296
57592
  `, { flag: "wx" });
57297
- renameSync6(tmp, join58(root, "run.json"));
57593
+ renameSync6(tmp, join59(root, "run.json"));
57298
57594
  } catch (e) {
57299
- rmSync14(tmp, { force: true });
57595
+ rmSync15(tmp, { force: true });
57300
57596
  throw e;
57301
57597
  }
57302
57598
  return true;
57303
57599
  }
57304
57600
  function removeRunRecord(dir, owner) {
57305
- const root = join58(dir, ".himi");
57601
+ const root = join59(dir, ".himi");
57306
57602
  try {
57307
- if (!lstatSync12(root).isDirectory()) return;
57603
+ if (!lstatSync13(root).isDirectory()) return;
57308
57604
  } catch {
57309
57605
  return;
57310
57606
  }
@@ -57317,22 +57613,22 @@ function removeRunRecord(dir, owner) {
57317
57613
  }
57318
57614
  if (typeof pid === "number" && pid !== owner) return;
57319
57615
  }
57320
- rmSync14(join58(root, "run.json"), { force: true });
57616
+ rmSync15(join59(root, "run.json"), { force: true });
57321
57617
  }
57322
57618
  function boardFile(dir, pathname) {
57323
57619
  if (pathname === RUN_IDENTITY_PATH) {
57324
57620
  return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
57325
57621
  }
57326
57622
  let rel = null;
57327
- if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join58("studio", "index.html");
57328
- else if (pathname === "/__himi/studio/state.js") rel = join58("studio", "state.js");
57329
- else if (pathname === "/__himi/studio/timeline.js") rel = join58("studio", "timeline.js");
57623
+ if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join59("studio", "index.html");
57624
+ else if (pathname === "/__himi/studio/state.js") rel = join59("studio", "state.js");
57625
+ else if (pathname === "/__himi/studio/timeline.js") rel = join59("studio", "timeline.js");
57330
57626
  else {
57331
57627
  const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
57332
- if (m) rel = join58("history", m[1]);
57628
+ if (m) rel = join59("history", m[1]);
57333
57629
  }
57334
57630
  if (!rel) return null;
57335
- const bytes2 = readConfined(resolve46(dir, ".himi"), rel);
57631
+ const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
57336
57632
  if (!bytes2) return new Response("not found", { status: 404 });
57337
57633
  return new Response(bytes2, {
57338
57634
  status: 200,
@@ -57341,20 +57637,20 @@ function boardFile(dir, pathname) {
57341
57637
  }
57342
57638
  function readConfined(root, rel) {
57343
57639
  try {
57344
- if (!lstatSync12(root).isDirectory()) return null;
57345
- const parts = rel.split(sep15);
57640
+ if (!lstatSync13(root).isDirectory()) return null;
57641
+ const parts = rel.split(sep16);
57346
57642
  let at2 = root;
57347
57643
  for (let i = 0; i < parts.length; i++) {
57348
- at2 = join58(at2, parts[i]);
57349
- const st = lstatSync12(at2);
57644
+ at2 = join59(at2, parts[i]);
57645
+ const st = lstatSync13(at2);
57350
57646
  if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
57351
57647
  }
57352
- const canonicalRoot = realpathSync8(root);
57353
- if (!realpathSync8(at2).startsWith(canonicalRoot + sep15)) return null;
57648
+ const canonicalRoot = realpathSync9(root);
57649
+ if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
57354
57650
  const fd = openSync3(at2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
57355
57651
  try {
57356
57652
  if (!fstatSync(fd).isFile()) return null;
57357
- return readFileSync66(fd);
57653
+ return readFileSync67(fd);
57358
57654
  } finally {
57359
57655
  closeSync4(fd);
57360
57656
  }
@@ -57383,7 +57679,7 @@ var init_run_watch = __esm({
57383
57679
  };
57384
57680
  isDir = (path2) => {
57385
57681
  try {
57386
- return statSync15(path2).isDirectory();
57682
+ return statSync16(path2).isDirectory();
57387
57683
  } catch {
57388
57684
  return false;
57389
57685
  }
@@ -57407,19 +57703,19 @@ __export(run_browser_exports, {
57407
57703
  runInBrowser: () => runInBrowser
57408
57704
  });
57409
57705
  import { createServer as createServer7 } from "node:http";
57410
- import { existsSync as existsSync60, readFileSync as readFileSync67 } from "node:fs";
57706
+ import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
57411
57707
  import { spawnSync as spawnSync3 } from "node:child_process";
57412
- import { dirname as dirname32, resolve as resolve47 } from "node:path";
57708
+ import { dirname as dirname33, resolve as resolve48 } from "node:path";
57413
57709
  import { fileURLToPath as fileURLToPath25 } from "node:url";
57414
57710
  function stagedDir() {
57415
- return process.env.HIMI_BROWSER_PLANE_OUT ? resolve47(process.env.HIMI_BROWSER_PLANE_OUT) : resolve47(REPO, "packages", "serve", "dist", "browser-plane");
57711
+ return process.env.HIMI_BROWSER_PLANE_OUT ? resolve48(process.env.HIMI_BROWSER_PLANE_OUT) : resolve48(REPO, "packages", "serve", "dist", "browser-plane");
57416
57712
  }
57417
57713
  function missingStaged() {
57418
- return [...SERVED].filter((f) => !existsSync60(resolve47(stagedDir(), f))).sort();
57714
+ return [...SERVED].filter((f) => !existsSync61(resolve48(stagedDir(), f))).sort();
57419
57715
  }
57420
57716
  function ensureBrowserPlaneStaged() {
57421
57717
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
57422
- const r = spawnSync3(process.execPath, [resolve47(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
57718
+ const r = spawnSync3(process.execPath, [resolve48(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
57423
57719
  cwd: REPO,
57424
57720
  encoding: "utf8"
57425
57721
  });
@@ -57505,7 +57801,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
57505
57801
  }
57506
57802
  const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
57507
57803
  if (SERVED.has(name)) {
57508
- if (!existsSync60(resolve47(stagedDir(), name))) {
57804
+ if (!existsSync61(resolve48(stagedDir(), name))) {
57509
57805
  const restaged = ensureBrowserPlaneStaged();
57510
57806
  if (!restaged.ok) {
57511
57807
  res.writeHead(503, { "content-type": "application/json" });
@@ -57515,7 +57811,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
57515
57811
  }
57516
57812
  let bytes2;
57517
57813
  try {
57518
- bytes2 = readFileSync67(resolve47(stagedDir(), name));
57814
+ bytes2 = readFileSync68(resolve48(stagedDir(), name));
57519
57815
  } catch (e) {
57520
57816
  res.writeHead(503, { "content-type": "application/json" });
57521
57817
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
@@ -57557,8 +57853,8 @@ var init_run_browser = __esm({
57557
57853
  init_open_url();
57558
57854
  init_file_store();
57559
57855
  init_wix_client_id();
57560
- HERE2 = dirname32(fileURLToPath25(import.meta.url));
57561
- REPO = resolve47(HERE2, "..", "..", "..");
57856
+ HERE2 = dirname33(fileURLToPath25(import.meta.url));
57857
+ REPO = resolve48(HERE2, "..", "..", "..");
57562
57858
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
57563
57859
  }
57564
57860
  });
@@ -57977,11 +58273,11 @@ __export(preflight_exports, {
57977
58273
  parseStoreConfig: () => parseStoreConfig,
57978
58274
  requireEnv: () => requireEnv
57979
58275
  });
57980
- import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
57981
- import { isAbsolute as isAbsolute5, relative as relative12, resolve as resolve48 } from "node:path";
58276
+ import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
58277
+ import { isAbsolute as isAbsolute6, relative as relative13, resolve as resolve49 } from "node:path";
57982
58278
  function isInsideRepo(p) {
57983
- const rel = relative12(REPO_ROOT3, resolve48(p));
57984
- return rel !== "" && !rel.startsWith("..") && !isAbsolute5(rel);
58279
+ const rel = relative13(REPO_ROOT3, resolve49(p));
58280
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute6(rel);
57985
58281
  }
57986
58282
  function assertCredentialOutsideRepo(label2, p) {
57987
58283
  if (isInsideRepo(p)) {
@@ -58034,10 +58330,10 @@ function parseStoreConfig(text8) {
58034
58330
  }
58035
58331
  function loadStoreConfig(app) {
58036
58332
  const p = storeConfigPath(app);
58037
- if (!existsSync61(p)) {
58333
+ if (!existsSync62(p)) {
58038
58334
  throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
58039
58335
  }
58040
- return parseStoreConfig(readFileSync68(p, "utf8"));
58336
+ return parseStoreConfig(readFileSync69(p, "utf8"));
58041
58337
  }
58042
58338
  var init_preflight = __esm({
58043
58339
  "../store-release/preflight.ts"() {
@@ -58056,19 +58352,19 @@ __export(credential_profile_exports, {
58056
58352
  profilePath: () => profilePath,
58057
58353
  resolveStoreCredentials: () => resolveStoreCredentials
58058
58354
  });
58059
- import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
58355
+ import { existsSync as existsSync63, readFileSync as readFileSync70 } from "node:fs";
58060
58356
  import { homedir as homedir5 } from "node:os";
58061
- import { join as join59 } from "node:path";
58357
+ import { join as join60 } from "node:path";
58062
58358
  function credentialsDir(home = homedir5()) {
58063
- return join59(home, ".himalaya", "store-credentials");
58359
+ return join60(home, ".himalaya", "store-credentials");
58064
58360
  }
58065
58361
  function profilePath(name, home = homedir5()) {
58066
58362
  if (!PROFILE_NAME.test(name)) {
58067
58363
  throw new Error(
58068
- `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join59(credentialsDir(home), "<name>.json")}; it is never a path.`
58364
+ `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join60(credentialsDir(home), "<name>.json")}; it is never a path.`
58069
58365
  );
58070
58366
  }
58071
- return join59(credentialsDir(home), `${name}.json`);
58367
+ return join60(credentialsDir(home), `${name}.json`);
58072
58368
  }
58073
58369
  function parseProfile(text8, label2) {
58074
58370
  let doc;
@@ -58099,8 +58395,8 @@ function resolveStoreCredentials(opts) {
58099
58395
  const { app, cfg } = opts;
58100
58396
  const env = opts.env ?? process.env;
58101
58397
  const home = opts.home ?? homedir5();
58102
- const read = opts.readProfile ?? ((p) => readFileSync69(p, "utf8"));
58103
- const exists = opts.profileExists ?? existsSync62;
58398
+ const read = opts.readProfile ?? ((p) => readFileSync70(p, "utf8"));
58399
+ const exists = opts.profileExists ?? existsSync63;
58104
58400
  const ios = cfg.ios ?? {};
58105
58401
  const flagName = opts.profileFlag?.trim();
58106
58402
  const named = namedProfile(cfg, opts.profileFlag);
@@ -58180,9 +58476,9 @@ __export(preflight_app_exports, {
58180
58476
  preflightApp: () => preflightApp,
58181
58477
  profileAccount: () => profileAccount
58182
58478
  });
58183
- import { readFileSync as readFileSync70, existsSync as existsSync63, readdirSync as readdirSync29, statSync as statSync16 } from "node:fs";
58479
+ import { readFileSync as readFileSync71, existsSync as existsSync64, readdirSync as readdirSync30, statSync as statSync17 } from "node:fs";
58184
58480
  import { createHash as createHash30 } from "node:crypto";
58185
- import { join as join60 } from "node:path";
58481
+ import { join as join61 } from "node:path";
58186
58482
  function analyze(projectYml, storeConfig, icon, account) {
58187
58483
  const f = [];
58188
58484
  const has = (re, s) => re.test(s);
@@ -58246,13 +58542,13 @@ function profileAccount(app, storeConfig, opts = {}) {
58246
58542
  }
58247
58543
  }
58248
58544
  async function preflightApp(app, opts = {}) {
58249
- const projectYml = existsSync63(iosProjectYml(app)) ? readFileSync70(iosProjectYml(app), "utf8") : "";
58250
- const storeConfig = existsSync63(storeConfigPath(app)) ? readFileSync70(storeConfigPath(app), "utf8") : "";
58545
+ const projectYml = existsSync64(iosProjectYml(app)) ? readFileSync71(iosProjectYml(app), "utf8") : "";
58546
+ const storeConfig = existsSync64(storeConfigPath(app)) ? readFileSync71(storeConfigPath(app), "utf8") : "";
58251
58547
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
58252
58548
  const findings = analyze(
58253
58549
  projectYml,
58254
58550
  storeConfig,
58255
- await appIconState(join60(appDir(app), "ios")),
58551
+ await appIconState(join61(appDir(app), "ios")),
58256
58552
  profileAccount(app, storeConfig, opts)
58257
58553
  );
58258
58554
  findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
@@ -58281,18 +58577,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
58281
58577
  return f;
58282
58578
  }
58283
58579
  function appLevelMetadataFiles(app, locale = "en-US") {
58284
- const root = join60(storeDir(app), "metadata");
58580
+ const root = join61(storeDir(app), "metadata");
58285
58581
  const out2 = /* @__PURE__ */ new Set();
58286
- if (existsSync63(root)) {
58287
- for (const n of readdirSync29(root)) if (n.endsWith(".txt")) out2.add(n);
58582
+ if (existsSync64(root)) {
58583
+ for (const n of readdirSync30(root)) if (n.endsWith(".txt")) out2.add(n);
58288
58584
  }
58289
- if (existsSync63(join60(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
58585
+ if (existsSync64(join61(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
58290
58586
  return out2;
58291
58587
  }
58292
58588
  function reviewInfoFiles(app) {
58293
- const dir = join60(storeDir(app), "review_information");
58294
- if (!existsSync63(dir)) return /* @__PURE__ */ new Set();
58295
- return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
58589
+ const dir = join61(storeDir(app), "review_information");
58590
+ if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
58591
+ return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
58296
58592
  }
58297
58593
  function isValidAppStoreSize(w, h) {
58298
58594
  return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
@@ -58401,12 +58697,12 @@ function analyzePlayListing(assets) {
58401
58697
  return f;
58402
58698
  }
58403
58699
  function playListingAssets(app, locale = "en-US") {
58404
- const dir = join60(storeDir(app), "play", locale, "images");
58700
+ const dir = join61(storeDir(app), "play", locale, "images");
58405
58701
  const read = (names) => {
58406
58702
  for (const name of names) {
58407
- const p = join60(dir, name);
58703
+ const p = join61(dir, name);
58408
58704
  try {
58409
- if (statSync16(p).isFile()) return { name, bytes: readFileSync70(p) };
58705
+ if (statSync17(p).isFile()) return { name, bytes: readFileSync71(p) };
58410
58706
  } catch {
58411
58707
  }
58412
58708
  }
@@ -58437,26 +58733,26 @@ function analyzeListing(metaFiles, shots) {
58437
58733
  return f;
58438
58734
  }
58439
58735
  function metadataFilesPresent(app, locale = "en-US") {
58440
- const dir = join60(storeDir(app), "metadata", locale);
58441
- if (!existsSync63(dir)) return /* @__PURE__ */ new Set();
58442
- return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
58736
+ const dir = join61(storeDir(app), "metadata", locale);
58737
+ if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
58738
+ return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
58443
58739
  }
58444
58740
  function listScreenshots(app, locale = "en-US") {
58445
58741
  const out2 = [];
58446
- const flat = join60(storeDir(app), "screenshots", locale);
58447
- if (existsSync63(flat)) {
58448
- for (const png of readdirSync29(flat).filter((n) => n.endsWith(".png"))) {
58449
- const sz = pngSize(readFileSync70(join60(flat, png)));
58742
+ const flat = join61(storeDir(app), "screenshots", locale);
58743
+ if (existsSync64(flat)) {
58744
+ for (const png of readdirSync30(flat).filter((n) => n.endsWith(".png"))) {
58745
+ const sz = pngSize(readFileSync71(join61(flat, png)));
58450
58746
  if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
58451
58747
  }
58452
58748
  }
58453
- const legacy = join60(storeDir(app), "metadata", locale, "screenshots");
58454
- if (existsSync63(legacy)) {
58455
- for (const deviceDir of readdirSync29(legacy)) {
58456
- const d = join60(legacy, deviceDir);
58457
- if (!statSync16(d).isDirectory()) continue;
58458
- for (const png of readdirSync29(d).filter((n) => n.endsWith(".png"))) {
58459
- const sz = pngSize(readFileSync70(join60(d, png)));
58749
+ const legacy = join61(storeDir(app), "metadata", locale, "screenshots");
58750
+ if (existsSync64(legacy)) {
58751
+ for (const deviceDir of readdirSync30(legacy)) {
58752
+ const d = join61(legacy, deviceDir);
58753
+ if (!statSync17(d).isDirectory()) continue;
58754
+ for (const png of readdirSync30(d).filter((n) => n.endsWith(".png"))) {
58755
+ const sz = pngSize(readFileSync71(join61(d, png)));
58460
58756
  if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
58461
58757
  }
58462
58758
  }
@@ -58464,13 +58760,13 @@ function listScreenshots(app, locale = "en-US") {
58464
58760
  return out2;
58465
58761
  }
58466
58762
  function placeholderHashes2() {
58467
- const templateIos = join60(appDir("_template"), "ios");
58468
- if (!existsSync63(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
58469
- for (const target of readdirSync29(templateIos)) {
58470
- const p = join60(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58763
+ const templateIos = join61(appDir("_template"), "ios");
58764
+ if (!existsSync64(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
58765
+ for (const target of readdirSync30(templateIos)) {
58766
+ const p = join61(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58471
58767
  try {
58472
- if (!statSync16(p).isFile()) continue;
58473
- return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync70(p)).digest("hex")];
58768
+ if (!statSync17(p).isFile()) continue;
58769
+ return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync71(p)).digest("hex")];
58474
58770
  } catch {
58475
58771
  }
58476
58772
  }
@@ -58501,12 +58797,12 @@ async function pixelIssues(bytes2) {
58501
58797
  }
58502
58798
  }
58503
58799
  async function appIconState(iosDir) {
58504
- if (!existsSync63(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
58505
- for (const target of readdirSync29(iosDir)) {
58506
- const p = join60(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58800
+ if (!existsSync64(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
58801
+ for (const target of readdirSync30(iosDir)) {
58802
+ const p = join61(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58507
58803
  try {
58508
- if (!statSync16(p).isFile()) continue;
58509
- const bytes2 = readFileSync70(p);
58804
+ if (!statSync17(p).isFile()) continue;
58805
+ const bytes2 = readFileSync71(p);
58510
58806
  const hash = createHash30("sha256").update(bytes2).digest("hex");
58511
58807
  const pixels = await pixelIssues(bytes2);
58512
58808
  return {
@@ -58578,7 +58874,7 @@ __export(version_exports, {
58578
58874
  setAndroidVersion: () => setAndroidVersion,
58579
58875
  setIosVersion: () => setIosVersion
58580
58876
  });
58581
- import { readFileSync as readFileSync71, writeFileSync as writeFileSync24 } from "node:fs";
58877
+ import { readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
58582
58878
  function readIosVersion(projectYml) {
58583
58879
  const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
58584
58880
  const build2 = matchScalar(projectYml, "CFBundleVersion");
@@ -58636,15 +58932,15 @@ function setAndroidVersion(gradle, v) {
58636
58932
  function bumpVersion(app, opts) {
58637
58933
  const iosPath = iosProjectYml(app);
58638
58934
  const gradlePath = androidGradle(app);
58639
- const iosYml = readFileSync71(iosPath, "utf8");
58640
- const gradle = readFileSync71(gradlePath, "utf8");
58935
+ const iosYml = readFileSync72(iosPath, "utf8");
58936
+ const gradle = readFileSync72(gradlePath, "utf8");
58641
58937
  const current = readIosVersion(iosYml);
58642
58938
  const next = {
58643
58939
  marketing: opts.marketing ?? current.marketing,
58644
58940
  build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
58645
58941
  };
58646
- writeFileSync24(iosPath, setIosVersion(iosYml, next));
58647
- writeFileSync24(gradlePath, setAndroidVersion(gradle, next));
58942
+ writeFileSync25(iosPath, setIosVersion(iosYml, next));
58943
+ writeFileSync25(gradlePath, setAndroidVersion(gradle, next));
58648
58944
  return next;
58649
58945
  }
58650
58946
  var init_version = __esm({
@@ -58654,7 +58950,7 @@ var init_version = __esm({
58654
58950
  });
58655
58951
 
58656
58952
  // ../store-release/register-bundle.ts
58657
- import { readFileSync as readFileSync72 } from "node:fs";
58953
+ import { readFileSync as readFileSync73 } from "node:fs";
58658
58954
  import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
58659
58955
  function b64url2(b) {
58660
58956
  return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -58672,7 +58968,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
58672
58968
  async function registerBundleId(opts) {
58673
58969
  const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
58674
58970
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
58675
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync72(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58971
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58676
58972
  const res = await fetch(`${ASC_API}/v1/bundleIds`, {
58677
58973
  method: "POST",
58678
58974
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
@@ -58726,7 +59022,7 @@ __export(asc_status_exports, {
58726
59022
  ascStatus: () => ascStatus,
58727
59023
  buildVerdict: () => buildVerdict
58728
59024
  });
58729
- import { readFileSync as readFileSync73 } from "node:fs";
59025
+ import { readFileSync as readFileSync74 } from "node:fs";
58730
59026
  function buildVerdict(builds) {
58731
59027
  if (!builds.length) {
58732
59028
  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).";
@@ -58740,7 +59036,7 @@ function buildVerdict(builds) {
58740
59036
  function client(creds) {
58741
59037
  const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
58742
59038
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
58743
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
59039
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync74(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58744
59040
  return async (path2) => {
58745
59041
  const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
58746
59042
  return { status: r.status, json: await r.json().catch(() => ({})) };
@@ -58789,7 +59085,7 @@ var init_asc_status = __esm({
58789
59085
  // ../../core/functions-secrets/src/vault.ts
58790
59086
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
58791
59087
  import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
58792
- import { dirname as dirname33 } from "node:path";
59088
+ import { dirname as dirname34 } from "node:path";
58793
59089
  function createJsonSecretStore(filePath) {
58794
59090
  const read = async () => {
58795
59091
  try {
@@ -58802,7 +59098,7 @@ function createJsonSecretStore(filePath) {
58802
59098
  }
58803
59099
  };
58804
59100
  const write2 = async (records) => {
58805
- await mkdir(dirname33(filePath), { recursive: true });
59101
+ await mkdir(dirname34(filePath), { recursive: true });
58806
59102
  const temporary = `${filePath}.${process.pid}.tmp`;
58807
59103
  await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
58808
59104
  `, { mode: 384 });
@@ -58900,7 +59196,7 @@ __export(secrets_exports, {
58900
59196
  runRemoteSecretsCommand: () => runRemoteSecretsCommand,
58901
59197
  runSecretsCommand: () => runSecretsCommand
58902
59198
  });
58903
- import { readFileSync as readFileSync74 } from "node:fs";
59199
+ import { readFileSync as readFileSync75 } from "node:fs";
58904
59200
  function environment(value) {
58905
59201
  if (value === "preview" || value === "production") return value;
58906
59202
  throw new Error("--environment must be preview or production");
@@ -58931,7 +59227,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
58931
59227
  io.log(JSON.stringify(await vault.list({ app, environment: env })));
58932
59228
  return 0;
58933
59229
  }
58934
- const value = options.readValue ? options.readValue() : readFileSync74(0, "utf8").replace(/\r?\n$/, "");
59230
+ const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
58935
59231
  if (operation === "set") await vault.set({ app, environment: env, name, value });
58936
59232
  else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
58937
59233
  else throw new Error(`unknown secrets operation ${operation}`);
@@ -58960,7 +59256,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
58960
59256
  }
58961
59257
  let body;
58962
59258
  if (operation !== "list") {
58963
- const value = options.readValue ? options.readValue() : readFileSync74(0, "utf8").replace(/\r?\n$/, "");
59259
+ const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
58964
59260
  body = JSON.stringify({ value });
58965
59261
  }
58966
59262
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
@@ -59097,29 +59393,29 @@ __export(notify_ping_exports, {
59097
59393
  runNotifyPing: () => runNotifyPing
59098
59394
  });
59099
59395
  import { randomUUID as randomUUID5 } from "node:crypto";
59100
- import { resolve as resolve49 } from "node:path";
59101
- function refuse4(io, error, hint, exit = 2, extra = {}) {
59396
+ import { resolve as resolve50 } from "node:path";
59397
+ function refuse5(io, error, hint, exit = 2, extra = {}) {
59102
59398
  io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
59103
59399
  return exit;
59104
59400
  }
59105
59401
  async function runNotifyPing(flags, io, deps = {}) {
59106
59402
  const flagError = flagRefusal(flags);
59107
- if (flagError) return refuse4(io, flagError);
59108
- const input = mergePushInputs(pushInputsFromContent(resolve49(text7(flags.content) ?? process.cwd())), flags);
59403
+ if (flagError) return refuse5(io, flagError);
59404
+ const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
59109
59405
  const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
59110
- if (missing.length) return refuse4(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
59406
+ if (missing.length) return refuse5(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
59111
59407
  const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
59112
- if (!UUID_RE.test(requestId2)) return refuse4(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59408
+ if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59113
59409
  const owner = await hostedOwnerSession(flags, deps);
59114
- if (!owner.ok) return refuse4(io, owner.error, owner.hint, owner.exit);
59410
+ if (!owner.ok) return refuse5(io, owner.error, owner.hint, owner.exit);
59115
59411
  const { session } = owner;
59116
59412
  const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
59117
- if (ownership.state !== "owned") return refuse4(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59413
+ if (ownership.state !== "owned") return refuse5(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59118
59414
  let siteToken2;
59119
59415
  try {
59120
59416
  siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
59121
59417
  } catch {
59122
- return refuse4(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59418
+ return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59123
59419
  }
59124
59420
  const body = {
59125
59421
  app: ownership.slug,
@@ -59142,12 +59438,12 @@ function flagRefusal(flags) {
59142
59438
  function report2(http, sent, flags, io) {
59143
59439
  const code = refusalCode(http);
59144
59440
  if (code === "send_outcome_unknown") {
59145
- return refuse4(io, code, `Ping may have accepted it. Re-run the same command with --request-id ${sent.requestId}: Ping runs one request at most once per site for 24 hours.`, 1, { requestId: sent.requestId });
59441
+ return refuse5(io, code, `Ping may have accepted it. Re-run the same command with --request-id ${sent.requestId}: Ping runs one request at most once per site for 24 hours.`, 1, { requestId: sent.requestId });
59146
59442
  }
59147
59443
  if (code === "rate_limited" && http.retryAfterSec) {
59148
- return refuse4(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59444
+ return refuse5(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59149
59445
  }
59150
- if (code) return refuse4(io, code, HINTS[code], 1);
59446
+ if (code) return refuse5(io, code, HINTS[code], 1);
59151
59447
  if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
59152
59448
  else io.log(summary(http.body ?? {}, sent));
59153
59449
  return 0;
@@ -59207,15 +59503,15 @@ __export(notify_exports, {
59207
59503
  runNotify: () => runNotify,
59208
59504
  saveAdminSession: () => saveAdminSession
59209
59505
  });
59210
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync29, readFileSync as readFileSync75, writeFileSync as writeFileSync25 } from "node:fs";
59506
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync26 } from "node:fs";
59211
59507
  import { homedir as homedir6 } from "node:os";
59212
- import { dirname as dirname34, join as join61 } from "node:path";
59508
+ import { dirname as dirname35, join as join62 } from "node:path";
59213
59509
  function defaultSessionsPath() {
59214
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join61(homedir6(), ".himalaya", "admin-sessions.json");
59510
+ return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join62(homedir6(), ".himalaya", "admin-sessions.json");
59215
59511
  }
59216
59512
  function loadSessionsFile(path2 = defaultSessionsPath()) {
59217
59513
  try {
59218
- return JSON.parse(readFileSync75(path2, "utf8"));
59514
+ return JSON.parse(readFileSync76(path2, "utf8"));
59219
59515
  } catch {
59220
59516
  return {};
59221
59517
  }
@@ -59223,10 +59519,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
59223
59519
  function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
59224
59520
  const file = loadSessionsFile(path2);
59225
59521
  file.sessions = { ...file.sessions, [adminUrl]: session };
59226
- mkdirSync29(dirname34(path2), { recursive: true, mode: 448 });
59227
- writeFileSync25(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
59522
+ mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
59523
+ writeFileSync26(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
59228
59524
  try {
59229
- chmodSync3(dirname34(path2), 448);
59525
+ chmodSync3(dirname35(path2), 448);
59230
59526
  chmodSync3(path2, 384);
59231
59527
  } catch {
59232
59528
  }
@@ -61826,10 +62122,10 @@ function assertPublicSiteUrl(raw) {
61826
62122
  if (refusal) throw new Error(refusal);
61827
62123
  }
61828
62124
  function resolveAll(hostname2) {
61829
- return new Promise((resolve53, reject) => {
62125
+ return new Promise((resolve54, reject) => {
61830
62126
  dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
61831
62127
  if (err) reject(err);
61832
- else resolve53(addresses);
62128
+ else resolve54(addresses);
61833
62129
  });
61834
62130
  });
61835
62131
  }
@@ -61837,13 +62133,13 @@ function withAbort(start, signal, what) {
61837
62133
  if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
61838
62134
  const work = start();
61839
62135
  if (!signal) return work;
61840
- return new Promise((resolve53, reject) => {
62136
+ return new Promise((resolve54, reject) => {
61841
62137
  const onAbort = () => reject(new Error(`${what} aborted`));
61842
62138
  signal.addEventListener("abort", onAbort, { once: true });
61843
- work.then(resolve53, reject).finally(() => signal.removeEventListener("abort", onAbort));
62139
+ work.then(resolve54, reject).finally(() => signal.removeEventListener("abort", onAbort));
61844
62140
  });
61845
62141
  }
61846
- async function pinAddress(url, resolve53 = resolveAll, signal) {
62142
+ async function pinAddress(url, resolve54 = resolveAll, signal) {
61847
62143
  const host = url.hostname.replace(/^\[|\]$/g, "");
61848
62144
  if (ipv4Octets(host)) {
61849
62145
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
@@ -61853,7 +62149,7 @@ async function pinAddress(url, resolve53 = resolveAll, signal) {
61853
62149
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
61854
62150
  return { address: host, family: 6 };
61855
62151
  }
61856
- const addresses = await withAbort(() => resolve53(host), signal, `${host} lookup`);
62152
+ const addresses = await withAbort(() => resolve54(host), signal, `${host} lookup`);
61857
62153
  if (!addresses.length) throw new Error(`${host} resolved to no address`);
61858
62154
  const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
61859
62155
  if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
@@ -61893,7 +62189,7 @@ function copyIncomingHeaders(headers2) {
61893
62189
  return out2;
61894
62190
  }
61895
62191
  function requestOnce(url, pinned, init) {
61896
- return new Promise((resolve53, reject) => {
62192
+ return new Promise((resolve54, reject) => {
61897
62193
  const headers2 = { host: url.host, "accept-encoding": "identity" };
61898
62194
  new Headers(init.headers ?? {}).forEach((value, key2) => {
61899
62195
  if (key2.toLowerCase() !== "host") headers2[key2] = value;
@@ -61923,7 +62219,7 @@ function requestOnce(url, pinned, init) {
61923
62219
  reject(err);
61924
62220
  return;
61925
62221
  }
61926
- resolve53(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
62222
+ resolve54(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
61927
62223
  }
61928
62224
  );
61929
62225
  req.on("error", reject);
@@ -62983,8 +63279,8 @@ var init_brand_font = __esm({
62983
63279
  });
62984
63280
 
62985
63281
  // src/site-analyze/write-artifacts.ts
62986
- import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync26 } from "node:fs";
62987
- import { join as join62 } from "node:path";
63282
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
63283
+ import { join as join63 } from "node:path";
62988
63284
  function attachVeloSources(book, sources, put) {
62989
63285
  const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
62990
63286
  for (const f of book.velo.files) {
@@ -63139,13 +63435,13 @@ async function downloadMedia(book, fetchImpl, put) {
63139
63435
  }
63140
63436
  async function writeBusinessBook(result, opts) {
63141
63437
  const out2 = opts.outDir;
63142
- mkdirSync30(join62(out2, "evidence/pages"), { recursive: true });
63143
- mkdirSync30(join62(out2, "media/catalog"), { recursive: true });
63438
+ mkdirSync31(join63(out2, "evidence/pages"), { recursive: true });
63439
+ mkdirSync31(join63(out2, "media/catalog"), { recursive: true });
63144
63440
  const files = [];
63145
63441
  const put = (rel, body) => {
63146
- const p = join62(out2, rel);
63147
- mkdirSync30(join62(p, ".."), { recursive: true });
63148
- writeFileSync26(p, body);
63442
+ const p = join63(out2, rel);
63443
+ mkdirSync31(join63(p, ".."), { recursive: true });
63444
+ writeFileSync27(p, body);
63149
63445
  files.push(rel);
63150
63446
  };
63151
63447
  const book = result.book;
@@ -63238,15 +63534,15 @@ var init_customer_build = __esm({
63238
63534
  });
63239
63535
 
63240
63536
  // src/site-analyze/apply.ts
63241
- import { existsSync as existsSync64, readFileSync as readFileSync76, writeFileSync as writeFileSync27, copyFileSync as copyFileSync3, mkdirSync as mkdirSync31, realpathSync as realpathSync9, statSync as statSync17 } from "node:fs";
63242
- import { dirname as dirname35, isAbsolute as isAbsolute6, join as join63, resolve as resolve50, sep as sep16 } from "node:path";
63537
+ import { existsSync as existsSync65, readFileSync as readFileSync77, writeFileSync as writeFileSync28, copyFileSync as copyFileSync3, mkdirSync as mkdirSync32, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
63538
+ import { dirname as dirname36, isAbsolute as isAbsolute7, join as join64, resolve as resolve51, sep as sep17 } from "node:path";
63243
63539
  import { spawnSync as spawnSync4 } from "node:child_process";
63244
63540
  function unpairedRedirectNote(overlay) {
63245
63541
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
63246
63542
  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)`;
63247
63543
  }
63248
63544
  function posix3(p) {
63249
- return resolve50(p).replace(/\\/g, "/");
63545
+ return resolve51(p).replace(/\\/g, "/");
63250
63546
  }
63251
63547
  function committedShellProvisioning(path2) {
63252
63548
  return committedShellFor(posix3(path2));
@@ -63254,8 +63550,8 @@ function committedShellProvisioning(path2) {
63254
63550
  function findRepoRoot(cwd) {
63255
63551
  let dir = cwd;
63256
63552
  for (let i = 0; i < 8; i++) {
63257
- if (SHELL_NAMES2.some((name) => existsSync64(join63(dir, shellAppDir(name), "package.json")))) return dir;
63258
- const next = dirname35(dir);
63553
+ if (SHELL_NAMES2.some((name) => existsSync65(join64(dir, shellAppDir(name), "package.json")))) return dir;
63554
+ const next = dirname36(dir);
63259
63555
  if (next === dir) break;
63260
63556
  dir = next;
63261
63557
  }
@@ -63280,7 +63576,7 @@ function assertNotCommitted(path2, forbidden) {
63280
63576
  `refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
63281
63577
  );
63282
63578
  }
63283
- if (forbidden && resolve50(path2) === resolve50(forbidden)) {
63579
+ if (forbidden && resolve51(path2) === resolve51(forbidden)) {
63284
63580
  const named = committedShellProvisioning(forbidden);
63285
63581
  throw new Error(
63286
63582
  `refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
@@ -63325,36 +63621,36 @@ function mergeCustomerOwned(committed, overlay) {
63325
63621
  }
63326
63622
  function buildMergedContract(options) {
63327
63623
  const { appDir: appDir3, packageDir, overlay } = options;
63328
- const committedPath = join63(appDir3, "provisioning.json");
63329
- if (!existsSync64(committedPath)) {
63624
+ const committedPath = join64(appDir3, "provisioning.json");
63625
+ if (!existsSync65(committedPath)) {
63330
63626
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
63331
63627
  }
63332
- const committed = JSON.parse(readFileSync76(committedPath, "utf8"));
63628
+ const committed = JSON.parse(readFileSync77(committedPath, "utf8"));
63333
63629
  const merged = mergeCustomerOwned(committed, overlay);
63334
63630
  const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
63335
63631
  const branding = merged.branding ?? {};
63336
63632
  const staged = [];
63337
63633
  const contained = (root, rel) => {
63338
- if (isAbsolute6(rel)) return void 0;
63339
- const full = resolve50(root, rel);
63340
- return full.startsWith(resolve50(root) + sep16) ? full : void 0;
63634
+ if (isAbsolute7(rel)) return void 0;
63635
+ const full = resolve51(root, rel);
63636
+ return full.startsWith(resolve51(root) + sep17) ? full : void 0;
63341
63637
  };
63342
63638
  const stage = (fromRel, toRel) => {
63343
63639
  const from = contained(packageDir, fromRel);
63344
- const to = contained(join63(appDir3, STAGED), toRel.slice(STAGED.length + 1));
63345
- if (!from || !to || !existsSync64(from)) return void 0;
63640
+ const to = contained(join64(appDir3, STAGED), toRel.slice(STAGED.length + 1));
63641
+ if (!from || !to || !existsSync65(from)) return void 0;
63346
63642
  let real;
63347
63643
  let realRoot;
63348
63644
  try {
63349
- real = realpathSync9(from);
63350
- realRoot = realpathSync9(packageDir);
63645
+ real = realpathSync10(from);
63646
+ realRoot = realpathSync10(packageDir);
63351
63647
  } catch {
63352
63648
  return void 0;
63353
63649
  }
63354
- if (!real.startsWith(realRoot + sep16)) return void 0;
63650
+ if (!real.startsWith(realRoot + sep17)) return void 0;
63355
63651
  try {
63356
- if (!statSync17(real).isFile()) return void 0;
63357
- mkdirSync31(dirname35(to), { recursive: true });
63652
+ if (!statSync18(real).isFile()) return void 0;
63653
+ mkdirSync32(dirname36(to), { recursive: true });
63358
63654
  copyFileSync3(real, to);
63359
63655
  } catch {
63360
63656
  return void 0;
@@ -63364,11 +63660,11 @@ function buildMergedContract(options) {
63364
63660
  };
63365
63661
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
63366
63662
  if (icon) branding.appIconPath = icon;
63367
- const facesPath = join63(packageDir, "media/fonts/faces.json");
63368
- if (existsSync64(facesPath)) {
63663
+ const facesPath = join64(packageDir, "media/fonts/faces.json");
63664
+ if (existsSync65(facesPath)) {
63369
63665
  let faces = [];
63370
63666
  try {
63371
- const parsed = JSON.parse(readFileSync76(facesPath, "utf8"));
63667
+ const parsed = JSON.parse(readFileSync77(facesPath, "utf8"));
63372
63668
  faces = Array.isArray(parsed) ? parsed : [];
63373
63669
  } catch {
63374
63670
  faces = [];
@@ -63389,11 +63685,11 @@ function buildMergedContract(options) {
63389
63685
  merged.branding = branding;
63390
63686
  const body = `${JSON.stringify(merged, null, 2)}
63391
63687
  `;
63392
- const path2 = join63(packageDir, "provisioning.contract.json");
63393
- writeFileSync27(path2, body);
63394
- const localPath = join63(appDir3, LOCAL_CONTRACT_REL);
63395
- mkdirSync31(dirname35(localPath), { recursive: true });
63396
- writeFileSync27(localPath, body);
63688
+ const path2 = join64(packageDir, "provisioning.contract.json");
63689
+ writeFileSync28(path2, body);
63690
+ const localPath = join64(appDir3, LOCAL_CONTRACT_REL);
63691
+ mkdirSync32(dirname36(localPath), { recursive: true });
63692
+ writeFileSync28(localPath, body);
63397
63693
  staged.push(localPath);
63398
63694
  return { path: path2, staged };
63399
63695
  }
@@ -63426,10 +63722,10 @@ function catalogTypography(overlay, template) {
63426
63722
  function staticFaqFor(overlay, overlayPath) {
63427
63723
  const own3 = overlay.faq;
63428
63724
  if (own3 !== void 0) return deriveStaticFaq(own3);
63429
- const bookPath = join63(dirname35(resolve50(overlayPath)), "book.json");
63430
- if (!existsSync64(bookPath)) return void 0;
63725
+ const bookPath = join64(dirname36(resolve51(overlayPath)), "book.json");
63726
+ if (!existsSync65(bookPath)) return void 0;
63431
63727
  try {
63432
- const book = JSON.parse(readFileSync76(bookPath, "utf8"));
63728
+ const book = JSON.parse(readFileSync77(bookPath, "utf8"));
63433
63729
  const copy = book?.copy;
63434
63730
  if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
63435
63731
  const pairs = deriveStaticFaq(copy.faq);
@@ -63440,11 +63736,11 @@ function staticFaqFor(overlay, overlayPath) {
63440
63736
  }
63441
63737
  }
63442
63738
  async function applyOverlays(input) {
63443
- const cwd = resolve50(input.cwd);
63739
+ const cwd = resolve51(input.cwd);
63444
63740
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
63445
63741
  assertKnownShell(shell);
63446
- const overlay = JSON.parse(readFileSync76(input.overlayPath, "utf8"));
63447
- const tokens = JSON.parse(readFileSync76(input.tokensPath, "utf8"));
63742
+ const overlay = JSON.parse(readFileSync77(input.overlayPath, "utf8"));
63743
+ const tokens = JSON.parse(readFileSync77(input.tokensPath, "utf8"));
63448
63744
  const faq = staticFaqFor(overlay, input.overlayPath);
63449
63745
  if (faq !== void 0) overlay.faq = faq;
63450
63746
  const wrote = [];
@@ -63456,15 +63752,15 @@ async function applyOverlays(input) {
63456
63752
  `shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
63457
63753
  );
63458
63754
  }
63459
- const appDir3 = join63(repoRoot2, shellAppDir(shell));
63460
- const committedPath = join63(appDir3, "provisioning.json");
63461
- const committedSite = existsSync64(committedPath) ? JSON.parse(readFileSync76(committedPath, "utf8")).site : void 0;
63755
+ const appDir3 = join64(repoRoot2, shellAppDir(shell));
63756
+ const committedPath = join64(appDir3, "provisioning.json");
63757
+ const committedSite = existsSync65(committedPath) ? JSON.parse(readFileSync77(committedPath, "utf8")).site : void 0;
63462
63758
  if (committedSite !== void 0 && overlay.site === void 0) {
63463
63759
  throw new Error(
63464
63760
  `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.`
63465
63761
  );
63466
63762
  }
63467
- const packageDir = dirname35(resolve50(input.overlayPath));
63763
+ const packageDir = dirname36(resolve51(input.overlayPath));
63468
63764
  const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
63469
63765
  wrote.push(...staged);
63470
63766
  const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -63485,22 +63781,22 @@ async function applyOverlays(input) {
63485
63781
  note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
63486
63782
  };
63487
63783
  }
63488
- const pkgProv = join63(cwd, "provisioning.json");
63784
+ const pkgProv = join64(cwd, "provisioning.json");
63489
63785
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
63490
63786
  let packageFaq = faq;
63491
- if (existsSync64(pkgProv)) {
63492
- const cur = JSON.parse(readFileSync76(pkgProv, "utf8"));
63787
+ if (existsSync65(pkgProv)) {
63788
+ const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
63493
63789
  const merged = deepMerge4(cur, overlay);
63494
63790
  packageFaq = merged.faq;
63495
- writeFileSync27(pkgProv, JSON.stringify(merged, null, 2) + "\n");
63791
+ writeFileSync28(pkgProv, JSON.stringify(merged, null, 2) + "\n");
63496
63792
  wrote.push(pkgProv);
63497
63793
  } else {
63498
- writeFileSync27(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
63794
+ writeFileSync28(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
63499
63795
  wrote.push(pkgProv);
63500
63796
  }
63501
- const pkgTokens = join63(cwd, "tokens.json");
63502
- if (existsSync64(pkgTokens) && (tokens.colors || tokens.typography)) {
63503
- const cur = JSON.parse(readFileSync76(pkgTokens, "utf8"));
63797
+ const pkgTokens = join64(cwd, "tokens.json");
63798
+ if (existsSync65(pkgTokens) && (tokens.colors || tokens.typography)) {
63799
+ const cur = JSON.parse(readFileSync77(pkgTokens, "utf8"));
63504
63800
  let tokensIn = tokens;
63505
63801
  if (tokens.typography) {
63506
63802
  const fonts = catalogTypography(tokens.typography, cur.typography);
@@ -63521,13 +63817,13 @@ async function applyOverlays(input) {
63521
63817
  if (primary && glow && typeof glow.color === "string") glow.color = primary;
63522
63818
  stripBrandFromIdiom(merged);
63523
63819
  }
63524
- writeFileSync27(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
63820
+ writeFileSync28(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
63525
63821
  wrote.push(pkgTokens);
63526
63822
  }
63527
63823
  const homeAction = homeRefreshActionId(shell);
63528
- const homeSrc = join63(cwd, "dev/index.ts");
63529
- if (homeAction && existsSync64(homeSrc)) {
63530
- const prev = readFileSync76(homeSrc, "utf8");
63824
+ const homeSrc = join64(cwd, "dev/index.ts");
63825
+ if (homeAction && existsSync65(homeSrc)) {
63826
+ const prev = readFileSync77(homeSrc, "utf8");
63531
63827
  const patched = patchBrandParams(prev, overlay, homeAction);
63532
63828
  let next = patched.src;
63533
63829
  if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
@@ -63551,20 +63847,20 @@ async function applyOverlays(input) {
63551
63847
  }
63552
63848
  }
63553
63849
  if (next !== prev) {
63554
- writeFileSync27(homeSrc, next);
63850
+ writeFileSync28(homeSrc, next);
63555
63851
  wrote.push(homeSrc);
63556
63852
  }
63557
63853
  if (patched.unparsed) {
63558
63854
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
63559
63855
  }
63560
63856
  }
63561
- if (!input.iconPath || !existsSync64(input.iconPath)) {
63562
- const book = input.iconPath ? dirname35(dirname35(resolve50(input.iconPath))) : void 0;
63857
+ if (!input.iconPath || !existsSync65(input.iconPath)) {
63858
+ const book = input.iconPath ? dirname36(dirname36(resolve51(input.iconPath))) : void 0;
63563
63859
  notes.push(
63564
63860
  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"
63565
63861
  );
63566
63862
  }
63567
- if (input.iconPath && existsSync64(input.iconPath)) {
63863
+ if (input.iconPath && existsSync65(input.iconPath)) {
63568
63864
  try {
63569
63865
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
63570
63866
  wrote.push(...installed.wrote);
@@ -64678,10 +64974,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
64678
64974
  }
64679
64975
  function createPromiseCallback(cb) {
64680
64976
  let callback;
64681
- let resolve53;
64977
+ let resolve54;
64682
64978
  let reject;
64683
64979
  const promise = new Promise((_resolve, _reject) => {
64684
- resolve53 = _resolve;
64980
+ resolve54 = _resolve;
64685
64981
  reject = _reject;
64686
64982
  });
64687
64983
  if (typeof cb === "function") {
@@ -64697,7 +64993,7 @@ function createPromiseCallback(cb) {
64697
64993
  callback = (err, result) => {
64698
64994
  try {
64699
64995
  if (err) reject(err);
64700
- else resolve53(result);
64996
+ else resolve54(result);
64701
64997
  } catch (e) {
64702
64998
  reject(e instanceof Error ? e : new Error());
64703
64999
  }
@@ -67785,14 +68081,14 @@ async function runSiteFunction(opts) {
67785
68081
  }
67786
68082
  if (opts.op === "publish") {
67787
68083
  const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
67788
- const ok = httpOk(snap.rev) && httpOk(snap.live);
68084
+ const ok2 = httpOk(snap.rev) && httpOk(snap.live);
67789
68085
  return {
67790
68086
  ...base,
67791
- ok,
68087
+ ok: ok2,
67792
68088
  revision: snap.revision,
67793
68089
  codeAppId: snap.codeAppId,
67794
68090
  publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
67795
- error: ok ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
68091
+ error: ok2 ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
67796
68092
  };
67797
68093
  }
67798
68094
  const { id, listed } = await withGrid(fetchImpl, opts.token, opts.msid, opts.siteUrl);
@@ -67887,12 +68183,12 @@ async function invokeAndReport(fetchImpl, opts, base, name, method) {
67887
68183
  await new Promise((res) => setTimeout(res, 2500));
67888
68184
  hit = await tryInvoke();
67889
68185
  }
67890
- const ok = httpOk(hit.r);
68186
+ const ok2 = httpOk(hit.r);
67891
68187
  return {
67892
68188
  ...base,
67893
- ok,
68189
+ ok: ok2,
67894
68190
  invoke: { url: hit.url, status: hit.r.status, body: hit.r.json ?? snippet2(hit.r.text) },
67895
- error: ok ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
68191
+ error: ok2 ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
67896
68192
  };
67897
68193
  }
67898
68194
  var HTTP_METHODS2, WRITE_LAYOUTS, VELO_PROVISION_URL, SITE_PUBLISH_URL, PUBLISH_RC_URL, SITE_FUNCTION_USAGE, NAME_RE, EXPORT_HEAD, WIX_HTTP_IMPORT_LINE;
@@ -67926,8 +68222,8 @@ __export(cli_exports, {
67926
68222
  runSiteAnalyze: () => runSiteAnalyze,
67927
68223
  runSiteFunctionCli: () => runSiteFunctionCli
67928
68224
  });
67929
- import { readFileSync as readFileSync77 } from "node:fs";
67930
- import { resolve as resolve51 } from "node:path";
68225
+ import { readFileSync as readFileSync78 } from "node:fs";
68226
+ import { resolve as resolve52 } from "node:path";
67931
68227
  function assetFetchFor(_opts) {
67932
68228
  return pinnedFetch2;
67933
68229
  }
@@ -67947,7 +68243,7 @@ async function runSiteAnalyze(opts) {
67947
68243
  const assetFetch = assetFetchFor(opts);
67948
68244
  const siteFetch = guardedSiteFetch;
67949
68245
  const cwd = opts.cwd ?? process.cwd();
67950
- const outDir = resolve51(cwd, opts.outDir ?? ".himi/business-book");
68246
+ const outDir = resolve52(cwd, opts.outDir ?? ".himi/business-book");
67951
68247
  let ownerAuth;
67952
68248
  let msid;
67953
68249
  const ownerSite = ownerSiteFor(opts);
@@ -67999,9 +68295,9 @@ async function runSiteAnalyze(opts) {
67999
68295
  if (opts.apply) {
68000
68296
  applied = await applyOverlays({
68001
68297
  cwd,
68002
- overlayPath: resolve51(outDir, "provisioning.overlay.json"),
68003
- tokensPath: resolve51(outDir, "tokens.overlay.json"),
68004
- iconPath: resolve51(outDir, "media/icon.png"),
68298
+ overlayPath: resolve52(outDir, "provisioning.overlay.json"),
68299
+ tokensPath: resolve52(outDir, "tokens.overlay.json"),
68300
+ iconPath: resolve52(outDir, "media/icon.png"),
68005
68301
  shell: opts.shell
68006
68302
  });
68007
68303
  const note = noteWithWarnings(applied.note, warnings);
@@ -68037,8 +68333,8 @@ async function runSiteFunctionCli(opts) {
68037
68333
  const token = opts.token ?? await siteToken(msid);
68038
68334
  let source;
68039
68335
  if (opts.sourcePath) {
68040
- const p = resolve51(opts.cwd ?? process.cwd(), opts.sourcePath);
68041
- source = readFileSync77(p, "utf8");
68336
+ const p = resolve52(opts.cwd ?? process.cwd(), opts.sourcePath);
68337
+ source = readFileSync78(p, "utf8");
68042
68338
  }
68043
68339
  let body;
68044
68340
  if (opts.bodyRaw != null) {
@@ -68093,7 +68389,7 @@ async function accountToken2(spawnImpl = spawn6) {
68093
68389
  cached2 = fromEnv;
68094
68390
  return fromEnv;
68095
68391
  }
68096
- const token = await new Promise((resolve53, reject) => {
68392
+ const token = await new Promise((resolve54, reject) => {
68097
68393
  let child;
68098
68394
  try {
68099
68395
  child = spawnImpl("wix", ["token"]);
@@ -68122,7 +68418,7 @@ async function accountToken2(spawnImpl = spawn6) {
68122
68418
  const scan = (d) => {
68123
68419
  out2 += String(d);
68124
68420
  const m = out2.match(TOKEN_RE2);
68125
- if (m) done(() => resolve53(m[0]));
68421
+ if (m) done(() => resolve54(m[0]));
68126
68422
  };
68127
68423
  child.stdout?.on("data", scan);
68128
68424
  child.stderr?.on("data", scan);
@@ -68299,7 +68595,7 @@ __export(site_create_exports, {
68299
68595
  runSiteList: () => runSiteList,
68300
68596
  writeProvisioningBinding: () => writeProvisioningBinding
68301
68597
  });
68302
- import { existsSync as existsSync65, readFileSync as readFileSync78, writeFileSync as writeFileSync28 } from "node:fs";
68598
+ import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync29 } from "node:fs";
68303
68599
  import { resolve as resolvePath2 } from "node:path";
68304
68600
  function oauthClientName(projectName) {
68305
68601
  return `${projectName} client`;
@@ -68448,7 +68744,7 @@ async function runSiteCreate(opts) {
68448
68744
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
68449
68745
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
68450
68746
  }
68451
- function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync65, readFileSync: readFileSync78, writeFileSync: writeFileSync28 }) {
68747
+ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync29 }) {
68452
68748
  const msid = binding2.siteId;
68453
68749
  const path2 = resolvePath2(target);
68454
68750
  const committed = committedShellProvisioning(path2);
@@ -69121,12 +69417,12 @@ var init_context = __esm({
69121
69417
  });
69122
69418
 
69123
69419
  // src/cli.ts
69124
- import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync79, mkdirSync as mkdirSync32, writeFileSync as writeFileSync29, existsSync as existsSync66, rmSync as rmSync15, readdirSync as readdirSync30, statSync as statSync18, lstatSync as lstatSync13, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
69420
+ import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync80, mkdirSync as mkdirSync33, writeFileSync as writeFileSync30, existsSync as existsSync67, rmSync as rmSync16, readdirSync as readdirSync31, statSync as statSync19, lstatSync as lstatSync14, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
69125
69421
  import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
69126
69422
  import { AsyncLocalStorage } from "node:async_hooks";
69127
69423
  import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
69128
69424
  import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
69129
- import { join as join64, resolve as resolve52, relative as relative13, basename as basename17, dirname as dirname36 } from "node:path";
69425
+ import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
69130
69426
  import { fileURLToPath as fileURLToPath26 } from "node:url";
69131
69427
 
69132
69428
  // ../serve-cli/src/client.ts
@@ -69867,7 +70163,7 @@ async function browserLogin(opts) {
69867
70163
  const log = opts.log ?? (() => {
69868
70164
  });
69869
70165
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
69870
- return await new Promise((resolve53, reject) => {
70166
+ return await new Promise((resolve54, reject) => {
69871
70167
  let settled = false;
69872
70168
  let loginUrl = "";
69873
70169
  const server = createServer();
@@ -69931,7 +70227,7 @@ async function browserLogin(opts) {
69931
70227
  return;
69932
70228
  }
69933
70229
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
69934
- finish2(() => resolve53({ token, loginUrl }));
70230
+ finish2(() => resolve54({ token, loginUrl }));
69935
70231
  });
69936
70232
  });
69937
70233
  server.on("error", (err) => finish2(() => reject(err)));
@@ -71261,8 +71557,8 @@ var str8 = (v) => typeof v === "string" ? v : void 0;
71261
71557
  var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
71262
71558
  function embeddedTemplateCatalog() {
71263
71559
  return availableTemplates().map((name) => {
71264
- const path2 = join64(templateSourceDir(name), TEMPLATE_META_FILE);
71265
- const meta = JSON.parse(readFileSync79(path2, "utf8"));
71560
+ const path2 = join65(templateSourceDir(name), TEMPLATE_META_FILE);
71561
+ const meta = JSON.parse(readFileSync80(path2, "utf8"));
71266
71562
  if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
71267
71563
  throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
71268
71564
  }
@@ -71944,7 +72240,7 @@ var COMMANDS = [
71944
72240
  { name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone. A NON-EMPTY destination is refused unless you say which you mean: `--force` merges and reports \u2014 it writes the archive over what is there, keeps files the release does not carry, and NAMES every one of them as `left: [...]` so a tree that matches no release is never silent (#2437); `--replace` restores exactly what was archived, removing those files first (`removed: [...]`) and implying `--force`. `--replace` refuses a directory holding no `himalaya.content.json`, so a mistyped `--out` cannot clear an unrelated tree, and the only paths it can remove are the ones a push would have archived \u2014 `.git/`, `node_modules/`, `dist/`, `.env*` and key material are out of its reach by construction.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]" },
71945
72241
  { name: "share", summary: "publish or revoke a content-addressed `.himi` share link. The package must be a validated archive for an already-published release; the resulting https URL is safe to QR, copy, or open in Himi Player.", required: "--file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>" },
71946
72242
  { name: "run", summary: "serve a .himi package on localhost and open it in a browser \u2014 no serve plane, no dev-server, no setup. Given no argument it builds the current content package first, so `himi run` is the inner loop: edit, run, look at it. The SPA and /v1 are served from ONE origin because Tier-5 bundle fetches on web are same-origin-only. --chrome preview frames the app in a device chassis; --chrome app serves it as a plain web app. Blocks until Ctrl-C, like any dev server. --browser runs the whole plane INSIDE the tab (service worker + in-memory store) so no app code executes in this process or on any pod. --lan also serves it to the local network and prints a QR, so a phone on the same Wi-Fi opens it as the real app, full screen. --watch keeps the preview LIVE: every save in the content package rebuilds it and repaints the open tab with only what changed (the dev-server's hot-reload events); a build that fails keeps the last good preview on screen and says why. --idle-exit <min> (with --watch only) stops the watch once that many minutes pass with no source save, printing `{\"watch\":\"idle_exit\"}` and removing its .himi/run.json on the way out \u2014 the watch `himi init` starts passes 30; one started by hand runs until Ctrl-C. Stopping (Ctrl-C, SIGTERM, SIGHUP or the idle exit) removes the run's own .himi/run.json. Any `himi run` of a content package (plain, --watch or --browser) frames its preview on the build board (`himi studio`) while it serves, and all but --browser also serve that board at /__himi/studio/ on the preview's own origin. Its .himi/run.json (pid, watching) is also how `himi render` and `himi test` tell a live --watch is running: while none is, they add a `reminder` naming `himi run --watch --content <dir> &`, and while one is (the one `himi init` started, usually, whose .himi/watch.json vouches for it until it serves) the reminder names its url and board instead (either at most once every ten minutes per app) \u2014 first in `next[]` and again as the envelope's LAST key (the last line of `himi test`'s plain report), so an output read with `tail` still carries it.", required: "[<package.himi|dir|url>] [--browser] [--watch] [--idle-exit <min>] [--lan] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
71947
- { name: "mcp", summary: "run the himi tools as a local Model Context Protocol server over stdio, for coding agents \u2014 Claude Code, Cursor, Codex, VS Code. Tools: docs/components/sdk/icons, init, build, validate, test (hermetic), render (returns the PNG), progress, a live preview (start/status/stop a `himi run --watch`), whoami, and DRAFT-only push/share/preview links \u2014 never promote, login, dist or secrets. Each tool runs the same command in-process on the content package on disk (default: the host's workspace root). `himi init` and `himi agent-init` write the config for every host (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, .codex/config.toml when absent) plus a `himi-preview` launch configuration (.claude/launch.json) that opens the live preview in Claude Code desktop's browser pane. Never self-updates (npx already runs the current CLI). Blocks until the host closes stdin. `himi mcp plugin --out <dir>` writes the Claude Code plugin (the customer skill + this server) as a folder \u2014 the same plugin the serve plane's marketplace hands out at /.claude-plugin/marketplace.json.", required: "[plugin --out <dir>]" },
72243
+ { name: "mcp", summary: "run the himi tools as a local Model Context Protocol server over stdio, for coding agents \u2014 Claude Code, Cursor, Codex, VS Code. Tools: docs/components/sdk/icons, init, build, validate, test (hermetic), render (returns the PNG), progress, a live preview (start/status/stop a `himi run --watch`), whoami, login (opens the browser sign-in for the user; the credential goes to a child `himi login` and onto disk, never through the server), and DRAFT-only push/share/preview links \u2014 never promote, dist or secrets. A sign-in's target is the one push/share then use. Each tool runs the same command in-process on the content package on disk (default: the host's workspace root). `himi init` and `himi agent-init` write the config for every host (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, .codex/config.toml when absent) plus a `himi-preview` launch configuration (.claude/launch.json) that opens the live preview in Claude Code desktop's browser pane. Never self-updates (npx already runs the current CLI). Blocks until the host closes stdin. `himi mcp plugin --out <dir>` writes the Claude Code plugin (the customer skill + this server) as a folder \u2014 the same plugin the serve plane's marketplace hands out at /.claude-plugin/marketplace.json. `--with-files` adds list/read/write/delete file tools confined to the workspace folder, for a host that cannot edit files (Claude Desktop chat, via the Desktop Extension); `HIMI_WORKSPACE` names that folder when the host names none.", required: "[plugin --out <dir>] [--with-files]" },
71948
72244
  { name: "preview", summary: "print the shareable web URL + himi:// deep link + agent /v1/preview JSON URLs for an app+release; --surface frames the web preview as any catalog surface (?surface=)", required: "--app --release [--screen] [--surface]" },
71949
72245
  { name: "surfaces", summary: "the surface catalog vs this app's envelope (platforms.json): targeted surfaces, the opt-in key for the rest, per-surface preview links with --app --release, and which widget families the package produces with --measure-widgets (which runs its built bundles)", required: "[--content <dir>] [--app --release] [--measure-widgets]" },
71950
72246
  { name: "context", summary: "fetch the agent preview envelope (GET /v1/preview/a/<app>) \u2014 ok/issues/screens/links; exit 1 if ok:false", required: "--app --release [--screen] [--include telemetry]" },
@@ -71976,7 +72272,7 @@ var COMMANDS = [
71976
72272
  ];
71977
72273
  function cliVersion() {
71978
72274
  try {
71979
- return JSON.parse(readFileSync79(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
72275
+ return JSON.parse(readFileSync80(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
71980
72276
  } catch {
71981
72277
  return "unknown";
71982
72278
  }
@@ -72027,16 +72323,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
72027
72323
  }
72028
72324
  var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
72029
72325
  function execNpmConfig(file, args, options) {
72030
- return new Promise((resolve53, reject) => {
72031
- execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve53(String(stdout)));
72326
+ return new Promise((resolve54, reject) => {
72327
+ execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve54(String(stdout)));
72032
72328
  });
72033
72329
  }
72034
72330
  var npmScopedWixRegistry = createScopedRegistryResolver();
72035
72331
  async function scopedRegistryBefore(lookup2, deadline) {
72036
72332
  let cancel = () => {
72037
72333
  };
72038
- const expired = new Promise((resolve53) => {
72039
- const timer = setTimeout(() => resolve53(void 0), Math.max(0, deadline - Date.now()));
72334
+ const expired = new Promise((resolve54) => {
72335
+ const timer = setTimeout(() => resolve54(void 0), Math.max(0, deadline - Date.now()));
72040
72336
  cancel = () => clearTimeout(timer);
72041
72337
  });
72042
72338
  try {
@@ -72094,18 +72390,18 @@ function ageInDays(publishedAt, now = Date.now()) {
72094
72390
  }
72095
72391
  function packageVersion(path2) {
72096
72392
  try {
72097
- const version2 = JSON.parse(readFileSync79(path2, "utf8")).version;
72393
+ const version2 = JSON.parse(readFileSync80(path2, "utf8")).version;
72098
72394
  return typeof version2 === "string" && version2 ? version2 : void 0;
72099
72395
  } catch {
72100
72396
  return void 0;
72101
72397
  }
72102
72398
  }
72103
72399
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
72104
- let dir = resolve52(fromDir);
72400
+ let dir = resolve53(fromDir);
72105
72401
  for (; ; ) {
72106
- const version2 = packageVersion(join64(dir, "node_modules", "@wix", "himalaya", "package.json"));
72402
+ const version2 = packageVersion(join65(dir, "node_modules", "@wix", "himalaya", "package.json"));
72107
72403
  if (version2) return { version: version2, source: "local" };
72108
- const parent = dirname36(dir);
72404
+ const parent = dirname37(dir);
72109
72405
  if (parent === dir) break;
72110
72406
  dir = parent;
72111
72407
  }
@@ -72113,7 +72409,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
72113
72409
  if (bundled) return { version: bundled, source: "bundled" };
72114
72410
  try {
72115
72411
  const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
72116
- const version2 = root ? packageVersion(join64(root, "@wix", "himalaya", "package.json")) : void 0;
72412
+ const version2 = root ? packageVersion(join65(root, "@wix", "himalaya", "package.json")) : void 0;
72117
72413
  return version2 ? { version: version2, source: "global" } : {};
72118
72414
  } catch {
72119
72415
  return {};
@@ -72160,11 +72456,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
72160
72456
  var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
72161
72457
  var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
72162
72458
  function updateCachePath(env = process.env) {
72163
- return env.HIMI_UPDATE_CACHE_FILE ?? join64(homedir7(), ".himalaya", "update-check.json");
72459
+ return env.HIMI_UPDATE_CACHE_FILE ?? join65(homedir7(), ".himalaya", "update-check.json");
72164
72460
  }
72165
72461
  function readUpdateCache(path2) {
72166
72462
  try {
72167
- const parsed = JSON.parse(readFileSync79(path2, "utf8"));
72463
+ const parsed = JSON.parse(readFileSync80(path2, "utf8"));
72168
72464
  return parsed && typeof parsed === "object" ? parsed : {};
72169
72465
  } catch {
72170
72466
  return {};
@@ -72172,8 +72468,8 @@ function readUpdateCache(path2) {
72172
72468
  }
72173
72469
  function writeUpdateCache(path2, cache) {
72174
72470
  try {
72175
- mkdirSync32(dirname36(path2), { recursive: true, mode: 448 });
72176
- writeFileSync29(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
72471
+ mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
72472
+ writeFileSync30(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
72177
72473
  } catch {
72178
72474
  }
72179
72475
  }
@@ -72233,12 +72529,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
72233
72529
  },
72234
72530
  installedVersion: () => {
72235
72531
  const root = globalNodeModulesRoot();
72236
- return root ? packageVersion(join64(root, "@wix", "himalaya-cli", "package.json")) : void 0;
72532
+ return root ? packageVersion(join65(root, "@wix", "himalaya-cli", "package.json")) : void 0;
72237
72533
  },
72238
72534
  reexec: (argv) => {
72239
72535
  const root = globalNodeModulesRoot();
72240
- const entry = root ? join64(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
72241
- if (!entry || !existsSync66(entry)) return void 0;
72536
+ const entry = root ? join65(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
72537
+ if (!entry || !existsSync67(entry)) return void 0;
72242
72538
  const result = spawnSync5(process.execPath, [entry, ...argv], {
72243
72539
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
72244
72540
  stdio: "inherit",
@@ -72285,7 +72581,7 @@ function staleUpdateLockFile(cachePath, now) {
72285
72581
  for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
72286
72582
  let content;
72287
72583
  try {
72288
- content = readFileSync79(path2, "utf8");
72584
+ content = readFileSync80(path2, "utf8");
72289
72585
  } catch {
72290
72586
  continue;
72291
72587
  }
@@ -72293,7 +72589,7 @@ function staleUpdateLockFile(cachePath, now) {
72293
72589
  let since = stamped;
72294
72590
  if (!Number.isFinite(since)) {
72295
72591
  try {
72296
- since = statSync18(path2).mtimeMs;
72592
+ since = statSync19(path2).mtimeMs;
72297
72593
  } catch {
72298
72594
  continue;
72299
72595
  }
@@ -72308,14 +72604,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72308
72604
  const mine = lockStamp(now);
72309
72605
  const readLock = (path2) => {
72310
72606
  try {
72311
- return readFileSync79(path2, "utf8");
72607
+ return readFileSync80(path2, "utf8");
72312
72608
  } catch {
72313
72609
  return void 0;
72314
72610
  }
72315
72611
  };
72316
72612
  const tryCreate = (path2) => {
72317
72613
  try {
72318
- writeFileSync29(path2, mine, { flag: "wx", mode: 384 });
72614
+ writeFileSync30(path2, mine, { flag: "wx", mode: 384 });
72319
72615
  return true;
72320
72616
  } catch {
72321
72617
  return false;
@@ -72323,13 +72619,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72323
72619
  };
72324
72620
  const removeIfMine = (path2) => {
72325
72621
  try {
72326
- if (readLock(path2) === mine) rmSync15(path2, { force: true });
72622
+ if (readLock(path2) === mine) rmSync16(path2, { force: true });
72327
72623
  } catch {
72328
72624
  }
72329
72625
  };
72330
72626
  const release = () => removeIfMine(lockPath);
72331
72627
  try {
72332
- mkdirSync32(dirname36(lockPath), { recursive: true, mode: 448 });
72628
+ mkdirSync33(dirname37(lockPath), { recursive: true, mode: 448 });
72333
72629
  } catch {
72334
72630
  return () => {
72335
72631
  };
@@ -72346,7 +72642,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72346
72642
  hooks.underBreakLock?.();
72347
72643
  if (current === void 0) return tryCreate(lockPath) ? release : void 0;
72348
72644
  if (!isAbandoned(current)) return void 0;
72349
- rmSync15(lockPath, { force: true });
72645
+ rmSync16(lockPath, { force: true });
72350
72646
  return tryCreate(lockPath) ? release : void 0;
72351
72647
  } finally {
72352
72648
  removeIfMine(breakPath);
@@ -72442,7 +72738,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
72442
72738
  return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
72443
72739
  };
72444
72740
  return async (dir, opts = {}) => {
72445
- const argv = ["validate", "--content", resolve52(dir), "--strict", "--skip-version-check"];
72741
+ const argv = ["validate", "--content", resolve53(dir), "--strict", "--skip-version-check"];
72446
72742
  if (!opts.fresh) {
72447
72743
  const out2 = [];
72448
72744
  const err = [];
@@ -72900,9 +73196,9 @@ function executableOnPath(name, env = process.env) {
72900
73196
  const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
72901
73197
  for (const dir of entries) {
72902
73198
  for (const suffix of suffixes) {
72903
- const candidate = join64(dir, `${name}${suffix}`);
73199
+ const candidate = join65(dir, `${name}${suffix}`);
72904
73200
  try {
72905
- if (!statSync18(candidate).isFile()) continue;
73201
+ if (!statSync19(candidate).isFile()) continue;
72906
73202
  if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
72907
73203
  return true;
72908
73204
  } catch {
@@ -72949,9 +73245,9 @@ function buildDoctorReport(input) {
72949
73245
  const versionSkew = versions?.cli.status === "outdated" || sdkSkew;
72950
73246
  const hostRefused = auth.controlTokenStatus === "refused";
72951
73247
  const staleToken = auth.controlTokenPresent === true && auth.controlToken === false && !hostRefused;
72952
- const ok = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
73248
+ const ok2 = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
72953
73249
  return {
72954
- ok,
73250
+ ok: ok2,
72955
73251
  target,
72956
73252
  version: version2,
72957
73253
  dataPlane: { ...data, note: "public Wix APIs \u2014 reachable off-VPN" },
@@ -73009,7 +73305,7 @@ async function nativeConfigAdvisories(app, configSource) {
73009
73305
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
73010
73306
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
73011
73307
  const iosYmlPath = iosProjectYml2(app);
73012
- const iosYml = existsSync66(iosYmlPath) ? readFileSync79(iosYmlPath, "utf8") : "";
73308
+ const iosYml = existsSync67(iosYmlPath) ? readFileSync80(iosYmlPath, "utf8") : "";
73013
73309
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
73014
73310
  if (!optedIn) {
73015
73311
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -73023,14 +73319,14 @@ async function nativeConfigAdvisories(app, configSource) {
73023
73319
  }
73024
73320
  function readConfigSource(dir) {
73025
73321
  try {
73026
- return readFileSync79(join64(dir, "config.ts"), "utf8");
73322
+ return readFileSync80(join65(dir, "config.ts"), "utf8");
73027
73323
  } catch {
73028
73324
  return null;
73029
73325
  }
73030
73326
  }
73031
73327
  function writePngFile(path2, base64) {
73032
- mkdirSync32(dirname36(path2), { recursive: true });
73033
- writeFileSync29(path2, Buffer.from(base64, "base64"));
73328
+ mkdirSync33(dirname37(path2), { recursive: true });
73329
+ writeFileSync30(path2, Buffer.from(base64, "base64"));
73034
73330
  return path2;
73035
73331
  }
73036
73332
  async function seedAgentFilesFor(dir, flags, mode = "init") {
@@ -73058,8 +73354,8 @@ function keptPlan(kept) {
73058
73354
  return note ? { kept, note } : {};
73059
73355
  }
73060
73356
  async function initFromRemoteTemplate(name, parentDir, template, c) {
73061
- const dir = resolve52(parentDir, name);
73062
- if (existsSync66(join64(dir, "himalaya.content.json"))) {
73357
+ const dir = resolve53(parentDir, name);
73358
+ if (existsSync67(join65(dir, "himalaya.content.json"))) {
73063
73359
  throw new Error(`content package already exists at ${dir}`);
73064
73360
  }
73065
73361
  const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -73071,7 +73367,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
73071
73367
  return finishScaffold(materializeSource(archive.files, name, dir), template);
73072
73368
  }
73073
73369
  function contentDir(flags) {
73074
- return resolve52(str8(flags.content) ?? process.cwd());
73370
+ return resolve53(str8(flags.content) ?? process.cwd());
73075
73371
  }
73076
73372
  function renameRestoredSource(restored, declaredApp, renamed) {
73077
73373
  const text8 = {};
@@ -73089,7 +73385,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
73089
73385
  function symlinkDestinationIssue(dest) {
73090
73386
  let kind;
73091
73387
  try {
73092
- kind = lstatSync13(dest);
73388
+ kind = lstatSync14(dest);
73093
73389
  } catch {
73094
73390
  return null;
73095
73391
  }
@@ -73102,11 +73398,11 @@ function symlinkDestinationIssue(dest) {
73102
73398
  function restoreDestinationIssue(dest, force) {
73103
73399
  const link = symlinkDestinationIssue(dest);
73104
73400
  if (link) return link;
73105
- if (!existsSync66(dest)) return null;
73106
- if (!statSync18(dest).isDirectory()) {
73401
+ if (!existsSync67(dest)) return null;
73402
+ if (!statSync19(dest).isDirectory()) {
73107
73403
  return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
73108
73404
  }
73109
- if (readdirSync30(dest).length > 0 && !force) {
73405
+ if (readdirSync31(dest).length > 0 && !force) {
73110
73406
  return {
73111
73407
  error: `${dest} already exists and is not empty`,
73112
73408
  hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
@@ -73115,10 +73411,10 @@ function restoreDestinationIssue(dest, force) {
73115
73411
  return null;
73116
73412
  }
73117
73413
  function isHimalayaMonorepoCheckout(start) {
73118
- let dir = resolve52(start);
73414
+ let dir = resolve53(start);
73119
73415
  for (; ; ) {
73120
- if (existsSync66(join64(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync66(join64(dir, "core", "serve", "src", "server.ts"))) return true;
73121
- const parent = dirname36(dir);
73416
+ if (existsSync67(join65(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync67(join65(dir, "core", "serve", "src", "server.ts"))) return true;
73417
+ const parent = dirname37(dir);
73122
73418
  if (parent === dir) return false;
73123
73419
  dir = parent;
73124
73420
  }
@@ -73177,8 +73473,8 @@ function materializeForPreview(appDir3, slug, displayName) {
73177
73473
  const forBuild = Object.fromEntries(
73178
73474
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
73179
73475
  );
73180
- const repoRoot2 = resolve52(fileURLToPath26(new URL("../../..", import.meta.url)));
73181
- const root = join64(repoRoot2, "node_modules", ".cache", "himi-template-preview");
73476
+ const repoRoot2 = resolve53(fileURLToPath26(new URL("../../..", import.meta.url)));
73477
+ const root = join65(repoRoot2, "node_modules", ".cache", "himi-template-preview");
73182
73478
  const stillRunning = (pid) => {
73183
73479
  try {
73184
73480
  process.kill(pid, 0);
@@ -73188,30 +73484,30 @@ function materializeForPreview(appDir3, slug, displayName) {
73188
73484
  }
73189
73485
  };
73190
73486
  try {
73191
- for (const entry of readdirSync30(root, { withFileTypes: true })) {
73487
+ for (const entry of readdirSync31(root, { withFileTypes: true })) {
73192
73488
  if (!entry.isDirectory()) continue;
73193
73489
  const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
73194
73490
  if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
73195
- rmSync15(join64(root, entry.name), { recursive: true, force: true });
73491
+ rmSync16(join65(root, entry.name), { recursive: true, force: true });
73196
73492
  }
73197
73493
  }
73198
73494
  } catch {
73199
73495
  }
73200
- const dest = join64(root, `${slug}-${process.pid}`);
73201
- rmSync15(dest, { recursive: true, force: true });
73202
- mkdirSync32(dest, { recursive: true });
73496
+ const dest = join65(root, `${slug}-${process.pid}`);
73497
+ rmSync16(dest, { recursive: true, force: true });
73498
+ mkdirSync33(dest, { recursive: true });
73203
73499
  try {
73204
73500
  materializeSource(forBuild, displayName, dest, slug);
73205
73501
  } catch (e) {
73206
- rmSync15(dest, { recursive: true, force: true });
73502
+ rmSync16(dest, { recursive: true, force: true });
73207
73503
  throw e;
73208
73504
  }
73209
73505
  return dest;
73210
73506
  }
73211
73507
  async function appId(dir) {
73212
73508
  try {
73213
- const { readFileSync: readFileSync80 } = await import("node:fs");
73214
- const m = JSON.parse(readFileSync80(join64(dir, "himalaya.content.json"), "utf8"));
73509
+ const { readFileSync: readFileSync81 } = await import("node:fs");
73510
+ const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
73215
73511
  if (m.name) return m.name;
73216
73512
  } catch {
73217
73513
  }
@@ -73219,8 +73515,8 @@ async function appId(dir) {
73219
73515
  }
73220
73516
  async function contentVisibility(dir) {
73221
73517
  try {
73222
- const { readFileSync: readFileSync80 } = await import("node:fs");
73223
- const m = JSON.parse(readFileSync80(join64(dir, "himalaya.content.json"), "utf8"));
73518
+ const { readFileSync: readFileSync81 } = await import("node:fs");
73519
+ const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
73224
73520
  if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
73225
73521
  } catch {
73226
73522
  }
@@ -73423,7 +73719,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73423
73719
  return 0;
73424
73720
  }
73425
73721
  case "agent-init": {
73426
- const dir = resolve52(str8(flags.dir) ?? process.cwd());
73722
+ const dir = resolve53(str8(flags.dir) ?? process.cwd());
73427
73723
  const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
73428
73724
  let res;
73429
73725
  try {
@@ -73445,7 +73741,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73445
73741
  ...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/" } : {},
73446
73742
  // In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
73447
73743
  // hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
73448
- ...existsSync66(join64(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" } : {},
73744
+ ...existsSync67(join65(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" } : {},
73449
73745
  ...res.skipped.length ? { skipped: res.skipped } : {},
73450
73746
  portalUrl: idx.portalUrl
73451
73747
  });
@@ -73468,7 +73764,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
73468
73764
  try {
73469
73765
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
73470
73766
  const bres = await buildContentForValidation2(dir, { resolution });
73471
- out2 = mkdtempSync4(join64(tmpdir5(), "himi-ux-record-"));
73767
+ out2 = mkdtempSync4(join65(tmpdir5(), "himi-ux-record-"));
73472
73768
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
73473
73769
  const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
73474
73770
  const releaseId = outcome.manifest.releaseId;
@@ -73481,7 +73777,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
73481
73777
  return null;
73482
73778
  } finally {
73483
73779
  if (out2 !== void 0) try {
73484
- rmSync15(out2, { recursive: true, force: true });
73780
+ rmSync16(out2, { recursive: true, force: true });
73485
73781
  } catch {
73486
73782
  }
73487
73783
  }
@@ -73635,7 +73931,7 @@ async function producedWidgetFamilies(dir) {
73635
73931
  }
73636
73932
  const outDir = tier5Dir.bundleOutDir(dir);
73637
73933
  try {
73638
- readdirSync30(outDir);
73934
+ readdirSync31(outDir);
73639
73935
  } catch {
73640
73936
  return { families: void 0, source: "unbuilt" };
73641
73937
  }
@@ -73646,7 +73942,7 @@ async function producedWidgetFamilies(dir) {
73646
73942
  let js;
73647
73943
  for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
73648
73944
  try {
73649
- js = readFileSync79(join64(outDir, candidate), "utf8");
73945
+ js = readFileSync80(join65(outDir, candidate), "utf8");
73650
73946
  break;
73651
73947
  } catch {
73652
73948
  }
@@ -73677,7 +73973,7 @@ async function producedWidgetFamilies(dir) {
73677
73973
  }
73678
73974
  return { families, source: "dist/bundles" };
73679
73975
  }
73680
- var boardOpen = (dir) => existsSync66(join64(dir, ".himi", "studio", "index.html"));
73976
+ var boardOpen = (dir) => existsSync67(join65(dir, ".himi", "studio", "index.html"));
73681
73977
  var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
73682
73978
  async function leaveForBoard(dir, record2, value) {
73683
73979
  if (!boardOpen(dir)) return;
@@ -73701,7 +73997,7 @@ async function liveMapFor(dir) {
73701
73997
  }
73702
73998
  var commandScratch = new AsyncLocalStorage();
73703
73999
  function commandScratchDir(prefix) {
73704
- const dir = mkdtempSync4(join64(tmpdir5(), prefix));
74000
+ const dir = mkdtempSync4(join65(tmpdir5(), prefix));
73705
74001
  commandScratch.getStore()?.push(dir);
73706
74002
  return dir;
73707
74003
  }
@@ -73712,7 +74008,7 @@ async function run(argv, io = defaultIO, deps = {}) {
73712
74008
  code = await commandScratch.run(scratch, () => runCommand(argv, io, deps));
73713
74009
  } finally {
73714
74010
  for (const dir of scratch) try {
73715
- rmSync15(dir, { recursive: true, force: true });
74011
+ rmSync16(dir, { recursive: true, force: true });
73716
74012
  } catch {
73717
74013
  }
73718
74014
  }
@@ -73980,7 +74276,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
73980
74276
  return 2;
73981
74277
  }
73982
74278
  const template = str8(flags.template);
73983
- const parentDir = resolve52(str8(flags.dir) ?? process.cwd());
74279
+ const parentDir = resolve53(str8(flags.dir) ?? process.cwd());
73984
74280
  const withAgentFiles = async (dir) => {
73985
74281
  const seeded = await seedAgentFilesFor(dir, flags);
73986
74282
  if (!seeded.agent || "error" in seeded.agent) return seeded;
@@ -73993,7 +74289,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
73993
74289
  const owed = openApprovals2(readApprovals2(dir).events).length;
73994
74290
  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`);
73995
74291
  }
73996
- const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync66(join64(parentDir, f)));
74292
+ const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync67(join65(parentDir, f)));
73997
74293
  if (planInParent.length) {
73998
74294
  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}`);
73999
74295
  }
@@ -74141,11 +74437,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74141
74437
  return 2;
74142
74438
  }
74143
74439
  }
74144
- const appDir3 = resolve52(str8(flags.dir) ?? process.cwd());
74145
- const sourceDir = resolve52(str8(flags["source-dir"]) ?? appDir3);
74440
+ const appDir3 = resolve53(str8(flags.dir) ?? process.cwd());
74441
+ const sourceDir = resolve53(str8(flags["source-dir"]) ?? appDir3);
74146
74442
  let meta;
74147
74443
  try {
74148
- meta = JSON.parse(readFileSync79(join64(sourceDir, TEMPLATE_META_FILE), "utf8"));
74444
+ meta = JSON.parse(readFileSync80(join65(sourceDir, TEMPLATE_META_FILE), "utf8"));
74149
74445
  } catch {
74150
74446
  io.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
74151
74447
  return 2;
@@ -74155,7 +74451,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74155
74451
  return 2;
74156
74452
  }
74157
74453
  try {
74158
- const appearance = extractTemplateAppearance(JSON.parse(readFileSync79(join64(sourceDir, "tokens.json"), "utf8")));
74454
+ const appearance = extractTemplateAppearance(JSON.parse(readFileSync80(join65(sourceDir, "tokens.json"), "utf8")));
74159
74455
  meta = { ...appearance, ...meta };
74160
74456
  } catch {
74161
74457
  }
@@ -74177,14 +74473,14 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74177
74473
  const force = flags.force === true;
74178
74474
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
74179
74475
  const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
74180
- const out2 = mkdtempSync4(join64(tmpdir5(), "himi-template-"));
74476
+ const out2 = mkdtempSync4(join65(tmpdir5(), "himi-template-"));
74181
74477
  publishScratch.push(out2);
74182
74478
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
74183
74479
  const outcome = await buildReleaseFromContent2(buildDir, out2, {
74184
74480
  ...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
74185
74481
  collect: { lint: true, strict }
74186
74482
  });
74187
- const scaffoldSourceFindings = resolve52(sourceDir) === resolve52(appDir3) ? [] : [
74483
+ const scaffoldSourceFindings = resolve53(sourceDir) === resolve53(appDir3) ? [] : [
74188
74484
  ...tokenColorIssues(sourceDir),
74189
74485
  ...surfaceIssues(sourceDir, void 0, strict),
74190
74486
  ...await fontIssues(sourceDir, strict),
@@ -74227,11 +74523,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74227
74523
  }));
74228
74524
  return 1;
74229
74525
  }
74230
- const iconPath = str8(flags.icon) ? resolve52(str8(flags.icon)) : templateIconPath(name);
74526
+ const iconPath = str8(flags.icon) ? resolve53(str8(flags.icon)) : templateIconPath(name);
74231
74527
  let iconHash;
74232
74528
  if (iconPath) {
74233
74529
  try {
74234
- const bytes2 = readFileSync79(iconPath);
74530
+ const bytes2 = readFileSync80(iconPath);
74235
74531
  payload.icon = bytes2.toString("base64");
74236
74532
  iconHash = createHash31("sha256").update(bytes2).digest("hex");
74237
74533
  } catch {
@@ -74404,7 +74700,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74404
74700
  } finally {
74405
74701
  for (const dir of publishScratch) {
74406
74702
  try {
74407
- rmSync15(dir, { recursive: true, force: true });
74703
+ rmSync16(dir, { recursive: true, force: true });
74408
74704
  } catch (e) {
74409
74705
  io.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e.message}` }));
74410
74706
  }
@@ -74438,12 +74734,12 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74438
74734
  print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
74439
74735
  return 2;
74440
74736
  }
74441
- const { readdirSync: readdirSync31, existsSync: fileExists } = await import("node:fs");
74737
+ const { readdirSync: readdirSync32, existsSync: fileExists } = await import("node:fs");
74442
74738
  const { join: pathJoin } = await import("node:path");
74443
74739
  const targets = [];
74444
74740
  const t5 = pathJoin(dir, "tier5-src");
74445
74741
  if (fileExists(t5)) {
74446
- for (const d of readdirSync31(t5, { withFileTypes: true })) {
74742
+ for (const d of readdirSync32(t5, { withFileTypes: true })) {
74447
74743
  if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
74448
74744
  }
74449
74745
  }
@@ -74518,7 +74814,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74518
74814
  const path2 = dpxSessionTokenPath();
74519
74815
  let raw;
74520
74816
  try {
74521
- raw = readFileSync79(path2, "utf8");
74817
+ raw = readFileSync80(path2, "utf8");
74522
74818
  } catch {
74523
74819
  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`);
74524
74820
  }
@@ -74649,32 +74945,37 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74649
74945
  return 1;
74650
74946
  }
74651
74947
  const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
74652
- const dir = resolve52(out2);
74948
+ const dir = resolve53(out2);
74653
74949
  const files = himiPluginFiles2(skills.skillMd);
74654
74950
  for (const f of files) {
74655
- mkdirSync32(dirname36(join64(dir, f.path)), { recursive: true });
74656
- writeFileSync29(join64(dir, f.path), f.text);
74951
+ mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
74952
+ writeFileSync30(join65(dir, f.path), f.text);
74657
74953
  }
74658
74954
  print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
74659
74955
  return 0;
74660
74956
  }
74661
74957
  const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
74662
- await startMcpServer2({ run, version: cliVersion() });
74958
+ await startMcpServer2({
74959
+ run,
74960
+ version: cliVersion(),
74961
+ withFiles: flags["with-files"] === true,
74962
+ ...process.env.HIMI_WORKSPACE ? { workspace: resolve53(process.env.HIMI_WORKSPACE) } : {}
74963
+ });
74663
74964
  return 0;
74664
74965
  }
74665
74966
  case "studio": {
74666
74967
  const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
74667
74968
  const dir = contentDir(flags);
74668
- if (!existsSync66(join64(dir, "himalaya.content.json"))) {
74969
+ if (!existsSync67(join65(dir, "himalaya.content.json"))) {
74669
74970
  io.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
74670
74971
  return 2;
74671
74972
  }
74672
74973
  if (pos[1] === "reel") {
74673
74974
  const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
74674
- const out2 = resolve52(str8(flags.out) ?? join64(dir, ".himi", "making-of.html"));
74975
+ const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
74675
74976
  const { html, plan } = buildReel2(dir);
74676
- mkdirSync32(dirname36(out2), { recursive: true });
74677
- writeFileSync29(out2, html);
74977
+ mkdirSync33(dirname37(out2), { recursive: true });
74978
+ writeFileSync30(out2, html);
74678
74979
  const { pathToFileURL: pathToFileURL9 } = await import("node:url");
74679
74980
  const url2 = pathToFileURL9(out2).href;
74680
74981
  const open2 = flags["no-open"] !== true;
@@ -74743,7 +75044,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74743
75044
  } = await Promise.resolve().then(() => (init_progress(), progress_exports));
74744
75045
  const dir = contentDir(flags);
74745
75046
  const journal2 = journalPath2(dir);
74746
- const isContentPackage = existsSync66(join64(dir, "himalaya.content.json"));
75047
+ const isContentPackage = existsSync67(join65(dir, "himalaya.content.json"));
74747
75048
  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" };
74748
75049
  const message = pos.slice(1).join(" ").trim();
74749
75050
  const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
@@ -74892,7 +75193,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74892
75193
  case "test": {
74893
75194
  const dir = contentDir(flags);
74894
75195
  const structuredOutput = flags.json === true || io.isTTY !== true;
74895
- if (existsSync66(join64(dir, "functions"))) {
75196
+ if (existsSync67(join65(dir, "functions"))) {
74896
75197
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
74897
75198
  const loaded = await loadFunctionsApp2(dir);
74898
75199
  const results = [];
@@ -75024,7 +75325,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75024
75325
  io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
75025
75326
  return 2;
75026
75327
  }
75027
- const sources = collectWorkerSources2(join64(dir, "tier5-src"), screen.bundleName);
75328
+ const sources = collectWorkerSources2(join65(dir, "tier5-src"), screen.bundleName);
75028
75329
  if (!sources) {
75029
75330
  io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
75030
75331
  return 2;
@@ -75201,7 +75502,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75201
75502
  const sp = await runShotsPass2({
75202
75503
  descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
75203
75504
  tokens: outcome.tokens,
75204
- outDir: join64(dir, ".himi", "shots"),
75505
+ outDir: join65(dir, ".himi", "shots"),
75205
75506
  width: 390,
75206
75507
  layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
75207
75508
  ...budgetMs ? { budgetMs } : {},
@@ -75211,7 +75512,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75211
75512
  renderDescriptorWeb: renderDescriptorWeb2,
75212
75513
  renderPngBatch: renderPngBatch2,
75213
75514
  writePng: (path2, base64) => writePngFile(path2, base64),
75214
- clearDir: (d) => rmSync15(d, { recursive: true, force: true })
75515
+ clearDir: (d) => rmSync16(d, { recursive: true, force: true })
75215
75516
  }
75216
75517
  });
75217
75518
  writtenShots = sp.written;
@@ -75239,7 +75540,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75239
75540
  releaseId: result.releaseId,
75240
75541
  releasePayload: release,
75241
75542
  descriptors: attestedDescriptors,
75242
- screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join64(dir, ".himi", "shots", name)])),
75543
+ screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join65(dir, ".himi", "shots", name)])),
75243
75544
  coverage: {
75244
75545
  screens: crawledScreens.size,
75245
75546
  actionsDispatched: result.actions.exercised,
@@ -75350,7 +75651,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75350
75651
  return 2;
75351
75652
  }
75352
75653
  try {
75353
- const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync79(stateArg.replace(/^@/, ""), "utf8");
75654
+ const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync80(stateArg.replace(/^@/, ""), "utf8");
75354
75655
  injectedState = JSON.parse(raw);
75355
75656
  } catch (e) {
75356
75657
  io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
@@ -75365,7 +75666,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75365
75666
  return 2;
75366
75667
  }
75367
75668
  try {
75368
- const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync79(inputArg.replace(/^@/, ""), "utf8");
75669
+ const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync80(inputArg.replace(/^@/, ""), "utf8");
75369
75670
  const parsed = JSON.parse(raw);
75370
75671
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
75371
75672
  injectedInput = parsed;
@@ -75428,11 +75729,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75428
75729
  const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
75429
75730
  let pngFile;
75430
75731
  let attestationPngFile;
75431
- const shotPath = join64(dir, ".himi", "shots", `${screenId}.png`);
75732
+ const shotPath = join65(dir, ".himi", "shots", `${screenId}.png`);
75432
75733
  const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
75433
75734
  if (pngTarget && r.pngBase64) {
75434
75735
  pngFile = writePngFile(pngTarget, r.pngBase64);
75435
- attestationPngFile = resolve52(pngTarget) === resolve52(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75736
+ attestationPngFile = resolve53(pngTarget) === resolve53(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75436
75737
  }
75437
75738
  if (renderWidth !== void 0 && r.renderable) {
75438
75739
  recordRenderWidth(dir, {
@@ -75768,7 +76069,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75768
76069
  return 2;
75769
76070
  }
75770
76071
  const renamed = str8(flags.name);
75771
- const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
76072
+ const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
75772
76073
  const replace = flags.replace === true;
75773
76074
  const force = replace || flags.force === true;
75774
76075
  const linked = symlinkDestinationIssue(dest);
@@ -75776,20 +76077,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75776
76077
  io.error(JSON.stringify(linked));
75777
76078
  return 1;
75778
76079
  }
75779
- if (existsSync66(dest)) {
75780
- if (!statSync18(dest).isDirectory()) {
76080
+ if (existsSync67(dest)) {
76081
+ if (!statSync19(dest).isDirectory()) {
75781
76082
  io.error(JSON.stringify({
75782
76083
  error: `${dest} exists and is not a directory`,
75783
76084
  hint: "pass --out/--name to land somewhere else, or remove the file"
75784
76085
  }));
75785
76086
  return 1;
75786
76087
  }
75787
- const occupied = readdirSync30(dest).length > 0;
76088
+ const occupied = readdirSync31(dest).length > 0;
75788
76089
  if (occupied && !force) {
75789
76090
  io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
75790
76091
  return 1;
75791
76092
  }
75792
- if (replace && occupied && !existsSync66(join64(dest, "himalaya.content.json"))) {
76093
+ if (replace && occupied && !existsSync67(join65(dest, "himalaya.content.json"))) {
75793
76094
  io.error(JSON.stringify({
75794
76095
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
75795
76096
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -75956,7 +76257,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75956
76257
  const manifest = outcome.manifest;
75957
76258
  const payload = await loadReleaseFromDir(declared, out2);
75958
76259
  const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
75959
- const contentRel = relative13(process.cwd(), dir) || ".";
76260
+ const contentRel = relative14(process.cwd(), dir) || ".";
75960
76261
  const contentArg2 = shellQuote3(contentRel);
75961
76262
  if (onlyRaw !== void 0) {
75962
76263
  const onlyDraft = flags.draft === true;
@@ -76427,7 +76728,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76427
76728
  return 2;
76428
76729
  }
76429
76730
  try {
76430
- const res = writePack(resolve52(releaseDir), only, resolve52(str8(flags.out) ?? process.cwd()));
76731
+ const res = writePack(resolve53(releaseDir), only, resolve53(str8(flags.out) ?? process.cwd()));
76431
76732
  print({
76432
76733
  ok: true,
76433
76734
  app: res.app,
@@ -76476,7 +76777,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76476
76777
  }
76477
76778
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76478
76779
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
76479
- const built = mkdtempSync4(join64(tmpdir5(), "himi-pack-"));
76780
+ const built = mkdtempSync4(join65(tmpdir5(), "himi-pack-"));
76480
76781
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
76481
76782
  const outcome = await buildReleaseFromContent2(dir, built, {
76482
76783
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -76493,12 +76794,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76493
76794
  ...await navIssues2(dir, strict)
76494
76795
  ]);
76495
76796
  if (hasErrors && !force) {
76496
- rmSync15(built, { recursive: true, force: true });
76797
+ rmSync16(built, { recursive: true, force: true });
76497
76798
  print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
76498
76799
  return 1;
76499
76800
  }
76500
76801
  try {
76501
- const res = writePack(built, app, resolve52(str8(flags.out) ?? dir), sourceArchive);
76802
+ const res = writePack(built, app, resolve53(str8(flags.out) ?? dir), sourceArchive);
76502
76803
  print({
76503
76804
  ok: true,
76504
76805
  app: res.app,
@@ -76529,7 +76830,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76529
76830
  io.error(JSON.stringify({ error: e.message }));
76530
76831
  return 1;
76531
76832
  } finally {
76532
- rmSync15(built, { recursive: true, force: true });
76833
+ rmSync16(built, { recursive: true, force: true });
76533
76834
  }
76534
76835
  }
76535
76836
  // ---- himi import — turn a dev .himi back into an editable content package ----
@@ -76543,7 +76844,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76543
76844
  const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
76544
76845
  let opened;
76545
76846
  try {
76546
- opened = openPackageFile2(resolve52(file));
76847
+ opened = openPackageFile2(resolve53(file));
76547
76848
  } catch (e) {
76548
76849
  io.error(JSON.stringify({ error: e.message }));
76549
76850
  return 1;
@@ -76556,7 +76857,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76556
76857
  io.error(JSON.stringify({
76557
76858
  ok: false,
76558
76859
  error: "app_source_not_in_package",
76559
- detail: `${resolve52(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76860
+ detail: `${resolve53(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76560
76861
  hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
76561
76862
  }));
76562
76863
  return 1;
@@ -76579,7 +76880,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76579
76880
  return 1;
76580
76881
  }
76581
76882
  }
76582
- const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76883
+ const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76583
76884
  const issue2 = restoreDestinationIssue(dest, flags.force === true);
76584
76885
  if (issue2) {
76585
76886
  io.error(JSON.stringify(issue2));
@@ -76666,7 +76967,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76666
76967
  }
76667
76968
  try {
76668
76969
  const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
76669
- const opened = openPackageFile2(resolve52(file));
76970
+ const opened = openPackageFile2(resolve53(file));
76670
76971
  if (!opened.validation.ok || !opened.header) {
76671
76972
  io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
76672
76973
  return 1;
@@ -76676,12 +76977,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76676
76977
  io.error(JSON.stringify({
76677
76978
  ok: false,
76678
76979
  error: "refusing to share a package that carries the app's source",
76679
- detail: `${resolve52(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
76980
+ detail: `${resolve53(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
76680
76981
  hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
76681
76982
  }));
76682
76983
  return 1;
76683
76984
  }
76684
- const archive = readFileSync79(resolve52(file));
76985
+ const archive = readFileSync80(resolve53(file));
76685
76986
  const result = await client2().createPackageShare({
76686
76987
  app: opened.header.app,
76687
76988
  releaseId: opened.header.releaseId,
@@ -76757,11 +77058,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76757
77058
  const app = await appId(dir2);
76758
77059
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76759
77060
  const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
76760
- temp = mkdtempSync4(join64(tmpdir5(), "himi-run-build-"));
77061
+ temp = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
76761
77062
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
76762
77063
  const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
76763
77064
  servedMissing = initial.missingBundles;
76764
- source = join64(temp, app);
77065
+ source = join65(temp, app);
76765
77066
  }
76766
77067
  const chromeArg = str8(flags.chrome) ?? "preview";
76767
77068
  if (chromeArg !== "preview" && chromeArg !== "app") {
@@ -76797,7 +77098,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76797
77098
  if (!recordKit) return;
76798
77099
  startedAt = (/* @__PURE__ */ new Date()).toISOString();
76799
77100
  const failure = record2(served2, { ok: true, at: startedAt });
76800
- if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join64(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
77101
+ if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join65(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
76801
77102
  await refreshBoard();
76802
77103
  };
76803
77104
  const retract = async () => {
@@ -76820,9 +77121,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76820
77121
  });
76821
77122
  await announce(run2);
76822
77123
  print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
76823
- await new Promise((resolve53) => {
77124
+ await new Promise((resolve54) => {
76824
77125
  const stop = () => {
76825
- void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve53()));
77126
+ void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
76826
77127
  };
76827
77128
  process.once("SIGINT", stop);
76828
77129
  process.once("SIGTERM", stop);
@@ -76831,7 +77132,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76831
77132
  }
76832
77133
  const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
76833
77134
  const bus = watchKit ? new watchKit.ReloadBus() : void 0;
76834
- if (watch2) served = mkdtempSync4(join64(tmpdir5(), "himi-run-served-"));
77135
+ if (watch2) served = mkdtempSync4(join65(tmpdir5(), "himi-run-served-"));
76835
77136
  const running = await runPackage2(source, {
76836
77137
  port,
76837
77138
  chrome: chromeArg,
@@ -76860,8 +77161,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76860
77161
  await announce(running);
76861
77162
  if (watchKit && bus) {
76862
77163
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76863
- const live2 = join64(running.releaseRoot, running.app);
76864
- const manifestOf = (tree) => JSON.parse(readFileSync79(join64(tree, "release-manifest.json"), "utf8"));
77164
+ const live2 = join65(running.releaseRoot, running.app);
77165
+ const manifestOf = (tree) => JSON.parse(readFileSync80(join65(tree, "release-manifest.json"), "utf8"));
76865
77166
  let current = manifestOf(live2);
76866
77167
  const failed2 = async (message) => {
76867
77168
  if (stopping) return;
@@ -76872,7 +77173,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76872
77173
  };
76873
77174
  rebuild = watchKit.serialize(async () => {
76874
77175
  const t0 = Date.now();
76875
- const next = mkdtempSync4(join64(tmpdir5(), "himi-run-build-"));
77176
+ const next = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
76876
77177
  try {
76877
77178
  const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
76878
77179
  if (bres.compileErrors.length) {
@@ -76889,18 +77190,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76889
77190
  return;
76890
77191
  }
76891
77192
  if (stopping) return;
76892
- const fresh = manifestOf(join64(next, running.app));
77193
+ const fresh = manifestOf(join65(next, running.app));
76893
77194
  const diff = watchKit.diffReleases(current, fresh);
76894
77195
  const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
76895
- const changes = describeChanges2(live2, join64(next, running.app), diff);
77196
+ const changes = describeChanges2(live2, join65(next, running.app), diff);
76896
77197
  const retired = `${live2}.retired-${Date.now()}`;
76897
77198
  renameSync7(live2, retired);
76898
77199
  try {
76899
- renameSync7(join64(next, running.app), live2);
77200
+ renameSync7(join65(next, running.app), live2);
76900
77201
  } catch {
76901
- cpSync3(join64(next, running.app), live2, { recursive: true });
77202
+ cpSync3(join65(next, running.app), live2, { recursive: true });
76902
77203
  }
76903
- rmSync15(retired, { recursive: true, force: true });
77204
+ rmSync16(retired, { recursive: true, force: true });
76904
77205
  current = fresh;
76905
77206
  servedMissing = outcome.missingBundles;
76906
77207
  for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
@@ -76910,7 +77211,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76910
77211
  } catch (e) {
76911
77212
  await failed2(e.message.split("\n")[0]);
76912
77213
  } finally {
76913
- rmSync15(next, { recursive: true, force: true });
77214
+ rmSync16(next, { recursive: true, force: true });
76914
77215
  }
76915
77216
  });
76916
77217
  watcher2 = watchKit.watchContent(dir, () => {
@@ -76978,9 +77279,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76978
77279
  io.error(JSON.stringify({ error: e.message }));
76979
77280
  return 1;
76980
77281
  } finally {
76981
- if (temp) rmSync15(temp, { recursive: true, force: true });
76982
- if (served) rmSync15(served, { recursive: true, force: true });
76983
- if (browserCopy) rmSync15(browserCopy, { recursive: true, force: true });
77282
+ if (temp) rmSync16(temp, { recursive: true, force: true });
77283
+ if (served) rmSync16(served, { recursive: true, force: true });
77284
+ if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
76984
77285
  }
76985
77286
  }
76986
77287
  case "preview": {
@@ -77522,7 +77823,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77522
77823
  io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
77523
77824
  return 2;
77524
77825
  }
77525
- if (!existsSync66(file)) {
77826
+ if (!existsSync67(file)) {
77526
77827
  io.error(JSON.stringify({ error: `no such file: ${file}` }));
77527
77828
  return 2;
77528
77829
  }
@@ -77578,7 +77879,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77578
77879
  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."
77579
77880
  };
77580
77881
  if (kind === "tokens" || kind === "app-config") {
77581
- const body = readFileSync79(file, "utf8");
77882
+ const body = readFileSync80(file, "utf8");
77582
77883
  const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
77583
77884
  return runReleasePatch({
77584
77885
  ...common,
@@ -77593,7 +77894,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77593
77894
  io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
77594
77895
  return 2;
77595
77896
  }
77596
- const descriptor = readFileSync79(file, "utf8");
77897
+ const descriptor = readFileSync80(file, "utf8");
77597
77898
  try {
77598
77899
  JSON.parse(descriptor);
77599
77900
  } catch (e) {
@@ -77633,7 +77934,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77633
77934
  extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
77634
77935
  });
77635
77936
  }
77636
- const bytes2 = readFileSync79(file);
77937
+ const bytes2 = readFileSync80(file);
77637
77938
  const sha = createHash31("sha256").update(bytes2).digest("hex");
77638
77939
  const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
77639
77940
  if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
@@ -77777,7 +78078,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77777
78078
  }
77778
78079
  let def;
77779
78080
  try {
77780
- const parsed = JSON.parse(arg.startsWith("@") ? readFileSync79(arg.slice(1), "utf8") : arg);
78081
+ const parsed = JSON.parse(arg.startsWith("@") ? readFileSync80(arg.slice(1), "utf8") : arg);
77781
78082
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
77782
78083
  io.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
77783
78084
  return 2;
@@ -78241,7 +78542,7 @@ ${label2}`);
78241
78542
  const platform = str8(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
78242
78543
  {
78243
78544
  const distDir = contentDir(flags);
78244
- if (existsSync66(join64(distDir, "himalaya.content.json"))) {
78545
+ if (existsSync67(join65(distDir, "himalaya.content.json"))) {
78245
78546
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
78246
78547
  const errors = issues.filter((i) => i.severity === "error");
78247
78548
  for (const i of issues.filter((i2) => i2.severity === "warning")) {
@@ -78527,7 +78828,7 @@ ${label2}`);
78527
78828
  const dpxPath = dpxSessionTokenPath();
78528
78829
  let dpx;
78529
78830
  try {
78530
- dpx = readFileSync79(dpxPath, "utf8").trim();
78831
+ dpx = readFileSync80(dpxPath, "utf8").trim();
78531
78832
  } catch {
78532
78833
  io.error(JSON.stringify({ error: `no dpx session at ${dpxPath} \u2014 run \`dpx auth login\` then \`dpx auth token > ${dpxPath}\` (dpx 2.x keeps its own state in ~/.dpx/auth.json and does NOT write the legacy session file), or omit --dpx` }));
78533
78834
  return 1;
@@ -78935,7 +79236,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
78935
79236
  const path2 = dpxSessionTokenPath();
78936
79237
  let raw;
78937
79238
  try {
78938
- raw = readFileSync79(path2, "utf8");
79239
+ raw = readFileSync80(path2, "utf8");
78939
79240
  } catch {
78940
79241
  io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
78941
79242
  return 1;