@wix/himalaya-cli 0.1114.0 → 0.1116.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) {
@@ -14806,8 +14806,8 @@ function matchWeightCss(available, desired) {
14806
14806
  const upFrom = (n) => sorted2.find((w) => w >= n);
14807
14807
  const downFrom = (n) => [...sorted2].reverse().find((w) => w <= n);
14808
14808
  if (desired >= 400 && desired <= 500) {
14809
- const within = sorted2.find((w) => w >= desired && w <= 500);
14810
- return within ?? downFrom(desired) ?? upFrom(desired);
14809
+ const within2 = sorted2.find((w) => w >= desired && w <= 500);
14810
+ return within2 ?? downFrom(desired) ?? upFrom(desired);
14811
14811
  }
14812
14812
  if (desired < 400) return downFrom(desired) ?? upFrom(desired);
14813
14813
  return upFrom(desired) ?? downFrom(desired);
@@ -15930,29 +15930,29 @@ function matchRuleEx(rules, method, path2, ctx = {}) {
15930
15930
  }
15931
15931
  if (m.query) {
15932
15932
  const q = ctx.query ?? {};
15933
- let ok = true;
15933
+ let ok2 = true;
15934
15934
  for (const [k, v] of Object.entries(m.query)) {
15935
15935
  if (q[k] !== v) {
15936
- ok = false;
15936
+ ok2 = false;
15937
15937
  break;
15938
15938
  }
15939
15939
  captures[`query.${k}`] = q[k];
15940
15940
  }
15941
- if (!ok) continue;
15941
+ if (!ok2) continue;
15942
15942
  for (const [k, v] of Object.entries(q)) captures[`query.${k}`] = v;
15943
15943
  } else if (ctx.query) {
15944
15944
  for (const [k, v] of Object.entries(ctx.query)) captures[`query.${k}`] = v;
15945
15945
  }
15946
15946
  if (m.headers) {
15947
15947
  const hh = lc(ctx.headers);
15948
- let ok = true;
15948
+ let ok2 = true;
15949
15949
  for (const [k, v] of Object.entries(m.headers)) {
15950
15950
  if (hh[k.toLowerCase()] !== v) {
15951
- ok = false;
15951
+ ok2 = false;
15952
15952
  break;
15953
15953
  }
15954
15954
  }
15955
- if (!ok) continue;
15955
+ if (!ok2) continue;
15956
15956
  }
15957
15957
  if (m.bodyContains && !(ctx.body ?? "").includes(m.bodyContains)) continue;
15958
15958
  return { rule: r, captures };
@@ -18574,11 +18574,11 @@ function appleScriptString(s) {
18574
18574
  function runNotifier(cmd, args) {
18575
18575
  return new Promise((done) => {
18576
18576
  let settled = false;
18577
- const finish2 = (ok) => {
18577
+ const finish2 = (ok2) => {
18578
18578
  if (!settled) {
18579
18579
  settled = true;
18580
18580
  clearTimeout(timer);
18581
- done(ok);
18581
+ done(ok2);
18582
18582
  }
18583
18583
  };
18584
18584
  const child = spawn3(cmd, args, { stdio: "ignore" });
@@ -19465,10 +19465,10 @@ var init_preview = __esm({
19465
19465
  }
19466
19466
  },
19467
19467
  kill: (pid, signal) => process.kill(pid, signal),
19468
- portFree: (port) => new Promise((resolve53) => {
19468
+ portFree: (port) => new Promise((resolve54) => {
19469
19469
  const s = createServer2();
19470
- s.once("error", () => resolve53(false));
19471
- s.listen(port, "127.0.0.1", () => s.close(() => resolve53(true)));
19470
+ s.once("error", () => resolve54(false));
19471
+ s.listen(port, "127.0.0.1", () => s.close(() => resolve54(true)));
19472
19472
  }),
19473
19473
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
19474
19474
  servingIdentity: async (origin) => {
@@ -20612,7 +20612,7 @@ async function injectRequest(listener, request) {
20612
20612
  req.headers.host ??= url.host;
20613
20613
  if (body && body.length > 0) req.push(body);
20614
20614
  req.push(null);
20615
- return await new Promise((resolve53, reject) => {
20615
+ return await new Promise((resolve54, reject) => {
20616
20616
  const streamed = () => {
20617
20617
  queueMicrotask(() => {
20618
20618
  req.emit("close");
@@ -20628,7 +20628,7 @@ async function injectRequest(listener, request) {
20628
20628
  else headers2.set(name, value);
20629
20629
  }
20630
20630
  const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
20631
- resolve53(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20631
+ resolve54(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20632
20632
  }, streamed);
20633
20633
  res.on("inject-error", reject);
20634
20634
  try {
@@ -21334,7 +21334,7 @@ function redactBodyString(body) {
21334
21334
  } catch {
21335
21335
  }
21336
21336
  }
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}`);
21337
+ 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
21338
  }
21339
21339
  function createWixGatewayState() {
21340
21340
  return { mode: "record", rules: [], traffic: [], clients: /* @__PURE__ */ new Set(), seq: 0, ruleSeq: 0 };
@@ -23080,10 +23080,10 @@ function recordDeviceLayout(payload) {
23080
23080
  }
23081
23081
  async function handleDeviceLayoutReport(res, payload) {
23082
23082
  const screenId = recordDeviceLayout(payload);
23083
- const ok = screenId !== null;
23084
- res.statusCode = ok ? 200 : 400;
23083
+ const ok2 = screenId !== null;
23084
+ res.statusCode = ok2 ? 200 : 400;
23085
23085
  res.setHeader("content-type", "application/json");
23086
- res.end(JSON.stringify(ok ? { status: "ok", screenId } : { error: "invalid_layout" }));
23086
+ res.end(JSON.stringify(ok2 ? { status: "ok", screenId } : { error: "invalid_layout" }));
23087
23087
  return screenId;
23088
23088
  }
23089
23089
  async function handlePreviewHitTest(res, payload) {
@@ -23162,12 +23162,12 @@ function finalizeRecording(key2, rec) {
23162
23162
  if (rec.finalize) return rec.finalize;
23163
23163
  rec.finalize = (async () => {
23164
23164
  clearTimeout(rec.autoStop);
23165
- await new Promise((resolve53) => {
23165
+ await new Promise((resolve54) => {
23166
23166
  let done = false;
23167
23167
  const finish2 = () => {
23168
23168
  if (!done) {
23169
23169
  done = true;
23170
- resolve53();
23170
+ resolve54();
23171
23171
  }
23172
23172
  };
23173
23173
  rec.child.once("close", finish2);
@@ -23278,7 +23278,7 @@ var init_preview2 = __esm({
23278
23278
  DEVICE_LIST_TIMEOUT_MS = 5e3;
23279
23279
  defaultRunner2 = {
23280
23280
  capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
23281
- return new Promise((resolve53, reject) => {
23281
+ return new Promise((resolve54, reject) => {
23282
23282
  const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
23283
23283
  const out2 = [];
23284
23284
  const err = [];
@@ -23300,7 +23300,7 @@ var init_preview2 = __esm({
23300
23300
  child.stderr.on("data", (b) => err.push(b));
23301
23301
  child.on("error", (e) => settle(reject, e));
23302
23302
  child.on("close", (code) => {
23303
- if (code === 0) settle(resolve53, Buffer.concat(out2));
23303
+ if (code === 0) settle(resolve54, Buffer.concat(out2));
23304
23304
  else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
23305
23305
  });
23306
23306
  });
@@ -24632,13 +24632,13 @@ function validate(rule, rawValue) {
24632
24632
  return { rule: "type", type: rule.type };
24633
24633
  }
24634
24634
  if (rule.regex) {
24635
- let ok;
24635
+ let ok2;
24636
24636
  try {
24637
- ok = new RegExp(`^(?:${rule.regex})$`).test(value);
24637
+ ok2 = new RegExp(`^(?:${rule.regex})$`).test(value);
24638
24638
  } catch {
24639
- ok = true;
24639
+ ok2 = true;
24640
24640
  }
24641
- if (!ok) return { rule: "regex" };
24641
+ if (!ok2) return { rule: "regex" };
24642
24642
  }
24643
24643
  if (typeof rule.minLength === "number" && rule.minLength > 0 && value.length < rule.minLength) {
24644
24644
  return { rule: "minLength", limit: rule.minLength };
@@ -27552,12 +27552,12 @@ function createRicosHostSession(o) {
27552
27552
  flush() {
27553
27553
  if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
27554
27554
  const requestId2 = newId();
27555
- return new Promise((resolve53) => {
27555
+ return new Promise((resolve54) => {
27556
27556
  const timer = t.setTimeout(() => {
27557
27557
  flushes.delete(requestId2);
27558
- resolve53(null);
27558
+ resolve54(null);
27559
27559
  }, flushMs);
27560
- flushes.set(requestId2, { resolve: resolve53, timer });
27560
+ flushes.set(requestId2, { resolve: resolve54, timer });
27561
27561
  o.send({ v: 1, type: "requestContent", requestId: requestId2 });
27562
27562
  });
27563
27563
  },
@@ -27610,7 +27610,7 @@ async function runRicosImageUpload(o) {
27610
27610
  };
27611
27611
  session.insertMediaPlaceholder(requestId2);
27612
27612
  try {
27613
- const entry = await new Promise((resolve53) => {
27613
+ const entry = await new Promise((resolve54) => {
27614
27614
  let done = false;
27615
27615
  let unsub = () => {
27616
27616
  };
@@ -27619,7 +27619,7 @@ async function runRicosImageUpload(o) {
27619
27619
  done = true;
27620
27620
  t.clearTimeout(timer);
27621
27621
  queueMicrotask(() => unsub());
27622
- resolve53(v);
27622
+ resolve54(v);
27623
27623
  };
27624
27624
  const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
27625
27625
  unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
@@ -27638,10 +27638,10 @@ async function runRicosImageUpload(o) {
27638
27638
  } catch {
27639
27639
  return fail2("read");
27640
27640
  }
27641
- const sep17 = entry.uploadUrl.includes("?") ? "&" : "?";
27641
+ const sep18 = entry.uploadUrl.includes("?") ? "&" : "?";
27642
27642
  let res;
27643
27643
  try {
27644
- res = await deps.fetch(`${entry.uploadUrl}${sep17}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
27644
+ res = await deps.fetch(`${entry.uploadUrl}${sep18}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
27645
27645
  } catch {
27646
27646
  return fail2("put");
27647
27647
  }
@@ -27656,14 +27656,14 @@ async function runRicosImageUpload(o) {
27656
27656
  const d = root.file && typeof root.file === "object" ? root.file : root;
27657
27657
  const id = typeof d.id === "string" ? d.id : "";
27658
27658
  if (!id) return fail2("bad_descriptor");
27659
- const ok = session.resolveMedia(requestId2, {
27659
+ const ok2 = session.resolveMedia(requestId2, {
27660
27660
  id,
27661
27661
  url: typeof d.url === "string" ? d.url : "",
27662
27662
  ...typeof d.width === "number" ? { width: d.width } : {},
27663
27663
  ...typeof d.height === "number" ? { height: d.height } : {},
27664
27664
  mimeType: file.mimeType
27665
27665
  });
27666
- return ok ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
27666
+ return ok2 ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
27667
27667
  } finally {
27668
27668
  deps.dispatch({ actionId: `tier5.${svc}.clearUpload`, args: { requestId: requestId2 } });
27669
27669
  }
@@ -29550,8 +29550,8 @@ function ensureCountUpRuntime() {
29550
29550
  const neg = fixed.startsWith("-");
29551
29551
  const body = neg ? fixed.slice(1) : fixed;
29552
29552
  const [int2, frac] = body.split(".");
29553
- const sep17 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
29554
- return (neg ? "-" : "") + sep17 + (frac ? "." + frac : "");
29553
+ const sep18 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
29554
+ return (neg ? "-" : "") + sep18 + (frac ? "." + frac : "");
29555
29555
  };
29556
29556
  const animateEl = (el) => {
29557
29557
  const node = el;
@@ -30372,24 +30372,24 @@ function usesSchematicRoute(props) {
30372
30372
  const hasRouteFeed = typeof props.routePath === "string" && props.routePath !== "";
30373
30373
  return hasFeed && !hasRoute && !hasRouteFeed;
30374
30374
  }
30375
- function longitudeAt(x, z2) {
30376
- return x / (TILE_PX * Math.pow(2, z2)) * 360 - 180;
30375
+ function longitudeAt(x, z3) {
30376
+ return x / (TILE_PX * Math.pow(2, z3)) * 360 - 180;
30377
30377
  }
30378
- function latitudeAt(y, z2) {
30379
- const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z2));
30378
+ function latitudeAt(y, z3) {
30379
+ const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z3));
30380
30380
  return 180 / Math.PI * Math.atan(Math.sinh(n));
30381
30381
  }
30382
- function regionArgs(centerLat, centerLng, z2, w, h) {
30383
- const cx = mercatorX(centerLng, z2);
30384
- const cy = mercatorY(centerLat, z2);
30382
+ function regionArgs(centerLat, centerLng, z3, w, h) {
30383
+ const cx = mercatorX(centerLng, z3);
30384
+ const cy = mercatorY(centerLat, z3);
30385
30385
  return {
30386
30386
  latitude: centerLat,
30387
30387
  longitude: centerLng,
30388
- zoom: z2,
30389
- north: latitudeAt(cy - h / 2, z2),
30390
- south: latitudeAt(cy + h / 2, z2),
30391
- east: longitudeAt(cx + w / 2, z2),
30392
- west: longitudeAt(cx - w / 2, z2)
30388
+ zoom: z3,
30389
+ north: latitudeAt(cy - h / 2, z3),
30390
+ south: latitudeAt(cy + h / 2, z3),
30391
+ east: longitudeAt(cx + w / 2, z3),
30392
+ west: longitudeAt(cx - w / 2, z3)
30393
30393
  };
30394
30394
  }
30395
30395
  function decodeCamera(v) {
@@ -30419,9 +30419,9 @@ function resolveTileSource(source) {
30419
30419
  const maxZoom = typeof s.maxZoom === "number" && s.maxZoom > 0 ? s.maxZoom : DEFAULT_TILE_MAX_ZOOM;
30420
30420
  return { urlTemplate, attribution, maxZoom };
30421
30421
  }
30422
- function tileUrl(source, z2, x, y) {
30423
- if (!source) return `https://tile.openstreetmap.org/${z2}/${x}/${y}.png`;
30424
- return source.urlTemplate.replace("{z}", String(z2)).replace("{x}", String(x)).replace("{y}", String(y));
30422
+ function tileUrl(source, z3, x, y) {
30423
+ if (!source) return `https://tile.openstreetmap.org/${z3}/${x}/${y}.png`;
30424
+ return source.urlTemplate.replace("{z}", String(z3)).replace("{x}", String(x)).replace("{y}", String(y));
30425
30425
  }
30426
30426
  function parseShapeKind(raw) {
30427
30427
  const k = typeof raw === "string" ? raw.toLowerCase() : "";
@@ -30438,12 +30438,12 @@ function circleRing(centreLat, centreLng, radiusM, segments = CIRCLE_SEGMENTS) {
30438
30438
  return { latitude: centreLat + dLat * Math.sin(theta), longitude: centreLng + dLng * Math.cos(theta) };
30439
30439
  });
30440
30440
  }
30441
- function distanceToPolylinePx(px, py, points, z2, originX, originY) {
30441
+ function distanceToPolylinePx(px, py, points, z3, originX, originY) {
30442
30442
  if (points.length < 2) return null;
30443
30443
  let best = Infinity;
30444
30444
  for (let i = 0; i < points.length - 1; i++) {
30445
- const ax = mercatorX(points[i].longitude, z2) - originX, ay = mercatorY(points[i].latitude, z2) - originY;
30446
- const bx = mercatorX(points[i + 1].longitude, z2) - originX, by = mercatorY(points[i + 1].latitude, z2) - originY;
30445
+ const ax = mercatorX(points[i].longitude, z3) - originX, ay = mercatorY(points[i].latitude, z3) - originY;
30446
+ const bx = mercatorX(points[i + 1].longitude, z3) - originX, by = mercatorY(points[i + 1].latitude, z3) - originY;
30447
30447
  const dx = bx - ax, dy = by - ay;
30448
30448
  const lenSq = dx * dx + dy * dy;
30449
30449
  const t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
@@ -30453,22 +30453,22 @@ function distanceToPolylinePx(px, py, points, z2, originX, originY) {
30453
30453
  }
30454
30454
  return best;
30455
30455
  }
30456
- function polygonContainsPx(px, py, points, z2, originX, originY) {
30456
+ function polygonContainsPx(px, py, points, z3, originX, originY) {
30457
30457
  if (points.length < 3) return false;
30458
30458
  let inside2 = false;
30459
30459
  for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
30460
- const xi = mercatorX(points[i].longitude, z2) - originX, yi = mercatorY(points[i].latitude, z2) - originY;
30461
- const xj = mercatorX(points[j].longitude, z2) - originX, yj = mercatorY(points[j].latitude, z2) - originY;
30460
+ const xi = mercatorX(points[i].longitude, z3) - originX, yi = mercatorY(points[i].latitude, z3) - originY;
30461
+ const xj = mercatorX(points[j].longitude, z3) - originX, yj = mercatorY(points[j].latitude, z3) - originY;
30462
30462
  if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) inside2 = !inside2;
30463
30463
  }
30464
30464
  return inside2;
30465
30465
  }
30466
- function markerHit(px, py, markers, z2, originX, originY) {
30466
+ function markerHit(px, py, markers, z3, originX, originY) {
30467
30467
  let best = null;
30468
30468
  let bestDistance = MARKER_HIT_RADIUS;
30469
30469
  markers.forEach((m, i) => {
30470
- const dx = mercatorX(m.longitude, z2) - originX - px;
30471
- const dy = mercatorY(m.latitude, z2) - originY - py;
30470
+ const dx = mercatorX(m.longitude, z3) - originX - px;
30471
+ const dy = mercatorY(m.latitude, z3) - originY - py;
30472
30472
  const d = Math.sqrt(dx * dx + dy * dy);
30473
30473
  if (d <= bestDistance) {
30474
30474
  bestDistance = d;
@@ -30477,22 +30477,22 @@ function markerHit(px, py, markers, z2, originX, originY) {
30477
30477
  });
30478
30478
  return best;
30479
30479
  }
30480
- function mercatorX(lng, z2) {
30481
- return (lng + 180) / 360 * TILE_PX * Math.pow(2, z2);
30480
+ function mercatorX(lng, z3) {
30481
+ return (lng + 180) / 360 * TILE_PX * Math.pow(2, z3);
30482
30482
  }
30483
- function mercatorY(lat, z2) {
30483
+ function mercatorY(lat, z3) {
30484
30484
  const s = Math.max(-85.05112878, Math.min(85.05112878, lat)) * Math.PI / 180;
30485
- return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z2);
30485
+ return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z3);
30486
30486
  }
30487
30487
  function fitZoom(pts, w, h, fallback) {
30488
30488
  if (pts.length < 2 || w <= 0 || h <= 0) return fallback;
30489
30489
  const lats = pts.map((p) => p.latitude), lngs = pts.map((p) => p.longitude);
30490
30490
  const minLa = Math.min(...lats), maxLa = Math.max(...lats);
30491
30491
  const minLo = Math.min(...lngs), maxLo = Math.max(...lngs);
30492
- for (let z2 = 19; z2 >= 1; z2--) {
30493
- const dx = Math.abs(mercatorX(maxLo, z2) - mercatorX(minLo, z2));
30494
- const dy = Math.abs(mercatorY(maxLa, z2) - mercatorY(minLa, z2));
30495
- if (dx <= w && dy <= h) return z2;
30492
+ for (let z3 = 19; z3 >= 1; z3--) {
30493
+ const dx = Math.abs(mercatorX(maxLo, z3) - mercatorX(minLo, z3));
30494
+ const dy = Math.abs(mercatorY(maxLa, z3) - mercatorY(minLa, z3));
30495
+ if (dx <= w && dy <= h) return z3;
30496
30496
  }
30497
30497
  return 1;
30498
30498
  }
@@ -34611,20 +34611,20 @@ var init_renderNode = __esm({
34611
34611
  const fitted = shouldFit ? fitZoom(all, W - 48, H - 48, declared) : declared;
34612
34612
  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;
34613
34613
  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;
34614
- const z2 = userCam?.z ?? fitted;
34614
+ const z3 = userCam?.z ?? fitted;
34615
34615
  const cLat = userCam?.lat ?? baseLat;
34616
34616
  const cLng = userCam?.lng ?? baseLng;
34617
34617
  React7.useEffect(() => {
34618
- const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z2);
34618
+ const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z3);
34619
34619
  if (!resolved2) return;
34620
34620
  setUserCam({
34621
34621
  lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
34622
34622
  lng: resolved2.longitude,
34623
- z: Math.max(1, Math.min(19, resolved2.zoom ?? z2))
34623
+ z: Math.max(1, Math.min(19, resolved2.zoom ?? z3))
34624
34624
  });
34625
34625
  }, [commandedCamera]);
34626
- const originX = mercatorX(cLng, z2) - W / 2;
34627
- const originY = mercatorY(cLat, z2) - H / 2;
34626
+ const originX = mercatorX(cLng, z3) - W / 2;
34627
+ const originY = mercatorY(cLat, z3) - H / 2;
34628
34628
  const interactive = pinsOnly ? props.interactive === true : props.interactive !== false;
34629
34629
  const resolvedTileSource = resolveTileSource(props.tileSource);
34630
34630
  const fireMapEvent = (action, payload) => {
@@ -34642,7 +34642,7 @@ var init_renderNode = __esm({
34642
34642
  const { kx, ky } = layoutScale(el);
34643
34643
  const px = (e.clientX - r.left) * kx - el.clientLeft;
34644
34644
  const py = (e.clientY - r.top) * ky - el.clientTop;
34645
- const hit = markerHit(px, py, markers, z2, originX, originY);
34645
+ const hit = markerHit(px, py, markers, z3, originX, originY);
34646
34646
  if (hit !== null) {
34647
34647
  const m = markers[hit];
34648
34648
  const payload = { index: hit, latitude: m.latitude, longitude: m.longitude };
@@ -34653,10 +34653,10 @@ var init_renderNode = __esm({
34653
34653
  const shapeIndex = shapes.findIndex((sh) => {
34654
34654
  if (sh.kind === "unknown" || sh.points.length < 2) return false;
34655
34655
  if (sh.kind === "line") {
34656
- const d2 = distanceToPolylinePx(px, py, sh.points, z2, originX, originY);
34656
+ const d2 = distanceToPolylinePx(px, py, sh.points, z3, originX, originY);
34657
34657
  return d2 !== null && d2 <= SHAPE_HIT_RADIUS;
34658
34658
  }
34659
- return polygonContainsPx(px, py, sh.points, z2, originX, originY);
34659
+ return polygonContainsPx(px, py, sh.points, z3, originX, originY);
34660
34660
  });
34661
34661
  if (shapeIndex >= 0 && props.onShapeTap) {
34662
34662
  const sh = shapes[shapeIndex];
@@ -34665,15 +34665,15 @@ var init_renderNode = __esm({
34665
34665
  fireMapEvent(props.onShapeTap, payload);
34666
34666
  } else {
34667
34667
  fireMapEvent(props.onMapTap, {
34668
- latitude: latitudeAt(originY + py, z2),
34669
- longitude: longitudeAt(originX + px, z2)
34668
+ latitude: latitudeAt(originY + py, z3),
34669
+ longitude: longitudeAt(originX + px, z3)
34670
34670
  });
34671
34671
  }
34672
34672
  }
34673
34673
  };
34674
34674
  const onPointerDown = (e) => {
34675
34675
  if (!interactive) return;
34676
- dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z2, ...layoutScale(e.currentTarget) };
34676
+ dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z3, ...layoutScale(e.currentTarget) };
34677
34677
  dragMovedRef.current = false;
34678
34678
  };
34679
34679
  const onPointerMove = (e) => {
@@ -34697,8 +34697,8 @@ var init_renderNode = __esm({
34697
34697
  const onWheel = (e) => {
34698
34698
  if (!interactive) return;
34699
34699
  e.preventDefault();
34700
- const next = Math.max(1, Math.min(19, z2 + (e.deltaY < 0 ? 1 : -1)));
34701
- if (next !== z2) setUserCam({ lat: cLat, lng: cLng, z: next });
34700
+ const next = Math.max(1, Math.min(19, z3 + (e.deltaY < 0 ? 1 : -1)));
34701
+ if (next !== z3) setUserCam({ lat: cLat, lng: cLng, z: next });
34702
34702
  };
34703
34703
  React7.useEffect(() => {
34704
34704
  const action = props.onRegionChange;
@@ -34709,22 +34709,22 @@ var init_renderNode = __esm({
34709
34709
  regionReportedRef.current = true;
34710
34710
  return;
34711
34711
  }
34712
- fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z2, W, H) } });
34712
+ fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z3, W, H) } });
34713
34713
  }, 250);
34714
34714
  return () => clearTimeout(t);
34715
- }, [cLat, cLng, z2, W, H, props.onRegionChange]);
34716
- const sx = (p) => mercatorX(p.longitude, z2) - originX;
34717
- const sy = (p) => mercatorY(p.latitude, z2) - originY;
34715
+ }, [cLat, cLng, z3, W, H, props.onRegionChange]);
34716
+ const sx = (p) => mercatorX(p.longitude, z3) - originX;
34717
+ const sy = (p) => mercatorY(p.latitude, z3) - originY;
34718
34718
  const accent = C("accentPrimary", "#116DFF");
34719
- const n = Math.pow(2, z2);
34719
+ const n = Math.pow(2, z3);
34720
34720
  const tiles = [];
34721
34721
  for (let tx = Math.floor(originX / TILE_PX); tx <= Math.floor((originX + W) / TILE_PX); tx++) {
34722
34722
  for (let ty = Math.floor(originY / TILE_PX); ty <= Math.floor((originY + H) / TILE_PX); ty++) {
34723
34723
  if (ty < 0 || ty >= n) continue;
34724
34724
  const wrapX = (tx % n + n) % n;
34725
34725
  tiles.push({
34726
- key: `${z2}/${wrapX}/${ty}`,
34727
- src: tileUrl(resolvedTileSource, z2, wrapX, ty),
34726
+ key: `${z3}/${wrapX}/${ty}`,
34727
+ src: tileUrl(resolvedTileSource, z3, wrapX, ty),
34728
34728
  left: tx * TILE_PX - originX,
34729
34729
  top: ty * TILE_PX - originY
34730
34730
  });
@@ -34736,7 +34736,7 @@ var init_renderNode = __esm({
34736
34736
  ref: attachBox,
34737
34737
  "data-map-mode": "tile",
34738
34738
  "data-route-points": route.length,
34739
- "data-map-zoom": z2,
34739
+ "data-map-zoom": z3,
34740
34740
  onClick: onSurfaceClick,
34741
34741
  onPointerDown,
34742
34742
  onPointerMove,
@@ -35902,7 +35902,7 @@ async function stabilizePngPage(page, scheme) {
35902
35902
  const browser = globalThis;
35903
35903
  browser.document.documentElement.style.colorScheme = selected;
35904
35904
  await browser.document.fonts?.ready;
35905
- await new Promise((resolve53) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve53())));
35905
+ await new Promise((resolve54) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve54())));
35906
35906
  }, scheme);
35907
35907
  }
35908
35908
  async function renderPngBatch(items) {
@@ -39543,7 +39543,7 @@ async function handleWebWix(req, res, state) {
39543
39543
  }
39544
39544
  if (match) {
39545
39545
  const mocked = match.rule.response;
39546
- if (mocked.delayMs) await new Promise((resolve53) => setTimeout(resolve53, mocked.delayMs));
39546
+ if (mocked.delayMs) await new Promise((resolve54) => setTimeout(resolve54, mocked.delayMs));
39547
39547
  const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
39548
39548
  record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
39549
39549
  return reply(200, { status: mocked.status, body: responseBody ?? "" });
@@ -40537,8 +40537,8 @@ async function handleActionHandlerBundleGet(res, app) {
40537
40537
  }
40538
40538
  async function serveStatic(req, res, root, prefix) {
40539
40539
  const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
40540
- const relative14 = requested.replace(prefix, "").replace(/^\//, "");
40541
- const safe = normalize3(relative14).replace(/^(\.\.[\/\\])+/, "");
40540
+ const relative15 = requested.replace(prefix, "").replace(/^\//, "");
40541
+ const safe = normalize3(relative15).replace(/^(\.\.[\/\\])+/, "");
40542
40542
  const fullPath = resolve33(root, safe);
40543
40543
  if (!fullPath.startsWith(root)) {
40544
40544
  return send(res, 403, "forbidden");
@@ -41269,8 +41269,8 @@ function sha256hex(b) {
41269
41269
  function stableStringify(value) {
41270
41270
  if (value === null || typeof value !== "object") return JSON.stringify(value);
41271
41271
  if (Array.isArray(value)) return "[" + value.map(stableStringify).join(",") + "]";
41272
- const object2 = value;
41273
- return "{" + Object.keys(object2).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object2[key2])).join(",") + "}";
41272
+ const object3 = value;
41273
+ return "{" + Object.keys(object3).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object3[key2])).join(",") + "}";
41274
41274
  }
41275
41275
  function manifestContent(m) {
41276
41276
  const {
@@ -41642,12 +41642,12 @@ var init_query = __esm({
41642
41642
  });
41643
41643
 
41644
41644
  // ../../core/dev-server/src/crawl-input.ts
41645
- function resolved(v, resolve53) {
41646
- if (typeof v === "string") return v.startsWith("$service:") ? resolve53(v) : v;
41645
+ function resolved(v, resolve54) {
41646
+ if (typeof v === "string") return v.startsWith("$service:") ? resolve54(v) : v;
41647
41647
  if (Array.isArray(v)) {
41648
41648
  const out2 = v.flatMap((el) => {
41649
41649
  if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
41650
- const r = resolve53(el);
41650
+ const r = resolve54(el);
41651
41651
  return Array.isArray(r) ? r : [r];
41652
41652
  });
41653
41653
  return out2;
@@ -41661,9 +41661,9 @@ function hasRowBinding(props) {
41661
41661
  return itemToken(v) || Array.isArray(v) && v.some(itemToken);
41662
41662
  });
41663
41663
  }
41664
- function declaredOptionIds(props, resolve53) {
41664
+ function declaredOptionIds(props, resolve54) {
41665
41665
  const literal = props.options ?? props.tabs ?? props.chips;
41666
- const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve53) : void 0;
41666
+ const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve54) : void 0;
41667
41667
  const raw = Array.isArray(bound) ? bound : literal;
41668
41668
  if (!Array.isArray(raw)) return [];
41669
41669
  const out2 = [];
@@ -41706,24 +41706,24 @@ function seedTokens(state, limit = 48) {
41706
41706
  walk2(state, 0);
41707
41707
  return out2;
41708
41708
  }
41709
- function synthesizeInput(control, resolve53, tokens) {
41709
+ function synthesizeInput(control, resolve54, tokens) {
41710
41710
  const id = `${control.type}.${control.callback}`;
41711
41711
  const row = SYNTHESIZED_CONTROLS[id];
41712
41712
  if (!row) return null;
41713
41713
  const props = control.props;
41714
41714
  if (hasRowBinding(props)) return null;
41715
41715
  if (row.from === "declared-options") {
41716
- const ids = declaredOptionIds(props, resolve53);
41716
+ const ids = declaredOptionIds(props, resolve54);
41717
41717
  if (!ids.length) return null;
41718
41718
  if (row.encoding === "string-array") {
41719
- const currentRaw2 = resolved(props.selectedIds, resolve53);
41719
+ const currentRaw2 = resolved(props.selectedIds, resolve54);
41720
41720
  const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
41721
41721
  const pick4 = ids.find((o) => !current3.includes(o));
41722
41722
  if (pick4 === void 0) return null;
41723
41723
  const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
41724
41724
  return { key: row.key, value, from: row.from, current: current3, control: id };
41725
41725
  }
41726
- const currentRaw = resolved(props.selectedId, resolve53);
41726
+ const currentRaw = resolved(props.selectedId, resolve54);
41727
41727
  const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
41728
41728
  const pick3 = ids.find((o) => o !== current2);
41729
41729
  if (pick3 === void 0) return null;
@@ -41731,7 +41731,7 @@ function synthesizeInput(control, resolve53, tokens) {
41731
41731
  }
41732
41732
  if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
41733
41733
  const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
41734
- const bound = binding2 === void 0 ? void 0 : resolve53(binding2);
41734
+ const bound = binding2 === void 0 ? void 0 : resolve54(binding2);
41735
41735
  const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
41736
41736
  const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
41737
41737
  const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
@@ -43216,8 +43216,8 @@ async function crawlScreenInner(opts) {
43216
43216
  if (linkable.has(target)) return true;
43217
43217
  for (const base of linkable) {
43218
43218
  if (target.length > base.length + 1 && target.startsWith(base)) {
43219
- const sep17 = target[base.length];
43220
- if (sep17 === "_" || sep17 === "/") return true;
43219
+ const sep18 = target[base.length];
43220
+ if (sep18 === "_" || sep18 === "/") return true;
43221
43221
  }
43222
43222
  }
43223
43223
  return false;
@@ -46244,7 +46244,7 @@ var init_studio_timeline = __esm({
46244
46244
  isStr = (x) => typeof x === "string";
46245
46245
  isObj2 = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
46246
46246
  strs = (x) => Array.isArray(x) && x.every(isStr);
46247
- nullOr = (x, ok) => x === null || isObj2(x) && ok(x);
46247
+ nullOr = (x, ok2) => x === null || isObj2(x) && ok2(x);
46248
46248
  accentOf = (palette2) => {
46249
46249
  for (const p of palette2 ?? []) {
46250
46250
  const [name, hex2] = Array.isArray(p) ? p : [p.name, p.hex];
@@ -47194,16 +47194,16 @@ function pushSetupBodyBytes(body) {
47194
47194
  return Buffer.byteLength(JSON.stringify(body), "utf8");
47195
47195
  }
47196
47196
  async function pushSetupRequest(options) {
47197
- const refuse5 = (error) => ({ ok: false, status: 0, body: null, error });
47198
- if (!options.target.controlToken) return refuse5("control_token_required");
47199
- if (!options.wixToken) return refuse5("wix_account_token_required");
47200
- if (credentialHostRefusal(options.target.control)) return refuse5("insecure_target");
47201
- if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse5("invalid_preview_tag");
47197
+ const refuse6 = (error) => ({ ok: false, status: 0, body: null, error });
47198
+ if (!options.target.controlToken) return refuse6("control_token_required");
47199
+ if (!options.wixToken) return refuse6("wix_account_token_required");
47200
+ if (credentialHostRefusal(options.target.control)) return refuse6("insecure_target");
47201
+ if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse6("invalid_preview_tag");
47202
47202
  const setup = options.operation === "setup";
47203
- if (setup && !options.body) return refuse5("push_setup_body_required");
47204
- if (!setup && (!options.query?.app || !options.query?.site)) return refuse5("push_setup_query_required");
47203
+ if (setup && !options.body) return refuse6("push_setup_body_required");
47204
+ if (!setup && (!options.query?.app || !options.query?.site)) return refuse6("push_setup_query_required");
47205
47205
  if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
47206
- return refuse5("push_setup_body_too_large");
47206
+ return refuse6("push_setup_body_too_large");
47207
47207
  }
47208
47208
  const base = options.target.control.replace(/\/+$/, "");
47209
47209
  let path2 = "/v1/admin/push/setup";
@@ -51021,8 +51021,8 @@ function baseOf(target, linkable, known) {
51021
51021
  let best = null;
51022
51022
  for (const base of linkable ?? []) {
51023
51023
  if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
51024
- const sep17 = target[base.length];
51025
- if ((sep17 === "_" || sep17 === "/") && (!best || base.length > best.length)) best = base;
51024
+ const sep18 = target[base.length];
51025
+ if ((sep18 === "_" || sep18 === "/") && (!best || base.length > best.length)) best = base;
51026
51026
  }
51027
51027
  return best;
51028
51028
  }
@@ -52263,7 +52263,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52263
52263
  const headers2 = Object.fromEntries(new Headers(init.headers).entries());
52264
52264
  const request = url.protocol === "https:" ? httpsRequest : httpRequest;
52265
52265
  const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
52266
- return await new Promise((resolve53, reject) => {
52266
+ return await new Promise((resolve54, reject) => {
52267
52267
  let settled = false;
52268
52268
  const finish2 = (fn) => {
52269
52269
  if (settled) return;
@@ -52300,7 +52300,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52300
52300
  }
52301
52301
  const responseHeaders = new Headers();
52302
52302
  for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
52303
- resolve53(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52303
+ resolve54(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52304
52304
  }));
52305
52305
  });
52306
52306
  req.once("error", (error) => finish2(() => reject(error)));
@@ -52600,7 +52600,7 @@ function createLocalTestSandbox() {
52600
52600
  }
52601
52601
  })();
52602
52602
  `;
52603
- return await new Promise((resolve53, reject) => {
52603
+ return await new Promise((resolve54, reject) => {
52604
52604
  const { port1, port2 } = new MessageChannel();
52605
52605
  const serializableContext = {
52606
52606
  auth: context.auth,
@@ -52676,7 +52676,7 @@ function createLocalTestSandbox() {
52676
52676
  timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
52677
52677
  return;
52678
52678
  }
52679
- if (message.ok) finish2(() => resolve53({ value: message.value, durationMs: Date.now() - started }));
52679
+ if (message.ok) finish2(() => resolve54({ value: message.value, durationMs: Date.now() - started }));
52680
52680
  else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
52681
52681
  });
52682
52682
  worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
@@ -53853,9 +53853,187 @@ var init_cli_bridge = __esm({
53853
53853
  }
53854
53854
  });
53855
53855
 
53856
- // src/mcp/tools.ts
53856
+ // src/mcp/file-tools.ts
53857
+ 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";
53858
+ import { dirname as dirname30, isAbsolute as isAbsolute5, join as join53, relative as relative11, resolve as resolve45, sep as sep14 } from "node:path";
53857
53859
  import * as z from "zod";
53858
- import { resolve as resolve45 } from "node:path";
53860
+ function within(root, p) {
53861
+ return p === root || p.startsWith(root.endsWith(sep14) ? root : root + sep14);
53862
+ }
53863
+ function realish(p) {
53864
+ let cur = p;
53865
+ const tail = [];
53866
+ while (!existsSync54(cur)) {
53867
+ const up = dirname30(cur);
53868
+ if (up === cur) break;
53869
+ tail.unshift(cur.slice(up.length + (up.endsWith(sep14) ? 0 : 1)));
53870
+ cur = up;
53871
+ }
53872
+ return join53(realpathSync7(cur), ...tail);
53873
+ }
53874
+ async function confinedAppDir(args, deps) {
53875
+ const root = resolve45(await deps.defaultDir());
53876
+ const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
53877
+ if (!existsSync54(root)) return refuse4("no_workspace", `the workspace folder ${root} does not exist`);
53878
+ if (!within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
53879
+ return dir;
53880
+ }
53881
+ function confinedPath(appDir3, rel) {
53882
+ if (typeof rel !== "string" || !rel.trim()) return { error: "a path is required" };
53883
+ if (rel.includes("\0")) return { error: "a path may not contain NUL" };
53884
+ if (isAbsolute5(rel)) return { error: `"${rel}" is absolute \u2014 give a path inside the app folder` };
53885
+ const abs = resolve45(appDir3, rel);
53886
+ const real = realish(abs);
53887
+ const base = existsSync54(appDir3) ? realpathSync7(appDir3) : realish(appDir3);
53888
+ if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
53889
+ const first = relative11(base, real).split(sep14)[0];
53890
+ if (RESERVED.has(first)) return { error: `"${rel}" is inside ${first}/, which this tool does not touch` };
53891
+ return abs;
53892
+ }
53893
+ function listFiles(appDir3) {
53894
+ const files = [];
53895
+ const walk2 = (d) => {
53896
+ for (const e of readdirSync27(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
53897
+ if (RESERVED.has(e.name)) continue;
53898
+ if (e.isSymbolicLink()) continue;
53899
+ const p = join53(d, e.name);
53900
+ if (e.isDirectory()) {
53901
+ if (!walk2(p)) return false;
53902
+ } else if (e.isFile()) {
53903
+ if (files.length >= MAX_LISTED) return false;
53904
+ files.push({ path: relative11(appDir3, p).split(sep14).join("/"), bytes: statSync13(p).size });
53905
+ }
53906
+ }
53907
+ return true;
53908
+ };
53909
+ const complete = walk2(appDir3);
53910
+ return { files, truncated: !complete };
53911
+ }
53912
+ function fileTools() {
53913
+ return [
53914
+ {
53915
+ name: "himi_list_apps",
53916
+ title: "List apps in the workspace",
53917
+ 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.",
53918
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53919
+ inputSchema: z.object({}),
53920
+ handler: async (_a, d) => {
53921
+ const root = resolve45(await d.defaultDir());
53922
+ if (!existsSync54(root)) return ok({ ok: true, workspace: root, apps: [] });
53923
+ const apps = [];
53924
+ if (existsSync54(join53(root, CONTENT_MARKER))) apps.push(".");
53925
+ for (const e of readdirSync27(root, { withFileTypes: true })) {
53926
+ if (e.isDirectory() && !e.name.startsWith(".") && existsSync54(join53(root, e.name, CONTENT_MARKER))) apps.push(e.name);
53927
+ }
53928
+ return ok({ ok: true, workspace: root, apps: apps.sort() });
53929
+ }
53930
+ },
53931
+ {
53932
+ name: "himi_list_files",
53933
+ title: "List app files",
53934
+ description: `Every file in an app folder with its size (skips ${[...RESERVED].join(", ")}; at most ${MAX_LISTED}).`,
53935
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53936
+ inputSchema: z.object({ dir: DIR }),
53937
+ handler: async (a, d) => {
53938
+ const app = await confinedAppDir(a, d);
53939
+ if (typeof app !== "string") return app;
53940
+ if (!existsSync54(app) || !statSync13(app).isDirectory()) return refuse4("no_app", `no folder at ${app}`);
53941
+ return ok({ ok: true, dir: app, ...listFiles(app) });
53942
+ }
53943
+ },
53944
+ {
53945
+ name: "himi_read_file",
53946
+ title: "Read an app file",
53947
+ description: `One file of an app folder, as UTF-8 text (at most ${MAX_FILE_BYTES / 1024} KiB).`,
53948
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53949
+ inputSchema: z.object({ dir: DIR, path: z.string().min(1).describe('Path inside the app folder, e.g. "screens/home.ts".') }),
53950
+ handler: async (a, d) => {
53951
+ const app = await confinedAppDir(a, d);
53952
+ if (typeof app !== "string") return app;
53953
+ const p = confinedPath(app, a.path);
53954
+ if (typeof p !== "string") return refuse4("bad_path", p.error);
53955
+ if (!existsSync54(p) || !lstatSync12(p).isFile()) return refuse4("not_found", `no file "${String(a.path)}"`);
53956
+ const size = statSync13(p).size;
53957
+ if (size > MAX_FILE_BYTES) return refuse4("too_large", `"${String(a.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
53958
+ return ok({ ok: true, path: a.path, bytes: size, content: readFileSync59(p, "utf8") });
53959
+ }
53960
+ },
53961
+ {
53962
+ name: "himi_write_files",
53963
+ title: "Write app files",
53964
+ 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.`,
53965
+ annotations: WRITE_ANN,
53966
+ inputSchema: z.object({
53967
+ dir: DIR,
53968
+ files: z.array(z.object({ path: z.string().min(1), content: z.string() })).min(1).max(MAX_FILES_PER_WRITE)
53969
+ }),
53970
+ handler: async (a, d) => {
53971
+ const app = await confinedAppDir(a, d);
53972
+ if (typeof app !== "string") return app;
53973
+ const files = Array.isArray(a.files) ? a.files : [];
53974
+ if (!files.length || files.length > MAX_FILES_PER_WRITE) return refuse4("bad_request", `between 1 and ${MAX_FILES_PER_WRITE} files per call`);
53975
+ const planned = [];
53976
+ const refused2 = [];
53977
+ for (const f of files) {
53978
+ const p = confinedPath(app, f.path);
53979
+ if (typeof p !== "string") refused2.push({ path: f.path, error: p.error });
53980
+ else if (typeof f.content !== "string") refused2.push({ path: f.path, error: "content must be text" });
53981
+ else if (Buffer.byteLength(f.content) > MAX_FILE_BYTES) refused2.push({ path: f.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
53982
+ else if (existsSync54(p) && !lstatSync12(p).isFile()) refused2.push({ path: f.path, error: "not a regular file" });
53983
+ else planned.push({ abs: p, rel: String(f.path), content: f.content });
53984
+ }
53985
+ if (refused2.length) return { ...ok({ ok: false, error: "refused", written: [], refused: refused2 }), isError: true };
53986
+ for (const f of planned) {
53987
+ mkdirSync26(dirname30(f.abs), { recursive: true });
53988
+ writeFileSync21(f.abs, f.content);
53989
+ }
53990
+ return ok({ ok: true, dir: app, written: planned.map((f) => f.rel) });
53991
+ }
53992
+ },
53993
+ {
53994
+ name: "himi_delete_files",
53995
+ title: "Delete app files",
53996
+ description: "Delete files (not folders) from an app folder. Nothing is deleted if any path is refused.",
53997
+ annotations: { ...WRITE_ANN, idempotentHint: false },
53998
+ inputSchema: z.object({ dir: DIR, paths: z.array(z.string().min(1)).min(1).max(MAX_FILES_PER_WRITE) }),
53999
+ handler: async (a, d) => {
54000
+ const app = await confinedAppDir(a, d);
54001
+ if (typeof app !== "string") return app;
54002
+ const paths = Array.isArray(a.paths) ? a.paths : [];
54003
+ const planned = [];
54004
+ const refused2 = [];
54005
+ for (const rel of paths) {
54006
+ const p = confinedPath(app, rel);
54007
+ if (typeof p !== "string") refused2.push({ path: rel, error: p.error });
54008
+ else if (!existsSync54(p)) refused2.push({ path: rel, error: "no such file" });
54009
+ else if (!lstatSync12(p).isFile()) refused2.push({ path: rel, error: "not a regular file" });
54010
+ else planned.push(p);
54011
+ }
54012
+ if (refused2.length) return { ...ok({ ok: false, error: "refused", deleted: [], refused: refused2 }), isError: true };
54013
+ for (const p of planned) rmSync12(p);
54014
+ return ok({ ok: true, dir: app, deleted: paths });
54015
+ }
54016
+ }
54017
+ ];
54018
+ }
54019
+ var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED, RESERVED, CONTENT_MARKER, ok, refuse4, DIR, WRITE_ANN;
54020
+ var init_file_tools = __esm({
54021
+ "src/mcp/file-tools.ts"() {
54022
+ MAX_FILE_BYTES = 1024 * 1024;
54023
+ MAX_FILES_PER_WRITE = 100;
54024
+ MAX_LISTED = 2e3;
54025
+ RESERVED = /* @__PURE__ */ new Set([".git", "node_modules", "dist"]);
54026
+ CONTENT_MARKER = "himalaya.content.json";
54027
+ ok = (o) => ({ content: [{ type: "text", text: JSON.stringify(o, null, 2) }] });
54028
+ refuse4 = (error, message) => ({ content: [{ type: "text", text: JSON.stringify({ ok: false, error, message }, null, 2) }], isError: true });
54029
+ DIR = z.string().optional().describe("The app folder, relative to the workspace folder. Default: the workspace folder itself.");
54030
+ WRITE_ANN = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
54031
+ }
54032
+ });
54033
+
54034
+ // src/mcp/tools.ts
54035
+ import * as z2 from "zod";
54036
+ import { resolve as resolve46 } from "node:path";
53859
54037
  function fromCli(r, extra = []) {
53860
54038
  const body = r.json !== void 0 ? JSON.stringify(r.json, null, 2) : r.text.trim();
53861
54039
  const content = [];
@@ -53867,7 +54045,7 @@ ${r.stderr.trim()}`) });
53867
54045
  }
53868
54046
  async function appDir2(args, deps) {
53869
54047
  const base = await deps.defaultDir();
53870
- return typeof args.dir === "string" && args.dir ? resolve45(base, args.dir) : base;
54048
+ return typeof args.dir === "string" && args.dir ? resolve46(base, args.dir) : base;
53871
54049
  }
53872
54050
  function loginResult(s) {
53873
54051
  switch (s.state) {
@@ -53906,8 +54084,8 @@ function guarded(h) {
53906
54084
  return h(args, deps);
53907
54085
  };
53908
54086
  }
53909
- function himiTools() {
53910
- return rawTools().map((t) => ({ ...t, handler: guarded(t.handler) }));
54087
+ function himiTools(opts = {}) {
54088
+ return [...rawTools(), ...opts.withFiles ? fileTools() : []].map((t) => ({ ...t, handler: guarded(t.handler) }));
53911
54089
  }
53912
54090
  function rawTools() {
53913
54091
  return [
@@ -53916,7 +54094,7 @@ function rawTools() {
53916
54094
  title: "Read a himi authoring guide",
53917
54095
  description: "List the Himalaya authoring guides, or read one by topic id. Offline \u2014 the guides ship with this CLI. Start here before authoring.",
53918
54096
  annotations: LEARN,
53919
- inputSchema: z.object({ topic: z.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
54097
+ inputSchema: z2.object({ topic: z2.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
53920
54098
  handler: async (a, d) => fromCli(await d.runCli(["docs", ...typeof a.topic === "string" && a.topic ? [a.topic] : [], "--json"]))
53921
54099
  },
53922
54100
  {
@@ -53924,7 +54102,7 @@ function rawTools() {
53924
54102
  title: "SDUI component vocabulary",
53925
54103
  description: "The SDUI component vocabulary and props a descriptor may use; a name returns that one component. Offline.",
53926
54104
  annotations: LEARN,
53927
- inputSchema: z.object({ name: z.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
54105
+ inputSchema: z2.object({ name: z2.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
53928
54106
  handler: async (a, d) => fromCli(await d.runCli(["components", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
53929
54107
  },
53930
54108
  {
@@ -53932,7 +54110,7 @@ function rawTools() {
53932
54110
  title: "Importable @himalaya SDKs",
53933
54111
  description: "The @himalaya/* SDKs a Tier-5 worker may import; a name returns that SDK's typed API. Offline.",
53934
54112
  annotations: LEARN,
53935
- inputSchema: z.object({ name: z.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
54113
+ inputSchema: z2.object({ name: z2.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
53936
54114
  handler: async (a, d) => fromCli(await d.runCli(["sdk", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
53937
54115
  },
53938
54116
  {
@@ -53940,7 +54118,7 @@ function rawTools() {
53940
54118
  title: "Icon name vocabulary",
53941
54119
  description: "The valid Icon.name values. An unknown name renders a fallback glyph and `himi_validate` warns. Offline.",
53942
54120
  annotations: LEARN,
53943
- inputSchema: z.object({}),
54121
+ inputSchema: z2.object({}),
53944
54122
  handler: async (_a, d) => fromCli(await d.runCli(["icons", "--json"]))
53945
54123
  },
53946
54124
  {
@@ -53948,14 +54126,14 @@ function rawTools() {
53948
54126
  title: "Create a new himi app",
53949
54127
  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.",
53950
54128
  annotations: LOCAL_WRITE,
53951
- inputSchema: z.object({
53952
- name: z.string().min(1).describe("The app name \u2014 also its folder name."),
53953
- parentDir: z.string().optional().describe("Where to create the folder. Default: the workspace root."),
53954
- template: z.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
54129
+ inputSchema: z2.object({
54130
+ name: z2.string().min(1).describe("The app name \u2014 also its folder name."),
54131
+ parentDir: z2.string().optional().describe("Where to create the folder. Default: the workspace root."),
54132
+ template: z2.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
53955
54133
  }),
53956
54134
  handler: async (a, d) => {
53957
54135
  const base = await d.defaultDir();
53958
- const parent = typeof a.parentDir === "string" && a.parentDir ? resolve45(base, a.parentDir) : base;
54136
+ const parent = typeof a.parentDir === "string" && a.parentDir ? resolve46(base, a.parentDir) : base;
53959
54137
  return fromCli(await d.runCli(["init", String(a.name), "--dir", parent, ...opt("--template", a.template)]));
53960
54138
  }
53961
54139
  },
@@ -53964,7 +54142,7 @@ function rawTools() {
53964
54142
  title: "Build the app's worker bundles",
53965
54143
  description: "Compile every tier5-src/<name>/index.ts to dist/bundles/<name>.bundle.js with esbuild. Writes dist/ only.",
53966
54144
  annotations: LOCAL_WRITE,
53967
- inputSchema: z.object({ dir: DIR }),
54145
+ inputSchema: z2.object({ dir: DIR2 }),
53968
54146
  handler: async (a, d) => fromCli(await d.runCli(["build", "--content", await appDir2(a, d)]))
53969
54147
  },
53970
54148
  {
@@ -53972,7 +54150,7 @@ function rawTools() {
53972
54150
  title: "Validate the app",
53973
54151
  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.",
53974
54152
  annotations: CHECK,
53975
- inputSchema: z.object({ dir: DIR, strict: z.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
54153
+ inputSchema: z2.object({ dir: DIR2, strict: z2.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
53976
54154
  handler: async (a, d) => fromCli(await d.runCli(["validate", "--content", await appDir2(a, d), ...sw("--strict", a.strict)]))
53977
54155
  },
53978
54156
  {
@@ -53980,10 +54158,10 @@ function rawTools() {
53980
54158
  title: "Behavioral crawl",
53981
54159
  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.",
53982
54160
  annotations: CHECK,
53983
- inputSchema: z.object({
53984
- dir: DIR,
53985
- screens: z.array(z.string()).optional().describe("Only these screen ids. Omit for all."),
53986
- deep: z.boolean().optional().describe("Also follow navigation into the screens actions open.")
54161
+ inputSchema: z2.object({
54162
+ dir: DIR2,
54163
+ screens: z2.array(z2.string()).optional().describe("Only these screen ids. Omit for all."),
54164
+ deep: z2.boolean().optional().describe("Also follow navigation into the screens actions open.")
53987
54165
  }),
53988
54166
  handler: async (a, d) => {
53989
54167
  const screens = Array.isArray(a.screens) ? a.screens.filter((s) => typeof s === "string") : [];
@@ -53995,13 +54173,13 @@ function rawTools() {
53995
54173
  title: "Render a screen to PNG",
53996
54174
  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.",
53997
54175
  annotations: CHECK,
53998
- inputSchema: z.object({
53999
- screen: z.string().min(1).describe("The screen id."),
54000
- dir: DIR,
54001
- scheme: z.enum(["light", "dark"]).optional(),
54002
- width: z.number().int().positive().optional().describe("Viewport width in px."),
54003
- device: z.string().optional().describe("A named device (overrides width)."),
54004
- rtl: z.boolean().optional()
54176
+ inputSchema: z2.object({
54177
+ screen: z2.string().min(1).describe("The screen id."),
54178
+ dir: DIR2,
54179
+ scheme: z2.enum(["light", "dark"]).optional(),
54180
+ width: z2.number().int().positive().optional().describe("Viewport width in px."),
54181
+ device: z2.string().optional().describe("A named device (overrides width)."),
54182
+ rtl: z2.boolean().optional()
54005
54183
  }),
54006
54184
  handler: async (a, d) => {
54007
54185
  const r = await d.runCli([
@@ -54031,12 +54209,12 @@ function rawTools() {
54031
54209
  title: "Build journal",
54032
54210
  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).",
54033
54211
  annotations: { ...LOCAL_WRITE, idempotentHint: false },
54034
- inputSchema: z.object({
54035
- dir: DIR,
54036
- message: z.string().optional().describe("What changed, one or two lines, for the owner."),
54037
- step: z.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
54038
- noImage: z.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
54039
- brief: z.boolean().optional()
54212
+ inputSchema: z2.object({
54213
+ dir: DIR2,
54214
+ message: z2.string().optional().describe("What changed, one or two lines, for the owner."),
54215
+ step: z2.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
54216
+ noImage: z2.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
54217
+ brief: z2.boolean().optional()
54040
54218
  }),
54041
54219
  handler: async (a, d) => {
54042
54220
  const dir = await appDir2(a, d);
@@ -54049,7 +54227,7 @@ function rawTools() {
54049
54227
  title: "Start the live preview",
54050
54228
  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,
54051
54229
  annotations: LOCAL_WRITE,
54052
- inputSchema: z.object({ dir: DIR }),
54230
+ inputSchema: z2.object({ dir: DIR2 }),
54053
54231
  handler: async (a, d) => {
54054
54232
  try {
54055
54233
  return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
@@ -54066,7 +54244,7 @@ ${log}` : ""}`, true);
54066
54244
  title: "Live preview status",
54067
54245
  description: "Whether this app's live preview is running, and its URL and last build result.",
54068
54246
  annotations: CHECK,
54069
- inputSchema: z.object({ dir: DIR }),
54247
+ inputSchema: z2.object({ dir: DIR2 }),
54070
54248
  handler: async (a, d) => json3(await d.preview.status(await appDir2(a, d)))
54071
54249
  },
54072
54250
  {
@@ -54074,7 +54252,7 @@ ${log}` : ""}`, true);
54074
54252
  title: "Stop the live preview",
54075
54253
  description: "Stop this app's live preview (the `himi run --watch` a `himi_preview_start` started).",
54076
54254
  annotations: { ...LOCAL_WRITE, destructiveHint: false },
54077
- inputSchema: z.object({ dir: DIR }),
54255
+ inputSchema: z2.object({ dir: DIR2 }),
54078
54256
  handler: async (a, d) => json3(await d.preview.stop(await appDir2(a, d)))
54079
54257
  },
54080
54258
  {
@@ -54082,7 +54260,7 @@ ${log}` : ""}`, true);
54082
54260
  title: "Signed-in identity",
54083
54261
  description: "The identity the stored serve-plane credential carries (account, scope, expiry). Local \u2014 decodes the stored token, no network.",
54084
54262
  annotations: LEARN,
54085
- inputSchema: z.object({ target: z.string().optional().describe("Serve target. Default: the CLI's default.") }),
54263
+ inputSchema: z2.object({ target: z2.string().optional().describe("Serve target. Default: the CLI's default.") }),
54086
54264
  handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target ?? d.login.target())]))
54087
54265
  },
54088
54266
  {
@@ -54090,9 +54268,9 @@ ${log}` : ""}`, true);
54090
54268
  title: "Sign in to Wix",
54091
54269
  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.",
54092
54270
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
54093
- inputSchema: z.object({
54094
- target: z.string().optional().describe("Serve target. Default: the CLI's default."),
54095
- switchAccount: z.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
54271
+ inputSchema: z2.object({
54272
+ target: z2.string().optional().describe("Serve target. Default: the CLI's default."),
54273
+ switchAccount: z2.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
54096
54274
  }),
54097
54275
  handler: async (a, d) => {
54098
54276
  const s = d.login.status();
@@ -54112,10 +54290,10 @@ ${log}` : ""}`, true);
54112
54290
  title: "Publish a draft",
54113
54291
  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).",
54114
54292
  annotations: PUBLISH,
54115
- inputSchema: z.object({
54116
- dir: DIR,
54117
- label: z.string().optional().describe("A short label for this draft."),
54118
- notes: z.string().optional().describe("Release notes for this draft.")
54293
+ inputSchema: z2.object({
54294
+ dir: DIR2,
54295
+ label: z2.string().optional().describe("A short label for this draft."),
54296
+ notes: z2.string().optional().describe("Release notes for this draft.")
54119
54297
  }),
54120
54298
  handler: async (a, d) => {
54121
54299
  const gate = await requireLogin(d);
@@ -54128,14 +54306,14 @@ ${log}` : ""}`, true);
54128
54306
  title: "Share a .himi package link",
54129
54307
  description: "Publish a content-addressed share link for a validated `.himi` package of an already-published release. Needs a sign-in first (himi_login).",
54130
54308
  annotations: PUBLISH,
54131
- inputSchema: z.object({
54132
- file: z.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
54133
- expiresAt: z.string().optional().describe("ISO timestamp the link stops working.")
54309
+ inputSchema: z2.object({
54310
+ file: z2.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
54311
+ expiresAt: z2.string().optional().describe("ISO timestamp the link stops working.")
54134
54312
  }),
54135
54313
  handler: async (a, d) => {
54136
54314
  const gate = await requireLogin(d);
54137
54315
  if (gate) return gate;
54138
- return fromCli(await d.runCli(["share", "--file", resolve45(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt), ...opt("--target", d.login.target())]));
54316
+ return fromCli(await d.runCli(["share", "--file", resolve46(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt), ...opt("--target", d.login.target())]));
54139
54317
  }
54140
54318
  },
54141
54319
  {
@@ -54145,19 +54323,20 @@ ${log}` : ""}`, true);
54145
54323
  // Not idempotent: with credentials, each `himi preview` mints a fresh single-use handover —
54146
54324
  // the same reason the hosted connector's tool of this name says false (RFC 0064 §5).
54147
54325
  annotations: { ...PUBLISH, readOnlyHint: true, idempotentHint: false },
54148
- inputSchema: z.object({
54149
- app: z.string().min(1),
54150
- release: z.string().min(1),
54151
- screen: z.string().optional(),
54152
- surface: z.string().optional()
54326
+ inputSchema: z2.object({
54327
+ app: z2.string().min(1),
54328
+ release: z2.string().min(1),
54329
+ screen: z2.string().optional(),
54330
+ surface: z2.string().optional()
54153
54331
  }),
54154
54332
  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())]))
54155
54333
  }
54156
54334
  ];
54157
54335
  }
54158
- var MAX_TEXT2, clip, text6, json3, opt, sw, DIR, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54336
+ var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54159
54337
  var init_tools = __esm({
54160
54338
  "src/mcp/tools.ts"() {
54339
+ init_file_tools();
54161
54340
  MAX_TEXT2 = 8e4;
54162
54341
  clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
54163
54342
  \u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
@@ -54165,7 +54344,7 @@ var init_tools = __esm({
54165
54344
  json3 = (o) => text6(JSON.stringify(o, null, 2));
54166
54345
  opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
54167
54346
  sw = (flag, v) => v === true ? [flag] : [];
54168
- DIR = z.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
54347
+ DIR2 = z2.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
54169
54348
  LEARN = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54170
54349
  CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54171
54350
  LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
@@ -54194,12 +54373,12 @@ function createLoginSession(deps) {
54194
54373
  current = pending;
54195
54374
  const out2 = [];
54196
54375
  const err = [];
54197
- return new Promise((resolve53) => {
54376
+ return new Promise((resolve54) => {
54198
54377
  let answered = false;
54199
54378
  const answer = () => {
54200
54379
  if (answered) return;
54201
54380
  answered = true;
54202
- resolve53(current);
54381
+ resolve54(current);
54203
54382
  };
54204
54383
  let child;
54205
54384
  try {
@@ -54258,7 +54437,7 @@ __export(server_exports, {
54258
54437
  protectStdout: () => protectStdout,
54259
54438
  startMcpServer: () => startMcpServer
54260
54439
  });
54261
- import { readFileSync as readFileSync59 } from "node:fs";
54440
+ import { readFileSync as readFileSync60 } from "node:fs";
54262
54441
  import { fileURLToPath as fileURLToPath21 } from "node:url";
54263
54442
  import { McpServer } from "@modelcontextprotocol/server";
54264
54443
  import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
@@ -54268,9 +54447,9 @@ function protectStdout() {
54268
54447
  console.info = toErr;
54269
54448
  console.debug = toErr;
54270
54449
  }
54271
- function buildServer(deps, version2) {
54450
+ function buildServer(deps, version2, tools = {}) {
54272
54451
  const server = new McpServer({ name: "himi", version: version2 }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
54273
- for (const tool of himiTools()) {
54452
+ for (const tool of himiTools(tools)) {
54274
54453
  server.registerTool(
54275
54454
  tool.name,
54276
54455
  { title: tool.title, description: tool.description, inputSchema: tool.inputSchema, annotations: { title: tool.title, ...tool.annotations } },
@@ -54304,23 +54483,23 @@ async function startMcpServer(opts) {
54304
54483
  // next call rather than pinning every later tool to the server's cwd (often $HOME for a GUI host).
54305
54484
  defaultDir: async () => {
54306
54485
  if (!rootDir && pinned) rootDir = await firstRoot(pinned);
54307
- return rootDir || process.cwd();
54486
+ return rootDir || opts.workspace || process.cwd();
54308
54487
  },
54309
54488
  preview: {
54310
54489
  start: (dir) => startPreview(dir, { port: previewPortForDir(dir) }, previewDeps),
54311
54490
  status: (dir) => previewStatus(dir, previewDeps),
54312
54491
  stop: (dir) => stopPreview(dir, previewDeps)
54313
54492
  },
54314
- readFile: (p) => readFileSync59(p),
54493
+ readFile: (p) => readFileSync60(p),
54315
54494
  login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
54316
54495
  };
54317
- const closed = new Promise((resolve53) => {
54318
- stdin.once("end", resolve53);
54319
- stdin.once("close", resolve53);
54496
+ const closed = new Promise((resolve54) => {
54497
+ stdin.once("end", resolve54);
54498
+ stdin.once("close", resolve54);
54320
54499
  });
54321
54500
  const handle = serveStdio(
54322
54501
  () => {
54323
- pinned = buildServer(deps, opts.version);
54502
+ pinned = buildServer(deps, opts.version, { withFiles: opts.withFiles });
54324
54503
  return pinned;
54325
54504
  },
54326
54505
  { transport: new StdioServerTransport(stdin, stdout), onerror: (e) => console.error(`[himi mcp] ${e.message}`) }
@@ -54354,9 +54533,9 @@ __export(native_decode_exports, {
54354
54533
  runNativeDecode: () => runNativeDecode
54355
54534
  });
54356
54535
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
54357
- import { existsSync as existsSync54, mkdtempSync as mkdtempSync2, readFileSync as readFileSync60, rmSync as rmSync12, writeFileSync as writeFileSync21 } from "node:fs";
54536
+ import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync22 } from "node:fs";
54358
54537
  import { tmpdir as tmpdir3 } from "node:os";
54359
- import { join as join53 } from "node:path";
54538
+ import { join as join54 } from "node:path";
54360
54539
  import { fileURLToPath as fileURLToPath22 } from "node:url";
54361
54540
  function nativeDecodePackageDir() {
54362
54541
  return fileURLToPath22(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
@@ -54366,8 +54545,8 @@ function nativeDecodeAndroidHarnessDir() {
54366
54545
  }
54367
54546
  function nativeOracleShipped() {
54368
54547
  return {
54369
- ios: existsSync54(join53(nativeDecodePackageDir(), "Package.swift")),
54370
- android: existsSync54(join53(nativeDecodeAndroidHarnessDir(), "gradlew"))
54548
+ ios: existsSync55(join54(nativeDecodePackageDir(), "Package.swift")),
54549
+ android: existsSync55(join54(nativeDecodeAndroidHarnessDir(), "gradlew"))
54371
54550
  };
54372
54551
  }
54373
54552
  function detectNativeDecode(options = {}) {
@@ -54378,7 +54557,7 @@ function detectNativeDecode(options = {}) {
54378
54557
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
54379
54558
  }
54380
54559
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
54381
- const packageAvailable = options.packageAvailable ?? existsSync54(join53(packageDir, "Package.swift"));
54560
+ const packageAvailable = options.packageAvailable ?? existsSync55(join54(packageDir, "Package.swift"));
54382
54561
  if (!packageAvailable) {
54383
54562
  return {
54384
54563
  platform: "ios",
@@ -54390,7 +54569,7 @@ function detectNativeDecode(options = {}) {
54390
54569
  }
54391
54570
  function localPropertiesSdk(harnessDir) {
54392
54571
  try {
54393
- const match = readFileSync60(join53(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
54572
+ const match = readFileSync61(join54(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
54394
54573
  return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
54395
54574
  } catch {
54396
54575
  return null;
@@ -54398,8 +54577,8 @@ function localPropertiesSdk(harnessDir) {
54398
54577
  }
54399
54578
  function detectAndroidNativeDecode(options = {}) {
54400
54579
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
54401
- const gradlew = join53(harnessDir, "gradlew");
54402
- const gradlewAvailable = options.gradlewAvailable ?? existsSync54(gradlew);
54580
+ const gradlew = join54(harnessDir, "gradlew");
54581
+ const gradlewAvailable = options.gradlewAvailable ?? existsSync55(gradlew);
54403
54582
  if (!gradlewAvailable) {
54404
54583
  return {
54405
54584
  platform: "android",
@@ -54409,7 +54588,7 @@ function detectAndroidNativeDecode(options = {}) {
54409
54588
  }
54410
54589
  const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
54411
54590
  const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
54412
- const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync54(sdk));
54591
+ const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync55(sdk));
54413
54592
  if (!sdkAvailable) {
54414
54593
  return {
54415
54594
  platform: "android",
@@ -54481,14 +54660,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
54481
54660
  return verdicts;
54482
54661
  }
54483
54662
  function runNativeDecode(options) {
54484
- const descriptorDir = mkdtempSync2(join53(tmpdir3(), "himi-native-decode-"));
54663
+ const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-"));
54485
54664
  const startedAt = Date.now();
54486
54665
  try {
54487
54666
  for (const descriptor of options.descriptors) {
54488
54667
  if (typeof descriptor.descriptorJson !== "string") {
54489
54668
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
54490
54669
  }
54491
- writeFileSync21(join53(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54670
+ writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54492
54671
  }
54493
54672
  options.progress?.("building cached Swift oracle");
54494
54673
  execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
@@ -54500,7 +54679,7 @@ function runNativeDecode(options) {
54500
54679
  encoding: "utf8"
54501
54680
  }).trim();
54502
54681
  options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
54503
- const stdout = execFileSync5(join53(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
54682
+ const stdout = execFileSync5(join54(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
54504
54683
  stdio: ["ignore", "pipe", "pipe"],
54505
54684
  encoding: "utf8"
54506
54685
  });
@@ -54514,19 +54693,19 @@ function runNativeDecode(options) {
54514
54693
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
54515
54694
  throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
54516
54695
  } finally {
54517
- rmSync12(descriptorDir, { recursive: true, force: true });
54696
+ rmSync13(descriptorDir, { recursive: true, force: true });
54518
54697
  }
54519
54698
  }
54520
54699
  function runAndroidNativeDecode(options) {
54521
- const descriptorDir = mkdtempSync2(join53(tmpdir3(), "himi-native-decode-android-"));
54522
- const outputPath = join53(descriptorDir, "verdicts.ndjson");
54700
+ const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-android-"));
54701
+ const outputPath = join54(descriptorDir, "verdicts.ndjson");
54523
54702
  const startedAt = Date.now();
54524
54703
  try {
54525
54704
  for (const descriptor of options.descriptors) {
54526
54705
  if (typeof descriptor.descriptorJson !== "string") {
54527
54706
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
54528
54707
  }
54529
- writeFileSync21(join53(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54708
+ writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54530
54709
  }
54531
54710
  options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
54532
54711
  execFileSync5(options.gradlew, [
@@ -54541,7 +54720,7 @@ function runAndroidNativeDecode(options) {
54541
54720
  stdio: ["ignore", "ignore", "pipe"],
54542
54721
  encoding: "utf8"
54543
54722
  });
54544
- const stdout = readFileSync60(outputPath, "utf8");
54723
+ const stdout = readFileSync61(outputPath, "utf8");
54545
54724
  return {
54546
54725
  platform: "android",
54547
54726
  verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
@@ -54552,7 +54731,7 @@ function runAndroidNativeDecode(options) {
54552
54731
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
54553
54732
  throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
54554
54733
  } finally {
54555
- rmSync12(descriptorDir, { recursive: true, force: true });
54734
+ rmSync13(descriptorDir, { recursive: true, force: true });
54556
54735
  }
54557
54736
  }
54558
54737
  function fieldAt(path2) {
@@ -54611,30 +54790,30 @@ __export(browser_authoring_exports, {
54611
54790
  });
54612
54791
  import { createServer as createServer5 } from "node:http";
54613
54792
  import { createHash as createHash29, randomBytes as randomBytes4 } from "node:crypto";
54614
- import { existsSync as existsSync55, readdirSync as readdirSync27, readFileSync as readFileSync61, realpathSync as realpathSync7, statSync as statSync13 } from "node:fs";
54615
- import { join as join54, posix as posix2, relative as relative11, sep as sep14 } from "node:path";
54793
+ import { existsSync as existsSync56, readdirSync as readdirSync28, readFileSync as readFileSync62, realpathSync as realpathSync8, statSync as statSync14 } from "node:fs";
54794
+ import { join as join55, posix as posix2, relative as relative12, sep as sep15 } from "node:path";
54616
54795
  function humanMs(ms) {
54617
54796
  return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
54618
54797
  }
54619
54798
  function collectWorkerSources(tier5SrcDir, bundleName) {
54620
- const root = join54(tier5SrcDir, bundleName);
54799
+ const root = join55(tier5SrcDir, bundleName);
54621
54800
  const files = {};
54622
54801
  const visitedDirs = /* @__PURE__ */ new Set();
54623
54802
  const walk2 = (abs, rel) => {
54624
- const real = realpathSync7(abs);
54803
+ const real = realpathSync8(abs);
54625
54804
  if (visitedDirs.has(real)) return;
54626
54805
  visitedDirs.add(real);
54627
- for (const name of readdirSync27(abs).sort()) {
54628
- const childAbs = join54(abs, name);
54806
+ for (const name of readdirSync28(abs).sort()) {
54807
+ const childAbs = join55(abs, name);
54629
54808
  const childRel = posix2.join(rel, name);
54630
- if (statSync13(childAbs).isDirectory()) {
54809
+ if (statSync14(childAbs).isDirectory()) {
54631
54810
  walk2(childAbs, childRel);
54632
54811
  } else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
54633
- files[childRel] = readFileSync61(childAbs, "utf8");
54812
+ files[childRel] = readFileSync62(childAbs, "utf8");
54634
54813
  }
54635
54814
  }
54636
54815
  };
54637
- if (!existsSync55(root)) return null;
54816
+ if (!existsSync56(root)) return null;
54638
54817
  walk2(root, `/tier5-src/${bundleName}`);
54639
54818
  const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
54640
54819
  if (!entry) return null;
@@ -54651,20 +54830,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
54651
54830
  const spec = m[1];
54652
54831
  const virtual = posix2.normalize(posix2.join(dir, spec));
54653
54832
  if (!virtual.startsWith("/tier5-src/")) continue;
54654
- const onDisk = join54(tier5SrcDir, virtual.slice("/tier5-src/".length));
54833
+ const onDisk = join55(tier5SrcDir, virtual.slice("/tier5-src/".length));
54655
54834
  const candidates = [
54656
54835
  onDisk,
54657
54836
  `${onDisk}.ts`,
54658
54837
  `${onDisk}.js`,
54659
54838
  onDisk.replace(/\.js$/, ".ts"),
54660
- join54(onDisk, "index.ts"),
54661
- join54(onDisk, "index.js")
54839
+ join55(onDisk, "index.ts"),
54840
+ join55(onDisk, "index.js")
54662
54841
  ];
54663
54842
  for (const abs of candidates) {
54664
- if (!existsSync55(abs) || statSync13(abs).isDirectory()) continue;
54665
- const key2 = `/tier5-src/${relative11(tier5SrcDir, abs).split(sep14).join(posix2.sep)}`;
54843
+ if (!existsSync56(abs) || statSync14(abs).isDirectory()) continue;
54844
+ const key2 = `/tier5-src/${relative12(tier5SrcDir, abs).split(sep15).join(posix2.sep)}`;
54666
54845
  if (key2 in files) break;
54667
- files[key2] = readFileSync61(abs, "utf8");
54846
+ files[key2] = readFileSync62(abs, "utf8");
54668
54847
  queue.push(key2);
54669
54848
  break;
54670
54849
  }
@@ -54696,10 +54875,10 @@ function collectSdkModules(files, resolveSubpath) {
54696
54875
  for (const source of Object.values(files)) visit(source);
54697
54876
  return { modules, unsupported };
54698
54877
  }
54699
- function sdkSubpathReader(resolve53) {
54878
+ function sdkSubpathReader(resolve54) {
54700
54879
  return (sub) => {
54701
54880
  try {
54702
- return readFileSync61(resolve53(`@wix/himalaya/${sub}`), "utf8");
54881
+ return readFileSync62(resolve54(`@wix/himalaya/${sub}`), "utf8");
54703
54882
  } catch {
54704
54883
  return null;
54705
54884
  }
@@ -54777,7 +54956,7 @@ async function runBrowserAuthoring(opts) {
54777
54956
  const token = mintToken2(payload);
54778
54957
  const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
54779
54958
  if (unusable) throw new Error(unusable);
54780
- return await new Promise((resolve53, reject) => {
54959
+ return await new Promise((resolve54, reject) => {
54781
54960
  let settled = false;
54782
54961
  let url = "";
54783
54962
  const server = createServer5();
@@ -54829,7 +55008,7 @@ async function runBrowserAuthoring(opts) {
54829
55008
  }
54830
55009
  res.writeHead(200, { "content-type": "text/plain" }).end("ok");
54831
55010
  const report3 = body.result;
54832
- finish2(() => resolve53({ report: report3, url }));
55011
+ finish2(() => resolve54({ report: report3, url }));
54833
55012
  })();
54834
55013
  });
54835
55014
  server.on("error", (e) => finish2(() => reject(e)));
@@ -54871,8 +55050,8 @@ __export(coverage_exports, {
54871
55050
  suppressedNativeKeys: () => suppressedNativeKeys,
54872
55051
  trendAndStore: () => trendAndStore
54873
55052
  });
54874
- import { existsSync as existsSync56, mkdirSync as mkdirSync26, readFileSync as readFileSync62, writeFileSync as writeFileSync22 } from "node:fs";
54875
- import { dirname as dirname30, join as join55 } from "node:path";
55053
+ import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as writeFileSync23 } from "node:fs";
55054
+ import { dirname as dirname31, join as join56 } from "node:path";
54876
55055
  function suppressedNativeKeys(oracle) {
54877
55056
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
54878
55057
  }
@@ -55052,11 +55231,11 @@ function assembleLedger(r, options = {}) {
55052
55231
  return out2;
55053
55232
  }
55054
55233
  function trendAndStore(dir, entries, suppressed) {
55055
- const p = join55(dir, LEDGER_FILE);
55234
+ const p = join56(dir, LEDGER_FILE);
55056
55235
  let previous = null;
55057
55236
  try {
55058
- if (existsSync56(p)) {
55059
- const parsed = JSON.parse(readFileSync62(p, "utf8"));
55237
+ if (existsSync57(p)) {
55238
+ const parsed = JSON.parse(readFileSync63(p, "utf8"));
55060
55239
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
55061
55240
  }
55062
55241
  } catch {
@@ -55064,8 +55243,8 @@ function trendAndStore(dir, entries, suppressed) {
55064
55243
  const current = entries.map((e) => e.key);
55065
55244
  const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
55066
55245
  try {
55067
- mkdirSync26(dirname30(p), { recursive: true });
55068
- writeFileSync22(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55246
+ mkdirSync27(dirname31(p), { recursive: true });
55247
+ writeFileSync23(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55069
55248
  } catch {
55070
55249
  return null;
55071
55250
  }
@@ -55095,11 +55274,11 @@ function formatLedger(entries, trend) {
55095
55274
  return out2.join("\n");
55096
55275
  }
55097
55276
  function diffAndStoreObservations(dir, current) {
55098
- const p = join55(dir, OBS_FILE);
55277
+ const p = join56(dir, OBS_FILE);
55099
55278
  let previous = null;
55100
55279
  try {
55101
- if (existsSync56(p)) {
55102
- const parsed = JSON.parse(readFileSync62(p, "utf8"));
55280
+ if (existsSync57(p)) {
55281
+ const parsed = JSON.parse(readFileSync63(p, "utf8"));
55103
55282
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
55104
55283
  (v) => Array.isArray(v) && v.every((l) => typeof l === "string")
55105
55284
  )) {
@@ -55109,8 +55288,8 @@ function diffAndStoreObservations(dir, current) {
55109
55288
  } catch {
55110
55289
  }
55111
55290
  try {
55112
- mkdirSync26(dirname30(p), { recursive: true });
55113
- writeFileSync22(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55291
+ mkdirSync27(dirname31(p), { recursive: true });
55292
+ writeFileSync23(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55114
55293
  } catch {
55115
55294
  return null;
55116
55295
  }
@@ -55148,8 +55327,8 @@ var LEDGER_FILE, OBS_FILE;
55148
55327
  var init_coverage = __esm({
55149
55328
  "src/coverage.ts"() {
55150
55329
  init_native_decode();
55151
- LEDGER_FILE = join55(".himi", "test-ledger.json");
55152
- OBS_FILE = join55(".himi", "test-observations.json");
55330
+ LEDGER_FILE = join56(".himi", "test-ledger.json");
55331
+ OBS_FILE = join56(".himi", "test-observations.json");
55153
55332
  }
55154
55333
  });
55155
55334
 
@@ -55160,16 +55339,16 @@ __export(design_kits_exports, {
55160
55339
  kitsDir: () => kitsDir,
55161
55340
  listKits: () => listKits2
55162
55341
  });
55163
- import { existsSync as existsSync57, readFileSync as readFileSync63, readdirSync as readdirSync28 } from "node:fs";
55164
- import { join as join56, basename as basename15 } from "node:path";
55342
+ import { existsSync as existsSync58, readFileSync as readFileSync64, readdirSync as readdirSync29 } from "node:fs";
55343
+ import { join as join57, basename as basename15 } from "node:path";
55165
55344
  import { fileURLToPath as fileURLToPath23 } from "node:url";
55166
55345
  function kitsDir() {
55167
- return KIT_DIR_CANDIDATES.find((p) => existsSync57(p));
55346
+ return KIT_DIR_CANDIDATES.find((p) => existsSync58(p));
55168
55347
  }
55169
55348
  function listKits2() {
55170
55349
  const dir = kitsDir();
55171
55350
  if (!dir) return [];
55172
- return readdirSync28(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
55351
+ return readdirSync29(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
55173
55352
  }
55174
55353
  function kitReport(name) {
55175
55354
  const dir = kitsDir();
@@ -55188,7 +55367,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
55188
55367
  if (!kits.includes(name)) {
55189
55368
  return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
55190
55369
  }
55191
- const raw = readFileSync63(join56(dir, `${name}.json`), "utf8");
55370
+ const raw = readFileSync64(join57(dir, `${name}.json`), "utf8");
55192
55371
  let parsed;
55193
55372
  try {
55194
55373
  parsed = JSON.parse(raw);
@@ -55212,9 +55391,9 @@ var init_design_kits = __esm({
55212
55391
  "src/design-kits.ts"() {
55213
55392
  KIT_DIR_CANDIDATES = [
55214
55393
  // in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
55215
- join56(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
55394
+ join57(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
55216
55395
  // published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
55217
- join56(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
55396
+ join57(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
55218
55397
  ];
55219
55398
  }
55220
55399
  });
@@ -55228,11 +55407,11 @@ __export(assets_exports, {
55228
55407
  removeAssetPayload: () => removeAssetPayload,
55229
55408
  verifyReport: () => verifyReport
55230
55409
  });
55231
- import { readFileSync as readFileSync64 } from "node:fs";
55410
+ import { readFileSync as readFileSync65 } from "node:fs";
55232
55411
  import { basename as basename16 } from "node:path";
55233
55412
  function declaredAssets(dir) {
55234
55413
  return collectAssets(dir).map((a) => {
55235
- const bytes2 = readFileSync64(a.path);
55414
+ const bytes2 = readFileSync65(a.path);
55236
55415
  return {
55237
55416
  name: a.name,
55238
55417
  sha256: assetSha256(bytes2),
@@ -55309,7 +55488,7 @@ function verifyReport(dir, app, manifest) {
55309
55488
  };
55310
55489
  }
55311
55490
  function addAssetPayload(manifest, filePath, opts) {
55312
- const bytes2 = readFileSync64(filePath);
55491
+ const bytes2 = readFileSync65(filePath);
55313
55492
  const name = opts.name ?? basename16(filePath);
55314
55493
  const sha2565 = assetSha256(bytes2);
55315
55494
  const record2 = {
@@ -57033,9 +57212,9 @@ __export(run_exports, {
57033
57212
  runPackage: () => runPackage,
57034
57213
  withoutProdServe: () => withoutProdServe
57035
57214
  });
57036
- 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";
57215
+ 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";
57037
57216
  import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
57038
- import { dirname as dirname31, join as join57 } from "node:path";
57217
+ import { dirname as dirname32, join as join58 } from "node:path";
57039
57218
  import { fileURLToPath as fileURLToPath24 } from "node:url";
57040
57219
  function makePackageRunHandler(opts) {
57041
57220
  const store = new FileReleaseStore(opts.releaseRoot);
@@ -57063,9 +57242,9 @@ async function fetchBytes(url) {
57063
57242
  }
57064
57243
  async function resolvePackage(source, workDir) {
57065
57244
  const isUrl2 = /^https?:\/\//i.test(source);
57066
- if (!isUrl2 && existsSync58(source) && statSync14(source).isDirectory()) {
57067
- const appDirManifest = join57(source, "release-manifest.json");
57068
- if (existsSync58(appDirManifest)) {
57245
+ if (!isUrl2 && existsSync59(source) && statSync15(source).isDirectory()) {
57246
+ const appDirManifest = join58(source, "release-manifest.json");
57247
+ if (existsSync59(appDirManifest)) {
57069
57248
  const opened2 = openPackageDir(source);
57070
57249
  if (!opened2.validation.ok) {
57071
57250
  throw new Error(`package is not valid:
@@ -57074,11 +57253,11 @@ async function resolvePackage(source, workDir) {
57074
57253
  const app2 = opened2.header?.app ?? opened2.manifest?.app;
57075
57254
  if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
57076
57255
  if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
57077
- const root2 = workDir ?? mkdtempSync3(join57(tmpdir4(), "himi-run-"));
57078
- const target = join57(root2, app2);
57079
- if (join57(source) !== target) {
57080
- mkdirSync27(root2, { recursive: true });
57081
- rmSync13(target, { recursive: true, force: true });
57256
+ const root2 = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
57257
+ const target = join58(root2, app2);
57258
+ if (join58(source) !== target) {
57259
+ mkdirSync28(root2, { recursive: true });
57260
+ rmSync14(target, { recursive: true, force: true });
57082
57261
  cpSync2(source, target, { recursive: true });
57083
57262
  }
57084
57263
  return {
@@ -57093,12 +57272,12 @@ async function resolvePackage(source, workDir) {
57093
57272
  }
57094
57273
  throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
57095
57274
  }
57096
- const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync65(source);
57097
- const root = workDir ?? mkdtempSync3(join57(tmpdir4(), "himi-run-"));
57275
+ const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync66(source);
57276
+ const root = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
57098
57277
  const { app, appDir: appDir3 } = unpackTo(bytes2, root);
57099
57278
  const opened = openPackageDir(appDir3);
57100
57279
  if (!opened.validation.ok) {
57101
- rmSync13(workDir ? appDir3 : root, { recursive: true, force: true });
57280
+ rmSync14(workDir ? appDir3 : root, { recursive: true, force: true });
57102
57281
  throw new Error(`package is not valid:
57103
57282
  ${opened.validation.errors.join("\n ")}`);
57104
57283
  }
@@ -57115,16 +57294,16 @@ async function resolvePackage(source, workDir) {
57115
57294
  async function loadPreviewAssets() {
57116
57295
  try {
57117
57296
  const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
57118
- const here = dirname31(fileURLToPath24(import.meta.url));
57297
+ const here = dirname32(fileURLToPath24(import.meta.url));
57119
57298
  const candidates = [
57120
- join57(here, "preview-assets.generated.bin"),
57299
+ join58(here, "preview-assets.generated.bin"),
57121
57300
  // published: copied next to the bundled CLI
57122
- join57(here, "../../../packages/serve/src/preview-assets.generated.bin")
57301
+ join58(here, "../../../packages/serve/src/preview-assets.generated.bin")
57123
57302
  // in-repo checkout
57124
57303
  ];
57125
57304
  for (const path2 of candidates) {
57126
- if (!existsSync58(path2)) continue;
57127
- const blob = readFileSync65(path2);
57305
+ if (!existsSync59(path2)) continue;
57306
+ const blob = readFileSync66(path2);
57128
57307
  return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
57129
57308
  }
57130
57309
  return /* @__PURE__ */ new Map();
@@ -57172,7 +57351,7 @@ async function runPackage(source, opts = {}) {
57172
57351
  const resolved2 = await resolvePackage(source, opts.workDir);
57173
57352
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
57174
57353
  if (!opts.spa && assets.size === 0) {
57175
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57354
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57176
57355
  throw new Error(NO_SPA_MESSAGE);
57177
57356
  }
57178
57357
  const plane = makePackageRunHandler({
@@ -57210,7 +57389,7 @@ async function runPackage(source, opts = {}) {
57210
57389
  lanBound = (await listen(lanServer, port, lanHost)).address;
57211
57390
  } catch (e) {
57212
57391
  await closeServer(server);
57213
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57392
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57214
57393
  throw new Error(`himi run --lan could not listen on ${lanHost}:${port} (${e.message}); drop --lan, or pass --port for a free one`);
57215
57394
  }
57216
57395
  bound.push(lanBound);
@@ -57232,7 +57411,7 @@ async function runPackage(source, opts = {}) {
57232
57411
  warnings: resolved2.warnings,
57233
57412
  close: async () => {
57234
57413
  await Promise.all(servers.map(closeServer));
57235
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57414
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57236
57415
  }
57237
57416
  };
57238
57417
  }
@@ -57271,9 +57450,9 @@ __export(run_watch_exports, {
57271
57450
  watchedContentDir: () => watchedContentDir,
57272
57451
  writeRunRecord: () => writeRunRecord
57273
57452
  });
57274
- 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";
57453
+ 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";
57275
57454
  import { randomUUID as randomUUID4 } from "node:crypto";
57276
- import { extname as extname4, join as join58, resolve as resolve46, sep as sep15 } from "node:path";
57455
+ import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
57277
57456
  function diffReleases(prev, next) {
57278
57457
  const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
57279
57458
  const changedBundles = new Set(bundles);
@@ -57314,7 +57493,7 @@ function watchContent(dir, onChange, opts = {}) {
57314
57493
  let timer = null;
57315
57494
  const pending = /* @__PURE__ */ new Set();
57316
57495
  const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
57317
- if (!file || ignoredChange(file, (rel) => isDir(join58(dir, rel)))) return;
57496
+ if (!file || ignoredChange(file, (rel) => isDir(join59(dir, rel)))) return;
57318
57497
  pending.add(file);
57319
57498
  if (timer) clearTimeout(timer);
57320
57499
  timer = setTimeout(() => {
@@ -57333,9 +57512,9 @@ function watchContent(dir, onChange, opts = {}) {
57333
57512
  }
57334
57513
  function watchedContentDir(source) {
57335
57514
  if (!source || /^https?:\/\//i.test(source)) return null;
57336
- const dir = resolve46(source);
57515
+ const dir = resolve47(source);
57337
57516
  try {
57338
- return statSync15(dir).isDirectory() && existsSync59(join58(dir, "himalaya.content.json")) ? dir : null;
57517
+ return statSync16(dir).isDirectory() && existsSync60(join59(dir, "himalaya.content.json")) ? dir : null;
57339
57518
  } catch {
57340
57519
  return null;
57341
57520
  }
@@ -57392,33 +57571,33 @@ function serialize(task) {
57392
57571
  });
57393
57572
  }
57394
57573
  function himiDir(dir) {
57395
- const root = join58(dir, ".himi");
57574
+ const root = join59(dir, ".himi");
57396
57575
  try {
57397
- return lstatSync12(root).isDirectory() ? root : null;
57576
+ return lstatSync13(root).isDirectory() ? root : null;
57398
57577
  } catch (e) {
57399
57578
  if (e.code !== "ENOENT") return null;
57400
- mkdirSync28(root, { recursive: true });
57401
- return lstatSync12(root).isDirectory() ? root : null;
57579
+ mkdirSync29(root, { recursive: true });
57580
+ return lstatSync13(root).isDirectory() ? root : null;
57402
57581
  }
57403
57582
  }
57404
57583
  function writeRunRecord(dir, record2) {
57405
57584
  const root = himiDir(dir);
57406
57585
  if (!root) return false;
57407
- const tmp = join58(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
57586
+ const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
57408
57587
  try {
57409
- writeFileSync23(tmp, `${JSON.stringify(record2, null, 2)}
57588
+ writeFileSync24(tmp, `${JSON.stringify(record2, null, 2)}
57410
57589
  `, { flag: "wx" });
57411
- renameSync6(tmp, join58(root, "run.json"));
57590
+ renameSync6(tmp, join59(root, "run.json"));
57412
57591
  } catch (e) {
57413
- rmSync14(tmp, { force: true });
57592
+ rmSync15(tmp, { force: true });
57414
57593
  throw e;
57415
57594
  }
57416
57595
  return true;
57417
57596
  }
57418
57597
  function removeRunRecord(dir, owner) {
57419
- const root = join58(dir, ".himi");
57598
+ const root = join59(dir, ".himi");
57420
57599
  try {
57421
- if (!lstatSync12(root).isDirectory()) return;
57600
+ if (!lstatSync13(root).isDirectory()) return;
57422
57601
  } catch {
57423
57602
  return;
57424
57603
  }
@@ -57431,22 +57610,22 @@ function removeRunRecord(dir, owner) {
57431
57610
  }
57432
57611
  if (typeof pid === "number" && pid !== owner) return;
57433
57612
  }
57434
- rmSync14(join58(root, "run.json"), { force: true });
57613
+ rmSync15(join59(root, "run.json"), { force: true });
57435
57614
  }
57436
57615
  function boardFile(dir, pathname) {
57437
57616
  if (pathname === RUN_IDENTITY_PATH) {
57438
57617
  return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
57439
57618
  }
57440
57619
  let rel = null;
57441
- if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join58("studio", "index.html");
57442
- else if (pathname === "/__himi/studio/state.js") rel = join58("studio", "state.js");
57443
- else if (pathname === "/__himi/studio/timeline.js") rel = join58("studio", "timeline.js");
57620
+ if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join59("studio", "index.html");
57621
+ else if (pathname === "/__himi/studio/state.js") rel = join59("studio", "state.js");
57622
+ else if (pathname === "/__himi/studio/timeline.js") rel = join59("studio", "timeline.js");
57444
57623
  else {
57445
57624
  const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
57446
- if (m) rel = join58("history", m[1]);
57625
+ if (m) rel = join59("history", m[1]);
57447
57626
  }
57448
57627
  if (!rel) return null;
57449
- const bytes2 = readConfined(resolve46(dir, ".himi"), rel);
57628
+ const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
57450
57629
  if (!bytes2) return new Response("not found", { status: 404 });
57451
57630
  return new Response(bytes2, {
57452
57631
  status: 200,
@@ -57455,20 +57634,20 @@ function boardFile(dir, pathname) {
57455
57634
  }
57456
57635
  function readConfined(root, rel) {
57457
57636
  try {
57458
- if (!lstatSync12(root).isDirectory()) return null;
57459
- const parts = rel.split(sep15);
57637
+ if (!lstatSync13(root).isDirectory()) return null;
57638
+ const parts = rel.split(sep16);
57460
57639
  let at2 = root;
57461
57640
  for (let i = 0; i < parts.length; i++) {
57462
- at2 = join58(at2, parts[i]);
57463
- const st = lstatSync12(at2);
57641
+ at2 = join59(at2, parts[i]);
57642
+ const st = lstatSync13(at2);
57464
57643
  if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
57465
57644
  }
57466
- const canonicalRoot = realpathSync8(root);
57467
- if (!realpathSync8(at2).startsWith(canonicalRoot + sep15)) return null;
57645
+ const canonicalRoot = realpathSync9(root);
57646
+ if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
57468
57647
  const fd = openSync3(at2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
57469
57648
  try {
57470
57649
  if (!fstatSync(fd).isFile()) return null;
57471
- return readFileSync66(fd);
57650
+ return readFileSync67(fd);
57472
57651
  } finally {
57473
57652
  closeSync4(fd);
57474
57653
  }
@@ -57497,7 +57676,7 @@ var init_run_watch = __esm({
57497
57676
  };
57498
57677
  isDir = (path2) => {
57499
57678
  try {
57500
- return statSync15(path2).isDirectory();
57679
+ return statSync16(path2).isDirectory();
57501
57680
  } catch {
57502
57681
  return false;
57503
57682
  }
@@ -57521,19 +57700,19 @@ __export(run_browser_exports, {
57521
57700
  runInBrowser: () => runInBrowser
57522
57701
  });
57523
57702
  import { createServer as createServer7 } from "node:http";
57524
- import { existsSync as existsSync60, readFileSync as readFileSync67 } from "node:fs";
57703
+ import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
57525
57704
  import { spawnSync as spawnSync3 } from "node:child_process";
57526
- import { dirname as dirname32, resolve as resolve47 } from "node:path";
57705
+ import { dirname as dirname33, resolve as resolve48 } from "node:path";
57527
57706
  import { fileURLToPath as fileURLToPath25 } from "node:url";
57528
57707
  function stagedDir() {
57529
- return process.env.HIMI_BROWSER_PLANE_OUT ? resolve47(process.env.HIMI_BROWSER_PLANE_OUT) : resolve47(REPO, "packages", "serve", "dist", "browser-plane");
57708
+ return process.env.HIMI_BROWSER_PLANE_OUT ? resolve48(process.env.HIMI_BROWSER_PLANE_OUT) : resolve48(REPO, "packages", "serve", "dist", "browser-plane");
57530
57709
  }
57531
57710
  function missingStaged() {
57532
- return [...SERVED].filter((f) => !existsSync60(resolve47(stagedDir(), f))).sort();
57711
+ return [...SERVED].filter((f) => !existsSync61(resolve48(stagedDir(), f))).sort();
57533
57712
  }
57534
57713
  function ensureBrowserPlaneStaged() {
57535
57714
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
57536
- const r = spawnSync3(process.execPath, [resolve47(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
57715
+ const r = spawnSync3(process.execPath, [resolve48(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
57537
57716
  cwd: REPO,
57538
57717
  encoding: "utf8"
57539
57718
  });
@@ -57619,7 +57798,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
57619
57798
  }
57620
57799
  const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
57621
57800
  if (SERVED.has(name)) {
57622
- if (!existsSync60(resolve47(stagedDir(), name))) {
57801
+ if (!existsSync61(resolve48(stagedDir(), name))) {
57623
57802
  const restaged = ensureBrowserPlaneStaged();
57624
57803
  if (!restaged.ok) {
57625
57804
  res.writeHead(503, { "content-type": "application/json" });
@@ -57629,7 +57808,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
57629
57808
  }
57630
57809
  let bytes2;
57631
57810
  try {
57632
- bytes2 = readFileSync67(resolve47(stagedDir(), name));
57811
+ bytes2 = readFileSync68(resolve48(stagedDir(), name));
57633
57812
  } catch (e) {
57634
57813
  res.writeHead(503, { "content-type": "application/json" });
57635
57814
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
@@ -57671,8 +57850,8 @@ var init_run_browser = __esm({
57671
57850
  init_open_url();
57672
57851
  init_file_store();
57673
57852
  init_wix_client_id();
57674
- HERE2 = dirname32(fileURLToPath25(import.meta.url));
57675
- REPO = resolve47(HERE2, "..", "..", "..");
57853
+ HERE2 = dirname33(fileURLToPath25(import.meta.url));
57854
+ REPO = resolve48(HERE2, "..", "..", "..");
57676
57855
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
57677
57856
  }
57678
57857
  });
@@ -58091,11 +58270,11 @@ __export(preflight_exports, {
58091
58270
  parseStoreConfig: () => parseStoreConfig,
58092
58271
  requireEnv: () => requireEnv
58093
58272
  });
58094
- import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
58095
- import { isAbsolute as isAbsolute5, relative as relative12, resolve as resolve48 } from "node:path";
58273
+ import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
58274
+ import { isAbsolute as isAbsolute6, relative as relative13, resolve as resolve49 } from "node:path";
58096
58275
  function isInsideRepo(p) {
58097
- const rel = relative12(REPO_ROOT3, resolve48(p));
58098
- return rel !== "" && !rel.startsWith("..") && !isAbsolute5(rel);
58276
+ const rel = relative13(REPO_ROOT3, resolve49(p));
58277
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute6(rel);
58099
58278
  }
58100
58279
  function assertCredentialOutsideRepo(label2, p) {
58101
58280
  if (isInsideRepo(p)) {
@@ -58148,10 +58327,10 @@ function parseStoreConfig(text8) {
58148
58327
  }
58149
58328
  function loadStoreConfig(app) {
58150
58329
  const p = storeConfigPath(app);
58151
- if (!existsSync61(p)) {
58330
+ if (!existsSync62(p)) {
58152
58331
  throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
58153
58332
  }
58154
- return parseStoreConfig(readFileSync68(p, "utf8"));
58333
+ return parseStoreConfig(readFileSync69(p, "utf8"));
58155
58334
  }
58156
58335
  var init_preflight = __esm({
58157
58336
  "../store-release/preflight.ts"() {
@@ -58170,19 +58349,19 @@ __export(credential_profile_exports, {
58170
58349
  profilePath: () => profilePath,
58171
58350
  resolveStoreCredentials: () => resolveStoreCredentials
58172
58351
  });
58173
- import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
58352
+ import { existsSync as existsSync63, readFileSync as readFileSync70 } from "node:fs";
58174
58353
  import { homedir as homedir5 } from "node:os";
58175
- import { join as join59 } from "node:path";
58354
+ import { join as join60 } from "node:path";
58176
58355
  function credentialsDir(home = homedir5()) {
58177
- return join59(home, ".himalaya", "store-credentials");
58356
+ return join60(home, ".himalaya", "store-credentials");
58178
58357
  }
58179
58358
  function profilePath(name, home = homedir5()) {
58180
58359
  if (!PROFILE_NAME.test(name)) {
58181
58360
  throw new Error(
58182
- `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.`
58361
+ `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.`
58183
58362
  );
58184
58363
  }
58185
- return join59(credentialsDir(home), `${name}.json`);
58364
+ return join60(credentialsDir(home), `${name}.json`);
58186
58365
  }
58187
58366
  function parseProfile(text8, label2) {
58188
58367
  let doc;
@@ -58213,8 +58392,8 @@ function resolveStoreCredentials(opts) {
58213
58392
  const { app, cfg } = opts;
58214
58393
  const env = opts.env ?? process.env;
58215
58394
  const home = opts.home ?? homedir5();
58216
- const read = opts.readProfile ?? ((p) => readFileSync69(p, "utf8"));
58217
- const exists = opts.profileExists ?? existsSync62;
58395
+ const read = opts.readProfile ?? ((p) => readFileSync70(p, "utf8"));
58396
+ const exists = opts.profileExists ?? existsSync63;
58218
58397
  const ios = cfg.ios ?? {};
58219
58398
  const flagName = opts.profileFlag?.trim();
58220
58399
  const named = namedProfile(cfg, opts.profileFlag);
@@ -58294,9 +58473,9 @@ __export(preflight_app_exports, {
58294
58473
  preflightApp: () => preflightApp,
58295
58474
  profileAccount: () => profileAccount
58296
58475
  });
58297
- import { readFileSync as readFileSync70, existsSync as existsSync63, readdirSync as readdirSync29, statSync as statSync16 } from "node:fs";
58476
+ import { readFileSync as readFileSync71, existsSync as existsSync64, readdirSync as readdirSync30, statSync as statSync17 } from "node:fs";
58298
58477
  import { createHash as createHash30 } from "node:crypto";
58299
- import { join as join60 } from "node:path";
58478
+ import { join as join61 } from "node:path";
58300
58479
  function analyze(projectYml, storeConfig, icon, account) {
58301
58480
  const f = [];
58302
58481
  const has = (re, s) => re.test(s);
@@ -58360,13 +58539,13 @@ function profileAccount(app, storeConfig, opts = {}) {
58360
58539
  }
58361
58540
  }
58362
58541
  async function preflightApp(app, opts = {}) {
58363
- const projectYml = existsSync63(iosProjectYml(app)) ? readFileSync70(iosProjectYml(app), "utf8") : "";
58364
- const storeConfig = existsSync63(storeConfigPath(app)) ? readFileSync70(storeConfigPath(app), "utf8") : "";
58542
+ const projectYml = existsSync64(iosProjectYml(app)) ? readFileSync71(iosProjectYml(app), "utf8") : "";
58543
+ const storeConfig = existsSync64(storeConfigPath(app)) ? readFileSync71(storeConfigPath(app), "utf8") : "";
58365
58544
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
58366
58545
  const findings = analyze(
58367
58546
  projectYml,
58368
58547
  storeConfig,
58369
- await appIconState(join60(appDir(app), "ios")),
58548
+ await appIconState(join61(appDir(app), "ios")),
58370
58549
  profileAccount(app, storeConfig, opts)
58371
58550
  );
58372
58551
  findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
@@ -58395,18 +58574,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
58395
58574
  return f;
58396
58575
  }
58397
58576
  function appLevelMetadataFiles(app, locale = "en-US") {
58398
- const root = join60(storeDir(app), "metadata");
58577
+ const root = join61(storeDir(app), "metadata");
58399
58578
  const out2 = /* @__PURE__ */ new Set();
58400
- if (existsSync63(root)) {
58401
- for (const n of readdirSync29(root)) if (n.endsWith(".txt")) out2.add(n);
58579
+ if (existsSync64(root)) {
58580
+ for (const n of readdirSync30(root)) if (n.endsWith(".txt")) out2.add(n);
58402
58581
  }
58403
- if (existsSync63(join60(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
58582
+ if (existsSync64(join61(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
58404
58583
  return out2;
58405
58584
  }
58406
58585
  function reviewInfoFiles(app) {
58407
- const dir = join60(storeDir(app), "review_information");
58408
- if (!existsSync63(dir)) return /* @__PURE__ */ new Set();
58409
- return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
58586
+ const dir = join61(storeDir(app), "review_information");
58587
+ if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
58588
+ return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
58410
58589
  }
58411
58590
  function isValidAppStoreSize(w, h) {
58412
58591
  return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
@@ -58515,12 +58694,12 @@ function analyzePlayListing(assets) {
58515
58694
  return f;
58516
58695
  }
58517
58696
  function playListingAssets(app, locale = "en-US") {
58518
- const dir = join60(storeDir(app), "play", locale, "images");
58697
+ const dir = join61(storeDir(app), "play", locale, "images");
58519
58698
  const read = (names) => {
58520
58699
  for (const name of names) {
58521
- const p = join60(dir, name);
58700
+ const p = join61(dir, name);
58522
58701
  try {
58523
- if (statSync16(p).isFile()) return { name, bytes: readFileSync70(p) };
58702
+ if (statSync17(p).isFile()) return { name, bytes: readFileSync71(p) };
58524
58703
  } catch {
58525
58704
  }
58526
58705
  }
@@ -58551,26 +58730,26 @@ function analyzeListing(metaFiles, shots) {
58551
58730
  return f;
58552
58731
  }
58553
58732
  function metadataFilesPresent(app, locale = "en-US") {
58554
- const dir = join60(storeDir(app), "metadata", locale);
58555
- if (!existsSync63(dir)) return /* @__PURE__ */ new Set();
58556
- return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
58733
+ const dir = join61(storeDir(app), "metadata", locale);
58734
+ if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
58735
+ return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
58557
58736
  }
58558
58737
  function listScreenshots(app, locale = "en-US") {
58559
58738
  const out2 = [];
58560
- const flat = join60(storeDir(app), "screenshots", locale);
58561
- if (existsSync63(flat)) {
58562
- for (const png of readdirSync29(flat).filter((n) => n.endsWith(".png"))) {
58563
- const sz = pngSize(readFileSync70(join60(flat, png)));
58739
+ const flat = join61(storeDir(app), "screenshots", locale);
58740
+ if (existsSync64(flat)) {
58741
+ for (const png of readdirSync30(flat).filter((n) => n.endsWith(".png"))) {
58742
+ const sz = pngSize(readFileSync71(join61(flat, png)));
58564
58743
  if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
58565
58744
  }
58566
58745
  }
58567
- const legacy = join60(storeDir(app), "metadata", locale, "screenshots");
58568
- if (existsSync63(legacy)) {
58569
- for (const deviceDir of readdirSync29(legacy)) {
58570
- const d = join60(legacy, deviceDir);
58571
- if (!statSync16(d).isDirectory()) continue;
58572
- for (const png of readdirSync29(d).filter((n) => n.endsWith(".png"))) {
58573
- const sz = pngSize(readFileSync70(join60(d, png)));
58746
+ const legacy = join61(storeDir(app), "metadata", locale, "screenshots");
58747
+ if (existsSync64(legacy)) {
58748
+ for (const deviceDir of readdirSync30(legacy)) {
58749
+ const d = join61(legacy, deviceDir);
58750
+ if (!statSync17(d).isDirectory()) continue;
58751
+ for (const png of readdirSync30(d).filter((n) => n.endsWith(".png"))) {
58752
+ const sz = pngSize(readFileSync71(join61(d, png)));
58574
58753
  if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
58575
58754
  }
58576
58755
  }
@@ -58578,13 +58757,13 @@ function listScreenshots(app, locale = "en-US") {
58578
58757
  return out2;
58579
58758
  }
58580
58759
  function placeholderHashes2() {
58581
- const templateIos = join60(appDir("_template"), "ios");
58582
- if (!existsSync63(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
58583
- for (const target of readdirSync29(templateIos)) {
58584
- const p = join60(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58760
+ const templateIos = join61(appDir("_template"), "ios");
58761
+ if (!existsSync64(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
58762
+ for (const target of readdirSync30(templateIos)) {
58763
+ const p = join61(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58585
58764
  try {
58586
- if (!statSync16(p).isFile()) continue;
58587
- return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync70(p)).digest("hex")];
58765
+ if (!statSync17(p).isFile()) continue;
58766
+ return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync71(p)).digest("hex")];
58588
58767
  } catch {
58589
58768
  }
58590
58769
  }
@@ -58615,12 +58794,12 @@ async function pixelIssues(bytes2) {
58615
58794
  }
58616
58795
  }
58617
58796
  async function appIconState(iosDir) {
58618
- if (!existsSync63(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
58619
- for (const target of readdirSync29(iosDir)) {
58620
- const p = join60(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58797
+ if (!existsSync64(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
58798
+ for (const target of readdirSync30(iosDir)) {
58799
+ const p = join61(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58621
58800
  try {
58622
- if (!statSync16(p).isFile()) continue;
58623
- const bytes2 = readFileSync70(p);
58801
+ if (!statSync17(p).isFile()) continue;
58802
+ const bytes2 = readFileSync71(p);
58624
58803
  const hash = createHash30("sha256").update(bytes2).digest("hex");
58625
58804
  const pixels = await pixelIssues(bytes2);
58626
58805
  return {
@@ -58692,7 +58871,7 @@ __export(version_exports, {
58692
58871
  setAndroidVersion: () => setAndroidVersion,
58693
58872
  setIosVersion: () => setIosVersion
58694
58873
  });
58695
- import { readFileSync as readFileSync71, writeFileSync as writeFileSync24 } from "node:fs";
58874
+ import { readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
58696
58875
  function readIosVersion(projectYml) {
58697
58876
  const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
58698
58877
  const build2 = matchScalar(projectYml, "CFBundleVersion");
@@ -58750,15 +58929,15 @@ function setAndroidVersion(gradle, v) {
58750
58929
  function bumpVersion(app, opts) {
58751
58930
  const iosPath = iosProjectYml(app);
58752
58931
  const gradlePath = androidGradle(app);
58753
- const iosYml = readFileSync71(iosPath, "utf8");
58754
- const gradle = readFileSync71(gradlePath, "utf8");
58932
+ const iosYml = readFileSync72(iosPath, "utf8");
58933
+ const gradle = readFileSync72(gradlePath, "utf8");
58755
58934
  const current = readIosVersion(iosYml);
58756
58935
  const next = {
58757
58936
  marketing: opts.marketing ?? current.marketing,
58758
58937
  build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
58759
58938
  };
58760
- writeFileSync24(iosPath, setIosVersion(iosYml, next));
58761
- writeFileSync24(gradlePath, setAndroidVersion(gradle, next));
58939
+ writeFileSync25(iosPath, setIosVersion(iosYml, next));
58940
+ writeFileSync25(gradlePath, setAndroidVersion(gradle, next));
58762
58941
  return next;
58763
58942
  }
58764
58943
  var init_version = __esm({
@@ -58768,7 +58947,7 @@ var init_version = __esm({
58768
58947
  });
58769
58948
 
58770
58949
  // ../store-release/register-bundle.ts
58771
- import { readFileSync as readFileSync72 } from "node:fs";
58950
+ import { readFileSync as readFileSync73 } from "node:fs";
58772
58951
  import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
58773
58952
  function b64url2(b) {
58774
58953
  return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -58786,7 +58965,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
58786
58965
  async function registerBundleId(opts) {
58787
58966
  const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
58788
58967
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
58789
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync72(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58968
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58790
58969
  const res = await fetch(`${ASC_API}/v1/bundleIds`, {
58791
58970
  method: "POST",
58792
58971
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
@@ -58840,7 +59019,7 @@ __export(asc_status_exports, {
58840
59019
  ascStatus: () => ascStatus,
58841
59020
  buildVerdict: () => buildVerdict
58842
59021
  });
58843
- import { readFileSync as readFileSync73 } from "node:fs";
59022
+ import { readFileSync as readFileSync74 } from "node:fs";
58844
59023
  function buildVerdict(builds) {
58845
59024
  if (!builds.length) {
58846
59025
  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).";
@@ -58854,7 +59033,7 @@ function buildVerdict(builds) {
58854
59033
  function client(creds) {
58855
59034
  const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
58856
59035
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
58857
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
59036
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync74(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58858
59037
  return async (path2) => {
58859
59038
  const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
58860
59039
  return { status: r.status, json: await r.json().catch(() => ({})) };
@@ -58903,7 +59082,7 @@ var init_asc_status = __esm({
58903
59082
  // ../../core/functions-secrets/src/vault.ts
58904
59083
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
58905
59084
  import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
58906
- import { dirname as dirname33 } from "node:path";
59085
+ import { dirname as dirname34 } from "node:path";
58907
59086
  function createJsonSecretStore(filePath) {
58908
59087
  const read = async () => {
58909
59088
  try {
@@ -58916,7 +59095,7 @@ function createJsonSecretStore(filePath) {
58916
59095
  }
58917
59096
  };
58918
59097
  const write2 = async (records) => {
58919
- await mkdir(dirname33(filePath), { recursive: true });
59098
+ await mkdir(dirname34(filePath), { recursive: true });
58920
59099
  const temporary = `${filePath}.${process.pid}.tmp`;
58921
59100
  await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
58922
59101
  `, { mode: 384 });
@@ -59014,7 +59193,7 @@ __export(secrets_exports, {
59014
59193
  runRemoteSecretsCommand: () => runRemoteSecretsCommand,
59015
59194
  runSecretsCommand: () => runSecretsCommand
59016
59195
  });
59017
- import { readFileSync as readFileSync74 } from "node:fs";
59196
+ import { readFileSync as readFileSync75 } from "node:fs";
59018
59197
  function environment(value) {
59019
59198
  if (value === "preview" || value === "production") return value;
59020
59199
  throw new Error("--environment must be preview or production");
@@ -59045,7 +59224,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
59045
59224
  io.log(JSON.stringify(await vault.list({ app, environment: env })));
59046
59225
  return 0;
59047
59226
  }
59048
- const value = options.readValue ? options.readValue() : readFileSync74(0, "utf8").replace(/\r?\n$/, "");
59227
+ const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
59049
59228
  if (operation === "set") await vault.set({ app, environment: env, name, value });
59050
59229
  else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
59051
59230
  else throw new Error(`unknown secrets operation ${operation}`);
@@ -59074,7 +59253,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
59074
59253
  }
59075
59254
  let body;
59076
59255
  if (operation !== "list") {
59077
- const value = options.readValue ? options.readValue() : readFileSync74(0, "utf8").replace(/\r?\n$/, "");
59256
+ const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
59078
59257
  body = JSON.stringify({ value });
59079
59258
  }
59080
59259
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
@@ -59211,29 +59390,29 @@ __export(notify_ping_exports, {
59211
59390
  runNotifyPing: () => runNotifyPing
59212
59391
  });
59213
59392
  import { randomUUID as randomUUID5 } from "node:crypto";
59214
- import { resolve as resolve49 } from "node:path";
59215
- function refuse4(io, error, hint, exit = 2, extra = {}) {
59393
+ import { resolve as resolve50 } from "node:path";
59394
+ function refuse5(io, error, hint, exit = 2, extra = {}) {
59216
59395
  io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
59217
59396
  return exit;
59218
59397
  }
59219
59398
  async function runNotifyPing(flags, io, deps = {}) {
59220
59399
  const flagError = flagRefusal(flags);
59221
- if (flagError) return refuse4(io, flagError);
59222
- const input = mergePushInputs(pushInputsFromContent(resolve49(text7(flags.content) ?? process.cwd())), flags);
59400
+ if (flagError) return refuse5(io, flagError);
59401
+ const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
59223
59402
  const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
59224
- 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 });
59403
+ 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 });
59225
59404
  const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
59226
- if (!UUID_RE.test(requestId2)) return refuse4(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59405
+ if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59227
59406
  const owner = await hostedOwnerSession(flags, deps);
59228
- if (!owner.ok) return refuse4(io, owner.error, owner.hint, owner.exit);
59407
+ if (!owner.ok) return refuse5(io, owner.error, owner.hint, owner.exit);
59229
59408
  const { session } = owner;
59230
59409
  const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
59231
- if (ownership.state !== "owned") return refuse4(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59410
+ if (ownership.state !== "owned") return refuse5(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59232
59411
  let siteToken2;
59233
59412
  try {
59234
59413
  siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
59235
59414
  } catch {
59236
- return refuse4(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59415
+ return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59237
59416
  }
59238
59417
  const body = {
59239
59418
  app: ownership.slug,
@@ -59256,12 +59435,12 @@ function flagRefusal(flags) {
59256
59435
  function report2(http, sent, flags, io) {
59257
59436
  const code = refusalCode(http);
59258
59437
  if (code === "send_outcome_unknown") {
59259
- 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 });
59438
+ 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 });
59260
59439
  }
59261
59440
  if (code === "rate_limited" && http.retryAfterSec) {
59262
- return refuse4(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59441
+ return refuse5(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59263
59442
  }
59264
- if (code) return refuse4(io, code, HINTS[code], 1);
59443
+ if (code) return refuse5(io, code, HINTS[code], 1);
59265
59444
  if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
59266
59445
  else io.log(summary(http.body ?? {}, sent));
59267
59446
  return 0;
@@ -59321,15 +59500,15 @@ __export(notify_exports, {
59321
59500
  runNotify: () => runNotify,
59322
59501
  saveAdminSession: () => saveAdminSession
59323
59502
  });
59324
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync29, readFileSync as readFileSync75, writeFileSync as writeFileSync25 } from "node:fs";
59503
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync26 } from "node:fs";
59325
59504
  import { homedir as homedir6 } from "node:os";
59326
- import { dirname as dirname34, join as join61 } from "node:path";
59505
+ import { dirname as dirname35, join as join62 } from "node:path";
59327
59506
  function defaultSessionsPath() {
59328
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join61(homedir6(), ".himalaya", "admin-sessions.json");
59507
+ return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join62(homedir6(), ".himalaya", "admin-sessions.json");
59329
59508
  }
59330
59509
  function loadSessionsFile(path2 = defaultSessionsPath()) {
59331
59510
  try {
59332
- return JSON.parse(readFileSync75(path2, "utf8"));
59511
+ return JSON.parse(readFileSync76(path2, "utf8"));
59333
59512
  } catch {
59334
59513
  return {};
59335
59514
  }
@@ -59337,10 +59516,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
59337
59516
  function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
59338
59517
  const file = loadSessionsFile(path2);
59339
59518
  file.sessions = { ...file.sessions, [adminUrl]: session };
59340
- mkdirSync29(dirname34(path2), { recursive: true, mode: 448 });
59341
- writeFileSync25(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
59519
+ mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
59520
+ writeFileSync26(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
59342
59521
  try {
59343
- chmodSync3(dirname34(path2), 448);
59522
+ chmodSync3(dirname35(path2), 448);
59344
59523
  chmodSync3(path2, 384);
59345
59524
  } catch {
59346
59525
  }
@@ -61940,10 +62119,10 @@ function assertPublicSiteUrl(raw) {
61940
62119
  if (refusal) throw new Error(refusal);
61941
62120
  }
61942
62121
  function resolveAll(hostname2) {
61943
- return new Promise((resolve53, reject) => {
62122
+ return new Promise((resolve54, reject) => {
61944
62123
  dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
61945
62124
  if (err) reject(err);
61946
- else resolve53(addresses);
62125
+ else resolve54(addresses);
61947
62126
  });
61948
62127
  });
61949
62128
  }
@@ -61951,13 +62130,13 @@ function withAbort(start, signal, what) {
61951
62130
  if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
61952
62131
  const work = start();
61953
62132
  if (!signal) return work;
61954
- return new Promise((resolve53, reject) => {
62133
+ return new Promise((resolve54, reject) => {
61955
62134
  const onAbort = () => reject(new Error(`${what} aborted`));
61956
62135
  signal.addEventListener("abort", onAbort, { once: true });
61957
- work.then(resolve53, reject).finally(() => signal.removeEventListener("abort", onAbort));
62136
+ work.then(resolve54, reject).finally(() => signal.removeEventListener("abort", onAbort));
61958
62137
  });
61959
62138
  }
61960
- async function pinAddress(url, resolve53 = resolveAll, signal) {
62139
+ async function pinAddress(url, resolve54 = resolveAll, signal) {
61961
62140
  const host = url.hostname.replace(/^\[|\]$/g, "");
61962
62141
  if (ipv4Octets(host)) {
61963
62142
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
@@ -61967,7 +62146,7 @@ async function pinAddress(url, resolve53 = resolveAll, signal) {
61967
62146
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
61968
62147
  return { address: host, family: 6 };
61969
62148
  }
61970
- const addresses = await withAbort(() => resolve53(host), signal, `${host} lookup`);
62149
+ const addresses = await withAbort(() => resolve54(host), signal, `${host} lookup`);
61971
62150
  if (!addresses.length) throw new Error(`${host} resolved to no address`);
61972
62151
  const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
61973
62152
  if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
@@ -62007,7 +62186,7 @@ function copyIncomingHeaders(headers2) {
62007
62186
  return out2;
62008
62187
  }
62009
62188
  function requestOnce(url, pinned, init) {
62010
- return new Promise((resolve53, reject) => {
62189
+ return new Promise((resolve54, reject) => {
62011
62190
  const headers2 = { host: url.host, "accept-encoding": "identity" };
62012
62191
  new Headers(init.headers ?? {}).forEach((value, key2) => {
62013
62192
  if (key2.toLowerCase() !== "host") headers2[key2] = value;
@@ -62037,7 +62216,7 @@ function requestOnce(url, pinned, init) {
62037
62216
  reject(err);
62038
62217
  return;
62039
62218
  }
62040
- resolve53(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
62219
+ resolve54(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
62041
62220
  }
62042
62221
  );
62043
62222
  req.on("error", reject);
@@ -63097,8 +63276,8 @@ var init_brand_font = __esm({
63097
63276
  });
63098
63277
 
63099
63278
  // src/site-analyze/write-artifacts.ts
63100
- import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync26 } from "node:fs";
63101
- import { join as join62 } from "node:path";
63279
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
63280
+ import { join as join63 } from "node:path";
63102
63281
  function attachVeloSources(book, sources, put) {
63103
63282
  const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
63104
63283
  for (const f of book.velo.files) {
@@ -63253,13 +63432,13 @@ async function downloadMedia(book, fetchImpl, put) {
63253
63432
  }
63254
63433
  async function writeBusinessBook(result, opts) {
63255
63434
  const out2 = opts.outDir;
63256
- mkdirSync30(join62(out2, "evidence/pages"), { recursive: true });
63257
- mkdirSync30(join62(out2, "media/catalog"), { recursive: true });
63435
+ mkdirSync31(join63(out2, "evidence/pages"), { recursive: true });
63436
+ mkdirSync31(join63(out2, "media/catalog"), { recursive: true });
63258
63437
  const files = [];
63259
63438
  const put = (rel, body) => {
63260
- const p = join62(out2, rel);
63261
- mkdirSync30(join62(p, ".."), { recursive: true });
63262
- writeFileSync26(p, body);
63439
+ const p = join63(out2, rel);
63440
+ mkdirSync31(join63(p, ".."), { recursive: true });
63441
+ writeFileSync27(p, body);
63263
63442
  files.push(rel);
63264
63443
  };
63265
63444
  const book = result.book;
@@ -63352,15 +63531,15 @@ var init_customer_build = __esm({
63352
63531
  });
63353
63532
 
63354
63533
  // src/site-analyze/apply.ts
63355
- 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";
63356
- import { dirname as dirname35, isAbsolute as isAbsolute6, join as join63, resolve as resolve50, sep as sep16 } from "node:path";
63534
+ 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";
63535
+ import { dirname as dirname36, isAbsolute as isAbsolute7, join as join64, resolve as resolve51, sep as sep17 } from "node:path";
63357
63536
  import { spawnSync as spawnSync4 } from "node:child_process";
63358
63537
  function unpairedRedirectNote(overlay) {
63359
63538
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
63360
63539
  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)`;
63361
63540
  }
63362
63541
  function posix3(p) {
63363
- return resolve50(p).replace(/\\/g, "/");
63542
+ return resolve51(p).replace(/\\/g, "/");
63364
63543
  }
63365
63544
  function committedShellProvisioning(path2) {
63366
63545
  return committedShellFor(posix3(path2));
@@ -63368,8 +63547,8 @@ function committedShellProvisioning(path2) {
63368
63547
  function findRepoRoot(cwd) {
63369
63548
  let dir = cwd;
63370
63549
  for (let i = 0; i < 8; i++) {
63371
- if (SHELL_NAMES2.some((name) => existsSync64(join63(dir, shellAppDir(name), "package.json")))) return dir;
63372
- const next = dirname35(dir);
63550
+ if (SHELL_NAMES2.some((name) => existsSync65(join64(dir, shellAppDir(name), "package.json")))) return dir;
63551
+ const next = dirname36(dir);
63373
63552
  if (next === dir) break;
63374
63553
  dir = next;
63375
63554
  }
@@ -63394,7 +63573,7 @@ function assertNotCommitted(path2, forbidden) {
63394
63573
  `refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
63395
63574
  );
63396
63575
  }
63397
- if (forbidden && resolve50(path2) === resolve50(forbidden)) {
63576
+ if (forbidden && resolve51(path2) === resolve51(forbidden)) {
63398
63577
  const named = committedShellProvisioning(forbidden);
63399
63578
  throw new Error(
63400
63579
  `refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
@@ -63439,36 +63618,36 @@ function mergeCustomerOwned(committed, overlay) {
63439
63618
  }
63440
63619
  function buildMergedContract(options) {
63441
63620
  const { appDir: appDir3, packageDir, overlay } = options;
63442
- const committedPath = join63(appDir3, "provisioning.json");
63443
- if (!existsSync64(committedPath)) {
63621
+ const committedPath = join64(appDir3, "provisioning.json");
63622
+ if (!existsSync65(committedPath)) {
63444
63623
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
63445
63624
  }
63446
- const committed = JSON.parse(readFileSync76(committedPath, "utf8"));
63625
+ const committed = JSON.parse(readFileSync77(committedPath, "utf8"));
63447
63626
  const merged = mergeCustomerOwned(committed, overlay);
63448
63627
  const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
63449
63628
  const branding = merged.branding ?? {};
63450
63629
  const staged = [];
63451
63630
  const contained = (root, rel) => {
63452
- if (isAbsolute6(rel)) return void 0;
63453
- const full = resolve50(root, rel);
63454
- return full.startsWith(resolve50(root) + sep16) ? full : void 0;
63631
+ if (isAbsolute7(rel)) return void 0;
63632
+ const full = resolve51(root, rel);
63633
+ return full.startsWith(resolve51(root) + sep17) ? full : void 0;
63455
63634
  };
63456
63635
  const stage = (fromRel, toRel) => {
63457
63636
  const from = contained(packageDir, fromRel);
63458
- const to = contained(join63(appDir3, STAGED), toRel.slice(STAGED.length + 1));
63459
- if (!from || !to || !existsSync64(from)) return void 0;
63637
+ const to = contained(join64(appDir3, STAGED), toRel.slice(STAGED.length + 1));
63638
+ if (!from || !to || !existsSync65(from)) return void 0;
63460
63639
  let real;
63461
63640
  let realRoot;
63462
63641
  try {
63463
- real = realpathSync9(from);
63464
- realRoot = realpathSync9(packageDir);
63642
+ real = realpathSync10(from);
63643
+ realRoot = realpathSync10(packageDir);
63465
63644
  } catch {
63466
63645
  return void 0;
63467
63646
  }
63468
- if (!real.startsWith(realRoot + sep16)) return void 0;
63647
+ if (!real.startsWith(realRoot + sep17)) return void 0;
63469
63648
  try {
63470
- if (!statSync17(real).isFile()) return void 0;
63471
- mkdirSync31(dirname35(to), { recursive: true });
63649
+ if (!statSync18(real).isFile()) return void 0;
63650
+ mkdirSync32(dirname36(to), { recursive: true });
63472
63651
  copyFileSync3(real, to);
63473
63652
  } catch {
63474
63653
  return void 0;
@@ -63478,11 +63657,11 @@ function buildMergedContract(options) {
63478
63657
  };
63479
63658
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
63480
63659
  if (icon) branding.appIconPath = icon;
63481
- const facesPath = join63(packageDir, "media/fonts/faces.json");
63482
- if (existsSync64(facesPath)) {
63660
+ const facesPath = join64(packageDir, "media/fonts/faces.json");
63661
+ if (existsSync65(facesPath)) {
63483
63662
  let faces = [];
63484
63663
  try {
63485
- const parsed = JSON.parse(readFileSync76(facesPath, "utf8"));
63664
+ const parsed = JSON.parse(readFileSync77(facesPath, "utf8"));
63486
63665
  faces = Array.isArray(parsed) ? parsed : [];
63487
63666
  } catch {
63488
63667
  faces = [];
@@ -63503,11 +63682,11 @@ function buildMergedContract(options) {
63503
63682
  merged.branding = branding;
63504
63683
  const body = `${JSON.stringify(merged, null, 2)}
63505
63684
  `;
63506
- const path2 = join63(packageDir, "provisioning.contract.json");
63507
- writeFileSync27(path2, body);
63508
- const localPath = join63(appDir3, LOCAL_CONTRACT_REL);
63509
- mkdirSync31(dirname35(localPath), { recursive: true });
63510
- writeFileSync27(localPath, body);
63685
+ const path2 = join64(packageDir, "provisioning.contract.json");
63686
+ writeFileSync28(path2, body);
63687
+ const localPath = join64(appDir3, LOCAL_CONTRACT_REL);
63688
+ mkdirSync32(dirname36(localPath), { recursive: true });
63689
+ writeFileSync28(localPath, body);
63511
63690
  staged.push(localPath);
63512
63691
  return { path: path2, staged };
63513
63692
  }
@@ -63540,10 +63719,10 @@ function catalogTypography(overlay, template) {
63540
63719
  function staticFaqFor(overlay, overlayPath) {
63541
63720
  const own3 = overlay.faq;
63542
63721
  if (own3 !== void 0) return deriveStaticFaq(own3);
63543
- const bookPath = join63(dirname35(resolve50(overlayPath)), "book.json");
63544
- if (!existsSync64(bookPath)) return void 0;
63722
+ const bookPath = join64(dirname36(resolve51(overlayPath)), "book.json");
63723
+ if (!existsSync65(bookPath)) return void 0;
63545
63724
  try {
63546
- const book = JSON.parse(readFileSync76(bookPath, "utf8"));
63725
+ const book = JSON.parse(readFileSync77(bookPath, "utf8"));
63547
63726
  const copy = book?.copy;
63548
63727
  if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
63549
63728
  const pairs = deriveStaticFaq(copy.faq);
@@ -63554,11 +63733,11 @@ function staticFaqFor(overlay, overlayPath) {
63554
63733
  }
63555
63734
  }
63556
63735
  async function applyOverlays(input) {
63557
- const cwd = resolve50(input.cwd);
63736
+ const cwd = resolve51(input.cwd);
63558
63737
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
63559
63738
  assertKnownShell(shell);
63560
- const overlay = JSON.parse(readFileSync76(input.overlayPath, "utf8"));
63561
- const tokens = JSON.parse(readFileSync76(input.tokensPath, "utf8"));
63739
+ const overlay = JSON.parse(readFileSync77(input.overlayPath, "utf8"));
63740
+ const tokens = JSON.parse(readFileSync77(input.tokensPath, "utf8"));
63562
63741
  const faq = staticFaqFor(overlay, input.overlayPath);
63563
63742
  if (faq !== void 0) overlay.faq = faq;
63564
63743
  const wrote = [];
@@ -63570,15 +63749,15 @@ async function applyOverlays(input) {
63570
63749
  `shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
63571
63750
  );
63572
63751
  }
63573
- const appDir3 = join63(repoRoot2, shellAppDir(shell));
63574
- const committedPath = join63(appDir3, "provisioning.json");
63575
- const committedSite = existsSync64(committedPath) ? JSON.parse(readFileSync76(committedPath, "utf8")).site : void 0;
63752
+ const appDir3 = join64(repoRoot2, shellAppDir(shell));
63753
+ const committedPath = join64(appDir3, "provisioning.json");
63754
+ const committedSite = existsSync65(committedPath) ? JSON.parse(readFileSync77(committedPath, "utf8")).site : void 0;
63576
63755
  if (committedSite !== void 0 && overlay.site === void 0) {
63577
63756
  throw new Error(
63578
63757
  `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.`
63579
63758
  );
63580
63759
  }
63581
- const packageDir = dirname35(resolve50(input.overlayPath));
63760
+ const packageDir = dirname36(resolve51(input.overlayPath));
63582
63761
  const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
63583
63762
  wrote.push(...staged);
63584
63763
  const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -63599,22 +63778,22 @@ async function applyOverlays(input) {
63599
63778
  note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
63600
63779
  };
63601
63780
  }
63602
- const pkgProv = join63(cwd, "provisioning.json");
63781
+ const pkgProv = join64(cwd, "provisioning.json");
63603
63782
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
63604
63783
  let packageFaq = faq;
63605
- if (existsSync64(pkgProv)) {
63606
- const cur = JSON.parse(readFileSync76(pkgProv, "utf8"));
63784
+ if (existsSync65(pkgProv)) {
63785
+ const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
63607
63786
  const merged = deepMerge4(cur, overlay);
63608
63787
  packageFaq = merged.faq;
63609
- writeFileSync27(pkgProv, JSON.stringify(merged, null, 2) + "\n");
63788
+ writeFileSync28(pkgProv, JSON.stringify(merged, null, 2) + "\n");
63610
63789
  wrote.push(pkgProv);
63611
63790
  } else {
63612
- writeFileSync27(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
63791
+ writeFileSync28(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
63613
63792
  wrote.push(pkgProv);
63614
63793
  }
63615
- const pkgTokens = join63(cwd, "tokens.json");
63616
- if (existsSync64(pkgTokens) && (tokens.colors || tokens.typography)) {
63617
- const cur = JSON.parse(readFileSync76(pkgTokens, "utf8"));
63794
+ const pkgTokens = join64(cwd, "tokens.json");
63795
+ if (existsSync65(pkgTokens) && (tokens.colors || tokens.typography)) {
63796
+ const cur = JSON.parse(readFileSync77(pkgTokens, "utf8"));
63618
63797
  let tokensIn = tokens;
63619
63798
  if (tokens.typography) {
63620
63799
  const fonts = catalogTypography(tokens.typography, cur.typography);
@@ -63635,13 +63814,13 @@ async function applyOverlays(input) {
63635
63814
  if (primary && glow && typeof glow.color === "string") glow.color = primary;
63636
63815
  stripBrandFromIdiom(merged);
63637
63816
  }
63638
- writeFileSync27(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
63817
+ writeFileSync28(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
63639
63818
  wrote.push(pkgTokens);
63640
63819
  }
63641
63820
  const homeAction = homeRefreshActionId(shell);
63642
- const homeSrc = join63(cwd, "dev/index.ts");
63643
- if (homeAction && existsSync64(homeSrc)) {
63644
- const prev = readFileSync76(homeSrc, "utf8");
63821
+ const homeSrc = join64(cwd, "dev/index.ts");
63822
+ if (homeAction && existsSync65(homeSrc)) {
63823
+ const prev = readFileSync77(homeSrc, "utf8");
63645
63824
  const patched = patchBrandParams(prev, overlay, homeAction);
63646
63825
  let next = patched.src;
63647
63826
  if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
@@ -63665,20 +63844,20 @@ async function applyOverlays(input) {
63665
63844
  }
63666
63845
  }
63667
63846
  if (next !== prev) {
63668
- writeFileSync27(homeSrc, next);
63847
+ writeFileSync28(homeSrc, next);
63669
63848
  wrote.push(homeSrc);
63670
63849
  }
63671
63850
  if (patched.unparsed) {
63672
63851
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
63673
63852
  }
63674
63853
  }
63675
- if (!input.iconPath || !existsSync64(input.iconPath)) {
63676
- const book = input.iconPath ? dirname35(dirname35(resolve50(input.iconPath))) : void 0;
63854
+ if (!input.iconPath || !existsSync65(input.iconPath)) {
63855
+ const book = input.iconPath ? dirname36(dirname36(resolve51(input.iconPath))) : void 0;
63677
63856
  notes.push(
63678
63857
  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"
63679
63858
  );
63680
63859
  }
63681
- if (input.iconPath && existsSync64(input.iconPath)) {
63860
+ if (input.iconPath && existsSync65(input.iconPath)) {
63682
63861
  try {
63683
63862
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
63684
63863
  wrote.push(...installed.wrote);
@@ -64792,10 +64971,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
64792
64971
  }
64793
64972
  function createPromiseCallback(cb) {
64794
64973
  let callback;
64795
- let resolve53;
64974
+ let resolve54;
64796
64975
  let reject;
64797
64976
  const promise = new Promise((_resolve, _reject) => {
64798
- resolve53 = _resolve;
64977
+ resolve54 = _resolve;
64799
64978
  reject = _reject;
64800
64979
  });
64801
64980
  if (typeof cb === "function") {
@@ -64811,7 +64990,7 @@ function createPromiseCallback(cb) {
64811
64990
  callback = (err, result) => {
64812
64991
  try {
64813
64992
  if (err) reject(err);
64814
- else resolve53(result);
64993
+ else resolve54(result);
64815
64994
  } catch (e) {
64816
64995
  reject(e instanceof Error ? e : new Error());
64817
64996
  }
@@ -67899,14 +68078,14 @@ async function runSiteFunction(opts) {
67899
68078
  }
67900
68079
  if (opts.op === "publish") {
67901
68080
  const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
67902
- const ok = httpOk(snap.rev) && httpOk(snap.live);
68081
+ const ok2 = httpOk(snap.rev) && httpOk(snap.live);
67903
68082
  return {
67904
68083
  ...base,
67905
- ok,
68084
+ ok: ok2,
67906
68085
  revision: snap.revision,
67907
68086
  codeAppId: snap.codeAppId,
67908
68087
  publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
67909
- error: ok ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
68088
+ error: ok2 ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
67910
68089
  };
67911
68090
  }
67912
68091
  const { id, listed } = await withGrid(fetchImpl, opts.token, opts.msid, opts.siteUrl);
@@ -68001,12 +68180,12 @@ async function invokeAndReport(fetchImpl, opts, base, name, method) {
68001
68180
  await new Promise((res) => setTimeout(res, 2500));
68002
68181
  hit = await tryInvoke();
68003
68182
  }
68004
- const ok = httpOk(hit.r);
68183
+ const ok2 = httpOk(hit.r);
68005
68184
  return {
68006
68185
  ...base,
68007
- ok,
68186
+ ok: ok2,
68008
68187
  invoke: { url: hit.url, status: hit.r.status, body: hit.r.json ?? snippet2(hit.r.text) },
68009
- error: ok ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
68188
+ error: ok2 ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
68010
68189
  };
68011
68190
  }
68012
68191
  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;
@@ -68034,14 +68213,19 @@ __export(cli_exports, {
68034
68213
  APPLY_NEEDS_CLIENT: () => APPLY_NEEDS_CLIENT,
68035
68214
  REDIRECT_NEEDS_CLIENT: () => REDIRECT_NEEDS_CLIENT,
68036
68215
  SITE_FUNCTION_USAGE: () => SITE_FUNCTION_USAGE,
68216
+ applyNeedsClient: () => applyNeedsClient,
68037
68217
  assetFetchFor: () => assetFetchFor,
68038
68218
  noteWithWarnings: () => noteWithWarnings,
68039
68219
  ownerSiteFor: () => ownerSiteFor,
68040
68220
  runSiteAnalyze: () => runSiteAnalyze,
68041
68221
  runSiteFunctionCli: () => runSiteFunctionCli
68042
68222
  });
68043
- import { readFileSync as readFileSync77 } from "node:fs";
68044
- import { resolve as resolve51 } from "node:path";
68223
+ import { readFileSync as readFileSync78 } from "node:fs";
68224
+ import { resolve as resolve52 } from "node:path";
68225
+ function applyNeedsClient(shell) {
68226
+ if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
68227
+ return !isSiteShell(shell);
68228
+ }
68045
68229
  function assetFetchFor(_opts) {
68046
68230
  return pinnedFetch2;
68047
68231
  }
@@ -68054,14 +68238,14 @@ function ownerSiteFor(opts, env = process.env) {
68054
68238
  async function runSiteAnalyze(opts) {
68055
68239
  if (opts.shell !== void 0) assertKnownShell(opts.shell);
68056
68240
  if (!opts.clientId?.trim()) {
68057
- if (opts.apply) throw Object.assign(new Error(APPLY_NEEDS_CLIENT), { exit: 2 });
68241
+ if (opts.apply && applyNeedsClient(opts.shell)) throw Object.assign(new Error(APPLY_NEEDS_CLIENT), { exit: 2 });
68058
68242
  if (opts.redirectUri?.trim()) throw Object.assign(new Error(REDIRECT_NEEDS_CLIENT), { exit: 2 });
68059
68243
  }
68060
68244
  const fetchImpl = opts.fetchImpl ?? fetch;
68061
68245
  const assetFetch = assetFetchFor(opts);
68062
68246
  const siteFetch = guardedSiteFetch;
68063
68247
  const cwd = opts.cwd ?? process.cwd();
68064
- const outDir = resolve51(cwd, opts.outDir ?? ".himi/business-book");
68248
+ const outDir = resolve52(cwd, opts.outDir ?? ".himi/business-book");
68065
68249
  let ownerAuth;
68066
68250
  let msid;
68067
68251
  const ownerSite = ownerSiteFor(opts);
@@ -68089,7 +68273,10 @@ async function runSiteAnalyze(opts) {
68089
68273
  try {
68090
68274
  const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look });
68091
68275
  result.provisioningOverlay.site = derived.site;
68092
- result.warnings = [...result.warnings ?? [], ...derived.notes];
68276
+ const warnings2 = (result.warnings ?? []).map(
68277
+ (w) => !opts.clientId?.trim() && w.startsWith("no --client-id:") ? `no --client-id: fine for --shell ${opts.shell} \u2014 a site shell binds no client, so --apply works without one. Only the vertical probes were skipped, so the catalog has no counts.` : w
68278
+ );
68279
+ result.warnings = [...warnings2, ...derived.notes];
68093
68280
  } catch (e) {
68094
68281
  result.warnings = [
68095
68282
  ...result.warnings ?? [],
@@ -68113,9 +68300,9 @@ async function runSiteAnalyze(opts) {
68113
68300
  if (opts.apply) {
68114
68301
  applied = await applyOverlays({
68115
68302
  cwd,
68116
- overlayPath: resolve51(outDir, "provisioning.overlay.json"),
68117
- tokensPath: resolve51(outDir, "tokens.overlay.json"),
68118
- iconPath: resolve51(outDir, "media/icon.png"),
68303
+ overlayPath: resolve52(outDir, "provisioning.overlay.json"),
68304
+ tokensPath: resolve52(outDir, "tokens.overlay.json"),
68305
+ iconPath: resolve52(outDir, "media/icon.png"),
68119
68306
  shell: opts.shell
68120
68307
  });
68121
68308
  const note = noteWithWarnings(applied.note, warnings);
@@ -68151,8 +68338,8 @@ async function runSiteFunctionCli(opts) {
68151
68338
  const token = opts.token ?? await siteToken(msid);
68152
68339
  let source;
68153
68340
  if (opts.sourcePath) {
68154
- const p = resolve51(opts.cwd ?? process.cwd(), opts.sourcePath);
68155
- source = readFileSync77(p, "utf8");
68341
+ const p = resolve52(opts.cwd ?? process.cwd(), opts.sourcePath);
68342
+ source = readFileSync78(p, "utf8");
68156
68343
  }
68157
68344
  let body;
68158
68345
  if (opts.bodyRaw != null) {
@@ -68207,7 +68394,7 @@ async function accountToken2(spawnImpl = spawn6) {
68207
68394
  cached2 = fromEnv;
68208
68395
  return fromEnv;
68209
68396
  }
68210
- const token = await new Promise((resolve53, reject) => {
68397
+ const token = await new Promise((resolve54, reject) => {
68211
68398
  let child;
68212
68399
  try {
68213
68400
  child = spawnImpl("wix", ["token"]);
@@ -68236,7 +68423,7 @@ async function accountToken2(spawnImpl = spawn6) {
68236
68423
  const scan = (d) => {
68237
68424
  out2 += String(d);
68238
68425
  const m = out2.match(TOKEN_RE2);
68239
- if (m) done(() => resolve53(m[0]));
68426
+ if (m) done(() => resolve54(m[0]));
68240
68427
  };
68241
68428
  child.stdout?.on("data", scan);
68242
68429
  child.stderr?.on("data", scan);
@@ -68413,7 +68600,7 @@ __export(site_create_exports, {
68413
68600
  runSiteList: () => runSiteList,
68414
68601
  writeProvisioningBinding: () => writeProvisioningBinding
68415
68602
  });
68416
- import { existsSync as existsSync65, readFileSync as readFileSync78, writeFileSync as writeFileSync28 } from "node:fs";
68603
+ import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync29 } from "node:fs";
68417
68604
  import { resolve as resolvePath2 } from "node:path";
68418
68605
  function oauthClientName(projectName) {
68419
68606
  return `${projectName} client`;
@@ -68562,7 +68749,7 @@ async function runSiteCreate(opts) {
68562
68749
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
68563
68750
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
68564
68751
  }
68565
- function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync65, readFileSync: readFileSync78, writeFileSync: writeFileSync28 }) {
68752
+ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync29 }) {
68566
68753
  const msid = binding2.siteId;
68567
68754
  const path2 = resolvePath2(target);
68568
68755
  const committed = committedShellProvisioning(path2);
@@ -69235,12 +69422,12 @@ var init_context = __esm({
69235
69422
  });
69236
69423
 
69237
69424
  // src/cli.ts
69238
- 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";
69425
+ 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";
69239
69426
  import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
69240
69427
  import { AsyncLocalStorage } from "node:async_hooks";
69241
69428
  import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
69242
69429
  import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
69243
- import { join as join64, resolve as resolve52, relative as relative13, basename as basename17, dirname as dirname36 } from "node:path";
69430
+ import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
69244
69431
  import { fileURLToPath as fileURLToPath26 } from "node:url";
69245
69432
 
69246
69433
  // ../serve-cli/src/client.ts
@@ -69981,7 +70168,7 @@ async function browserLogin(opts) {
69981
70168
  const log = opts.log ?? (() => {
69982
70169
  });
69983
70170
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
69984
- return await new Promise((resolve53, reject) => {
70171
+ return await new Promise((resolve54, reject) => {
69985
70172
  let settled = false;
69986
70173
  let loginUrl = "";
69987
70174
  const server = createServer();
@@ -70045,7 +70232,7 @@ async function browserLogin(opts) {
70045
70232
  return;
70046
70233
  }
70047
70234
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
70048
- finish2(() => resolve53({ token, loginUrl }));
70235
+ finish2(() => resolve54({ token, loginUrl }));
70049
70236
  });
70050
70237
  });
70051
70238
  server.on("error", (err) => finish2(() => reject(err)));
@@ -71375,8 +71562,8 @@ var str8 = (v) => typeof v === "string" ? v : void 0;
71375
71562
  var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
71376
71563
  function embeddedTemplateCatalog() {
71377
71564
  return availableTemplates().map((name) => {
71378
- const path2 = join64(templateSourceDir(name), TEMPLATE_META_FILE);
71379
- const meta = JSON.parse(readFileSync79(path2, "utf8"));
71565
+ const path2 = join65(templateSourceDir(name), TEMPLATE_META_FILE);
71566
+ const meta = JSON.parse(readFileSync80(path2, "utf8"));
71380
71567
  if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
71381
71568
  throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
71382
71569
  }
@@ -71934,7 +72121,8 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
71934
72121
  a brandable shell's content package. --url alone is the
71935
72122
  visitor-only pass (published pages, look, copy); --client-id
71936
72123
  adds the vertical catalog counts and the app binding, and
71937
- --apply requires it. --shell takes the same
72124
+ --apply requires it (not for a site shell, which binds no
72125
+ client). --shell takes the same
71938
72126
  names 'himi dist --shell' does; default branded-lite.
71939
72127
  A SITE shell (brandy) also derives the site's page map
71940
72128
  (tabs/drawer from its menu) into the overlay's \`site\`
@@ -72049,7 +72237,7 @@ var COMMANDS = [
72049
72237
  { name: "login", summary: "obtain a scoped serve-control token from Wix identity and store it in ~/.himalaya/serve-targets.json (so push/promote need no hand-pasted token). Three modes: --browser (your own Wix account, no VPN/BO), --wix (HEADLESS \u2014 the machine's own Wix CLI credential; the mode a CI pod or agent container can satisfy), --dpx (Wix employee, reads ~/.dpx/session/token). RFC 0026 WS3.", required: "[--browser|--wix|--dpx] [--target <t>] [--issue-url <url>]" },
72050
72238
  { name: "logout", summary: "remove the stored control token for a target", required: "[--target <t>]" },
72051
72239
  { name: "notify", summary: "`setup` optionally configures Branded/Ping from local customer key files; `status --refresh` reads live backend readiness. Setup may be deferred while building. These use serve-control and require owner plus Wix account authentication. `send`, `tokens`, `doctor`: send a REAL push notification to registered devices (RFC 0036 WS5) \u2014 APNs .p8 over HTTP/2 for iOS, FCM v1 for Android. `send` targets one device (--token / --device <registry id>) or fans out to the whole app (--all), reporting a per-device result; a token the provider says is uninstalled (APNs 410 Unregistered / FCM UNREGISTERED) is auto-disabled, while a merely wrong one (BadDeviceToken \u2014 usually a sandbox/production mismatch) is recorded and left enabled. `tokens` lists the registry. `doctor` reports which credentials resolve and which sender each platform picks. Talks to the admin-server via --admin-url/HIMALAYA_ADMIN_URL, authenticated with --admin-session/HIMALAYA_ADMIN_SESSION. `send --provider ping` is the hosted alternative: the serve plane sends one test notification to one site member through Ping as Himalaya, with owner login instead of provider keys, and reports acceptance, never delivery. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send --provider ping [--content <dir>] [--app <a>] [--site <msid>] --member-email <email> --title <s> [--body <s>] --link <url> [--request-id <uuid>] [--dry-run] [--json] | send|tokens|doctor [--app <a>] [--token <t> | --device <id> | --all] [--title <s>] [--body <s>] [--link <url>] [--platform ios|android] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]" },
72052
- { name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no URL/browser and never uploads or applies anything. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell; `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--json] | analyze --url <https> [--client-id <id>] [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
72240
+ { name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no URL/browser and never uploads or applies anything. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell (a site shell needs no `--client-id`: it is visitor-only and binds no client); `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--json] | analyze --url <https> [--client-id <id>] [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
72053
72241
  { name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
72054
72242
  { name: "upgrade", summary: "install the newest published CLI (`npm i -g @wix/himalaya-cli@latest`) and report what moved. This is the explicit door: himi also updates itself when the running build is more than a week old \u2014 unattended it just does it and re-runs your command, at a terminal it asks first \u2014 and `HIMI_NO_UPDATE_CHECK=1` turns that off, leaving this command as the way to catch up. Reports `unchanged` rather than claiming success when npm exits 0 without moving the version, which is what a registry mirror serving its own pinned copy looks like.", required: "[--json]" },
72055
72243
  { name: "push", summary: "lint + build + publish a release (default --draft: servable via ?release= but NOT live). REFUSES to publish on any error unless --force; --strict promotes warnings. Prints preview + agent-context links. A successful draft push also rebuilds the making-of (.himi/making-of.html, local and offline) and names it as `reel` \u2014 the file to hand the owner beside the preview link. Its postcard carries the home shot only when that shot is newer than the last source edit; otherwise the postcard says why and names `himi render <home> --png`, and the envelope's `postcardPicture: {skipped, render}` leads next[] with that render (the push never renders it itself). The published slug is NAMESPACED per owner \u2014 `<ownerPrefix>.<name>`, composed offline from the control token's ownerPrefix claim, so the CLI and the server derive the identical string and himalaya.content.json is NOT rewritten (a legacy token with no ownerPrefix publishes the declared name unchanged). An app claimed BEFORE namespacing is stored under its FLAT slug, so the claim route answers `alreadyYours` naming that slug and the push adopts it \u2014 reported as `adoptedSlug`, since it is the one case where the published `app` differs from what the declared name composes to. `--no-claim` skips the route that knows this, so a pre-namespacing app pushed with it still fails 403. --visibility public|unlisted decides whether /v1/apps + the Himi Player picker LIST the app (also declarable as `visibility` in himalaya.content.json; omitted, a brand-new app defaults to unlisted \u2014 share by link \u2014 and an existing setting is kept). --account-id names which account owns the app when your Wix session resolves to several (the auto-claim of a brand-new slug cannot guess \u2014 without it a multi-account caller is told to name one). An unforced push of a release that carries SCREENS also refuses when `.himi/ux-audit.json` holds no mobile-UX drive recorded against that release id, or holds one that FAILED (#2955) \u2014 a published draft IS the owner-private preview a customer is handed; `himi ux record` clears it and `--force` overrides it, which the success envelope then says out loud. `--only <selector>` publishes ONLY the named items as a release derived from the app's live release (or `--from-release <id>`), running the identical build + lint gate and simply publishing less; it requires an explicit `--draft` or `--live` because a partial publish has no safe default, never claims a slug, and carries neither attestation nor a source archive (both named in the output). Selectors are comma-separated in ONE `--only`: `changed` (every item whose bytes differ from the base), `screen:<id|glob>`, `bundle:<name>`, `tokens`, `app-config` \u2014 a selected screen drags its logic bundle and a selected bundle drags the screens that reference it, or the bytes land under a key nothing reads.", required: "[--content <dir>] [--draft] [--live] [--force] [--strict] [--label] [--notes] [--visibility public|unlisted] [--no-claim] [--account-id <id>] [--only <selector>] [--from-release <id>] [--accept-regressions] [--accept-partial] [--app <slug>] (--control-token)" },
@@ -72058,7 +72246,7 @@ var COMMANDS = [
72058
72246
  { 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>]" },
72059
72247
  { 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>" },
72060
72248
  { 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>]" },
72061
- { 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.", required: "[plugin --out <dir>]" },
72249
+ { 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]" },
72062
72250
  { 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]" },
72063
72251
  { 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]" },
72064
72252
  { 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]" },
@@ -72090,7 +72278,7 @@ var COMMANDS = [
72090
72278
  ];
72091
72279
  function cliVersion() {
72092
72280
  try {
72093
- return JSON.parse(readFileSync79(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
72281
+ return JSON.parse(readFileSync80(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
72094
72282
  } catch {
72095
72283
  return "unknown";
72096
72284
  }
@@ -72141,16 +72329,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
72141
72329
  }
72142
72330
  var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
72143
72331
  function execNpmConfig(file, args, options) {
72144
- return new Promise((resolve53, reject) => {
72145
- execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve53(String(stdout)));
72332
+ return new Promise((resolve54, reject) => {
72333
+ execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve54(String(stdout)));
72146
72334
  });
72147
72335
  }
72148
72336
  var npmScopedWixRegistry = createScopedRegistryResolver();
72149
72337
  async function scopedRegistryBefore(lookup2, deadline) {
72150
72338
  let cancel = () => {
72151
72339
  };
72152
- const expired = new Promise((resolve53) => {
72153
- const timer = setTimeout(() => resolve53(void 0), Math.max(0, deadline - Date.now()));
72340
+ const expired = new Promise((resolve54) => {
72341
+ const timer = setTimeout(() => resolve54(void 0), Math.max(0, deadline - Date.now()));
72154
72342
  cancel = () => clearTimeout(timer);
72155
72343
  });
72156
72344
  try {
@@ -72208,18 +72396,18 @@ function ageInDays(publishedAt, now = Date.now()) {
72208
72396
  }
72209
72397
  function packageVersion(path2) {
72210
72398
  try {
72211
- const version2 = JSON.parse(readFileSync79(path2, "utf8")).version;
72399
+ const version2 = JSON.parse(readFileSync80(path2, "utf8")).version;
72212
72400
  return typeof version2 === "string" && version2 ? version2 : void 0;
72213
72401
  } catch {
72214
72402
  return void 0;
72215
72403
  }
72216
72404
  }
72217
72405
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
72218
- let dir = resolve52(fromDir);
72406
+ let dir = resolve53(fromDir);
72219
72407
  for (; ; ) {
72220
- const version2 = packageVersion(join64(dir, "node_modules", "@wix", "himalaya", "package.json"));
72408
+ const version2 = packageVersion(join65(dir, "node_modules", "@wix", "himalaya", "package.json"));
72221
72409
  if (version2) return { version: version2, source: "local" };
72222
- const parent = dirname36(dir);
72410
+ const parent = dirname37(dir);
72223
72411
  if (parent === dir) break;
72224
72412
  dir = parent;
72225
72413
  }
@@ -72227,7 +72415,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
72227
72415
  if (bundled) return { version: bundled, source: "bundled" };
72228
72416
  try {
72229
72417
  const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
72230
- const version2 = root ? packageVersion(join64(root, "@wix", "himalaya", "package.json")) : void 0;
72418
+ const version2 = root ? packageVersion(join65(root, "@wix", "himalaya", "package.json")) : void 0;
72231
72419
  return version2 ? { version: version2, source: "global" } : {};
72232
72420
  } catch {
72233
72421
  return {};
@@ -72274,11 +72462,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
72274
72462
  var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
72275
72463
  var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
72276
72464
  function updateCachePath(env = process.env) {
72277
- return env.HIMI_UPDATE_CACHE_FILE ?? join64(homedir7(), ".himalaya", "update-check.json");
72465
+ return env.HIMI_UPDATE_CACHE_FILE ?? join65(homedir7(), ".himalaya", "update-check.json");
72278
72466
  }
72279
72467
  function readUpdateCache(path2) {
72280
72468
  try {
72281
- const parsed = JSON.parse(readFileSync79(path2, "utf8"));
72469
+ const parsed = JSON.parse(readFileSync80(path2, "utf8"));
72282
72470
  return parsed && typeof parsed === "object" ? parsed : {};
72283
72471
  } catch {
72284
72472
  return {};
@@ -72286,8 +72474,8 @@ function readUpdateCache(path2) {
72286
72474
  }
72287
72475
  function writeUpdateCache(path2, cache) {
72288
72476
  try {
72289
- mkdirSync32(dirname36(path2), { recursive: true, mode: 448 });
72290
- writeFileSync29(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
72477
+ mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
72478
+ writeFileSync30(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
72291
72479
  } catch {
72292
72480
  }
72293
72481
  }
@@ -72347,12 +72535,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
72347
72535
  },
72348
72536
  installedVersion: () => {
72349
72537
  const root = globalNodeModulesRoot();
72350
- return root ? packageVersion(join64(root, "@wix", "himalaya-cli", "package.json")) : void 0;
72538
+ return root ? packageVersion(join65(root, "@wix", "himalaya-cli", "package.json")) : void 0;
72351
72539
  },
72352
72540
  reexec: (argv) => {
72353
72541
  const root = globalNodeModulesRoot();
72354
- const entry = root ? join64(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
72355
- if (!entry || !existsSync66(entry)) return void 0;
72542
+ const entry = root ? join65(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
72543
+ if (!entry || !existsSync67(entry)) return void 0;
72356
72544
  const result = spawnSync5(process.execPath, [entry, ...argv], {
72357
72545
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
72358
72546
  stdio: "inherit",
@@ -72399,7 +72587,7 @@ function staleUpdateLockFile(cachePath, now) {
72399
72587
  for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
72400
72588
  let content;
72401
72589
  try {
72402
- content = readFileSync79(path2, "utf8");
72590
+ content = readFileSync80(path2, "utf8");
72403
72591
  } catch {
72404
72592
  continue;
72405
72593
  }
@@ -72407,7 +72595,7 @@ function staleUpdateLockFile(cachePath, now) {
72407
72595
  let since = stamped;
72408
72596
  if (!Number.isFinite(since)) {
72409
72597
  try {
72410
- since = statSync18(path2).mtimeMs;
72598
+ since = statSync19(path2).mtimeMs;
72411
72599
  } catch {
72412
72600
  continue;
72413
72601
  }
@@ -72422,14 +72610,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72422
72610
  const mine = lockStamp(now);
72423
72611
  const readLock = (path2) => {
72424
72612
  try {
72425
- return readFileSync79(path2, "utf8");
72613
+ return readFileSync80(path2, "utf8");
72426
72614
  } catch {
72427
72615
  return void 0;
72428
72616
  }
72429
72617
  };
72430
72618
  const tryCreate = (path2) => {
72431
72619
  try {
72432
- writeFileSync29(path2, mine, { flag: "wx", mode: 384 });
72620
+ writeFileSync30(path2, mine, { flag: "wx", mode: 384 });
72433
72621
  return true;
72434
72622
  } catch {
72435
72623
  return false;
@@ -72437,13 +72625,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72437
72625
  };
72438
72626
  const removeIfMine = (path2) => {
72439
72627
  try {
72440
- if (readLock(path2) === mine) rmSync15(path2, { force: true });
72628
+ if (readLock(path2) === mine) rmSync16(path2, { force: true });
72441
72629
  } catch {
72442
72630
  }
72443
72631
  };
72444
72632
  const release = () => removeIfMine(lockPath);
72445
72633
  try {
72446
- mkdirSync32(dirname36(lockPath), { recursive: true, mode: 448 });
72634
+ mkdirSync33(dirname37(lockPath), { recursive: true, mode: 448 });
72447
72635
  } catch {
72448
72636
  return () => {
72449
72637
  };
@@ -72460,7 +72648,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72460
72648
  hooks.underBreakLock?.();
72461
72649
  if (current === void 0) return tryCreate(lockPath) ? release : void 0;
72462
72650
  if (!isAbandoned(current)) return void 0;
72463
- rmSync15(lockPath, { force: true });
72651
+ rmSync16(lockPath, { force: true });
72464
72652
  return tryCreate(lockPath) ? release : void 0;
72465
72653
  } finally {
72466
72654
  removeIfMine(breakPath);
@@ -72556,7 +72744,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
72556
72744
  return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
72557
72745
  };
72558
72746
  return async (dir, opts = {}) => {
72559
- const argv = ["validate", "--content", resolve52(dir), "--strict", "--skip-version-check"];
72747
+ const argv = ["validate", "--content", resolve53(dir), "--strict", "--skip-version-check"];
72560
72748
  if (!opts.fresh) {
72561
72749
  const out2 = [];
72562
72750
  const err = [];
@@ -73014,9 +73202,9 @@ function executableOnPath(name, env = process.env) {
73014
73202
  const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
73015
73203
  for (const dir of entries) {
73016
73204
  for (const suffix of suffixes) {
73017
- const candidate = join64(dir, `${name}${suffix}`);
73205
+ const candidate = join65(dir, `${name}${suffix}`);
73018
73206
  try {
73019
- if (!statSync18(candidate).isFile()) continue;
73207
+ if (!statSync19(candidate).isFile()) continue;
73020
73208
  if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
73021
73209
  return true;
73022
73210
  } catch {
@@ -73063,9 +73251,9 @@ function buildDoctorReport(input) {
73063
73251
  const versionSkew = versions?.cli.status === "outdated" || sdkSkew;
73064
73252
  const hostRefused = auth.controlTokenStatus === "refused";
73065
73253
  const staleToken = auth.controlTokenPresent === true && auth.controlToken === false && !hostRefused;
73066
- const ok = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
73254
+ const ok2 = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
73067
73255
  return {
73068
- ok,
73256
+ ok: ok2,
73069
73257
  target,
73070
73258
  version: version2,
73071
73259
  dataPlane: { ...data, note: "public Wix APIs \u2014 reachable off-VPN" },
@@ -73123,7 +73311,7 @@ async function nativeConfigAdvisories(app, configSource) {
73123
73311
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
73124
73312
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
73125
73313
  const iosYmlPath = iosProjectYml2(app);
73126
- const iosYml = existsSync66(iosYmlPath) ? readFileSync79(iosYmlPath, "utf8") : "";
73314
+ const iosYml = existsSync67(iosYmlPath) ? readFileSync80(iosYmlPath, "utf8") : "";
73127
73315
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
73128
73316
  if (!optedIn) {
73129
73317
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -73137,14 +73325,14 @@ async function nativeConfigAdvisories(app, configSource) {
73137
73325
  }
73138
73326
  function readConfigSource(dir) {
73139
73327
  try {
73140
- return readFileSync79(join64(dir, "config.ts"), "utf8");
73328
+ return readFileSync80(join65(dir, "config.ts"), "utf8");
73141
73329
  } catch {
73142
73330
  return null;
73143
73331
  }
73144
73332
  }
73145
73333
  function writePngFile(path2, base64) {
73146
- mkdirSync32(dirname36(path2), { recursive: true });
73147
- writeFileSync29(path2, Buffer.from(base64, "base64"));
73334
+ mkdirSync33(dirname37(path2), { recursive: true });
73335
+ writeFileSync30(path2, Buffer.from(base64, "base64"));
73148
73336
  return path2;
73149
73337
  }
73150
73338
  async function seedAgentFilesFor(dir, flags, mode = "init") {
@@ -73172,8 +73360,8 @@ function keptPlan(kept) {
73172
73360
  return note ? { kept, note } : {};
73173
73361
  }
73174
73362
  async function initFromRemoteTemplate(name, parentDir, template, c) {
73175
- const dir = resolve52(parentDir, name);
73176
- if (existsSync66(join64(dir, "himalaya.content.json"))) {
73363
+ const dir = resolve53(parentDir, name);
73364
+ if (existsSync67(join65(dir, "himalaya.content.json"))) {
73177
73365
  throw new Error(`content package already exists at ${dir}`);
73178
73366
  }
73179
73367
  const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -73185,7 +73373,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
73185
73373
  return finishScaffold(materializeSource(archive.files, name, dir), template);
73186
73374
  }
73187
73375
  function contentDir(flags) {
73188
- return resolve52(str8(flags.content) ?? process.cwd());
73376
+ return resolve53(str8(flags.content) ?? process.cwd());
73189
73377
  }
73190
73378
  function renameRestoredSource(restored, declaredApp, renamed) {
73191
73379
  const text8 = {};
@@ -73203,7 +73391,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
73203
73391
  function symlinkDestinationIssue(dest) {
73204
73392
  let kind;
73205
73393
  try {
73206
- kind = lstatSync13(dest);
73394
+ kind = lstatSync14(dest);
73207
73395
  } catch {
73208
73396
  return null;
73209
73397
  }
@@ -73216,11 +73404,11 @@ function symlinkDestinationIssue(dest) {
73216
73404
  function restoreDestinationIssue(dest, force) {
73217
73405
  const link = symlinkDestinationIssue(dest);
73218
73406
  if (link) return link;
73219
- if (!existsSync66(dest)) return null;
73220
- if (!statSync18(dest).isDirectory()) {
73407
+ if (!existsSync67(dest)) return null;
73408
+ if (!statSync19(dest).isDirectory()) {
73221
73409
  return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
73222
73410
  }
73223
- if (readdirSync30(dest).length > 0 && !force) {
73411
+ if (readdirSync31(dest).length > 0 && !force) {
73224
73412
  return {
73225
73413
  error: `${dest} already exists and is not empty`,
73226
73414
  hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
@@ -73229,10 +73417,10 @@ function restoreDestinationIssue(dest, force) {
73229
73417
  return null;
73230
73418
  }
73231
73419
  function isHimalayaMonorepoCheckout(start) {
73232
- let dir = resolve52(start);
73420
+ let dir = resolve53(start);
73233
73421
  for (; ; ) {
73234
- if (existsSync66(join64(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync66(join64(dir, "core", "serve", "src", "server.ts"))) return true;
73235
- const parent = dirname36(dir);
73422
+ if (existsSync67(join65(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync67(join65(dir, "core", "serve", "src", "server.ts"))) return true;
73423
+ const parent = dirname37(dir);
73236
73424
  if (parent === dir) return false;
73237
73425
  dir = parent;
73238
73426
  }
@@ -73291,8 +73479,8 @@ function materializeForPreview(appDir3, slug, displayName) {
73291
73479
  const forBuild = Object.fromEntries(
73292
73480
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
73293
73481
  );
73294
- const repoRoot2 = resolve52(fileURLToPath26(new URL("../../..", import.meta.url)));
73295
- const root = join64(repoRoot2, "node_modules", ".cache", "himi-template-preview");
73482
+ const repoRoot2 = resolve53(fileURLToPath26(new URL("../../..", import.meta.url)));
73483
+ const root = join65(repoRoot2, "node_modules", ".cache", "himi-template-preview");
73296
73484
  const stillRunning = (pid) => {
73297
73485
  try {
73298
73486
  process.kill(pid, 0);
@@ -73302,30 +73490,30 @@ function materializeForPreview(appDir3, slug, displayName) {
73302
73490
  }
73303
73491
  };
73304
73492
  try {
73305
- for (const entry of readdirSync30(root, { withFileTypes: true })) {
73493
+ for (const entry of readdirSync31(root, { withFileTypes: true })) {
73306
73494
  if (!entry.isDirectory()) continue;
73307
73495
  const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
73308
73496
  if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
73309
- rmSync15(join64(root, entry.name), { recursive: true, force: true });
73497
+ rmSync16(join65(root, entry.name), { recursive: true, force: true });
73310
73498
  }
73311
73499
  }
73312
73500
  } catch {
73313
73501
  }
73314
- const dest = join64(root, `${slug}-${process.pid}`);
73315
- rmSync15(dest, { recursive: true, force: true });
73316
- mkdirSync32(dest, { recursive: true });
73502
+ const dest = join65(root, `${slug}-${process.pid}`);
73503
+ rmSync16(dest, { recursive: true, force: true });
73504
+ mkdirSync33(dest, { recursive: true });
73317
73505
  try {
73318
73506
  materializeSource(forBuild, displayName, dest, slug);
73319
73507
  } catch (e) {
73320
- rmSync15(dest, { recursive: true, force: true });
73508
+ rmSync16(dest, { recursive: true, force: true });
73321
73509
  throw e;
73322
73510
  }
73323
73511
  return dest;
73324
73512
  }
73325
73513
  async function appId(dir) {
73326
73514
  try {
73327
- const { readFileSync: readFileSync80 } = await import("node:fs");
73328
- const m = JSON.parse(readFileSync80(join64(dir, "himalaya.content.json"), "utf8"));
73515
+ const { readFileSync: readFileSync81 } = await import("node:fs");
73516
+ const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
73329
73517
  if (m.name) return m.name;
73330
73518
  } catch {
73331
73519
  }
@@ -73333,8 +73521,8 @@ async function appId(dir) {
73333
73521
  }
73334
73522
  async function contentVisibility(dir) {
73335
73523
  try {
73336
- const { readFileSync: readFileSync80 } = await import("node:fs");
73337
- const m = JSON.parse(readFileSync80(join64(dir, "himalaya.content.json"), "utf8"));
73524
+ const { readFileSync: readFileSync81 } = await import("node:fs");
73525
+ const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
73338
73526
  if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
73339
73527
  } catch {
73340
73528
  }
@@ -73537,7 +73725,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73537
73725
  return 0;
73538
73726
  }
73539
73727
  case "agent-init": {
73540
- const dir = resolve52(str8(flags.dir) ?? process.cwd());
73728
+ const dir = resolve53(str8(flags.dir) ?? process.cwd());
73541
73729
  const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
73542
73730
  let res;
73543
73731
  try {
@@ -73559,7 +73747,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73559
73747
  ...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/" } : {},
73560
73748
  // In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
73561
73749
  // hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
73562
- ...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" } : {},
73750
+ ...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" } : {},
73563
73751
  ...res.skipped.length ? { skipped: res.skipped } : {},
73564
73752
  portalUrl: idx.portalUrl
73565
73753
  });
@@ -73582,7 +73770,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
73582
73770
  try {
73583
73771
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
73584
73772
  const bres = await buildContentForValidation2(dir, { resolution });
73585
- out2 = mkdtempSync4(join64(tmpdir5(), "himi-ux-record-"));
73773
+ out2 = mkdtempSync4(join65(tmpdir5(), "himi-ux-record-"));
73586
73774
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
73587
73775
  const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
73588
73776
  const releaseId = outcome.manifest.releaseId;
@@ -73595,7 +73783,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
73595
73783
  return null;
73596
73784
  } finally {
73597
73785
  if (out2 !== void 0) try {
73598
- rmSync15(out2, { recursive: true, force: true });
73786
+ rmSync16(out2, { recursive: true, force: true });
73599
73787
  } catch {
73600
73788
  }
73601
73789
  }
@@ -73749,7 +73937,7 @@ async function producedWidgetFamilies(dir) {
73749
73937
  }
73750
73938
  const outDir = tier5Dir.bundleOutDir(dir);
73751
73939
  try {
73752
- readdirSync30(outDir);
73940
+ readdirSync31(outDir);
73753
73941
  } catch {
73754
73942
  return { families: void 0, source: "unbuilt" };
73755
73943
  }
@@ -73760,7 +73948,7 @@ async function producedWidgetFamilies(dir) {
73760
73948
  let js;
73761
73949
  for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
73762
73950
  try {
73763
- js = readFileSync79(join64(outDir, candidate), "utf8");
73951
+ js = readFileSync80(join65(outDir, candidate), "utf8");
73764
73952
  break;
73765
73953
  } catch {
73766
73954
  }
@@ -73791,7 +73979,7 @@ async function producedWidgetFamilies(dir) {
73791
73979
  }
73792
73980
  return { families, source: "dist/bundles" };
73793
73981
  }
73794
- var boardOpen = (dir) => existsSync66(join64(dir, ".himi", "studio", "index.html"));
73982
+ var boardOpen = (dir) => existsSync67(join65(dir, ".himi", "studio", "index.html"));
73795
73983
  var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
73796
73984
  async function leaveForBoard(dir, record2, value) {
73797
73985
  if (!boardOpen(dir)) return;
@@ -73815,7 +74003,7 @@ async function liveMapFor(dir) {
73815
74003
  }
73816
74004
  var commandScratch = new AsyncLocalStorage();
73817
74005
  function commandScratchDir(prefix) {
73818
- const dir = mkdtempSync4(join64(tmpdir5(), prefix));
74006
+ const dir = mkdtempSync4(join65(tmpdir5(), prefix));
73819
74007
  commandScratch.getStore()?.push(dir);
73820
74008
  return dir;
73821
74009
  }
@@ -73826,7 +74014,7 @@ async function run(argv, io = defaultIO, deps = {}) {
73826
74014
  code = await commandScratch.run(scratch, () => runCommand(argv, io, deps));
73827
74015
  } finally {
73828
74016
  for (const dir of scratch) try {
73829
- rmSync15(dir, { recursive: true, force: true });
74017
+ rmSync16(dir, { recursive: true, force: true });
73830
74018
  } catch {
73831
74019
  }
73832
74020
  }
@@ -74094,7 +74282,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
74094
74282
  return 2;
74095
74283
  }
74096
74284
  const template = str8(flags.template);
74097
- const parentDir = resolve52(str8(flags.dir) ?? process.cwd());
74285
+ const parentDir = resolve53(str8(flags.dir) ?? process.cwd());
74098
74286
  const withAgentFiles = async (dir) => {
74099
74287
  const seeded = await seedAgentFilesFor(dir, flags);
74100
74288
  if (!seeded.agent || "error" in seeded.agent) return seeded;
@@ -74107,7 +74295,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
74107
74295
  const owed = openApprovals2(readApprovals2(dir).events).length;
74108
74296
  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`);
74109
74297
  }
74110
- const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync66(join64(parentDir, f)));
74298
+ const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync67(join65(parentDir, f)));
74111
74299
  if (planInParent.length) {
74112
74300
  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}`);
74113
74301
  }
@@ -74255,11 +74443,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74255
74443
  return 2;
74256
74444
  }
74257
74445
  }
74258
- const appDir3 = resolve52(str8(flags.dir) ?? process.cwd());
74259
- const sourceDir = resolve52(str8(flags["source-dir"]) ?? appDir3);
74446
+ const appDir3 = resolve53(str8(flags.dir) ?? process.cwd());
74447
+ const sourceDir = resolve53(str8(flags["source-dir"]) ?? appDir3);
74260
74448
  let meta;
74261
74449
  try {
74262
- meta = JSON.parse(readFileSync79(join64(sourceDir, TEMPLATE_META_FILE), "utf8"));
74450
+ meta = JSON.parse(readFileSync80(join65(sourceDir, TEMPLATE_META_FILE), "utf8"));
74263
74451
  } catch {
74264
74452
  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>)` }));
74265
74453
  return 2;
@@ -74269,7 +74457,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74269
74457
  return 2;
74270
74458
  }
74271
74459
  try {
74272
- const appearance = extractTemplateAppearance(JSON.parse(readFileSync79(join64(sourceDir, "tokens.json"), "utf8")));
74460
+ const appearance = extractTemplateAppearance(JSON.parse(readFileSync80(join65(sourceDir, "tokens.json"), "utf8")));
74273
74461
  meta = { ...appearance, ...meta };
74274
74462
  } catch {
74275
74463
  }
@@ -74291,14 +74479,14 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74291
74479
  const force = flags.force === true;
74292
74480
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
74293
74481
  const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
74294
- const out2 = mkdtempSync4(join64(tmpdir5(), "himi-template-"));
74482
+ const out2 = mkdtempSync4(join65(tmpdir5(), "himi-template-"));
74295
74483
  publishScratch.push(out2);
74296
74484
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
74297
74485
  const outcome = await buildReleaseFromContent2(buildDir, out2, {
74298
74486
  ...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
74299
74487
  collect: { lint: true, strict }
74300
74488
  });
74301
- const scaffoldSourceFindings = resolve52(sourceDir) === resolve52(appDir3) ? [] : [
74489
+ const scaffoldSourceFindings = resolve53(sourceDir) === resolve53(appDir3) ? [] : [
74302
74490
  ...tokenColorIssues(sourceDir),
74303
74491
  ...surfaceIssues(sourceDir, void 0, strict),
74304
74492
  ...await fontIssues(sourceDir, strict),
@@ -74341,11 +74529,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74341
74529
  }));
74342
74530
  return 1;
74343
74531
  }
74344
- const iconPath = str8(flags.icon) ? resolve52(str8(flags.icon)) : templateIconPath(name);
74532
+ const iconPath = str8(flags.icon) ? resolve53(str8(flags.icon)) : templateIconPath(name);
74345
74533
  let iconHash;
74346
74534
  if (iconPath) {
74347
74535
  try {
74348
- const bytes2 = readFileSync79(iconPath);
74536
+ const bytes2 = readFileSync80(iconPath);
74349
74537
  payload.icon = bytes2.toString("base64");
74350
74538
  iconHash = createHash31("sha256").update(bytes2).digest("hex");
74351
74539
  } catch {
@@ -74518,7 +74706,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74518
74706
  } finally {
74519
74707
  for (const dir of publishScratch) {
74520
74708
  try {
74521
- rmSync15(dir, { recursive: true, force: true });
74709
+ rmSync16(dir, { recursive: true, force: true });
74522
74710
  } catch (e) {
74523
74711
  io.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e.message}` }));
74524
74712
  }
@@ -74552,12 +74740,12 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74552
74740
  print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
74553
74741
  return 2;
74554
74742
  }
74555
- const { readdirSync: readdirSync31, existsSync: fileExists } = await import("node:fs");
74743
+ const { readdirSync: readdirSync32, existsSync: fileExists } = await import("node:fs");
74556
74744
  const { join: pathJoin } = await import("node:path");
74557
74745
  const targets = [];
74558
74746
  const t5 = pathJoin(dir, "tier5-src");
74559
74747
  if (fileExists(t5)) {
74560
- for (const d of readdirSync31(t5, { withFileTypes: true })) {
74748
+ for (const d of readdirSync32(t5, { withFileTypes: true })) {
74561
74749
  if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
74562
74750
  }
74563
74751
  }
@@ -74632,7 +74820,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74632
74820
  const path2 = dpxSessionTokenPath();
74633
74821
  let raw;
74634
74822
  try {
74635
- raw = readFileSync79(path2, "utf8");
74823
+ raw = readFileSync80(path2, "utf8");
74636
74824
  } catch {
74637
74825
  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`);
74638
74826
  }
@@ -74763,32 +74951,37 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74763
74951
  return 1;
74764
74952
  }
74765
74953
  const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
74766
- const dir = resolve52(out2);
74954
+ const dir = resolve53(out2);
74767
74955
  const files = himiPluginFiles2(skills.skillMd);
74768
74956
  for (const f of files) {
74769
- mkdirSync32(dirname36(join64(dir, f.path)), { recursive: true });
74770
- writeFileSync29(join64(dir, f.path), f.text);
74957
+ mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
74958
+ writeFileSync30(join65(dir, f.path), f.text);
74771
74959
  }
74772
74960
  print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
74773
74961
  return 0;
74774
74962
  }
74775
74963
  const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
74776
- await startMcpServer2({ run, version: cliVersion() });
74964
+ await startMcpServer2({
74965
+ run,
74966
+ version: cliVersion(),
74967
+ withFiles: flags["with-files"] === true,
74968
+ ...process.env.HIMI_WORKSPACE ? { workspace: resolve53(process.env.HIMI_WORKSPACE) } : {}
74969
+ });
74777
74970
  return 0;
74778
74971
  }
74779
74972
  case "studio": {
74780
74973
  const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
74781
74974
  const dir = contentDir(flags);
74782
- if (!existsSync66(join64(dir, "himalaya.content.json"))) {
74975
+ if (!existsSync67(join65(dir, "himalaya.content.json"))) {
74783
74976
  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/" }));
74784
74977
  return 2;
74785
74978
  }
74786
74979
  if (pos[1] === "reel") {
74787
74980
  const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
74788
- const out2 = resolve52(str8(flags.out) ?? join64(dir, ".himi", "making-of.html"));
74981
+ const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
74789
74982
  const { html, plan } = buildReel2(dir);
74790
- mkdirSync32(dirname36(out2), { recursive: true });
74791
- writeFileSync29(out2, html);
74983
+ mkdirSync33(dirname37(out2), { recursive: true });
74984
+ writeFileSync30(out2, html);
74792
74985
  const { pathToFileURL: pathToFileURL9 } = await import("node:url");
74793
74986
  const url2 = pathToFileURL9(out2).href;
74794
74987
  const open2 = flags["no-open"] !== true;
@@ -74857,7 +75050,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74857
75050
  } = await Promise.resolve().then(() => (init_progress(), progress_exports));
74858
75051
  const dir = contentDir(flags);
74859
75052
  const journal2 = journalPath2(dir);
74860
- const isContentPackage = existsSync66(join64(dir, "himalaya.content.json"));
75053
+ const isContentPackage = existsSync67(join65(dir, "himalaya.content.json"));
74861
75054
  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" };
74862
75055
  const message = pos.slice(1).join(" ").trim();
74863
75056
  const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
@@ -75006,7 +75199,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75006
75199
  case "test": {
75007
75200
  const dir = contentDir(flags);
75008
75201
  const structuredOutput = flags.json === true || io.isTTY !== true;
75009
- if (existsSync66(join64(dir, "functions"))) {
75202
+ if (existsSync67(join65(dir, "functions"))) {
75010
75203
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
75011
75204
  const loaded = await loadFunctionsApp2(dir);
75012
75205
  const results = [];
@@ -75138,7 +75331,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75138
75331
  io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
75139
75332
  return 2;
75140
75333
  }
75141
- const sources = collectWorkerSources2(join64(dir, "tier5-src"), screen.bundleName);
75334
+ const sources = collectWorkerSources2(join65(dir, "tier5-src"), screen.bundleName);
75142
75335
  if (!sources) {
75143
75336
  io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
75144
75337
  return 2;
@@ -75315,7 +75508,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75315
75508
  const sp = await runShotsPass2({
75316
75509
  descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
75317
75510
  tokens: outcome.tokens,
75318
- outDir: join64(dir, ".himi", "shots"),
75511
+ outDir: join65(dir, ".himi", "shots"),
75319
75512
  width: 390,
75320
75513
  layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
75321
75514
  ...budgetMs ? { budgetMs } : {},
@@ -75325,7 +75518,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75325
75518
  renderDescriptorWeb: renderDescriptorWeb2,
75326
75519
  renderPngBatch: renderPngBatch2,
75327
75520
  writePng: (path2, base64) => writePngFile(path2, base64),
75328
- clearDir: (d) => rmSync15(d, { recursive: true, force: true })
75521
+ clearDir: (d) => rmSync16(d, { recursive: true, force: true })
75329
75522
  }
75330
75523
  });
75331
75524
  writtenShots = sp.written;
@@ -75353,7 +75546,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75353
75546
  releaseId: result.releaseId,
75354
75547
  releasePayload: release,
75355
75548
  descriptors: attestedDescriptors,
75356
- screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join64(dir, ".himi", "shots", name)])),
75549
+ screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join65(dir, ".himi", "shots", name)])),
75357
75550
  coverage: {
75358
75551
  screens: crawledScreens.size,
75359
75552
  actionsDispatched: result.actions.exercised,
@@ -75464,7 +75657,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75464
75657
  return 2;
75465
75658
  }
75466
75659
  try {
75467
- const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync79(stateArg.replace(/^@/, ""), "utf8");
75660
+ const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync80(stateArg.replace(/^@/, ""), "utf8");
75468
75661
  injectedState = JSON.parse(raw);
75469
75662
  } catch (e) {
75470
75663
  io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
@@ -75479,7 +75672,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75479
75672
  return 2;
75480
75673
  }
75481
75674
  try {
75482
- const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync79(inputArg.replace(/^@/, ""), "utf8");
75675
+ const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync80(inputArg.replace(/^@/, ""), "utf8");
75483
75676
  const parsed = JSON.parse(raw);
75484
75677
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
75485
75678
  injectedInput = parsed;
@@ -75542,11 +75735,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75542
75735
  const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
75543
75736
  let pngFile;
75544
75737
  let attestationPngFile;
75545
- const shotPath = join64(dir, ".himi", "shots", `${screenId}.png`);
75738
+ const shotPath = join65(dir, ".himi", "shots", `${screenId}.png`);
75546
75739
  const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
75547
75740
  if (pngTarget && r.pngBase64) {
75548
75741
  pngFile = writePngFile(pngTarget, r.pngBase64);
75549
- attestationPngFile = resolve52(pngTarget) === resolve52(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75742
+ attestationPngFile = resolve53(pngTarget) === resolve53(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75550
75743
  }
75551
75744
  if (renderWidth !== void 0 && r.renderable) {
75552
75745
  recordRenderWidth(dir, {
@@ -75882,7 +76075,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75882
76075
  return 2;
75883
76076
  }
75884
76077
  const renamed = str8(flags.name);
75885
- const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
76078
+ const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
75886
76079
  const replace = flags.replace === true;
75887
76080
  const force = replace || flags.force === true;
75888
76081
  const linked = symlinkDestinationIssue(dest);
@@ -75890,20 +76083,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75890
76083
  io.error(JSON.stringify(linked));
75891
76084
  return 1;
75892
76085
  }
75893
- if (existsSync66(dest)) {
75894
- if (!statSync18(dest).isDirectory()) {
76086
+ if (existsSync67(dest)) {
76087
+ if (!statSync19(dest).isDirectory()) {
75895
76088
  io.error(JSON.stringify({
75896
76089
  error: `${dest} exists and is not a directory`,
75897
76090
  hint: "pass --out/--name to land somewhere else, or remove the file"
75898
76091
  }));
75899
76092
  return 1;
75900
76093
  }
75901
- const occupied = readdirSync30(dest).length > 0;
76094
+ const occupied = readdirSync31(dest).length > 0;
75902
76095
  if (occupied && !force) {
75903
76096
  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" }));
75904
76097
  return 1;
75905
76098
  }
75906
- if (replace && occupied && !existsSync66(join64(dest, "himalaya.content.json"))) {
76099
+ if (replace && occupied && !existsSync67(join65(dest, "himalaya.content.json"))) {
75907
76100
  io.error(JSON.stringify({
75908
76101
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
75909
76102
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -76070,7 +76263,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76070
76263
  const manifest = outcome.manifest;
76071
76264
  const payload = await loadReleaseFromDir(declared, out2);
76072
76265
  const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
76073
- const contentRel = relative13(process.cwd(), dir) || ".";
76266
+ const contentRel = relative14(process.cwd(), dir) || ".";
76074
76267
  const contentArg2 = shellQuote3(contentRel);
76075
76268
  if (onlyRaw !== void 0) {
76076
76269
  const onlyDraft = flags.draft === true;
@@ -76541,7 +76734,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76541
76734
  return 2;
76542
76735
  }
76543
76736
  try {
76544
- const res = writePack(resolve52(releaseDir), only, resolve52(str8(flags.out) ?? process.cwd()));
76737
+ const res = writePack(resolve53(releaseDir), only, resolve53(str8(flags.out) ?? process.cwd()));
76545
76738
  print({
76546
76739
  ok: true,
76547
76740
  app: res.app,
@@ -76590,7 +76783,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76590
76783
  }
76591
76784
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76592
76785
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
76593
- const built = mkdtempSync4(join64(tmpdir5(), "himi-pack-"));
76786
+ const built = mkdtempSync4(join65(tmpdir5(), "himi-pack-"));
76594
76787
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
76595
76788
  const outcome = await buildReleaseFromContent2(dir, built, {
76596
76789
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -76607,12 +76800,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76607
76800
  ...await navIssues2(dir, strict)
76608
76801
  ]);
76609
76802
  if (hasErrors && !force) {
76610
- rmSync15(built, { recursive: true, force: true });
76803
+ rmSync16(built, { recursive: true, force: true });
76611
76804
  print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
76612
76805
  return 1;
76613
76806
  }
76614
76807
  try {
76615
- const res = writePack(built, app, resolve52(str8(flags.out) ?? dir), sourceArchive);
76808
+ const res = writePack(built, app, resolve53(str8(flags.out) ?? dir), sourceArchive);
76616
76809
  print({
76617
76810
  ok: true,
76618
76811
  app: res.app,
@@ -76643,7 +76836,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76643
76836
  io.error(JSON.stringify({ error: e.message }));
76644
76837
  return 1;
76645
76838
  } finally {
76646
- rmSync15(built, { recursive: true, force: true });
76839
+ rmSync16(built, { recursive: true, force: true });
76647
76840
  }
76648
76841
  }
76649
76842
  // ---- himi import — turn a dev .himi back into an editable content package ----
@@ -76657,7 +76850,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76657
76850
  const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
76658
76851
  let opened;
76659
76852
  try {
76660
- opened = openPackageFile2(resolve52(file));
76853
+ opened = openPackageFile2(resolve53(file));
76661
76854
  } catch (e) {
76662
76855
  io.error(JSON.stringify({ error: e.message }));
76663
76856
  return 1;
@@ -76670,7 +76863,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76670
76863
  io.error(JSON.stringify({
76671
76864
  ok: false,
76672
76865
  error: "app_source_not_in_package",
76673
- detail: `${resolve52(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76866
+ detail: `${resolve53(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76674
76867
  hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
76675
76868
  }));
76676
76869
  return 1;
@@ -76693,7 +76886,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76693
76886
  return 1;
76694
76887
  }
76695
76888
  }
76696
- const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76889
+ const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76697
76890
  const issue2 = restoreDestinationIssue(dest, flags.force === true);
76698
76891
  if (issue2) {
76699
76892
  io.error(JSON.stringify(issue2));
@@ -76780,7 +76973,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76780
76973
  }
76781
76974
  try {
76782
76975
  const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
76783
- const opened = openPackageFile2(resolve52(file));
76976
+ const opened = openPackageFile2(resolve53(file));
76784
76977
  if (!opened.validation.ok || !opened.header) {
76785
76978
  io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
76786
76979
  return 1;
@@ -76790,12 +76983,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76790
76983
  io.error(JSON.stringify({
76791
76984
  ok: false,
76792
76985
  error: "refusing to share a package that carries the app's source",
76793
- 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`,
76986
+ 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`,
76794
76987
  hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
76795
76988
  }));
76796
76989
  return 1;
76797
76990
  }
76798
- const archive = readFileSync79(resolve52(file));
76991
+ const archive = readFileSync80(resolve53(file));
76799
76992
  const result = await client2().createPackageShare({
76800
76993
  app: opened.header.app,
76801
76994
  releaseId: opened.header.releaseId,
@@ -76871,11 +77064,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76871
77064
  const app = await appId(dir2);
76872
77065
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76873
77066
  const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
76874
- temp = mkdtempSync4(join64(tmpdir5(), "himi-run-build-"));
77067
+ temp = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
76875
77068
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
76876
77069
  const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
76877
77070
  servedMissing = initial.missingBundles;
76878
- source = join64(temp, app);
77071
+ source = join65(temp, app);
76879
77072
  }
76880
77073
  const chromeArg = str8(flags.chrome) ?? "preview";
76881
77074
  if (chromeArg !== "preview" && chromeArg !== "app") {
@@ -76911,7 +77104,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76911
77104
  if (!recordKit) return;
76912
77105
  startedAt = (/* @__PURE__ */ new Date()).toISOString();
76913
77106
  const failure = record2(served2, { ok: true, at: startedAt });
76914
- 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.` }));
77107
+ 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.` }));
76915
77108
  await refreshBoard();
76916
77109
  };
76917
77110
  const retract = async () => {
@@ -76934,9 +77127,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76934
77127
  });
76935
77128
  await announce(run2);
76936
77129
  print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
76937
- await new Promise((resolve53) => {
77130
+ await new Promise((resolve54) => {
76938
77131
  const stop = () => {
76939
- void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve53()));
77132
+ void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
76940
77133
  };
76941
77134
  process.once("SIGINT", stop);
76942
77135
  process.once("SIGTERM", stop);
@@ -76945,7 +77138,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76945
77138
  }
76946
77139
  const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
76947
77140
  const bus = watchKit ? new watchKit.ReloadBus() : void 0;
76948
- if (watch2) served = mkdtempSync4(join64(tmpdir5(), "himi-run-served-"));
77141
+ if (watch2) served = mkdtempSync4(join65(tmpdir5(), "himi-run-served-"));
76949
77142
  const running = await runPackage2(source, {
76950
77143
  port,
76951
77144
  chrome: chromeArg,
@@ -76974,8 +77167,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76974
77167
  await announce(running);
76975
77168
  if (watchKit && bus) {
76976
77169
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76977
- const live2 = join64(running.releaseRoot, running.app);
76978
- const manifestOf = (tree) => JSON.parse(readFileSync79(join64(tree, "release-manifest.json"), "utf8"));
77170
+ const live2 = join65(running.releaseRoot, running.app);
77171
+ const manifestOf = (tree) => JSON.parse(readFileSync80(join65(tree, "release-manifest.json"), "utf8"));
76979
77172
  let current = manifestOf(live2);
76980
77173
  const failed2 = async (message) => {
76981
77174
  if (stopping) return;
@@ -76986,7 +77179,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76986
77179
  };
76987
77180
  rebuild = watchKit.serialize(async () => {
76988
77181
  const t0 = Date.now();
76989
- const next = mkdtempSync4(join64(tmpdir5(), "himi-run-build-"));
77182
+ const next = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
76990
77183
  try {
76991
77184
  const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
76992
77185
  if (bres.compileErrors.length) {
@@ -77003,18 +77196,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77003
77196
  return;
77004
77197
  }
77005
77198
  if (stopping) return;
77006
- const fresh = manifestOf(join64(next, running.app));
77199
+ const fresh = manifestOf(join65(next, running.app));
77007
77200
  const diff = watchKit.diffReleases(current, fresh);
77008
77201
  const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
77009
- const changes = describeChanges2(live2, join64(next, running.app), diff);
77202
+ const changes = describeChanges2(live2, join65(next, running.app), diff);
77010
77203
  const retired = `${live2}.retired-${Date.now()}`;
77011
77204
  renameSync7(live2, retired);
77012
77205
  try {
77013
- renameSync7(join64(next, running.app), live2);
77206
+ renameSync7(join65(next, running.app), live2);
77014
77207
  } catch {
77015
- cpSync3(join64(next, running.app), live2, { recursive: true });
77208
+ cpSync3(join65(next, running.app), live2, { recursive: true });
77016
77209
  }
77017
- rmSync15(retired, { recursive: true, force: true });
77210
+ rmSync16(retired, { recursive: true, force: true });
77018
77211
  current = fresh;
77019
77212
  servedMissing = outcome.missingBundles;
77020
77213
  for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
@@ -77024,7 +77217,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77024
77217
  } catch (e) {
77025
77218
  await failed2(e.message.split("\n")[0]);
77026
77219
  } finally {
77027
- rmSync15(next, { recursive: true, force: true });
77220
+ rmSync16(next, { recursive: true, force: true });
77028
77221
  }
77029
77222
  });
77030
77223
  watcher2 = watchKit.watchContent(dir, () => {
@@ -77092,9 +77285,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77092
77285
  io.error(JSON.stringify({ error: e.message }));
77093
77286
  return 1;
77094
77287
  } finally {
77095
- if (temp) rmSync15(temp, { recursive: true, force: true });
77096
- if (served) rmSync15(served, { recursive: true, force: true });
77097
- if (browserCopy) rmSync15(browserCopy, { recursive: true, force: true });
77288
+ if (temp) rmSync16(temp, { recursive: true, force: true });
77289
+ if (served) rmSync16(served, { recursive: true, force: true });
77290
+ if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
77098
77291
  }
77099
77292
  }
77100
77293
  case "preview": {
@@ -77636,7 +77829,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77636
77829
  io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
77637
77830
  return 2;
77638
77831
  }
77639
- if (!existsSync66(file)) {
77832
+ if (!existsSync67(file)) {
77640
77833
  io.error(JSON.stringify({ error: `no such file: ${file}` }));
77641
77834
  return 2;
77642
77835
  }
@@ -77692,7 +77885,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77692
77885
  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."
77693
77886
  };
77694
77887
  if (kind === "tokens" || kind === "app-config") {
77695
- const body = readFileSync79(file, "utf8");
77888
+ const body = readFileSync80(file, "utf8");
77696
77889
  const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
77697
77890
  return runReleasePatch({
77698
77891
  ...common,
@@ -77707,7 +77900,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77707
77900
  io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
77708
77901
  return 2;
77709
77902
  }
77710
- const descriptor = readFileSync79(file, "utf8");
77903
+ const descriptor = readFileSync80(file, "utf8");
77711
77904
  try {
77712
77905
  JSON.parse(descriptor);
77713
77906
  } catch (e) {
@@ -77747,7 +77940,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77747
77940
  extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
77748
77941
  });
77749
77942
  }
77750
- const bytes2 = readFileSync79(file);
77943
+ const bytes2 = readFileSync80(file);
77751
77944
  const sha = createHash31("sha256").update(bytes2).digest("hex");
77752
77945
  const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
77753
77946
  if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
@@ -77891,7 +78084,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77891
78084
  }
77892
78085
  let def;
77893
78086
  try {
77894
- const parsed = JSON.parse(arg.startsWith("@") ? readFileSync79(arg.slice(1), "utf8") : arg);
78087
+ const parsed = JSON.parse(arg.startsWith("@") ? readFileSync80(arg.slice(1), "utf8") : arg);
77895
78088
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
77896
78089
  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}`] }));
77897
78090
  return 2;
@@ -78355,7 +78548,7 @@ ${label2}`);
78355
78548
  const platform = str8(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
78356
78549
  {
78357
78550
  const distDir = contentDir(flags);
78358
- if (existsSync66(join64(distDir, "himalaya.content.json"))) {
78551
+ if (existsSync67(join65(distDir, "himalaya.content.json"))) {
78359
78552
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
78360
78553
  const errors = issues.filter((i) => i.severity === "error");
78361
78554
  for (const i of issues.filter((i2) => i2.severity === "warning")) {
@@ -78641,7 +78834,7 @@ ${label2}`);
78641
78834
  const dpxPath = dpxSessionTokenPath();
78642
78835
  let dpx;
78643
78836
  try {
78644
- dpx = readFileSync79(dpxPath, "utf8").trim();
78837
+ dpx = readFileSync80(dpxPath, "utf8").trim();
78645
78838
  } catch {
78646
78839
  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` }));
78647
78840
  return 1;
@@ -79049,7 +79242,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
79049
79242
  const path2 = dpxSessionTokenPath();
79050
79243
  let raw;
79051
79244
  try {
79052
- raw = readFileSync79(path2, "utf8");
79245
+ raw = readFileSync80(path2, "utf8");
79053
79246
  } catch {
79054
79247
  io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
79055
79248
  return 1;
@@ -79365,10 +79558,11 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
79365
79558
  return 2;
79366
79559
  }
79367
79560
  const redirectFlag = str8(flags["redirect-uri"]);
79368
- if (!clientId && (flags.apply === true || redirectFlag)) {
79369
- const { APPLY_NEEDS_CLIENT: APPLY_NEEDS_CLIENT2, REDIRECT_NEEDS_CLIENT: REDIRECT_NEEDS_CLIENT2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
79561
+ const { APPLY_NEEDS_CLIENT: APPLY_NEEDS_CLIENT2, REDIRECT_NEEDS_CLIENT: REDIRECT_NEEDS_CLIENT2, applyNeedsClient: applyNeedsClient2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
79562
+ const applyWantsClient = flags.apply === true && applyNeedsClient2(str8(flags.shell));
79563
+ if (!clientId && (applyWantsClient || redirectFlag)) {
79370
79564
  io.error(JSON.stringify({
79371
- error: flags.apply === true ? APPLY_NEEDS_CLIENT2 : REDIRECT_NEEDS_CLIENT2,
79565
+ error: applyWantsClient ? APPLY_NEEDS_CLIENT2 : REDIRECT_NEEDS_CLIENT2,
79372
79566
  usage: analyzeUsage
79373
79567
  }));
79374
79568
  return 2;