@wix/himalaya-cli 0.1013.0 → 0.1015.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
@@ -1341,7 +1341,7 @@ function sentinelizeIdentity(body, identity) {
1341
1341
  }
1342
1342
  if (identity.name) {
1343
1343
  const re = new RegExp(`\\b(${NAME_FIELDS.join("|")})(["']?\\s*[:=]\\s*)(["'])${escapeRe(identity.name)}\\3`, "g");
1344
- out = out.replace(re, (_m, key2, sep14, q) => `${key2}${sep14}${q}__HIMI_APP_NAME__${q}`);
1344
+ out = out.replace(re, (_m, key2, sep15, q) => `${key2}${sep15}${q}__HIMI_APP_NAME__${q}`);
1345
1345
  }
1346
1346
  return out;
1347
1347
  }
@@ -2368,7 +2368,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
2368
2368
  tokenCache.set(cacheKey, fromEnv);
2369
2369
  return fromEnv;
2370
2370
  }
2371
- const token = await new Promise((resolve47, reject) => {
2371
+ const token = await new Promise((resolve48, reject) => {
2372
2372
  let child;
2373
2373
  try {
2374
2374
  child = spawnImpl("wix", [...args]);
@@ -2397,12 +2397,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
2397
2397
  child.stdout?.on("data", (d) => {
2398
2398
  out += String(d);
2399
2399
  const m = out.match(TOKEN_RE);
2400
- if (m) done(() => resolve47(m[0]));
2400
+ if (m) done(() => resolve48(m[0]));
2401
2401
  });
2402
2402
  child.stderr?.on("data", (d) => {
2403
2403
  out += String(d);
2404
2404
  const m = out.match(TOKEN_RE);
2405
- if (m) done(() => resolve47(m[0]));
2405
+ if (m) done(() => resolve48(m[0]));
2406
2406
  });
2407
2407
  child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
2408
2408
  child.on("exit", (code) => done(() => reject(new Error(
@@ -5345,7 +5345,6 @@ function walk(node, registry, path2, out) {
5345
5345
  var SYSTEM_FONT_FAMILY;
5346
5346
  var init_tokens = __esm({
5347
5347
  "../../core/ts/src/tokens.ts"() {
5348
- "use strict";
5349
5348
  SYSTEM_FONT_FAMILY = "$system";
5350
5349
  }
5351
5350
  });
@@ -15593,7 +15592,7 @@ async function injectRequest(listener, request) {
15593
15592
  req.headers.host ??= url.host;
15594
15593
  if (body && body.length > 0) req.push(body);
15595
15594
  req.push(null);
15596
- return await new Promise((resolve47, reject) => {
15595
+ return await new Promise((resolve48, reject) => {
15597
15596
  const streamed = () => {
15598
15597
  queueMicrotask(() => {
15599
15598
  req.emit("close");
@@ -15609,7 +15608,7 @@ async function injectRequest(listener, request) {
15609
15608
  else headers2.set(name, value);
15610
15609
  }
15611
15610
  const bodyless = out.status === 204 || out.status === 304 || request.method === "HEAD";
15612
- resolve47(new Response(bodyless ? null : out.body, { status: out.status, headers: headers2 }));
15611
+ resolve48(new Response(bodyless ? null : out.body, { status: out.status, headers: headers2 }));
15613
15612
  }, streamed);
15614
15613
  res.on("inject-error", reject);
15615
15614
  try {
@@ -16304,7 +16303,7 @@ function redactBodyString(body) {
16304
16303
  } catch {
16305
16304
  }
16306
16305
  }
16307
- return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep14) => isSensitiveBodyName(name) ? `"${name}"${sep14}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep14) => isSensitiveBodyName(name) ? `"${name}"${sep14}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
16306
+ return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep15) => isSensitiveBodyName(name) ? `"${name}"${sep15}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep15) => isSensitiveBodyName(name) ? `"${name}"${sep15}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
16308
16307
  }
16309
16308
  function createWixGatewayState() {
16310
16309
  return { mode: "record", rules: [], traffic: [], clients: /* @__PURE__ */ new Set(), seq: 0, ruleSeq: 0 };
@@ -17996,12 +17995,12 @@ function finalizeRecording(key2, rec) {
17996
17995
  if (rec.finalize) return rec.finalize;
17997
17996
  rec.finalize = (async () => {
17998
17997
  clearTimeout(rec.autoStop);
17999
- await new Promise((resolve47) => {
17998
+ await new Promise((resolve48) => {
18000
17999
  let done = false;
18001
18000
  const finish2 = () => {
18002
18001
  if (!done) {
18003
18002
  done = true;
18004
- resolve47();
18003
+ resolve48();
18005
18004
  }
18006
18005
  };
18007
18006
  rec.child.once("close", finish2);
@@ -18112,7 +18111,7 @@ var init_preview = __esm({
18112
18111
  DEVICE_LIST_TIMEOUT_MS = 5e3;
18113
18112
  defaultRunner2 = {
18114
18113
  capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
18115
- return new Promise((resolve47, reject) => {
18114
+ return new Promise((resolve48, reject) => {
18116
18115
  const child = spawn3(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
18117
18116
  const out = [];
18118
18117
  const err = [];
@@ -18134,7 +18133,7 @@ var init_preview = __esm({
18134
18133
  child.stderr.on("data", (b) => err.push(b));
18135
18134
  child.on("error", (e) => settle(reject, e));
18136
18135
  child.on("close", (code) => {
18137
- if (code === 0) settle(resolve47, Buffer.concat(out));
18136
+ if (code === 0) settle(resolve48, Buffer.concat(out));
18138
18137
  else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
18139
18138
  });
18140
18139
  });
@@ -23189,8 +23188,8 @@ function ensureCountUpRuntime() {
23189
23188
  const neg = fixed.startsWith("-");
23190
23189
  const body = neg ? fixed.slice(1) : fixed;
23191
23190
  const [int, frac] = body.split(".");
23192
- const sep14 = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
23193
- return (neg ? "-" : "") + sep14 + (frac ? "." + frac : "");
23191
+ const sep15 = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
23192
+ return (neg ? "-" : "") + sep15 + (frac ? "." + frac : "");
23194
23193
  };
23195
23194
  const animateEl = (el) => {
23196
23195
  const node = el;
@@ -28914,7 +28913,7 @@ async function stabilizePngPage(page, scheme) {
28914
28913
  const browser = globalThis;
28915
28914
  browser.document.documentElement.style.colorScheme = selected;
28916
28915
  await browser.document.fonts?.ready;
28917
- await new Promise((resolve47) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve47())));
28916
+ await new Promise((resolve48) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve48())));
28918
28917
  }, scheme);
28919
28918
  }
28920
28919
  async function renderPngBatch(items) {
@@ -32486,7 +32485,7 @@ async function handleWebWix(req, res, state) {
32486
32485
  }
32487
32486
  if (match && (match.rule.kind ?? "mock") === "mock") {
32488
32487
  const mocked = match.rule.response;
32489
- if (mocked.delayMs) await new Promise((resolve47) => setTimeout(resolve47, mocked.delayMs));
32488
+ if (mocked.delayMs) await new Promise((resolve48) => setTimeout(resolve48, mocked.delayMs));
32490
32489
  const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
32491
32490
  recordWixTraffic(state.wix, state.appName, state.adminUrl, {
32492
32491
  ts: started,
@@ -34488,12 +34487,12 @@ var init_query = __esm({
34488
34487
  });
34489
34488
 
34490
34489
  // ../../core/dev-server/src/crawl-input.ts
34491
- function resolved(v, resolve47) {
34492
- if (typeof v === "string") return v.startsWith("$service:") ? resolve47(v) : v;
34490
+ function resolved(v, resolve48) {
34491
+ if (typeof v === "string") return v.startsWith("$service:") ? resolve48(v) : v;
34493
34492
  if (Array.isArray(v)) {
34494
34493
  const out = v.flatMap((el) => {
34495
34494
  if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
34496
- const r = resolve47(el);
34495
+ const r = resolve48(el);
34497
34496
  return Array.isArray(r) ? r : [r];
34498
34497
  });
34499
34498
  return out;
@@ -34507,9 +34506,9 @@ function hasRowBinding(props) {
34507
34506
  return itemToken(v) || Array.isArray(v) && v.some(itemToken);
34508
34507
  });
34509
34508
  }
34510
- function declaredOptionIds(props, resolve47) {
34509
+ function declaredOptionIds(props, resolve48) {
34511
34510
  const literal = props.options ?? props.tabs ?? props.chips;
34512
- const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve47) : void 0;
34511
+ const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve48) : void 0;
34513
34512
  const raw = Array.isArray(bound) ? bound : literal;
34514
34513
  if (!Array.isArray(raw)) return [];
34515
34514
  const out = [];
@@ -34552,24 +34551,24 @@ function seedTokens(state, limit = 48) {
34552
34551
  walk2(state, 0);
34553
34552
  return out;
34554
34553
  }
34555
- function synthesizeInput(control, resolve47, tokens) {
34554
+ function synthesizeInput(control, resolve48, tokens) {
34556
34555
  const id = `${control.type}.${control.callback}`;
34557
34556
  const row = SYNTHESIZED_CONTROLS[id];
34558
34557
  if (!row) return null;
34559
34558
  const props = control.props;
34560
34559
  if (hasRowBinding(props)) return null;
34561
34560
  if (row.from === "declared-options") {
34562
- const ids = declaredOptionIds(props, resolve47);
34561
+ const ids = declaredOptionIds(props, resolve48);
34563
34562
  if (!ids.length) return null;
34564
34563
  if (row.encoding === "string-array") {
34565
- const currentRaw2 = resolved(props.selectedIds, resolve47);
34564
+ const currentRaw2 = resolved(props.selectedIds, resolve48);
34566
34565
  const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
34567
34566
  const pick4 = ids.find((o) => !current3.includes(o));
34568
34567
  if (pick4 === void 0) return null;
34569
34568
  const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
34570
34569
  return { key: row.key, value, from: row.from, current: current3, control: id };
34571
34570
  }
34572
- const currentRaw = resolved(props.selectedId, resolve47);
34571
+ const currentRaw = resolved(props.selectedId, resolve48);
34573
34572
  const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
34574
34573
  const pick3 = ids.find((o) => o !== current2);
34575
34574
  if (pick3 === void 0) return null;
@@ -34577,7 +34576,7 @@ function synthesizeInput(control, resolve47, tokens) {
34577
34576
  }
34578
34577
  if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
34579
34578
  const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
34580
- const bound = binding2 === void 0 ? void 0 : resolve47(binding2);
34579
+ const bound = binding2 === void 0 ? void 0 : resolve48(binding2);
34581
34580
  const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
34582
34581
  const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
34583
34582
  const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
@@ -35835,8 +35834,8 @@ async function crawlScreenInner(opts) {
35835
35834
  if (linkable.has(target)) return true;
35836
35835
  for (const base of linkable) {
35837
35836
  if (target.length > base.length + 1 && target.startsWith(base)) {
35838
- const sep14 = target[base.length];
35839
- if (sep14 === "_" || sep14 === "/") return true;
35837
+ const sep15 = target[base.length];
35838
+ if (sep15 === "_" || sep15 === "/") return true;
35840
35839
  }
35841
35840
  }
35842
35841
  return false;
@@ -38090,6 +38089,7 @@ __export(progress_exports, {
38090
38089
  MAX_MESSAGE_CHARS: () => MAX_MESSAGE_CHARS,
38091
38090
  PROGRESS_FILE: () => PROGRESS_FILE,
38092
38091
  ProgressError: () => ProgressError,
38092
+ UnsafeHimiDirError: () => UnsafeHimiDirError,
38093
38093
  appLabel: () => appLabel,
38094
38094
  appendProgress: () => appendProgress,
38095
38095
  appleScriptString: () => appleScriptString,
@@ -38099,11 +38099,14 @@ __export(progress_exports, {
38099
38099
  notifyDesktop: () => notifyDesktop,
38100
38100
  parseStep: () => parseStep,
38101
38101
  readProgress: () => readProgress,
38102
- summarizeProgress: () => summarizeProgress
38102
+ realDirIn: () => realDirIn,
38103
+ summarizeProgress: () => summarizeProgress,
38104
+ writeFileAtomic: () => writeFileAtomic
38103
38105
  });
38104
38106
  import { spawn as spawn4 } from "node:child_process";
38105
38107
  import { createHash as createHash19 } from "node:crypto";
38106
- import { appendFileSync, closeSync, existsSync as existsSync38, mkdirSync as mkdirSync17, openSync, readFileSync as readFileSync41, readSync, renameSync as renameSync3, statSync as statSync7, writeFileSync as writeFileSync13 } from "node:fs";
38108
+ import { randomUUID as randomUUID2 } from "node:crypto";
38109
+ import { appendFileSync, closeSync, existsSync as existsSync38, lstatSync as lstatSync5, mkdirSync as mkdirSync17, openSync, readFileSync as readFileSync41, readSync, renameSync as renameSync3, rmSync as rmSync6, statSync as statSync7, writeFileSync as writeFileSync13 } from "node:fs";
38107
38110
  import { join as join35, relative as relative5, resolve as resolve32, sep as sep8 } from "node:path";
38108
38111
  function parseStep(raw) {
38109
38112
  const v = raw.trim().toLowerCase();
@@ -38131,21 +38134,49 @@ function archiveImage(dir, src) {
38131
38134
  if (size > MAX_IMAGE_BYTES) {
38132
38135
  throw new ProgressError("image_too_large", `${src} is ${size} bytes; a progress image is capped at ${MAX_IMAGE_BYTES} \u2014 render at phone width (--device iphone)`);
38133
38136
  }
38134
- const archived = archiveBytes(dir, readFileSync41(abs));
38137
+ let archived;
38138
+ try {
38139
+ archived = archiveBytes(dir, readFileSync41(abs));
38140
+ } catch (e) {
38141
+ if (e instanceof UnsafeHimiDirError) throw new ProgressError("unsafe_himi_dir", e.message);
38142
+ throw e;
38143
+ }
38135
38144
  if (!archived) throw new ProgressError("not_an_image", `${src} is not a PNG, JPEG, GIF or WebP image`);
38136
38145
  return { file: archived.file, sha256: archived.sha256, source: src };
38137
38146
  }
38147
+ function realDirIn(dir, rel) {
38148
+ let at = dir;
38149
+ for (const part of rel.split(/[\\/]+/).filter(Boolean)) {
38150
+ at = join35(at, part);
38151
+ try {
38152
+ if (!lstatSync5(at).isDirectory()) return null;
38153
+ } catch (e) {
38154
+ if (e.code !== "ENOENT") return null;
38155
+ mkdirSync17(at);
38156
+ if (!lstatSync5(at).isDirectory()) return null;
38157
+ }
38158
+ }
38159
+ return at;
38160
+ }
38161
+ function writeFileAtomic(file, content) {
38162
+ const tmp = `${file}.${process.pid}.${randomUUID2()}.tmp`;
38163
+ try {
38164
+ writeFileSync13(tmp, content, { flag: "wx" });
38165
+ renameSync3(tmp, file);
38166
+ } catch (e) {
38167
+ rmSync6(tmp, { force: true });
38168
+ throw e;
38169
+ }
38170
+ }
38138
38171
  function archiveBytes(dir, bytes2) {
38139
38172
  const ext = imageExtension(bytes2);
38140
38173
  if (!ext) return null;
38141
38174
  const sha2565 = createHash19("sha256").update(bytes2).digest("hex");
38142
38175
  const rel = join35(HISTORY_DIR, `${sha2565}.${ext}`);
38143
38176
  const dest = join35(dir, rel);
38177
+ if (!realDirIn(dir, HISTORY_DIR)) throw new UnsafeHimiDirError(HISTORY_DIR);
38144
38178
  if (!existsSync38(dest)) {
38145
- mkdirSync17(join35(dir, HISTORY_DIR), { recursive: true });
38146
- const tmp = `${dest}.${process.pid}.tmp`;
38147
- writeFileSync13(tmp, bytes2);
38148
- renameSync3(tmp, dest);
38179
+ writeFileAtomic(dest, bytes2);
38149
38180
  }
38150
38181
  return { sha256: sha2565, ext, file: toPosix(rel) };
38151
38182
  }
@@ -38165,8 +38196,9 @@ function appendProgress(dir, input) {
38165
38196
  ...input.step ? { step: input.step, stepNumber: JOURNEY_STEPS.indexOf(input.step) + 1 } : {},
38166
38197
  ...images.length ? { images } : {}
38167
38198
  };
38168
- mkdirSync17(join35(dir, ".himi"), { recursive: true });
38199
+ if (!realDirIn(dir, ".himi")) throw new ProgressError("unsafe_himi_dir", new UnsafeHimiDirError(".himi").message);
38169
38200
  const file = join35(dir, PROGRESS_FILE);
38201
+ if (existsSync38(file) && lstatSync5(file).isSymbolicLink()) throw new ProgressError("unsafe_himi_dir", `${PROGRESS_FILE} is a symlink \u2014 refusing to append through it`);
38170
38202
  appendFileSync(file, `${endsWithNewline(file) ? "" : "\n"}${JSON.stringify(entry)}
38171
38203
  `);
38172
38204
  return entry;
@@ -38269,7 +38301,7 @@ function journalPath(dir) {
38269
38301
  const rel = relative5(process.cwd(), abs);
38270
38302
  return rel && !rel.startsWith("..") ? rel : abs;
38271
38303
  }
38272
- var JOURNEY_STEPS, PROGRESS_FILE, HISTORY_DIR, MAX_MESSAGE_CHARS, MAX_IMAGE_BYTES, ProgressError, toPosix, NOTIFY_TIMEOUT_MS;
38304
+ var JOURNEY_STEPS, PROGRESS_FILE, HISTORY_DIR, MAX_MESSAGE_CHARS, MAX_IMAGE_BYTES, ProgressError, toPosix, UnsafeHimiDirError, NOTIFY_TIMEOUT_MS;
38273
38305
  var init_progress = __esm({
38274
38306
  "src/progress.ts"() {
38275
38307
  JOURNEY_STEPS = ["discover", "classify", "plan", "implement", "brand", "validate", "review", "download"];
@@ -38284,6 +38316,11 @@ var init_progress = __esm({
38284
38316
  }
38285
38317
  };
38286
38318
  toPosix = (p) => p.split(sep8).join("/");
38319
+ UnsafeHimiDirError = class extends Error {
38320
+ constructor(rel) {
38321
+ super(`${rel} is not a real directory inside the content package (a symlink?) \u2014 refusing to write through it`);
38322
+ }
38323
+ };
38287
38324
  NOTIFY_TIMEOUT_MS = 3e3;
38288
38325
  }
38289
38326
  });
@@ -38305,7 +38342,7 @@ __export(studio_exports, {
38305
38342
  writeStudioRecord: () => writeStudioRecord
38306
38343
  });
38307
38344
  import { createHash as createHash20 } from "node:crypto";
38308
- import { existsSync as existsSync39, mkdirSync as mkdirSync18, readdirSync as readdirSync20, readFileSync as readFileSync42, realpathSync as realpathSync4, renameSync as renameSync4, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
38345
+ import { existsSync as existsSync39, readdirSync as readdirSync20, readFileSync as readFileSync42, realpathSync as realpathSync4, statSync as statSync8 } from "node:fs";
38309
38346
  import { basename as basename9, extname as extname3, join as join36, relative as relative6, resolve as resolve33, sep as sep9 } from "node:path";
38310
38347
  import { pathToFileURL as pathToFileURL7 } from "node:url";
38311
38348
  function realInside(dir, abs) {
@@ -38433,9 +38470,10 @@ function liveRun(dir) {
38433
38470
  const url = text(rec?.url);
38434
38471
  const pid = rec?.pid;
38435
38472
  if (!url || !/^https?:\/\//i.test(url) || typeof pid !== "number") return null;
38473
+ const build2 = obj(rec?.build);
38436
38474
  try {
38437
38475
  process.kill(pid, 0);
38438
- return { url };
38476
+ return { url, buildError: build2?.ok === false ? text(build2.error) ?? "the last rebuild failed" : null };
38439
38477
  } catch {
38440
38478
  return null;
38441
38479
  }
@@ -38509,14 +38547,13 @@ function buildView(dir, memory, now) {
38509
38547
  return { v, ...view };
38510
38548
  }
38511
38549
  function writeAtomic(file, content) {
38512
- const tmp = `${file}.${process.pid}.tmp`;
38513
- writeFileSync14(tmp, content);
38514
- renameSync4(tmp, file);
38550
+ writeFileAtomic(file, content);
38515
38551
  }
38516
38552
  function writeBoard(dir, now) {
38553
+ if (!realDirIn(dir, STUDIO_DIR)) throw new UnsafeHimiDirError(STUDIO_DIR);
38554
+ if (!realDirIn(dir, HISTORY_DIR)) throw new UnsafeHimiDirError(HISTORY_DIR);
38517
38555
  const memory = observeShots(dir, loadMemory(dir, now), now);
38518
38556
  const view = buildView(dir, memory, now);
38519
- mkdirSync18(join36(dir, STUDIO_DIR), { recursive: true });
38520
38557
  writeAtomic(join36(dir, MEMORY_FILE), JSON.stringify(memory));
38521
38558
  writeAtomic(join36(dir, STATE_FILE), `window.__himiStudio && window.__himiStudio(${scriptJson(view)});
38522
38559
  `);
@@ -38538,7 +38575,7 @@ function openStudio(dir, now = /* @__PURE__ */ new Date()) {
38538
38575
  }
38539
38576
  function writeStudioRecord(dir, record2, value) {
38540
38577
  try {
38541
- mkdirSync18(join36(dir, ".himi"), { recursive: true });
38578
+ if (!realDirIn(dir, ".himi")) return;
38542
38579
  writeAtomic(join36(dir, record2), `${JSON.stringify(value, null, 2)}
38543
38580
  `);
38544
38581
  } catch {
@@ -38624,7 +38661,7 @@ function render(s){
38624
38661
  $("nowmsg").textContent=last?last.message:"Waiting for the first postcard.";
38625
38662
  $("nowmeta").textContent=last?("Now \xB7 "+(last.step?("step "+last.stepNumber+" of 8, "+last.step+" \xB7 "):"")+ago(last.ts)):"Now";
38626
38663
  var focus=$("focus");clear(focus);var film=$("film");clear(film);
38627
- if(s.live){$("focuslbl").textContent="Live preview";var f=el("div","phone");var fr=document.createElement("iframe");fr.src=s.live.url;fr.title="Live preview";f.appendChild(fr);focus.appendChild(f);focus.appendChild(el("div","cap","Repaints as the app is edited \xB7 "+s.live.url))}
38664
+ if(s.live){$("focuslbl").textContent="Live preview";var f=el("div","phone");var fr=document.createElement("iframe");fr.src=s.live.url;fr.title="Live preview";f.appendChild(fr);focus.appendChild(f);if(s.live.buildError){var be=el("div","chip bad",null);be.style.display="block";be.style.marginTop="8px";be.textContent="Last edit did not build, still showing the last good version: "+s.live.buildError;focus.appendChild(be)}focus.appendChild(el("div","cap","Repaints as the app is edited \xB7 "+s.live.url))}
38628
38665
  else if(s.focus&&s.focus.frames.length){var fl=s.focus.frames;$("focuslbl").textContent="Latest \xB7 "+s.focus.id;var p=el("div","phone");p.appendChild(img(fl[fl.length-1].img));focus.appendChild(p);focus.appendChild(el("div","cap",fl.length+(fl.length===1?" version":" versions")+" so far"))}
38629
38666
  else{$("focuslbl").textContent="Latest";focus.appendChild(el("div","empty","The first render appears here."))}
38630
38667
  if(s.focus&&s.focus.frames.length>1)s.focus.frames.forEach(function(fm){film.appendChild(img(fm.img))});
@@ -39318,7 +39355,7 @@ var init_push_setup_apple_credentials = __esm({
39318
39355
  });
39319
39356
 
39320
39357
  // src/push-onboarding.ts
39321
- import { existsSync as existsSync40, mkdirSync as mkdirSync19, readFileSync as readFileSync44, statSync as statSync9, writeFileSync as writeFileSync15, chmodSync as chmodSync2 } from "node:fs";
39358
+ import { existsSync as existsSync40, mkdirSync as mkdirSync18, readFileSync as readFileSync44, statSync as statSync9, writeFileSync as writeFileSync14, chmodSync as chmodSync2 } from "node:fs";
39322
39359
  import { basename as basename10, dirname as dirname22, join as join37, resolve as resolve35 } from "node:path";
39323
39360
  function readJson3(path2) {
39324
39361
  try {
@@ -39468,8 +39505,8 @@ function readPushOnboarding(dir) {
39468
39505
  }
39469
39506
  function writeFile(dir, file) {
39470
39507
  const path2 = join37(resolve35(dir), PUSH_ONBOARDING_PATH);
39471
- mkdirSync19(dirname22(path2), { recursive: true, mode: 448 });
39472
- writeFileSync15(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
39508
+ mkdirSync18(dirname22(path2), { recursive: true, mode: 448 });
39509
+ writeFileSync14(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
39473
39510
  try {
39474
39511
  chmodSync2(path2, 384);
39475
39512
  } catch {
@@ -40230,7 +40267,7 @@ __export(template_trim_exports, {
40230
40267
  routeMatcher: () => routeMatcher,
40231
40268
  runTemplateTrim: () => runTemplateTrim
40232
40269
  });
40233
- import { cpSync, existsSync as existsSync41, mkdirSync as mkdirSync20, readdirSync as readdirSync21, readFileSync as readFileSync45, renameSync as renameSync5, rmSync as rmSync6, statSync as statSync10, writeFileSync as writeFileSync16 } from "node:fs";
40270
+ import { cpSync, existsSync as existsSync41, mkdirSync as mkdirSync19, readdirSync as readdirSync21, readFileSync as readFileSync45, renameSync as renameSync4, rmSync as rmSync7, statSync as statSync10, writeFileSync as writeFileSync15 } from "node:fs";
40234
40271
  import { dirname as dirname23, join as join38 } from "node:path";
40235
40272
  function routeMatcher(pattern) {
40236
40273
  const detail = /^\^([A-Za-z0-9_]+)\(\?:\[_\/\]\(\.\+\)\)\?\$$/.exec(pattern);
@@ -40988,16 +41025,16 @@ async function runTemplateTrim(req, deps) {
40988
41025
  const restore = () => {
40989
41026
  for (const [path2, rel] of originals) {
40990
41027
  const original = readFileSync45(join38(backup, rel));
40991
- if (!existsSync41(path2) || !readFileSync45(path2).equals(original)) writeFileSync16(path2, original);
41028
+ if (!existsSync41(path2) || !readFileSync45(path2).equals(original)) writeFileSync15(path2, original);
40992
41029
  }
40993
- for (const name of [...moved].reverse()) renameSync5(join38(backup, "tier5-src", name), join38(dir, "tier5-src", name));
41030
+ for (const name of [...moved].reverse()) renameSync4(join38(backup, "tier5-src", name), join38(dir, "tier5-src", name));
40994
41031
  };
40995
41032
  const dropBackup = () => {
40996
- rmSync6(backup, { recursive: true, force: true });
41033
+ rmSync7(backup, { recursive: true, force: true });
40997
41034
  for (const d of [dirname23(backup), join38(dir, ".himi")]) {
40998
41035
  if (d === join38(dir, ".himi") && hadHimi) break;
40999
41036
  try {
41000
- if (!readdirSync21(d).length) rmSync6(d, { recursive: true });
41037
+ if (!readdirSync21(d).length) rmSync7(d, { recursive: true });
41001
41038
  } catch {
41002
41039
  }
41003
41040
  }
@@ -41021,21 +41058,21 @@ async function runTemplateTrim(req, deps) {
41021
41058
  return { code: 1, result: { ok: false, error: `${error} (${message}); every file was restored`, rolledBack: true, ...base(validate4) } };
41022
41059
  };
41023
41060
  try {
41024
- mkdirSync20(join38(backup, "dev"), { recursive: true });
41061
+ mkdirSync19(join38(backup, "dev"), { recursive: true });
41025
41062
  for (const [path2, rel] of originals) cpSync(path2, join38(backup, rel));
41026
- if (plan.removedWorkers.length) mkdirSync20(join38(backup, "tier5-src"), { recursive: true });
41063
+ if (plan.removedWorkers.length) mkdirSync19(join38(backup, "tier5-src"), { recursive: true });
41027
41064
  } catch (e) {
41028
41065
  dropBackup();
41029
41066
  return { code: 1, result: { ok: false, error: `could not back up the app before trimming it (${e.message}); nothing was changed`, rolledBack: true, ...base() } };
41030
41067
  }
41031
41068
  try {
41032
- const moveDir = deps.moveDir ?? renameSync5;
41069
+ const moveDir = deps.moveDir ?? renameSync4;
41033
41070
  for (const name of plan.removedWorkers) {
41034
41071
  moveDir(join38(dir, "tier5-src", name), join38(backup, "tier5-src", name));
41035
41072
  moved.push(name);
41036
41073
  }
41037
- if (plan.dev !== dev) writeFileSync16(devPath, plan.dev);
41038
- if (plan.config !== config) writeFileSync16(configPath, plan.config);
41074
+ if (plan.dev !== dev) writeFileSync15(devPath, plan.dev);
41075
+ if (plan.config !== config) writeFileSync15(configPath, plan.config);
41039
41076
  } catch (e) {
41040
41077
  return abort("the trim failed while writing", e);
41041
41078
  }
@@ -41736,7 +41773,7 @@ __export(pack_exports, {
41736
41773
  });
41737
41774
  import { createHash as createHash21 } from "node:crypto";
41738
41775
  import { deflateRawSync, inflateRawSync } from "node:zlib";
41739
- import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync46, readdirSync as readdirSync22, rmSync as rmSync7, statSync as statSync11, writeFileSync as writeFileSync17 } from "node:fs";
41776
+ import { existsSync as existsSync42, mkdirSync as mkdirSync20, readFileSync as readFileSync46, readdirSync as readdirSync22, rmSync as rmSync8, statSync as statSync11, writeFileSync as writeFileSync16 } from "node:fs";
41740
41777
  import { dirname as dirname24, join as join39, resolve as resolve37 } from "node:path";
41741
41778
  function writeZip(entries) {
41742
41779
  const sorted2 = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
@@ -41913,10 +41950,10 @@ function packRelease(releaseRoot, app, out, opts = {}) {
41913
41950
  const appDir2 = join39(resolve37(releaseRoot), app);
41914
41951
  const { all, header, skipped } = buildEntries(appDir2, app, opts);
41915
41952
  const buf = writeZip(all);
41916
- const isDir = existsSync42(out) && statSync11(out).isDirectory();
41917
- const outFile = isDir ? join39(resolve37(out), packageFileName(app, header.releaseId)) : resolve37(out);
41918
- mkdirSync21(dirname24(outFile), { recursive: true });
41919
- writeFileSync17(outFile, buf);
41953
+ const isDir2 = existsSync42(out) && statSync11(out).isDirectory();
41954
+ const outFile = isDir2 ? join39(resolve37(out), packageFileName(app, header.releaseId)) : resolve37(out);
41955
+ mkdirSync20(dirname24(outFile), { recursive: true });
41956
+ writeFileSync16(outFile, buf);
41920
41957
  return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
41921
41958
  }
41922
41959
  function resolvePackageDirDest(outDir, app, releaseId) {
@@ -41955,12 +41992,12 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
41955
41992
  const appDir2 = join39(resolve37(releaseRoot), app);
41956
41993
  const { all, header, skipped } = buildEntries(appDir2, app, opts);
41957
41994
  const dest = resolvePackageDirDest(resolve37(outDir), app, header.releaseId);
41958
- rmSync7(dest, { recursive: true, force: true });
41995
+ rmSync8(dest, { recursive: true, force: true });
41959
41996
  let bytes2 = 0;
41960
41997
  for (const entry of all) {
41961
41998
  const target = join39(dest, entry.path);
41962
- mkdirSync21(dirname24(target), { recursive: true });
41963
- writeFileSync17(target, entry.bytes);
41999
+ mkdirSync20(dirname24(target), { recursive: true });
42000
+ writeFileSync16(target, entry.bytes);
41964
42001
  bytes2 += entry.bytes.length;
41965
42002
  }
41966
42003
  return { app, releaseId: header.releaseId, header, out: dest, bytes: bytes2, entryCount: all.length, skipped };
@@ -42038,11 +42075,11 @@ function unpackTo(buf, dest, appFallback) {
42038
42075
  if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
42039
42076
  const root = resolve37(dest);
42040
42077
  const appDir2 = join39(root, app);
42041
- rmSync7(appDir2, { recursive: true, force: true });
42078
+ rmSync8(appDir2, { recursive: true, force: true });
42042
42079
  for (const [rel, bytes2] of entries) {
42043
42080
  const target = join39(appDir2, rel);
42044
- mkdirSync21(dirname24(target), { recursive: true });
42045
- writeFileSync17(target, bytes2);
42081
+ mkdirSync20(dirname24(target), { recursive: true });
42082
+ writeFileSync16(target, bytes2);
42046
42083
  }
42047
42084
  return { root, appDir: appDir2, app };
42048
42085
  }
@@ -42076,14 +42113,14 @@ __export(app_source_exports, {
42076
42113
  writeConflicts: () => writeConflicts,
42077
42114
  zipAppSource: () => zipAppSource
42078
42115
  });
42079
- import { readdirSync as readdirSync23, lstatSync as lstatSync5, readFileSync as readFileSync47, mkdirSync as mkdirSync22, writeFileSync as writeFileSync18, existsSync as existsSync43, rmSync as rmSync8, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
42116
+ import { readdirSync as readdirSync23, lstatSync as lstatSync6, readFileSync as readFileSync47, mkdirSync as mkdirSync21, writeFileSync as writeFileSync17, existsSync as existsSync43, rmSync as rmSync9, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
42080
42117
  import { join as join40, resolve as resolve38, sep as sep10 } from "node:path";
42081
42118
  import { deflateRawSync as deflateRawSync2 } from "node:zlib";
42082
42119
  function walkSourceTree(dir, file, skip) {
42083
42120
  const walk2 = (relDir) => {
42084
42121
  for (const name of readdirSync23(join40(dir, relDir))) {
42085
42122
  const rel = relDir ? join40(relDir, name) : name;
42086
- const st = lstatSync5(join40(dir, rel));
42123
+ const st = lstatSync6(join40(dir, rel));
42087
42124
  if (st.isSymbolicLink()) {
42088
42125
  skip(rel);
42089
42126
  continue;
@@ -42142,7 +42179,7 @@ function readAppSource(zip) {
42142
42179
  }
42143
42180
  function pathKind(p) {
42144
42181
  try {
42145
- return lstatSync5(p);
42182
+ return lstatSync6(p);
42146
42183
  } catch {
42147
42184
  return null;
42148
42185
  }
@@ -42154,7 +42191,7 @@ function writeAppSource(entries, destDir) {
42154
42191
  `refusing to restore into ${root}: the destination itself is a symlink, so every file would be written outside it. Remove it, or pass --out/--name somewhere else.`
42155
42192
  );
42156
42193
  }
42157
- mkdirSync22(root, { recursive: true });
42194
+ mkdirSync21(root, { recursive: true });
42158
42195
  const written = [];
42159
42196
  for (const entry of entries) {
42160
42197
  if (isDeniedSourcePath(entry.path)) continue;
@@ -42165,11 +42202,11 @@ function writeAppSource(entries, destDir) {
42165
42202
  const kind = pathKind(dir);
42166
42203
  if (kind?.isSymbolicLink()) unlinkSync3(dir);
42167
42204
  else if (kind) continue;
42168
- mkdirSync22(dir);
42205
+ mkdirSync21(dir);
42169
42206
  }
42170
42207
  const target = join40(root, ...segments);
42171
42208
  if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
42172
- writeFileSync18(target, entry.bytes);
42209
+ writeFileSync17(target, entry.bytes);
42173
42210
  written.push(entry.path);
42174
42211
  }
42175
42212
  return written;
@@ -42224,7 +42261,7 @@ function writeConflicts(entries, destDir) {
42224
42261
  function removeStaleSource(entries, destDir) {
42225
42262
  const root = resolve38(destDir);
42226
42263
  const removed = staleSourcePaths(entries, root);
42227
- for (const rel of removed) rmSync8(join40(root, ...rel.split("/")), { force: true });
42264
+ for (const rel of removed) rmSync9(join40(root, ...rel.split("/")), { force: true });
42228
42265
  const needed = /* @__PURE__ */ new Set();
42229
42266
  for (const entry of entries) {
42230
42267
  if (isDeniedSourcePath(entry.path)) continue;
@@ -42239,7 +42276,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
42239
42276
  for (const name of readdirSync23(rel ? join40(root, rel) : root)) {
42240
42277
  const childRel = rel ? join40(rel, name) : name;
42241
42278
  const posix3 = childRel.split(sep10).join("/");
42242
- const kind = lstatSync5(join40(root, childRel));
42279
+ const kind = lstatSync6(join40(root, childRel));
42243
42280
  if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name, rel)) {
42244
42281
  empty = false;
42245
42282
  continue;
@@ -42304,7 +42341,7 @@ __export(eject_exports, {
42304
42341
  EJECTABLE: () => EJECTABLE,
42305
42342
  ejectModule: () => ejectModule
42306
42343
  });
42307
- import { existsSync as existsSync44, mkdirSync as mkdirSync23, readFileSync as readFileSync48, writeFileSync as writeFileSync19 } from "node:fs";
42344
+ import { existsSync as existsSync44, mkdirSync as mkdirSync22, readFileSync as readFileSync48, writeFileSync as writeFileSync18 } from "node:fs";
42308
42345
  import { dirname as dirname25, join as join41, relative as relative7, resolve as resolve39, sep as sep11 } from "node:path";
42309
42346
  function locate(repoRootOrCwd, mod) {
42310
42347
  const inRepo = resolve39(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
@@ -42335,7 +42372,7 @@ function ejectModule(opts) {
42335
42372
  }
42336
42373
  const ext = found.form === "source" ? "ts" : "mjs";
42337
42374
  const target = join41(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
42338
- mkdirSync23(dirname25(target), { recursive: true });
42375
+ mkdirSync22(dirname25(target), { recursive: true });
42339
42376
  const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
42340
42377
  //
42341
42378
  // Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
@@ -42352,7 +42389,7 @@ function ejectModule(opts) {
42352
42389
  /(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
42353
42390
  (_m, q, sub) => `${q}@wix/himalaya/${sub}${q}`
42354
42391
  );
42355
- writeFileSync19(target, banner + normalized);
42392
+ writeFileSync18(target, banner + normalized);
42356
42393
  const rewired = [];
42357
42394
  for (const f of files) {
42358
42395
  if (!existsSync44(f)) continue;
@@ -42368,7 +42405,7 @@ function ejectModule(opts) {
42368
42405
  );
42369
42406
  }
42370
42407
  if (after !== before) {
42371
- writeFileSync19(f, after);
42408
+ writeFileSync18(f, after);
42372
42409
  rewired.push(f);
42373
42410
  }
42374
42411
  }
@@ -42404,7 +42441,7 @@ __export(test_exports, {
42404
42441
  scopeDescriptors: () => scopeDescriptors,
42405
42442
  writeRecordedMocks: () => writeRecordedMocks
42406
42443
  });
42407
- import { existsSync as existsSync45, mkdirSync as mkdirSync24, readFileSync as readFileSync49, writeFileSync as writeFileSync20 } from "node:fs";
42444
+ import { existsSync as existsSync45, mkdirSync as mkdirSync23, readFileSync as readFileSync49, writeFileSync as writeFileSync19 } from "node:fs";
42408
42445
  import { join as join42, resolve as resolve40 } from "node:path";
42409
42446
  function readTestConfig(dir) {
42410
42447
  const p = resolve40(dir, TEST_CONFIG_FILE);
@@ -42580,8 +42617,8 @@ function writeRecordedMocks(opts) {
42580
42617
  };
42581
42618
  }
42582
42619
  const fs = opts.io ?? {
42583
- mkdir: (p) => mkdirSync24(p, { recursive: true }),
42584
- write: (p, s) => writeFileSync20(p, s)
42620
+ mkdir: (p) => mkdirSync23(p, { recursive: true }),
42621
+ write: (p, s) => writeFileSync19(p, s)
42585
42622
  };
42586
42623
  fs.mkdir(join42(opts.dir, "dev"));
42587
42624
  fs.write(join42(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
@@ -43342,7 +43379,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
43342
43379
  const headers2 = Object.fromEntries(new Headers(init.headers).entries());
43343
43380
  const request = url.protocol === "https:" ? httpsRequest : httpRequest;
43344
43381
  const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
43345
- return await new Promise((resolve47, reject) => {
43382
+ return await new Promise((resolve48, reject) => {
43346
43383
  let settled = false;
43347
43384
  const finish2 = (fn) => {
43348
43385
  if (settled) return;
@@ -43379,7 +43416,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
43379
43416
  }
43380
43417
  const responseHeaders = new Headers();
43381
43418
  for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
43382
- resolve47(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
43419
+ resolve48(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
43383
43420
  }));
43384
43421
  });
43385
43422
  req.once("error", (error) => finish2(() => reject(error)));
@@ -43679,7 +43716,7 @@ function createLocalTestSandbox() {
43679
43716
  }
43680
43717
  })();
43681
43718
  `;
43682
- return await new Promise((resolve47, reject) => {
43719
+ return await new Promise((resolve48, reject) => {
43683
43720
  const { port1, port2 } = new MessageChannel();
43684
43721
  const serializableContext = {
43685
43722
  auth: context.auth,
@@ -43755,7 +43792,7 @@ function createLocalTestSandbox() {
43755
43792
  timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
43756
43793
  return;
43757
43794
  }
43758
- if (message.ok) finish2(() => resolve47({ value: message.value, durationMs: Date.now() - started }));
43795
+ if (message.ok) finish2(() => resolve48({ value: message.value, durationMs: Date.now() - started }));
43759
43796
  else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
43760
43797
  });
43761
43798
  worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
@@ -44900,7 +44937,7 @@ __export(native_decode_exports, {
44900
44937
  runNativeDecode: () => runNativeDecode
44901
44938
  });
44902
44939
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
44903
- import { existsSync as existsSync48, mkdtempSync as mkdtempSync2, readFileSync as readFileSync52, rmSync as rmSync9, writeFileSync as writeFileSync21 } from "node:fs";
44940
+ import { existsSync as existsSync48, mkdtempSync as mkdtempSync2, readFileSync as readFileSync52, rmSync as rmSync10, writeFileSync as writeFileSync20 } from "node:fs";
44904
44941
  import { tmpdir as tmpdir3 } from "node:os";
44905
44942
  import { join as join45 } from "node:path";
44906
44943
  import { fileURLToPath as fileURLToPath20 } from "node:url";
@@ -45034,7 +45071,7 @@ function runNativeDecode(options) {
45034
45071
  if (typeof descriptor.descriptorJson !== "string") {
45035
45072
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
45036
45073
  }
45037
- writeFileSync21(join45(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
45074
+ writeFileSync20(join45(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
45038
45075
  }
45039
45076
  options.progress?.("building cached Swift oracle");
45040
45077
  execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
@@ -45060,7 +45097,7 @@ function runNativeDecode(options) {
45060
45097
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
45061
45098
  throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
45062
45099
  } finally {
45063
- rmSync9(descriptorDir, { recursive: true, force: true });
45100
+ rmSync10(descriptorDir, { recursive: true, force: true });
45064
45101
  }
45065
45102
  }
45066
45103
  function runAndroidNativeDecode(options) {
@@ -45072,7 +45109,7 @@ function runAndroidNativeDecode(options) {
45072
45109
  if (typeof descriptor.descriptorJson !== "string") {
45073
45110
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
45074
45111
  }
45075
- writeFileSync21(join45(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
45112
+ writeFileSync20(join45(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
45076
45113
  }
45077
45114
  options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
45078
45115
  execFileSync5(options.gradlew, [
@@ -45098,7 +45135,7 @@ function runAndroidNativeDecode(options) {
45098
45135
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
45099
45136
  throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
45100
45137
  } finally {
45101
- rmSync9(descriptorDir, { recursive: true, force: true });
45138
+ rmSync10(descriptorDir, { recursive: true, force: true });
45102
45139
  }
45103
45140
  }
45104
45141
  function fieldAt(path2) {
@@ -45242,10 +45279,10 @@ function collectSdkModules(files, resolveSubpath) {
45242
45279
  for (const source of Object.values(files)) visit(source);
45243
45280
  return { modules, unsupported };
45244
45281
  }
45245
- function sdkSubpathReader(resolve47) {
45282
+ function sdkSubpathReader(resolve48) {
45246
45283
  return (sub) => {
45247
45284
  try {
45248
- return readFileSync53(resolve47(`@wix/himalaya/${sub}`), "utf8");
45285
+ return readFileSync53(resolve48(`@wix/himalaya/${sub}`), "utf8");
45249
45286
  } catch {
45250
45287
  return null;
45251
45288
  }
@@ -45323,7 +45360,7 @@ async function runBrowserAuthoring(opts) {
45323
45360
  const token = mintToken2(payload);
45324
45361
  const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
45325
45362
  if (unusable) throw new Error(unusable);
45326
- return await new Promise((resolve47, reject) => {
45363
+ return await new Promise((resolve48, reject) => {
45327
45364
  let settled = false;
45328
45365
  let url = "";
45329
45366
  const server = createServer3();
@@ -45375,7 +45412,7 @@ async function runBrowserAuthoring(opts) {
45375
45412
  }
45376
45413
  res.writeHead(200, { "content-type": "text/plain" }).end("ok");
45377
45414
  const report2 = body.result;
45378
- finish2(() => resolve47({ report: report2, url }));
45415
+ finish2(() => resolve48({ report: report2, url }));
45379
45416
  })();
45380
45417
  });
45381
45418
  server.on("error", (e) => finish2(() => reject(e)));
@@ -45417,7 +45454,7 @@ __export(coverage_exports, {
45417
45454
  suppressedNativeKeys: () => suppressedNativeKeys,
45418
45455
  trendAndStore: () => trendAndStore
45419
45456
  });
45420
- import { existsSync as existsSync50, mkdirSync as mkdirSync25, readFileSync as readFileSync54, writeFileSync as writeFileSync22 } from "node:fs";
45457
+ import { existsSync as existsSync50, mkdirSync as mkdirSync24, readFileSync as readFileSync54, writeFileSync as writeFileSync21 } from "node:fs";
45421
45458
  import { dirname as dirname26, join as join47 } from "node:path";
45422
45459
  function suppressedNativeKeys(oracle) {
45423
45460
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
@@ -45600,8 +45637,8 @@ function trendAndStore(dir, entries, suppressed) {
45600
45637
  const current = entries.map((e) => e.key);
45601
45638
  const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
45602
45639
  try {
45603
- mkdirSync25(dirname26(p), { recursive: true });
45604
- writeFileSync22(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
45640
+ mkdirSync24(dirname26(p), { recursive: true });
45641
+ writeFileSync21(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
45605
45642
  } catch {
45606
45643
  return null;
45607
45644
  }
@@ -45645,8 +45682,8 @@ function diffAndStoreObservations(dir, current) {
45645
45682
  } catch {
45646
45683
  }
45647
45684
  try {
45648
- mkdirSync25(dirname26(p), { recursive: true });
45649
- writeFileSync22(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
45685
+ mkdirSync24(dirname26(p), { recursive: true });
45686
+ writeFileSync21(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
45650
45687
  } catch {
45651
45688
  return null;
45652
45689
  }
@@ -45887,6 +45924,29 @@ var init_assets = __esm({
45887
45924
  }
45888
45925
  });
45889
45926
 
45927
+ // ../../core/serve-runtime/src/pinned-read.ts
45928
+ async function checkPinnedRead(input) {
45929
+ const { secret, token, app, releaseId, screenId, authorizePreview } = input;
45930
+ if (!secret) return authorizePreview ? { status: 503, body: { error: "preview_token_unavailable" } } : null;
45931
+ if (!token) return await input.isLive() ? null : { status: 401, body: { error: "preview_token_required", app, releaseId } };
45932
+ const verified = await verifyPreviewToken({ token, secret, app, releaseId, screenId });
45933
+ if (verified.ok) {
45934
+ if (authorizePreview ? !await authorizePreview(verified.claims) : !!verified.claims.siteLease) {
45935
+ return { status: 403, body: { error: "site_preview_forbidden" } };
45936
+ }
45937
+ return null;
45938
+ }
45939
+ return {
45940
+ status: verified.error === "scope_mismatch" ? 403 : 401,
45941
+ body: { error: `preview_token_${verified.error}`, app, releaseId, ...screenId ? { screenId } : {} }
45942
+ };
45943
+ }
45944
+ var init_pinned_read = __esm({
45945
+ "../../core/serve-runtime/src/pinned-read.ts"() {
45946
+ init_preview_token();
45947
+ }
45948
+ });
45949
+
45890
45950
  // ../../core/serve-runtime/package-share.ts
45891
45951
  function parseStored(bytes2, id) {
45892
45952
  if (!bytes2) return null;
@@ -46093,6 +46153,15 @@ function json3(status, body, headers2 = {}) {
46093
46153
  function isCookieAuthorizedPath(path2) {
46094
46154
  return path2 === "/v1/__webwix/call" || path2 === "/v1/owner" || path2.startsWith("/v1/owner/") || path2 === "/v1/__webwix/identity" || path2 === "/v1/__webwix/login" || path2 === "/v1/__webwix/register" || path2 === "/v1/__webwix/logout" || path2 === MEMBER_CALLBACK_PATH;
46095
46155
  }
46156
+ function webwixCallLog(served, status) {
46157
+ const directRung = served.rung === "visitor" || served.rung === "owner";
46158
+ return {
46159
+ rung: served.rung,
46160
+ ...directRung ? { fallback: served.fallback === true } : {},
46161
+ ...served.app ? { app: served.app } : {},
46162
+ status
46163
+ };
46164
+ }
46096
46165
  function makeServeHandler(opts) {
46097
46166
  let storePromise = null;
46098
46167
  const getStore = () => storePromise ??= (async () => {
@@ -46222,23 +46291,16 @@ ${releaseId}`;
46222
46291
  return new Response(body, { status: 200, headers: { "content-type": JSON_CT, etag, "cache-control": cache, ...vary } });
46223
46292
  }
46224
46293
  async function authorizePinnedRead(request, url, app, releaseId, screenId) {
46225
- const secret = opts.previewTokenSecret;
46226
- if (!secret) return opts.authorizePreview ? json3(503, { error: "preview_token_unavailable" }) : null;
46227
- const token = resolvePreviewToken(request, url);
46228
- const live2 = await manifest(app);
46229
- const isLive = live2?.releaseId === releaseId;
46230
- if (!token) return isLive ? null : json3(401, { error: "preview_token_required", app, releaseId });
46231
- const verified = await verifyPreviewToken({ token, secret, app, releaseId, screenId });
46232
- if (verified.ok) {
46233
- if (opts.authorizePreview ? !await opts.authorizePreview(verified.claims) : !!verified.claims.siteLease) return json3(403, { error: "site_preview_forbidden" });
46234
- return null;
46235
- }
46236
- return json3(verified.error === "scope_mismatch" ? 403 : 401, {
46237
- error: `preview_token_${verified.error}`,
46294
+ const denied = await checkPinnedRead({
46295
+ secret: opts.previewTokenSecret,
46296
+ token: resolvePreviewToken(request, url),
46238
46297
  app,
46239
46298
  releaseId,
46240
- ...screenId ? { screenId } : {}
46299
+ screenId,
46300
+ isLive: async () => (await manifest(app))?.releaseId === releaseId,
46301
+ authorizePreview: opts.authorizePreview
46241
46302
  });
46303
+ return denied && json3(denied.status, denied.body);
46242
46304
  }
46243
46305
  const corsHeaders = (request) => {
46244
46306
  const origin = request.headers.get("origin");
@@ -46406,83 +46468,109 @@ ${releaseId}`;
46406
46468
  return json3(200, { authenticated: false, userId: null, email: null, webwixDirect }, { "cache-control": "no-store" });
46407
46469
  }
46408
46470
  if (request.method === "POST" && path2 === "/v1/__webwix/call") {
46409
- if (opts.webwixBridge === false) {
46410
- return json3(503, { error: "webwix_bridge_disabled" });
46411
- }
46412
- const app2 = resolveApp(request, url);
46413
- if (!app2) return json3(400, { error: "app_required" });
46414
- const resolvedCfg = await appConfigFor(request, url, app2);
46415
- if (!resolvedCfg.ok) return resolvedCfg.response;
46416
- const cfgBytes = resolvedCfg.bytes;
46417
- let call;
46471
+ const served = { rung: "none" };
46472
+ let status = 500;
46418
46473
  try {
46419
- call = await request.json();
46420
- } catch {
46421
- return json3(400, { error: "invalid_json" });
46422
- }
46423
- if (call.checkOwnerSession !== void 0 && (typeof call.checkOwnerSession !== "boolean" || call.checkOwnerSession && call.ownerMsid === void 0)) {
46424
- return json3(400, { error: "invalid_owner_session_check" });
46425
- }
46426
- const method = String(call.method ?? "GET").toUpperCase();
46427
- const reqPath = String(call.path ?? "/");
46428
- const body = call.body === void 0 ? void 0 : typeof call.body === "string" ? call.body : JSON.stringify(call.body);
46429
- const forwardedHeaders = normalizeWixForwardedHeaders(call.headers);
46430
- const callerCookie = request.headers.get("cookie") ?? "";
46431
- if (!call.checkOwnerSession && webwixOwnerRungOn() && method === "POST" && isOwnerSitesPath(reqPath) && /wixSession2=/.test(callerCookie)) {
46432
- try {
46433
- const envelope = await wixOwnerSitesCall(reqPath, callerCookie, body, webwixFetch);
46434
- if (envelope.status >= 200 && envelope.status < 300) return json3(200, envelope);
46435
- return json3(200, {
46436
- status: 501,
46437
- body: JSON.stringify({ error: "webwix_owner_sites_failed", upstream: envelope.status })
46438
- });
46439
- } catch (e) {
46440
- return json3(200, {
46441
- status: 501,
46442
- body: JSON.stringify({ error: "webwix_owner_sites_failed", detail: String(e?.message ?? e).slice(0, 200) })
46443
- });
46444
- }
46445
- }
46446
- if (call.ownerMsid !== void 0) {
46447
- if (!webwixOwnerRungOn()) {
46448
- return json3(503, { error: "webwix_owner_disabled" });
46449
- }
46450
- const msid = String(call.ownerMsid);
46451
- if (!isSafeMsid(msid)) return json3(400, { error: "webwix_owner_bad_msid" });
46452
- const cookie = request.headers.get("cookie") ?? "";
46453
- if (!/wixSession2=/.test(cookie)) return json3(501, { error: "webwix_owner_no_session", app: app2 });
46454
- try {
46455
- const instance = await webwixOwnerInstances.instance(msid, cookie);
46456
- if (call.checkOwnerSession === true) return json3(200, { status: 200, body: JSON.stringify({ ready: true }) }, { "cache-control": "no-store" });
46457
- const first = await wixVisitorCall(method, reqPath, body, instance, webwixFetch, forwardedHeaders);
46458
- if (first.status !== 401) return json3(200, first);
46459
- webwixOwnerInstances.invalidate(msid, cookie);
46460
- const fresh = await webwixOwnerInstances.instance(msid, cookie);
46461
- return json3(200, await wixVisitorCall(method, reqPath, body, fresh, webwixFetch, forwardedHeaders));
46462
- } catch (e) {
46463
- const msg = String(e?.message ?? e);
46464
- if (msg.includes("absolute URLs")) {
46465
- return absoluteUrlRejection(reqPath) === "owner-only" ? json3(501, { error: "webwix_owner_only", app: app2 }) : json3(400, { error: "absolute_urls_not_allowed" });
46474
+ const res = await (async () => {
46475
+ if (opts.webwixBridge === false) {
46476
+ return json3(503, { error: "webwix_bridge_disabled" });
46466
46477
  }
46467
- if (msg.includes("owner mint failed")) {
46468
- if (/owner mint failed \(5\d\d\)/.test(msg)) return json3(502, { error: "webwix_bridge_upstream_failed" });
46469
- return json3(501, { error: "webwix_owner_mint_failed", app: app2 });
46478
+ const app2 = resolveApp(request, url);
46479
+ if (!app2) return json3(400, { error: "app_required" });
46480
+ const resolvedCfg = await appConfigFor(request, url, app2);
46481
+ if (!resolvedCfg.ok) return resolvedCfg.response;
46482
+ served.app = app2;
46483
+ const cfgBytes = resolvedCfg.bytes;
46484
+ let call;
46485
+ try {
46486
+ call = await request.json();
46487
+ } catch {
46488
+ return json3(400, { error: "invalid_json" });
46489
+ }
46490
+ served.fallback = call.fallback === true;
46491
+ if (call.checkOwnerSession !== void 0 && (typeof call.checkOwnerSession !== "boolean" || call.checkOwnerSession && call.ownerMsid === void 0)) {
46492
+ return json3(400, { error: "invalid_owner_session_check" });
46493
+ }
46494
+ const method = String(call.method ?? "GET").toUpperCase();
46495
+ const reqPath = String(call.path ?? "/");
46496
+ const body = call.body === void 0 ? void 0 : typeof call.body === "string" ? call.body : JSON.stringify(call.body);
46497
+ const forwardedHeaders = normalizeWixForwardedHeaders(call.headers);
46498
+ const callerCookie = request.headers.get("cookie") ?? "";
46499
+ if (!call.checkOwnerSession && webwixOwnerRungOn() && method === "POST" && isOwnerSitesPath(reqPath) && /wixSession2=/.test(callerCookie)) {
46500
+ served.rung = "sites";
46501
+ try {
46502
+ const envelope = await wixOwnerSitesCall(reqPath, callerCookie, body, webwixFetch);
46503
+ if (envelope.status >= 200 && envelope.status < 300) return json3(200, envelope);
46504
+ return json3(200, {
46505
+ status: 501,
46506
+ body: JSON.stringify({ error: "webwix_owner_sites_failed", upstream: envelope.status })
46507
+ });
46508
+ } catch (e) {
46509
+ return json3(200, {
46510
+ status: 501,
46511
+ body: JSON.stringify({ error: "webwix_owner_sites_failed", detail: String(e?.message ?? e).slice(0, 200) })
46512
+ });
46513
+ }
46514
+ }
46515
+ if (call.ownerMsid !== void 0) {
46516
+ served.rung = call.checkOwnerSession === true ? "gate" : "owner";
46517
+ if (!webwixOwnerRungOn()) {
46518
+ return json3(503, { error: "webwix_owner_disabled" });
46519
+ }
46520
+ const msid = String(call.ownerMsid);
46521
+ if (!isSafeMsid(msid)) return json3(400, { error: "webwix_owner_bad_msid" });
46522
+ const cookie = request.headers.get("cookie") ?? "";
46523
+ if (!/wixSession2=/.test(cookie)) return json3(501, { error: "webwix_owner_no_session", app: app2 });
46524
+ try {
46525
+ const instance = await webwixOwnerInstances.instance(msid, cookie);
46526
+ if (call.checkOwnerSession === true) return json3(200, { status: 200, body: JSON.stringify({ ready: true }) }, { "cache-control": "no-store" });
46527
+ const first = await wixVisitorCall(method, reqPath, body, instance, webwixFetch, forwardedHeaders);
46528
+ if (first.status !== 401) return json3(200, first);
46529
+ webwixOwnerInstances.invalidate(msid, cookie);
46530
+ const fresh = await webwixOwnerInstances.instance(msid, cookie);
46531
+ return json3(200, await wixVisitorCall(method, reqPath, body, fresh, webwixFetch, forwardedHeaders));
46532
+ } catch (e) {
46533
+ const msg = String(e?.message ?? e);
46534
+ if (msg.includes("absolute URLs")) {
46535
+ return absoluteUrlRejection(reqPath) === "owner-only" ? json3(501, { error: "webwix_owner_only", app: app2 }) : json3(400, { error: "absolute_urls_not_allowed" });
46536
+ }
46537
+ if (msg.includes("owner mint failed")) {
46538
+ if (/owner mint failed \(5\d\d\)/.test(msg)) return json3(502, { error: "webwix_bridge_upstream_failed" });
46539
+ return json3(501, { error: "webwix_owner_mint_failed", app: app2 });
46540
+ }
46541
+ return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
46542
+ }
46543
+ }
46544
+ const resolved2 = wixClientIdOf(utf8Decode(cfgBytes));
46545
+ if ("error" in resolved2) {
46546
+ return json3(501, { error: `webwix_bridge_${resolved2.error}`, app: app2 });
46547
+ }
46548
+ served.rung = "visitor";
46549
+ const memberStore = memberSessions();
46550
+ const memberBoundApp = memberApp(request);
46551
+ if (memberAuthOn() && memberStore && memberBoundApp !== null && memberBoundApp === app2) {
46552
+ const nowAuth = wixMemberAuthOf(utf8Decode(cfgBytes), callbackUrlFor(url));
46553
+ const memberToken = nowAuth.ok ? await memberTokenFor(memberStore, readSessionCookie(request.headers.get("cookie")), memberBoundApp, nowAuth.config.clientId) : null;
46554
+ if (memberToken) {
46555
+ served.rung = "member";
46556
+ try {
46557
+ return json3(200, await wixVisitorCall(method, reqPath, body, memberToken, webwixFetch, forwardedHeaders), { "cache-control": "no-store" });
46558
+ } catch (e) {
46559
+ const msg = String(e?.message ?? e);
46560
+ if (msg.includes("absolute URLs")) {
46561
+ return absoluteUrlRejection(reqPath) === "owner-only" ? json3(501, { error: "webwix_owner_only", app: app2 }) : json3(400, { error: "absolute_urls_not_allowed" });
46562
+ }
46563
+ return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
46564
+ }
46565
+ }
46470
46566
  }
46471
- return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
46472
- }
46473
- }
46474
- const resolved2 = wixClientIdOf(utf8Decode(cfgBytes));
46475
- if ("error" in resolved2) {
46476
- return json3(501, { error: `webwix_bridge_${resolved2.error}`, app: app2 });
46477
- }
46478
- const memberStore = memberSessions();
46479
- const memberBoundApp = memberApp(request);
46480
- if (memberAuthOn() && memberStore && memberBoundApp !== null && memberBoundApp === app2) {
46481
- const nowAuth = wixMemberAuthOf(utf8Decode(cfgBytes), callbackUrlFor(url));
46482
- const memberToken = nowAuth.ok ? await memberTokenFor(memberStore, readSessionCookie(request.headers.get("cookie")), memberBoundApp, nowAuth.config.clientId) : null;
46483
- if (memberToken) {
46484
46567
  try {
46485
- return json3(200, await wixVisitorCall(method, reqPath, body, memberToken, webwixFetch, forwardedHeaders), { "cache-control": "no-store" });
46568
+ const token = await webwixTokens.token(resolved2.clientId);
46569
+ const first = await wixVisitorCall(method, reqPath, body, token, webwixFetch, forwardedHeaders);
46570
+ if (first.status !== 401) return json3(200, first);
46571
+ webwixTokens.invalidate(resolved2.clientId);
46572
+ const fresh = await webwixTokens.token(resolved2.clientId);
46573
+ return json3(200, await wixVisitorCall(method, reqPath, body, fresh, webwixFetch, forwardedHeaders));
46486
46574
  } catch (e) {
46487
46575
  const msg = String(e?.message ?? e);
46488
46576
  if (msg.includes("absolute URLs")) {
@@ -46490,22 +46578,15 @@ ${releaseId}`;
46490
46578
  }
46491
46579
  return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
46492
46580
  }
46581
+ })();
46582
+ status = res.status;
46583
+ return res;
46584
+ } finally {
46585
+ try {
46586
+ opts.onWebwixCall?.(webwixCallLog(served, status));
46587
+ } catch {
46493
46588
  }
46494
46589
  }
46495
- try {
46496
- const token = await webwixTokens.token(resolved2.clientId);
46497
- const first = await wixVisitorCall(method, reqPath, body, token, webwixFetch, forwardedHeaders);
46498
- if (first.status !== 401) return json3(200, first);
46499
- webwixTokens.invalidate(resolved2.clientId);
46500
- const fresh = await webwixTokens.token(resolved2.clientId);
46501
- return json3(200, await wixVisitorCall(method, reqPath, body, fresh, webwixFetch, forwardedHeaders));
46502
- } catch (e) {
46503
- const msg = String(e?.message ?? e);
46504
- if (msg.includes("absolute URLs")) {
46505
- return absoluteUrlRejection(reqPath) === "owner-only" ? json3(501, { error: "webwix_owner_only", app: app2 }) : json3(400, { error: "absolute_urls_not_allowed" });
46506
- }
46507
- return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
46508
- }
46509
46590
  }
46510
46591
  if (request.method !== "GET") return json3(405, { error: "method_not_allowed" });
46511
46592
  if (path2 === "/__health") return json3(200, { ok: true });
@@ -46540,6 +46621,11 @@ ${releaseId}`;
46540
46621
  }
46541
46622
  if (path2 === "/v1/owner/instance") {
46542
46623
  if (opts.webwixBridge === false) return json3(503, { error: "webwix_bridge_disabled" });
46624
+ const gateApp = url.searchParams.get("app");
46625
+ if (gateApp) {
46626
+ const cfg = await appConfigFor(request, url, gateApp);
46627
+ if (!cfg.ok) return cfg.response;
46628
+ }
46543
46629
  if (!webwixOwnerRungOn()) return json3(503, { error: "webwix_owner_disabled" });
46544
46630
  const msid = url.searchParams.get("msid") ?? "";
46545
46631
  if (!isSafeMsid(msid)) return json3(400, { error: "webwix_owner_bad_msid" });
@@ -46669,6 +46755,10 @@ ${releaseId}`;
46669
46755
  const cfgMatch = /^\/v1\/app-config\/([^/]+)$/.exec(path2);
46670
46756
  const app = cfgMatch?.[1] ?? resolveApp(request, url);
46671
46757
  const pin = resolvePin(request, url);
46758
+ if (app && pin) {
46759
+ const denied = await authorizePinnedRead(request, url, app, pin);
46760
+ if (denied) return denied;
46761
+ }
46672
46762
  if (path2 === "/v1/template-source") {
46673
46763
  if (!app) return json3(400, { error: "missing_app" });
46674
46764
  if (!store.getSource) return json3(501, { error: "templates_unsupported" });
@@ -46685,10 +46775,6 @@ ${releaseId}`;
46685
46775
  headers: { "content-type": JSON_CT, etag, "cache-control": DOC_CACHE_CONTROL, "x-himalaya-app": app }
46686
46776
  });
46687
46777
  }
46688
- if (app && pin) {
46689
- const denied = await authorizePinnedRead(request, url, app, pin);
46690
- if (denied) return denied;
46691
- }
46692
46778
  if (path2 === "/v1/authoring-docs" || /^\/v1\/authoring-docs\/(spec|mobile-ux)$/.test(path2)) {
46693
46779
  if (!app) return json3(400, { error: "missing_app" });
46694
46780
  const m = pin ? await pinnedManifest(app, pin) : await manifest(app);
@@ -47008,7 +47094,7 @@ var init_server = __esm({
47008
47094
  init_store();
47009
47095
  init_base64();
47010
47096
  init_contract();
47011
- init_preview_token();
47097
+ init_pinned_read();
47012
47098
  init_package_share();
47013
47099
  init_wix_bridge();
47014
47100
  init_wix_member_auth();
@@ -47198,8 +47284,29 @@ function makeRunHandler(opts) {
47198
47284
  return new Response(null, { status: 204 });
47199
47285
  }
47200
47286
  if (path2 === "/v1/screen-events") {
47201
- return new Response(new ReadableStream({ start() {
47202
- } }), {
47287
+ const source = opts.screenEvents;
47288
+ let unsubscribe;
47289
+ const body = new ReadableStream({
47290
+ start(controller) {
47291
+ if (!source) return;
47292
+ const encoder = new TextEncoder();
47293
+ controller.enqueue(encoder.encode(": himi run --watch\n\n"));
47294
+ unsubscribe = source.subscribe((event, data) => {
47295
+ try {
47296
+ controller.enqueue(encoder.encode(`event: ${event}
47297
+ data: ${JSON.stringify(data ?? {})}
47298
+
47299
+ `));
47300
+ } catch {
47301
+ unsubscribe?.();
47302
+ }
47303
+ });
47304
+ },
47305
+ cancel() {
47306
+ unsubscribe?.();
47307
+ }
47308
+ });
47309
+ return new Response(body, {
47203
47310
  status: 200,
47204
47311
  headers: { "content-type": "text/event-stream", "cache-control": "no-store", connection: "keep-alive" }
47205
47312
  });
@@ -47262,6 +47369,24 @@ async function toRequest(req) {
47262
47369
  async function writeResponse(res, response) {
47263
47370
  res.statusCode = response.status;
47264
47371
  response.headers.forEach((value, key2) => res.setHeader(key2, value));
47372
+ if (response.body && /^text\/event-stream\b/i.test(response.headers.get("content-type") ?? "")) {
47373
+ res.flushHeaders();
47374
+ const reader = response.body.getReader();
47375
+ res.on("close", () => {
47376
+ void reader.cancel().catch(() => {
47377
+ });
47378
+ });
47379
+ try {
47380
+ for (; ; ) {
47381
+ const { done, value } = await reader.read();
47382
+ if (done) break;
47383
+ res.write(value);
47384
+ }
47385
+ } catch {
47386
+ }
47387
+ res.end();
47388
+ return;
47389
+ }
47265
47390
  const ab = await response.arrayBuffer();
47266
47391
  res.end(ab.byteLength ? Buffer.from(ab) : void 0);
47267
47392
  }
@@ -47324,19 +47449,19 @@ var init_preview_assets_generated = __esm({
47324
47449
  "../../packages/serve/src/preview-assets.generated.ts"() {
47325
47450
  init_preview_assets_format();
47326
47451
  PREVIEW_ASSET_MANIFEST = [
47327
- { key: "assets/index-tPdez24X.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1012335, sha256: "9af3d246668e3b69acbdbaebf33129e45f99fdaa32230f782b675fcdeeb38773" },
47328
- { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1012343, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
47329
- { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1103267, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
47330
- { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1194251, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
47331
- { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1285231, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
47332
- { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1376103, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
47333
- { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1467083, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
47334
- { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 1575719, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
47335
- { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 1684803, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
47336
- { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 1793851, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
47337
- { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 1901551, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
47338
- { key: "index.html", contentType: "text/html; charset=utf-8", offset: 1989659, length: 4448, sha256: "c4235c7ba4a7bdea831017711424c9e4f8a8b33466bef53f4def1bfcea6a3b15" },
47339
- { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 1994107, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
47452
+ { key: "assets/index-TpXF5JLO.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1013412, sha256: "e6d1da59c13ca586b7834f4d08ca9e136b7fea8be9355d952d757fc66fc779a5" },
47453
+ { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1013420, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
47454
+ { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1104344, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
47455
+ { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1195328, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
47456
+ { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1286308, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
47457
+ { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1377180, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
47458
+ { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1468160, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
47459
+ { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 1576796, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
47460
+ { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 1685880, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
47461
+ { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 1794928, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
47462
+ { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 1902628, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
47463
+ { key: "index.html", contentType: "text/html; charset=utf-8", offset: 1990736, length: 4448, sha256: "5f0ee56640a5dfc73d3b2b78526aa1f7966de1bec39fe746e0d9ba39d57d829e" },
47464
+ { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 1995184, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
47340
47465
  ];
47341
47466
  }
47342
47467
  });
@@ -47352,7 +47477,7 @@ __export(run_exports, {
47352
47477
  runPackage: () => runPackage,
47353
47478
  withoutProdServe: () => withoutProdServe
47354
47479
  });
47355
- import { cpSync as cpSync2, existsSync as existsSync52, mkdirSync as mkdirSync26, mkdtempSync as mkdtempSync3, readFileSync as readFileSync57, rmSync as rmSync10, statSync as statSync13 } from "node:fs";
47480
+ import { cpSync as cpSync2, existsSync as existsSync52, mkdirSync as mkdirSync25, mkdtempSync as mkdtempSync3, readFileSync as readFileSync57, rmSync as rmSync11, statSync as statSync13 } from "node:fs";
47356
47481
  import { tmpdir as tmpdir4 } from "node:os";
47357
47482
  import { dirname as dirname27, join as join49 } from "node:path";
47358
47483
  import { fileURLToPath as fileURLToPath22 } from "node:url";
@@ -47362,7 +47487,8 @@ function makePackageRunHandler(opts) {
47362
47487
  app: opts.app,
47363
47488
  assets: opts.assets,
47364
47489
  ...opts.chrome ? { chrome: opts.chrome } : {},
47365
- header: opts.header ?? null
47490
+ header: opts.header ?? null,
47491
+ ...opts.screenEvents ? { screenEvents: opts.screenEvents } : {}
47366
47492
  });
47367
47493
  }
47368
47494
  async function fetchBytes(url) {
@@ -47386,8 +47512,8 @@ async function resolvePackage(source, workDir) {
47386
47512
  const root2 = workDir ?? mkdtempSync3(join49(tmpdir4(), "himi-run-"));
47387
47513
  const target = join49(root2, app2);
47388
47514
  if (join49(source) !== target) {
47389
- mkdirSync26(root2, { recursive: true });
47390
- rmSync10(target, { recursive: true, force: true });
47515
+ mkdirSync25(root2, { recursive: true });
47516
+ rmSync11(target, { recursive: true, force: true });
47391
47517
  cpSync2(source, target, { recursive: true });
47392
47518
  }
47393
47519
  return {
@@ -47407,7 +47533,7 @@ async function resolvePackage(source, workDir) {
47407
47533
  const { app, appDir: appDir2 } = unpackTo(bytes2, root);
47408
47534
  const opened = openPackageDir(appDir2);
47409
47535
  if (!opened.validation.ok) {
47410
- rmSync10(workDir ? appDir2 : root, { recursive: true, force: true });
47536
+ rmSync11(workDir ? appDir2 : root, { recursive: true, force: true });
47411
47537
  throw new Error(`package is not valid:
47412
47538
  ${opened.validation.errors.join("\n ")}`);
47413
47539
  }
@@ -47454,16 +47580,19 @@ async function runPackage(source, opts = {}) {
47454
47580
  const resolved2 = await resolvePackage(source, opts.workDir);
47455
47581
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
47456
47582
  if (!opts.spa && assets.size === 0) {
47457
- if (resolved2.temp) rmSync10(resolved2.temp, { recursive: true, force: true });
47583
+ if (resolved2.temp) rmSync11(resolved2.temp, { recursive: true, force: true });
47458
47584
  throw new Error(NO_SPA_MESSAGE);
47459
47585
  }
47460
- const handler = makePackageRunHandler({
47586
+ const plane = makePackageRunHandler({
47461
47587
  releaseRoot: resolved2.releaseRoot,
47462
47588
  app: resolved2.app,
47463
47589
  assets,
47464
47590
  chrome: opts.chrome,
47465
- header: resolved2.header
47591
+ header: resolved2.header,
47592
+ ...opts.screenEvents ? { screenEvents: opts.screenEvents } : {}
47466
47593
  });
47594
+ const extra = opts.extraRoutes;
47595
+ const handler = extra ? (request) => extra(request) ?? plane(request) : plane;
47467
47596
  const server = nodeAdapter(handler);
47468
47597
  const host = opts.host ?? "127.0.0.1";
47469
47598
  const port = await new Promise((resolvePort, reject) => {
@@ -47481,10 +47610,13 @@ async function runPackage(source, opts = {}) {
47481
47610
  releaseId: resolved2.releaseId,
47482
47611
  port,
47483
47612
  url,
47613
+ releaseRoot: resolved2.releaseRoot,
47614
+ origin,
47484
47615
  warnings: resolved2.warnings,
47485
47616
  close: () => new Promise((done) => {
47617
+ server.closeAllConnections?.();
47486
47618
  server.close(() => {
47487
- if (resolved2.temp) rmSync10(resolved2.temp, { recursive: true, force: true });
47619
+ if (resolved2.temp) rmSync11(resolved2.temp, { recursive: true, force: true });
47488
47620
  done();
47489
47621
  });
47490
47622
  })
@@ -47504,6 +47636,250 @@ var init_run = __esm({
47504
47636
  }
47505
47637
  });
47506
47638
 
47639
+ // src/run-watch.ts
47640
+ var run_watch_exports = {};
47641
+ __export(run_watch_exports, {
47642
+ ReloadBus: () => ReloadBus,
47643
+ boardFile: () => boardFile,
47644
+ diffReleases: () => diffReleases,
47645
+ himiDir: () => himiDir,
47646
+ ignoredChange: () => ignoredChange,
47647
+ isEmptyDiff: () => isEmptyDiff,
47648
+ rebuildBlocker: () => rebuildBlocker,
47649
+ reloadEvents: () => reloadEvents,
47650
+ removeRunRecord: () => removeRunRecord,
47651
+ serialize: () => serialize,
47652
+ watchContent: () => watchContent,
47653
+ watchFlagConflict: () => watchFlagConflict,
47654
+ watchedContentDir: () => watchedContentDir,
47655
+ writeRunRecord: () => writeRunRecord
47656
+ });
47657
+ import { closeSync as closeSync2, constants, existsSync as existsSync53, fstatSync, lstatSync as lstatSync7, statSync as statSync14, mkdirSync as mkdirSync26, openSync as openSync2, readFileSync as readFileSync58, realpathSync as realpathSync6, renameSync as renameSync5, rmSync as rmSync12, writeFileSync as writeFileSync22, watch as fsWatch } from "node:fs";
47658
+ import { randomUUID as randomUUID3 } from "node:crypto";
47659
+ import { extname as extname4, join as join50, resolve as resolve42, sep as sep13 } from "node:path";
47660
+ function diffReleases(prev, next) {
47661
+ const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
47662
+ const changedBundles = new Set(bundles);
47663
+ const screens = Object.entries(next.screens).filter(([id, s]) => {
47664
+ const before = prev.screens[id];
47665
+ return !before || before.descriptorHash !== s.descriptorHash || before.bundle !== s.bundle || s.bundle !== null && changedBundles.has(s.bundle);
47666
+ }).map(([id]) => id).sort();
47667
+ const prevIds = Object.keys(prev.screens).sort().join("\n");
47668
+ const nextIds = Object.keys(next.screens).sort().join("\n");
47669
+ return {
47670
+ screens,
47671
+ bundles,
47672
+ tokens: prev.tokensHash !== next.tokensHash,
47673
+ config: prev.appConfigHash !== next.appConfigHash || prevIds !== nextIds
47674
+ };
47675
+ }
47676
+ function reloadEvents(d) {
47677
+ const out = [];
47678
+ if (d.bundles.length) out.push(["bundle.invalidated", { bundles: d.bundles }]);
47679
+ if (d.screens.length) out.push(["screen.invalidated", { screenIds: d.screens }]);
47680
+ if (d.tokens) out.push(["tokens.changed", {}]);
47681
+ if (d.config) out.push(["config.invalidated", {}]);
47682
+ return out;
47683
+ }
47684
+ function ignoredChange(relPath, isDirectory = () => false) {
47685
+ const parts = relPath.split(/[\\/]/).filter(Boolean);
47686
+ if (!parts.length) return true;
47687
+ const [top] = parts;
47688
+ if ([".himi", "dist", "node_modules", ".git", ".build"].includes(top)) return true;
47689
+ if ((top === "shots" || top === "evidence") && (parts.length > 1 || isDirectory(top))) return true;
47690
+ const name = parts[parts.length - 1];
47691
+ return /(^\.#|~$|\.sw[a-p]$|^\.DS_Store$|\.tmp$)/.test(name);
47692
+ }
47693
+ function watchContent(dir, onChange, opts = {}) {
47694
+ const debounceMs = opts.debounceMs ?? 200;
47695
+ const watch2 = opts.watch ?? ((p, o, l) => fsWatch(p, o, (event, file) => l(event, file === null ? null : String(file))));
47696
+ let timer = null;
47697
+ const pending = /* @__PURE__ */ new Set();
47698
+ const watcher = watch2(dir, { recursive: true }, (_event, file) => {
47699
+ if (!file || ignoredChange(file, (rel) => isDir(join50(dir, rel)))) return;
47700
+ pending.add(file);
47701
+ if (timer) clearTimeout(timer);
47702
+ timer = setTimeout(() => {
47703
+ timer = null;
47704
+ const paths = [...pending];
47705
+ pending.clear();
47706
+ onChange(paths);
47707
+ }, debounceMs);
47708
+ });
47709
+ return {
47710
+ close() {
47711
+ if (timer) clearTimeout(timer);
47712
+ watcher.close();
47713
+ }
47714
+ };
47715
+ }
47716
+ function watchedContentDir(source) {
47717
+ if (!source || /^https?:\/\//i.test(source)) return null;
47718
+ const dir = resolve42(source);
47719
+ try {
47720
+ return statSync14(dir).isDirectory() && existsSync53(join50(dir, "himalaya.content.json")) ? dir : null;
47721
+ } catch {
47722
+ return null;
47723
+ }
47724
+ }
47725
+ function watchFlagConflict(opts) {
47726
+ if (opts.source) {
47727
+ return { error: "watch_needs_source", message: "--watch rebuilds a content package on every save, so it cannot watch a packaged release or a URL. Pass the app's directory (the one with himalaya.content.json), --content <dir>, or run it from there with no argument." };
47728
+ }
47729
+ if (opts.browser) {
47730
+ return { error: "watch_with_browser", message: "--watch rebuilds and serves from this process; --browser runs the whole plane inside the tab. Pick one." };
47731
+ }
47732
+ if (opts.spa) {
47733
+ return { error: "watch_with_spa", message: "--watch pushes each rebuild to the open tab over this server's own origin, and a hosted SPA (--spa) listens on its origin instead, so it would never repaint. Drop --spa to watch with the bundled web host, or drop --watch." };
47734
+ }
47735
+ return null;
47736
+ }
47737
+ function rebuildBlocker(outcome, servedMissing) {
47738
+ const failed2 = outcome.failedToBuild[0];
47739
+ if (failed2) return `${failed2.screenId}: ${failed2.error.split("\n")[0]}`;
47740
+ const had = new Set(servedMissing.map((m) => `${m.screen}\0${m.bundle}`));
47741
+ const lost = outcome.missingBundles.find((m) => !had.has(`${m.screen}\0${m.bundle}`));
47742
+ if (lost) return `${lost.screen}: its worker bundle "${lost.bundle}" is referenced but was not built`;
47743
+ return null;
47744
+ }
47745
+ function serialize(task) {
47746
+ let running = null;
47747
+ let again = false;
47748
+ let stopped = false;
47749
+ const go = () => {
47750
+ if (stopped) return;
47751
+ if (running) {
47752
+ again = true;
47753
+ return;
47754
+ }
47755
+ running = (async () => {
47756
+ try {
47757
+ await task();
47758
+ } finally {
47759
+ running = null;
47760
+ if (again && !stopped) {
47761
+ again = false;
47762
+ go();
47763
+ }
47764
+ }
47765
+ })();
47766
+ };
47767
+ return Object.assign(() => go(), {
47768
+ async stop() {
47769
+ stopped = true;
47770
+ again = false;
47771
+ await running?.catch(() => {
47772
+ });
47773
+ }
47774
+ });
47775
+ }
47776
+ function himiDir(dir) {
47777
+ const root = join50(dir, ".himi");
47778
+ try {
47779
+ return lstatSync7(root).isDirectory() ? root : null;
47780
+ } catch (e) {
47781
+ if (e.code !== "ENOENT") return null;
47782
+ mkdirSync26(root, { recursive: true });
47783
+ return lstatSync7(root).isDirectory() ? root : null;
47784
+ }
47785
+ }
47786
+ function writeRunRecord(dir, record2) {
47787
+ const root = himiDir(dir);
47788
+ if (!root) return false;
47789
+ const tmp = join50(root, `.run.json.${process.pid}.${randomUUID3()}.tmp`);
47790
+ try {
47791
+ writeFileSync22(tmp, `${JSON.stringify(record2, null, 2)}
47792
+ `, { flag: "wx" });
47793
+ renameSync5(tmp, join50(root, "run.json"));
47794
+ } catch (e) {
47795
+ rmSync12(tmp, { force: true });
47796
+ throw e;
47797
+ }
47798
+ return true;
47799
+ }
47800
+ function removeRunRecord(dir) {
47801
+ const root = join50(dir, ".himi");
47802
+ try {
47803
+ if (!lstatSync7(root).isDirectory()) return;
47804
+ } catch {
47805
+ return;
47806
+ }
47807
+ rmSync12(join50(root, "run.json"), { force: true });
47808
+ }
47809
+ function boardFile(dir, pathname) {
47810
+ let rel = null;
47811
+ if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join50("studio", "index.html");
47812
+ else if (pathname === "/__himi/studio/state.js") rel = join50("studio", "state.js");
47813
+ else {
47814
+ const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
47815
+ if (m) rel = join50("history", m[1]);
47816
+ }
47817
+ if (!rel) return null;
47818
+ const bytes2 = readConfined(resolve42(dir, ".himi"), rel);
47819
+ if (!bytes2) return new Response("not found", { status: 404 });
47820
+ return new Response(bytes2, {
47821
+ status: 200,
47822
+ headers: { "content-type": BOARD_TYPES[extname4(rel)] ?? "application/octet-stream", "cache-control": rel.startsWith("history") ? "public, max-age=31536000, immutable" : "no-store" }
47823
+ });
47824
+ }
47825
+ function readConfined(root, rel) {
47826
+ try {
47827
+ if (!lstatSync7(root).isDirectory()) return null;
47828
+ const parts = rel.split(sep13);
47829
+ let at = root;
47830
+ for (let i = 0; i < parts.length; i++) {
47831
+ at = join50(at, parts[i]);
47832
+ const st = lstatSync7(at);
47833
+ if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
47834
+ }
47835
+ const canonicalRoot = realpathSync6(root);
47836
+ if (!realpathSync6(at).startsWith(canonicalRoot + sep13)) return null;
47837
+ const fd = openSync2(at, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
47838
+ try {
47839
+ if (!fstatSync(fd).isFile()) return null;
47840
+ return readFileSync58(fd);
47841
+ } finally {
47842
+ closeSync2(fd);
47843
+ }
47844
+ } catch {
47845
+ return null;
47846
+ }
47847
+ }
47848
+ var isEmptyDiff, ReloadBus, isDir, BOARD_TYPES;
47849
+ var init_run_watch = __esm({
47850
+ "src/run-watch.ts"() {
47851
+ isEmptyDiff = (d) => !d.screens.length && !d.bundles.length && !d.tokens && !d.config;
47852
+ ReloadBus = class {
47853
+ subscribers = /* @__PURE__ */ new Set();
47854
+ subscribe(send2) {
47855
+ this.subscribers.add(send2);
47856
+ return () => this.subscribers.delete(send2);
47857
+ }
47858
+ publish(event, data) {
47859
+ for (const send2 of [...this.subscribers]) send2(event, data);
47860
+ }
47861
+ get listeners() {
47862
+ return this.subscribers.size;
47863
+ }
47864
+ };
47865
+ isDir = (path2) => {
47866
+ try {
47867
+ return statSync14(path2).isDirectory();
47868
+ } catch {
47869
+ return false;
47870
+ }
47871
+ };
47872
+ BOARD_TYPES = {
47873
+ ".html": "text/html; charset=utf-8",
47874
+ ".js": "text/javascript; charset=utf-8",
47875
+ ".png": "image/png",
47876
+ ".jpg": "image/jpeg",
47877
+ ".gif": "image/gif",
47878
+ ".webp": "image/webp"
47879
+ };
47880
+ }
47881
+ });
47882
+
47507
47883
  // src/run-browser.ts
47508
47884
  var run_browser_exports = {};
47509
47885
  __export(run_browser_exports, {
@@ -47512,19 +47888,19 @@ __export(run_browser_exports, {
47512
47888
  runInBrowser: () => runInBrowser
47513
47889
  });
47514
47890
  import { createServer as createServer5 } from "node:http";
47515
- import { existsSync as existsSync53, readFileSync as readFileSync58 } from "node:fs";
47891
+ import { existsSync as existsSync54, readFileSync as readFileSync59 } from "node:fs";
47516
47892
  import { spawnSync as spawnSync3 } from "node:child_process";
47517
- import { dirname as dirname28, resolve as resolve42 } from "node:path";
47893
+ import { dirname as dirname28, resolve as resolve43 } from "node:path";
47518
47894
  import { fileURLToPath as fileURLToPath23 } from "node:url";
47519
47895
  function stagedDir() {
47520
- return process.env.HIMI_BROWSER_PLANE_OUT ? resolve42(process.env.HIMI_BROWSER_PLANE_OUT) : resolve42(REPO, "packages", "serve", "dist", "browser-plane");
47896
+ return process.env.HIMI_BROWSER_PLANE_OUT ? resolve43(process.env.HIMI_BROWSER_PLANE_OUT) : resolve43(REPO, "packages", "serve", "dist", "browser-plane");
47521
47897
  }
47522
47898
  function missingStaged() {
47523
- return [...SERVED].filter((f) => !existsSync53(resolve42(stagedDir(), f))).sort();
47899
+ return [...SERVED].filter((f) => !existsSync54(resolve43(stagedDir(), f))).sort();
47524
47900
  }
47525
47901
  function ensureBrowserPlaneStaged() {
47526
47902
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
47527
- const r = spawnSync3(process.execPath, [resolve42(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
47903
+ const r = spawnSync3(process.execPath, [resolve43(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
47528
47904
  cwd: REPO,
47529
47905
  encoding: "utf8"
47530
47906
  });
@@ -47610,7 +47986,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
47610
47986
  }
47611
47987
  const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
47612
47988
  if (SERVED.has(name)) {
47613
- if (!existsSync53(resolve42(stagedDir(), name))) {
47989
+ if (!existsSync54(resolve43(stagedDir(), name))) {
47614
47990
  const restaged = ensureBrowserPlaneStaged();
47615
47991
  if (!restaged.ok) {
47616
47992
  res.writeHead(503, { "content-type": "application/json" });
@@ -47620,7 +47996,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
47620
47996
  }
47621
47997
  let bytes2;
47622
47998
  try {
47623
- bytes2 = readFileSync58(resolve42(stagedDir(), name));
47999
+ bytes2 = readFileSync59(resolve43(stagedDir(), name));
47624
48000
  } catch (e) {
47625
48001
  res.writeHead(503, { "content-type": "application/json" });
47626
48002
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
@@ -47661,7 +48037,7 @@ var init_run_browser = __esm({
47661
48037
  init_open_url();
47662
48038
  init_file_store();
47663
48039
  HERE = dirname28(fileURLToPath23(import.meta.url));
47664
- REPO = resolve42(HERE, "..", "..", "..");
48040
+ REPO = resolve43(HERE, "..", "..", "..");
47665
48041
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
47666
48042
  }
47667
48043
  });
@@ -48080,10 +48456,10 @@ __export(preflight_exports, {
48080
48456
  parseStoreConfig: () => parseStoreConfig,
48081
48457
  requireEnv: () => requireEnv
48082
48458
  });
48083
- import { existsSync as existsSync54, readFileSync as readFileSync59 } from "node:fs";
48084
- import { isAbsolute as isAbsolute3, relative as relative9, resolve as resolve43 } from "node:path";
48459
+ import { existsSync as existsSync55, readFileSync as readFileSync60 } from "node:fs";
48460
+ import { isAbsolute as isAbsolute3, relative as relative9, resolve as resolve44 } from "node:path";
48085
48461
  function isInsideRepo(p) {
48086
- const rel = relative9(REPO_ROOT3, resolve43(p));
48462
+ const rel = relative9(REPO_ROOT3, resolve44(p));
48087
48463
  return rel !== "" && !rel.startsWith("..") && !isAbsolute3(rel);
48088
48464
  }
48089
48465
  function assertCredentialOutsideRepo(label2, p) {
@@ -48137,10 +48513,10 @@ function parseStoreConfig(text5) {
48137
48513
  }
48138
48514
  function loadStoreConfig(app) {
48139
48515
  const p = storeConfigPath(app);
48140
- if (!existsSync54(p)) {
48516
+ if (!existsSync55(p)) {
48141
48517
  throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
48142
48518
  }
48143
- return parseStoreConfig(readFileSync59(p, "utf8"));
48519
+ return parseStoreConfig(readFileSync60(p, "utf8"));
48144
48520
  }
48145
48521
  var init_preflight = __esm({
48146
48522
  "../store-release/preflight.ts"() {
@@ -48159,19 +48535,19 @@ __export(credential_profile_exports, {
48159
48535
  profilePath: () => profilePath,
48160
48536
  resolveStoreCredentials: () => resolveStoreCredentials
48161
48537
  });
48162
- import { existsSync as existsSync55, readFileSync as readFileSync60 } from "node:fs";
48538
+ import { existsSync as existsSync56, readFileSync as readFileSync61 } from "node:fs";
48163
48539
  import { homedir as homedir5 } from "node:os";
48164
- import { join as join50 } from "node:path";
48540
+ import { join as join51 } from "node:path";
48165
48541
  function credentialsDir(home = homedir5()) {
48166
- return join50(home, ".himalaya", "store-credentials");
48542
+ return join51(home, ".himalaya", "store-credentials");
48167
48543
  }
48168
48544
  function profilePath(name, home = homedir5()) {
48169
48545
  if (!PROFILE_NAME.test(name)) {
48170
48546
  throw new Error(
48171
- `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join50(credentialsDir(home), "<name>.json")}; it is never a path.`
48547
+ `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join51(credentialsDir(home), "<name>.json")}; it is never a path.`
48172
48548
  );
48173
48549
  }
48174
- return join50(credentialsDir(home), `${name}.json`);
48550
+ return join51(credentialsDir(home), `${name}.json`);
48175
48551
  }
48176
48552
  function parseProfile(text5, label2) {
48177
48553
  let doc;
@@ -48202,8 +48578,8 @@ function resolveStoreCredentials(opts) {
48202
48578
  const { app, cfg } = opts;
48203
48579
  const env = opts.env ?? process.env;
48204
48580
  const home = opts.home ?? homedir5();
48205
- const read = opts.readProfile ?? ((p) => readFileSync60(p, "utf8"));
48206
- const exists = opts.profileExists ?? existsSync55;
48581
+ const read = opts.readProfile ?? ((p) => readFileSync61(p, "utf8"));
48582
+ const exists = opts.profileExists ?? existsSync56;
48207
48583
  const ios = cfg.ios ?? {};
48208
48584
  const flagName = opts.profileFlag?.trim();
48209
48585
  const named = namedProfile(cfg, opts.profileFlag);
@@ -48283,9 +48659,9 @@ __export(preflight_app_exports, {
48283
48659
  preflightApp: () => preflightApp,
48284
48660
  profileAccount: () => profileAccount
48285
48661
  });
48286
- import { readFileSync as readFileSync61, existsSync as existsSync56, readdirSync as readdirSync26, statSync as statSync14 } from "node:fs";
48662
+ import { readFileSync as readFileSync62, existsSync as existsSync57, readdirSync as readdirSync26, statSync as statSync15 } from "node:fs";
48287
48663
  import { createHash as createHash25 } from "node:crypto";
48288
- import { join as join51 } from "node:path";
48664
+ import { join as join52 } from "node:path";
48289
48665
  function analyze(projectYml, storeConfig, icon, account) {
48290
48666
  const f = [];
48291
48667
  const has = (re, s) => re.test(s);
@@ -48349,13 +48725,13 @@ function profileAccount(app, storeConfig, opts = {}) {
48349
48725
  }
48350
48726
  }
48351
48727
  async function preflightApp(app, opts = {}) {
48352
- const projectYml = existsSync56(iosProjectYml(app)) ? readFileSync61(iosProjectYml(app), "utf8") : "";
48353
- const storeConfig = existsSync56(storeConfigPath(app)) ? readFileSync61(storeConfigPath(app), "utf8") : "";
48728
+ const projectYml = existsSync57(iosProjectYml(app)) ? readFileSync62(iosProjectYml(app), "utf8") : "";
48729
+ const storeConfig = existsSync57(storeConfigPath(app)) ? readFileSync62(storeConfigPath(app), "utf8") : "";
48354
48730
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
48355
48731
  const findings = analyze(
48356
48732
  projectYml,
48357
48733
  storeConfig,
48358
- await appIconState(join51(appDir(app), "ios")),
48734
+ await appIconState(join52(appDir(app), "ios")),
48359
48735
  profileAccount(app, storeConfig, opts)
48360
48736
  );
48361
48737
  findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
@@ -48384,17 +48760,17 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
48384
48760
  return f;
48385
48761
  }
48386
48762
  function appLevelMetadataFiles(app, locale = "en-US") {
48387
- const root = join51(storeDir(app), "metadata");
48763
+ const root = join52(storeDir(app), "metadata");
48388
48764
  const out = /* @__PURE__ */ new Set();
48389
- if (existsSync56(root)) {
48765
+ if (existsSync57(root)) {
48390
48766
  for (const n of readdirSync26(root)) if (n.endsWith(".txt")) out.add(n);
48391
48767
  }
48392
- if (existsSync56(join51(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
48768
+ if (existsSync57(join52(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
48393
48769
  return out;
48394
48770
  }
48395
48771
  function reviewInfoFiles(app) {
48396
- const dir = join51(storeDir(app), "review_information");
48397
- if (!existsSync56(dir)) return /* @__PURE__ */ new Set();
48772
+ const dir = join52(storeDir(app), "review_information");
48773
+ if (!existsSync57(dir)) return /* @__PURE__ */ new Set();
48398
48774
  return new Set(readdirSync26(dir).filter((n) => n.endsWith(".txt")));
48399
48775
  }
48400
48776
  function isValidAppStoreSize(w, h) {
@@ -48504,12 +48880,12 @@ function analyzePlayListing(assets) {
48504
48880
  return f;
48505
48881
  }
48506
48882
  function playListingAssets(app, locale = "en-US") {
48507
- const dir = join51(storeDir(app), "play", locale, "images");
48883
+ const dir = join52(storeDir(app), "play", locale, "images");
48508
48884
  const read = (names) => {
48509
48885
  for (const name of names) {
48510
- const p = join51(dir, name);
48886
+ const p = join52(dir, name);
48511
48887
  try {
48512
- if (statSync14(p).isFile()) return { name, bytes: readFileSync61(p) };
48888
+ if (statSync15(p).isFile()) return { name, bytes: readFileSync62(p) };
48513
48889
  } catch {
48514
48890
  }
48515
48891
  }
@@ -48540,26 +48916,26 @@ function analyzeListing(metaFiles, shots) {
48540
48916
  return f;
48541
48917
  }
48542
48918
  function metadataFilesPresent(app, locale = "en-US") {
48543
- const dir = join51(storeDir(app), "metadata", locale);
48544
- if (!existsSync56(dir)) return /* @__PURE__ */ new Set();
48919
+ const dir = join52(storeDir(app), "metadata", locale);
48920
+ if (!existsSync57(dir)) return /* @__PURE__ */ new Set();
48545
48921
  return new Set(readdirSync26(dir).filter((n) => n.endsWith(".txt")));
48546
48922
  }
48547
48923
  function listScreenshots(app, locale = "en-US") {
48548
48924
  const out = [];
48549
- const flat = join51(storeDir(app), "screenshots", locale);
48550
- if (existsSync56(flat)) {
48925
+ const flat = join52(storeDir(app), "screenshots", locale);
48926
+ if (existsSync57(flat)) {
48551
48927
  for (const png of readdirSync26(flat).filter((n) => n.endsWith(".png"))) {
48552
- const sz = pngSize(readFileSync61(join51(flat, png)));
48928
+ const sz = pngSize(readFileSync62(join52(flat, png)));
48553
48929
  if (sz) out.push({ name: png, w: sz.w, h: sz.h });
48554
48930
  }
48555
48931
  }
48556
- const legacy = join51(storeDir(app), "metadata", locale, "screenshots");
48557
- if (existsSync56(legacy)) {
48932
+ const legacy = join52(storeDir(app), "metadata", locale, "screenshots");
48933
+ if (existsSync57(legacy)) {
48558
48934
  for (const deviceDir of readdirSync26(legacy)) {
48559
- const d = join51(legacy, deviceDir);
48560
- if (!statSync14(d).isDirectory()) continue;
48935
+ const d = join52(legacy, deviceDir);
48936
+ if (!statSync15(d).isDirectory()) continue;
48561
48937
  for (const png of readdirSync26(d).filter((n) => n.endsWith(".png"))) {
48562
- const sz = pngSize(readFileSync61(join51(d, png)));
48938
+ const sz = pngSize(readFileSync62(join52(d, png)));
48563
48939
  if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
48564
48940
  }
48565
48941
  }
@@ -48567,13 +48943,13 @@ function listScreenshots(app, locale = "en-US") {
48567
48943
  return out;
48568
48944
  }
48569
48945
  function placeholderHashes2() {
48570
- const templateIos = join51(appDir("_template"), "ios");
48571
- if (!existsSync56(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
48946
+ const templateIos = join52(appDir("_template"), "ios");
48947
+ if (!existsSync57(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
48572
48948
  for (const target of readdirSync26(templateIos)) {
48573
- const p = join51(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
48949
+ const p = join52(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
48574
48950
  try {
48575
- if (!statSync14(p).isFile()) continue;
48576
- return [LEGACY_PLACEHOLDER_SHA2562, createHash25("sha256").update(readFileSync61(p)).digest("hex")];
48951
+ if (!statSync15(p).isFile()) continue;
48952
+ return [LEGACY_PLACEHOLDER_SHA2562, createHash25("sha256").update(readFileSync62(p)).digest("hex")];
48577
48953
  } catch {
48578
48954
  }
48579
48955
  }
@@ -48604,12 +48980,12 @@ async function pixelIssues(bytes2) {
48604
48980
  }
48605
48981
  }
48606
48982
  async function appIconState(iosDir) {
48607
- if (!existsSync56(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
48983
+ if (!existsSync57(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
48608
48984
  for (const target of readdirSync26(iosDir)) {
48609
- const p = join51(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
48985
+ const p = join52(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
48610
48986
  try {
48611
- if (!statSync14(p).isFile()) continue;
48612
- const bytes2 = readFileSync61(p);
48987
+ if (!statSync15(p).isFile()) continue;
48988
+ const bytes2 = readFileSync62(p);
48613
48989
  const hash = createHash25("sha256").update(bytes2).digest("hex");
48614
48990
  const pixels = await pixelIssues(bytes2);
48615
48991
  return {
@@ -48681,7 +49057,7 @@ __export(version_exports, {
48681
49057
  setAndroidVersion: () => setAndroidVersion,
48682
49058
  setIosVersion: () => setIosVersion
48683
49059
  });
48684
- import { readFileSync as readFileSync62, writeFileSync as writeFileSync23 } from "node:fs";
49060
+ import { readFileSync as readFileSync63, writeFileSync as writeFileSync23 } from "node:fs";
48685
49061
  function readIosVersion(projectYml) {
48686
49062
  const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
48687
49063
  const build2 = matchScalar(projectYml, "CFBundleVersion");
@@ -48739,8 +49115,8 @@ function setAndroidVersion(gradle, v) {
48739
49115
  function bumpVersion(app, opts) {
48740
49116
  const iosPath = iosProjectYml(app);
48741
49117
  const gradlePath = androidGradle(app);
48742
- const iosYml = readFileSync62(iosPath, "utf8");
48743
- const gradle = readFileSync62(gradlePath, "utf8");
49118
+ const iosYml = readFileSync63(iosPath, "utf8");
49119
+ const gradle = readFileSync63(gradlePath, "utf8");
48744
49120
  const current = readIosVersion(iosYml);
48745
49121
  const next = {
48746
49122
  marketing: opts.marketing ?? current.marketing,
@@ -48757,7 +49133,7 @@ var init_version = __esm({
48757
49133
  });
48758
49134
 
48759
49135
  // ../store-release/register-bundle.ts
48760
- import { readFileSync as readFileSync63 } from "node:fs";
49136
+ import { readFileSync as readFileSync64 } from "node:fs";
48761
49137
  import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
48762
49138
  function b64url2(b) {
48763
49139
  return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -48775,7 +49151,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
48775
49151
  async function registerBundleId(opts) {
48776
49152
  const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
48777
49153
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
48778
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync63(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
49154
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync64(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
48779
49155
  const res = await fetch(`${ASC_API}/v1/bundleIds`, {
48780
49156
  method: "POST",
48781
49157
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
@@ -48829,7 +49205,7 @@ __export(asc_status_exports, {
48829
49205
  ascStatus: () => ascStatus,
48830
49206
  buildVerdict: () => buildVerdict
48831
49207
  });
48832
- import { readFileSync as readFileSync64 } from "node:fs";
49208
+ import { readFileSync as readFileSync65 } from "node:fs";
48833
49209
  function buildVerdict(builds) {
48834
49210
  if (!builds.length) {
48835
49211
  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).";
@@ -48843,7 +49219,7 @@ function buildVerdict(builds) {
48843
49219
  function client(creds) {
48844
49220
  const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
48845
49221
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
48846
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync64(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
49222
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync65(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
48847
49223
  return async (path2) => {
48848
49224
  const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
48849
49225
  return { status: r.status, json: await r.json().catch(() => ({})) };
@@ -49003,7 +49379,7 @@ __export(secrets_exports, {
49003
49379
  runRemoteSecretsCommand: () => runRemoteSecretsCommand,
49004
49380
  runSecretsCommand: () => runSecretsCommand
49005
49381
  });
49006
- import { readFileSync as readFileSync65 } from "node:fs";
49382
+ import { readFileSync as readFileSync66 } from "node:fs";
49007
49383
  function environment(value) {
49008
49384
  if (value === "preview" || value === "production") return value;
49009
49385
  throw new Error("--environment must be preview or production");
@@ -49034,7 +49410,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
49034
49410
  io.log(JSON.stringify(await vault.list({ app, environment: env })));
49035
49411
  return 0;
49036
49412
  }
49037
- const value = options.readValue ? options.readValue() : readFileSync65(0, "utf8").replace(/\r?\n$/, "");
49413
+ const value = options.readValue ? options.readValue() : readFileSync66(0, "utf8").replace(/\r?\n$/, "");
49038
49414
  if (operation === "set") await vault.set({ app, environment: env, name, value });
49039
49415
  else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
49040
49416
  else throw new Error(`unknown secrets operation ${operation}`);
@@ -49063,7 +49439,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
49063
49439
  }
49064
49440
  let body;
49065
49441
  if (operation !== "list") {
49066
- const value = options.readValue ? options.readValue() : readFileSync65(0, "utf8").replace(/\r?\n$/, "");
49442
+ const value = options.readValue ? options.readValue() : readFileSync66(0, "utf8").replace(/\r?\n$/, "");
49067
49443
  body = JSON.stringify({ value });
49068
49444
  }
49069
49445
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
@@ -49099,15 +49475,15 @@ __export(notify_exports, {
49099
49475
  runNotify: () => runNotify,
49100
49476
  saveAdminSession: () => saveAdminSession
49101
49477
  });
49102
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync27, readFileSync as readFileSync66, writeFileSync as writeFileSync24 } from "node:fs";
49478
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync27, readFileSync as readFileSync67, writeFileSync as writeFileSync24 } from "node:fs";
49103
49479
  import { homedir as homedir6 } from "node:os";
49104
- import { dirname as dirname30, join as join52 } from "node:path";
49480
+ import { dirname as dirname30, join as join53 } from "node:path";
49105
49481
  function defaultSessionsPath() {
49106
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join52(homedir6(), ".himalaya", "admin-sessions.json");
49482
+ return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join53(homedir6(), ".himalaya", "admin-sessions.json");
49107
49483
  }
49108
49484
  function loadSessionsFile(path2 = defaultSessionsPath()) {
49109
49485
  try {
49110
- return JSON.parse(readFileSync66(path2, "utf8"));
49486
+ return JSON.parse(readFileSync67(path2, "utf8"));
49111
49487
  } catch {
49112
49488
  return {};
49113
49489
  }
@@ -51764,10 +52140,10 @@ function assertPublicSiteUrl(raw) {
51764
52140
  if (refusal) throw new Error(refusal);
51765
52141
  }
51766
52142
  function resolveAll(hostname2) {
51767
- return new Promise((resolve47, reject) => {
52143
+ return new Promise((resolve48, reject) => {
51768
52144
  dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
51769
52145
  if (err) reject(err);
51770
- else resolve47(addresses);
52146
+ else resolve48(addresses);
51771
52147
  });
51772
52148
  });
51773
52149
  }
@@ -51775,13 +52151,13 @@ function withAbort(start, signal, what) {
51775
52151
  if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
51776
52152
  const work = start();
51777
52153
  if (!signal) return work;
51778
- return new Promise((resolve47, reject) => {
52154
+ return new Promise((resolve48, reject) => {
51779
52155
  const onAbort = () => reject(new Error(`${what} aborted`));
51780
52156
  signal.addEventListener("abort", onAbort, { once: true });
51781
- work.then(resolve47, reject).finally(() => signal.removeEventListener("abort", onAbort));
52157
+ work.then(resolve48, reject).finally(() => signal.removeEventListener("abort", onAbort));
51782
52158
  });
51783
52159
  }
51784
- async function pinAddress(url, resolve47 = resolveAll, signal) {
52160
+ async function pinAddress(url, resolve48 = resolveAll, signal) {
51785
52161
  const host = url.hostname.replace(/^\[|\]$/g, "");
51786
52162
  if (ipv4Octets(host)) {
51787
52163
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
@@ -51791,7 +52167,7 @@ async function pinAddress(url, resolve47 = resolveAll, signal) {
51791
52167
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
51792
52168
  return { address: host, family: 6 };
51793
52169
  }
51794
- const addresses = await withAbort(() => resolve47(host), signal, `${host} lookup`);
52170
+ const addresses = await withAbort(() => resolve48(host), signal, `${host} lookup`);
51795
52171
  if (!addresses.length) throw new Error(`${host} resolved to no address`);
51796
52172
  const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
51797
52173
  if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
@@ -51831,7 +52207,7 @@ function copyIncomingHeaders(headers2) {
51831
52207
  return out;
51832
52208
  }
51833
52209
  function requestOnce(url, pinned, init) {
51834
- return new Promise((resolve47, reject) => {
52210
+ return new Promise((resolve48, reject) => {
51835
52211
  const headers2 = { host: url.host, "accept-encoding": "identity" };
51836
52212
  new Headers(init.headers ?? {}).forEach((value, key2) => {
51837
52213
  if (key2.toLowerCase() !== "host") headers2[key2] = value;
@@ -51861,7 +52237,7 @@ function requestOnce(url, pinned, init) {
51861
52237
  reject(err);
51862
52238
  return;
51863
52239
  }
51864
- resolve47(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out }));
52240
+ resolve48(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out }));
51865
52241
  }
51866
52242
  );
51867
52243
  req.on("error", reject);
@@ -52665,7 +53041,7 @@ var init_brand_font = __esm({
52665
53041
 
52666
53042
  // src/site-analyze/write-artifacts.ts
52667
53043
  import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync25 } from "node:fs";
52668
- import { join as join53 } from "node:path";
53044
+ import { join as join54 } from "node:path";
52669
53045
  function attachVeloSources(book, sources, put) {
52670
53046
  const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
52671
53047
  for (const f of book.velo.files) {
@@ -52820,12 +53196,12 @@ async function downloadMedia(book, fetchImpl, put) {
52820
53196
  }
52821
53197
  async function writeBusinessBook(result, opts) {
52822
53198
  const out = opts.outDir;
52823
- mkdirSync28(join53(out, "evidence/pages"), { recursive: true });
52824
- mkdirSync28(join53(out, "media/catalog"), { recursive: true });
53199
+ mkdirSync28(join54(out, "evidence/pages"), { recursive: true });
53200
+ mkdirSync28(join54(out, "media/catalog"), { recursive: true });
52825
53201
  const files = [];
52826
53202
  const put = (rel, body) => {
52827
- const p = join53(out, rel);
52828
- mkdirSync28(join53(p, ".."), { recursive: true });
53203
+ const p = join54(out, rel);
53204
+ mkdirSync28(join54(p, ".."), { recursive: true });
52829
53205
  writeFileSync25(p, body);
52830
53206
  files.push(rel);
52831
53207
  };
@@ -52919,15 +53295,15 @@ var init_customer_build = __esm({
52919
53295
  });
52920
53296
 
52921
53297
  // src/site-analyze/apply.ts
52922
- import { existsSync as existsSync57, readFileSync as readFileSync67, writeFileSync as writeFileSync26, copyFileSync as copyFileSync3, mkdirSync as mkdirSync29, realpathSync as realpathSync6, statSync as statSync15 } from "node:fs";
52923
- import { dirname as dirname31, isAbsolute as isAbsolute4, join as join54, resolve as resolve44, sep as sep13 } from "node:path";
53298
+ import { existsSync as existsSync58, readFileSync as readFileSync68, writeFileSync as writeFileSync26, copyFileSync as copyFileSync3, mkdirSync as mkdirSync29, realpathSync as realpathSync7, statSync as statSync16 } from "node:fs";
53299
+ import { dirname as dirname31, isAbsolute as isAbsolute4, join as join55, resolve as resolve45, sep as sep14 } from "node:path";
52924
53300
  import { spawnSync as spawnSync4 } from "node:child_process";
52925
53301
  function unpairedRedirectNote(overlay) {
52926
53302
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
52927
53303
  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)`;
52928
53304
  }
52929
53305
  function posix2(p) {
52930
- return resolve44(p).replace(/\\/g, "/");
53306
+ return resolve45(p).replace(/\\/g, "/");
52931
53307
  }
52932
53308
  function committedShellProvisioning(path2) {
52933
53309
  return committedShellFor(posix2(path2));
@@ -52935,7 +53311,7 @@ function committedShellProvisioning(path2) {
52935
53311
  function findRepoRoot(cwd) {
52936
53312
  let dir = cwd;
52937
53313
  for (let i = 0; i < 8; i++) {
52938
- if (SHELL_NAMES2.some((name) => existsSync57(join54(dir, shellAppDir(name), "package.json")))) return dir;
53314
+ if (SHELL_NAMES2.some((name) => existsSync58(join55(dir, shellAppDir(name), "package.json")))) return dir;
52939
53315
  const next = dirname31(dir);
52940
53316
  if (next === dir) break;
52941
53317
  dir = next;
@@ -52961,7 +53337,7 @@ function assertNotCommitted(path2, forbidden) {
52961
53337
  `refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
52962
53338
  );
52963
53339
  }
52964
- if (forbidden && resolve44(path2) === resolve44(forbidden)) {
53340
+ if (forbidden && resolve45(path2) === resolve45(forbidden)) {
52965
53341
  const named = committedShellProvisioning(forbidden);
52966
53342
  throw new Error(
52967
53343
  `refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
@@ -53003,35 +53379,35 @@ function mergeCustomerOwned(committed, overlay) {
53003
53379
  }
53004
53380
  function buildMergedContract(options) {
53005
53381
  const { appDir: appDir2, packageDir, overlay } = options;
53006
- const committedPath = join54(appDir2, "provisioning.json");
53007
- if (!existsSync57(committedPath)) {
53382
+ const committedPath = join55(appDir2, "provisioning.json");
53383
+ if (!existsSync58(committedPath)) {
53008
53384
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
53009
53385
  }
53010
- const committed = JSON.parse(readFileSync67(committedPath, "utf8"));
53386
+ const committed = JSON.parse(readFileSync68(committedPath, "utf8"));
53011
53387
  const merged = mergeCustomerOwned(committed, overlay);
53012
53388
  const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
53013
53389
  const branding = merged.branding ?? {};
53014
53390
  const staged = [];
53015
53391
  const contained = (root, rel) => {
53016
53392
  if (isAbsolute4(rel)) return void 0;
53017
- const full = resolve44(root, rel);
53018
- return full.startsWith(resolve44(root) + sep13) ? full : void 0;
53393
+ const full = resolve45(root, rel);
53394
+ return full.startsWith(resolve45(root) + sep14) ? full : void 0;
53019
53395
  };
53020
53396
  const stage = (fromRel, toRel) => {
53021
53397
  const from = contained(packageDir, fromRel);
53022
- const to = contained(join54(appDir2, STAGED), toRel.slice(STAGED.length + 1));
53023
- if (!from || !to || !existsSync57(from)) return void 0;
53398
+ const to = contained(join55(appDir2, STAGED), toRel.slice(STAGED.length + 1));
53399
+ if (!from || !to || !existsSync58(from)) return void 0;
53024
53400
  let real;
53025
53401
  let realRoot;
53026
53402
  try {
53027
- real = realpathSync6(from);
53028
- realRoot = realpathSync6(packageDir);
53403
+ real = realpathSync7(from);
53404
+ realRoot = realpathSync7(packageDir);
53029
53405
  } catch {
53030
53406
  return void 0;
53031
53407
  }
53032
- if (!real.startsWith(realRoot + sep13)) return void 0;
53408
+ if (!real.startsWith(realRoot + sep14)) return void 0;
53033
53409
  try {
53034
- if (!statSync15(real).isFile()) return void 0;
53410
+ if (!statSync16(real).isFile()) return void 0;
53035
53411
  mkdirSync29(dirname31(to), { recursive: true });
53036
53412
  copyFileSync3(real, to);
53037
53413
  } catch {
@@ -53042,11 +53418,11 @@ function buildMergedContract(options) {
53042
53418
  };
53043
53419
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
53044
53420
  if (icon) branding.appIconPath = icon;
53045
- const facesPath = join54(packageDir, "media/fonts/faces.json");
53046
- if (existsSync57(facesPath)) {
53421
+ const facesPath = join55(packageDir, "media/fonts/faces.json");
53422
+ if (existsSync58(facesPath)) {
53047
53423
  let faces = [];
53048
53424
  try {
53049
- const parsed = JSON.parse(readFileSync67(facesPath, "utf8"));
53425
+ const parsed = JSON.parse(readFileSync68(facesPath, "utf8"));
53050
53426
  faces = Array.isArray(parsed) ? parsed : [];
53051
53427
  } catch {
53052
53428
  faces = [];
@@ -53067,20 +53443,20 @@ function buildMergedContract(options) {
53067
53443
  merged.branding = branding;
53068
53444
  const body = `${JSON.stringify(merged, null, 2)}
53069
53445
  `;
53070
- const path2 = join54(packageDir, "provisioning.contract.json");
53446
+ const path2 = join55(packageDir, "provisioning.contract.json");
53071
53447
  writeFileSync26(path2, body);
53072
- const localPath = join54(appDir2, LOCAL_CONTRACT_REL);
53448
+ const localPath = join55(appDir2, LOCAL_CONTRACT_REL);
53073
53449
  mkdirSync29(dirname31(localPath), { recursive: true });
53074
53450
  writeFileSync26(localPath, body);
53075
53451
  staged.push(localPath);
53076
53452
  return { path: path2, staged };
53077
53453
  }
53078
53454
  async function applyOverlays(input) {
53079
- const cwd = resolve44(input.cwd);
53455
+ const cwd = resolve45(input.cwd);
53080
53456
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
53081
53457
  assertKnownShell(shell);
53082
- const overlay = JSON.parse(readFileSync67(input.overlayPath, "utf8"));
53083
- const tokens = JSON.parse(readFileSync67(input.tokensPath, "utf8"));
53458
+ const overlay = JSON.parse(readFileSync68(input.overlayPath, "utf8"));
53459
+ const tokens = JSON.parse(readFileSync68(input.tokensPath, "utf8"));
53084
53460
  const wrote = [];
53085
53461
  const notes = [];
53086
53462
  const repoRoot2 = findRepoRoot(cwd);
@@ -53090,8 +53466,8 @@ async function applyOverlays(input) {
53090
53466
  `shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
53091
53467
  );
53092
53468
  }
53093
- const appDir2 = join54(repoRoot2, shellAppDir(shell));
53094
- const packageDir = dirname31(resolve44(input.overlayPath));
53469
+ const appDir2 = join55(repoRoot2, shellAppDir(shell));
53470
+ const packageDir = dirname31(resolve45(input.overlayPath));
53095
53471
  const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
53096
53472
  wrote.push(...staged);
53097
53473
  const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -53112,10 +53488,10 @@ async function applyOverlays(input) {
53112
53488
  note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
53113
53489
  };
53114
53490
  }
53115
- const pkgProv = join54(cwd, "provisioning.json");
53491
+ const pkgProv = join55(cwd, "provisioning.json");
53116
53492
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
53117
- if (existsSync57(pkgProv)) {
53118
- const cur = JSON.parse(readFileSync67(pkgProv, "utf8"));
53493
+ if (existsSync58(pkgProv)) {
53494
+ const cur = JSON.parse(readFileSync68(pkgProv, "utf8"));
53119
53495
  const merged = deepMerge4(cur, overlay);
53120
53496
  writeFileSync26(pkgProv, JSON.stringify(merged, null, 2) + "\n");
53121
53497
  wrote.push(pkgProv);
@@ -53123,9 +53499,9 @@ async function applyOverlays(input) {
53123
53499
  writeFileSync26(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
53124
53500
  wrote.push(pkgProv);
53125
53501
  }
53126
- const pkgTokens = join54(cwd, "tokens.json");
53127
- if (existsSync57(pkgTokens) && (tokens.colors || tokens.typography)) {
53128
- const cur = JSON.parse(readFileSync67(pkgTokens, "utf8"));
53502
+ const pkgTokens = join55(cwd, "tokens.json");
53503
+ if (existsSync58(pkgTokens) && (tokens.colors || tokens.typography)) {
53504
+ const cur = JSON.parse(readFileSync68(pkgTokens, "utf8"));
53129
53505
  const merged = deepMerge4(cur, tokens);
53130
53506
  const mergedColors = merged.colors;
53131
53507
  if (mergedColors && typeof mergedColors === "object" && !Array.isArray(mergedColors)) {
@@ -53144,9 +53520,9 @@ async function applyOverlays(input) {
53144
53520
  wrote.push(pkgTokens);
53145
53521
  }
53146
53522
  const homeAction = homeRefreshActionId(shell);
53147
- const homeSrc = join54(cwd, "dev/index.ts");
53148
- if (homeAction && existsSync57(homeSrc)) {
53149
- const prev = readFileSync67(homeSrc, "utf8");
53523
+ const homeSrc = join55(cwd, "dev/index.ts");
53524
+ if (homeAction && existsSync58(homeSrc)) {
53525
+ const prev = readFileSync68(homeSrc, "utf8");
53150
53526
  const patched = patchBrandParams(prev, overlay, homeAction);
53151
53527
  let next = patched.src;
53152
53528
  if (!patched.foreign && overlay.installedVerticals?.length) {
@@ -53169,13 +53545,13 @@ async function applyOverlays(input) {
53169
53545
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
53170
53546
  }
53171
53547
  }
53172
- if (!input.iconPath || !existsSync57(input.iconPath)) {
53173
- const book = input.iconPath ? dirname31(dirname31(resolve44(input.iconPath))) : void 0;
53548
+ if (!input.iconPath || !existsSync58(input.iconPath)) {
53549
+ const book = input.iconPath ? dirname31(dirname31(resolve45(input.iconPath))) : void 0;
53174
53550
  notes.push(
53175
53551
  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"
53176
53552
  );
53177
53553
  }
53178
- if (input.iconPath && existsSync57(input.iconPath)) {
53554
+ if (input.iconPath && existsSync58(input.iconPath)) {
53179
53555
  try {
53180
53556
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
53181
53557
  wrote.push(...installed.wrote);
@@ -54113,10 +54489,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
54113
54489
  }
54114
54490
  function createPromiseCallback(cb) {
54115
54491
  let callback;
54116
- let resolve47;
54492
+ let resolve48;
54117
54493
  let reject;
54118
54494
  const promise = new Promise((_resolve, _reject) => {
54119
- resolve47 = _resolve;
54495
+ resolve48 = _resolve;
54120
54496
  reject = _reject;
54121
54497
  });
54122
54498
  if (typeof cb === "function") {
@@ -54132,7 +54508,7 @@ function createPromiseCallback(cb) {
54132
54508
  callback = (err, result) => {
54133
54509
  try {
54134
54510
  if (err) reject(err);
54135
- else resolve47(result);
54511
+ else resolve48(result);
54136
54512
  } catch (e) {
54137
54513
  reject(e instanceof Error ? e : new Error());
54138
54514
  }
@@ -56704,7 +57080,7 @@ var init_crawl_look = __esm({
56704
57080
  });
56705
57081
 
56706
57082
  // src/site-analyze/site-function.ts
56707
- import { randomUUID as randomUUID2 } from "node:crypto";
57083
+ import { randomUUID as randomUUID4 } from "node:crypto";
56708
57084
  function createRevisionUrl(msid, esi) {
56709
57085
  const q = new URLSearchParams({ editorSessionId: esi, esi, metaSiteId: msid });
56710
57086
  return `https://editor.wix.com/html/v1/create_revision?${q}`;
@@ -57149,7 +57525,7 @@ function codeAppIdFromRevision(json5) {
57149
57525
  async function snapshotAndPublish(fetchImpl, token, msid, opts = {}) {
57150
57526
  const production = opts.production !== false;
57151
57527
  const initiator = opts.initiator ?? "himi";
57152
- const esi = randomUUID2();
57528
+ const esi = randomUUID4();
57153
57529
  const rev = await veloCall(fetchImpl, "POST", createRevisionUrl(msid, esi), {
57154
57530
  token,
57155
57531
  msid,
@@ -57330,8 +57706,8 @@ __export(cli_exports, {
57330
57706
  runSiteAnalyze: () => runSiteAnalyze,
57331
57707
  runSiteFunctionCli: () => runSiteFunctionCli
57332
57708
  });
57333
- import { readFileSync as readFileSync68 } from "node:fs";
57334
- import { resolve as resolve45 } from "node:path";
57709
+ import { readFileSync as readFileSync69 } from "node:fs";
57710
+ import { resolve as resolve46 } from "node:path";
57335
57711
  function assetFetchFor(_opts) {
57336
57712
  return pinnedFetch2;
57337
57713
  }
@@ -57340,7 +57716,7 @@ async function runSiteAnalyze(opts) {
57340
57716
  const assetFetch = assetFetchFor(opts);
57341
57717
  const siteFetch = guardedSiteFetch;
57342
57718
  const cwd = opts.cwd ?? process.cwd();
57343
- const outDir = resolve45(cwd, opts.outDir ?? ".himi/business-book");
57719
+ const outDir = resolve46(cwd, opts.outDir ?? ".himi/business-book");
57344
57720
  let ownerAuth;
57345
57721
  let msid;
57346
57722
  try {
@@ -57378,9 +57754,9 @@ async function runSiteAnalyze(opts) {
57378
57754
  if (opts.apply) {
57379
57755
  applied = await applyOverlays({
57380
57756
  cwd,
57381
- overlayPath: resolve45(outDir, "provisioning.overlay.json"),
57382
- tokensPath: resolve45(outDir, "tokens.overlay.json"),
57383
- iconPath: resolve45(outDir, "media/icon.png"),
57757
+ overlayPath: resolve46(outDir, "provisioning.overlay.json"),
57758
+ tokensPath: resolve46(outDir, "tokens.overlay.json"),
57759
+ iconPath: resolve46(outDir, "media/icon.png"),
57384
57760
  shell: opts.shell
57385
57761
  });
57386
57762
  const note = noteWithWarnings(applied.note, warnings);
@@ -57416,8 +57792,8 @@ async function runSiteFunctionCli(opts) {
57416
57792
  const token = opts.token ?? await siteToken(msid);
57417
57793
  let source;
57418
57794
  if (opts.sourcePath) {
57419
- const p = resolve45(opts.cwd ?? process.cwd(), opts.sourcePath);
57420
- source = readFileSync68(p, "utf8");
57795
+ const p = resolve46(opts.cwd ?? process.cwd(), opts.sourcePath);
57796
+ source = readFileSync69(p, "utf8");
57421
57797
  }
57422
57798
  let body;
57423
57799
  if (opts.bodyRaw != null) {
@@ -57468,7 +57844,7 @@ async function accountToken2(spawnImpl = spawn5) {
57468
57844
  cached2 = fromEnv;
57469
57845
  return fromEnv;
57470
57846
  }
57471
- const token = await new Promise((resolve47, reject) => {
57847
+ const token = await new Promise((resolve48, reject) => {
57472
57848
  let child;
57473
57849
  try {
57474
57850
  child = spawnImpl("wix", ["token"]);
@@ -57497,7 +57873,7 @@ async function accountToken2(spawnImpl = spawn5) {
57497
57873
  const scan = (d) => {
57498
57874
  out += String(d);
57499
57875
  const m = out.match(TOKEN_RE2);
57500
- if (m) done(() => resolve47(m[0]));
57876
+ if (m) done(() => resolve48(m[0]));
57501
57877
  };
57502
57878
  child.stdout?.on("data", scan);
57503
57879
  child.stderr?.on("data", scan);
@@ -57674,7 +58050,7 @@ __export(site_create_exports, {
57674
58050
  runSiteList: () => runSiteList,
57675
58051
  writeProvisioningBinding: () => writeProvisioningBinding
57676
58052
  });
57677
- import { existsSync as existsSync58, readFileSync as readFileSync69, writeFileSync as writeFileSync27 } from "node:fs";
58053
+ import { existsSync as existsSync59, readFileSync as readFileSync70, writeFileSync as writeFileSync27 } from "node:fs";
57678
58054
  import { resolve as resolvePath2 } from "node:path";
57679
58055
  function oauthClientName(projectName) {
57680
58056
  return `${projectName} client`;
@@ -57823,7 +58199,7 @@ async function runSiteCreate(opts) {
57823
58199
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
57824
58200
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
57825
58201
  }
57826
- function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync58, readFileSync: readFileSync69, writeFileSync: writeFileSync27 }) {
58202
+ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync59, readFileSync: readFileSync70, writeFileSync: writeFileSync27 }) {
57827
58203
  const msid = binding2.siteId;
57828
58204
  const path2 = resolvePath2(target);
57829
58205
  const committed = committedShellProvisioning(path2);
@@ -58496,11 +58872,11 @@ var init_context = __esm({
58496
58872
  });
58497
58873
 
58498
58874
  // src/cli.ts
58499
- import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync70, mkdirSync as mkdirSync30, writeFileSync as writeFileSync28, existsSync as existsSync59, rmSync as rmSync11, readdirSync as readdirSync27, statSync as statSync16, lstatSync as lstatSync6, accessSync, constants } from "node:fs";
58875
+ import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync71, mkdirSync as mkdirSync30, writeFileSync as writeFileSync28, existsSync as existsSync60, rmSync as rmSync13, readdirSync as readdirSync27, statSync as statSync17, lstatSync as lstatSync8, accessSync, constants as constants2, renameSync as renameSync6, cpSync as cpSync3 } from "node:fs";
58500
58876
  import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn6 } from "node:child_process";
58501
- import { createHash as createHash26, randomUUID as randomUUID3 } from "node:crypto";
58877
+ import { createHash as createHash26, randomUUID as randomUUID5 } from "node:crypto";
58502
58878
  import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
58503
- import { join as join55, resolve as resolve46, relative as relative10, basename as basename13, dirname as dirname32 } from "node:path";
58879
+ import { join as join56, resolve as resolve47, relative as relative10, basename as basename13, dirname as dirname32 } from "node:path";
58504
58880
  import { fileURLToPath as fileURLToPath24 } from "node:url";
58505
58881
 
58506
58882
  // ../serve-cli/src/client.ts
@@ -60209,7 +60585,7 @@ async function browserLogin(opts) {
60209
60585
  const log = opts.log ?? (() => {
60210
60586
  });
60211
60587
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
60212
- return await new Promise((resolve47, reject) => {
60588
+ return await new Promise((resolve48, reject) => {
60213
60589
  let settled = false;
60214
60590
  let loginUrl = "";
60215
60591
  const server = createServer();
@@ -60273,7 +60649,7 @@ async function browserLogin(opts) {
60273
60649
  return;
60274
60650
  }
60275
60651
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
60276
- finish2(() => resolve47({ token, loginUrl }));
60652
+ finish2(() => resolve48({ token, loginUrl }));
60277
60653
  });
60278
60654
  });
60279
60655
  server.on("error", (err) => finish2(() => reject(err)));
@@ -61776,8 +62152,8 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
61776
62152
  var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
61777
62153
  function embeddedTemplateCatalog() {
61778
62154
  return availableTemplates().map((name) => {
61779
- const path2 = join55(templateSourceDir(name), TEMPLATE_META_FILE);
61780
- const meta = JSON.parse(readFileSync70(path2, "utf8"));
62155
+ const path2 = join56(templateSourceDir(name), TEMPLATE_META_FILE);
62156
+ const meta = JSON.parse(readFileSync71(path2, "utf8"));
61781
62157
  if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
61782
62158
  throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
61783
62159
  }
@@ -62059,11 +62435,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
62059
62435
  file is not the plane's per-release archive.
62060
62436
  himi share --file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>
62061
62437
  publish a content-addressed package link for a released app
62062
- himi run [<package.himi|dir|url>] [--browser] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open]
62438
+ himi run [<package.himi|dir|url>] [--browser] [--watch] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open]
62063
62439
  serve a package on localhost + open it in a browser. No serve
62064
62440
  plane, no dev-server. With no argument it packs the current
62065
62441
  content package first \u2014 edit, run, look at it.
62066
- Blocks until Ctrl-C.
62442
+ --watch rebuilds on every save and repaints the open tab
62443
+ (a failed build keeps the last good preview). Blocks until Ctrl-C.
62067
62444
  himi flags list|set|ramp|rm [<key>] [--app <a>]
62068
62445
  read/change operational flags (RFC 0013); writes report
62069
62446
  servedNow from the device door, never just ok
@@ -62406,7 +62783,7 @@ var COMMANDS = [
62406
62783
  { name: "import", summary: "turn a `himi pack --dev` package back into an EDITABLE content package \u2014 the file counterpart of `himi pull`, needing no serve plane, no account and no network. Refuses an invalid package before trusting its source (the content hash is recomputed over every entry on open, so the archive is provably the one that was packed), and refuses a RELEASE package by naming the absence \u2014 it carries built output and no source \u2014 rather than reporting a missing file. `--name` re-substitutes the app identity through the same machinery `himi init --template` and `himi pull --name` use, 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 needs `--force` and a merge NAMES what it kept (`left: [...]`), the same contract `himi pull --force` has; a shape clash is refused whole before anything is written. There is no `--replace`: a file you were handed is not the plane's per-release archive.", required: "<package.himi> [--out <dir>] [--name <new>] [--force]" },
62407
62784
  { 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>]" },
62408
62785
  { 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>" },
62409
- { 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.", required: "[<package.himi|dir|url>] [--browser] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
62786
+ { 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. --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. It also frames itself on the build board (`himi studio`) and serves the board at /__himi/studio/ on the same origin.", required: "[<package.himi|dir|url>] [--browser] [--watch] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
62410
62787
  { 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]" },
62411
62788
  { 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]" },
62412
62789
  { 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]" },
@@ -62438,7 +62815,7 @@ var COMMANDS = [
62438
62815
  ];
62439
62816
  function cliVersion() {
62440
62817
  try {
62441
- return JSON.parse(readFileSync70(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
62818
+ return JSON.parse(readFileSync71(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
62442
62819
  } catch {
62443
62820
  return "unknown";
62444
62821
  }
@@ -62489,16 +62866,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
62489
62866
  }
62490
62867
  var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
62491
62868
  function execNpmConfig(file, args, options) {
62492
- return new Promise((resolve47, reject) => {
62493
- execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve47(String(stdout)));
62869
+ return new Promise((resolve48, reject) => {
62870
+ execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve48(String(stdout)));
62494
62871
  });
62495
62872
  }
62496
62873
  var npmScopedWixRegistry = createScopedRegistryResolver();
62497
62874
  async function scopedRegistryBefore(lookup2, deadline) {
62498
62875
  let cancel = () => {
62499
62876
  };
62500
- const expired = new Promise((resolve47) => {
62501
- const timer = setTimeout(() => resolve47(void 0), Math.max(0, deadline - Date.now()));
62877
+ const expired = new Promise((resolve48) => {
62878
+ const timer = setTimeout(() => resolve48(void 0), Math.max(0, deadline - Date.now()));
62502
62879
  cancel = () => clearTimeout(timer);
62503
62880
  });
62504
62881
  try {
@@ -62556,16 +62933,16 @@ function ageInDays(publishedAt, now = Date.now()) {
62556
62933
  }
62557
62934
  function packageVersion(path2) {
62558
62935
  try {
62559
- const version2 = JSON.parse(readFileSync70(path2, "utf8")).version;
62936
+ const version2 = JSON.parse(readFileSync71(path2, "utf8")).version;
62560
62937
  return typeof version2 === "string" && version2 ? version2 : void 0;
62561
62938
  } catch {
62562
62939
  return void 0;
62563
62940
  }
62564
62941
  }
62565
62942
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
62566
- let dir = resolve46(fromDir);
62943
+ let dir = resolve47(fromDir);
62567
62944
  for (; ; ) {
62568
- const version2 = packageVersion(join55(dir, "node_modules", "@wix", "himalaya", "package.json"));
62945
+ const version2 = packageVersion(join56(dir, "node_modules", "@wix", "himalaya", "package.json"));
62569
62946
  if (version2) return { version: version2, source: "local" };
62570
62947
  const parent = dirname32(dir);
62571
62948
  if (parent === dir) break;
@@ -62575,7 +62952,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
62575
62952
  if (bundled) return { version: bundled, source: "bundled" };
62576
62953
  try {
62577
62954
  const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
62578
- const version2 = root ? packageVersion(join55(root, "@wix", "himalaya", "package.json")) : void 0;
62955
+ const version2 = root ? packageVersion(join56(root, "@wix", "himalaya", "package.json")) : void 0;
62579
62956
  return version2 ? { version: version2, source: "global" } : {};
62580
62957
  } catch {
62581
62958
  return {};
@@ -62622,11 +62999,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
62622
62999
  var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
62623
63000
  var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
62624
63001
  function updateCachePath(env = process.env) {
62625
- return env.HIMI_UPDATE_CACHE_FILE ?? join55(homedir7(), ".himalaya", "update-check.json");
63002
+ return env.HIMI_UPDATE_CACHE_FILE ?? join56(homedir7(), ".himalaya", "update-check.json");
62626
63003
  }
62627
63004
  function readUpdateCache(path2) {
62628
63005
  try {
62629
- const parsed = JSON.parse(readFileSync70(path2, "utf8"));
63006
+ const parsed = JSON.parse(readFileSync71(path2, "utf8"));
62630
63007
  return parsed && typeof parsed === "object" ? parsed : {};
62631
63008
  } catch {
62632
63009
  return {};
@@ -62665,7 +63042,7 @@ function globalPrefixWritable() {
62665
63042
  const root = globalNodeModulesRoot();
62666
63043
  if (!root) return false;
62667
63044
  try {
62668
- accessSync(root, constants.W_OK);
63045
+ accessSync(root, constants2.W_OK);
62669
63046
  return true;
62670
63047
  } catch {
62671
63048
  return false;
@@ -62694,12 +63071,12 @@ function createUpdateRunner(spawn7 = spawnSync5) {
62694
63071
  },
62695
63072
  installedVersion: () => {
62696
63073
  const root = globalNodeModulesRoot();
62697
- return root ? packageVersion(join55(root, "@wix", "himalaya-cli", "package.json")) : void 0;
63074
+ return root ? packageVersion(join56(root, "@wix", "himalaya-cli", "package.json")) : void 0;
62698
63075
  },
62699
63076
  reexec: (argv) => {
62700
63077
  const root = globalNodeModulesRoot();
62701
- const entry = root ? join55(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
62702
- if (!entry || !existsSync59(entry)) return void 0;
63078
+ const entry = root ? join56(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
63079
+ if (!entry || !existsSync60(entry)) return void 0;
62703
63080
  const result = spawnSync5(process.execPath, [entry, ...argv], {
62704
63081
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
62705
63082
  stdio: "inherit",
@@ -62727,7 +63104,7 @@ function thisHost() {
62727
63104
  return hostname().replace(/\s+/g, "_");
62728
63105
  }
62729
63106
  function lockStamp(now) {
62730
- return `${now} ${process.pid} ${thisHost()} ${randomUUID3()}`;
63107
+ return `${now} ${process.pid} ${thisHost()} ${randomUUID5()}`;
62731
63108
  }
62732
63109
  function processAlive(pid) {
62733
63110
  try {
@@ -62746,7 +63123,7 @@ function staleUpdateLockFile(cachePath, now) {
62746
63123
  for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
62747
63124
  let content;
62748
63125
  try {
62749
- content = readFileSync70(path2, "utf8");
63126
+ content = readFileSync71(path2, "utf8");
62750
63127
  } catch {
62751
63128
  continue;
62752
63129
  }
@@ -62754,7 +63131,7 @@ function staleUpdateLockFile(cachePath, now) {
62754
63131
  let since = stamped;
62755
63132
  if (!Number.isFinite(since)) {
62756
63133
  try {
62757
- since = statSync16(path2).mtimeMs;
63134
+ since = statSync17(path2).mtimeMs;
62758
63135
  } catch {
62759
63136
  continue;
62760
63137
  }
@@ -62769,7 +63146,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
62769
63146
  const mine = lockStamp(now);
62770
63147
  const readLock = (path2) => {
62771
63148
  try {
62772
- return readFileSync70(path2, "utf8");
63149
+ return readFileSync71(path2, "utf8");
62773
63150
  } catch {
62774
63151
  return void 0;
62775
63152
  }
@@ -62784,7 +63161,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
62784
63161
  };
62785
63162
  const removeIfMine = (path2) => {
62786
63163
  try {
62787
- if (readLock(path2) === mine) rmSync11(path2, { force: true });
63164
+ if (readLock(path2) === mine) rmSync13(path2, { force: true });
62788
63165
  } catch {
62789
63166
  }
62790
63167
  };
@@ -62807,7 +63184,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
62807
63184
  hooks.underBreakLock?.();
62808
63185
  if (current === void 0) return tryCreate(lockPath) ? release : void 0;
62809
63186
  if (!isAbandoned(current)) return void 0;
62810
- rmSync11(lockPath, { force: true });
63187
+ rmSync13(lockPath, { force: true });
62811
63188
  return tryCreate(lockPath) ? release : void 0;
62812
63189
  } finally {
62813
63190
  removeIfMine(breakPath);
@@ -63307,10 +63684,10 @@ function executableOnPath(name, env = process.env) {
63307
63684
  const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
63308
63685
  for (const dir of entries) {
63309
63686
  for (const suffix of suffixes) {
63310
- const candidate = join55(dir, `${name}${suffix}`);
63687
+ const candidate = join56(dir, `${name}${suffix}`);
63311
63688
  try {
63312
- if (!statSync16(candidate).isFile()) continue;
63313
- if (process.platform !== "win32") accessSync(candidate, constants.X_OK);
63689
+ if (!statSync17(candidate).isFile()) continue;
63690
+ if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
63314
63691
  return true;
63315
63692
  } catch {
63316
63693
  }
@@ -63416,7 +63793,7 @@ async function nativeConfigAdvisories(app, configSource) {
63416
63793
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
63417
63794
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
63418
63795
  const iosYmlPath = iosProjectYml2(app);
63419
- const iosYml = existsSync59(iosYmlPath) ? readFileSync70(iosYmlPath, "utf8") : "";
63796
+ const iosYml = existsSync60(iosYmlPath) ? readFileSync71(iosYmlPath, "utf8") : "";
63420
63797
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
63421
63798
  if (!optedIn) {
63422
63799
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -63430,7 +63807,7 @@ async function nativeConfigAdvisories(app, configSource) {
63430
63807
  }
63431
63808
  function readConfigSource(dir) {
63432
63809
  try {
63433
- return readFileSync70(join55(dir, "config.ts"), "utf8");
63810
+ return readFileSync71(join56(dir, "config.ts"), "utf8");
63434
63811
  } catch {
63435
63812
  return null;
63436
63813
  }
@@ -63441,8 +63818,8 @@ function writePngFile(path2, base64) {
63441
63818
  return path2;
63442
63819
  }
63443
63820
  async function initFromRemoteTemplate(name, parentDir, template, c) {
63444
- const dir = resolve46(parentDir, name);
63445
- if (existsSync59(join55(dir, "himalaya.content.json"))) {
63821
+ const dir = resolve47(parentDir, name);
63822
+ if (existsSync60(join56(dir, "himalaya.content.json"))) {
63446
63823
  throw new Error(`content package already exists at ${dir}`);
63447
63824
  }
63448
63825
  const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -63454,7 +63831,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
63454
63831
  return finishScaffold(materializeSource(archive.files, name, dir), template);
63455
63832
  }
63456
63833
  function contentDir(flags) {
63457
- return resolve46(str5(flags.content) ?? process.cwd());
63834
+ return resolve47(str5(flags.content) ?? process.cwd());
63458
63835
  }
63459
63836
  function renameRestoredSource(restored, declaredApp, renamed) {
63460
63837
  const text5 = {};
@@ -63472,7 +63849,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
63472
63849
  function symlinkDestinationIssue(dest) {
63473
63850
  let kind;
63474
63851
  try {
63475
- kind = lstatSync6(dest);
63852
+ kind = lstatSync8(dest);
63476
63853
  } catch {
63477
63854
  return null;
63478
63855
  }
@@ -63485,8 +63862,8 @@ function symlinkDestinationIssue(dest) {
63485
63862
  function restoreDestinationIssue(dest, force) {
63486
63863
  const link = symlinkDestinationIssue(dest);
63487
63864
  if (link) return link;
63488
- if (!existsSync59(dest)) return null;
63489
- if (!statSync16(dest).isDirectory()) {
63865
+ if (!existsSync60(dest)) return null;
63866
+ if (!statSync17(dest).isDirectory()) {
63490
63867
  return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
63491
63868
  }
63492
63869
  if (readdirSync27(dest).length > 0 && !force) {
@@ -63498,9 +63875,9 @@ function restoreDestinationIssue(dest, force) {
63498
63875
  return null;
63499
63876
  }
63500
63877
  function isHimalayaMonorepoCheckout(start) {
63501
- let dir = resolve46(start);
63878
+ let dir = resolve47(start);
63502
63879
  for (; ; ) {
63503
- if (existsSync59(join55(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync59(join55(dir, "core", "serve", "src", "server.ts"))) return true;
63880
+ if (existsSync60(join56(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync60(join56(dir, "core", "serve", "src", "server.ts"))) return true;
63504
63881
  const parent = dirname32(dir);
63505
63882
  if (parent === dir) return false;
63506
63883
  dir = parent;
@@ -63542,8 +63919,8 @@ function materializeForPreview(appDir2, slug, displayName) {
63542
63919
  const forBuild = Object.fromEntries(
63543
63920
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
63544
63921
  );
63545
- const repoRoot2 = resolve46(fileURLToPath24(new URL("../../..", import.meta.url)));
63546
- const root = join55(repoRoot2, "node_modules", ".cache", "himi-template-preview");
63922
+ const repoRoot2 = resolve47(fileURLToPath24(new URL("../../..", import.meta.url)));
63923
+ const root = join56(repoRoot2, "node_modules", ".cache", "himi-template-preview");
63547
63924
  const stillRunning = (pid) => {
63548
63925
  try {
63549
63926
  process.kill(pid, 0);
@@ -63557,21 +63934,21 @@ function materializeForPreview(appDir2, slug, displayName) {
63557
63934
  if (!entry.isDirectory()) continue;
63558
63935
  const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
63559
63936
  if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
63560
- rmSync11(join55(root, entry.name), { recursive: true, force: true });
63937
+ rmSync13(join56(root, entry.name), { recursive: true, force: true });
63561
63938
  }
63562
63939
  }
63563
63940
  } catch {
63564
63941
  }
63565
- const dest = join55(root, `${slug}-${process.pid}`);
63566
- rmSync11(dest, { recursive: true, force: true });
63942
+ const dest = join56(root, `${slug}-${process.pid}`);
63943
+ rmSync13(dest, { recursive: true, force: true });
63567
63944
  mkdirSync30(dest, { recursive: true });
63568
63945
  materializeSource(forBuild, displayName, dest, slug);
63569
63946
  return dest;
63570
63947
  }
63571
63948
  async function appId(dir) {
63572
63949
  try {
63573
- const { readFileSync: readFileSync71 } = await import("node:fs");
63574
- const m = JSON.parse(readFileSync71(join55(dir, "himalaya.content.json"), "utf8"));
63950
+ const { readFileSync: readFileSync72 } = await import("node:fs");
63951
+ const m = JSON.parse(readFileSync72(join56(dir, "himalaya.content.json"), "utf8"));
63575
63952
  if (m.name) return m.name;
63576
63953
  } catch {
63577
63954
  }
@@ -63579,8 +63956,8 @@ async function appId(dir) {
63579
63956
  }
63580
63957
  async function contentVisibility(dir) {
63581
63958
  try {
63582
- const { readFileSync: readFileSync71 } = await import("node:fs");
63583
- const m = JSON.parse(readFileSync71(join55(dir, "himalaya.content.json"), "utf8"));
63959
+ const { readFileSync: readFileSync72 } = await import("node:fs");
63960
+ const m = JSON.parse(readFileSync72(join56(dir, "himalaya.content.json"), "utf8"));
63584
63961
  if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
63585
63962
  } catch {
63586
63963
  }
@@ -63782,7 +64159,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
63782
64159
  return 0;
63783
64160
  }
63784
64161
  case "agent-init": {
63785
- const dir = resolve46(str5(flags.dir) ?? process.cwd());
64162
+ const dir = resolve47(str5(flags.dir) ?? process.cwd());
63786
64163
  const res = writeAgentContext(dir);
63787
64164
  print({ ok: true, dir: res.dir, files: res.files, portalUrl: idx.portalUrl });
63788
64165
  return 0;
@@ -63804,7 +64181,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
63804
64181
  try {
63805
64182
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
63806
64183
  const bres = await buildContentForValidation2(dir, { resolution });
63807
- out = mkdtempSync4(join55(tmpdir5(), "himi-ux-record-"));
64184
+ out = mkdtempSync4(join56(tmpdir5(), "himi-ux-record-"));
63808
64185
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
63809
64186
  const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
63810
64187
  const releaseId = outcome.manifest.releaseId;
@@ -63817,7 +64194,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
63817
64194
  return null;
63818
64195
  } finally {
63819
64196
  if (out !== void 0) try {
63820
- rmSync11(out, { recursive: true, force: true });
64197
+ rmSync13(out, { recursive: true, force: true });
63821
64198
  } catch {
63822
64199
  }
63823
64200
  }
@@ -63982,7 +64359,7 @@ async function producedWidgetFamilies(dir) {
63982
64359
  let js;
63983
64360
  for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
63984
64361
  try {
63985
- js = readFileSync70(join55(outDir, candidate), "utf8");
64362
+ js = readFileSync71(join56(outDir, candidate), "utf8");
63986
64363
  break;
63987
64364
  } catch {
63988
64365
  }
@@ -64013,7 +64390,7 @@ async function producedWidgetFamilies(dir) {
64013
64390
  }
64014
64391
  return { families, source: "dist/bundles" };
64015
64392
  }
64016
- var boardOpen = (dir) => existsSync59(join55(dir, ".himi", "studio", "index.html"));
64393
+ var boardOpen = (dir) => existsSync60(join56(dir, ".himi", "studio", "index.html"));
64017
64394
  var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
64018
64395
  async function leaveForBoard(dir, record2, value) {
64019
64396
  if (!boardOpen(dir)) return;
@@ -64280,7 +64657,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64280
64657
  return 2;
64281
64658
  }
64282
64659
  const template = str5(flags.template);
64283
- const parentDir = resolve46(str5(flags.dir) ?? process.cwd());
64660
+ const parentDir = resolve47(str5(flags.dir) ?? process.cwd());
64284
64661
  if (template && flags.remote === true) {
64285
64662
  try {
64286
64663
  const res2 = await initFromRemoteTemplate(name, parentDir, template, client2());
@@ -64397,11 +64774,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64397
64774
  return outcome.code;
64398
64775
  }
64399
64776
  if (sub === "publish") {
64400
- const appDir2 = resolve46(str5(flags.dir) ?? process.cwd());
64401
- const sourceDir = resolve46(str5(flags["source-dir"]) ?? appDir2);
64777
+ const appDir2 = resolve47(str5(flags.dir) ?? process.cwd());
64778
+ const sourceDir = resolve47(str5(flags["source-dir"]) ?? appDir2);
64402
64779
  let meta;
64403
64780
  try {
64404
- meta = JSON.parse(readFileSync70(join55(sourceDir, TEMPLATE_META_FILE), "utf8"));
64781
+ meta = JSON.parse(readFileSync71(join56(sourceDir, TEMPLATE_META_FILE), "utf8"));
64405
64782
  } catch {
64406
64783
  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>)` }));
64407
64784
  return 2;
@@ -64411,7 +64788,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64411
64788
  return 2;
64412
64789
  }
64413
64790
  try {
64414
- const appearance = extractTemplateAppearance(JSON.parse(readFileSync70(join55(sourceDir, "tokens.json"), "utf8")));
64791
+ const appearance = extractTemplateAppearance(JSON.parse(readFileSync71(join56(sourceDir, "tokens.json"), "utf8")));
64415
64792
  meta = { ...appearance, ...meta };
64416
64793
  } catch {
64417
64794
  }
@@ -64423,13 +64800,13 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64423
64800
  const force = flags.force === true;
64424
64801
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
64425
64802
  const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
64426
- const out = mkdtempSync4(join55(tmpdir5(), "himi-template-"));
64803
+ const out = mkdtempSync4(join56(tmpdir5(), "himi-template-"));
64427
64804
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
64428
64805
  const outcome = await buildReleaseFromContent2(buildDir, out, {
64429
64806
  ...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
64430
64807
  collect: { lint: true, strict }
64431
64808
  });
64432
- const scaffoldSourceFindings = resolve46(sourceDir) === resolve46(appDir2) ? [] : [
64809
+ const scaffoldSourceFindings = resolve47(sourceDir) === resolve47(appDir2) ? [] : [
64433
64810
  ...tokenColorIssues(sourceDir),
64434
64811
  ...surfaceIssues(sourceDir, void 0, strict),
64435
64812
  ...await fontIssues(sourceDir, strict),
@@ -64472,11 +64849,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64472
64849
  }));
64473
64850
  return 1;
64474
64851
  }
64475
- const iconPath = str5(flags.icon) ? resolve46(str5(flags.icon)) : templateIconPath(name);
64852
+ const iconPath = str5(flags.icon) ? resolve47(str5(flags.icon)) : templateIconPath(name);
64476
64853
  let iconHash;
64477
64854
  if (iconPath) {
64478
64855
  try {
64479
- const bytes2 = readFileSync70(iconPath);
64856
+ const bytes2 = readFileSync71(iconPath);
64480
64857
  payload.icon = bytes2.toString("base64");
64481
64858
  iconHash = createHash26("sha256").update(bytes2).digest("hex");
64482
64859
  } catch {
@@ -64709,7 +65086,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64709
65086
  const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
64710
65087
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
64711
65088
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
64712
- const out = mkdtempSync4(join55(tmpdir5(), "himi-validate-"));
65089
+ const out = mkdtempSync4(join56(tmpdir5(), "himi-validate-"));
64713
65090
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
64714
65091
  const outcome = await buildReleaseFromContent2(dir, out, {
64715
65092
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -64752,7 +65129,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64752
65129
  const path2 = dpxSessionTokenPath();
64753
65130
  let raw;
64754
65131
  try {
64755
- raw = readFileSync70(path2, "utf8");
65132
+ raw = readFileSync71(path2, "utf8");
64756
65133
  } catch {
64757
65134
  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`);
64758
65135
  }
@@ -64872,7 +65249,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64872
65249
  case "studio": {
64873
65250
  const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
64874
65251
  const dir = contentDir(flags);
64875
- if (!existsSync59(join55(dir, "himalaya.content.json"))) {
65252
+ if (!existsSync60(join56(dir, "himalaya.content.json"))) {
64876
65253
  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/" }));
64877
65254
  return 2;
64878
65255
  }
@@ -64897,7 +65274,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64897
65274
  const { appendProgress: appendProgress2, readProgress: readProgress2, summarizeProgress: summarizeProgress2, parseStep: parseStep2, notifyDesktop: notifyDesktop2, appLabel: appLabel2, journalPath: journalPath2, ProgressError: ProgressError2, JOURNEY_STEPS: JOURNEY_STEPS2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
64898
65275
  const dir = contentDir(flags);
64899
65276
  const journal = journalPath2(dir);
64900
- const hint = existsSync59(join55(dir, "himalaya.content.json")) ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
65277
+ const hint = existsSync60(join56(dir, "himalaya.content.json")) ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
64901
65278
  const message = pos.slice(1).join(" ").trim();
64902
65279
  if (!message) {
64903
65280
  if (flags.step !== void 0 || flags.image !== void 0 || flags.notify === true) {
@@ -64989,7 +65366,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
64989
65366
  case "test": {
64990
65367
  const dir = contentDir(flags);
64991
65368
  const structuredOutput = flags.json === true || io.isTTY !== true;
64992
- if (existsSync59(join55(dir, "functions"))) {
65369
+ if (existsSync60(join56(dir, "functions"))) {
64993
65370
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
64994
65371
  const loaded = await loadFunctionsApp2(dir);
64995
65372
  const results = [];
@@ -65076,7 +65453,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65076
65453
  }
65077
65454
  }
65078
65455
  const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
65079
- const out = mkdtempSync4(join55(tmpdir5(), "himi-test-"));
65456
+ const out = mkdtempSync4(join56(tmpdir5(), "himi-test-"));
65080
65457
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
65081
65458
  const outcome = await buildReleaseFromContent2(dir, out, {
65082
65459
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -65121,7 +65498,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65121
65498
  io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
65122
65499
  return 2;
65123
65500
  }
65124
- const sources = collectWorkerSources2(join55(dir, "tier5-src"), screen.bundleName);
65501
+ const sources = collectWorkerSources2(join56(dir, "tier5-src"), screen.bundleName);
65125
65502
  if (!sources) {
65126
65503
  io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
65127
65504
  return 2;
@@ -65282,7 +65659,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65282
65659
  const sp = await runShotsPass2({
65283
65660
  descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
65284
65661
  tokens: outcome.tokens,
65285
- outDir: join55(dir, ".himi", "shots"),
65662
+ outDir: join56(dir, ".himi", "shots"),
65286
65663
  width: 390,
65287
65664
  layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
65288
65665
  ...budgetMs ? { budgetMs } : {},
@@ -65292,7 +65669,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65292
65669
  renderDescriptorWeb: renderDescriptorWeb2,
65293
65670
  renderPngBatch: renderPngBatch2,
65294
65671
  writePng: (path2, base64) => writePngFile(path2, base64),
65295
- clearDir: (d) => rmSync11(d, { recursive: true, force: true })
65672
+ clearDir: (d) => rmSync13(d, { recursive: true, force: true })
65296
65673
  }
65297
65674
  });
65298
65675
  writtenShots = sp.written;
@@ -65320,7 +65697,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65320
65697
  releaseId: result.releaseId,
65321
65698
  releasePayload: release,
65322
65699
  descriptors: attestedDescriptors,
65323
- screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join55(dir, ".himi", "shots", name)])),
65700
+ screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join56(dir, ".himi", "shots", name)])),
65324
65701
  coverage: {
65325
65702
  screens: crawledScreens.size,
65326
65703
  actionsDispatched: result.actions.exercised,
@@ -65410,7 +65787,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65410
65787
  return 2;
65411
65788
  }
65412
65789
  try {
65413
- const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync70(stateArg.replace(/^@/, ""), "utf8");
65790
+ const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync71(stateArg.replace(/^@/, ""), "utf8");
65414
65791
  injectedState = JSON.parse(raw);
65415
65792
  } catch (e) {
65416
65793
  io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
@@ -65425,7 +65802,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65425
65802
  return 2;
65426
65803
  }
65427
65804
  try {
65428
- const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync70(inputArg.replace(/^@/, ""), "utf8");
65805
+ const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync71(inputArg.replace(/^@/, ""), "utf8");
65429
65806
  const parsed = JSON.parse(raw);
65430
65807
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
65431
65808
  injectedInput = parsed;
@@ -65474,7 +65851,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65474
65851
  }
65475
65852
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
65476
65853
  const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
65477
- const out = mkdtempSync4(join55(tmpdir5(), "himi-render-"));
65854
+ const out = mkdtempSync4(join56(tmpdir5(), "himi-render-"));
65478
65855
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
65479
65856
  const outcome = await buildReleaseFromContent2(dir, out, {
65480
65857
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -65488,11 +65865,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
65488
65865
  const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
65489
65866
  let pngFile;
65490
65867
  let attestationPngFile;
65491
- const shotPath = join55(dir, ".himi", "shots", `${screenId}.png`);
65868
+ const shotPath = join56(dir, ".himi", "shots", `${screenId}.png`);
65492
65869
  const pngTarget = typeof flags.png === "string" ? str5(flags.png) : flags.png === true ? shotPath : void 0;
65493
65870
  if (pngTarget && r.pngBase64) {
65494
65871
  pngFile = writePngFile(pngTarget, r.pngBase64);
65495
- attestationPngFile = resolve46(pngTarget) === resolve46(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
65872
+ attestationPngFile = resolve47(pngTarget) === resolve47(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
65496
65873
  }
65497
65874
  if (renderWidth !== void 0 && r.renderable) {
65498
65875
  recordRenderWidth(dir, {
@@ -65816,7 +66193,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
65816
66193
  return 2;
65817
66194
  }
65818
66195
  const renamed = str5(flags.name);
65819
- const dest = resolve46(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
66196
+ const dest = resolve47(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
65820
66197
  const replace = flags.replace === true;
65821
66198
  const force = replace || flags.force === true;
65822
66199
  const linked = symlinkDestinationIssue(dest);
@@ -65824,8 +66201,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
65824
66201
  io.error(JSON.stringify(linked));
65825
66202
  return 1;
65826
66203
  }
65827
- if (existsSync59(dest)) {
65828
- if (!statSync16(dest).isDirectory()) {
66204
+ if (existsSync60(dest)) {
66205
+ if (!statSync17(dest).isDirectory()) {
65829
66206
  io.error(JSON.stringify({
65830
66207
  error: `${dest} exists and is not a directory`,
65831
66208
  hint: "pass --out/--name to land somewhere else, or remove the file"
@@ -65837,7 +66214,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
65837
66214
  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" }));
65838
66215
  return 1;
65839
66216
  }
65840
- if (replace && occupied && !existsSync59(join55(dest, "himalaya.content.json"))) {
66217
+ if (replace && occupied && !existsSync60(join56(dest, "himalaya.content.json"))) {
65841
66218
  io.error(JSON.stringify({
65842
66219
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
65843
66220
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -65976,7 +66353,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
65976
66353
  const force = flags.force === true;
65977
66354
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
65978
66355
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
65979
- const out = mkdtempSync4(join55(tmpdir5(), "himi-push-"));
66356
+ const out = mkdtempSync4(join56(tmpdir5(), "himi-push-"));
65980
66357
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
65981
66358
  const outcome = await buildReleaseFromContent2(dir, out, {
65982
66359
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -66448,7 +66825,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66448
66825
  return 2;
66449
66826
  }
66450
66827
  try {
66451
- const res = writePack(resolve46(releaseDir), only, resolve46(str5(flags.out) ?? process.cwd()));
66828
+ const res = writePack(resolve47(releaseDir), only, resolve47(str5(flags.out) ?? process.cwd()));
66452
66829
  print({
66453
66830
  ok: true,
66454
66831
  app: res.app,
@@ -66497,7 +66874,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66497
66874
  }
66498
66875
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
66499
66876
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
66500
- const built = mkdtempSync4(join55(tmpdir5(), "himi-pack-"));
66877
+ const built = mkdtempSync4(join56(tmpdir5(), "himi-pack-"));
66501
66878
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
66502
66879
  const outcome = await buildReleaseFromContent2(dir, built, {
66503
66880
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -66514,12 +66891,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66514
66891
  ...await navIssues2(dir, strict)
66515
66892
  ]);
66516
66893
  if (hasErrors && !force) {
66517
- rmSync11(built, { recursive: true, force: true });
66894
+ rmSync13(built, { recursive: true, force: true });
66518
66895
  print({ ...report2, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
66519
66896
  return 1;
66520
66897
  }
66521
66898
  try {
66522
- const res = writePack(built, app, resolve46(str5(flags.out) ?? dir), sourceArchive);
66899
+ const res = writePack(built, app, resolve47(str5(flags.out) ?? dir), sourceArchive);
66523
66900
  print({
66524
66901
  ok: true,
66525
66902
  app: res.app,
@@ -66550,7 +66927,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66550
66927
  io.error(JSON.stringify({ error: e.message }));
66551
66928
  return 1;
66552
66929
  } finally {
66553
- rmSync11(built, { recursive: true, force: true });
66930
+ rmSync13(built, { recursive: true, force: true });
66554
66931
  }
66555
66932
  }
66556
66933
  // ---- himi import — turn a dev .himi back into an editable content package ----
@@ -66564,7 +66941,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66564
66941
  const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
66565
66942
  let opened;
66566
66943
  try {
66567
- opened = openPackageFile2(resolve46(file));
66944
+ opened = openPackageFile2(resolve47(file));
66568
66945
  } catch (e) {
66569
66946
  io.error(JSON.stringify({ error: e.message }));
66570
66947
  return 1;
@@ -66577,7 +66954,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66577
66954
  io.error(JSON.stringify({
66578
66955
  ok: false,
66579
66956
  error: "app_source_not_in_package",
66580
- detail: `${resolve46(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
66957
+ detail: `${resolve47(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
66581
66958
  hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
66582
66959
  }));
66583
66960
  return 1;
@@ -66600,7 +66977,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66600
66977
  return 1;
66601
66978
  }
66602
66979
  }
66603
- const dest = resolve46(str5(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
66980
+ const dest = resolve47(str5(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
66604
66981
  const issue2 = restoreDestinationIssue(dest, flags.force === true);
66605
66982
  if (issue2) {
66606
66983
  io.error(JSON.stringify(issue2));
@@ -66685,7 +67062,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66685
67062
  }
66686
67063
  try {
66687
67064
  const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
66688
- const opened = openPackageFile2(resolve46(file));
67065
+ const opened = openPackageFile2(resolve47(file));
66689
67066
  if (!opened.validation.ok || !opened.header) {
66690
67067
  io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
66691
67068
  return 1;
@@ -66695,12 +67072,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66695
67072
  io.error(JSON.stringify({
66696
67073
  ok: false,
66697
67074
  error: "refusing to share a package that carries the app's source",
66698
- detail: `${resolve46(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
67075
+ detail: `${resolve47(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
66699
67076
  hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
66700
67077
  }));
66701
67078
  return 1;
66702
67079
  }
66703
- const archive = readFileSync70(resolve46(file));
67080
+ const archive = readFileSync71(resolve47(file));
66704
67081
  const result = await client2().createPackageShare({
66705
67082
  app: opened.header.app,
66706
67083
  releaseId: opened.header.releaseId,
@@ -66731,16 +67108,33 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66731
67108
  const { runPackage: runPackage2 } = await Promise.resolve().then(() => (init_run(), run_exports));
66732
67109
  let source = pos[1];
66733
67110
  let temp = null;
67111
+ const watch2 = flags.watch === true;
67112
+ if (watch2) {
67113
+ const { watchFlagConflict: watchFlagConflict2, watchedContentDir: watchedContentDir2 } = await Promise.resolve().then(() => (init_run_watch(), run_watch_exports));
67114
+ const watchedDir = watchedContentDir2(source);
67115
+ if (watchedDir) {
67116
+ flags.content = watchedDir;
67117
+ source = void 0;
67118
+ }
67119
+ const conflict = watchFlagConflict2({ source, browser: flags.browser === true, spa: str5(flags.spa) });
67120
+ if (conflict) {
67121
+ io.error(JSON.stringify({ ok: false, ...conflict }));
67122
+ return 2;
67123
+ }
67124
+ }
67125
+ let served = null;
67126
+ let servedMissing = [];
66734
67127
  try {
66735
67128
  if (!source) {
66736
- const dir = contentDir(flags);
66737
- const app = await appId(dir);
67129
+ const dir2 = contentDir(flags);
67130
+ const app = await appId(dir2);
66738
67131
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
66739
- const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
66740
- temp = mkdtempSync4(join55(tmpdir5(), "himi-run-build-"));
67132
+ const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
67133
+ temp = mkdtempSync4(join56(tmpdir5(), "himi-run-build-"));
66741
67134
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
66742
- await buildReleaseFromContent2(dir, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
66743
- source = join55(temp, app);
67135
+ const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
67136
+ servedMissing = initial.missingBundles;
67137
+ source = join56(temp, app);
66744
67138
  }
66745
67139
  const chromeArg = str5(flags.chrome) ?? "preview";
66746
67140
  if (chromeArg !== "preview" && chromeArg !== "app") {
@@ -66765,45 +67159,142 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
66765
67159
  open: flags["no-open"] !== true
66766
67160
  });
66767
67161
  print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
66768
- await new Promise((resolve47) => {
67162
+ await new Promise((resolve48) => {
66769
67163
  const stop = () => {
66770
- void run2.close().finally(() => resolve47());
67164
+ void run2.close().finally(() => resolve48());
66771
67165
  };
66772
67166
  process.once("SIGINT", stop);
66773
67167
  process.once("SIGTERM", stop);
66774
67168
  });
66775
67169
  return 0;
66776
67170
  }
67171
+ const dir = contentDir(flags);
67172
+ const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
67173
+ const bus = watchKit ? new watchKit.ReloadBus() : void 0;
67174
+ if (watch2) served = mkdtempSync4(join56(tmpdir5(), "himi-run-served-"));
66777
67175
  const running = await runPackage2(source, {
66778
67176
  port,
66779
67177
  chrome: chromeArg,
66780
67178
  screen: str5(flags.screen),
66781
67179
  surface: str5(flags.surface),
66782
67180
  spa: str5(flags.spa),
66783
- open: flags["no-open"] !== true
67181
+ open: flags["no-open"] !== true,
67182
+ ...watchKit && served && bus ? { workDir: served, screenEvents: bus, extraRoutes: (request) => watchKit.boardFile(dir, new URL(request.url).pathname) } : {}
66784
67183
  });
67184
+ let watcher;
67185
+ let rebuild;
67186
+ let recorded = false;
67187
+ let stopping = false;
67188
+ const refreshBoard = async () => {
67189
+ if (!boardOpen(dir)) return;
67190
+ const { refreshStudio: refreshStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
67191
+ refreshStudio2(dir);
67192
+ };
67193
+ if (watchKit && bus) {
67194
+ try {
67195
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
67196
+ const record2 = (build2) => {
67197
+ if (watchKit.writeRunRecord(dir, { url: running.url, port: running.port, pid: process.pid, startedAt, build: build2 })) recorded = true;
67198
+ };
67199
+ record2({ ok: true, at: startedAt });
67200
+ if (!recorded) io.error(JSON.stringify({ watch: "run_record_skipped", message: `${join56(dir, ".himi")} is not a real directory, so the build board will not frame this preview.` }));
67201
+ await refreshBoard();
67202
+ const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
67203
+ const live2 = join56(running.releaseRoot, running.app);
67204
+ const manifestOf = (tree) => JSON.parse(readFileSync71(join56(tree, "release-manifest.json"), "utf8"));
67205
+ let current = manifestOf(live2);
67206
+ const failed2 = async (message) => {
67207
+ if (stopping) return;
67208
+ bus.publish("build.failed", { message });
67209
+ record2({ ok: false, at: (/* @__PURE__ */ new Date()).toISOString(), error: message });
67210
+ await refreshBoard();
67211
+ io.error(JSON.stringify({ watch: "build_failed", keptLastGood: true, message }));
67212
+ };
67213
+ rebuild = watchKit.serialize(async () => {
67214
+ const t0 = Date.now();
67215
+ const next = mkdtempSync4(join56(tmpdir5(), "himi-run-build-"));
67216
+ try {
67217
+ const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
67218
+ if (bres.compileErrors.length) {
67219
+ const first = bres.compileErrors[0];
67220
+ const diag = first.errors[0];
67221
+ await failed2(`${first.bundle}: ${diag ? `${diag.file ? `${diag.file}${diag.line ? `:${diag.line}` : ""} ` : ""}${diag.text}` : "did not compile"}`);
67222
+ return;
67223
+ }
67224
+ const hasWorkers = bres.built.length > 0;
67225
+ const outcome = await buildReleaseFromContent2(dir, next, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
67226
+ const blocker = watchKit.rebuildBlocker(outcome, servedMissing);
67227
+ if (blocker) {
67228
+ await failed2(blocker);
67229
+ return;
67230
+ }
67231
+ if (stopping) return;
67232
+ const fresh = manifestOf(join56(next, running.app));
67233
+ const diff = watchKit.diffReleases(current, fresh);
67234
+ const retired = `${live2}.retired-${Date.now()}`;
67235
+ renameSync6(live2, retired);
67236
+ try {
67237
+ renameSync6(join56(next, running.app), live2);
67238
+ } catch {
67239
+ cpSync3(join56(next, running.app), live2, { recursive: true });
67240
+ }
67241
+ rmSync13(retired, { recursive: true, force: true });
67242
+ current = fresh;
67243
+ servedMissing = outcome.missingBundles;
67244
+ for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
67245
+ record2({ ok: true, at: (/* @__PURE__ */ new Date()).toISOString() });
67246
+ await refreshBoard();
67247
+ io.error(JSON.stringify({ watch: "rebuilt", ms: Date.now() - t0, screens: diff.screens, tokens: diff.tokens, config: diff.config, tabs: bus.listeners }));
67248
+ } catch (e) {
67249
+ await failed2(e.message.split("\n")[0]);
67250
+ } finally {
67251
+ rmSync13(next, { recursive: true, force: true });
67252
+ }
67253
+ });
67254
+ watcher = watchKit.watchContent(dir, () => rebuild?.());
67255
+ } catch (e) {
67256
+ if (recorded) watchKit.removeRunRecord(dir);
67257
+ await running.close();
67258
+ throw e;
67259
+ }
67260
+ }
66785
67261
  print({
66786
67262
  ok: true,
66787
67263
  app: running.app,
66788
67264
  releaseId: running.releaseId,
66789
67265
  url: running.url,
66790
67266
  port: running.port,
67267
+ ...watch2 ? { watching: dir, ...boardOpen(dir) ? { board: `${running.origin}/__himi/studio/` } : {} } : {},
66791
67268
  ...running.warnings.length ? { warnings: running.warnings } : {},
66792
67269
  stop: "Ctrl-C"
66793
67270
  });
66794
67271
  await new Promise((done) => {
66795
- const stop = () => {
66796
- void running.close().then(done);
67272
+ const stop = async () => {
67273
+ stopping = true;
67274
+ watcher?.close();
67275
+ try {
67276
+ await rebuild?.stop();
67277
+ if (recorded) {
67278
+ watchKit?.removeRunRecord(dir);
67279
+ await refreshBoard();
67280
+ }
67281
+ } catch (e) {
67282
+ io.error(JSON.stringify({ watch: "stop_cleanup_failed", message: e.message }));
67283
+ } finally {
67284
+ await running.close();
67285
+ done();
67286
+ }
66797
67287
  };
66798
- process.once("SIGINT", stop);
66799
- process.once("SIGTERM", stop);
67288
+ process.once("SIGINT", () => void stop());
67289
+ process.once("SIGTERM", () => void stop());
66800
67290
  });
66801
67291
  return 0;
66802
67292
  } catch (e) {
66803
67293
  io.error(JSON.stringify({ error: e.message }));
66804
67294
  return 1;
66805
67295
  } finally {
66806
- if (temp) rmSync11(temp, { recursive: true, force: true });
67296
+ if (temp) rmSync13(temp, { recursive: true, force: true });
67297
+ if (served) rmSync13(served, { recursive: true, force: true });
66807
67298
  }
66808
67299
  }
66809
67300
  case "preview": {
@@ -67344,7 +67835,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
67344
67835
  io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
67345
67836
  return 2;
67346
67837
  }
67347
- if (!existsSync59(file)) {
67838
+ if (!existsSync60(file)) {
67348
67839
  io.error(JSON.stringify({ error: `no such file: ${file}` }));
67349
67840
  return 2;
67350
67841
  }
@@ -67400,7 +67891,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
67400
67891
  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."
67401
67892
  };
67402
67893
  if (kind === "tokens" || kind === "app-config") {
67403
- const body = readFileSync70(file, "utf8");
67894
+ const body = readFileSync71(file, "utf8");
67404
67895
  const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
67405
67896
  return runReleasePatch({
67406
67897
  ...common,
@@ -67415,7 +67906,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
67415
67906
  io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
67416
67907
  return 2;
67417
67908
  }
67418
- const descriptor = readFileSync70(file, "utf8");
67909
+ const descriptor = readFileSync71(file, "utf8");
67419
67910
  try {
67420
67911
  JSON.parse(descriptor);
67421
67912
  } catch (e) {
@@ -67455,7 +67946,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
67455
67946
  extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
67456
67947
  });
67457
67948
  }
67458
- const bytes2 = readFileSync70(file);
67949
+ const bytes2 = readFileSync71(file);
67459
67950
  const sha = createHash26("sha256").update(bytes2).digest("hex");
67460
67951
  const forScreens = (str5(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
67461
67952
  if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
@@ -67599,7 +68090,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
67599
68090
  }
67600
68091
  let def;
67601
68092
  try {
67602
- const parsed = JSON.parse(arg.startsWith("@") ? readFileSync70(arg.slice(1), "utf8") : arg);
68093
+ const parsed = JSON.parse(arg.startsWith("@") ? readFileSync71(arg.slice(1), "utf8") : arg);
67603
68094
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
67604
68095
  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}`] }));
67605
68096
  return 2;
@@ -68063,7 +68554,7 @@ ${label2}`);
68063
68554
  const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
68064
68555
  {
68065
68556
  const distDir = contentDir(flags);
68066
- if (existsSync59(join55(distDir, "himalaya.content.json"))) {
68557
+ if (existsSync60(join56(distDir, "himalaya.content.json"))) {
68067
68558
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
68068
68559
  const errors = issues.filter((i) => i.severity === "error");
68069
68560
  for (const i of issues.filter((i2) => i2.severity === "warning")) {
@@ -68332,7 +68823,7 @@ ${label2}`);
68332
68823
  const dpxPath = dpxSessionTokenPath();
68333
68824
  let dpx;
68334
68825
  try {
68335
- dpx = readFileSync70(dpxPath, "utf8").trim();
68826
+ dpx = readFileSync71(dpxPath, "utf8").trim();
68336
68827
  } catch {
68337
68828
  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` }));
68338
68829
  return 1;
@@ -68734,7 +69225,7 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
68734
69225
  const path2 = dpxSessionTokenPath();
68735
69226
  let raw;
68736
69227
  try {
68737
- raw = readFileSync70(path2, "utf8");
69228
+ raw = readFileSync71(path2, "utf8");
68738
69229
  } catch {
68739
69230
  io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
68740
69231
  return 1;