@wix/himalaya-cli 0.1326.0 → 0.1328.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.
Files changed (2) hide show
  1. package/dist/cli.mjs +759 -652
  2. package/package.json +2 -2
package/dist/cli.mjs CHANGED
@@ -7591,6 +7591,7 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
7591
7591
  var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
7592
7592
  var init_bindings = __esm({
7593
7593
  "../../core/ts/src/bindings.ts"() {
7594
+ "use strict";
7594
7595
  BINDING_SIGILS = ["service", "flag", "item", "t"];
7595
7596
  BINDING_SIGIL_RE = new RegExp(
7596
7597
  `^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
@@ -34746,9 +34747,83 @@ var init_net_mocks_rollover = __esm({
34746
34747
  });
34747
34748
 
34748
34749
  // ../../core/dev-server/src/player-proxy.ts
34750
+ import { readFileSync as readFileSync45 } from "node:fs";
34751
+ import { homedir as homedir6 } from "node:os";
34752
+ import { dirname as dirname27, join as join41 } from "node:path";
34753
+ import { fileURLToPath as fileURLToPath18 } from "node:url";
34754
+ function readJson2(path2) {
34755
+ try {
34756
+ return JSON.parse(readFileSync45(path2, "utf8"));
34757
+ } catch {
34758
+ return void 0;
34759
+ }
34760
+ }
34761
+ function ledgerDevServerPort(tenant) {
34762
+ const here = dirname27(fileURLToPath18(import.meta.url));
34763
+ const ledger = readJson2(join41(here, "..", "..", "..", "tools", "dev-cli", "ports.json"));
34764
+ const port = ledger?.apps?.[tenant]?.devServer;
34765
+ return typeof port === "number" ? port : void 0;
34766
+ }
34767
+ function loadSupervisorRegistry() {
34768
+ const home = process.env.HIMALAYA_HOME ?? join41(homedir6(), ".himalaya");
34769
+ const reg = readJson2(join41(home, "instances.json"));
34770
+ return { instances: reg?.instances && typeof reg.instances === "object" ? reg.instances : {} };
34771
+ }
34749
34772
  function isPlayerHost(appName2) {
34750
34773
  return appName2 === PLAYER_APP_ID || process.env.HIMALAYA_DEV_MULTI_APP === "1";
34751
34774
  }
34775
+ function isTenantHost(appName2) {
34776
+ return !!appName2 && Object.prototype.hasOwnProperty.call(HOSTED_TENANTS, appName2);
34777
+ }
34778
+ function resolveTenantBase(tenant, registry2 = loadSupervisorRegistry) {
34779
+ for (const pair of (process.env.HIMALAYA_DEV_TENANT_UPSTREAMS ?? "").split(",")) {
34780
+ const i2 = pair.indexOf("=");
34781
+ if (i2 > 0 && pair.slice(0, i2).trim() === tenant) return pair.slice(i2 + 1).trim().replace(/\/$/, "");
34782
+ }
34783
+ if (process.env.HIMALAYA_DEV_TENANT_SOURCE !== "serve") {
34784
+ let port;
34785
+ try {
34786
+ const running = registry2().instances[tenant];
34787
+ if (running?.status === "running" && running.port) port = running.port;
34788
+ } catch {
34789
+ }
34790
+ port ??= ledgerDevServerPort(tenant);
34791
+ if (port) return `http://127.0.0.1:${port}`;
34792
+ }
34793
+ return resolveServeBase();
34794
+ }
34795
+ function isTenantAdminPath(url) {
34796
+ const path2 = url.split("?")[0];
34797
+ return path2 === "/v1/admin" || path2.startsWith("/v1/admin/");
34798
+ }
34799
+ function tenantPrefixed(url, hostApp, method = "GET") {
34800
+ if (!hostApp || !isTenantHost(hostApp) || !url.startsWith(TENANT_PREFIX)) return null;
34801
+ if (method !== "GET" && method !== "HEAD") return null;
34802
+ const rest = url.slice(TENANT_PREFIX.length);
34803
+ const slash = rest.indexOf("/");
34804
+ if (slash <= 0) return null;
34805
+ const tenant = decodeURIComponent(rest.slice(0, slash));
34806
+ const tenantUrl = rest.slice(slash);
34807
+ const path2 = tenantUrl.split("?")[0];
34808
+ let normalized;
34809
+ try {
34810
+ normalized = new URL(decodeURIComponent(path2), "http://tenant.invalid").pathname;
34811
+ } catch {
34812
+ return null;
34813
+ }
34814
+ if (!normalized.startsWith("/v1/") || normalized !== path2 || isTenantAdminPath(normalized)) return null;
34815
+ return HOSTED_TENANTS[hostApp].includes(tenant) ? { tenant, url: tenantUrl } : null;
34816
+ }
34817
+ function forwardedBaseUrl(req) {
34818
+ if (!LOOPBACK_PEERS.has(req.socket?.remoteAddress ?? "")) return null;
34819
+ const first = (h2) => (Array.isArray(h2) ? h2[0] : h2)?.split(",", 1)[0]?.trim() ?? "";
34820
+ const host = first(req.headers["x-forwarded-host"]);
34821
+ if (!host || !/^[A-Za-z0-9.\-:[\]]+$/.test(host)) return null;
34822
+ const proto = first(req.headers["x-forwarded-proto"]).toLowerCase() === "https" ? "https" : "http";
34823
+ const prefix = first(req.headers["x-forwarded-prefix"]);
34824
+ const safePrefix = /^(\/[A-Za-z0-9._~\-]+)+$/.test(prefix) && !prefix.split("/").some((seg) => seg === "." || seg === "..") ? prefix : "";
34825
+ return `${proto}://${host}${safePrefix}`;
34826
+ }
34752
34827
  function resolveServeBase() {
34753
34828
  const override = process.env.HIMALAYA_PLAYER_SERVE_URL;
34754
34829
  let raw = override;
@@ -34776,15 +34851,16 @@ function targetTenant(url, headers2, hostApp) {
34776
34851
  }
34777
34852
  if (!app) return null;
34778
34853
  if (app === hostApp || app === PLAYER_APP_ID) return null;
34854
+ if (hostApp && isTenantHost(hostApp) && !HOSTED_TENANTS[hostApp].includes(app)) return null;
34779
34855
  return app;
34780
34856
  }
34781
34857
  function shouldServeFromPlane(url, headers2, hostApp) {
34782
34858
  const path2 = url.split("?")[0];
34783
- if (path2 === "/v1/apps" || path2 === "/v1/templates") return true;
34859
+ if (path2 === "/v1/apps" || path2 === "/v1/templates") return !isTenantHost(hostApp);
34784
34860
  if (!path2.startsWith("/v1/")) return false;
34785
34861
  return targetTenant(url, headers2, hostApp) !== null;
34786
34862
  }
34787
- async function proxyToServe(base, req, res) {
34863
+ async function proxyToServe(base, req, res, opts = {}) {
34788
34864
  const body = await new Promise((done) => {
34789
34865
  const chunks = [];
34790
34866
  req.on("data", (c2) => chunks.push(Buffer.from(c2)));
@@ -34796,7 +34872,11 @@ async function proxyToServe(base, req, res) {
34796
34872
  if (STRIP_REQUEST_HEADERS.has(k2.toLowerCase()) || v2 === void 0) continue;
34797
34873
  reqHeaders[k2] = Array.isArray(v2) ? v2.join(", ") : v2;
34798
34874
  }
34799
- const target = `${base}${req.url ?? ""}`;
34875
+ if (opts.forwardAs) {
34876
+ reqHeaders["x-forwarded-host"] = opts.forwardAs.host;
34877
+ reqHeaders["x-forwarded-prefix"] = opts.forwardAs.prefix;
34878
+ }
34879
+ const target = `${base}${opts.url ?? req.url ?? ""}`;
34800
34880
  let upstream;
34801
34881
  try {
34802
34882
  upstream = await fetch(target, {
@@ -34819,11 +34899,16 @@ async function proxyToServe(base, req, res) {
34819
34899
  res.writeHead(upstream.status, outHeaders);
34820
34900
  res.end(buf);
34821
34901
  }
34822
- var PLAYER_APP_ID, STRIP_RESPONSE_HEADERS, STRIP_REQUEST_HEADERS;
34902
+ var PLAYER_APP_ID, HOSTED_TENANTS, TENANT_PREFIX, LOOPBACK_PEERS, STRIP_RESPONSE_HEADERS, STRIP_REQUEST_HEADERS;
34823
34903
  var init_player_proxy = __esm({
34824
34904
  "../../core/dev-server/src/player-proxy.ts"() {
34825
34905
  init_config();
34826
34906
  PLAYER_APP_ID = "himi-player";
34907
+ HOSTED_TENANTS = {
34908
+ "himi-spaces-lite": ["himi-branded-lite"]
34909
+ };
34910
+ TENANT_PREFIX = "/__tenant/";
34911
+ LOOPBACK_PEERS = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "::ffff:127.0.0.1"]);
34827
34912
  STRIP_RESPONSE_HEADERS = /* @__PURE__ */ new Set([
34828
34913
  "connection",
34829
34914
  "keep-alive",
@@ -42407,7 +42492,7 @@ var init_pdf = __esm({
42407
42492
  var defineProperty = Object.defineProperty;
42408
42493
  var stringSlice = uncurryThis("".slice);
42409
42494
  var replace = uncurryThis("".replace);
42410
- var join83 = uncurryThis([].join);
42495
+ var join84 = uncurryThis([].join);
42411
42496
  var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
42412
42497
  return defineProperty(function() {
42413
42498
  }, "length", { value: 8 }).length !== 8;
@@ -42434,7 +42519,7 @@ var init_pdf = __esm({
42434
42519
  }
42435
42520
  var state = enforceInternalState(value);
42436
42521
  if (!hasOwn(state, "source")) {
42437
- state.source = join83(TEMPLATE, typeof name == "string" ? name : "");
42522
+ state.source = join84(TEMPLATE, typeof name == "string" ? name : "");
42438
42523
  }
42439
42524
  return value;
42440
42525
  };
@@ -44957,7 +45042,7 @@ var init_pdf = __esm({
44957
45042
  var charAt = uncurryThis("".charAt);
44958
45043
  var Uint8Array2 = globalThis2.Uint8Array;
44959
45044
  var $Array = globalThis2.Array;
44960
- var join83 = uncurryThis([].join);
45045
+ var join84 = uncurryThis([].join);
44961
45046
  var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
44962
45047
  try {
44963
45048
  var target = new Uint8Array2();
@@ -45003,7 +45088,7 @@ var init_pdf = __esm({
45003
45088
  result[written++] = "=";
45004
45089
  }
45005
45090
  }
45006
- return join83(result, "");
45091
+ return join84(result, "");
45007
45092
  }
45008
45093
  });
45009
45094
  },
@@ -45015,7 +45100,7 @@ var init_pdf = __esm({
45015
45100
  var anUint8Array = __webpack_require__3(4154);
45016
45101
  var notDetached = __webpack_require__3(5169);
45017
45102
  var numberToString2 = uncurryThis(1.1.toString);
45018
- var join83 = uncurryThis([].join);
45103
+ var join84 = uncurryThis([].join);
45019
45104
  var $Array = Array;
45020
45105
  var Uint8Array2 = globalThis2.Uint8Array;
45021
45106
  var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
@@ -45035,7 +45120,7 @@ var init_pdf = __esm({
45035
45120
  var hex2 = numberToString2(this[i2], 16);
45036
45121
  result[i2] = hex2.length === 1 ? "0" + hex2 : hex2;
45037
45122
  }
45038
- return join83(result, "");
45123
+ return join84(result, "");
45039
45124
  }
45040
45125
  });
45041
45126
  },
@@ -127862,12 +127947,12 @@ var init_render_descriptor = __esm({
127862
127947
  });
127863
127948
 
127864
127949
  // ../../core/dev-server/src/render-fonts.ts
127865
- import { existsSync as existsSync44, readFileSync as readFileSync45 } from "node:fs";
127866
- import { extname, join as join41 } from "node:path";
127950
+ import { existsSync as existsSync44, readFileSync as readFileSync46 } from "node:fs";
127951
+ import { extname, join as join42 } from "node:path";
127867
127952
  function servedFontFaces(appDir3, tokens2) {
127868
127953
  try {
127869
- const policyPath = join41(appDir3, "fonts.json");
127870
- const policy = existsSync44(policyPath) ? JSON.parse(readFileSync45(policyPath, "utf8")) : {};
127954
+ const policyPath = join42(appDir3, "fonts.json");
127955
+ const policy = existsSync44(policyPath) ? JSON.parse(readFileSync46(policyPath, "utf8")) : {};
127871
127956
  let plan = planFonts(tokens2, policy);
127872
127957
  if (!hasVendoredFloor()) plan = { ...plan, families: plan.families.filter((f2) => !isHostProvided(f2.name)) };
127873
127958
  if (plan.families.length === 0) return void 0;
@@ -127888,7 +127973,7 @@ async function faceBytes(face, catalog3, opts) {
127888
127973
  try {
127889
127974
  if (opts.source) {
127890
127975
  const path2 = opts.source(face.file, face.sha256);
127891
- return path2 ? readFileSync45(path2) : null;
127976
+ return path2 ? readFileSync46(path2) : null;
127892
127977
  }
127893
127978
  const bytes2 = await catalogFaceBytes(face.sha256, { catalog: catalog3, ...opts.fetchFace ? { fetchFace: opts.fetchFace } : {} });
127894
127979
  return bytes2 ?? null;
@@ -127954,7 +128039,7 @@ async function idiomFontFaceCss(idiomContext) {
127954
128039
  const bundled = idiomControls2(controlIdiomFor2(idiomContext)).font.bundled;
127955
128040
  if (!bundled) return "";
127956
128041
  try {
127957
- const bytes2 = readFileSync45(new URL(`../../web-host/public/${bundled.file}`, import.meta.url));
128042
+ const bytes2 = readFileSync46(new URL(`../../web-host/public/${bundled.file}`, import.meta.url));
127958
128043
  return `@font-face { font-family: "${bundled.family}"; font-weight: 100 900; font-style: normal; src: url(data:font/ttf;base64,${bytes2.toString("base64")}) format("truetype"); }`;
127959
128044
  } catch {
127960
128045
  return "";
@@ -127997,7 +128082,7 @@ var init_tier = __esm({
127997
128082
  });
127998
128083
 
127999
128084
  // ../../core/dev-server/src/flags/index.ts
128000
- import { readFileSync as readFileSync46 } from "node:fs";
128085
+ import { readFileSync as readFileSync47 } from "node:fs";
128001
128086
  import { resolve as resolve34 } from "node:path";
128002
128087
  function selectProvider(config, store) {
128003
128088
  const local = new LocalFlagProvider(store, () => config?.overrides);
@@ -128093,7 +128178,7 @@ var init_flags2 = __esm({
128093
128178
  if (now - this.lastFetch < this.ttlMs) return;
128094
128179
  this.lastFetch = now;
128095
128180
  try {
128096
- const defs = JSON.parse(readFileSync46(resolve34(appDir3, "flags.json"), "utf8"));
128181
+ const defs = JSON.parse(readFileSync47(resolve34(appDir3, "flags.json"), "utf8"));
128097
128182
  if (Array.isArray(defs) && defs.length > 0) store.replaceAll(defs);
128098
128183
  } catch {
128099
128184
  }
@@ -128143,19 +128228,19 @@ var init_motion_flags = __esm({
128143
128228
  });
128144
128229
 
128145
128230
  // ../../core/dev-server/src/kits.ts
128146
- import { readdirSync as readdirSync23, readFileSync as readFileSync47 } from "node:fs";
128147
- import { resolve as resolve35, join as join42 } from "node:path";
128148
- import { fileURLToPath as fileURLToPath18 } from "node:url";
128231
+ import { readdirSync as readdirSync23, readFileSync as readFileSync48 } from "node:fs";
128232
+ import { resolve as resolve35, join as join43 } from "node:path";
128233
+ import { fileURLToPath as fileURLToPath19 } from "node:url";
128149
128234
  function listKits() {
128150
128235
  return readdirSync23(CATALOG).filter((f2) => f2.endsWith(".json")).map((f2) => {
128151
- const { tokens: tokens2, ...meta } = JSON.parse(readFileSync47(join42(CATALOG, f2), "utf8"));
128236
+ const { tokens: tokens2, ...meta } = JSON.parse(readFileSync48(join43(CATALOG, f2), "utf8"));
128152
128237
  return meta;
128153
128238
  });
128154
128239
  }
128155
128240
  function readKit(id) {
128156
128241
  if (!/^[a-z0-9-]+$/.test(id)) return null;
128157
128242
  try {
128158
- return JSON.parse(readFileSync47(join42(CATALOG, `${id}.json`), "utf8"));
128243
+ return JSON.parse(readFileSync48(join43(CATALOG, `${id}.json`), "utf8"));
128159
128244
  } catch {
128160
128245
  return null;
128161
128246
  }
@@ -128163,8 +128248,8 @@ function readKit(id) {
128163
128248
  var ROOT5, CATALOG;
128164
128249
  var init_kits = __esm({
128165
128250
  "../../core/dev-server/src/kits.ts"() {
128166
- ROOT5 = resolve35(fileURLToPath18(new URL("../../..", import.meta.url)));
128167
- CATALOG = join42(ROOT5, "stdlib/design-kits");
128251
+ ROOT5 = resolve35(fileURLToPath19(new URL("../../..", import.meta.url)));
128252
+ CATALOG = join43(ROOT5, "stdlib/design-kits");
128168
128253
  }
128169
128254
  });
128170
128255
 
@@ -128890,9 +128975,9 @@ __export(config_exports2, {
128890
128975
  serializeRolloutYaml: () => serializeRolloutYaml,
128891
128976
  validateOverlayPatch: () => validateOverlayPatch
128892
128977
  });
128893
- import { mkdirSync as mkdirSync22, readFileSync as readFileSync48, writeFileSync as writeFileSync19 } from "node:fs";
128894
- import { dirname as dirname27, join as join43, resolve as resolve36 } from "node:path";
128895
- import { fileURLToPath as fileURLToPath19 } from "node:url";
128978
+ import { mkdirSync as mkdirSync22, readFileSync as readFileSync49, writeFileSync as writeFileSync19 } from "node:fs";
128979
+ import { dirname as dirname28, join as join44, resolve as resolve36 } from "node:path";
128980
+ import { fileURLToPath as fileURLToPath20 } from "node:url";
128896
128981
  function strip(line) {
128897
128982
  const h2 = line.indexOf("#");
128898
128983
  return (h2 >= 0 ? line.slice(0, h2) : line).replace(/\s+$/, "");
@@ -128956,14 +129041,14 @@ function parseRevocationsYaml(text9) {
128956
129041
  function appConfigPath(app, file2, root = REPO_ROOT6) {
128957
129042
  assertAppId(app, "appConfigPath");
128958
129043
  for (const base of ["apps", "test-apps"]) {
128959
- const p2 = join43(root, base, app, file2);
129044
+ const p2 = join44(root, base, app, file2);
128960
129045
  try {
128961
- readFileSync48(p2);
129046
+ readFileSync49(p2);
128962
129047
  return p2;
128963
129048
  } catch {
128964
129049
  }
128965
129050
  }
128966
- return join43(root, "apps", app, file2);
129051
+ return join44(root, "apps", app, file2);
128967
129052
  }
128968
129053
  function serializeRolloutYaml(cfg) {
128969
129054
  const lines = [`app: ${cfg.app}`, "rings:"];
@@ -129011,14 +129096,14 @@ function validateOverlayPatch(patch) {
129011
129096
  }
129012
129097
  function readJsonAt(app, file2, root) {
129013
129098
  try {
129014
- return JSON.parse(readFileSync48(appConfigPath(app, file2, root), "utf8"));
129099
+ return JSON.parse(readFileSync49(appConfigPath(app, file2, root), "utf8"));
129015
129100
  } catch {
129016
129101
  return null;
129017
129102
  }
129018
129103
  }
129019
129104
  function writeJsonAt(app, file2, root, value) {
129020
129105
  const path2 = appConfigPath(app, file2, root);
129021
- mkdirSync22(dirname27(path2), { recursive: true });
129106
+ mkdirSync22(dirname28(path2), { recursive: true });
129022
129107
  writeFileSync19(path2, JSON.stringify(value, null, 2) + "\n");
129023
129108
  return path2;
129024
129109
  }
@@ -129049,14 +129134,14 @@ function saveLocalFlags(app, defs, root = REPO_ROOT6) {
129049
129134
  }
129050
129135
  function loadRollout(app) {
129051
129136
  try {
129052
- return parseRolloutYaml(readFileSync48(appConfigPath(app, "rollout.yaml"), "utf8"));
129137
+ return parseRolloutYaml(readFileSync49(appConfigPath(app, "rollout.yaml"), "utf8"));
129053
129138
  } catch {
129054
129139
  return null;
129055
129140
  }
129056
129141
  }
129057
129142
  function loadRevocations(app) {
129058
129143
  try {
129059
- return parseRevocationsYaml(readFileSync48(appConfigPath(app, "revocations.yaml"), "utf8")).revoked;
129144
+ return parseRevocationsYaml(readFileSync49(appConfigPath(app, "revocations.yaml"), "utf8")).revoked;
129060
129145
  } catch {
129061
129146
  return [];
129062
129147
  }
@@ -129066,7 +129151,7 @@ var init_config2 = __esm({
129066
129151
  "../../core/serve-control/src/config.ts"() {
129067
129152
  init_errors();
129068
129153
  init_contract();
129069
- REPO_ROOT6 = resolve36(dirname27(fileURLToPath19(import.meta.url)), "../../..");
129154
+ REPO_ROOT6 = resolve36(dirname28(fileURLToPath20(import.meta.url)), "../../..");
129070
129155
  OPERATIONAL_OVERLAY_KEYS = /* @__PURE__ */ new Set([
129071
129156
  "wixCachePolicy",
129072
129157
  "telemetryConfig",
@@ -129134,10 +129219,10 @@ var init_config2 = __esm({
129134
129219
  // ../../core/dev-server/src/index.ts
129135
129220
  import { createServer as createServer3 } from "node:http";
129136
129221
  import { readFile, stat } from "node:fs/promises";
129137
- import { readFileSync as readFileSync49, existsSync as existsSync45, watch, mkdirSync as mkdirSync23, rmSync as rmSync11 } from "node:fs";
129138
- import { basename as basename10, dirname as dirname28, extname as extname2, join as join44, relative as relative8, resolve as resolve37, normalize as normalize3, sep as sep10 } from "node:path";
129222
+ import { readFileSync as readFileSync50, existsSync as existsSync45, watch, mkdirSync as mkdirSync23, rmSync as rmSync11 } from "node:fs";
129223
+ import { basename as basename10, dirname as dirname29, extname as extname2, join as join45, relative as relative8, resolve as resolve37, normalize as normalize3, sep as sep10 } from "node:path";
129139
129224
  import { createHash as createHash20, randomUUID as randomUUID5 } from "node:crypto";
129140
- import { fileURLToPath as fileURLToPath20, pathToFileURL as pathToFileURL6 } from "node:url";
129225
+ import { fileURLToPath as fileURLToPath21, pathToFileURL as pathToFileURL6 } from "node:url";
129141
129226
  function readLogicBundle(read, tier5Dir, name) {
129142
129227
  return read(tier5Dir ?? TIER5_ROOT2, name) ?? (tier5Dir && tier5Dir !== TIER5_ROOT2 ? read(TIER5_ROOT2, name) : void 0);
129143
129228
  }
@@ -129190,7 +129275,7 @@ function servedTokensPath(app) {
129190
129275
  function readAppTokens(state) {
129191
129276
  if (!state.app) return null;
129192
129277
  try {
129193
- const parsed = JSON.parse(readFileSync49(servedTokensPath(state.app), "utf8"));
129278
+ const parsed = JSON.parse(readFileSync50(servedTokensPath(state.app), "utf8"));
129194
129279
  delete parsed._meta;
129195
129280
  return parsed;
129196
129281
  } catch {
@@ -129202,7 +129287,7 @@ function effectiveAppConfigOverride(state) {
129202
129287
  if (state.app) {
129203
129288
  try {
129204
129289
  gitOverlay = JSON.parse(
129205
- readFileSync49(resolve37(state.app.dir, "app-config.overlay.json"), "utf8")
129290
+ readFileSync50(resolve37(state.app.dir, "app-config.overlay.json"), "utf8")
129206
129291
  );
129207
129292
  } catch {
129208
129293
  }
@@ -129271,7 +129356,7 @@ function handleL10nRequest(req, res, state) {
129271
129356
  let messages;
129272
129357
  try {
129273
129358
  messages = Object.fromEntries(
129274
- keyMap(parseCatalog(readFileSync49(path2, "utf8")), { sourceFallback: tag === sourceLocale })
129359
+ keyMap(parseCatalog(readFileSync50(path2, "utf8")), { sourceFallback: tag === sourceLocale })
129275
129360
  );
129276
129361
  } catch {
129277
129362
  return sendJson(res, 500, { error: "catalog_unreadable", app, tag }, cors);
@@ -129375,6 +129460,8 @@ function requestServerBaseUrl(req, configuredBaseUrl) {
129375
129460
  }
129376
129461
  const loopbackHosts = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]);
129377
129462
  if (!loopbackHosts.has(configured.hostname)) return configuredBaseUrl;
129463
+ const forwarded = forwardedBaseUrl(req);
129464
+ if (forwarded) return forwarded;
129378
129465
  const reqHost = req.headers.host;
129379
129466
  if (!reqHost) return configuredBaseUrl;
129380
129467
  const forwardedProto = String(req.headers["x-forwarded-proto"] ?? "").split(",", 1)[0].trim().toLowerCase();
@@ -129671,7 +129758,7 @@ async function buildDescriptorForScreenId(state, screenId, query = new URLSearch
129671
129758
  function bundleIntegritySync(name, dir) {
129672
129759
  for (const root of dir ? [dir, TIER5_ROOT2] : [TIER5_ROOT2]) {
129673
129760
  try {
129674
- const bytes2 = readFileSync49(resolve37(root, `${name}.bundle.js`));
129761
+ const bytes2 = readFileSync50(resolve37(root, `${name}.bundle.js`));
129675
129762
  return "sha256-" + createHash20("sha256").update(bytes2).digest("base64");
129676
129763
  } catch {
129677
129764
  }
@@ -129688,7 +129775,7 @@ async function handleScreenRequest(req, res, state) {
129688
129775
  const acceptLanguage = req.headers["accept-language"];
129689
129776
  const locale = pickLocale(typeof acceptLanguage === "string" ? acceptLanguage : null);
129690
129777
  const reqHost = req.headers.host;
129691
- const reqBaseUrl = reqHost ? `http://${reqHost}` : state.serverBaseUrl;
129778
+ const reqBaseUrl = forwardedBaseUrl(req) ?? (reqHost ? `http://${reqHost}` : state.serverBaseUrl);
129692
129779
  const reqState = reqBaseUrl === state.serverBaseUrl ? state : { ...state, serverBaseUrl: reqBaseUrl };
129693
129780
  const baseKey = queryString ? `${screenId}?${query.toString()}` : screenId;
129694
129781
  const localeKey = locale ? `${baseKey}::${locale}` : baseKey;
@@ -130093,7 +130180,7 @@ function tokensAreDerived(state) {
130093
130180
  }
130094
130181
  function servedTokensHash(app) {
130095
130182
  try {
130096
- return createHash20("sha256").update(readFileSync49(servedTokensPath(app))).digest("hex");
130183
+ return createHash20("sha256").update(readFileSync50(servedTokensPath(app))).digest("hex");
130097
130184
  } catch {
130098
130185
  return "";
130099
130186
  }
@@ -130119,7 +130206,7 @@ function syncAppDependencyWatchers(state, inputs) {
130119
130206
  }
130120
130207
  const byDir = /* @__PURE__ */ new Map();
130121
130208
  for (const file2 of appDependencyFiles(inputs, state.app.dir)) {
130122
- const dir = dirname28(file2);
130209
+ const dir = dirname29(file2);
130123
130210
  if (!byDir.has(dir)) byDir.set(dir, /* @__PURE__ */ new Set());
130124
130211
  byDir.get(dir).add(basename10(file2));
130125
130212
  }
@@ -130130,7 +130217,7 @@ function syncAppDependencyWatchers(state, inputs) {
130130
130217
  try {
130131
130218
  const w2 = watch(dir, { persistent: false }, (_event, filename) => {
130132
130219
  if (!filename || !names.has(String(filename))) return;
130133
- changed.add(join44(dir, String(filename)));
130220
+ changed.add(join45(dir, String(filename)));
130134
130221
  if (timer) clearTimeout(timer);
130135
130222
  timer = setTimeout(() => {
130136
130223
  timer = void 0;
@@ -130321,7 +130408,7 @@ async function handleWebWix(req, res, state) {
130321
130408
  const session = webWixSession(req, res, state);
130322
130409
  const auth = resolveWebWixAuth(state.app);
130323
130410
  const path2 = new URL(req.url ?? "", "http://localhost").pathname;
130324
- const readJson8 = async () => {
130411
+ const readJson9 = async () => {
130325
130412
  const chunks = [];
130326
130413
  for await (const c2 of req) chunks.push(c2);
130327
130414
  const t2 = Buffer.concat(chunks).toString("utf8");
@@ -130338,7 +130425,7 @@ async function handleWebWix(req, res, state) {
130338
130425
  res.end(JSON.stringify(obj3));
130339
130426
  };
130340
130427
  if (path2 === "/v1/__webwix/stream" && req.method === "POST") {
130341
- const b2 = await readJson8();
130428
+ const b2 = await readJson9();
130342
130429
  const method = String(b2.method ?? "GET").toUpperCase();
130343
130430
  const requestedUrl = String(b2.url ?? "");
130344
130431
  const body = b2.body === void 0 ? void 0 : typeof b2.body === "string" ? b2.body : JSON.stringify(b2.body);
@@ -130487,7 +130574,7 @@ async function handleWebWix(req, res, state) {
130487
130574
  return;
130488
130575
  }
130489
130576
  if (path2 === "/v1/__webwix/login" && req.method === "POST") {
130490
- const b2 = await readJson8();
130577
+ const b2 = await readJson9();
130491
130578
  try {
130492
130579
  const { memberToken, visitorToken } = await memberDirectLogin(
130493
130580
  auth.clientId,
@@ -130504,7 +130591,7 @@ async function handleWebWix(req, res, state) {
130504
130591
  }
130505
130592
  }
130506
130593
  if (path2 === "/v1/__webwix/call" && req.method === "POST") {
130507
- const b2 = await readJson8();
130594
+ const b2 = await readJson9();
130508
130595
  const ownerRung = b2.ownerMsid !== void 0 || b2.checkOwnerSession === true;
130509
130596
  const msid = String(b2.ownerMsid ?? "");
130510
130597
  const cookie = req.headers.cookie ?? "";
@@ -130652,7 +130739,7 @@ async function handleWebWix(req, res, state) {
130652
130739
  });
130653
130740
  }
130654
130741
  if (path2 === "/v1/__webwix/register" && req.method === "POST") {
130655
- const b2 = await readJson8();
130742
+ const b2 = await readJson9();
130656
130743
  try {
130657
130744
  const { memberToken, visitorToken } = await memberDirectRegister(
130658
130745
  auth.clientId,
@@ -131528,8 +131615,8 @@ function readActionHandlerManifest(app) {
131528
131615
  let decls;
131529
131616
  let bytes2;
131530
131617
  try {
131531
- decls = JSON.parse(readFileSync49(manifestPath, "utf8"));
131532
- bytes2 = readFileSync49(bundlePath);
131618
+ decls = JSON.parse(readFileSync50(manifestPath, "utf8"));
131619
+ bytes2 = readFileSync50(bundlePath);
131533
131620
  } catch {
131534
131621
  return { handlers: [] };
131535
131622
  }
@@ -131812,6 +131899,25 @@ function createDevServer(opts = {}) {
131812
131899
  try {
131813
131900
  await maybeReseedNetMocks(state);
131814
131901
  if (url.startsWith("/__dev/")) return await handleDev(req, res, state);
131902
+ if (isTenantHost(state.appName)) {
131903
+ const prefixed = tenantPrefixed(url, state.appName, req.method);
131904
+ const tenant = prefixed?.tenant ?? (shouldServeFromPlane(url, req.headers, state.appName) && !isTenantAdminPath(url) ? targetTenant(url, req.headers, state.appName) : null);
131905
+ if (tenant) {
131906
+ const upstream = resolveTenantBase(tenant);
131907
+ if (!upstream) {
131908
+ return sendJson(res, 503, {
131909
+ error: "tenant_upstream_unconfigured",
131910
+ tenant,
131911
+ hint: "Start the tenant's dev-server, or set HIMALAYA_DEV_TENANT_UPSTREAMS=<app>=<url>."
131912
+ }, { "access-control-allow-origin": "*" });
131913
+ }
131914
+ const clientHost = req.headers.host ?? "";
131915
+ return await proxyToServe(upstream, req, res, {
131916
+ url: prefixed?.url,
131917
+ forwardAs: clientHost ? { host: clientHost, prefix: `${TENANT_PREFIX}${encodeURIComponent(tenant)}` } : void 0
131918
+ });
131919
+ }
131920
+ }
131815
131921
  if (url.split("?")[0] === "/v1/app-icon" && req.method === "GET") {
131816
131922
  const iconApp = new URLSearchParams(url.split("?")[1] ?? "").get("app") ?? "";
131817
131923
  const iconDir = iconApp ? state.app && iconApp === state.app.name ? state.app.dir : resolveAppDir(iconApp) : null;
@@ -131827,7 +131933,7 @@ function createDevServer(opts = {}) {
131827
131933
  const q2 = new URLSearchParams(url.split("?")[1] ?? "");
131828
131934
  const assetApp = q2.get("app") ?? state.appName;
131829
131935
  const assetDir = state.app && assetApp === state.app.name ? state.app.dir : resolveAppDir(assetApp);
131830
- const hit = assetDir ? collectAssets(assetDir).find((a2) => assetSha256(readFileSync49(a2.path)) === sha2) : void 0;
131936
+ const hit = assetDir ? collectAssets(assetDir).find((a2) => assetSha256(readFileSync50(a2.path)) === sha2) : void 0;
131831
131937
  if (!hit && assetDir) {
131832
131938
  const fontBytes = await fontFaceBytesBySha(assetDir, sha2);
131833
131939
  if (fontBytes) {
@@ -131850,7 +131956,7 @@ function createDevServer(opts = {}) {
131850
131956
  res.end(JSON.stringify({ error: "asset_not_found", app: assetApp, sha: sha2 }));
131851
131957
  return;
131852
131958
  }
131853
- const bytes2 = readFileSync49(hit.path);
131959
+ const bytes2 = readFileSync50(hit.path);
131854
131960
  res.writeHead(200, {
131855
131961
  "content-type": hit.contentType,
131856
131962
  "content-length": String(bytes2.length),
@@ -131943,7 +132049,7 @@ function createDevServer(opts = {}) {
131943
132049
  if (url === "/v1/schema/screen-descriptor.json" && req.method === "GET") {
131944
132050
  try {
131945
132051
  const schemaPath = resolve37(ROOT6, "core/schema/generated/screen-descriptor.schema.json");
131946
- const body = readFileSync49(schemaPath, "utf8");
132052
+ const body = readFileSync50(schemaPath, "utf8");
131947
132053
  return send(res, 200, body, {
131948
132054
  "content-type": "application/schema+json; charset=utf-8",
131949
132055
  "cache-control": "no-store",
@@ -131994,7 +132100,7 @@ function createDevServer(opts = {}) {
131994
132100
  try {
131995
132101
  const { parseRevocationsYaml: parseRevocationsYaml2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
131996
132102
  revoked = parseRevocationsYaml2(
131997
- readFileSync49(resolve37(state.app.dir, "revocations.yaml"), "utf8")
132103
+ readFileSync50(resolve37(state.app.dir, "revocations.yaml"), "utf8")
131998
132104
  ).revoked;
131999
132105
  } catch {
132000
132106
  }
@@ -132009,7 +132115,8 @@ function createDevServer(opts = {}) {
132009
132115
  if (url.startsWith("/v1/app-config/") && req.method === "GET") {
132010
132116
  const override = effectiveAppConfigOverride(state);
132011
132117
  return handleAppConfigRequest(req, res, state.app.meta, override, {
132012
- serverBaseUrl: state.serverBaseUrl,
132118
+ // Through a tenant host's proxy, the nav bundle routes back through that host, as screens do.
132119
+ serverBaseUrl: forwardedBaseUrl(req) ?? state.serverBaseUrl,
132013
132120
  bundleIntegrity: (name) => bundleIntegritySync(name, state.tier5Dir)
132014
132121
  });
132015
132122
  }
@@ -132020,7 +132127,7 @@ function createDevServer(opts = {}) {
132020
132127
  const hit = appRoutes[routePath] ?? Object.entries(appRoutes).sort((a2, b2) => b2[0].length - a2[0].length).find(([p2]) => routePath.startsWith(p2))?.[1];
132021
132128
  if (hit) {
132022
132129
  const reqHost = req.headers.host;
132023
- const serverBaseUrl = reqHost ? `http://${reqHost}` : state.serverBaseUrl;
132130
+ const serverBaseUrl = forwardedBaseUrl(req) ?? (reqHost ? `http://${reqHost}` : state.serverBaseUrl);
132024
132131
  return await hit(req, res, { store: state.moduleStore, serverBaseUrl });
132025
132132
  }
132026
132133
  }
@@ -132249,7 +132356,7 @@ var init_src6 = __esm({
132249
132356
  init_kits();
132250
132357
  init_widgets();
132251
132358
  init_descriptor_postprocess();
132252
- ROOT6 = resolve37(fileURLToPath20(new URL("../../..", import.meta.url)));
132359
+ ROOT6 = resolve37(fileURLToPath21(new URL("../../..", import.meta.url)));
132253
132360
  setPngFontCss(async (tokens2, idiomContext) => await pngFontFaceCss(tokens2) + (idiomContext ? await idiomFontFaceCss(idiomContext) : ""));
132254
132361
  TIER3_ROOT = resolve37(ROOT6, "core/dev-server/web");
132255
132362
  TIER4_ROOT = resolve37(ROOT6, "core/dev-server/tier4-bundles");
@@ -135430,9 +135537,9 @@ __export(build_exports2, {
135430
135537
  withoutDevOnlyAppConfig: () => withoutDevOnlyAppConfig
135431
135538
  });
135432
135539
  import { createHash as createHash24 } from "node:crypto";
135433
- import { readFileSync as readFileSync50, readdirSync as readdirSync24, existsSync as existsSync46 } from "node:fs";
135434
- import { dirname as dirname29, join as join45, resolve as resolve38 } from "node:path";
135435
- import { fileURLToPath as fileURLToPath21 } from "node:url";
135540
+ import { readFileSync as readFileSync51, readdirSync as readdirSync24, existsSync as existsSync46 } from "node:fs";
135541
+ import { dirname as dirname30, join as join46, resolve as resolve38 } from "node:path";
135542
+ import { fileURLToPath as fileURLToPath22 } from "node:url";
135436
135543
  import { createRequire as createRequire2 } from "node:module";
135437
135544
  import { execFileSync as execFileSync4 } from "node:child_process";
135438
135545
  import { gzipSync } from "node:zlib";
@@ -135473,10 +135580,10 @@ function l10nLintOptions(locale, appDir3) {
135473
135580
  const tags = (locale.translations ?? []).filter((t2) => t2 !== locale.default);
135474
135581
  const catalog3 = /* @__PURE__ */ new Set();
135475
135582
  for (const tag of tags) {
135476
- const path2 = join45(appDir3, "l10n", `${tag}.json`);
135583
+ const path2 = join46(appDir3, "l10n", `${tag}.json`);
135477
135584
  if (!existsSync46(path2)) continue;
135478
135585
  try {
135479
- const parsed = JSON.parse(readFileSync50(path2, "utf8"));
135586
+ const parsed = JSON.parse(readFileSync51(path2, "utf8"));
135480
135587
  for (const m2 of Object.values(parsed.messages ?? {})) {
135481
135588
  if (typeof m2?.source === "string" && typeof m2.translation === "string" && m2.translation.length > 0) {
135482
135589
  catalog3.add(m2.source);
@@ -135647,7 +135754,7 @@ function shellSha(root = REPO_ROOT7) {
135647
135754
  function isMonorepoCheckout(dir) {
135648
135755
  try {
135649
135756
  const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
135650
- return top.length > 0 && existsSync46(join45(top, "core", "schema", "core.proto"));
135757
+ return top.length > 0 && existsSync46(join46(top, "core", "schema", "core.proto"));
135651
135758
  } catch {
135652
135759
  return false;
135653
135760
  }
@@ -135834,7 +135941,7 @@ async function buildReleaseFromContent(contentDir2, dest, opts = {}) {
135834
135941
  function readTokensForLint(preloaded) {
135835
135942
  try {
135836
135943
  const tokenPath = preloaded.module.designTokensPath ?? resolve38(preloaded.dir, uiConfig(preloaded.module.config).designTokensPath ?? "tokens.json");
135837
- const parsed = JSON.parse(readFileSync50(tokenPath, "utf8"));
135944
+ const parsed = JSON.parse(readFileSync51(tokenPath, "utf8"));
135838
135945
  delete parsed._meta;
135839
135946
  return parsed;
135840
135947
  } catch {
@@ -135845,18 +135952,18 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
135845
135952
  const app = preloaded.name;
135846
135953
  const tier5Dir = opts.tier5Dir ?? TIER5_DIR;
135847
135954
  const bundlePath = (name) => {
135848
- const own4 = join45(tier5Dir, `${name}.bundle.js`);
135955
+ const own4 = join46(tier5Dir, `${name}.bundle.js`);
135849
135956
  if (existsSync46(own4)) return own4;
135850
- const shared = join45(TIER5_DIR, `${name}.bundle.js`);
135957
+ const shared = join46(TIER5_DIR, `${name}.bundle.js`);
135851
135958
  return resolve38(tier5Dir) !== TIER5_DIR && existsSync46(shared) ? shared : void 0;
135852
135959
  };
135853
135960
  const bundleDirFor = (name) => {
135854
135961
  const path2 = name ? bundlePath(name) : void 0;
135855
- return path2 ? dirname29(path2) : tier5Dir;
135962
+ return path2 ? dirname30(path2) : tier5Dir;
135856
135963
  };
135857
135964
  const readBundle = (name) => {
135858
135965
  const path2 = bundlePath(name);
135859
- return path2 ? readFileSync50(path2, "utf8") : void 0;
135966
+ return path2 ? readFileSync51(path2, "utf8") : void 0;
135860
135967
  };
135861
135968
  const collect2 = opts.collect;
135862
135969
  const config = preloaded.module.config;
@@ -136001,12 +136108,12 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136001
136108
  return { services, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved: mockUnserved ?? [] } : {}, ...mockBootFailed ? { mockBootFailed } : {} };
136002
136109
  };
136003
136110
  checkRegistry(preloaded.module.actions);
136004
- const contentManifestPath2 = join45(preloaded.dir, "himalaya.content.json");
136005
- const contentManifest = existsSync46(contentManifestPath2) ? JSON.parse(readFileSync50(contentManifestPath2, "utf8")) : void 0;
136111
+ const contentManifestPath2 = join46(preloaded.dir, "himalaya.content.json");
136112
+ const contentManifest = existsSync46(contentManifestPath2) ? JSON.parse(readFileSync51(contentManifestPath2, "utf8")) : void 0;
136006
136113
  let screenMetadata = parseScreenMetadata(contentManifest?.screens);
136007
136114
  if (contentManifest?.shell === "brandy" && screenMetadata) {
136008
- const provisioningPath2 = join45(preloaded.dir, "provisioning.json");
136009
- if (existsSync46(provisioningPath2)) screenMetadata = siteViewMetadataForBuild(screenMetadata, JSON.parse(readFileSync50(provisioningPath2, "utf8")).site);
136115
+ const provisioningPath2 = join46(preloaded.dir, "provisioning.json");
136116
+ if (existsSync46(provisioningPath2)) screenMetadata = siteViewMetadataForBuild(screenMetadata, JSON.parse(readFileSync51(provisioningPath2, "utf8")).site);
136010
136117
  }
136011
136118
  await store.reset(app);
136012
136119
  const bundles = {};
@@ -136043,7 +136150,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136043
136150
  try {
136044
136151
  const path2 = bundlePath(name);
136045
136152
  if (!path2) return null;
136046
- bytes2 = readFileSync50(path2);
136153
+ bytes2 = readFileSync51(path2);
136047
136154
  } catch {
136048
136155
  return null;
136049
136156
  }
@@ -136065,9 +136172,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136065
136172
  const MAX_AUTHORING_DOC_BYTES = 128 * 1024;
136066
136173
  if (store.putDoc) {
136067
136174
  for (const [name, file2] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
136068
- const path2 = join45(preloaded.dir, file2);
136175
+ const path2 = join46(preloaded.dir, file2);
136069
136176
  if (!existsSync46(path2)) continue;
136070
- const bytes2 = readFileSync50(path2);
136177
+ const bytes2 = readFileSync51(path2);
136071
136178
  if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
136072
136179
  throw new Error(`${file2} must be non-empty and at most ${MAX_AUTHORING_DOC_BYTES} bytes to ship with a release.`);
136073
136180
  }
@@ -136082,7 +136189,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136082
136189
  const iconPath = resolveAppDirIcon(preloaded.dir);
136083
136190
  if (iconPath) {
136084
136191
  try {
136085
- const bytes2 = readFileSync50(iconPath);
136192
+ const bytes2 = readFileSync51(iconPath);
136086
136193
  await store.putIcon(app, bytes2);
136087
136194
  iconHash = sha2564(bytes2);
136088
136195
  } catch {
@@ -136104,7 +136211,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136104
136211
  }
136105
136212
  const seenAssetSha = /* @__PURE__ */ new Set();
136106
136213
  for (const a2 of collected) {
136107
- const bytes2 = readFileSync50(a2.path);
136214
+ const bytes2 = readFileSync51(a2.path);
136108
136215
  const hash2 = sha2564(bytes2);
136109
136216
  if (!seenAssetSha.has(hash2)) {
136110
136217
  await store.putAsset(app, hash2, bytes2, a2.contentType);
@@ -136126,7 +136233,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136126
136233
  const fontWarnings = [];
136127
136234
  try {
136128
136235
  const appTokens = readTokensForLint(preloaded) ?? {};
136129
- const policy = existsSync46(join45(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync50(join45(preloaded.dir, "fonts.json"), "utf8")) : {};
136236
+ const policy = existsSync46(join46(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync51(join46(preloaded.dir, "fonts.json"), "utf8")) : {};
136130
136237
  fontPlan = planFonts(appTokens, policy);
136131
136238
  } catch (err) {
136132
136239
  throw new Error(
@@ -136142,7 +136249,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136142
136249
  `[release-build] ${family.name} face ${face.postScriptName} has no local bytes (sha ${face.sha256.slice(0, 12)}\u2026), so the release would declare a face the asset route cannot serve. Run \`npm run fonts:catalog\` to warm the cache before publishing.`
136143
136250
  );
136144
136251
  }
136145
- const bytes2 = readFileSync50(src);
136252
+ const bytes2 = readFileSync51(src);
136146
136253
  const hash2 = sha2564(bytes2);
136147
136254
  if (hash2 !== face.sha256) {
136148
136255
  throw new Error(
@@ -136192,7 +136299,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136192
136299
  if (store.putAsset) {
136193
136300
  for (const face of collectBrandFonts(preloaded.dir)) {
136194
136301
  try {
136195
- const bytes2 = readFileSync50(face.path);
136302
+ const bytes2 = readFileSync51(face.path);
136196
136303
  if (bytes2.length === 0) continue;
136197
136304
  const hash2 = sha2564(bytes2);
136198
136305
  await store.putAsset(app, hash2, bytes2, "font/ttf");
@@ -136648,10 +136755,10 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
136648
136755
  await store.reset(app);
136649
136756
  const sources = {};
136650
136757
  for (const definition of config.functions.functions) {
136651
- const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join45(preloaded.dir, "functions", `${definition.name}${extension}`));
136758
+ const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join46(preloaded.dir, "functions", `${definition.name}${extension}`));
136652
136759
  const source = candidates.find((candidate) => existsSync46(candidate));
136653
136760
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
136654
- sources[definition.name] = readFileSync50(source, "utf8");
136761
+ sources[definition.name] = readFileSync51(source, "utf8");
136655
136762
  }
136656
136763
  const built = await buildFunctions(config.functions.functions, sources);
136657
136764
  const bundles = {};
@@ -136679,7 +136786,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
136679
136786
  return { manifest, failedToBuild: [], missingBundles: [], auth: {}, tierCapViolations: [] };
136680
136787
  }
136681
136788
  function listBuildableApps() {
136682
- const appsDir = join45(REPO_ROOT7, "apps");
136789
+ const appsDir = join46(REPO_ROOT7, "apps");
136683
136790
  return readdirSync24(appsDir, { withFileTypes: true }).filter((d2) => d2.isDirectory() && !d2.name.startsWith("_")).map((d2) => d2.name);
136684
136791
  }
136685
136792
  var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL;
@@ -136719,10 +136826,10 @@ var init_build3 = __esm({
136719
136826
  BAKE_OFFLINE_BASE = "http://himalaya-bake.invalid";
136720
136827
  KNOWN_ICON_NAMES = [...ICON_NAMES].sort();
136721
136828
  KNOWN_ICONS = new Set(KNOWN_ICON_NAMES);
136722
- REPO_ROOT7 = resolve38(dirname29(fileURLToPath21(import.meta.url)), "../..");
136723
- TIER5_DIR = join45(REPO_ROOT7, "core/dev-server/tier5-bundles");
136829
+ REPO_ROOT7 = resolve38(dirname30(fileURLToPath22(import.meta.url)), "../..");
136830
+ TIER5_DIR = join46(REPO_ROOT7, "core/dev-server/tier5-bundles");
136724
136831
  requireFromHere = createRequire2(import.meta.url);
136725
- SOURCEMAP_ON_DEMAND_PATH = join45(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
136832
+ SOURCEMAP_ON_DEMAND_PATH = join46(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
136726
136833
  BAKED_SERVER_BASE_URL = "http://baked.himalaya.invalid";
136727
136834
  }
136728
136835
  });
@@ -137282,8 +137389,8 @@ __export(build_changes_exports, {
137282
137389
  diffTokens: () => diffTokens,
137283
137390
  headline: () => headline
137284
137391
  });
137285
- import { existsSync as existsSync47, readdirSync as readdirSync25, readFileSync as readFileSync51 } from "node:fs";
137286
- import { join as join46 } from "node:path";
137392
+ import { existsSync as existsSync47, readdirSync as readdirSync25, readFileSync as readFileSync52 } from "node:fs";
137393
+ import { join as join47 } from "node:path";
137287
137394
  function componentsOf(descriptor) {
137288
137395
  const out2 = /* @__PURE__ */ new Map();
137289
137396
  visitComponents(descriptor, (n2) => {
@@ -137354,13 +137461,13 @@ function describeChanges(oldTree, newTree, diff, opts = {}) {
137354
137461
  const after = screensIn(newTree);
137355
137462
  for (const id of diff.screens) {
137356
137463
  if (!after.has(id) || !before.has(id)) continue;
137357
- const was = readJson2(join46(oldTree, "screens", `${id}.json`));
137358
- const now = readJson2(join46(newTree, "screens", `${id}.json`));
137464
+ const was = readJson3(join47(oldTree, "screens", `${id}.json`));
137465
+ const now = readJson3(join47(newTree, "screens", `${id}.json`));
137359
137466
  const changes = diffDescriptors(id, was, now);
137360
137467
  if (changes.length) all.push(...changes);
137361
137468
  else all.push({ kind: JSON.stringify(was) === JSON.stringify(now) ? "logic" : "descriptor", screen: id });
137362
137469
  }
137363
- if (diff.tokens) all.push(...diffTokens(readJson2(join46(oldTree, "tokens.json")), readJson2(join46(newTree, "tokens.json"))));
137470
+ if (diff.tokens) all.push(...diffTokens(readJson3(join47(oldTree, "tokens.json")), readJson3(join47(newTree, "tokens.json"))));
137364
137471
  for (const id of [...after].sort()) if (!before.has(id)) all.push({ kind: "screen-added", screen: id });
137365
137472
  for (const id of [...before].sort()) if (!after.has(id)) all.push({ kind: "screen-removed", screen: id });
137366
137473
  const ranked = all.map((c2, i2) => ({ c: c2, i: i2 })).sort((x2, y2) => RANK[x2.c.kind] - RANK[y2.c.kind] || x2.i - y2.i).map((x2) => x2.c);
@@ -137410,7 +137517,7 @@ function lineOf2(c2) {
137410
137517
  return `screen removed: ${c2.screen}`;
137411
137518
  }
137412
137519
  }
137413
- var TEXT_PROPS, RANK, MAX_TEXT, MAX_ITEMS, cut, scalar2, readJson2, screensIn, HEX;
137520
+ var TEXT_PROPS, RANK, MAX_TEXT, MAX_ITEMS, cut, scalar2, readJson3, screensIn, HEX;
137414
137521
  var init_build_changes = __esm({
137415
137522
  "src/build-changes.ts"() {
137416
137523
  init_stable_ids();
@@ -137420,16 +137527,16 @@ var init_build_changes = __esm({
137420
137527
  MAX_ITEMS = 12;
137421
137528
  cut = (s2) => s2.length > MAX_TEXT ? `${s2.slice(0, MAX_TEXT - 1)}\u2026` : s2;
137422
137529
  scalar2 = (v2) => typeof v2 === "string" || typeof v2 === "number" || typeof v2 === "boolean";
137423
- readJson2 = (path2) => {
137530
+ readJson3 = (path2) => {
137424
137531
  try {
137425
- return JSON.parse(readFileSync51(path2, "utf8"));
137532
+ return JSON.parse(readFileSync52(path2, "utf8"));
137426
137533
  } catch {
137427
137534
  return void 0;
137428
137535
  }
137429
137536
  };
137430
137537
  screensIn = (tree) => {
137431
137538
  try {
137432
- return new Set(readdirSync25(join46(tree, "screens")).filter((f2) => f2.endsWith(".json")).map((f2) => f2.slice(0, -5)));
137539
+ return new Set(readdirSync25(join47(tree, "screens")).filter((f2) => f2.endsWith(".json")).map((f2) => f2.slice(0, -5)));
137433
137540
  } catch {
137434
137541
  return /* @__PURE__ */ new Set();
137435
137542
  }
@@ -137439,8 +137546,8 @@ var init_build_changes = __esm({
137439
137546
  });
137440
137547
 
137441
137548
  // src/studio-timeline.ts
137442
- import { existsSync as existsSync48, readFileSync as readFileSync52 } from "node:fs";
137443
- import { join as join47 } from "node:path";
137549
+ import { existsSync as existsSync48, readFileSync as readFileSync53 } from "node:fs";
137550
+ import { join as join48 } from "node:path";
137444
137551
  function stateOf(view) {
137445
137552
  const j2 = view.journal[0];
137446
137553
  const h2 = view.health;
@@ -137507,10 +137614,10 @@ function validFrame(f2) {
137507
137614
  return true;
137508
137615
  }
137509
137616
  function readTimeline(dir) {
137510
- const file2 = join47(dir, TIMELINE_FILE);
137617
+ const file2 = join48(dir, TIMELINE_FILE);
137511
137618
  if (!existsSync48(file2)) return [];
137512
137619
  const out2 = [];
137513
- for (const line of readFileSync52(file2, "utf8").split("\n")) {
137620
+ for (const line of readFileSync53(file2, "utf8").split("\n")) {
137514
137621
  if (!line.trim()) continue;
137515
137622
  try {
137516
137623
  const f2 = JSON.parse(line);
@@ -137527,14 +137634,14 @@ function trim(frames) {
137527
137634
  return frames.slice(-MAX_FRAMES);
137528
137635
  }
137529
137636
  function writeTimelineJs(dir, frames) {
137530
- writeFileAtomic(join47(dir, TIMELINE_JS), `window.__himiTimeline && window.__himiTimeline(${scriptJson(frames)});
137637
+ writeFileAtomic(join48(dir, TIMELINE_JS), `window.__himiTimeline && window.__himiTimeline(${scriptJson(frames)});
137531
137638
  `);
137532
137639
  }
137533
137640
  function appendFrame(dir, view, reveal = null) {
137534
137641
  const frames = readTimeline(dir);
137535
137642
  const last = frames[frames.length - 1];
137536
137643
  if (last && last.v === view.v && !reveal) {
137537
- if (!existsSync48(join47(dir, TIMELINE_JS))) writeTimelineJs(dir, frames);
137644
+ if (!existsSync48(join48(dir, TIMELINE_JS))) writeTimelineJs(dir, frames);
137538
137645
  return frames.length;
137539
137646
  }
137540
137647
  let prev = null;
@@ -137543,7 +137650,7 @@ function appendFrame(dir, view, reveal = null) {
137543
137650
  if (!frame.key && !reveal && Object.keys(frame).every((k2) => k2 === "ts" || k2 === "v")) return frames.length;
137544
137651
  if (reveal) frame.reveal = reveal;
137545
137652
  const kept = trim([...frames, frame]);
137546
- writeFileAtomic(join47(dir, TIMELINE_FILE), kept.map((f2) => JSON.stringify(f2)).join("\n") + "\n");
137653
+ writeFileAtomic(join48(dir, TIMELINE_FILE), kept.map((f2) => JSON.stringify(f2)).join("\n") + "\n");
137547
137654
  writeTimelineJs(dir, kept);
137548
137655
  return kept.length;
137549
137656
  }
@@ -137565,8 +137672,8 @@ var init_studio_timeline = __esm({
137565
137672
  "src/studio-timeline.ts"() {
137566
137673
  init_progress();
137567
137674
  init_studio_page();
137568
- TIMELINE_FILE = join47(".himi", "studio", "timeline.jsonl");
137569
- TIMELINE_JS = join47(".himi", "studio", "timeline.js");
137675
+ TIMELINE_FILE = join48(".himi", "studio", "timeline.jsonl");
137676
+ TIMELINE_JS = join48(".himi", "studio", "timeline.js");
137570
137677
  MAX_FRAMES = 2e3;
137571
137678
  KEYFRAME_EVERY = 50;
137572
137679
  same2 = (a2, b2) => JSON.stringify(a2) === JSON.stringify(b2);
@@ -137604,8 +137711,8 @@ __export(studio_exports, {
137604
137711
  writeStudioRecord: () => writeStudioRecord
137605
137712
  });
137606
137713
  import { createHash as createHash25 } from "node:crypto";
137607
- import { existsSync as existsSync49, readdirSync as readdirSync26, readFileSync as readFileSync53, realpathSync as realpathSync8, statSync as statSync10 } from "node:fs";
137608
- import { basename as basename11, extname as extname3, join as join48, relative as relative9, resolve as resolve39, sep as sep11 } from "node:path";
137714
+ import { existsSync as existsSync49, readdirSync as readdirSync26, readFileSync as readFileSync54, realpathSync as realpathSync8, statSync as statSync10 } from "node:fs";
137715
+ import { basename as basename11, extname as extname3, join as join49, relative as relative9, resolve as resolve39, sep as sep11 } from "node:path";
137609
137716
  import { pathToFileURL as pathToFileURL7 } from "node:url";
137610
137717
  function realInside(dir, abs) {
137611
137718
  try {
@@ -137630,12 +137737,12 @@ function archiveFile(dir, memory, abs) {
137630
137737
  if (size === 0) return null;
137631
137738
  const key2 = relative9(dir, abs);
137632
137739
  const hit = memory.files?.[key2];
137633
- if (hit && hit.size === size && hit.mtimeMs === mtimeMs && hit.ino === ino && existsSync49(join48(dir, HISTORY_DIR, `${hit.sha}.${hit.ext}`))) {
137740
+ if (hit && hit.size === size && hit.mtimeMs === mtimeMs && hit.ino === ino && existsSync49(join49(dir, HISTORY_DIR, `${hit.sha}.${hit.ext}`))) {
137634
137741
  return { sha: hit.sha, ext: hit.ext, file: `${hit.sha}.${hit.ext}` };
137635
137742
  }
137636
137743
  let archived;
137637
137744
  try {
137638
- archived = archiveBytes(dir, readFileSync53(real));
137745
+ archived = archiveBytes(dir, readFileSync54(real));
137639
137746
  } catch {
137640
137747
  return null;
137641
137748
  }
@@ -137644,17 +137751,17 @@ function archiveFile(dir, memory, abs) {
137644
137751
  return { sha: archived.sha256, ext: archived.ext, file: `${archived.sha256}.${archived.ext}` };
137645
137752
  }
137646
137753
  function loadMemory(dir, now) {
137647
- const raw = obj(readJson3(join48(dir, MEMORY_FILE)));
137754
+ const raw = obj(readJson4(join49(dir, MEMORY_FILE)));
137648
137755
  if (raw && raw.version === 1 && obj(raw.shots) && Array.isArray(raw.timeline)) return raw;
137649
137756
  return { version: 1, createdAt: now, shots: {}, timeline: [] };
137650
137757
  }
137651
137758
  function observeShots(dir, memory, now) {
137652
- const shotsDir = join48(dir, ".himi", "shots");
137759
+ const shotsDir = join49(dir, ".himi", "shots");
137653
137760
  const seen = /* @__PURE__ */ new Set();
137654
137761
  const files = existsSync49(shotsDir) ? readdirSync26(shotsDir).filter((f2) => /\.(png|jpe?g)$/i.test(f2)).sort() : [];
137655
137762
  for (const f2 of files) {
137656
137763
  const id = basename11(f2, extname3(f2));
137657
- const archived = archiveFile(dir, memory, join48(shotsDir, f2));
137764
+ const archived = archiveFile(dir, memory, join49(shotsDir, f2));
137658
137765
  if (!archived) continue;
137659
137766
  seen.add(id);
137660
137767
  const { sha: sha2, ext } = archived;
@@ -137676,7 +137783,7 @@ function observeShots(dir, memory, now) {
137676
137783
  return memory;
137677
137784
  }
137678
137785
  function palette(dir) {
137679
- const colors = obj(obj(readJson3(join48(dir, "tokens.json")))?.colors);
137786
+ const colors = obj(obj(readJson4(join49(dir, "tokens.json")))?.colors);
137680
137787
  if (!colors) return [];
137681
137788
  const pick2 = (key2) => {
137682
137789
  const v2 = colors[key2];
@@ -137686,7 +137793,7 @@ function palette(dir) {
137686
137793
  return ["accentPrimary", "accentSecondary", "accentSurface", "surfacePrimary", "textPrimary"].map(pick2).filter((x2) => !!x2);
137687
137794
  }
137688
137795
  function appIdentity(dir) {
137689
- const manifest = obj(readJson3(join48(dir, "himalaya.content.json")));
137796
+ const manifest = obj(readJson4(join49(dir, "himalaya.content.json")));
137690
137797
  const name = text(manifest?.name) ?? basename11(resolve39(dir));
137691
137798
  const icon = text(manifest?.icon)?.trim();
137692
137799
  const iconPath = icon ? resolve39(dir, icon) : null;
@@ -137694,12 +137801,12 @@ function appIdentity(dir) {
137694
137801
  return { name, iconFile: real && statSync10(real).isFile() ? iconPath : null };
137695
137802
  }
137696
137803
  function testRuns(dir) {
137697
- const att = join48(dir, ".himi", "attestations");
137804
+ const att = join49(dir, ".himi", "attestations");
137698
137805
  if (!existsSync49(att)) return [];
137699
137806
  const runs = [];
137700
137807
  for (const f2 of readdirSync26(att)) {
137701
137808
  if (!f2.endsWith(".json") || f2 === "latest.json") continue;
137702
- const r2 = obj(readJson3(join48(att, f2)));
137809
+ const r2 = obj(readJson4(join49(att, f2)));
137703
137810
  if (!r2 || r2.tool !== "himi-test" || typeof r2.runId !== "string") continue;
137704
137811
  const report3 = obj(r2.report);
137705
137812
  const coverage = obj(r2.coverage);
@@ -137715,20 +137822,20 @@ function testRuns(dir) {
137715
137822
  return runs.sort((a2, b2) => a2.runId.localeCompare(b2.runId));
137716
137823
  }
137717
137824
  function siteHome(dir) {
137718
- for (const pages2 of [join48(dir, ".himi", "business-book", "evidence", "pages"), join48(dir, "evidence", "pages")]) {
137825
+ for (const pages2 of [join49(dir, ".himi", "business-book", "evidence", "pages"), join49(dir, "evidence", "pages")]) {
137719
137826
  if (!existsSync49(pages2)) continue;
137720
137827
  const home = readdirSync26(pages2).filter((f2) => /^home.*\.(png|jpe?g)$/i.test(f2)).sort()[0];
137721
- if (home) return join48(pages2, home);
137828
+ if (home) return join49(pages2, home);
137722
137829
  }
137723
137830
  return null;
137724
137831
  }
137725
137832
  function uxStatuses(dir) {
137726
- const platforms = obj(obj(readJson3(join48(dir, ".himi", "ux-audit.json")))?.platforms);
137833
+ const platforms = obj(obj(readJson4(join49(dir, ".himi", "ux-audit.json")))?.platforms);
137727
137834
  if (!platforms) return [];
137728
137835
  return Object.entries(platforms).map(([platform, rec]) => ({ platform, status: text(obj(rec)?.status) ?? "" })).filter((p2) => p2.status);
137729
137836
  }
137730
137837
  function liveRun(dir) {
137731
- const rec = obj(readJson3(join48(dir, RUN_RECORD)));
137838
+ const rec = obj(readJson4(join49(dir, RUN_RECORD)));
137732
137839
  const url = text(rec?.url);
137733
137840
  const pid = rec?.pid;
137734
137841
  if (!url || !/^https?:\/\//i.test(url) || typeof pid !== "number") return null;
@@ -137838,9 +137945,9 @@ function buildView(dir, memory, now) {
137838
137945
  const runs = testRuns(dir);
137839
137946
  const last = runs[runs.length - 1];
137840
137947
  const prev = runs[runs.length - 2];
137841
- const validate4 = obj(readJson3(join48(dir, VALIDATE_RECORD)));
137842
- const push = obj(readJson3(join48(dir, PUSH_RECORD)));
137843
- const edges = readJson3(join48(dir, EDGES_RECORD));
137948
+ const validate4 = obj(readJson4(join49(dir, VALIDATE_RECORD)));
137949
+ const push = obj(readJson4(join49(dir, PUSH_RECORD)));
137950
+ const edges = readJson4(join49(dir, EDGES_RECORD));
137844
137951
  const nav = [];
137845
137952
  if (Array.isArray(edges)) {
137846
137953
  const seen = /* @__PURE__ */ new Set();
@@ -137879,7 +137986,7 @@ function buildView(dir, memory, now) {
137879
137986
  },
137880
137987
  brand: { site: siteImg },
137881
137988
  nav,
137882
- map: mapOf(readJson3(join48(dir, MAP_RECORD))),
137989
+ map: mapOf(readJson4(join49(dir, MAP_RECORD))),
137883
137990
  live: liveRun(dir),
137884
137991
  timelineFrames: 0,
137885
137992
  reveal: memory.reveal ?? null
@@ -137913,15 +138020,15 @@ function writeBoard(dir, now) {
137913
138020
  } catch {
137914
138021
  view.timelineFrames = 0;
137915
138022
  }
137916
- writeAtomic(join48(dir, MEMORY_FILE), JSON.stringify(memory));
137917
- writeAtomic(join48(dir, STATE_FILE), `window.__himiStudio && window.__himiStudio(${scriptJson(view)});
138023
+ writeAtomic(join49(dir, MEMORY_FILE), JSON.stringify(memory));
138024
+ writeAtomic(join49(dir, STATE_FILE), `window.__himiStudio && window.__himiStudio(${scriptJson(view)});
137918
138025
  `);
137919
- writeAtomic(join48(dir, STUDIO_PAGE), renderStudioHtml(view));
138026
+ writeAtomic(join49(dir, STUDIO_PAGE), renderStudioHtml(view));
137920
138027
  return view;
137921
138028
  }
137922
138029
  function refreshStudio(dir, now = /* @__PURE__ */ new Date()) {
137923
138030
  try {
137924
- if (!existsSync49(join48(dir, STUDIO_PAGE))) return { refreshed: false };
138031
+ if (!existsSync49(join49(dir, STUDIO_PAGE))) return { refreshed: false };
137925
138032
  return { refreshed: true, view: writeBoard(dir, now.toISOString()) };
137926
138033
  } catch {
137927
138034
  return { refreshed: false };
@@ -137929,18 +138036,18 @@ function refreshStudio(dir, now = /* @__PURE__ */ new Date()) {
137929
138036
  }
137930
138037
  function openStudio(dir, now = /* @__PURE__ */ new Date()) {
137931
138038
  const view = writeBoard(dir, now.toISOString());
137932
- const page = join48(dir, STUDIO_PAGE);
138039
+ const page = join49(dir, STUDIO_PAGE);
137933
138040
  return { page, url: pathToFileURL7(page).href, view };
137934
138041
  }
137935
138042
  function writeStudioRecord(dir, record2, value) {
137936
138043
  try {
137937
138044
  if (!realDirIn(dir, ".himi")) return;
137938
- writeAtomic(join48(dir, record2), `${JSON.stringify(value, null, 2)}
138045
+ writeAtomic(join49(dir, record2), `${JSON.stringify(value, null, 2)}
137939
138046
  `);
137940
138047
  } catch {
137941
138048
  }
137942
138049
  }
137943
- var STUDIO_DIR, STUDIO_PAGE, STATE_FILE, MEMORY_FILE, VALIDATE_RECORD, PUSH_RECORD, EDGES_RECORD, MAP_RECORD, RUN_RECORD, MAX_TIMELINE, MAX_JOURNAL, MAX_NAV_EDGES, readJson3, obj, num2, text, historyUrl, runTime, MAP_STATUSES, count, CHANGE_KINDS;
138050
+ var STUDIO_DIR, STUDIO_PAGE, STATE_FILE, MEMORY_FILE, VALIDATE_RECORD, PUSH_RECORD, EDGES_RECORD, MAP_RECORD, RUN_RECORD, MAX_TIMELINE, MAX_JOURNAL, MAX_NAV_EDGES, readJson4, obj, num2, text, historyUrl, runTime, MAP_STATUSES, count, CHANGE_KINDS;
137944
138051
  var init_studio = __esm({
137945
138052
  "src/studio.ts"() {
137946
138053
  init_studio_page();
@@ -137949,21 +138056,21 @@ var init_studio = __esm({
137949
138056
  init_studio_timeline();
137950
138057
  init_progress();
137951
138058
  init_studio_page();
137952
- STUDIO_DIR = join48(".himi", "studio");
137953
- STUDIO_PAGE = join48(STUDIO_DIR, "index.html");
137954
- STATE_FILE = join48(STUDIO_DIR, "state.js");
137955
- MEMORY_FILE = join48(STUDIO_DIR, "memory.json");
137956
- VALIDATE_RECORD = join48(".himi", "validate.json");
137957
- PUSH_RECORD = join48(".himi", "last-push.json");
137958
- EDGES_RECORD = join48(".himi", "test-edges.json");
137959
- MAP_RECORD = join48(".himi", "test-map.json");
137960
- RUN_RECORD = join48(".himi", "run.json");
138059
+ STUDIO_DIR = join49(".himi", "studio");
138060
+ STUDIO_PAGE = join49(STUDIO_DIR, "index.html");
138061
+ STATE_FILE = join49(STUDIO_DIR, "state.js");
138062
+ MEMORY_FILE = join49(STUDIO_DIR, "memory.json");
138063
+ VALIDATE_RECORD = join49(".himi", "validate.json");
138064
+ PUSH_RECORD = join49(".himi", "last-push.json");
138065
+ EDGES_RECORD = join49(".himi", "test-edges.json");
138066
+ MAP_RECORD = join49(".himi", "test-map.json");
138067
+ RUN_RECORD = join49(".himi", "run.json");
137961
138068
  MAX_TIMELINE = 500;
137962
138069
  MAX_JOURNAL = 80;
137963
138070
  MAX_NAV_EDGES = 40;
137964
- readJson3 = (file2) => {
138071
+ readJson4 = (file2) => {
137965
138072
  try {
137966
- return JSON.parse(readFileSync53(file2, "utf8"));
138073
+ return JSON.parse(readFileSync54(file2, "utf8"));
137967
138074
  } catch {
137968
138075
  return null;
137969
138076
  }
@@ -138527,11 +138634,11 @@ __export(captcha_exports, {
138527
138634
  captchaContentInput: () => captchaContentInput,
138528
138635
  runCaptcha: () => runCaptcha
138529
138636
  });
138530
- import { readFileSync as readFileSync54 } from "node:fs";
138637
+ import { readFileSync as readFileSync55 } from "node:fs";
138531
138638
  import { resolve as resolve40 } from "node:path";
138532
138639
  function readObject(path2) {
138533
138640
  try {
138534
- return JSON.parse(readFileSync54(path2, "utf8"));
138641
+ return JSON.parse(readFileSync55(path2, "utf8"));
138535
138642
  } catch {
138536
138643
  return {};
138537
138644
  }
@@ -138601,7 +138708,7 @@ __export(preflight_exports, {
138601
138708
  parseStoreConfig: () => parseStoreConfig,
138602
138709
  requireEnv: () => requireEnv
138603
138710
  });
138604
- import { existsSync as existsSync50, readFileSync as readFileSync55 } from "node:fs";
138711
+ import { existsSync as existsSync50, readFileSync as readFileSync56 } from "node:fs";
138605
138712
  import { isAbsolute as isAbsolute4, relative as relative10, resolve as resolve41 } from "node:path";
138606
138713
  function isInsideRepo(p2) {
138607
138714
  const rel = relative10(REPO_ROOT3, resolve41(p2));
@@ -138661,7 +138768,7 @@ function loadStoreConfig(app) {
138661
138768
  if (!existsSync50(p2)) {
138662
138769
  throw new Error(`No store config at ${p2}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
138663
138770
  }
138664
- return parseStoreConfig(readFileSync55(p2, "utf8"));
138771
+ return parseStoreConfig(readFileSync56(p2, "utf8"));
138665
138772
  }
138666
138773
  var init_preflight = __esm({
138667
138774
  "../store-release/preflight.ts"() {
@@ -145390,11 +145497,11 @@ var init_customer_signing_inspect = __esm({
145390
145497
  });
145391
145498
 
145392
145499
  // src/push-onboarding.ts
145393
- import { existsSync as existsSync51, mkdirSync as mkdirSync24, readFileSync as readFileSync56, statSync as statSync11, writeFileSync as writeFileSync20, chmodSync as chmodSync2 } from "node:fs";
145394
- import { basename as basename12, dirname as dirname30, join as join49, resolve as resolve42 } from "node:path";
145395
- function readJson4(path2) {
145500
+ import { existsSync as existsSync51, mkdirSync as mkdirSync24, readFileSync as readFileSync57, statSync as statSync11, writeFileSync as writeFileSync20, chmodSync as chmodSync2 } from "node:fs";
145501
+ import { basename as basename12, dirname as dirname31, join as join50, resolve as resolve42 } from "node:path";
145502
+ function readJson5(path2) {
145396
145503
  try {
145397
- const parsed = JSON.parse(readFileSync56(path2, "utf8"));
145504
+ const parsed = JSON.parse(readFileSync57(path2, "utf8"));
145398
145505
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
145399
145506
  } catch {
145400
145507
  return {};
@@ -145402,9 +145509,9 @@ function readJson4(path2) {
145402
145509
  }
145403
145510
  function pushInputsFromContent(dir) {
145404
145511
  const root = resolve42(dir);
145405
- if (!existsSync51(join49(root, "himalaya.content.json"))) return { initialized: false };
145406
- const content = readJson4(join49(root, "himalaya.content.json"));
145407
- const provisioning = readJson4(join49(root, "provisioning.json"));
145512
+ if (!existsSync51(join50(root, "himalaya.content.json"))) return { initialized: false };
145513
+ const content = readJson5(join50(root, "himalaya.content.json"));
145514
+ const provisioning = readJson5(join50(root, "provisioning.json"));
145408
145515
  const native = provisioning.native ?? {};
145409
145516
  return {
145410
145517
  initialized: true,
@@ -145479,7 +145586,7 @@ function readKeyFile(path2) {
145479
145586
  }
145480
145587
  let body;
145481
145588
  try {
145482
- body = readFileSync56(path2, "utf8");
145589
+ body = readFileSync57(path2, "utf8");
145483
145590
  } catch {
145484
145591
  return { ok: false, code: "key_file_unreadable", reason: "cannot read the selected key file; check its path and file permissions" };
145485
145592
  }
@@ -145533,14 +145640,14 @@ function buildPushSetupBody(i2, keys) {
145533
145640
  };
145534
145641
  }
145535
145642
  function readPushOnboarding(dir) {
145536
- const path2 = join49(resolve42(dir), PUSH_ONBOARDING_PATH);
145643
+ const path2 = join50(resolve42(dir), PUSH_ONBOARDING_PATH);
145537
145644
  if (!existsSync51(path2)) return { version: 1 };
145538
- const parsed = readJson4(path2);
145645
+ const parsed = readJson5(path2);
145539
145646
  return { version: 1, ...parsed };
145540
145647
  }
145541
145648
  function writeFile(dir, file2) {
145542
- const path2 = join49(resolve42(dir), PUSH_ONBOARDING_PATH);
145543
- mkdirSync24(dirname30(path2), { recursive: true, mode: 448 });
145649
+ const path2 = join50(resolve42(dir), PUSH_ONBOARDING_PATH);
145650
+ mkdirSync24(dirname31(path2), { recursive: true, mode: 448 });
145544
145651
  writeFileSync20(path2, JSON.stringify(file2, null, 2) + "\n", { mode: 384 });
145545
145652
  try {
145546
145653
  chmodSync2(path2, 384);
@@ -145568,7 +145675,7 @@ function recordPushDeferral(dir, d2) {
145568
145675
  return push;
145569
145676
  }
145570
145677
  function clearPushDeferral(dir) {
145571
- const path2 = join49(resolve42(dir), PUSH_ONBOARDING_PATH);
145678
+ const path2 = join50(resolve42(dir), PUSH_ONBOARDING_PATH);
145572
145679
  if (!existsSync51(path2)) return;
145573
145680
  const { push: _dropped, ...rest } = readPushOnboarding(dir);
145574
145681
  writeFile(dir, { ...rest, version: 1 });
@@ -145637,7 +145744,7 @@ var signing_inspect_exports = {};
145637
145744
  __export(signing_inspect_exports, {
145638
145745
  runSigningInspect: () => runSigningInspect
145639
145746
  });
145640
- import { existsSync as existsSync52, readFileSync as readFileSync57, statSync as statSync12 } from "node:fs";
145747
+ import { existsSync as existsSync52, readFileSync as readFileSync58, statSync as statSync12 } from "node:fs";
145641
145748
  import { isAbsolute as isAbsolute5, resolve as resolve43 } from "node:path";
145642
145749
  function fail3(io2, code, fields = {}) {
145643
145750
  io2.error(JSON.stringify({ ok: false, code, ...fields }));
@@ -145734,9 +145841,9 @@ async function runSigningInspect(pos, flags, io2, deps = {}) {
145734
145841
  return fail3(io2, "signing_inspect_local_assets_unreadable", { error: "cert or profile file is unexpectedly large" });
145735
145842
  }
145736
145843
  assets = {
145737
- certificate: readFileSync57(certPath),
145844
+ certificate: readFileSync58(certPath),
145738
145845
  certificatePassword: text4(flags["cert-password"]),
145739
- provisioningProfile: readFileSync57(profilePath2)
145846
+ provisioningProfile: readFileSync58(profilePath2)
145740
145847
  };
145741
145848
  }
145742
145849
  try {
@@ -145885,7 +145992,7 @@ var init_hosted_owner = __esm({
145885
145992
 
145886
145993
  // src/config-source-edit.ts
145887
145994
  import { lstatSync as lstatSync14 } from "node:fs";
145888
- import { join as join50 } from "node:path";
145995
+ import { join as join51 } from "node:path";
145889
145996
  import ts5 from "typescript";
145890
145997
  function defineAppLiteral(file2) {
145891
145998
  for (const statement of file2.statements) {
@@ -145984,7 +146091,7 @@ function backUpConfig(dir, folder, fileName, original) {
145984
146091
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
145985
146092
  const backupDir = realDirIn(dir, `.himi/${folder}/${stamp}`);
145986
146093
  if (!backupDir) return void 0;
145987
- const backup = join50(backupDir, fileName);
146094
+ const backup = join51(backupDir, fileName);
145988
146095
  writeFileAtomic(backup, original);
145989
146096
  return backup;
145990
146097
  }
@@ -146021,7 +146128,7 @@ __export(config_push_edit_exports, {
146021
146128
  enablePushInConfig: () => enablePushInConfig,
146022
146129
  previewPushConfigEdit: () => previewPushConfigEdit
146023
146130
  });
146024
- import { readFileSync as readFileSync58 } from "node:fs";
146131
+ import { readFileSync as readFileSync59 } from "node:fs";
146025
146132
  import { basename as basename13 } from "node:path";
146026
146133
  import ts6 from "typescript";
146027
146134
  function enablePushInConfig(source, options) {
@@ -146141,7 +146248,7 @@ function noLiteralInstruction(pingAppName) {
146141
146248
  function previewPushConfigEdit(dir, options) {
146142
146249
  const path2 = configEntry(dir);
146143
146250
  if (!path2) return void 0;
146144
- const { applied, instructions } = enablePushInConfig(readFileSync58(path2, "utf8"), { ...options, fileName: basename13(path2) });
146251
+ const { applied, instructions } = enablePushInConfig(readFileSync59(path2, "utf8"), { ...options, fileName: basename13(path2) });
146145
146252
  return { wouldApply: applied, instructions };
146146
146253
  }
146147
146254
  async function applyPushConfigEdit(dir, options, validate4) {
@@ -146150,7 +146257,7 @@ async function applyPushConfigEdit(dir, options, validate4) {
146150
146257
  const fileName = basename13(path2);
146151
146258
  const refuse7 = (why) => ({ changed: false, pushOn: false, applied: [], instructions: [why] });
146152
146259
  if (isSymlink2(path2)) return refuse7(`${fileName} is a symlink, so it was not edited: turn push on in the file it points to.`);
146153
- const original = readFileSync58(path2, "utf8");
146260
+ const original = readFileSync59(path2, "utf8");
146154
146261
  const edit = enablePushInConfig(original, { ...options, fileName });
146155
146262
  const { applied, instructions, pushOn } = edit;
146156
146263
  if (!edit.changed) return { changed: false, pushOn, applied, instructions };
@@ -146470,8 +146577,8 @@ __export(pack_exports, {
146470
146577
  });
146471
146578
  import { createHash as createHash28 } from "node:crypto";
146472
146579
  import { deflateRawSync, inflateRawSync } from "node:zlib";
146473
- import { existsSync as existsSync53, mkdirSync as mkdirSync25, readFileSync as readFileSync59, readdirSync as readdirSync27, rmSync as rmSync12, statSync as statSync13, writeFileSync as writeFileSync21 } from "node:fs";
146474
- import { dirname as dirname31, join as join51, resolve as resolve45 } from "node:path";
146580
+ import { existsSync as existsSync53, mkdirSync as mkdirSync25, readFileSync as readFileSync60, readdirSync as readdirSync27, rmSync as rmSync12, statSync as statSync13, writeFileSync as writeFileSync21 } from "node:fs";
146581
+ import { dirname as dirname32, join as join52, resolve as resolve45 } from "node:path";
146475
146582
  function writeZip(entries) {
146476
146583
  const sorted2 = entries.slice().sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
146477
146584
  const total = sorted2.reduce((n2, e2) => n2 + e2.bytes.length, 0);
@@ -146565,13 +146672,13 @@ function inflateEntry(buf, entry) {
146565
146672
  return bytes2;
146566
146673
  }
146567
146674
  function readIf(path2) {
146568
- return existsSync53(path2) && statSync13(path2).isFile() ? readFileSync59(path2) : null;
146675
+ return existsSync53(path2) && statSync13(path2).isFile() ? readFileSync60(path2) : null;
146569
146676
  }
146570
146677
  function listDir(dir) {
146571
- return existsSync53(dir) ? readdirSync27(dir).filter((f2) => statSync13(join51(dir, f2)).isFile()) : [];
146678
+ return existsSync53(dir) ? readdirSync27(dir).filter((f2) => statSync13(join52(dir, f2)).isFile()) : [];
146572
146679
  }
146573
146680
  function gatherReleaseEntries(appDir3) {
146574
- const manifestPath = join51(appDir3, HIMI_PACKAGE_MANIFEST_PATH);
146681
+ const manifestPath = join52(appDir3, HIMI_PACKAGE_MANIFEST_PATH);
146575
146682
  const manifestBytes = readIf(manifestPath);
146576
146683
  if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir3} \u2014 build a release there first`);
146577
146684
  const manifest = JSON.parse(manifestBytes.toString("utf8"));
@@ -146595,7 +146702,7 @@ function gatherReleaseEntries(appDir3) {
146595
146702
  }
146596
146703
  const missing = [];
146597
146704
  for (const rel of wanted) {
146598
- const bytes2 = readIf(join51(appDir3, rel));
146705
+ const bytes2 = readIf(join52(appDir3, rel));
146599
146706
  if (bytes2) entries.push({ path: rel, bytes: bytes2 });
146600
146707
  else missing.push(rel);
146601
146708
  }
@@ -146606,12 +146713,12 @@ function gatherReleaseEntries(appDir3) {
146606
146713
  );
146607
146714
  }
146608
146715
  for (const name of SINGLETONS) {
146609
- const bytes2 = readIf(join51(appDir3, name));
146716
+ const bytes2 = readIf(join52(appDir3, name));
146610
146717
  if (bytes2) entries.push({ path: name, bytes: bytes2 });
146611
146718
  }
146612
146719
  const skipped = [];
146613
146720
  for (const sub of ["screens", "bundles", "assets", "widgets"]) {
146614
- for (const f2 of listDir(join51(appDir3, sub))) {
146721
+ for (const f2 of listDir(join52(appDir3, sub))) {
146615
146722
  if (!wanted.has(`${sub}/${f2}`)) skipped.push(`${sub}/${f2}`);
146616
146723
  }
146617
146724
  }
@@ -146644,18 +146751,18 @@ function buildEntries(appDir3, app, opts) {
146644
146751
  return { all, header, manifest, skipped };
146645
146752
  }
146646
146753
  function packRelease(releaseRoot, app, out2, opts = {}) {
146647
- const appDir3 = join51(resolve45(releaseRoot), app);
146754
+ const appDir3 = join52(resolve45(releaseRoot), app);
146648
146755
  const { all, header, skipped } = buildEntries(appDir3, app, opts);
146649
146756
  const buf = writeZip(all);
146650
146757
  const isDir2 = existsSync53(out2) && statSync13(out2).isDirectory();
146651
- const outFile = isDir2 ? join51(resolve45(out2), packageFileName(app, header.releaseId)) : resolve45(out2);
146652
- mkdirSync25(dirname31(outFile), { recursive: true });
146758
+ const outFile = isDir2 ? join52(resolve45(out2), packageFileName(app, header.releaseId)) : resolve45(out2);
146759
+ mkdirSync25(dirname32(outFile), { recursive: true });
146653
146760
  writeFileSync21(outFile, buf);
146654
146761
  return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
146655
146762
  }
146656
146763
  function resolvePackageDirDest(outDir, app, releaseId) {
146657
146764
  const packagedApp = (dir) => {
146658
- const bytes2 = readIf(join51(dir, HIMI_PACKAGE_HEADER_PATH));
146765
+ const bytes2 = readIf(join52(dir, HIMI_PACKAGE_HEADER_PATH));
146659
146766
  if (!bytes2) return void 0;
146660
146767
  try {
146661
146768
  return JSON.parse(bytes2.toString("utf8")).app;
@@ -146672,7 +146779,7 @@ function resolvePackageDirDest(outDir, app, releaseId) {
146672
146779
  throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
146673
146780
  }
146674
146781
  if (replaceable(outDir)) return outDir;
146675
- const child = join51(outDir, packageDirName(app, releaseId));
146782
+ const child = join52(outDir, packageDirName(app, releaseId));
146676
146783
  if (!replaceable(child)) {
146677
146784
  throw new Error(
146678
146785
  `refusing to replace ${child}: it is not empty and is not a ${app} package (no ${HIMI_PACKAGE_HEADER_PATH}). Pass --out to a new or empty directory.`
@@ -146686,14 +146793,14 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
146686
146793
  "a package carrying the app's source has no --format dir form: readers that predate the source entry drop it before hashing a directory and refuse the package as tampered. Pack it as a .himi archive."
146687
146794
  );
146688
146795
  }
146689
- const appDir3 = join51(resolve45(releaseRoot), app);
146796
+ const appDir3 = join52(resolve45(releaseRoot), app);
146690
146797
  const { all, header, skipped } = buildEntries(appDir3, app, opts);
146691
146798
  const dest = resolvePackageDirDest(resolve45(outDir), app, header.releaseId);
146692
146799
  rmSync12(dest, { recursive: true, force: true });
146693
146800
  let bytes2 = 0;
146694
146801
  for (const entry of all) {
146695
- const target = join51(dest, entry.path);
146696
- mkdirSync25(dirname31(target), { recursive: true });
146802
+ const target = join52(dest, entry.path);
146803
+ mkdirSync25(dirname32(target), { recursive: true });
146697
146804
  writeFileSync21(target, entry.bytes);
146698
146805
  bytes2 += entry.bytes.length;
146699
146806
  }
@@ -146715,18 +146822,18 @@ function openPackageBuffer(buf) {
146715
146822
  return openFromEntries(readZip(buf), { requireHeader: true });
146716
146823
  }
146717
146824
  function openPackageFile(file2) {
146718
- return openPackageBuffer(readFileSync59(file2));
146825
+ return openPackageBuffer(readFileSync60(file2));
146719
146826
  }
146720
146827
  function openPackageDir(dir) {
146721
146828
  const root = resolve45(dir);
146722
146829
  const entries = /* @__PURE__ */ new Map();
146723
146830
  const walk2 = (rel) => {
146724
- const abs = rel ? join51(root, rel) : root;
146831
+ const abs = rel ? join52(root, rel) : root;
146725
146832
  for (const name of readdirSync27(abs)) {
146726
146833
  const childRel = rel ? `${rel}/${name}` : name;
146727
- const childAbs = join51(abs, name);
146834
+ const childAbs = join52(abs, name);
146728
146835
  if (statSync13(childAbs).isDirectory()) walk2(childRel);
146729
- else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync59(childAbs));
146836
+ else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync60(childAbs));
146730
146837
  }
146731
146838
  };
146732
146839
  if (!existsSync53(root)) throw new Error(`no such package directory: ${root}`);
@@ -146771,11 +146878,11 @@ function unpackTo(buf, dest, appFallback) {
146771
146878
  if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
146772
146879
  if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
146773
146880
  const root = resolve45(dest);
146774
- const appDir3 = join51(root, app);
146881
+ const appDir3 = join52(root, app);
146775
146882
  rmSync12(appDir3, { recursive: true, force: true });
146776
146883
  for (const [rel, bytes2] of entries) {
146777
- const target = join51(appDir3, rel);
146778
- mkdirSync25(dirname31(target), { recursive: true });
146884
+ const target = join52(appDir3, rel);
146885
+ mkdirSync25(dirname32(target), { recursive: true });
146779
146886
  writeFileSync21(target, bytes2);
146780
146887
  }
146781
146888
  return { root, appDir: appDir3, app };
@@ -146814,23 +146921,23 @@ __export(app_source_exports, {
146814
146921
  zipAppSource: () => zipAppSource
146815
146922
  });
146816
146923
  import { createHash as createHash29 } from "node:crypto";
146817
- import { readdirSync as readdirSync28, lstatSync as lstatSync15, readFileSync as readFileSync60, mkdirSync as mkdirSync26, writeFileSync as writeFileSync22, existsSync as existsSync54, rmSync as rmSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
146818
- import { join as join52, resolve as resolve46, sep as sep13 } from "node:path";
146924
+ import { readdirSync as readdirSync28, lstatSync as lstatSync15, readFileSync as readFileSync61, mkdirSync as mkdirSync26, writeFileSync as writeFileSync22, existsSync as existsSync54, rmSync as rmSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
146925
+ import { join as join53, resolve as resolve46, sep as sep13 } from "node:path";
146819
146926
  import { createRequire as createRequire3 } from "node:module";
146820
146927
  import { deflateRawSync as deflateRawSync2 } from "node:zlib";
146821
146928
  function walkSourceTree(dir, file2, skip, enter = () => {
146822
146929
  }) {
146823
146930
  const walk2 = (relDir) => {
146824
146931
  enter(relDir);
146825
- for (const name of readdirSync28(join52(dir, relDir))) {
146826
- const rel = relDir ? join52(relDir, name) : name;
146827
- const st2 = lstatSync15(join52(dir, rel));
146932
+ for (const name of readdirSync28(join53(dir, relDir))) {
146933
+ const rel = relDir ? join53(relDir, name) : name;
146934
+ const st2 = lstatSync15(join53(dir, rel));
146828
146935
  if (st2.isSymbolicLink()) {
146829
146936
  skip(rel);
146830
146937
  continue;
146831
146938
  }
146832
146939
  if (st2.isDirectory()) {
146833
- if (isDeniedSourceDir(name, relDir) || existsSync54(join52(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
146940
+ if (isDeniedSourceDir(name, relDir) || existsSync54(join53(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
146834
146941
  else walk2(rel);
146835
146942
  continue;
146836
146943
  }
@@ -146848,7 +146955,7 @@ function collectAppSource(dir) {
146848
146955
  const skipped = [];
146849
146956
  walkSourceTree(
146850
146957
  dir,
146851
- (archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync60(join52(dir, hostRel)) }),
146958
+ (archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync61(join53(dir, hostRel)) }),
146852
146959
  (hostRel) => skipped.push(hostRel)
146853
146960
  );
146854
146961
  entries.sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
@@ -146862,7 +146969,7 @@ function renderInputRootDirs(dir) {
146862
146969
  (archivePath, hostRel) => {
146863
146970
  const segs = archivePath.split("/");
146864
146971
  if (!CODE_FILE.test(archivePath) || /\.d\.[cm]?ts$/i.test(archivePath)) return;
146865
- if (segs.length === 1 || segs[0] === "dev" || segs[0] === "tier5-src") entries.push(join52(dir, hostRel));
146972
+ if (segs.length === 1 || segs[0] === "dev" || segs[0] === "tier5-src") entries.push(join53(dir, hostRel));
146866
146973
  },
146867
146974
  () => {
146868
146975
  }
@@ -146883,7 +146990,7 @@ function renderInputRootDirs(dir) {
146883
146990
  packages: "external",
146884
146991
  platform: "neutral",
146885
146992
  format: "esm",
146886
- outdir: join52(dir, ".himi", "render-inputs-out"),
146993
+ outdir: join53(dir, ".himi", "render-inputs-out"),
146887
146994
  loader: empty,
146888
146995
  logLevel: "silent"
146889
146996
  });
@@ -146905,7 +147012,7 @@ function newestSourceChangeMs(dir) {
146905
147012
  dir,
146906
147013
  (archivePath, hostRel) => {
146907
147014
  if (/\.md$/i.test(archivePath) || !counts(hostRel)) return;
146908
- const m2 = lstatSync15(join52(dir, hostRel)).mtimeMs;
147015
+ const m2 = lstatSync15(join53(dir, hostRel)).mtimeMs;
146909
147016
  if (m2 > newest) newest = m2;
146910
147017
  },
146911
147018
  () => {
@@ -146917,7 +147024,7 @@ function newestSourceChangeMs(dir) {
146917
147024
  // Nor a root directory the render does not read: creating a file in `_qa/` moves `_qa/`.
146918
147025
  (hostRel) => {
146919
147026
  if (hostRel === "" || !inRead(hostRel)) return;
146920
- const m2 = lstatSync15(join52(dir, hostRel)).mtimeMs;
147027
+ const m2 = lstatSync15(join53(dir, hostRel)).mtimeMs;
146921
147028
  if (m2 > newest) newest = m2;
146922
147029
  }
146923
147030
  );
@@ -146929,7 +147036,7 @@ function sourceFingerprint(dir) {
146929
147036
  dir,
146930
147037
  (archivePath, hostRel) => {
146931
147038
  if (/\.md$/i.test(archivePath)) return;
146932
- files.push(`${archivePath}\0${createHash29("sha256").update(readFileSync60(join52(dir, hostRel))).digest("hex")}`);
147039
+ files.push(`${archivePath}\0${createHash29("sha256").update(readFileSync61(join53(dir, hostRel))).digest("hex")}`);
146933
147040
  },
146934
147041
  () => {
146935
147042
  }
@@ -146984,13 +147091,13 @@ function writeAppSource(entries, destDir) {
146984
147091
  const segments = entry.path.split("/");
146985
147092
  let dir = root;
146986
147093
  for (const segment of segments.slice(0, -1)) {
146987
- dir = join52(dir, segment);
147094
+ dir = join53(dir, segment);
146988
147095
  const kind = pathKind(dir);
146989
147096
  if (kind?.isSymbolicLink()) unlinkSync4(dir);
146990
147097
  else if (kind) continue;
146991
147098
  mkdirSync26(dir);
146992
147099
  }
146993
- const target = join52(root, ...segments);
147100
+ const target = join53(root, ...segments);
146994
147101
  if (pathKind(target)?.isSymbolicLink()) unlinkSync4(target);
146995
147102
  writeFileSync22(target, entry.bytes);
146996
147103
  written.push(entry.path);
@@ -147025,7 +147132,7 @@ function writeConflicts(entries, destDir) {
147025
147132
  let dir = root;
147026
147133
  let stop = false;
147027
147134
  for (const [i2, segment] of segments.slice(0, -1).entries()) {
147028
- dir = join52(dir, segment);
147135
+ dir = join53(dir, segment);
147029
147136
  const kind2 = pathKind(dir);
147030
147137
  if (!kind2 || kind2.isSymbolicLink()) {
147031
147138
  stop = true;
@@ -147037,7 +147144,7 @@ function writeConflicts(entries, destDir) {
147037
147144
  break;
147038
147145
  }
147039
147146
  if (stop) continue;
147040
- const kind = pathKind(join52(root, ...segments));
147147
+ const kind = pathKind(join53(root, ...segments));
147041
147148
  if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
147042
147149
  say(entry.path, "is a directory here, but the release has a file at that path");
147043
147150
  }
@@ -147047,7 +147154,7 @@ function writeConflicts(entries, destDir) {
147047
147154
  function removeStaleSource(entries, destDir) {
147048
147155
  const root = resolve46(destDir);
147049
147156
  const removed = staleSourcePaths(entries, root);
147050
- for (const rel of removed) rmSync13(join52(root, ...rel.split("/")), { force: true });
147157
+ for (const rel of removed) rmSync13(join53(root, ...rel.split("/")), { force: true });
147051
147158
  const needed = /* @__PURE__ */ new Set();
147052
147159
  for (const entry of entries) {
147053
147160
  if (isDeniedSourcePath(entry.path)) continue;
@@ -147059,10 +147166,10 @@ function removeStaleSource(entries, destDir) {
147059
147166
  }
147060
147167
  function pruneEmptyDirs(root, rel, needed, removed) {
147061
147168
  let empty = true;
147062
- for (const name of readdirSync28(rel ? join52(root, rel) : root)) {
147063
- const childRel = rel ? join52(rel, name) : name;
147169
+ for (const name of readdirSync28(rel ? join53(root, rel) : root)) {
147170
+ const childRel = rel ? join53(rel, name) : name;
147064
147171
  const posix5 = childRel.split(sep13).join("/");
147065
- const kind = lstatSync15(join52(root, childRel));
147172
+ const kind = lstatSync15(join53(root, childRel));
147066
147173
  if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name, rel)) {
147067
147174
  empty = false;
147068
147175
  continue;
@@ -147072,7 +147179,7 @@ function pruneEmptyDirs(root, rel, needed, removed) {
147072
147179
  empty = false;
147073
147180
  continue;
147074
147181
  }
147075
- rmdirSync2(join52(root, childRel));
147182
+ rmdirSync2(join53(root, childRel));
147076
147183
  removed.push(`${posix5}/`);
147077
147184
  }
147078
147185
  return empty;
@@ -147142,9 +147249,9 @@ __export(run_watch_exports, {
147142
147249
  watchedContentDir: () => watchedContentDir,
147143
147250
  writeRunRecord: () => writeRunRecord
147144
147251
  });
147145
- import { closeSync as closeSync4, constants as constants2, existsSync as existsSync55, fstatSync, lstatSync as lstatSync16, statSync as statSync14, readdirSync as readdirSync29, mkdirSync as mkdirSync27, openSync as openSync4, readFileSync as readFileSync61, realpathSync as realpathSync9, renameSync as renameSync10, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
147252
+ import { closeSync as closeSync4, constants as constants2, existsSync as existsSync55, fstatSync, lstatSync as lstatSync16, statSync as statSync14, readdirSync as readdirSync29, mkdirSync as mkdirSync27, openSync as openSync4, readFileSync as readFileSync62, realpathSync as realpathSync9, renameSync as renameSync10, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
147146
147253
  import { randomUUID as randomUUID6 } from "node:crypto";
147147
- import { extname as extname4, join as join53, resolve as resolve47, sep as sep14 } from "node:path";
147254
+ import { extname as extname4, join as join54, resolve as resolve47, sep as sep14 } from "node:path";
147148
147255
  function diffReleases(prev, next) {
147149
147256
  const bundles = Object.keys(next.bundles).filter((b2) => prev.bundles[b2]?.sha256 !== next.bundles[b2].sha256).sort();
147150
147257
  const changedBundles = new Set(bundles);
@@ -147187,7 +147294,7 @@ function watchContent(dir, onChange, opts = {}) {
147187
147294
  let timer = null;
147188
147295
  const pending = /* @__PURE__ */ new Set();
147189
147296
  const changed = (_event, file2) => {
147190
- if (!file2 || ignoredChange(file2, (rel) => isDir(join53(dir, rel)))) return;
147297
+ if (!file2 || ignoredChange(file2, (rel) => isDir(join54(dir, rel)))) return;
147191
147298
  pending.add(file2);
147192
147299
  if (timer) clearTimeout(timer);
147193
147300
  timer = setTimeout(() => {
@@ -147208,7 +147315,7 @@ function watchContent(dir, onChange, opts = {}) {
147208
147315
  return;
147209
147316
  }
147210
147317
  for (const name of entries) {
147211
- const path2 = join53(directory, String(name)), rel = prefix ? `${prefix}/${name}` : String(name);
147318
+ const path2 = join54(directory, String(name)), rel = prefix ? `${prefix}/${name}` : String(name);
147212
147319
  try {
147213
147320
  const stat2 = lstatSync16(path2);
147214
147321
  if (stat2.isSymbolicLink() || ignoredChange(rel, () => stat2.isDirectory())) continue;
@@ -147249,7 +147356,7 @@ function watchedContentDir(source) {
147249
147356
  if (!source || /^https?:\/\//i.test(source)) return null;
147250
147357
  const dir = resolve47(source);
147251
147358
  try {
147252
- return statSync14(dir).isDirectory() && existsSync55(join53(dir, "himalaya.content.json")) ? dir : null;
147359
+ return statSync14(dir).isDirectory() && existsSync55(join54(dir, "himalaya.content.json")) ? dir : null;
147253
147360
  } catch {
147254
147361
  return null;
147255
147362
  }
@@ -147306,7 +147413,7 @@ function serialize(task) {
147306
147413
  });
147307
147414
  }
147308
147415
  function himiDir(dir) {
147309
- const root = join53(dir, ".himi");
147416
+ const root = join54(dir, ".himi");
147310
147417
  try {
147311
147418
  return lstatSync16(root).isDirectory() ? root : null;
147312
147419
  } catch (e2) {
@@ -147318,11 +147425,11 @@ function himiDir(dir) {
147318
147425
  function writeRunRecord(dir, record2) {
147319
147426
  const root = himiDir(dir);
147320
147427
  if (!root) return false;
147321
- const tmp = join53(root, `.run.json.${process.pid}.${randomUUID6()}.tmp`);
147428
+ const tmp = join54(root, `.run.json.${process.pid}.${randomUUID6()}.tmp`);
147322
147429
  try {
147323
147430
  writeFileSync23(tmp, `${JSON.stringify(record2, null, 2)}
147324
147431
  `, { flag: "wx" });
147325
- renameSync10(tmp, join53(root, "run.json"));
147432
+ renameSync10(tmp, join54(root, "run.json"));
147326
147433
  } catch (e2) {
147327
147434
  rmSync14(tmp, { force: true });
147328
147435
  throw e2;
@@ -147330,7 +147437,7 @@ function writeRunRecord(dir, record2) {
147330
147437
  return true;
147331
147438
  }
147332
147439
  function removeRunRecord(dir, owner) {
147333
- const root = join53(dir, ".himi");
147440
+ const root = join54(dir, ".himi");
147334
147441
  try {
147335
147442
  if (!lstatSync16(root).isDirectory()) return;
147336
147443
  } catch {
@@ -147345,10 +147452,10 @@ function removeRunRecord(dir, owner) {
147345
147452
  }
147346
147453
  if (typeof pid === "number" && pid !== owner) return;
147347
147454
  }
147348
- rmSync14(join53(root, "run.json"), { force: true });
147455
+ rmSync14(join54(root, "run.json"), { force: true });
147349
147456
  }
147350
147457
  function removeInitWatchRecord(dir, owner) {
147351
- const root = join53(dir, ".himi");
147458
+ const root = join54(dir, ".himi");
147352
147459
  try {
147353
147460
  if (!lstatSync16(root).isDirectory()) return;
147354
147461
  } catch {
@@ -147363,19 +147470,19 @@ function removeInitWatchRecord(dir, owner) {
147363
147470
  return;
147364
147471
  }
147365
147472
  if (pid !== owner) return;
147366
- rmSync14(join53(root, "watch.json"), { force: true });
147473
+ rmSync14(join54(root, "watch.json"), { force: true });
147367
147474
  }
147368
147475
  function boardFile(dir, pathname) {
147369
147476
  if (pathname === RUN_IDENTITY_PATH) {
147370
147477
  return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
147371
147478
  }
147372
147479
  let rel = null;
147373
- if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join53("studio", "index.html");
147374
- else if (pathname === "/__himi/studio/state.js") rel = join53("studio", "state.js");
147375
- else if (pathname === "/__himi/studio/timeline.js") rel = join53("studio", "timeline.js");
147480
+ if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join54("studio", "index.html");
147481
+ else if (pathname === "/__himi/studio/state.js") rel = join54("studio", "state.js");
147482
+ else if (pathname === "/__himi/studio/timeline.js") rel = join54("studio", "timeline.js");
147376
147483
  else {
147377
147484
  const m2 = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
147378
- if (m2) rel = join53("history", m2[1]);
147485
+ if (m2) rel = join54("history", m2[1]);
147379
147486
  }
147380
147487
  if (!rel) return null;
147381
147488
  const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
@@ -147391,7 +147498,7 @@ function readConfined(root, rel) {
147391
147498
  const parts = rel.split(sep14);
147392
147499
  let at2 = root;
147393
147500
  for (let i2 = 0; i2 < parts.length; i2++) {
147394
- at2 = join53(at2, parts[i2]);
147501
+ at2 = join54(at2, parts[i2]);
147395
147502
  const st2 = lstatSync16(at2);
147396
147503
  if (st2.isSymbolicLink() || !(i2 === parts.length - 1 ? st2.isFile() : st2.isDirectory())) return null;
147397
147504
  }
@@ -147400,7 +147507,7 @@ function readConfined(root, rel) {
147400
147507
  const fd = openSync4(at2, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
147401
147508
  try {
147402
147509
  if (!fstatSync(fd).isFile()) return null;
147403
- return readFileSync61(fd);
147510
+ return readFileSync62(fd);
147404
147511
  } finally {
147405
147512
  closeSync4(fd);
147406
147513
  }
@@ -147458,8 +147565,8 @@ __export(screen_state_exports, {
147458
147565
  withHomeCaveat: () => withHomeCaveat
147459
147566
  });
147460
147567
  import { createHash as createHash30 } from "node:crypto";
147461
- import { lstatSync as lstatSync17, readFileSync as readFileSync62 } from "node:fs";
147462
- import { join as join54 } from "node:path";
147568
+ import { lstatSync as lstatSync17, readFileSync as readFileSync63 } from "node:fs";
147569
+ import { join as join55 } from "node:path";
147463
147570
  function quotableLine(text9) {
147464
147571
  if (!text9) return void 0;
147465
147572
  const first = text9.split(/\r?\n/).map((l2) => l2.trim()).find(Boolean);
@@ -147515,10 +147622,10 @@ function screenStateOf(services, html, opts = {}) {
147515
147622
  return empty ? { ...empty, ...why } : { state: "content" };
147516
147623
  }
147517
147624
  function readRecord(dir) {
147518
- const file2 = join54(dir, SHOT_STATES_FILE);
147625
+ const file2 = join55(dir, SHOT_STATES_FILE);
147519
147626
  try {
147520
147627
  if (!lstatSync17(file2).isFile()) return {};
147521
- const r2 = JSON.parse(readFileSync62(file2, "utf8"));
147628
+ const r2 = JSON.parse(readFileSync63(file2, "utf8"));
147522
147629
  return r2.v === 1 && r2.shots && typeof r2.shots === "object" ? r2.shots : {};
147523
147630
  } catch {
147524
147631
  return {};
@@ -147530,7 +147637,7 @@ function recordShotState(dir, screenId, png, state, now = /* @__PURE__ */ new Da
147530
147637
  const shots = readRecord(dir);
147531
147638
  shots[sha256Of(png)] = { screen: screenId, state: state.state, ...state.line ? { line: state.line } : {}, ...state.initial ? { initial: true } : {}, ...state.offline ? { offline: true } : {}, at: now.toISOString() };
147532
147639
  const kept = Object.entries(shots).sort(([, a2], [, b2]) => a2.at < b2.at ? 1 : a2.at > b2.at ? -1 : 0).slice(0, KEEP);
147533
- writeFileAtomic(join54(dir, SHOT_STATES_FILE), `${JSON.stringify({ v: 1, shots: Object.fromEntries(kept) }, null, 2)}
147640
+ writeFileAtomic(join55(dir, SHOT_STATES_FILE), `${JSON.stringify({ v: 1, shots: Object.fromEntries(kept) }, null, 2)}
147534
147641
  `);
147535
147642
  } catch {
147536
147643
  }
@@ -147573,11 +147680,11 @@ var SHOT_STATES_FILE, KEEP, LINE_MAX, str3, sha256Of;
147573
147680
  var init_screen_state = __esm({
147574
147681
  "src/screen-state.ts"() {
147575
147682
  init_progress();
147576
- SHOT_STATES_FILE = join54(".himi", "shot-states.json");
147683
+ SHOT_STATES_FILE = join55(".himi", "shot-states.json");
147577
147684
  KEEP = 40;
147578
147685
  LINE_MAX = 120;
147579
147686
  str3 = (v2) => typeof v2 === "string" && v2.trim() ? v2 : void 0;
147580
- sha256Of = (file2) => createHash30("sha256").update(readFileSync62(file2)).digest("hex");
147687
+ sha256Of = (file2) => createHash30("sha256").update(readFileSync63(file2)).digest("hex");
147581
147688
  }
147582
147689
  });
147583
147690
 
@@ -147593,10 +147700,10 @@ __export(studio_reel_exports, {
147593
147700
  utcDay: () => utcDay
147594
147701
  });
147595
147702
  import { createHash as createHash31 } from "node:crypto";
147596
- import { lstatSync as lstatSync18, readFileSync as readFileSync63 } from "node:fs";
147597
- import { basename as basename14, join as join55 } from "node:path";
147703
+ import { lstatSync as lstatSync18, readFileSync as readFileSync64 } from "node:fs";
147704
+ import { basename as basename14, join as join56 } from "node:path";
147598
147705
  function loadMemory2(dir) {
147599
- const m2 = readJson5(join55(dir, ".himi", "studio", "memory.json"));
147706
+ const m2 = readJson6(join56(dir, ".himi", "studio", "memory.json"));
147600
147707
  if (!isObj3(m2) || m2.version !== 1 || !isObj3(m2.shots) || !Array.isArray(m2.timeline)) return null;
147601
147708
  const shots = [];
147602
147709
  for (const [id, s2] of Object.entries(m2.shots)) {
@@ -147633,8 +147740,8 @@ function planReel(dir) {
147633
147740
  const memory = loadMemory2(dir);
147634
147741
  const { entries } = readProgress(dir);
147635
147742
  const summary2 = summarizeProgress(entries);
147636
- const manifest = readJson5(join55(dir, "himalaya.content.json"));
147637
- const tokens2 = readJson5(join55(dir, "tokens.json"));
147743
+ const manifest = readJson6(join56(dir, "himalaya.content.json"));
147744
+ const tokens2 = readJson6(join56(dir, "tokens.json"));
147638
147745
  const accentToken = tokens2?.colors?.accentPrimary;
147639
147746
  const accentRaw = typeof accentToken === "string" ? accentToken : accentToken?.light;
147640
147747
  const accent = typeof accentRaw === "string" && ACCENT.test(accentRaw) ? accentRaw : DEFAULT_ACCENT;
@@ -147677,10 +147784,10 @@ function inlineImages(dir, plan, budget = REEL_BUDGET_BYTES) {
147677
147784
  const verified = (f2) => {
147678
147785
  if (!HISTORY_NAME.test(f2)) return null;
147679
147786
  try {
147680
- const path2 = join55(dir, HISTORY_DIR, f2);
147787
+ const path2 = join56(dir, HISTORY_DIR, f2);
147681
147788
  const st2 = lstatSync18(path2);
147682
147789
  if (!st2.isFile() || st2.nlink !== 1) return null;
147683
- const bytes2 = readFileSync63(path2);
147790
+ const bytes2 = readFileSync64(path2);
147684
147791
  return createHash31("sha256").update(bytes2).digest("hex") === f2.slice(0, 64) && imageExtension(bytes2) === f2.slice(65) ? bytes2 : null;
147685
147792
  } catch {
147686
147793
  return null;
@@ -147800,7 +147907,7 @@ function buildReel(dir, budget = REEL_BUDGET_BYTES) {
147800
147907
  const { plan, images } = inlineImages(dir, planReel(dir), budget);
147801
147908
  return { html: renderReel(plan, images), plan };
147802
147909
  }
147803
- var REEL_BUDGET_BYTES, MAX_FLIP_FRAMES, DEFAULT_ACCENT, ACCENT, HISTORY_NAME, MIME2, mimeOf, readJson5, isObj3, str4, historyName, cited;
147910
+ var REEL_BUDGET_BYTES, MAX_FLIP_FRAMES, DEFAULT_ACCENT, ACCENT, HISTORY_NAME, MIME2, mimeOf, readJson6, isObj3, str4, historyName, cited;
147804
147911
  var init_studio_reel = __esm({
147805
147912
  "src/studio-reel.ts"() {
147806
147913
  init_progress();
@@ -147812,9 +147919,9 @@ var init_studio_reel = __esm({
147812
147919
  HISTORY_NAME = /^[0-9a-f]{64}\.(png|jpg|gif|webp)$/;
147813
147920
  MIME2 = { png: "image/png", jpg: "image/jpeg", gif: "image/gif", webp: "image/webp" };
147814
147921
  mimeOf = (file2) => MIME2[file2.slice(65)] ?? "image/png";
147815
- readJson5 = (file2) => {
147922
+ readJson6 = (file2) => {
147816
147923
  try {
147817
- return JSON.parse(readFileSync63(file2, "utf8"));
147924
+ return JSON.parse(readFileSync64(file2, "utf8"));
147818
147925
  } catch {
147819
147926
  return null;
147820
147927
  }
@@ -147831,12 +147938,12 @@ var init_studio_reel = __esm({
147831
147938
  });
147832
147939
 
147833
147940
  // src/home-screen-id.ts
147834
- import { readFileSync as readFileSync64 } from "node:fs";
147835
- import { join as join56 } from "node:path";
147941
+ import { readFileSync as readFileSync65 } from "node:fs";
147942
+ import { join as join57 } from "node:path";
147836
147943
  function homeScreenIdOf(dir) {
147837
147944
  let src;
147838
147945
  try {
147839
- src = readFileSync64(join56(dir, "dev", "index.ts"), "utf8");
147946
+ src = readFileSync65(join57(dir, "dev", "index.ts"), "utf8");
147840
147947
  } catch {
147841
147948
  return null;
147842
147949
  }
@@ -147904,15 +148011,15 @@ __export(milestones_exports, {
147904
148011
  });
147905
148012
  import { createHash as createHash32, randomUUID as randomUUID7 } from "node:crypto";
147906
148013
  import { spawn as spawn5 } from "node:child_process";
147907
- import { closeSync as closeSync5, existsSync as existsSync56, lstatSync as lstatSync19, readFileSync as readFileSync65, statSync as statSync15 } from "node:fs";
148014
+ import { closeSync as closeSync5, existsSync as existsSync56, lstatSync as lstatSync19, readFileSync as readFileSync66, statSync as statSync15 } from "node:fs";
147908
148015
  import { createServer as createServer4 } from "node:net";
147909
- import { basename as basename15, dirname as dirname32, isAbsolute as isAbsolute6, join as join57, relative as relative11, resolve as resolve48, sep as sep15 } from "node:path";
148016
+ import { basename as basename15, dirname as dirname33, isAbsolute as isAbsolute6, join as join58, relative as relative11, resolve as resolve48, sep as sep15 } from "node:path";
147910
148017
  function homeShotPath(dir, home) {
147911
148018
  const root = resolve48(dir);
147912
148019
  const base = resolve48(root, ".himi", "shots");
147913
148020
  const shot = resolve48(base, `${home}.png`);
147914
148021
  if (!shot.startsWith(base + sep15)) return null;
147915
- for (let p2 = shot; p2 !== root && p2.startsWith(root + sep15); p2 = dirname32(p2)) {
148022
+ for (let p2 = shot; p2 !== root && p2.startsWith(root + sep15); p2 = dirname33(p2)) {
147916
148023
  try {
147917
148024
  if (lstatSync19(p2).isSymbolicLink()) return null;
147918
148025
  } catch {
@@ -148017,7 +148124,7 @@ function autoPictureGate(dir) {
148017
148124
  }
148018
148125
  async function homePictureAtValidate(dir, opts) {
148019
148126
  if (!opts.ok) return { skipped: "validate found errors, so the picture was left as it is" };
148020
- if (!existsSync56(join57(dir, "himalaya.content.json"))) return { skipped: "not a content package" };
148127
+ if (!existsSync56(join58(dir, "himalaya.content.json"))) return { skipped: "not a content package" };
148021
148128
  const env = opts.env ?? process.env;
148022
148129
  if (ciSet(env)) return { skipped: "the CI environment variable is set" };
148023
148130
  if (env.NODE_TEST_CONTEXT) return { skipped: "running under `node --test`" };
@@ -148241,16 +148348,16 @@ function rememberDraft(dir, releaseId, m2) {
148241
148348
  ...m2.tokensHash ? { tokensHash: m2.tokensHash } : {},
148242
148349
  ...m2.appConfigHash ? { appConfigHash: m2.appConfigHash } : {}
148243
148350
  };
148244
- writeFileAtomic(join57(dir, LAST_DRAFT_FILE), `${JSON.stringify({ v: 1, releaseId, manifest })}
148351
+ writeFileAtomic(join58(dir, LAST_DRAFT_FILE), `${JSON.stringify({ v: 1, releaseId, manifest })}
148245
148352
  `);
148246
148353
  } catch {
148247
148354
  }
148248
148355
  }
148249
148356
  function lastDraft(dir) {
148250
148357
  try {
148251
- const file2 = join57(dir, LAST_DRAFT_FILE);
148358
+ const file2 = join58(dir, LAST_DRAFT_FILE);
148252
148359
  if (!lstatSync19(file2).isFile()) return null;
148253
- const r2 = JSON.parse(readFileSync65(file2, "utf8"));
148360
+ const r2 = JSON.parse(readFileSync66(file2, "utf8"));
148254
148361
  const m2 = r2.manifest;
148255
148362
  if (r2.v !== 1 || typeof r2.releaseId !== "string" || !m2 || typeof m2.screens !== "object" || !m2.screens || typeof m2.bundles !== "object" || !m2.bundles) return null;
148256
148363
  return { releaseId: r2.releaseId, manifest: m2 };
@@ -148301,7 +148408,7 @@ function recordInitSource(dir, opts = {}) {
148301
148408
  template: opts.template && TEMPLATE_NAME.test(opts.template) ? opts.template : null,
148302
148409
  ...opts.source ? { source: opts.source } : {}
148303
148410
  };
148304
- writeFileAtomic(join57(dir, INIT_SOURCE_FILE), `${JSON.stringify(record2, null, 2)}
148411
+ writeFileAtomic(join58(dir, INIT_SOURCE_FILE), `${JSON.stringify(record2, null, 2)}
148305
148412
  `);
148306
148413
  return true;
148307
148414
  } catch {
@@ -148309,10 +148416,10 @@ function recordInitSource(dir, opts = {}) {
148309
148416
  }
148310
148417
  }
148311
148418
  function readInitSource(dir) {
148312
- const file2 = join57(dir, INIT_SOURCE_FILE);
148419
+ const file2 = join58(dir, INIT_SOURCE_FILE);
148313
148420
  try {
148314
148421
  if (!lstatSync19(file2).isFile()) return null;
148315
- const r2 = JSON.parse(readFileSync65(file2, "utf8"));
148422
+ const r2 = JSON.parse(readFileSync66(file2, "utf8"));
148316
148423
  if (r2.v !== 1 || typeof r2.fingerprint !== "string" || !/^[0-9a-f]{64}$/.test(r2.fingerprint) || typeof r2.newestMs !== "number") return null;
148317
148424
  return {
148318
148425
  v: 1,
@@ -148381,10 +148488,10 @@ function homeShotForPostcard(dir, opts = {}) {
148381
148488
  function contentHomePictures(dir, home) {
148382
148489
  const out2 = [];
148383
148490
  const shot = homeShotPath(dir, home);
148384
- const hist = realDirIn(dir, HISTORY_DIR) ? join57(dir, HISTORY_DIR) : null;
148491
+ const hist = realDirIn(dir, HISTORY_DIR) ? join58(dir, HISTORY_DIR) : null;
148385
148492
  for (const r2 of recordedShots(dir, home)) {
148386
148493
  if (r2.state.state !== "content") continue;
148387
- for (const file2 of [shot, hist && join57(hist, `${r2.sha256}.png`)]) {
148494
+ for (const file2 of [shot, hist && join58(hist, `${r2.sha256}.png`)]) {
148388
148495
  try {
148389
148496
  if (!file2 || !lstatSync19(file2).isFile() || sha256Of2(file2) !== r2.sha256) continue;
148390
148497
  } catch {
@@ -148397,10 +148504,10 @@ function contentHomePictures(dir, home) {
148397
148504
  return out2;
148398
148505
  }
148399
148506
  function readInitWatch(dir) {
148400
- const file2 = join57(dir, INIT_WATCH_FILE);
148507
+ const file2 = join58(dir, INIT_WATCH_FILE);
148401
148508
  try {
148402
148509
  if (!lstatSync19(file2).isFile()) return null;
148403
- const r2 = JSON.parse(readFileSync65(file2, "utf8"));
148510
+ const r2 = JSON.parse(readFileSync66(file2, "utf8"));
148404
148511
  if (r2.v !== 1 || typeof r2.pid !== "number" || !Number.isInteger(r2.pid) || r2.pid < 1) return null;
148405
148512
  if (typeof r2.url !== "string" || !/^http:\/\/127\.0\.0\.1:\d+\//.test(r2.url) || typeof r2.board !== "string" || typeof r2.log !== "string" || typeof r2.startedAt !== "string") return null;
148406
148513
  if (r2.root !== runRootId(dir)) return null;
@@ -148425,14 +148532,14 @@ function liveWatchRunning(dir, isAlive = pidAlive, now) {
148425
148532
  }
148426
148533
  function watchReminder(dir, opts = {}) {
148427
148534
  try {
148428
- if (!existsSync56(join57(dir, "himalaya.content.json"))) return void 0;
148535
+ if (!existsSync56(join58(dir, "himalaya.content.json"))) return void 0;
148429
148536
  const nowDate = opts.now ?? /* @__PURE__ */ new Date();
148430
148537
  const live3 = liveWatch(dir, opts.isAlive, nowDate);
148431
148538
  const now = nowDate.getTime();
148432
- const file2 = join57(dir, REMINDERS_FILE);
148539
+ const file2 = join58(dir, REMINDERS_FILE);
148433
148540
  let last = Number.NaN;
148434
148541
  try {
148435
- if (lstatSync19(file2).isFile()) last = Date.parse(JSON.parse(readFileSync65(file2, "utf8")).watch ?? "");
148542
+ if (lstatSync19(file2).isFile()) last = Date.parse(JSON.parse(readFileSync66(file2, "utf8")).watch ?? "");
148436
148543
  } catch {
148437
148544
  }
148438
148545
  if (Number.isFinite(last) && now - last >= 0 && now - last < WATCH_REMINDER_EVERY_MS) return void 0;
@@ -148444,7 +148551,7 @@ function watchReminder(dir, opts = {}) {
148444
148551
  }
148445
148552
  const content = opts.content ?? displayPath(dir);
148446
148553
  const remote = readInitSource(dir)?.source === "remote" ? "init did not start it because this template came off the serve plane \u2014 once you have read its code, " : "";
148447
- return `${remote}start the live preview and leave it running: \`himi run --watch --content ${shellQuote(content)} &\` (the consent preflight first, if a worker or config calls Wix at boot) \u2014 it repaints on every save; the build board is ${shellQuote(join57(content, ".himi", "studio", "index.html"))}, or /__himi/studio/ on the preview`;
148554
+ return `${remote}start the live preview and leave it running: \`himi run --watch --content ${shellQuote(content)} &\` (the consent preflight first, if a worker or config calls Wix at boot) \u2014 it repaints on every save; the build board is ${shellQuote(join58(content, ".himi", "studio", "index.html"))}, or /__himi/studio/ on the preview`;
148448
148555
  } catch {
148449
148556
  return void 0;
148450
148557
  }
@@ -148510,7 +148617,7 @@ async function startWatchAtInit(dir, opts) {
148510
148617
  child.unref();
148511
148618
  if (!child.pid) return { skipped: "the live preview did not start (no process) \u2014 start it yourself: `himi run --watch --content <dir> &`", ...note };
148512
148619
  const record2 = { v: 1, pid: child.pid, root: runRootId(dir), url, board, log: WATCH_LOG, startedAt: now.toISOString() };
148513
- if (realDirIn(dir, ".himi")) writeFileAtomic(join57(dir, INIT_WATCH_FILE), `${JSON.stringify(record2, null, 2)}
148620
+ if (realDirIn(dir, ".himi")) writeFileAtomic(join58(dir, INIT_WATCH_FILE), `${JSON.stringify(record2, null, 2)}
148514
148621
  `);
148515
148622
  return { started: true, pid: child.pid, url, board, log: WATCH_LOG, ...note };
148516
148623
  } catch (e2) {
@@ -148525,7 +148632,7 @@ function watchRunning(w2) {
148525
148632
  function doNowBlock(opts) {
148526
148633
  const content = displayPath(opts.dir, opts.cwd);
148527
148634
  const home = opts.home ?? "<homeScreenId>";
148528
- const board = join57(content, ".himi", "studio", "index.html");
148635
+ const board = join58(content, ".himi", "studio", "index.html");
148529
148636
  const running = watchRunning(opts.watch);
148530
148637
  const who = running?.by === "init" ? "init started it" : "already running";
148531
148638
  const watch2 = running ? `${running.url} (${who}; the board: ${running.board}) \u2014 leave it running, and do not start another` : `\`himi run --watch${contentArg(content)} &\` and leave it running (the board: ${shellQuote(board)}, or /__himi/studio/ on the preview)`;
@@ -148544,7 +148651,7 @@ function writeHandoverReel(dir) {
148544
148651
  try {
148545
148652
  if (!realDirIn(dir, ".himi")) return { skipped: ".himi is not a real directory inside the package (a symlink?), so no making-of was written" };
148546
148653
  const { html } = buildReel(dir);
148547
- const file2 = join57(dir, ".himi", "making-of.html");
148654
+ const file2 = join58(dir, ".himi", "making-of.html");
148548
148655
  writeFileAtomic(file2, html);
148549
148656
  return { file: file2, hint: `hand ${basename15(file2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` };
148550
148657
  } catch (e2) {
@@ -148552,11 +148659,11 @@ function writeHandoverReel(dir) {
148552
148659
  }
148553
148660
  }
148554
148661
  function afterHandoverPostcard(dir, opts = {}) {
148555
- const file2 = join57(dir, ".himi", "making-of.html");
148662
+ const file2 = join58(dir, ".himi", "making-of.html");
148556
148663
  let fresh = false;
148557
148664
  try {
148558
148665
  const st2 = lstatSync19(file2);
148559
- fresh = st2.isFile() && !st2.isSymbolicLink() && st2.mtimeMs >= statSync15(join57(dir, ".himi", "progress.jsonl")).mtimeMs;
148666
+ fresh = st2.isFile() && !st2.isSymbolicLink() && st2.mtimeMs >= statSync15(join58(dir, ".himi", "progress.jsonl")).mtimeMs;
148560
148667
  } catch {
148561
148668
  fresh = false;
148562
148669
  }
@@ -148588,13 +148695,13 @@ var init_milestones = __esm({
148588
148695
  STILL_BUILDING_MESSAGE = "Still building: here's the home screen now.";
148589
148696
  yourFirstLookMessage = (dir) => `First look at your app: ${appName(dir)}'s home screen, with your changes.`;
148590
148697
  homeCaveat = (dir, image) => homeStateCaveat(shotStateFor(dir, image));
148591
- LAST_DRAFT_FILE = join57(".himi", "last-draft.json");
148592
- INIT_SOURCE_FILE = join57(".himi", "init-source.json");
148698
+ LAST_DRAFT_FILE = join58(".himi", "last-draft.json");
148699
+ INIT_SOURCE_FILE = join58(".himi", "init-source.json");
148593
148700
  STARTING_POINT_REF = "starting-point";
148594
148701
  TEMPLATE_NAME = /^[A-Za-z0-9._-]{1,64}$/;
148595
- sha256Of2 = (file2) => createHash32("sha256").update(readFileSync65(file2)).digest("hex");
148702
+ sha256Of2 = (file2) => createHash32("sha256").update(readFileSync66(file2)).digest("hex");
148596
148703
  WATCH_REMINDER_EVERY_MS = 10 * 60 * 1e3;
148597
- REMINDERS_FILE = join57(".himi", "reminders.json");
148704
+ REMINDERS_FILE = join58(".himi", "reminders.json");
148598
148705
  pidAlive = (pid) => {
148599
148706
  try {
148600
148707
  process.kill(pid, 0);
@@ -148603,7 +148710,7 @@ var init_milestones = __esm({
148603
148710
  return e2.code === "EPERM";
148604
148711
  }
148605
148712
  };
148606
- INIT_WATCH_FILE = join57(".himi", "watch.json");
148713
+ INIT_WATCH_FILE = join58(".himi", "watch.json");
148607
148714
  INIT_WATCH_STARTING_MS = 5 * 60 * 1e3;
148608
148715
  INIT_WATCH_IDLE_MINUTES = 30;
148609
148716
  WATCH_LOG = ".himi/watch.log";
@@ -148639,8 +148746,8 @@ __export(template_sweep_exports, {
148639
148746
  sweepCopy: () => sweepCopy,
148640
148747
  sweepPairs: () => sweepPairs
148641
148748
  });
148642
- import { readFileSync as readFileSync66, writeFileSync as writeFileSync24 } from "node:fs";
148643
- import { join as join58 } from "node:path";
148749
+ import { readFileSync as readFileSync67, writeFileSync as writeFileSync24 } from "node:fs";
148750
+ import { join as join59 } from "node:path";
148644
148751
  import ts7 from "typescript";
148645
148752
  function isCopy(node, file2) {
148646
148753
  const parent = node.parent;
@@ -148681,7 +148788,7 @@ function sweepCopy(dir, pairs, dryRun) {
148681
148788
  const next = /* @__PURE__ */ new Map();
148682
148789
  const replaced = pairs.map(([from, to2]) => ({ from, to: to2, files: {} }));
148683
148790
  for (const f2 of files) {
148684
- const text9 = readFileSync66(join58(dir, f2), "utf8");
148791
+ const text9 = readFileSync67(join59(dir, f2), "utf8");
148685
148792
  if (!pairs.some(([from]) => text9.includes(from) || text9.includes(JSON.stringify(from).slice(1, -1)))) continue;
148686
148793
  const kind = f2.endsWith(".json") ? ts7.ScriptKind.JSON : f2.endsWith("x") ? ts7.ScriptKind.TSX : ts7.ScriptKind.TS;
148687
148794
  const sf2 = ts7.createSourceFile(f2, text9, ts7.ScriptTarget.Latest, true, kind);
@@ -148710,16 +148817,16 @@ function sweepCopy(dir, pairs, dryRun) {
148710
148817
  if (errors.length) throw new TrimRefusal(`the sweep would break ${f2} \u2014 nothing written: ${errors[0]}`);
148711
148818
  next.set(f2, out2);
148712
148819
  }
148713
- const dev = next.get("dev/index.ts") ?? readFileSync66(join58(dir, "dev", "index.ts"), "utf8");
148714
- const config = next.get("config.ts") ?? readFileSync66(join58(dir, "config.ts"), "utf8");
148820
+ const dev = next.get("dev/index.ts") ?? readFileSync67(join59(dir, "dev", "index.ts"), "utf8");
148821
+ const config = next.get("config.ts") ?? readFileSync67(join59(dir, "config.ts"), "utf8");
148715
148822
  try {
148716
148823
  parseApp(dev, config);
148717
148824
  } catch (e2) {
148718
148825
  throw new TrimRefusal(`the sweep would leave dev/index.ts or config.ts unparseable \u2014 nothing written: ${e2.message}`);
148719
148826
  }
148720
- if (!dryRun) for (const [f2, t2] of next) writeFileSync24(join58(dir, f2), t2);
148827
+ if (!dryRun) for (const [f2, t2] of next) writeFileSync24(join59(dir, f2), t2);
148721
148828
  const g2 = new RegExp(PLACEHOLDER.source, `${PLACEHOLDER.flags.replace("g", "")}g`);
148722
- const placeholdersLeft = all.reduce((n2, f2) => n2 + [...(next.get(f2) ?? readFileSync66(join58(dir, f2), "utf8")).matchAll(g2)].length, 0);
148829
+ const placeholdersLeft = all.reduce((n2, f2) => n2 + [...(next.get(f2) ?? readFileSync67(join59(dir, f2), "utf8")).matchAll(g2)].length, 0);
148723
148830
  return {
148724
148831
  ok: true,
148725
148832
  dryRun,
@@ -148736,7 +148843,7 @@ function sweepPairs(set, mapFile) {
148736
148843
  pairs.push([s2.slice(0, at2), s2.slice(at2 + 2)]);
148737
148844
  }
148738
148845
  if (mapFile) {
148739
- const map = JSON.parse(readFileSync66(mapFile, "utf8"));
148846
+ const map = JSON.parse(readFileSync67(mapFile, "utf8"));
148740
148847
  for (const [k2, v2] of Object.entries(map)) {
148741
148848
  if (typeof v2 !== "string") throw new TrimRefusal(`--map ${mapFile}: "${k2}" must map to a string`);
148742
148849
  pairs.push([k2, v2]);
@@ -148981,18 +149088,18 @@ __export(template_recommend_exports, {
148981
149088
  recommendTemplates: () => recommendTemplates,
148982
149089
  verticalsFromBook: () => verticalsFromBook
148983
149090
  });
148984
- import { existsSync as existsSync57, readFileSync as readFileSync67 } from "node:fs";
148985
- import { join as join59 } from "node:path";
149091
+ import { existsSync as existsSync57, readFileSync as readFileSync68 } from "node:fs";
149092
+ import { join as join60 } from "node:path";
148986
149093
  function verticalsFromBook(path2) {
148987
- const dir = existsSync57(join59(path2, "book.json")) || existsSync57(join59(path2, "provisioning.overlay.json")) ? path2 : join59(path2, ".himi", "business-book");
148988
- const overlay = join59(dir, "provisioning.overlay.json");
149094
+ const dir = existsSync57(join60(path2, "book.json")) || existsSync57(join60(path2, "provisioning.overlay.json")) ? path2 : join60(path2, ".himi", "business-book");
149095
+ const overlay = join60(dir, "provisioning.overlay.json");
148989
149096
  if (existsSync57(overlay)) {
148990
- const v2 = JSON.parse(readFileSync67(overlay, "utf8")).installedVerticals;
149097
+ const v2 = JSON.parse(readFileSync68(overlay, "utf8")).installedVerticals;
148991
149098
  if (Array.isArray(v2) && v2.length) return v2.filter((x2) => typeof x2 === "string");
148992
149099
  }
148993
- const book = join59(dir, "book.json");
149100
+ const book = join60(dir, "book.json");
148994
149101
  if (existsSync57(book)) {
148995
- const probes = JSON.parse(readFileSync67(book, "utf8")).probes;
149102
+ const probes = JSON.parse(readFileSync68(book, "utf8")).probes;
148996
149103
  if (Array.isArray(probes)) return installedFromProbes(probes);
148997
149104
  }
148998
149105
  throw new Error(`no book.json / provisioning.overlay.json under ${path2} \u2014 run \`himi site analyze\` first, or pass --verticals`);
@@ -149402,8 +149509,8 @@ __export(eject_exports, {
149402
149509
  EJECTABLE: () => EJECTABLE,
149403
149510
  ejectModule: () => ejectModule
149404
149511
  });
149405
- import { existsSync as existsSync58, mkdirSync as mkdirSync28, readFileSync as readFileSync68, writeFileSync as writeFileSync25 } from "node:fs";
149406
- import { dirname as dirname33, join as join60, relative as relative12, resolve as resolve49, sep as sep16 } from "node:path";
149512
+ import { existsSync as existsSync58, mkdirSync as mkdirSync28, readFileSync as readFileSync69, writeFileSync as writeFileSync25 } from "node:fs";
149513
+ import { dirname as dirname34, join as join61, relative as relative12, resolve as resolve49, sep as sep16 } from "node:path";
149407
149514
  function locate(repoRootOrCwd, mod) {
149408
149515
  const inRepo = resolve49(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
149409
149516
  if (existsSync58(inRepo)) return { path: inRepo, form: "source" };
@@ -149432,8 +149539,8 @@ function ejectModule(opts) {
149432
149539
  };
149433
149540
  }
149434
149541
  const ext = found.form === "source" ? "ts" : "mjs";
149435
- const target = join60(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
149436
- mkdirSync28(dirname33(target), { recursive: true });
149542
+ const target = join61(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
149543
+ mkdirSync28(dirname34(target), { recursive: true });
149437
149544
  const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
149438
149545
  //
149439
149546
  // Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
@@ -149446,7 +149553,7 @@ function ejectModule(opts) {
149446
149553
  // gate still applies. Ejecting buys layout and flow, never the floor.
149447
149554
 
149448
149555
  `;
149449
- const normalized = readFileSync68(found.path, "utf8").replace(
149556
+ const normalized = readFileSync69(found.path, "utf8").replace(
149450
149557
  /(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
149451
149558
  (_m, q2, sub) => `${q2}@wix/himalaya/${sub}${q2}`
149452
149559
  );
@@ -149454,9 +149561,9 @@ function ejectModule(opts) {
149454
149561
  const rewired = [];
149455
149562
  for (const f2 of files) {
149456
149563
  if (!existsSync58(f2)) continue;
149457
- const before = readFileSync68(f2, "utf8");
149564
+ const before = readFileSync69(f2, "utf8");
149458
149565
  let after = before;
149459
- let rel = relative12(dirname33(f2), target).split(sep16).join("/").replace(/\.tsx?$/, ".js");
149566
+ let rel = relative12(dirname34(f2), target).split(sep16).join("/").replace(/\.tsx?$/, ".js");
149460
149567
  if (!rel.startsWith(".")) rel = `./${rel}`;
149461
149568
  for (const spec of specifiersFor(mod)) {
149462
149569
  const q2 = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -149574,8 +149681,8 @@ var init_app_map = __esm({
149574
149681
  });
149575
149682
 
149576
149683
  // src/wix-writes.ts
149577
- import { existsSync as existsSync59, readFileSync as readFileSync69 } from "node:fs";
149578
- import { join as join61 } from "node:path";
149684
+ import { existsSync as existsSync59, readFileSync as readFileSync70 } from "node:fs";
149685
+ import { join as join62 } from "node:path";
149579
149686
  function isProvenRead(method, path2) {
149580
149687
  if (/[#\x00-\x1F\x7F]/.test(path2)) return false;
149581
149688
  const verb = method.toUpperCase();
@@ -149693,11 +149800,11 @@ function parseDataAccess(text9, from) {
149693
149800
  }
149694
149801
  function readDataAccess(dir) {
149695
149802
  for (const name of ["SPEC.md", "MOBILE-UX.md"]) {
149696
- const p2 = join61(dir, name);
149803
+ const p2 = join62(dir, name);
149697
149804
  if (!existsSync59(p2)) continue;
149698
149805
  let text9;
149699
149806
  try {
149700
- text9 = readFileSync69(p2, "utf8");
149807
+ text9 = readFileSync70(p2, "utf8");
149701
149808
  } catch {
149702
149809
  continue;
149703
149810
  }
@@ -149811,14 +149918,14 @@ __export(test_exports, {
149811
149918
  scopeDescriptors: () => scopeDescriptors,
149812
149919
  writeRecordedMocks: () => writeRecordedMocks
149813
149920
  });
149814
- import { existsSync as existsSync60, mkdirSync as mkdirSync29, readFileSync as readFileSync70, writeFileSync as writeFileSync26 } from "node:fs";
149815
- import { join as join62, resolve as resolve50 } from "node:path";
149921
+ import { existsSync as existsSync60, mkdirSync as mkdirSync29, readFileSync as readFileSync71, writeFileSync as writeFileSync26 } from "node:fs";
149922
+ import { join as join63, resolve as resolve50 } from "node:path";
149816
149923
  function readTestConfig(dir) {
149817
149924
  const p2 = resolve50(dir, TEST_CONFIG_FILE);
149818
149925
  if (!existsSync60(p2)) return {};
149819
149926
  let parsed;
149820
149927
  try {
149821
- parsed = JSON.parse(readFileSync70(p2, "utf8"));
149928
+ parsed = JSON.parse(readFileSync71(p2, "utf8"));
149822
149929
  } catch (e2) {
149823
149930
  throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e2.message}`);
149824
149931
  }
@@ -149865,7 +149972,7 @@ function readTestConfig(dir) {
149865
149972
  function readNetRules(path2) {
149866
149973
  let parsed;
149867
149974
  try {
149868
- parsed = JSON.parse(readFileSync70(path2, "utf8"));
149975
+ parsed = JSON.parse(readFileSync71(path2, "utf8"));
149869
149976
  } catch (e2) {
149870
149977
  throw new Error(`--net ${path2} could not be read as JSON \u2014 ${e2.message}`);
149871
149978
  }
@@ -149902,7 +150009,7 @@ function readCannedResponses() {
149902
150009
  ];
149903
150010
  for (const url of candidates) {
149904
150011
  try {
149905
- const parsed = JSON.parse(readFileSync70(url, "utf8"));
150012
+ const parsed = JSON.parse(readFileSync71(url, "utf8"));
149906
150013
  const byKey = {};
149907
150014
  for (const [k2, v2] of Object.entries(parsed)) {
149908
150015
  if (!k2.startsWith("//")) byKey[k2] = v2;
@@ -149992,8 +150099,8 @@ function writeRecordedMocks(opts) {
149992
150099
  mkdir: (p2) => mkdirSync29(p2, { recursive: true }),
149993
150100
  write: (p2, s2) => writeFileSync26(p2, s2)
149994
150101
  };
149995
- fs2.mkdir(join62(opts.dir, "dev"));
149996
- fs2.write(join62(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
150102
+ fs2.mkdir(join63(opts.dir, "dev"));
150103
+ fs2.write(join63(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
149997
150104
  return { ok: true, rules, to: "dev/net-mocks.json" };
149998
150105
  }
149999
150106
  function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
@@ -150539,14 +150646,14 @@ var mobile_ux_lint_exports = {};
150539
150646
  __export(mobile_ux_lint_exports, {
150540
150647
  mobileUxIssues: () => mobileUxIssues
150541
150648
  });
150542
- import { existsSync as existsSync61, readFileSync as readFileSync71 } from "node:fs";
150543
- import { join as join63 } from "node:path";
150649
+ import { existsSync as existsSync61, readFileSync as readFileSync72 } from "node:fs";
150650
+ import { join as join64 } from "node:path";
150544
150651
  function mobileUxIssues(dir, strict) {
150545
- const file2 = join63(dir, "MOBILE-UX.md");
150652
+ const file2 = join64(dir, "MOBILE-UX.md");
150546
150653
  if (!existsSync61(file2)) return [];
150547
150654
  let text9;
150548
150655
  try {
150549
- text9 = readFileSync71(file2, "utf8");
150656
+ text9 = readFileSync72(file2, "utf8");
150550
150657
  } catch {
150551
150658
  return [];
150552
150659
  }
@@ -152227,8 +152334,8 @@ __export(functions_exports, {
152227
152334
  resolveFunctionsTarget: () => resolveFunctionsTarget,
152228
152335
  runRemoteFunctionOperation: () => runRemoteFunctionOperation
152229
152336
  });
152230
- import { readFileSync as readFileSync72, existsSync as existsSync62 } from "node:fs";
152231
- import { join as join64, resolve as resolve51 } from "node:path";
152337
+ import { readFileSync as readFileSync73, existsSync as existsSync62 } from "node:fs";
152338
+ import { join as join65, resolve as resolve51 } from "node:path";
152232
152339
  function resolveFunctionsTarget(input) {
152233
152340
  const explicitUrl = input.functionsUrl?.trim();
152234
152341
  if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
@@ -152247,9 +152354,9 @@ async function loadFunctionsApp(dir) {
152247
152354
  }
152248
152355
  const sources = {};
152249
152356
  for (const definition of config.functions.functions) {
152250
- const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join64(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync62);
152357
+ const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join65(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync62);
152251
152358
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
152252
- sources[definition.name] = readFileSync72(source, "utf8");
152359
+ sources[definition.name] = readFileSync73(source, "utf8");
152253
152360
  }
152254
152361
  const data = config.cms || config.data ? mergeDataResources(config) : void 0;
152255
152362
  const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
@@ -152437,9 +152544,9 @@ var init_cli_bridge = __esm({
152437
152544
  });
152438
152545
 
152439
152546
  // src/mcp/file-tools.ts
152440
- import { closeSync as closeSync6, constants as constants3, lstatSync as lstatSync20, mkdirSync as mkdirSync30, openSync as openSync5, readdirSync as readdirSync30, readFileSync as readFileSync73, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync15, statSync as statSync16, writeSync, existsSync as existsSync63 } from "node:fs";
152547
+ import { closeSync as closeSync6, constants as constants3, lstatSync as lstatSync20, mkdirSync as mkdirSync30, openSync as openSync5, readdirSync as readdirSync30, readFileSync as readFileSync74, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync15, statSync as statSync16, writeSync, existsSync as existsSync63 } from "node:fs";
152441
152548
  import { randomBytes as randomBytes4 } from "node:crypto";
152442
- import { dirname as dirname34, isAbsolute as isAbsolute7, join as join65, relative as relative13, resolve as resolve52, sep as sep17 } from "node:path";
152549
+ import { dirname as dirname35, isAbsolute as isAbsolute7, join as join66, relative as relative13, resolve as resolve52, sep as sep17 } from "node:path";
152443
152550
  import * as z2 from "zod";
152444
152551
  function within(root, p2) {
152445
152552
  return p2 === root || p2.startsWith(root.endsWith(sep17) ? root : root + sep17);
@@ -152448,17 +152555,17 @@ function realish(p2) {
152448
152555
  let cur = p2;
152449
152556
  const tail = [];
152450
152557
  while (!existsSync63(cur)) {
152451
- const up = dirname34(cur);
152558
+ const up = dirname35(cur);
152452
152559
  if (up === cur) break;
152453
152560
  tail.unshift(cur.slice(up.length + (up.endsWith(sep17) ? 0 : 1)));
152454
152561
  cur = up;
152455
152562
  }
152456
- return join65(realpathSync10(cur), ...tail);
152563
+ return join66(realpathSync10(cur), ...tail);
152457
152564
  }
152458
152565
  function symlinkComponent(base, abs) {
152459
152566
  let cur = base;
152460
152567
  for (const part of relative13(base, abs).split(sep17).filter(Boolean)) {
152461
- cur = join65(cur, part);
152568
+ cur = join66(cur, part);
152462
152569
  try {
152463
152570
  if (lstatSync20(cur).isSymbolicLink()) return relative13(base, cur);
152464
152571
  } catch {
@@ -152485,7 +152592,7 @@ async function confinedAppDir(args, deps) {
152485
152592
  if (link) return refuse5("outside_workspace", `"${link}" is a symlink \u2014 the app folder must be a real folder in the workspace`);
152486
152593
  const rel = relative13(root, dir);
152487
152594
  if (rel && (isDeniedSourcePath(`${rel}/x`) || isDeniedSourcePath(`${rel.toLowerCase()}/x`))) return refuse5("denied", `"${rel}" is a folder this tool does not touch`);
152488
- if (!existsSync63(join65(dir, CONTENT_MARKER))) {
152595
+ if (!existsSync63(join66(dir, CONTENT_MARKER))) {
152489
152596
  return refuse5("not_an_app", `"${rel || "."}" is not an app folder (no ${CONTENT_MARKER}) \u2014 see himi_list_apps, or create one with himi_init`);
152490
152597
  }
152491
152598
  return dir;
@@ -152494,12 +152601,12 @@ function onDiskSpelling(abs) {
152494
152601
  let cur = abs;
152495
152602
  const tail = [];
152496
152603
  while (!existsSync63(cur)) {
152497
- const up = dirname34(cur);
152604
+ const up = dirname35(cur);
152498
152605
  if (up === cur) break;
152499
152606
  tail.unshift(cur.slice(up.length + (up.endsWith(sep17) ? 0 : 1)));
152500
152607
  cur = up;
152501
152608
  }
152502
- return join65(realpathSync10.native(cur), ...tail);
152609
+ return join66(realpathSync10.native(cur), ...tail);
152503
152610
  }
152504
152611
  function denied(appDir3, abs) {
152505
152612
  const rel = relative13(appDir3, abs);
@@ -152525,10 +152632,10 @@ function confinedPath(appDir3, rel) {
152525
152632
  return abs;
152526
152633
  }
152527
152634
  function writeNoFollow2(appDir3, abs, content) {
152528
- mkdirSync30(dirname34(abs), { recursive: true });
152635
+ mkdirSync30(dirname35(abs), { recursive: true });
152529
152636
  const before = symlinkComponent(appDir3, abs);
152530
152637
  if (before) throw new Error(`"${before}" became a symlink`);
152531
- const tmp = join65(dirname34(abs), `.himi-write-${process.pid}-${randomBytes4(6).toString("hex")}.tmp`);
152638
+ const tmp = join66(dirname35(abs), `.himi-write-${process.pid}-${randomBytes4(6).toString("hex")}.tmp`);
152532
152639
  const fd = openSync5(tmp, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | (constants3.O_NOFOLLOW ?? 0), 420);
152533
152640
  try {
152534
152641
  writeSync(fd, content);
@@ -152536,9 +152643,9 @@ function writeNoFollow2(appDir3, abs, content) {
152536
152643
  closeSync6(fd);
152537
152644
  }
152538
152645
  const link = symlinkComponent(appDir3, abs);
152539
- if (link || !within(realpathSync10(appDir3), realpathSync10(dirname34(abs)))) {
152646
+ if (link || !within(realpathSync10(appDir3), realpathSync10(dirname35(abs)))) {
152540
152647
  rmSync15(tmp, { force: true });
152541
- throw new Error(`"${link ?? relative13(appDir3, dirname34(abs))}" changed into a link while writing`);
152648
+ throw new Error(`"${link ?? relative13(appDir3, dirname35(abs))}" changed into a link while writing`);
152542
152649
  }
152543
152650
  renameSync11(tmp, abs);
152544
152651
  }
@@ -152548,7 +152655,7 @@ function listFiles(appDir3) {
152548
152655
  const parentRel = relative13(appDir3, d2);
152549
152656
  for (const e2 of readdirSync30(d2, { withFileTypes: true }).sort((a2, b2) => a2.name.localeCompare(b2.name))) {
152550
152657
  if (e2.isSymbolicLink()) continue;
152551
- const p2 = join65(d2, e2.name);
152658
+ const p2 = join66(d2, e2.name);
152552
152659
  if (e2.isDirectory()) {
152553
152660
  if (isDeniedSourceDir(e2.name, parentRel) || isDeniedSourceDir(e2.name.toLowerCase(), parentRel)) continue;
152554
152661
  if (!walk2(p2)) return false;
@@ -152576,9 +152683,9 @@ function fileTools() {
152576
152683
  const root = resolve52(await d2.defaultDir());
152577
152684
  if (!existsSync63(root)) return ok({ ok: true, workspace: root, apps: [] });
152578
152685
  const apps = [];
152579
- if (existsSync63(join65(root, CONTENT_MARKER))) apps.push(".");
152686
+ if (existsSync63(join66(root, CONTENT_MARKER))) apps.push(".");
152580
152687
  for (const e2 of readdirSync30(root, { withFileTypes: true })) {
152581
- if (e2.isDirectory() && !e2.name.startsWith(".") && existsSync63(join65(root, e2.name, CONTENT_MARKER))) apps.push(e2.name);
152688
+ if (e2.isDirectory() && !e2.name.startsWith(".") && existsSync63(join66(root, e2.name, CONTENT_MARKER))) apps.push(e2.name);
152582
152689
  }
152583
152690
  return ok({ ok: true, workspace: root, apps: apps.sort() });
152584
152691
  }
@@ -152610,7 +152717,7 @@ function fileTools() {
152610
152717
  if (!existsSync63(p2) || !lstatSync20(p2).isFile()) return refuse5("not_found", `no file "${String(a2.path)}"`);
152611
152718
  const size = statSync16(p2).size;
152612
152719
  if (size > MAX_FILE_BYTES) return refuse5("too_large", `"${String(a2.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
152613
- return ok({ ok: true, path: a2.path, bytes: size, content: readFileSync73(p2, "utf8") });
152720
+ return ok({ ok: true, path: a2.path, bytes: size, content: readFileSync74(p2, "utf8") });
152614
152721
  }
152615
152722
  },
152616
152723
  {
@@ -153222,8 +153329,8 @@ __export(server_exports, {
153222
153329
  protectStdout: () => protectStdout,
153223
153330
  startMcpServer: () => startMcpServer
153224
153331
  });
153225
- import { mkdirSync as mkdirSync31, readFileSync as readFileSync74 } from "node:fs";
153226
- import { fileURLToPath as fileURLToPath22 } from "node:url";
153332
+ import { mkdirSync as mkdirSync31, readFileSync as readFileSync75 } from "node:fs";
153333
+ import { fileURLToPath as fileURLToPath23 } from "node:url";
153227
153334
  import { McpServer } from "@modelcontextprotocol/server";
153228
153335
  import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
153229
153336
  function protectStdout() {
@@ -153248,7 +153355,7 @@ async function firstRoot(server) {
153248
153355
  if (!server.server.getClientCapabilities()?.roots) return void 0;
153249
153356
  const { roots } = await server.server.listRoots();
153250
153357
  const uri = roots.find((r2) => r2.uri.startsWith("file://"))?.uri;
153251
- return uri ? fileURLToPath22(uri) : void 0;
153358
+ return uri ? fileURLToPath23(uri) : void 0;
153252
153359
  } catch {
153253
153360
  return void 0;
153254
153361
  }
@@ -153282,7 +153389,7 @@ async function startMcpServer(opts) {
153282
153389
  status: (dir) => previewStatus(dir, previewDeps),
153283
153390
  stop: (dir) => stopPreview(dir, previewDeps)
153284
153391
  },
153285
- readFile: (p2) => readFileSync74(p2),
153392
+ readFile: (p2) => readFileSync75(p2),
153286
153393
  login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login }),
153287
153394
  ...opts.workspace ? { workspaceBoundary: opts.workspace } : {}
153288
153395
  };
@@ -153326,20 +153433,20 @@ __export(native_decode_exports, {
153326
153433
  runNativeDecode: () => runNativeDecode
153327
153434
  });
153328
153435
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
153329
- import { existsSync as existsSync64, mkdtempSync as mkdtempSync2, readFileSync as readFileSync75, rmSync as rmSync16, writeFileSync as writeFileSync27 } from "node:fs";
153436
+ import { existsSync as existsSync64, mkdtempSync as mkdtempSync2, readFileSync as readFileSync76, rmSync as rmSync16, writeFileSync as writeFileSync27 } from "node:fs";
153330
153437
  import { tmpdir as tmpdir3 } from "node:os";
153331
- import { join as join66 } from "node:path";
153332
- import { fileURLToPath as fileURLToPath23 } from "node:url";
153438
+ import { join as join67 } from "node:path";
153439
+ import { fileURLToPath as fileURLToPath24 } from "node:url";
153333
153440
  function nativeDecodePackageDir() {
153334
- return fileURLToPath23(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
153441
+ return fileURLToPath24(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
153335
153442
  }
153336
153443
  function nativeDecodeAndroidHarnessDir() {
153337
- return fileURLToPath23(new URL("../../../tools/wix-sdk-android-tests/", import.meta.url));
153444
+ return fileURLToPath24(new URL("../../../tools/wix-sdk-android-tests/", import.meta.url));
153338
153445
  }
153339
153446
  function nativeOracleShipped() {
153340
153447
  return {
153341
- ios: existsSync64(join66(nativeDecodePackageDir(), "Package.swift")),
153342
- android: existsSync64(join66(nativeDecodeAndroidHarnessDir(), "gradlew"))
153448
+ ios: existsSync64(join67(nativeDecodePackageDir(), "Package.swift")),
153449
+ android: existsSync64(join67(nativeDecodeAndroidHarnessDir(), "gradlew"))
153343
153450
  };
153344
153451
  }
153345
153452
  function detectNativeDecode(options = {}) {
@@ -153350,7 +153457,7 @@ function detectNativeDecode(options = {}) {
153350
153457
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
153351
153458
  }
153352
153459
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
153353
- const packageAvailable = options.packageAvailable ?? existsSync64(join66(packageDir, "Package.swift"));
153460
+ const packageAvailable = options.packageAvailable ?? existsSync64(join67(packageDir, "Package.swift"));
153354
153461
  if (!packageAvailable) {
153355
153462
  return {
153356
153463
  platform: "ios",
@@ -153362,7 +153469,7 @@ function detectNativeDecode(options = {}) {
153362
153469
  }
153363
153470
  function localPropertiesSdk(harnessDir) {
153364
153471
  try {
153365
- const match = readFileSync75(join66(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
153472
+ const match = readFileSync76(join67(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
153366
153473
  return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
153367
153474
  } catch {
153368
153475
  return null;
@@ -153370,7 +153477,7 @@ function localPropertiesSdk(harnessDir) {
153370
153477
  }
153371
153478
  function detectAndroidNativeDecode(options = {}) {
153372
153479
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
153373
- const gradlew = join66(harnessDir, "gradlew");
153480
+ const gradlew = join67(harnessDir, "gradlew");
153374
153481
  const gradlewAvailable = options.gradlewAvailable ?? existsSync64(gradlew);
153375
153482
  if (!gradlewAvailable) {
153376
153483
  return {
@@ -153453,14 +153560,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
153453
153560
  return verdicts;
153454
153561
  }
153455
153562
  function runNativeDecode(options) {
153456
- const descriptorDir = mkdtempSync2(join66(tmpdir3(), "himi-native-decode-"));
153563
+ const descriptorDir = mkdtempSync2(join67(tmpdir3(), "himi-native-decode-"));
153457
153564
  const startedAt = Date.now();
153458
153565
  try {
153459
153566
  for (const descriptor of options.descriptors) {
153460
153567
  if (typeof descriptor.descriptorJson !== "string") {
153461
153568
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
153462
153569
  }
153463
- writeFileSync27(join66(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
153570
+ writeFileSync27(join67(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
153464
153571
  }
153465
153572
  options.progress?.("building cached Swift oracle");
153466
153573
  execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
@@ -153472,7 +153579,7 @@ function runNativeDecode(options) {
153472
153579
  encoding: "utf8"
153473
153580
  }).trim();
153474
153581
  options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
153475
- const stdout = execFileSync5(join66(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
153582
+ const stdout = execFileSync5(join67(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
153476
153583
  stdio: ["ignore", "pipe", "pipe"],
153477
153584
  encoding: "utf8"
153478
153585
  });
@@ -153490,15 +153597,15 @@ function runNativeDecode(options) {
153490
153597
  }
153491
153598
  }
153492
153599
  function runAndroidNativeDecode(options) {
153493
- const descriptorDir = mkdtempSync2(join66(tmpdir3(), "himi-native-decode-android-"));
153494
- const outputPath = join66(descriptorDir, "verdicts.ndjson");
153600
+ const descriptorDir = mkdtempSync2(join67(tmpdir3(), "himi-native-decode-android-"));
153601
+ const outputPath = join67(descriptorDir, "verdicts.ndjson");
153495
153602
  const startedAt = Date.now();
153496
153603
  try {
153497
153604
  for (const descriptor of options.descriptors) {
153498
153605
  if (typeof descriptor.descriptorJson !== "string") {
153499
153606
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
153500
153607
  }
153501
- writeFileSync27(join66(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
153608
+ writeFileSync27(join67(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
153502
153609
  }
153503
153610
  options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
153504
153611
  execFileSync5(options.gradlew, [
@@ -153513,7 +153620,7 @@ function runAndroidNativeDecode(options) {
153513
153620
  stdio: ["ignore", "ignore", "pipe"],
153514
153621
  encoding: "utf8"
153515
153622
  });
153516
- const stdout = readFileSync75(outputPath, "utf8");
153623
+ const stdout = readFileSync76(outputPath, "utf8");
153517
153624
  return {
153518
153625
  platform: "android",
153519
153626
  verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
@@ -153583,13 +153690,13 @@ __export(browser_authoring_exports, {
153583
153690
  });
153584
153691
  import { createServer as createServer5 } from "node:http";
153585
153692
  import { createHash as createHash35, randomBytes as randomBytes5 } from "node:crypto";
153586
- import { existsSync as existsSync65, readdirSync as readdirSync31, readFileSync as readFileSync76, realpathSync as realpathSync11, statSync as statSync17 } from "node:fs";
153587
- import { join as join67, posix as posix3, relative as relative14, sep as sep18 } from "node:path";
153693
+ import { existsSync as existsSync65, readdirSync as readdirSync31, readFileSync as readFileSync77, realpathSync as realpathSync11, statSync as statSync17 } from "node:fs";
153694
+ import { join as join68, posix as posix3, relative as relative14, sep as sep18 } from "node:path";
153588
153695
  function humanMs(ms2) {
153589
153696
  return ms2 < 1e3 ? `${ms2}ms` : `${Math.round(ms2 / 1e3)}s`;
153590
153697
  }
153591
153698
  function collectWorkerSources(tier5SrcDir, bundleName) {
153592
- const root = join67(tier5SrcDir, bundleName);
153699
+ const root = join68(tier5SrcDir, bundleName);
153593
153700
  const files = {};
153594
153701
  const visitedDirs = /* @__PURE__ */ new Set();
153595
153702
  const walk2 = (abs, rel) => {
@@ -153597,12 +153704,12 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
153597
153704
  if (visitedDirs.has(real)) return;
153598
153705
  visitedDirs.add(real);
153599
153706
  for (const name of readdirSync31(abs).sort()) {
153600
- const childAbs = join67(abs, name);
153707
+ const childAbs = join68(abs, name);
153601
153708
  const childRel = posix3.join(rel, name);
153602
153709
  if (statSync17(childAbs).isDirectory()) {
153603
153710
  walk2(childAbs, childRel);
153604
153711
  } else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
153605
- files[childRel] = readFileSync76(childAbs, "utf8");
153712
+ files[childRel] = readFileSync77(childAbs, "utf8");
153606
153713
  }
153607
153714
  }
153608
153715
  };
@@ -153623,20 +153730,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
153623
153730
  const spec = m2[1];
153624
153731
  const virtual = posix3.normalize(posix3.join(dir, spec));
153625
153732
  if (!virtual.startsWith("/tier5-src/")) continue;
153626
- const onDisk = join67(tier5SrcDir, virtual.slice("/tier5-src/".length));
153733
+ const onDisk = join68(tier5SrcDir, virtual.slice("/tier5-src/".length));
153627
153734
  const candidates = [
153628
153735
  onDisk,
153629
153736
  `${onDisk}.ts`,
153630
153737
  `${onDisk}.js`,
153631
153738
  onDisk.replace(/\.js$/, ".ts"),
153632
- join67(onDisk, "index.ts"),
153633
- join67(onDisk, "index.js")
153739
+ join68(onDisk, "index.ts"),
153740
+ join68(onDisk, "index.js")
153634
153741
  ];
153635
153742
  for (const abs of candidates) {
153636
153743
  if (!existsSync65(abs) || statSync17(abs).isDirectory()) continue;
153637
153744
  const key2 = `/tier5-src/${relative14(tier5SrcDir, abs).split(sep18).join(posix3.sep)}`;
153638
153745
  if (key2 in files) break;
153639
- files[key2] = readFileSync76(abs, "utf8");
153746
+ files[key2] = readFileSync77(abs, "utf8");
153640
153747
  queue.push(key2);
153641
153748
  break;
153642
153749
  }
@@ -153671,7 +153778,7 @@ function collectSdkModules(files, resolveSubpath) {
153671
153778
  function sdkSubpathReader(resolve61) {
153672
153779
  return (sub) => {
153673
153780
  try {
153674
- return readFileSync76(resolve61(`@wix/himalaya/${sub}`), "utf8");
153781
+ return readFileSync77(resolve61(`@wix/himalaya/${sub}`), "utf8");
153675
153782
  } catch {
153676
153783
  return null;
153677
153784
  }
@@ -153843,8 +153950,8 @@ __export(coverage_exports, {
153843
153950
  suppressedNativeKeys: () => suppressedNativeKeys,
153844
153951
  trendAndStore: () => trendAndStore
153845
153952
  });
153846
- import { existsSync as existsSync66, mkdirSync as mkdirSync32, readFileSync as readFileSync77, writeFileSync as writeFileSync28 } from "node:fs";
153847
- import { dirname as dirname35, join as join68 } from "node:path";
153953
+ import { existsSync as existsSync66, mkdirSync as mkdirSync32, readFileSync as readFileSync78, writeFileSync as writeFileSync28 } from "node:fs";
153954
+ import { dirname as dirname36, join as join69 } from "node:path";
153848
153955
  function suppressedNativeKeys(oracle) {
153849
153956
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
153850
153957
  }
@@ -154024,11 +154131,11 @@ function assembleLedger(r2, options = {}) {
154024
154131
  return out2;
154025
154132
  }
154026
154133
  function trendAndStore(dir, entries, suppressed) {
154027
- const p2 = join68(dir, LEDGER_FILE);
154134
+ const p2 = join69(dir, LEDGER_FILE);
154028
154135
  let previous = null;
154029
154136
  try {
154030
154137
  if (existsSync66(p2)) {
154031
- const parsed = JSON.parse(readFileSync77(p2, "utf8"));
154138
+ const parsed = JSON.parse(readFileSync78(p2, "utf8"));
154032
154139
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k2) => typeof k2 === "string");
154033
154140
  }
154034
154141
  } catch {
@@ -154036,7 +154143,7 @@ function trendAndStore(dir, entries, suppressed) {
154036
154143
  const current = entries.map((e2) => e2.key);
154037
154144
  const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
154038
154145
  try {
154039
- mkdirSync32(dirname35(p2), { recursive: true });
154146
+ mkdirSync32(dirname36(p2), { recursive: true });
154040
154147
  writeFileSync28(p2, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
154041
154148
  } catch {
154042
154149
  return null;
@@ -154067,11 +154174,11 @@ function formatLedger(entries, trend) {
154067
154174
  return out2.join("\n");
154068
154175
  }
154069
154176
  function diffAndStoreObservations(dir, current) {
154070
- const p2 = join68(dir, OBS_FILE);
154177
+ const p2 = join69(dir, OBS_FILE);
154071
154178
  let previous = null;
154072
154179
  try {
154073
154180
  if (existsSync66(p2)) {
154074
- const parsed = JSON.parse(readFileSync77(p2, "utf8"));
154181
+ const parsed = JSON.parse(readFileSync78(p2, "utf8"));
154075
154182
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
154076
154183
  (v2) => Array.isArray(v2) && v2.every((l2) => typeof l2 === "string")
154077
154184
  )) {
@@ -154081,7 +154188,7 @@ function diffAndStoreObservations(dir, current) {
154081
154188
  } catch {
154082
154189
  }
154083
154190
  try {
154084
- mkdirSync32(dirname35(p2), { recursive: true });
154191
+ mkdirSync32(dirname36(p2), { recursive: true });
154085
154192
  writeFileSync28(p2, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
154086
154193
  } catch {
154087
154194
  return null;
@@ -154120,8 +154227,8 @@ var LEDGER_FILE, OBS_FILE;
154120
154227
  var init_coverage = __esm({
154121
154228
  "src/coverage.ts"() {
154122
154229
  init_native_decode();
154123
- LEDGER_FILE = join68(".himi", "test-ledger.json");
154124
- OBS_FILE = join68(".himi", "test-observations.json");
154230
+ LEDGER_FILE = join69(".himi", "test-ledger.json");
154231
+ OBS_FILE = join69(".himi", "test-observations.json");
154125
154232
  }
154126
154233
  });
154127
154234
 
@@ -154132,9 +154239,9 @@ __export(design_kits_exports, {
154132
154239
  kitsDir: () => kitsDir,
154133
154240
  listKits: () => listKits2
154134
154241
  });
154135
- import { existsSync as existsSync67, readFileSync as readFileSync78, readdirSync as readdirSync32 } from "node:fs";
154136
- import { join as join69, basename as basename16 } from "node:path";
154137
- import { fileURLToPath as fileURLToPath24 } from "node:url";
154242
+ import { existsSync as existsSync67, readFileSync as readFileSync79, readdirSync as readdirSync32 } from "node:fs";
154243
+ import { join as join70, basename as basename16 } from "node:path";
154244
+ import { fileURLToPath as fileURLToPath25 } from "node:url";
154138
154245
  function kitsDir() {
154139
154246
  return KIT_DIR_CANDIDATES.find((p2) => existsSync67(p2));
154140
154247
  }
@@ -154160,7 +154267,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
154160
154267
  if (!kits.includes(name)) {
154161
154268
  return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
154162
154269
  }
154163
- const raw = readFileSync78(join69(dir, `${name}.json`), "utf8");
154270
+ const raw = readFileSync79(join70(dir, `${name}.json`), "utf8");
154164
154271
  let parsed;
154165
154272
  try {
154166
154273
  parsed = JSON.parse(raw);
@@ -154184,9 +154291,9 @@ var init_design_kits = __esm({
154184
154291
  "src/design-kits.ts"() {
154185
154292
  KIT_DIR_CANDIDATES = [
154186
154293
  // in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
154187
- join69(fileURLToPath24(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
154294
+ join70(fileURLToPath25(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
154188
154295
  // published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
154189
- join69(fileURLToPath24(new URL("..", import.meta.url)), "stdlib", "design-kits")
154296
+ join70(fileURLToPath25(new URL("..", import.meta.url)), "stdlib", "design-kits")
154190
154297
  ];
154191
154298
  }
154192
154299
  });
@@ -154200,11 +154307,11 @@ __export(assets_exports, {
154200
154307
  removeAssetPayload: () => removeAssetPayload,
154201
154308
  verifyReport: () => verifyReport
154202
154309
  });
154203
- import { readFileSync as readFileSync79 } from "node:fs";
154310
+ import { readFileSync as readFileSync80 } from "node:fs";
154204
154311
  import { basename as basename17 } from "node:path";
154205
154312
  function declaredAssets(dir) {
154206
154313
  return collectAssets(dir).map((a2) => {
154207
- const bytes2 = readFileSync79(a2.path);
154314
+ const bytes2 = readFileSync80(a2.path);
154208
154315
  return {
154209
154316
  name: a2.name,
154210
154317
  sha256: assetSha256(bytes2),
@@ -154281,7 +154388,7 @@ function verifyReport(dir, app, manifest) {
154281
154388
  };
154282
154389
  }
154283
154390
  function addAssetPayload(manifest, filePath, opts) {
154284
- const bytes2 = readFileSync79(filePath);
154391
+ const bytes2 = readFileSync80(filePath);
154285
154392
  const name = opts.name ?? basename17(filePath);
154286
154393
  const sha2566 = assetSha256(bytes2);
154287
154394
  const record2 = {
@@ -156072,10 +156179,10 @@ __export(run_exports, {
156072
156179
  runPackage: () => runPackage,
156073
156180
  withoutProdServe: () => withoutProdServe
156074
156181
  });
156075
- import { cpSync as cpSync2, existsSync as existsSync68, mkdirSync as mkdirSync33, mkdtempSync as mkdtempSync3, readFileSync as readFileSync80, rmSync as rmSync17, statSync as statSync18 } from "node:fs";
156182
+ import { cpSync as cpSync2, existsSync as existsSync68, mkdirSync as mkdirSync33, mkdtempSync as mkdtempSync3, readFileSync as readFileSync81, rmSync as rmSync17, statSync as statSync18 } from "node:fs";
156076
156183
  import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
156077
- import { dirname as dirname36, join as join70 } from "node:path";
156078
- import { fileURLToPath as fileURLToPath25 } from "node:url";
156184
+ import { dirname as dirname37, join as join71 } from "node:path";
156185
+ import { fileURLToPath as fileURLToPath26 } from "node:url";
156079
156186
  function makePackageRunHandler(opts) {
156080
156187
  const store = new FileReleaseStore(opts.releaseRoot);
156081
156188
  const webwixDirect = async () => {
@@ -156103,7 +156210,7 @@ async function fetchBytes(url) {
156103
156210
  async function resolvePackage(source, workDir) {
156104
156211
  const isUrl2 = /^https?:\/\//i.test(source);
156105
156212
  if (!isUrl2 && existsSync68(source) && statSync18(source).isDirectory()) {
156106
- const appDirManifest = join70(source, "release-manifest.json");
156213
+ const appDirManifest = join71(source, "release-manifest.json");
156107
156214
  if (existsSync68(appDirManifest)) {
156108
156215
  const opened2 = openPackageDir(source);
156109
156216
  if (!opened2.validation.ok) {
@@ -156113,9 +156220,9 @@ async function resolvePackage(source, workDir) {
156113
156220
  const app2 = opened2.header?.app ?? opened2.manifest?.app;
156114
156221
  if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
156115
156222
  if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
156116
- const root2 = workDir ?? mkdtempSync3(join70(tmpdir4(), "himi-run-"));
156117
- const target = join70(root2, app2);
156118
- if (join70(source) !== target) {
156223
+ const root2 = workDir ?? mkdtempSync3(join71(tmpdir4(), "himi-run-"));
156224
+ const target = join71(root2, app2);
156225
+ if (join71(source) !== target) {
156119
156226
  mkdirSync33(root2, { recursive: true });
156120
156227
  rmSync17(target, { recursive: true, force: true });
156121
156228
  cpSync2(source, target, { recursive: true });
@@ -156132,8 +156239,8 @@ async function resolvePackage(source, workDir) {
156132
156239
  }
156133
156240
  throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
156134
156241
  }
156135
- const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync80(source);
156136
- const root = workDir ?? mkdtempSync3(join70(tmpdir4(), "himi-run-"));
156242
+ const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync81(source);
156243
+ const root = workDir ?? mkdtempSync3(join71(tmpdir4(), "himi-run-"));
156137
156244
  const { app, appDir: appDir3 } = unpackTo(bytes2, root);
156138
156245
  const opened = openPackageDir(appDir3);
156139
156246
  if (!opened.validation.ok) {
@@ -156154,16 +156261,16 @@ async function resolvePackage(source, workDir) {
156154
156261
  async function loadPreviewAssets() {
156155
156262
  try {
156156
156263
  const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
156157
- const here = dirname36(fileURLToPath25(import.meta.url));
156264
+ const here = dirname37(fileURLToPath26(import.meta.url));
156158
156265
  const candidates = [
156159
- join70(here, "preview-assets.generated.bin"),
156266
+ join71(here, "preview-assets.generated.bin"),
156160
156267
  // published: copied next to the bundled CLI
156161
- join70(here, "../../../packages/serve/src/preview-assets.generated.bin")
156268
+ join71(here, "../../../packages/serve/src/preview-assets.generated.bin")
156162
156269
  // in-repo checkout
156163
156270
  ];
156164
156271
  for (const path2 of candidates) {
156165
156272
  if (!existsSync68(path2)) continue;
156166
- const blob = readFileSync80(path2);
156273
+ const blob = readFileSync81(path2);
156167
156274
  return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
156168
156275
  }
156169
156276
  return /* @__PURE__ */ new Map();
@@ -156300,10 +156407,10 @@ __export(run_browser_exports, {
156300
156407
  runInBrowser: () => runInBrowser
156301
156408
  });
156302
156409
  import { createServer as createServer7 } from "node:http";
156303
- import { existsSync as existsSync69, readFileSync as readFileSync81 } from "node:fs";
156410
+ import { existsSync as existsSync69, readFileSync as readFileSync82 } from "node:fs";
156304
156411
  import { spawnSync as spawnSync3 } from "node:child_process";
156305
- import { dirname as dirname37, resolve as resolve54 } from "node:path";
156306
- import { fileURLToPath as fileURLToPath26 } from "node:url";
156412
+ import { dirname as dirname38, resolve as resolve54 } from "node:path";
156413
+ import { fileURLToPath as fileURLToPath27 } from "node:url";
156307
156414
  function stagedDir() {
156308
156415
  return process.env.HIMI_BROWSER_PLANE_OUT ? resolve54(process.env.HIMI_BROWSER_PLANE_OUT) : resolve54(REPO, "packages", "serve", "dist", "browser-plane");
156309
156416
  }
@@ -156408,7 +156515,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
156408
156515
  }
156409
156516
  let bytes2;
156410
156517
  try {
156411
- bytes2 = readFileSync81(resolve54(stagedDir(), name));
156518
+ bytes2 = readFileSync82(resolve54(stagedDir(), name));
156412
156519
  } catch (e2) {
156413
156520
  res.writeHead(503, { "content-type": "application/json" });
156414
156521
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e2) }));
@@ -156450,7 +156557,7 @@ var init_run_browser = __esm({
156450
156557
  init_open_url();
156451
156558
  init_file_store();
156452
156559
  init_wix_client_id();
156453
- HERE2 = dirname37(fileURLToPath26(import.meta.url));
156560
+ HERE2 = dirname38(fileURLToPath27(import.meta.url));
156454
156561
  REPO = resolve54(HERE2, "..", "..", "..");
156455
156562
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
156456
156563
  }
@@ -156461,14 +156568,14 @@ var hhp_preview_exports = {};
156461
156568
  __export(hhp_preview_exports, {
156462
156569
  hhpPreviewResponse: () => hhpPreviewResponse
156463
156570
  });
156464
- import { existsSync as existsSync70, readFileSync as readFileSync82 } from "node:fs";
156465
- import { join as join71 } from "node:path";
156571
+ import { existsSync as existsSync70, readFileSync as readFileSync83 } from "node:fs";
156572
+ import { join as join72 } from "node:path";
156466
156573
  function hhpPreviewResponse(root, request) {
156467
- if (new URL(request.url).pathname !== "/__himi/hhp-preview" || !existsSync70(join71(root, "hhp.json"))) return null;
156574
+ if (new URL(request.url).pathname !== "/__himi/hhp-preview" || !existsSync70(join72(root, "hhp.json"))) return null;
156468
156575
  if (request.method !== "GET") return new Response(null, { status: 405 });
156469
156576
  try {
156470
156577
  const file2 = localPath(root, ".himi/hhp-preview.json");
156471
- const authored2 = existsSync70(file2) ? JSON.parse(readFileSync82(file2, "utf8")) : {};
156578
+ const authored2 = existsSync70(file2) ? JSON.parse(readFileSync83(file2, "utf8")) : {};
156472
156579
  if (authored2.mockCapabilities && (!Array.isArray(authored2.mockCapabilities) || authored2.mockCapabilities.some((v2) => typeof v2 !== "string"))) throw new Error("mockCapabilities must be a string array.");
156473
156580
  const fixtures = authored2.fixtures ?? {};
156474
156581
  if (typeof fixtures !== "object" || Array.isArray(fixtures) || fixtures === null) throw new Error("fixtures must be an object.");
@@ -156618,7 +156725,7 @@ var init_embedded_bundles = __esm({
156618
156725
  });
156619
156726
 
156620
156727
  // ../store-release/register-bundle.ts
156621
- import { readFileSync as readFileSync83 } from "node:fs";
156728
+ import { readFileSync as readFileSync84 } from "node:fs";
156622
156729
  import { createPrivateKey as createPrivateKey4, sign as sign2 } from "node:crypto";
156623
156730
  function b64url2(b2) {
156624
156731
  return Buffer.from(b2).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -156636,7 +156743,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
156636
156743
  async function registerBundleId(opts) {
156637
156744
  const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
156638
156745
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
156639
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync83(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
156746
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync84(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
156640
156747
  const res = await fetch(`${ASC_API}/v1/bundleIds`, {
156641
156748
  method: "POST",
156642
156749
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
@@ -156666,7 +156773,7 @@ async function main() {
156666
156773
  }
156667
156774
  const ni2 = rest.indexOf("--name");
156668
156775
  const name = ni2 >= 0 ? rest[ni2 + 1] : cfg.app ?? app;
156669
- const yml = readFileSync83(iosProjectYml(app), "utf8");
156776
+ const yml = readFileSync84(iosProjectYml(app), "utf8");
156670
156777
  for (const { id, label: label2 } of [{ id: identifier, label: name }, ...embeddedBundles(yml).map((b2) => ({
156671
156778
  id: embeddedBundleId(identifier, b2),
156672
156779
  label: `${name} ${embeddedAppIdLabel(b2)}`
@@ -156707,7 +156814,7 @@ function retryAfterMs(header, nowMs) {
156707
156814
  function backoffMs(attempt) {
156708
156815
  return Math.min(BASE_BACKOFF_MS * 2 ** (attempt - 1), MAX_RETRY_WAIT_MS);
156709
156816
  }
156710
- async function readJson6(response) {
156817
+ async function readJson7(response) {
156711
156818
  try {
156712
156819
  return await response.json();
156713
156820
  } catch {
@@ -156821,7 +156928,7 @@ var init_iap_client = __esm({
156821
156928
  }
156822
156929
  async send(method, url, body) {
156823
156930
  const response = await this.fetchOrNetworkError(method, url, body);
156824
- const payload = await readJson6(response);
156931
+ const payload = await readJson7(response);
156825
156932
  if (!response.ok) throw this.httpError(method, url, response, payload);
156826
156933
  if (payload === void 0 && response.status !== 204) {
156827
156934
  throw new AscError("server", `${method} ${url.pathname} \u2192 ${response.status} with an unreadable body`, response.status);
@@ -158075,19 +158182,19 @@ __export(credential_profile_exports, {
158075
158182
  profilePath: () => profilePath,
158076
158183
  resolveStoreCredentials: () => resolveStoreCredentials
158077
158184
  });
158078
- import { existsSync as existsSync71, readFileSync as readFileSync84 } from "node:fs";
158079
- import { homedir as homedir6 } from "node:os";
158080
- import { join as join72 } from "node:path";
158081
- function credentialsDir(home = homedir6()) {
158082
- return join72(home, ".himalaya", "store-credentials");
158185
+ import { existsSync as existsSync71, readFileSync as readFileSync85 } from "node:fs";
158186
+ import { homedir as homedir7 } from "node:os";
158187
+ import { join as join73 } from "node:path";
158188
+ function credentialsDir(home = homedir7()) {
158189
+ return join73(home, ".himalaya", "store-credentials");
158083
158190
  }
158084
- function profilePath(name, home = homedir6()) {
158191
+ function profilePath(name, home = homedir7()) {
158085
158192
  if (!PROFILE_NAME.test(name)) {
158086
158193
  throw new Error(
158087
- `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join72(credentialsDir(home), "<name>.json")}; it is never a path.`
158194
+ `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join73(credentialsDir(home), "<name>.json")}; it is never a path.`
158088
158195
  );
158089
158196
  }
158090
- return join72(credentialsDir(home), `${name}.json`);
158197
+ return join73(credentialsDir(home), `${name}.json`);
158091
158198
  }
158092
158199
  function parseProfile(text9, label2) {
158093
158200
  let doc;
@@ -158117,8 +158224,8 @@ function namedProfile(cfg, profileFlag) {
158117
158224
  function resolveStoreCredentials(opts) {
158118
158225
  const { app, cfg } = opts;
158119
158226
  const env = opts.env ?? process.env;
158120
- const home = opts.home ?? homedir6();
158121
- const read = opts.readProfile ?? ((p2) => readFileSync84(p2, "utf8"));
158227
+ const home = opts.home ?? homedir7();
158228
+ const read = opts.readProfile ?? ((p2) => readFileSync85(p2, "utf8"));
158122
158229
  const exists = opts.profileExists ?? existsSync71;
158123
158230
  const ios = cfg.ios ?? {};
158124
158231
  const flagName = opts.profileFlag?.trim();
@@ -158185,8 +158292,8 @@ var init_credential_profile = __esm({
158185
158292
 
158186
158293
  // ../store-release/iap-credentials.ts
158187
158294
  import { createHash as createHash37 } from "node:crypto";
158188
- import { existsSync as existsSync72, readFileSync as readFileSync85, realpathSync as realpathSync12 } from "node:fs";
158189
- import { homedir as homedir7 } from "node:os";
158295
+ import { existsSync as existsSync72, readFileSync as readFileSync86, realpathSync as realpathSync12 } from "node:fs";
158296
+ import { homedir as homedir8 } from "node:os";
158190
158297
  function accountFingerprint(keyId, issuerId) {
158191
158298
  return `sha256:${createHash37("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
158192
158299
  }
@@ -158218,8 +158325,8 @@ function canonicalKeyPath(path2, profile, realpath) {
158218
158325
  }
158219
158326
  function resolveIapCredentials(options) {
158220
158327
  const { target } = options;
158221
- const home = options.home ?? homedir7();
158222
- const readFile3 = options.readFile ?? ((p2) => readFileSync85(p2, "utf8"));
158328
+ const home = options.home ?? homedir8();
158329
+ const readFile3 = options.readFile ?? ((p2) => readFileSync86(p2, "utf8"));
158223
158330
  const realpath = options.realpath ?? realpathSync12;
158224
158331
  const profile = requireExplicitProfile(options.profileFlag, target);
158225
158332
  const creds = resolveStoreCredentials({
@@ -158540,7 +158647,7 @@ __export(version_exports, {
158540
158647
  stampTargetVersion: () => stampTargetVersion,
158541
158648
  stampVersionKeys: () => stampVersionKeys
158542
158649
  });
158543
- import { readFileSync as readFileSync86, writeFileSync as writeFileSync29 } from "node:fs";
158650
+ import { readFileSync as readFileSync87, writeFileSync as writeFileSync29 } from "node:fs";
158544
158651
  function readIosVersion(projectYml) {
158545
158652
  const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
158546
158653
  const build3 = matchScalar(projectYml, "CFBundleVersion");
@@ -158687,8 +158794,8 @@ function setAndroidVersion(gradle, v2) {
158687
158794
  function bumpVersion(app, opts) {
158688
158795
  const iosPath = iosProjectYml(app);
158689
158796
  const gradlePath = androidGradle(app);
158690
- const iosYml = readFileSync86(iosPath, "utf8");
158691
- const gradle = readFileSync86(gradlePath, "utf8");
158797
+ const iosYml = readFileSync87(iosPath, "utf8");
158798
+ const gradle = readFileSync87(gradlePath, "utf8");
158692
158799
  const current = readIosVersion(iosYml);
158693
158800
  const next = {
158694
158801
  marketing: opts.marketing ?? current.marketing,
@@ -158718,8 +158825,8 @@ var init_store_spec = __esm({
158718
158825
  });
158719
158826
 
158720
158827
  // src/iap-config-edit.ts
158721
- import { existsSync as existsSync73, readFileSync as readFileSync87 } from "node:fs";
158722
- import { basename as basename18, join as join73 } from "node:path";
158828
+ import { existsSync as existsSync73, readFileSync as readFileSync88 } from "node:fs";
158829
+ import { basename as basename18, join as join74 } from "node:path";
158723
158830
  import ts8 from "typescript";
158724
158831
  function bindPurchasesAppInConfig(source, options) {
158725
158832
  const fileName = options.fileName ?? "config.ts";
@@ -158798,16 +158905,16 @@ function capabilityFinding(app, fileName) {
158798
158905
  }
158799
158906
  function withStoreBundle(dir, options) {
158800
158907
  if (options.storeBundleId) return options;
158801
- const path2 = join73(dir, "store", "store.config.yaml");
158908
+ const path2 = join74(dir, "store", "store.config.yaml");
158802
158909
  if (!existsSync73(path2)) return options;
158803
- const storeBundleId = parseStoreConfig(readFileSync87(path2, "utf8")).ios?.bundleId;
158910
+ const storeBundleId = parseStoreConfig(readFileSync88(path2, "utf8")).ios?.bundleId;
158804
158911
  return storeBundleId ? { ...options, storeBundleId } : options;
158805
158912
  }
158806
158913
  function previewIapConfigEdit(dir, options) {
158807
158914
  const path2 = configEntry(dir);
158808
158915
  if (!path2) return void 0;
158809
158916
  if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${basename18(path2)} is a symlink, so it would not be edited: add the purchases app in the file it points to.`] };
158810
- const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync87(path2, "utf8"), { ...withStoreBundle(dir, options), fileName: basename18(path2) });
158917
+ const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync88(path2, "utf8"), { ...withStoreBundle(dir, options), fileName: basename18(path2) });
158811
158918
  return { path: path2, changed, applied, conflicts, instructions };
158812
158919
  }
158813
158920
  async function applyIapConfigEdit(dir, options, validate4) {
@@ -158816,7 +158923,7 @@ async function applyIapConfigEdit(dir, options, validate4) {
158816
158923
  const fileName = basename18(path2);
158817
158924
  const refuse7 = (why) => ({ path: path2, changed: false, applied: [], conflicts: [], instructions: [why] });
158818
158925
  if (isSymlink2(path2)) return refuse7(`${fileName} is a symlink, so it was not edited: add the purchases app in the file it points to.`);
158819
- const original = readFileSync87(path2, "utf8");
158926
+ const original = readFileSync88(path2, "utf8");
158820
158927
  const edit = bindPurchasesAppInConfig(original, { ...withStoreBundle(dir, options), fileName });
158821
158928
  const { applied, conflicts, instructions } = edit;
158822
158929
  if (!edit.changed) return { path: path2, changed: false, applied, conflicts, instructions };
@@ -159289,9 +159396,9 @@ __export(store_iap_exports, {
159289
159396
  runStoreIap: () => runStoreIap
159290
159397
  });
159291
159398
  import { randomUUID as randomUUID8 } from "node:crypto";
159292
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync34, readFileSync as readFileSync88, realpathSync as realpathSync13, rmSync as rmSync18, writeFileSync as writeFileSync30 } from "node:fs";
159293
- import { homedir as homedir8, hostname } from "node:os";
159294
- import { join as join74 } from "node:path";
159399
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync34, readFileSync as readFileSync89, realpathSync as realpathSync13, rmSync as rmSync18, writeFileSync as writeFileSync30 } from "node:fs";
159400
+ import { homedir as homedir9, hostname } from "node:os";
159401
+ import { join as join75 } from "node:path";
159295
159402
  function scrubDeep(value, scrub) {
159296
159403
  if (typeof value === "string") return scrub(value);
159297
159404
  if (Array.isArray(value)) return value.map((v2) => scrubDeep(v2, scrub));
@@ -159747,14 +159854,14 @@ function fileJournal(path2) {
159747
159854
  }
159748
159855
  function readLockSummary(path2) {
159749
159856
  try {
159750
- const { pid, host, at: at2 } = JSON.parse(readFileSync88(path2, "utf8"));
159857
+ const { pid, host, at: at2 } = JSON.parse(readFileSync89(path2, "utf8"));
159751
159858
  return `pid ${pid} on ${host} since ${at2}`;
159752
159859
  } catch {
159753
159860
  return "unreadable lock";
159754
159861
  }
159755
159862
  }
159756
159863
  function acquireApplyLock(dir, appleAppId) {
159757
- const path2 = join74(dir, "apply.lock");
159864
+ const path2 = join75(dir, "apply.lock");
159758
159865
  const stamp = JSON.stringify({ pid: process.pid, host: hostname(), at: (/* @__PURE__ */ new Date()).toISOString(), token: randomUUID8() });
159759
159866
  try {
159760
159867
  writeFileSync30(path2, stamp, { flag: "wx", mode: 384 });
@@ -159767,7 +159874,7 @@ function acquireApplyLock(dir, appleAppId) {
159767
159874
  return () => {
159768
159875
  let current = "";
159769
159876
  try {
159770
- current = readFileSync88(path2, "utf8");
159877
+ current = readFileSync89(path2, "utf8");
159771
159878
  } catch {
159772
159879
  return;
159773
159880
  }
@@ -159775,7 +159882,7 @@ function acquireApplyLock(dir, appleAppId) {
159775
159882
  };
159776
159883
  }
159777
159884
  function stateDir(appleAppId) {
159778
- const dir = join74(homedir8(), ".himalaya", "store-iap", appleAppId);
159885
+ const dir = join75(homedir9(), ".himalaya", "store-iap", appleAppId);
159779
159886
  mkdirSync34(dir, { recursive: true, mode: 448 });
159780
159887
  return dir;
159781
159888
  }
@@ -159791,11 +159898,11 @@ async function confirmOnTerminal(question) {
159791
159898
  }
159792
159899
  function defaultStoreIapDeps() {
159793
159900
  return {
159794
- readFile: (path2) => readFileSync88(path2, "utf8"),
159901
+ readFile: (path2) => readFileSync89(path2, "utf8"),
159795
159902
  writeFileAtomic,
159796
159903
  resolveCredentials: ({ profileFlag, target }) => resolveIapCredentials({ profileFlag, target }),
159797
159904
  createApi: (key2) => createIapApi(createAscClient({ key: key2 })),
159798
- openJournal: (appleAppId) => fileJournal(join74(stateDir(appleAppId), "journal.jsonl")),
159905
+ openJournal: (appleAppId) => fileJournal(join75(stateDir(appleAppId), "journal.jsonl")),
159799
159906
  acquireLock: (appleAppId) => acquireApplyLock(stateDir(appleAppId), appleAppId),
159800
159907
  canPrompt: () => process.stdin.isTTY === true,
159801
159908
  wixTransport: (siteId) => ownerTransport(siteId),
@@ -160273,9 +160380,9 @@ __export(preflight_app_exports, {
160273
160380
  preflightApp: () => preflightApp,
160274
160381
  profileAccount: () => profileAccount
160275
160382
  });
160276
- import { readFileSync as readFileSync89, existsSync as existsSync74, readdirSync as readdirSync33, statSync as statSync19 } from "node:fs";
160383
+ import { readFileSync as readFileSync90, existsSync as existsSync74, readdirSync as readdirSync33, statSync as statSync19 } from "node:fs";
160277
160384
  import { createHash as createHash39 } from "node:crypto";
160278
- import { join as join75 } from "node:path";
160385
+ import { join as join76 } from "node:path";
160279
160386
  function analyze(projectYml, storeConfig, icon, account) {
160280
160387
  const f2 = [];
160281
160388
  const has = (re2, s2) => re2.test(s2);
@@ -160339,13 +160446,13 @@ function profileAccount(app, storeConfig, opts = {}) {
160339
160446
  }
160340
160447
  }
160341
160448
  async function preflightApp(app, opts = {}) {
160342
- const projectYml = existsSync74(iosProjectYml(app)) ? readFileSync89(iosProjectYml(app), "utf8") : "";
160343
- const storeConfig = existsSync74(storeConfigPath(app)) ? readFileSync89(storeConfigPath(app), "utf8") : "";
160449
+ const projectYml = existsSync74(iosProjectYml(app)) ? readFileSync90(iosProjectYml(app), "utf8") : "";
160450
+ const storeConfig = existsSync74(storeConfigPath(app)) ? readFileSync90(storeConfigPath(app), "utf8") : "";
160344
160451
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
160345
160452
  const findings = analyze(
160346
160453
  projectYml,
160347
160454
  storeConfig,
160348
- await appIconState(join75(appDir(app), "ios")),
160455
+ await appIconState(join76(appDir(app), "ios")),
160349
160456
  profileAccount(app, storeConfig, opts)
160350
160457
  );
160351
160458
  findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
@@ -160374,16 +160481,16 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
160374
160481
  return f2;
160375
160482
  }
160376
160483
  function appLevelMetadataFiles(app, locale = "en-US") {
160377
- const root = join75(storeDir(app), "metadata");
160484
+ const root = join76(storeDir(app), "metadata");
160378
160485
  const out2 = /* @__PURE__ */ new Set();
160379
160486
  if (existsSync74(root)) {
160380
160487
  for (const n2 of readdirSync33(root)) if (n2.endsWith(".txt")) out2.add(n2);
160381
160488
  }
160382
- if (existsSync74(join75(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
160489
+ if (existsSync74(join76(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
160383
160490
  return out2;
160384
160491
  }
160385
160492
  function reviewInfoFiles(app) {
160386
- const dir = join75(storeDir(app), "review_information");
160493
+ const dir = join76(storeDir(app), "review_information");
160387
160494
  if (!existsSync74(dir)) return /* @__PURE__ */ new Set();
160388
160495
  return new Set(readdirSync33(dir).filter((n2) => n2.endsWith(".txt")));
160389
160496
  }
@@ -160494,12 +160601,12 @@ function analyzePlayListing(assets) {
160494
160601
  return f2;
160495
160602
  }
160496
160603
  function playListingAssets(app, locale = "en-US") {
160497
- const dir = join75(storeDir(app), "play", locale, "images");
160604
+ const dir = join76(storeDir(app), "play", locale, "images");
160498
160605
  const read = (names) => {
160499
160606
  for (const name of names) {
160500
- const p2 = join75(dir, name);
160607
+ const p2 = join76(dir, name);
160501
160608
  try {
160502
- if (statSync19(p2).isFile()) return { name, bytes: readFileSync89(p2) };
160609
+ if (statSync19(p2).isFile()) return { name, bytes: readFileSync90(p2) };
160503
160610
  } catch {
160504
160611
  }
160505
160612
  }
@@ -160530,26 +160637,26 @@ function analyzeListing(metaFiles, shots) {
160530
160637
  return f2;
160531
160638
  }
160532
160639
  function metadataFilesPresent(app, locale = "en-US") {
160533
- const dir = join75(storeDir(app), "metadata", locale);
160640
+ const dir = join76(storeDir(app), "metadata", locale);
160534
160641
  if (!existsSync74(dir)) return /* @__PURE__ */ new Set();
160535
160642
  return new Set(readdirSync33(dir).filter((n2) => n2.endsWith(".txt")));
160536
160643
  }
160537
160644
  function listScreenshots(app, locale = "en-US") {
160538
160645
  const out2 = [];
160539
- const flat = join75(storeDir(app), "screenshots", locale);
160646
+ const flat = join76(storeDir(app), "screenshots", locale);
160540
160647
  if (existsSync74(flat)) {
160541
160648
  for (const png of readdirSync33(flat).filter((n2) => n2.endsWith(".png"))) {
160542
- const sz = pngSize(readFileSync89(join75(flat, png)));
160649
+ const sz = pngSize(readFileSync90(join76(flat, png)));
160543
160650
  if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
160544
160651
  }
160545
160652
  }
160546
- const legacy = join75(storeDir(app), "metadata", locale, "screenshots");
160653
+ const legacy = join76(storeDir(app), "metadata", locale, "screenshots");
160547
160654
  if (existsSync74(legacy)) {
160548
160655
  for (const deviceDir of readdirSync33(legacy)) {
160549
- const d2 = join75(legacy, deviceDir);
160656
+ const d2 = join76(legacy, deviceDir);
160550
160657
  if (!statSync19(d2).isDirectory()) continue;
160551
160658
  for (const png of readdirSync33(d2).filter((n2) => n2.endsWith(".png"))) {
160552
- const sz = pngSize(readFileSync89(join75(d2, png)));
160659
+ const sz = pngSize(readFileSync90(join76(d2, png)));
160553
160660
  if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
160554
160661
  }
160555
160662
  }
@@ -160557,13 +160664,13 @@ function listScreenshots(app, locale = "en-US") {
160557
160664
  return out2;
160558
160665
  }
160559
160666
  function placeholderHashes2() {
160560
- const templateIos = join75(appDir("_template"), "ios");
160667
+ const templateIos = join76(appDir("_template"), "ios");
160561
160668
  if (!existsSync74(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
160562
160669
  for (const target of readdirSync33(templateIos)) {
160563
- const p2 = join75(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
160670
+ const p2 = join76(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
160564
160671
  try {
160565
160672
  if (!statSync19(p2).isFile()) continue;
160566
- return [LEGACY_PLACEHOLDER_SHA2562, createHash39("sha256").update(readFileSync89(p2)).digest("hex")];
160673
+ return [LEGACY_PLACEHOLDER_SHA2562, createHash39("sha256").update(readFileSync90(p2)).digest("hex")];
160567
160674
  } catch {
160568
160675
  }
160569
160676
  }
@@ -160596,10 +160703,10 @@ async function pixelIssues(bytes2) {
160596
160703
  async function appIconState(iosDir) {
160597
160704
  if (!existsSync74(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
160598
160705
  for (const target of readdirSync33(iosDir)) {
160599
- const p2 = join75(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
160706
+ const p2 = join76(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
160600
160707
  try {
160601
160708
  if (!statSync19(p2).isFile()) continue;
160602
- const bytes2 = readFileSync89(p2);
160709
+ const bytes2 = readFileSync90(p2);
160603
160710
  const hash2 = createHash39("sha256").update(bytes2).digest("hex");
160604
160711
  const pixels = await pixelIssues(bytes2);
160605
160712
  return {
@@ -160666,7 +160773,7 @@ __export(asc_status_exports, {
160666
160773
  ascStatus: () => ascStatus,
160667
160774
  buildVerdict: () => buildVerdict
160668
160775
  });
160669
- import { readFileSync as readFileSync90 } from "node:fs";
160776
+ import { readFileSync as readFileSync91 } from "node:fs";
160670
160777
  function buildVerdict(builds) {
160671
160778
  if (!builds.length) {
160672
160779
  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).";
@@ -160680,7 +160787,7 @@ function buildVerdict(builds) {
160680
160787
  function client(creds) {
160681
160788
  const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
160682
160789
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
160683
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync90(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
160790
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync91(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
160684
160791
  return async (path2) => {
160685
160792
  const r2 = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
160686
160793
  return { status: r2.status, json: await r2.json().catch(() => ({})) };
@@ -160729,7 +160836,7 @@ var init_asc_status = __esm({
160729
160836
  // ../../core/functions-secrets/src/vault.ts
160730
160837
  import { createCipheriv, createDecipheriv as createDecipheriv2, randomBytes as randomBytes6 } from "node:crypto";
160731
160838
  import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
160732
- import { dirname as dirname38 } from "node:path";
160839
+ import { dirname as dirname39 } from "node:path";
160733
160840
  function createJsonSecretStore(filePath) {
160734
160841
  const read = async () => {
160735
160842
  try {
@@ -160742,7 +160849,7 @@ function createJsonSecretStore(filePath) {
160742
160849
  }
160743
160850
  };
160744
160851
  const write2 = async (records) => {
160745
- await mkdir(dirname38(filePath), { recursive: true });
160852
+ await mkdir(dirname39(filePath), { recursive: true });
160746
160853
  const temporary = `${filePath}.${process.pid}.tmp`;
160747
160854
  await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
160748
160855
  `, { mode: 384 });
@@ -160840,7 +160947,7 @@ __export(secrets_exports, {
160840
160947
  runRemoteSecretsCommand: () => runRemoteSecretsCommand,
160841
160948
  runSecretsCommand: () => runSecretsCommand
160842
160949
  });
160843
- import { readFileSync as readFileSync91 } from "node:fs";
160950
+ import { readFileSync as readFileSync92 } from "node:fs";
160844
160951
  function environment(value) {
160845
160952
  if (value === "preview" || value === "production") return value;
160846
160953
  throw new Error("--environment must be preview or production");
@@ -160871,7 +160978,7 @@ async function runSecretsCommand(operation, flags, io2, options = {}) {
160871
160978
  io2.log(JSON.stringify(await vault.list({ app, environment: env })));
160872
160979
  return 0;
160873
160980
  }
160874
- const value = options.readValue ? options.readValue() : readFileSync91(0, "utf8").replace(/\r?\n$/, "");
160981
+ const value = options.readValue ? options.readValue() : readFileSync92(0, "utf8").replace(/\r?\n$/, "");
160875
160982
  if (operation === "set") await vault.set({ app, environment: env, name, value });
160876
160983
  else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
160877
160984
  else throw new Error(`unknown secrets operation ${operation}`);
@@ -160900,7 +161007,7 @@ async function runRemoteSecretsCommand(operation, flags, io2, options) {
160900
161007
  }
160901
161008
  let body;
160902
161009
  if (operation !== "list") {
160903
- const value = options.readValue ? options.readValue() : readFileSync91(0, "utf8").replace(/\r?\n$/, "");
161010
+ const value = options.readValue ? options.readValue() : readFileSync92(0, "utf8").replace(/\r?\n$/, "");
160904
161011
  body = JSON.stringify({ value });
160905
161012
  }
160906
161013
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
@@ -161398,15 +161505,15 @@ __export(notify_exports, {
161398
161505
  runNotify: () => runNotify,
161399
161506
  saveAdminSession: () => saveAdminSession
161400
161507
  });
161401
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync35, readFileSync as readFileSync92, writeFileSync as writeFileSync31 } from "node:fs";
161402
- import { homedir as homedir9 } from "node:os";
161403
- import { dirname as dirname39, join as join76 } from "node:path";
161508
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync35, readFileSync as readFileSync93, writeFileSync as writeFileSync31 } from "node:fs";
161509
+ import { homedir as homedir10 } from "node:os";
161510
+ import { dirname as dirname40, join as join77 } from "node:path";
161404
161511
  function defaultSessionsPath() {
161405
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join76(homedir9(), ".himalaya", "admin-sessions.json");
161512
+ return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join77(homedir10(), ".himalaya", "admin-sessions.json");
161406
161513
  }
161407
161514
  function loadSessionsFile(path2 = defaultSessionsPath()) {
161408
161515
  try {
161409
- return JSON.parse(readFileSync92(path2, "utf8"));
161516
+ return JSON.parse(readFileSync93(path2, "utf8"));
161410
161517
  } catch {
161411
161518
  return {};
161412
161519
  }
@@ -161414,10 +161521,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
161414
161521
  function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
161415
161522
  const file2 = loadSessionsFile(path2);
161416
161523
  file2.sessions = { ...file2.sessions, [adminUrl]: session };
161417
- mkdirSync35(dirname39(path2), { recursive: true, mode: 448 });
161524
+ mkdirSync35(dirname40(path2), { recursive: true, mode: 448 });
161418
161525
  writeFileSync31(path2, JSON.stringify(file2, null, 2) + "\n", { mode: 384 });
161419
161526
  try {
161420
- chmodSync3(dirname39(path2), 448);
161527
+ chmodSync3(dirname40(path2), 448);
161421
161528
  chmodSync3(path2, 384);
161422
161529
  } catch {
161423
161530
  }
@@ -161783,20 +161890,20 @@ __export(base44_auth_exports, {
161783
161890
  usableBase44Auth: () => usableBase44Auth,
161784
161891
  writeBase44Session: () => writeBase44Session
161785
161892
  });
161786
- import { chmodSync as chmodSync4, existsSync as existsSync75, mkdirSync as mkdirSync36, readFileSync as readFileSync93, rmSync as rmSync19, writeFileSync as writeFileSync32 } from "node:fs";
161787
- import { homedir as homedir10 } from "node:os";
161788
- import { dirname as dirname40, join as join77 } from "node:path";
161893
+ import { chmodSync as chmodSync4, existsSync as existsSync75, mkdirSync as mkdirSync36, readFileSync as readFileSync94, rmSync as rmSync19, writeFileSync as writeFileSync32 } from "node:fs";
161894
+ import { homedir as homedir11 } from "node:os";
161895
+ import { dirname as dirname41, join as join78 } from "node:path";
161789
161896
  function base44ApiBase(env = process.env) {
161790
161897
  return (env.BASE44_API_URL?.trim() || "https://app.base44.com").replace(/\/+$/, "");
161791
161898
  }
161792
- function base44SessionPath(home = homedir10()) {
161793
- return join77(home, ".himi", "base44", "session.json");
161899
+ function base44SessionPath(home = homedir11()) {
161900
+ return join78(home, ".himi", "base44", "session.json");
161794
161901
  }
161795
161902
  function readBase44Session(home) {
161796
161903
  const p2 = base44SessionPath(home);
161797
161904
  if (!existsSync75(p2)) return void 0;
161798
161905
  try {
161799
- const s2 = JSON.parse(readFileSync93(p2, "utf8"));
161906
+ const s2 = JSON.parse(readFileSync94(p2, "utf8"));
161800
161907
  return typeof s2.accessToken === "string" && s2.accessToken ? s2 : void 0;
161801
161908
  } catch {
161802
161909
  return void 0;
@@ -161804,7 +161911,7 @@ function readBase44Session(home) {
161804
161911
  }
161805
161912
  function writeBase44Session(session, home) {
161806
161913
  const p2 = base44SessionPath(home);
161807
- mkdirSync36(dirname40(p2), { recursive: true, mode: 448 });
161914
+ mkdirSync36(dirname41(p2), { recursive: true, mode: 448 });
161808
161915
  writeFileSync32(p2, `${JSON.stringify(session, null, 2)}
161809
161916
  `, { mode: 384 });
161810
161917
  chmodSync4(p2, 384);
@@ -161906,10 +162013,10 @@ async function base44DeviceLogin(opts) {
161906
162013
  }
161907
162014
  throw new Error("the Base44 sign-in code expired before it was approved \u2014 run `himi base44 login` again");
161908
162015
  }
161909
- function importBase44CliSession(home = homedir10(), env = process.env) {
161910
- const src = join77(home, ".base44", "auth", "auth.json");
162016
+ function importBase44CliSession(home = homedir11(), env = process.env) {
162017
+ const src = join78(home, ".base44", "auth", "auth.json");
161911
162018
  if (!existsSync75(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
161912
- const a2 = JSON.parse(readFileSync93(src, "utf8"));
162019
+ const a2 = JSON.parse(readFileSync94(src, "utf8"));
161913
162020
  if (typeof a2.accessToken !== "string" || !a2.accessToken) throw new Error(`${src} holds no access token`);
161914
162021
  const session = {
161915
162022
  accessToken: a2.accessToken,
@@ -164044,7 +164151,7 @@ var init_brand_font = __esm({
164044
164151
 
164045
164152
  // src/site-analyze/write-artifacts.ts
164046
164153
  import { mkdirSync as mkdirSync37, writeFileSync as writeFileSync33 } from "node:fs";
164047
- import { join as join78 } from "node:path";
164154
+ import { join as join79 } from "node:path";
164048
164155
  function attachVeloSources(book, sources, put) {
164049
164156
  const byPath = new Map((sources ?? []).map((s2) => [s2.path, s2.text]));
164050
164157
  for (const f2 of book.velo.files) {
@@ -164199,12 +164306,12 @@ async function downloadMedia(book, fetchImpl, put) {
164199
164306
  }
164200
164307
  async function writeBusinessBook(result, opts) {
164201
164308
  const out2 = opts.outDir;
164202
- mkdirSync37(join78(out2, "evidence/pages"), { recursive: true });
164203
- mkdirSync37(join78(out2, "media/catalog"), { recursive: true });
164309
+ mkdirSync37(join79(out2, "evidence/pages"), { recursive: true });
164310
+ mkdirSync37(join79(out2, "media/catalog"), { recursive: true });
164204
164311
  const files = [];
164205
164312
  const put = (rel, body) => {
164206
- const p2 = join78(out2, rel);
164207
- mkdirSync37(join78(p2, ".."), { recursive: true });
164313
+ const p2 = join79(out2, rel);
164314
+ mkdirSync37(join79(p2, ".."), { recursive: true });
164208
164315
  writeFileSync33(p2, body);
164209
164316
  files.push(rel);
164210
164317
  };
@@ -164345,7 +164452,7 @@ function dropTrailingCommas(text9) {
164345
164452
  }
164346
164453
  return out2;
164347
164454
  }
164348
- function readJson7(files, path2) {
164455
+ function readJson8(files, path2) {
164349
164456
  const text9 = files.get(path2);
164350
164457
  if (text9 === void 0) return void 0;
164351
164458
  try {
@@ -164360,7 +164467,7 @@ function filesIn(files, dir, re2) {
164360
164467
  return [...files.keys()].filter((p2) => p2.startsWith(prefix) && !p2.slice(prefix.length).includes("/") && re2.test(p2)).sort();
164361
164468
  }
164362
164469
  function projectDirs(files) {
164363
- const cfg = readJson7(files, "base44/config.jsonc") ?? readJson7(files, "base44/config.json") ?? {};
164470
+ const cfg = readJson8(files, "base44/config.jsonc") ?? readJson8(files, "base44/config.json") ?? {};
164364
164471
  const dir = (k2, d2) => {
164365
164472
  const v2 = cfg[k2];
164366
164473
  return `base44/${typeof v2 === "string" && v2 && !v2.includes("..") ? v2.replace(/^\.\/|\/+$/g, "") : d2}`;
@@ -164391,7 +164498,7 @@ function fieldsOf(schema) {
164391
164498
  function readEntities(files, dirs) {
164392
164499
  const out2 = [];
164393
164500
  for (const path2 of [...filesIn(files, dirs.entities, JSON_FILE), ...filesIn(files, "entities", JSON_FILE)]) {
164394
- const schema = readJson7(files, path2);
164501
+ const schema = readJson8(files, path2);
164395
164502
  if (!schema) continue;
164396
164503
  const base = path2.split("/").pop().replace(JSON_FILE, "");
164397
164504
  const name = typeof schema.name === "string" && schema.name ? schema.name : base;
@@ -164435,7 +164542,7 @@ function readFunctions(files, dirs) {
164435
164542
  const prefix = `${dirs.functions}/`;
164436
164543
  const under = [...files.keys()].filter((p2) => p2.startsWith(prefix)).sort();
164437
164544
  for (const cfgPath of under.filter((p2) => /\/function\.jsonc?$/i.test(p2))) {
164438
- const cfg = readJson7(files, cfgPath);
164545
+ const cfg = readJson8(files, cfgPath);
164439
164546
  if (!cfg || typeof cfg.name !== "string") continue;
164440
164547
  const folder = cfgPath.slice(0, cfgPath.lastIndexOf("/"));
164441
164548
  const entry = typeof cfg.entry === "string" ? `${folder}/${cfg.entry.replace(/^\.\//, "")}` : void 0;
@@ -164462,12 +164569,12 @@ function agentFromConfig(cfg, source) {
164462
164569
  return { name: cfg.name, ...typeof cfg.description === "string" ? { description: cfg.description } : {}, tools, source };
164463
164570
  }
164464
164571
  function readAgents(files, dirs) {
164465
- return filesIn(files, dirs.agents, JSON_FILE).map((p2) => readJson7(files, p2)).map((cfg) => cfg ? agentFromConfig(cfg, "project-files") : void 0).filter((a2) => !!a2);
164572
+ return filesIn(files, dirs.agents, JSON_FILE).map((p2) => readJson8(files, p2)).map((cfg) => cfg ? agentFromConfig(cfg, "project-files") : void 0).filter((a2) => !!a2);
164466
164573
  }
164467
164574
  function readConnectors(files, dirs) {
164468
164575
  const out2 = [];
164469
164576
  for (const p2 of filesIn(files, dirs.connectors, JSON_FILE)) {
164470
- const cfg = readJson7(files, p2);
164577
+ const cfg = readJson8(files, p2);
164471
164578
  if (!cfg || typeof cfg.type !== "string") continue;
164472
164579
  out2.push({ type: cfg.type, scopes: Array.isArray(cfg.scopes) ? cfg.scopes.map(String) : [], source: "project-files" });
164473
164580
  }
@@ -164486,7 +164593,7 @@ function providersOf(cfg) {
164486
164593
  }
164487
164594
  function readAuthConfig(files, dirs) {
164488
164595
  for (const p2 of filesIn(files, dirs.auth, JSON_FILE)) {
164489
- const cfg = readJson7(files, p2);
164596
+ const cfg = readJson8(files, p2);
164490
164597
  if (cfg && Object.keys(cfg).some((k2) => /^enable/.test(k2))) return { providers: providersOf(cfg), source: "project-files" };
164491
164598
  }
164492
164599
  return void 0;
@@ -165108,11 +165215,11 @@ var init_analyze = __esm({
165108
165215
  });
165109
165216
 
165110
165217
  // src/base44-analyze/write-artifacts.ts
165111
- import { existsSync as existsSync76, mkdirSync as mkdirSync38, readFileSync as readFileSync94, rmSync as rmSync20, writeFileSync as writeFileSync34 } from "node:fs";
165112
- import { dirname as dirname41, join as join79, resolve as resolve56, sep as sep19 } from "node:path";
165218
+ import { existsSync as existsSync76, mkdirSync as mkdirSync38, readFileSync as readFileSync95, rmSync as rmSync20, writeFileSync as writeFileSync34 } from "node:fs";
165219
+ import { dirname as dirname42, join as join80, resolve as resolve56, sep as sep19 } from "node:path";
165113
165220
  function isBookFolder(dir) {
165114
165221
  try {
165115
- return JSON.parse(readFileSync94(join79(dir, "book.json"), "utf8")).kind === "base44-app-book";
165222
+ return JSON.parse(readFileSync95(join80(dir, "book.json"), "utf8")).kind === "base44-app-book";
165116
165223
  } catch {
165117
165224
  return false;
165118
165225
  }
@@ -165199,26 +165306,26 @@ function writeBase44Book(result, outDir, opts = {}) {
165199
165306
  const md = renderBookMd(book);
165200
165307
  assertNoSecrets(json6);
165201
165308
  assertNoSecrets(md);
165202
- const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync76(join79(out2, n2)));
165309
+ const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync76(join80(out2, n2)));
165203
165310
  if (owned.length) {
165204
165311
  if (!isBookFolder(out2)) throw new Error(`refusing to write the app book into ${out2}: it already has ${owned.join(", ")} that ${owned.length === 1 ? "is" : "are"} not from an app book \u2014 pick an empty --out`);
165205
- for (const d2 of ["source", "screenshots"]) rmSync20(join79(out2, d2), { recursive: true, force: true });
165312
+ for (const d2 of ["source", "screenshots"]) rmSync20(join80(out2, d2), { recursive: true, force: true });
165206
165313
  }
165207
165314
  mkdirSync38(out2, { recursive: true });
165208
- writeFileSync34(join79(out2, "book.json"), json6);
165209
- writeFileSync34(join79(out2, "BOOK.md"), md);
165315
+ writeFileSync34(join80(out2, "book.json"), json6);
165316
+ writeFileSync34(join80(out2, "BOOK.md"), md);
165210
165317
  files.push("book.json", "BOOK.md");
165211
165318
  for (const s2 of shots) {
165212
- mkdirSync38(join79(out2, "screenshots"), { recursive: true });
165213
- writeFileSync34(join79(out2, "screenshots", s2.filename), s2.bytes);
165319
+ mkdirSync38(join80(out2, "screenshots"), { recursive: true });
165320
+ writeFileSync34(join80(out2, "screenshots", s2.filename), s2.bytes);
165214
165321
  files.push(`screenshots/${s2.filename}`);
165215
165322
  }
165216
- const sourceRoot = join79(out2, "source");
165323
+ const sourceRoot = join80(out2, "source");
165217
165324
  for (const f2 of result.sourceFiles) {
165218
165325
  if (!safeRel(f2.path)) continue;
165219
- const dest = join79(sourceRoot, ...f2.path.split("/"));
165326
+ const dest = join80(sourceRoot, ...f2.path.split("/"));
165220
165327
  if (!dest.startsWith(sourceRoot + sep19)) continue;
165221
- mkdirSync38(dirname41(dest), { recursive: true });
165328
+ mkdirSync38(dirname42(dest), { recursive: true });
165222
165329
  writeFileSync34(dest, f2.bytes);
165223
165330
  }
165224
165331
  if (result.sourceFiles.length) files.push(`source/ (${result.sourceFiles.length} files)`);
@@ -168762,7 +168869,7 @@ __export(cli_exports, {
168762
168869
  import { execFile } from "node:child_process";
168763
168870
  import { mkdirSync as mkdirSync39, mkdtempSync as mkdtempSync4, rmSync as rmSync21, writeFileSync as writeFileSync35 } from "node:fs";
168764
168871
  import { tmpdir as tmpdir5 } from "node:os";
168765
- import { join as join80, resolve as resolve57 } from "node:path";
168872
+ import { join as join81, resolve as resolve57 } from "node:path";
168766
168873
  import { promisify } from "node:util";
168767
168874
  function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
168768
168875
  return async (appId2) => {
@@ -168775,11 +168882,11 @@ function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
168775
168882
  }
168776
168883
  const bytes2 = await readCapped(res, MAX_TARBALL_BYTES);
168777
168884
  if (!bytes2) throw new Error(`project download is over the ${MAX_TARBALL_BYTES}-byte cap`);
168778
- const root = mkdtempSync4(join80(tmpdir5(), "himi-base44-"));
168885
+ const root = mkdtempSync4(join81(tmpdir5(), "himi-base44-"));
168779
168886
  const cleanup = () => rmSync21(root, { recursive: true, force: true });
168780
168887
  try {
168781
- const archive = join80(root, "project.tar");
168782
- const dir = join80(root, "project");
168888
+ const archive = join81(root, "project.tar");
168889
+ const dir = join81(root, "project");
168783
168890
  writeFileSync35(archive, bytes2);
168784
168891
  mkdirSync39(dir);
168785
168892
  await extract(archive, dir);
@@ -170074,8 +170181,8 @@ var init_customer_build = __esm({
170074
170181
  });
170075
170182
 
170076
170183
  // src/site-analyze/apply.ts
170077
- import { existsSync as existsSync77, readFileSync as readFileSync95, writeFileSync as writeFileSync36, copyFileSync as copyFileSync2, mkdirSync as mkdirSync40, realpathSync as realpathSync14, statSync as statSync20 } from "node:fs";
170078
- import { dirname as dirname42, isAbsolute as isAbsolute8, join as join81, resolve as resolve58, sep as sep20 } from "node:path";
170184
+ import { existsSync as existsSync77, readFileSync as readFileSync96, writeFileSync as writeFileSync36, copyFileSync as copyFileSync2, mkdirSync as mkdirSync40, realpathSync as realpathSync14, statSync as statSync20 } from "node:fs";
170185
+ import { dirname as dirname43, isAbsolute as isAbsolute8, join as join82, resolve as resolve58, sep as sep20 } from "node:path";
170079
170186
  import { spawnSync as spawnSync4 } from "node:child_process";
170080
170187
  function unpairedRedirectNote(overlay) {
170081
170188
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
@@ -170090,8 +170197,8 @@ function committedShellProvisioning(path2) {
170090
170197
  function findRepoRoot(cwd) {
170091
170198
  let dir = cwd;
170092
170199
  for (let i2 = 0; i2 < 8; i2++) {
170093
- if (SHELL_NAMES2.some((name) => existsSync77(join81(dir, shellAppDir(name), "package.json")))) return dir;
170094
- const next = dirname42(dir);
170200
+ if (SHELL_NAMES2.some((name) => existsSync77(join82(dir, shellAppDir(name), "package.json")))) return dir;
170201
+ const next = dirname43(dir);
170095
170202
  if (next === dir) break;
170096
170203
  dir = next;
170097
170204
  }
@@ -170193,11 +170300,11 @@ function sameKnownSite(previous, next) {
170193
170300
  }
170194
170301
  function buildMergedContract(options) {
170195
170302
  const { appDir: appDir3, packageDir, overlay } = options;
170196
- const committedPath = join81(appDir3, "provisioning.json");
170303
+ const committedPath = join82(appDir3, "provisioning.json");
170197
170304
  if (!existsSync77(committedPath)) {
170198
170305
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
170199
170306
  }
170200
- const committed = JSON.parse(readFileSync95(committedPath, "utf8"));
170307
+ const committed = JSON.parse(readFileSync96(committedPath, "utf8"));
170201
170308
  const merged = mergeCustomerOwned(committed, overlay);
170202
170309
  const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
170203
170310
  const branding = merged.branding ?? {};
@@ -170209,7 +170316,7 @@ function buildMergedContract(options) {
170209
170316
  };
170210
170317
  const stage = (fromRel, toRel) => {
170211
170318
  const from = contained(packageDir, fromRel);
170212
- const to2 = contained(join81(appDir3, STAGED), toRel.slice(STAGED.length + 1));
170319
+ const to2 = contained(join82(appDir3, STAGED), toRel.slice(STAGED.length + 1));
170213
170320
  if (!from || !to2 || !existsSync77(from)) return void 0;
170214
170321
  let real;
170215
170322
  let realRoot;
@@ -170222,7 +170329,7 @@ function buildMergedContract(options) {
170222
170329
  if (!real.startsWith(realRoot + sep20)) return void 0;
170223
170330
  try {
170224
170331
  if (!statSync20(real).isFile()) return void 0;
170225
- mkdirSync40(dirname42(to2), { recursive: true });
170332
+ mkdirSync40(dirname43(to2), { recursive: true });
170226
170333
  copyFileSync2(real, to2);
170227
170334
  } catch {
170228
170335
  return void 0;
@@ -170232,11 +170339,11 @@ function buildMergedContract(options) {
170232
170339
  };
170233
170340
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
170234
170341
  if (icon) branding.appIconPath = icon;
170235
- const facesPath = join81(packageDir, "media/fonts/faces.json");
170342
+ const facesPath = join82(packageDir, "media/fonts/faces.json");
170236
170343
  if (existsSync77(facesPath)) {
170237
170344
  let faces = [];
170238
170345
  try {
170239
- const parsed = JSON.parse(readFileSync95(facesPath, "utf8"));
170346
+ const parsed = JSON.parse(readFileSync96(facesPath, "utf8"));
170240
170347
  faces = Array.isArray(parsed) ? parsed : [];
170241
170348
  } catch {
170242
170349
  faces = [];
@@ -170257,10 +170364,10 @@ function buildMergedContract(options) {
170257
170364
  merged.branding = branding;
170258
170365
  const body = `${JSON.stringify(merged, null, 2)}
170259
170366
  `;
170260
- const path2 = join81(packageDir, "provisioning.contract.json");
170367
+ const path2 = join82(packageDir, "provisioning.contract.json");
170261
170368
  writeFileSync36(path2, body);
170262
- const localPath2 = join81(appDir3, LOCAL_CONTRACT_REL);
170263
- mkdirSync40(dirname42(localPath2), { recursive: true });
170369
+ const localPath2 = join82(appDir3, LOCAL_CONTRACT_REL);
170370
+ mkdirSync40(dirname43(localPath2), { recursive: true });
170264
170371
  writeFileSync36(localPath2, body);
170265
170372
  staged.push(localPath2);
170266
170373
  return { path: path2, staged };
@@ -170294,10 +170401,10 @@ function catalogTypography(overlay, template) {
170294
170401
  function staticFaqFor(overlay, overlayPath) {
170295
170402
  const own4 = overlay.faq;
170296
170403
  if (own4 !== void 0) return deriveStaticFaq(own4);
170297
- const bookPath = join81(dirname42(resolve58(overlayPath)), "book.json");
170404
+ const bookPath = join82(dirname43(resolve58(overlayPath)), "book.json");
170298
170405
  if (!existsSync77(bookPath)) return void 0;
170299
170406
  try {
170300
- const book = JSON.parse(readFileSync95(bookPath, "utf8"));
170407
+ const book = JSON.parse(readFileSync96(bookPath, "utf8"));
170301
170408
  const copy = book?.copy;
170302
170409
  if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
170303
170410
  const pairs = deriveStaticFaq(copy.faq);
@@ -170311,10 +170418,10 @@ function staticGalleriesFor(overlay, overlayPath) {
170311
170418
  if (overlay.galleries !== void 0) return deriveStaticGalleries(
170312
170419
  overlay.galleries.map((gallery) => ({ role: "gallery", title: gallery.title, galleryImageUrls: gallery.photos }))
170313
170420
  );
170314
- const bookPath = join81(dirname42(resolve58(overlayPath)), "book.json");
170421
+ const bookPath = join82(dirname43(resolve58(overlayPath)), "book.json");
170315
170422
  if (!existsSync77(bookPath)) return void 0;
170316
170423
  try {
170317
- const book = JSON.parse(readFileSync95(bookPath, "utf8"));
170424
+ const book = JSON.parse(readFileSync96(bookPath, "utf8"));
170318
170425
  if (!book.look || book.look.unavailable || !Array.isArray(book.look.pages)) return void 0;
170319
170426
  const galleries = deriveStaticGalleries(book.look.pages);
170320
170427
  return galleries.length || book.look.complete === true ? galleries : void 0;
@@ -170326,8 +170433,8 @@ async function applyOverlays(input) {
170326
170433
  const cwd = resolve58(input.cwd);
170327
170434
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
170328
170435
  assertKnownShell(shell);
170329
- const overlay = JSON.parse(readFileSync95(input.overlayPath, "utf8"));
170330
- const tokens2 = JSON.parse(readFileSync95(input.tokensPath, "utf8"));
170436
+ const overlay = JSON.parse(readFileSync96(input.overlayPath, "utf8"));
170437
+ const tokens2 = JSON.parse(readFileSync96(input.tokensPath, "utf8"));
170331
170438
  const faq = staticFaqFor(overlay, input.overlayPath);
170332
170439
  if (faq !== void 0) overlay.faq = faq;
170333
170440
  const galleries = staticGalleriesFor(overlay, input.overlayPath);
@@ -170344,15 +170451,15 @@ async function applyOverlays(input) {
170344
170451
  `shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
170345
170452
  );
170346
170453
  }
170347
- const appDir3 = join81(repoRoot2, shellAppDir(shell));
170348
- const committedPath = join81(appDir3, "provisioning.json");
170349
- const committedSite = existsSync77(committedPath) ? JSON.parse(readFileSync95(committedPath, "utf8")).site : void 0;
170454
+ const appDir3 = join82(repoRoot2, shellAppDir(shell));
170455
+ const committedPath = join82(appDir3, "provisioning.json");
170456
+ const committedSite = existsSync77(committedPath) ? JSON.parse(readFileSync96(committedPath, "utf8")).site : void 0;
170350
170457
  if (committedSite !== void 0 && overlay.site === void 0) {
170351
170458
  throw new Error(
170352
170459
  `shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
170353
170460
  );
170354
170461
  }
170355
- const packageDir = dirname42(resolve58(input.overlayPath));
170462
+ const packageDir = dirname43(resolve58(input.overlayPath));
170356
170463
  const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
170357
170464
  wrote.push(...staged);
170358
170465
  const r2 = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -170373,9 +170480,9 @@ async function applyOverlays(input) {
170373
170480
  note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
170374
170481
  };
170375
170482
  }
170376
- const pkgProv = join81(cwd, "provisioning.json");
170483
+ const pkgProv = join82(cwd, "provisioning.json");
170377
170484
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
170378
- const contentPath = join81(cwd, "himalaya.content.json");
170485
+ const contentPath = join82(cwd, "himalaya.content.json");
170379
170486
  const syncViewNames = (before, after) => {
170380
170487
  const content = readContentManifest(cwd);
170381
170488
  if (!content) return;
@@ -170388,7 +170495,7 @@ async function applyOverlays(input) {
170388
170495
  let packageFaq = faq;
170389
170496
  let packageGalleries = galleries;
170390
170497
  if (existsSync77(pkgProv)) {
170391
- const cur = JSON.parse(readFileSync95(pkgProv, "utf8"));
170498
+ const cur = JSON.parse(readFileSync96(pkgProv, "utf8"));
170392
170499
  if (galleries === void 0 && !sameKnownSite(cur, overlay)) overlay.galleries = [];
170393
170500
  const merged = deepMerge4(cur, overlay);
170394
170501
  packageFaq = merged.faq;
@@ -170404,9 +170511,9 @@ async function applyOverlays(input) {
170404
170511
  if (Array.isArray(packageGalleries) && packageGalleries.length && !overlay.installedVerticals.includes("galleries")) {
170405
170512
  overlay.installedVerticals.push("galleries");
170406
170513
  }
170407
- const pkgTokens = join81(cwd, "tokens.json");
170514
+ const pkgTokens = join82(cwd, "tokens.json");
170408
170515
  if (existsSync77(pkgTokens) && (tokens2.colors || tokens2.typography)) {
170409
- const cur = JSON.parse(readFileSync95(pkgTokens, "utf8"));
170516
+ const cur = JSON.parse(readFileSync96(pkgTokens, "utf8"));
170410
170517
  let tokensIn = tokens2;
170411
170518
  if (tokens2.typography) {
170412
170519
  const fonts = catalogTypography(tokens2.typography, cur.typography);
@@ -170431,9 +170538,9 @@ async function applyOverlays(input) {
170431
170538
  wrote.push(pkgTokens);
170432
170539
  }
170433
170540
  const homeAction = homeRefreshActionId(shell);
170434
- const homeSrc = join81(cwd, "dev/index.ts");
170541
+ const homeSrc = join82(cwd, "dev/index.ts");
170435
170542
  if (homeAction && existsSync77(homeSrc)) {
170436
- const prev = readFileSync95(homeSrc, "utf8");
170543
+ const prev = readFileSync96(homeSrc, "utf8");
170437
170544
  const patched = patchBrandParams(prev, overlay, homeAction);
170438
170545
  let next = patched.src;
170439
170546
  if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
@@ -170469,7 +170576,7 @@ async function applyOverlays(input) {
170469
170576
  }
170470
170577
  }
170471
170578
  if (!input.iconPath || !existsSync77(input.iconPath)) {
170472
- const book = input.iconPath ? dirname42(dirname42(resolve58(input.iconPath))) : void 0;
170579
+ const book = input.iconPath ? dirname43(dirname43(resolve58(input.iconPath))) : void 0;
170473
170580
  notes.push(
170474
170581
  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"
170475
170582
  );
@@ -171432,7 +171539,7 @@ __export(cli_exports2, {
171432
171539
  runSiteAnalyze: () => runSiteAnalyze,
171433
171540
  runSiteFunctionCli: () => runSiteFunctionCli
171434
171541
  });
171435
- import { existsSync as existsSync78, readFileSync as readFileSync96 } from "node:fs";
171542
+ import { existsSync as existsSync78, readFileSync as readFileSync97 } from "node:fs";
171436
171543
  import { resolve as resolve59 } from "node:path";
171437
171544
  function applyNeedsClient(shell) {
171438
171545
  if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
@@ -171491,7 +171598,7 @@ async function runSiteAnalyze(opts) {
171491
171598
  const prevOverlayPath = resolve59(outDir, "provisioning.overlay.json");
171492
171599
  const prevSite = existsSync78(prevOverlayPath) ? (() => {
171493
171600
  try {
171494
- return JSON.parse(readFileSync96(prevOverlayPath, "utf8")).site;
171601
+ return JSON.parse(readFileSync97(prevOverlayPath, "utf8")).site;
171495
171602
  } catch {
171496
171603
  return void 0;
171497
171604
  }
@@ -171510,7 +171617,7 @@ async function runSiteAnalyze(opts) {
171510
171617
  }
171511
171618
  const previousOverlay = resolve59(outDir, "provisioning.overlay.json");
171512
171619
  carryOverGoals(
171513
- existsSync78(previousOverlay) ? readFileSync96(previousOverlay, "utf8") : void 0,
171620
+ existsSync78(previousOverlay) ? readFileSync97(previousOverlay, "utf8") : void 0,
171514
171621
  result.provisioningOverlay
171515
171622
  );
171516
171623
  const ownerCall = ownerAuth ? ownerTransportFrom(fetchImpl, ownerAuth) : void 0;
@@ -171568,7 +171675,7 @@ async function runSiteFunctionCli(opts) {
171568
171675
  let source;
171569
171676
  if (opts.sourcePath) {
171570
171677
  const p2 = resolve59(opts.cwd ?? process.cwd(), opts.sourcePath);
171571
- source = readFileSync96(p2, "utf8");
171678
+ source = readFileSync97(p2, "utf8");
171572
171679
  }
171573
171680
  let body;
171574
171681
  if (opts.bodyRaw != null) {
@@ -171598,7 +171705,7 @@ async function runSiteFunctionCli(opts) {
171598
171705
  function base44BookRoutes(bookPath, siteUrl) {
171599
171706
  if (!existsSync78(bookPath)) return void 0;
171600
171707
  try {
171601
- const book = JSON.parse(readFileSync96(bookPath, "utf8"));
171708
+ const book = JSON.parse(readFileSync97(bookPath, "utf8"));
171602
171709
  if (book.kind !== "base44-app-book" || !Array.isArray(book.routes)) return void 0;
171603
171710
  const host = (u2) => {
171604
171711
  try {
@@ -171853,7 +171960,7 @@ __export(site_create_exports, {
171853
171960
  runSiteList: () => runSiteList,
171854
171961
  writeProvisioningBinding: () => writeProvisioningBinding
171855
171962
  });
171856
- import { existsSync as existsSync79, readFileSync as readFileSync97, writeFileSync as writeFileSync37 } from "node:fs";
171963
+ import { existsSync as existsSync79, readFileSync as readFileSync98, writeFileSync as writeFileSync37 } from "node:fs";
171857
171964
  import { resolve as resolvePath2 } from "node:path";
171858
171965
  function oauthClientName(projectName) {
171859
171966
  return `${projectName} client`;
@@ -172002,7 +172109,7 @@ async function runSiteCreate(opts) {
172002
172109
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
172003
172110
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
172004
172111
  }
172005
- function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync79, readFileSync: readFileSync97, writeFileSync: writeFileSync37 }) {
172112
+ function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync79, readFileSync: readFileSync98, writeFileSync: writeFileSync37 }) {
172006
172113
  const msid = binding2.siteId;
172007
172114
  const path2 = resolvePath2(target);
172008
172115
  const committed = committedShellProvisioning(path2);
@@ -172678,13 +172785,13 @@ var init_context = __esm({
172678
172785
  });
172679
172786
 
172680
172787
  // src/cli.ts
172681
- import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync98, mkdirSync as mkdirSync41, writeFileSync as writeFileSync38, existsSync as existsSync80, rmSync as rmSync22, readdirSync as readdirSync34, statSync as statSync21, lstatSync as lstatSync21, accessSync, constants as constants4, renameSync as renameSync12, cpSync as cpSync3 } from "node:fs";
172788
+ import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync99, mkdirSync as mkdirSync41, writeFileSync as writeFileSync38, existsSync as existsSync80, rmSync as rmSync22, readdirSync as readdirSync34, statSync as statSync21, lstatSync as lstatSync21, accessSync, constants as constants4, renameSync as renameSync12, cpSync as cpSync3 } from "node:fs";
172682
172789
  import { execFile as execFile2, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
172683
172790
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
172684
172791
  import { createHash as createHash41, randomUUID as randomUUID11 } from "node:crypto";
172685
- import { tmpdir as tmpdir6, homedir as homedir11, hostname as hostname2 } from "node:os";
172686
- import { join as join82, resolve as resolve60, relative as relative15, basename as basename19, dirname as dirname43 } from "node:path";
172687
- import { fileURLToPath as fileURLToPath27 } from "node:url";
172792
+ import { tmpdir as tmpdir6, homedir as homedir12, hostname as hostname2 } from "node:os";
172793
+ import { join as join83, resolve as resolve60, relative as relative15, basename as basename19, dirname as dirname44 } from "node:path";
172794
+ import { fileURLToPath as fileURLToPath28 } from "node:url";
172688
172795
 
172689
172796
  // ../serve-cli/src/client.ts
172690
172797
  var MAX_PUBLISH_BODY_BYTES = 8 * 1024 * 1024;
@@ -174837,8 +174944,8 @@ var str9 = (v2) => typeof v2 === "string" ? v2 : void 0;
174837
174944
  var num3 = (v2) => typeof v2 === "string" && v2 !== "" && Number.isFinite(Number(v2)) ? Number(v2) : void 0;
174838
174945
  function embeddedTemplateCatalog() {
174839
174946
  return availableTemplates().map((name) => {
174840
- const path2 = join82(templateSourceDir(name), TEMPLATE_META_FILE);
174841
- const meta = JSON.parse(readFileSync98(path2, "utf8"));
174947
+ const path2 = join83(templateSourceDir(name), TEMPLATE_META_FILE);
174948
+ const meta = JSON.parse(readFileSync99(path2, "utf8"));
174842
174949
  if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
174843
174950
  throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
174844
174951
  }
@@ -175709,7 +175816,7 @@ var COMMANDS2 = [
175709
175816
  ];
175710
175817
  function cliVersion() {
175711
175818
  try {
175712
- return JSON.parse(readFileSync98(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
175819
+ return JSON.parse(readFileSync99(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
175713
175820
  } catch {
175714
175821
  return "unknown";
175715
175822
  }
@@ -175747,7 +175854,7 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
175747
175854
  const configured = async (key2) => {
175748
175855
  const timeout = deadline - Date.now();
175749
175856
  if (timeout <= 0) throw new Error("npm config: out of budget");
175750
- const raw = String(await exec("npm", ["config", "get", key2], { cwd: homedir11(), timeout })).trim();
175857
+ const raw = String(await exec("npm", ["config", "get", key2], { cwd: homedir12(), timeout })).trim();
175751
175858
  return raw && raw !== "undefined" ? raw : void 0;
175752
175859
  };
175753
175860
  const effective = normalizeRegistry(await configured("@wix:registry") ?? await configured("registry"));
@@ -175834,7 +175941,7 @@ function ageInDays(publishedAt, now = Date.now()) {
175834
175941
  }
175835
175942
  function packageVersion(path2) {
175836
175943
  try {
175837
- const version4 = JSON.parse(readFileSync98(path2, "utf8")).version;
175944
+ const version4 = JSON.parse(readFileSync99(path2, "utf8")).version;
175838
175945
  return typeof version4 === "string" && version4 ? version4 : void 0;
175839
175946
  } catch {
175840
175947
  return void 0;
@@ -175843,9 +175950,9 @@ function packageVersion(path2) {
175843
175950
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
175844
175951
  let dir = resolve60(fromDir);
175845
175952
  for (; ; ) {
175846
- const version4 = packageVersion(join82(dir, "node_modules", "@wix", "himalaya", "package.json"));
175953
+ const version4 = packageVersion(join83(dir, "node_modules", "@wix", "himalaya", "package.json"));
175847
175954
  if (version4) return { version: version4, source: "local" };
175848
- const parent = dirname43(dir);
175955
+ const parent = dirname44(dir);
175849
175956
  if (parent === dir) break;
175850
175957
  dir = parent;
175851
175958
  }
@@ -175853,7 +175960,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
175853
175960
  if (bundled) return { version: bundled, source: "bundled" };
175854
175961
  try {
175855
175962
  const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
175856
- const version4 = root ? packageVersion(join82(root, "@wix", "himalaya", "package.json")) : void 0;
175963
+ const version4 = root ? packageVersion(join83(root, "@wix", "himalaya", "package.json")) : void 0;
175857
175964
  return version4 ? { version: version4, source: "global" } : {};
175858
175965
  } catch {
175859
175966
  return {};
@@ -175900,11 +176007,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
175900
176007
  var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
175901
176008
  var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
175902
176009
  function updateCachePath(env = process.env) {
175903
- return env.HIMI_UPDATE_CACHE_FILE ?? join82(homedir11(), ".himalaya", "update-check.json");
176010
+ return env.HIMI_UPDATE_CACHE_FILE ?? join83(homedir12(), ".himalaya", "update-check.json");
175904
176011
  }
175905
176012
  function readUpdateCache(path2) {
175906
176013
  try {
175907
- const parsed = JSON.parse(readFileSync98(path2, "utf8"));
176014
+ const parsed = JSON.parse(readFileSync99(path2, "utf8"));
175908
176015
  return parsed && typeof parsed === "object" ? parsed : {};
175909
176016
  } catch {
175910
176017
  return {};
@@ -175912,7 +176019,7 @@ function readUpdateCache(path2) {
175912
176019
  }
175913
176020
  function writeUpdateCache(path2, cache) {
175914
176021
  try {
175915
- mkdirSync41(dirname43(path2), { recursive: true, mode: 448 });
176022
+ mkdirSync41(dirname44(path2), { recursive: true, mode: 448 });
175916
176023
  writeFileSync38(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
175917
176024
  } catch {
175918
176025
  }
@@ -175966,18 +176073,18 @@ function createUpdateRunner(spawn8 = spawnSync5) {
175966
176073
  // parse — the agent case this whole feature exists for (#2985 review). And no stdin: an
175967
176074
  // install needs none, and must not consume input piped to the command we are about to re-run.
175968
176075
  stdio: ["ignore", 2, 2],
175969
- cwd: homedir11()
176076
+ cwd: homedir12()
175970
176077
  });
175971
176078
  if (result.error) return { ok: false, detail: result.error.message };
175972
176079
  return result.status === 0 ? { ok: true } : { ok: false, detail: `npm exited ${result.status}` };
175973
176080
  },
175974
176081
  installedVersion: () => {
175975
176082
  const root = globalNodeModulesRoot();
175976
- return root ? packageVersion(join82(root, "@wix", "himalaya-cli", "package.json")) : void 0;
176083
+ return root ? packageVersion(join83(root, "@wix", "himalaya-cli", "package.json")) : void 0;
175977
176084
  },
175978
176085
  reexec: (argv) => {
175979
176086
  const root = globalNodeModulesRoot();
175980
- const entry = root ? join82(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
176087
+ const entry = root ? join83(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
175981
176088
  if (!entry || !existsSync80(entry)) return void 0;
175982
176089
  const result = spawnSync5(process.execPath, [entry, ...argv], {
175983
176090
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
@@ -176025,7 +176132,7 @@ function staleUpdateLockFile(cachePath, now) {
176025
176132
  for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
176026
176133
  let content;
176027
176134
  try {
176028
- content = readFileSync98(path2, "utf8");
176135
+ content = readFileSync99(path2, "utf8");
176029
176136
  } catch {
176030
176137
  continue;
176031
176138
  }
@@ -176048,7 +176155,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
176048
176155
  const mine = lockStamp(now);
176049
176156
  const readLock = (path2) => {
176050
176157
  try {
176051
- return readFileSync98(path2, "utf8");
176158
+ return readFileSync99(path2, "utf8");
176052
176159
  } catch {
176053
176160
  return void 0;
176054
176161
  }
@@ -176069,7 +176176,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
176069
176176
  };
176070
176177
  const release2 = () => removeIfMine(lockPath);
176071
176178
  try {
176072
- mkdirSync41(dirname43(lockPath), { recursive: true, mode: 448 });
176179
+ mkdirSync41(dirname44(lockPath), { recursive: true, mode: 448 });
176073
176180
  } catch {
176074
176181
  return () => {
176075
176182
  };
@@ -176136,10 +176243,10 @@ function supersededInCache(current, latest, now) {
176136
176243
  function createUpdateRefreshSpawner(spawnFn = spawn7, execArgv = process.execArgv) {
176137
176244
  return () => {
176138
176245
  try {
176139
- const child = spawnFn(process.execPath, [...loaderArgs(execArgv), fileURLToPath27(import.meta.url), UPDATE_REFRESH_COMMAND], {
176246
+ const child = spawnFn(process.execPath, [...loaderArgs(execArgv), fileURLToPath28(import.meta.url), UPDATE_REFRESH_COMMAND], {
176140
176247
  detached: true,
176141
176248
  stdio: "ignore",
176142
- cwd: homedir11(),
176249
+ cwd: homedir12(),
176143
176250
  env: process.env
176144
176251
  });
176145
176252
  child.on("error", () => {
@@ -176191,7 +176298,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
176191
176298
  }
176192
176299
  const { code, stdout, stderr } = await new Promise((done) => {
176193
176300
  const chunks = { out: [], err: [] };
176194
- const child = spawnFn(process.execPath, [...loaderArgs(process.execArgv), fileURLToPath27(import.meta.url), ...argv], {
176301
+ const child = spawnFn(process.execPath, [...loaderArgs(process.execArgv), fileURLToPath28(import.meta.url), ...argv], {
176195
176302
  cwd: process.cwd(),
176196
176303
  env: process.env,
176197
176304
  stdio: ["ignore", "pipe", "pipe"]
@@ -176640,7 +176747,7 @@ function executableOnPath(name, env = process.env) {
176640
176747
  const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
176641
176748
  for (const dir of entries) {
176642
176749
  for (const suffix of suffixes) {
176643
- const candidate = join82(dir, `${name}${suffix}`);
176750
+ const candidate = join83(dir, `${name}${suffix}`);
176644
176751
  try {
176645
176752
  if (!statSync21(candidate).isFile()) continue;
176646
176753
  if (process.platform !== "win32") accessSync(candidate, constants4.X_OK);
@@ -176749,7 +176856,7 @@ async function nativeConfigAdvisories(app, configSource) {
176749
176856
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
176750
176857
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
176751
176858
  const iosYmlPath = iosProjectYml2(app);
176752
- const iosYml = existsSync80(iosYmlPath) ? readFileSync98(iosYmlPath, "utf8") : "";
176859
+ const iosYml = existsSync80(iosYmlPath) ? readFileSync99(iosYmlPath, "utf8") : "";
176753
176860
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
176754
176861
  if (!optedIn) {
176755
176862
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -176763,13 +176870,13 @@ async function nativeConfigAdvisories(app, configSource) {
176763
176870
  }
176764
176871
  function readConfigSource(dir) {
176765
176872
  try {
176766
- return readFileSync98(join82(dir, "config.ts"), "utf8");
176873
+ return readFileSync99(join83(dir, "config.ts"), "utf8");
176767
176874
  } catch {
176768
176875
  return null;
176769
176876
  }
176770
176877
  }
176771
176878
  function writePngFile(path2, base64) {
176772
- mkdirSync41(dirname43(path2), { recursive: true });
176879
+ mkdirSync41(dirname44(path2), { recursive: true });
176773
176880
  writeFileSync38(path2, Buffer.from(base64, "base64"));
176774
176881
  return path2;
176775
176882
  }
@@ -176817,7 +176924,7 @@ var NoBase44SlotError = class extends Error {
176817
176924
  };
176818
176925
  async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {}) {
176819
176926
  const dir = resolve60(parentDir, name);
176820
- if (existsSync80(join82(dir, "himalaya.content.json"))) {
176927
+ if (existsSync80(join83(dir, "himalaya.content.json"))) {
176821
176928
  throw new Error(`content package already exists at ${dir}`);
176822
176929
  }
176823
176930
  const r2 = await c2.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -176878,8 +176985,8 @@ function restoreDestinationIssue(dest, force) {
176878
176985
  function isHimalayaMonorepoCheckout(start) {
176879
176986
  let dir = resolve60(start);
176880
176987
  for (; ; ) {
176881
- if (existsSync80(join82(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync80(join82(dir, "core", "serve", "src", "server.ts"))) return true;
176882
- const parent = dirname43(dir);
176988
+ if (existsSync80(join83(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync80(join83(dir, "core", "serve", "src", "server.ts"))) return true;
176989
+ const parent = dirname44(dir);
176883
176990
  if (parent === dir) return false;
176884
176991
  dir = parent;
176885
176992
  }
@@ -176938,8 +177045,8 @@ function materializeForPreview(appDir3, slug, displayName2) {
176938
177045
  const forBuild = Object.fromEntries(
176939
177046
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
176940
177047
  );
176941
- const repoRoot2 = resolve60(fileURLToPath27(new URL("../../..", import.meta.url)));
176942
- const root = join82(repoRoot2, "node_modules", ".cache", "himi-template-preview");
177048
+ const repoRoot2 = resolve60(fileURLToPath28(new URL("../../..", import.meta.url)));
177049
+ const root = join83(repoRoot2, "node_modules", ".cache", "himi-template-preview");
176943
177050
  const stillRunning = (pid) => {
176944
177051
  try {
176945
177052
  process.kill(pid, 0);
@@ -176953,12 +177060,12 @@ function materializeForPreview(appDir3, slug, displayName2) {
176953
177060
  if (!entry.isDirectory()) continue;
176954
177061
  const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
176955
177062
  if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
176956
- rmSync22(join82(root, entry.name), { recursive: true, force: true });
177063
+ rmSync22(join83(root, entry.name), { recursive: true, force: true });
176957
177064
  }
176958
177065
  }
176959
177066
  } catch {
176960
177067
  }
176961
- const dest = join82(root, `${slug}-${process.pid}`);
177068
+ const dest = join83(root, `${slug}-${process.pid}`);
176962
177069
  rmSync22(dest, { recursive: true, force: true });
176963
177070
  mkdirSync41(dest, { recursive: true });
176964
177071
  try {
@@ -176971,8 +177078,8 @@ function materializeForPreview(appDir3, slug, displayName2) {
176971
177078
  }
176972
177079
  async function appId(dir) {
176973
177080
  try {
176974
- const { readFileSync: readFileSync99 } = await import("node:fs");
176975
- const m2 = JSON.parse(readFileSync99(join82(dir, "himalaya.content.json"), "utf8"));
177081
+ const { readFileSync: readFileSync100 } = await import("node:fs");
177082
+ const m2 = JSON.parse(readFileSync100(join83(dir, "himalaya.content.json"), "utf8"));
176976
177083
  if (m2.name) return m2.name;
176977
177084
  } catch {
176978
177085
  }
@@ -176980,8 +177087,8 @@ async function appId(dir) {
176980
177087
  }
176981
177088
  async function contentVisibility(dir) {
176982
177089
  try {
176983
- const { readFileSync: readFileSync99 } = await import("node:fs");
176984
- const m2 = JSON.parse(readFileSync99(join82(dir, "himalaya.content.json"), "utf8"));
177090
+ const { readFileSync: readFileSync100 } = await import("node:fs");
177091
+ const m2 = JSON.parse(readFileSync100(join83(dir, "himalaya.content.json"), "utf8"));
176985
177092
  if (m2.visibility === "public" || m2.visibility === "unlisted") return m2.visibility;
176986
177093
  } catch {
176987
177094
  }
@@ -177270,7 +177377,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
177270
177377
  ...res.removed.length ? { removed: res.removed, note: "older copies at the app root, moved to .himi/legacy-agent-files/ (a backup, in case one became app code) \u2014 the current ones live in .agents/skills/himalaya/" } : {},
177271
177378
  // In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
177272
177379
  // hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
177273
- ...existsSync80(join82(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
177380
+ ...existsSync80(join83(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
177274
177381
  ...res.skipped.length ? { skipped: res.skipped } : {},
177275
177382
  portalUrl: idx.portalUrl
177276
177383
  });
@@ -177293,7 +177400,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
177293
177400
  try {
177294
177401
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
177295
177402
  const bres = await buildContentForValidation2(dir, { resolution });
177296
- out2 = mkdtempSync5(join82(tmpdir6(), "himi-ux-record-"));
177403
+ out2 = mkdtempSync5(join83(tmpdir6(), "himi-ux-record-"));
177297
177404
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
177298
177405
  const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
177299
177406
  const releaseId = outcome.manifest.releaseId;
@@ -177472,7 +177579,7 @@ async function producedWidgetFamilies(dir) {
177472
177579
  let js2;
177473
177580
  for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
177474
177581
  try {
177475
- js2 = readFileSync98(join82(outDir, candidate), "utf8");
177582
+ js2 = readFileSync99(join83(outDir, candidate), "utf8");
177476
177583
  break;
177477
177584
  } catch {
177478
177585
  }
@@ -177503,7 +177610,7 @@ async function producedWidgetFamilies(dir) {
177503
177610
  }
177504
177611
  return { families, source: "dist/bundles" };
177505
177612
  }
177506
- var boardOpen = (dir) => existsSync80(join82(dir, ".himi", "studio", "index.html"));
177613
+ var boardOpen = (dir) => existsSync80(join83(dir, ".himi", "studio", "index.html"));
177507
177614
  var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
177508
177615
  async function leaveForBoard(dir, record2, value) {
177509
177616
  if (!boardOpen(dir)) return;
@@ -177527,7 +177634,7 @@ async function liveMapFor(dir) {
177527
177634
  }
177528
177635
  var commandScratch = new AsyncLocalStorage2();
177529
177636
  function commandScratchDir(prefix) {
177530
- const dir = mkdtempSync5(join82(tmpdir6(), prefix));
177637
+ const dir = mkdtempSync5(join83(tmpdir6(), prefix));
177531
177638
  commandScratch.getStore()?.push(dir);
177532
177639
  return dir;
177533
177640
  }
@@ -177881,7 +177988,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
177881
177988
  const owed = openApprovals2(readApprovals2(dir).events).length;
177882
177989
  next.push(`carried the planning journal into the app (${carried.join(", ")}${owed ? `; ${owed} approval${owed === 1 ? "" : "s"} still owed` : ""}) \u2014 \`himi progress --brief\` there shows it`);
177883
177990
  }
177884
- const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync80(join82(parentDir, f2)));
177991
+ const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync80(join83(parentDir, f2)));
177885
177992
  if (planInParent.length) {
177886
177993
  next.push(`${planInParent.join(" and ")} in ${parentDir} ${planInParent.length > 1 ? "are" : "is"} not the app's \u2014 if that is the approved plan, move it over the template's boilerplate in ${dir}`);
177887
177994
  }
@@ -177892,12 +177999,12 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
177892
177999
  const board = await openBoardForSession2(dir);
177893
178000
  const home = homeScreenIdOf2(dir);
177894
178001
  recordInitSource2(dir, { template: template ?? null, source });
177895
- const firstLook = flags["no-first-look"] === true ? { skipped: "--no-first-look" } : await firstLookAtInit2(dir, { source, home, entry: fileURLToPath27(import.meta.url), loader: loaderArgs(process.execArgv) });
178002
+ const firstLook = flags["no-first-look"] === true ? { skipped: "--no-first-look" } : await firstLookAtInit2(dir, { source, home, entry: fileURLToPath28(import.meta.url), loader: loaderArgs(process.execArgv) });
177896
178003
  const pictured = "image" in firstLook;
177897
178004
  const watch2 = await startWatchAtInit2(dir, {
177898
178005
  source,
177899
178006
  app: await appId(dir),
177900
- entry: fileURLToPath27(import.meta.url),
178007
+ entry: fileURLToPath28(import.meta.url),
177901
178008
  loader: loaderArgs(process.execArgv),
177902
178009
  noWatch: flags["no-watch"] === true
177903
178010
  });
@@ -178042,13 +178149,13 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178042
178149
  if (adding) {
178043
178150
  const from = str9(flags.from);
178044
178151
  if (!from) throw new TrimRefusal2('--add <id> needs --from <file> holding the whole new SCREENS entry (` "<id>": { "screenId": "<id>", \u2026 },`)');
178045
- print(adopt.addScreen(dir, adding, readFileSync98(from, "utf8"), { parent: str9(flags.parent), tab: str9(flags.tab), displayName: str9(flags["display-name"]) }));
178152
+ print(adopt.addScreen(dir, adding, readFileSync99(from, "utf8"), { parent: str9(flags.parent), tab: str9(flags.tab), displayName: str9(flags["display-name"]) }));
178046
178153
  return 0;
178047
178154
  }
178048
178155
  if (target) {
178049
178156
  const from = str9(flags.from);
178050
178157
  if (!from) throw new TrimRefusal2("--write <id> needs --from <file> holding the whole entry, as --show prints it");
178051
- print(adopt.replaceScreen(dir, target, readFileSync98(from, "utf8")));
178158
+ print(adopt.replaceScreen(dir, target, readFileSync99(from, "utf8")));
178052
178159
  return 0;
178053
178160
  }
178054
178161
  if (show) {
@@ -178130,7 +178237,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178130
178237
  const { keepFromSpec: keepFromSpec2 } = await Promise.resolve().then(() => (init_template_adopt(), template_adopt_exports));
178131
178238
  const dir = contentDir(flags);
178132
178239
  try {
178133
- const spec = keepFromSpec2(dir, str9(flags["from-spec"]) ?? join82(dir, "SPEC.md"));
178240
+ const spec = keepFromSpec2(dir, str9(flags["from-spec"]) ?? join83(dir, "SPEC.md"));
178134
178241
  const own4 = typeof keep === "string" ? keep.split(",").map((k2) => k2.trim()).filter(Boolean) : [];
178135
178242
  keep = [.../* @__PURE__ */ new Set([...spec.keep, ...own4])].join(",");
178136
178243
  fromSpec = { fromSpec: {
@@ -178171,7 +178278,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178171
178278
  const result = { ...outcome.result, ...fromSpec };
178172
178279
  const adoptDir = contentDir(flags);
178173
178280
  const kept = flags["dry-run"] !== true && (outcome.code === 0 || outcome.result.forcedKeep === true);
178174
- if (kept && existsSync80(join82(adoptDir, adoptBits.ADOPT_FILE))) {
178281
+ if (kept && existsSync80(join83(adoptDir, adoptBits.ADOPT_FILE))) {
178175
178282
  try {
178176
178283
  const inv = adoptBits.inspectApp(adoptDir);
178177
178284
  adoptBits.writeInventory(adoptDir, inv, { companions: "if-missing" });
@@ -178200,7 +178307,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178200
178307
  const sourceDir = resolve60(str9(flags["source-dir"]) ?? appDir3);
178201
178308
  let meta;
178202
178309
  try {
178203
- meta = JSON.parse(readFileSync98(join82(sourceDir, TEMPLATE_META_FILE), "utf8"));
178310
+ meta = JSON.parse(readFileSync99(join83(sourceDir, TEMPLATE_META_FILE), "utf8"));
178204
178311
  } catch {
178205
178312
  io2.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
178206
178313
  return 2;
@@ -178210,7 +178317,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178210
178317
  return 2;
178211
178318
  }
178212
178319
  try {
178213
- const appearance = extractTemplateAppearance(JSON.parse(readFileSync98(join82(sourceDir, "tokens.json"), "utf8")));
178320
+ const appearance = extractTemplateAppearance(JSON.parse(readFileSync99(join83(sourceDir, "tokens.json"), "utf8")));
178214
178321
  meta = { ...appearance, ...meta };
178215
178322
  } catch {
178216
178323
  }
@@ -178232,7 +178339,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178232
178339
  const force = flags.force === true;
178233
178340
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
178234
178341
  const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
178235
- const out2 = mkdtempSync5(join82(tmpdir6(), "himi-template-"));
178342
+ const out2 = mkdtempSync5(join83(tmpdir6(), "himi-template-"));
178236
178343
  publishScratch.push(out2);
178237
178344
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
178238
178345
  const outcome = await buildReleaseFromContent2(buildDir, out2, {
@@ -178289,7 +178396,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178289
178396
  let iconHash;
178290
178397
  if (iconPath) {
178291
178398
  try {
178292
- const bytes2 = readFileSync98(iconPath);
178399
+ const bytes2 = readFileSync99(iconPath);
178293
178400
  payload.icon = bytes2.toString("base64");
178294
178401
  iconHash = createHash41("sha256").update(bytes2).digest("hex");
178295
178402
  } catch {
@@ -178573,7 +178680,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178573
178680
  const homePicture = await homePictureAtValidate2(dir, {
178574
178681
  ok: !hasErrors,
178575
178682
  home: outcome.homeScreenId,
178576
- entry: fileURLToPath27(import.meta.url),
178683
+ entry: fileURLToPath28(import.meta.url),
178577
178684
  loader: loaderArgs(process.execArgv)
178578
178685
  });
178579
178686
  const { postcard: picturePostcard, ...picture } = homePicture;
@@ -178588,7 +178695,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178588
178695
  const path2 = dpxSessionTokenPath();
178589
178696
  let raw;
178590
178697
  try {
178591
- raw = readFileSync98(path2, "utf8");
178698
+ raw = readFileSync99(path2, "utf8");
178592
178699
  } catch {
178593
178700
  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`);
178594
178701
  }
@@ -178722,8 +178829,8 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178722
178829
  const dir = resolve60(out2);
178723
178830
  const files = himiPluginFiles2(skills.skillMd);
178724
178831
  for (const f2 of files) {
178725
- mkdirSync41(dirname43(join82(dir, f2.path)), { recursive: true });
178726
- writeFileSync38(join82(dir, f2.path), f2.text);
178832
+ mkdirSync41(dirname44(join83(dir, f2.path)), { recursive: true });
178833
+ writeFileSync38(join83(dir, f2.path), f2.text);
178727
178834
  }
178728
178835
  print({ ok: true, dir, files: files.map((f2) => f2.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
178729
178836
  return 0;
@@ -178740,15 +178847,15 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
178740
178847
  case "studio": {
178741
178848
  const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
178742
178849
  const dir = contentDir(flags);
178743
- if (!existsSync80(join82(dir, "himalaya.content.json"))) {
178850
+ if (!existsSync80(join83(dir, "himalaya.content.json"))) {
178744
178851
  io2.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
178745
178852
  return 2;
178746
178853
  }
178747
178854
  if (pos[1] === "reel") {
178748
178855
  const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
178749
- const out2 = resolve60(str9(flags.out) ?? join82(dir, ".himi", "making-of.html"));
178856
+ const out2 = resolve60(str9(flags.out) ?? join83(dir, ".himi", "making-of.html"));
178750
178857
  const { html, plan } = buildReel2(dir);
178751
- mkdirSync41(dirname43(out2), { recursive: true });
178858
+ mkdirSync41(dirname44(out2), { recursive: true });
178752
178859
  writeFileSync38(out2, html);
178753
178860
  const { pathToFileURL: pathToFileURL9 } = await import("node:url");
178754
178861
  const url2 = pathToFileURL9(out2).href;
@@ -178818,7 +178925,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
178818
178925
  } = await Promise.resolve().then(() => (init_progress(), progress_exports));
178819
178926
  const dir = contentDir(flags);
178820
178927
  const journal2 = journalPath2(dir);
178821
- const isContentPackage = existsSync80(join82(dir, "himalaya.content.json"));
178928
+ const isContentPackage = existsSync80(join83(dir, "himalaya.content.json"));
178822
178929
  const hint = isContentPackage ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
178823
178930
  const message = pos.slice(1).join(" ").trim();
178824
178931
  const approvalFlags = ["approve", "done", "drop"].filter((f2) => flags[f2] !== void 0);
@@ -178970,7 +179077,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
178970
179077
  case "test": {
178971
179078
  const dir = contentDir(flags);
178972
179079
  const structuredOutput = flags.json === true || io2.isTTY !== true;
178973
- if (existsSync80(join82(dir, "functions"))) {
179080
+ if (existsSync80(join83(dir, "functions"))) {
178974
179081
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
178975
179082
  const loaded = await loadFunctionsApp2(dir);
178976
179083
  const results = [];
@@ -179102,13 +179209,13 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
179102
179209
  io2.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
179103
179210
  return 2;
179104
179211
  }
179105
- const sources = collectWorkerSources2(join82(dir, "tier5-src"), screen.bundleName);
179212
+ const sources = collectWorkerSources2(join83(dir, "tier5-src"), screen.bundleName);
179106
179213
  if (!sources) {
179107
179214
  io2.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
179108
179215
  return 2;
179109
179216
  }
179110
- const { fileURLToPath: fileURLToPath28 } = await import("node:url");
179111
- const sdk = collectSdkModules2(sources.files, sdkSubpathReader2((s2) => fileURLToPath28(import.meta.resolve(s2))));
179217
+ const { fileURLToPath: fileURLToPath29 } = await import("node:url");
179218
+ const sdk = collectSdkModules2(sources.files, sdkSubpathReader2((s2) => fileURLToPath29(import.meta.resolve(s2))));
179112
179219
  if (sdk.unsupported.length) {
179113
179220
  io2.error(JSON.stringify({
179114
179221
  error: `this worker imports ${sdk.unsupported.map((u2) => `@himalaya/${u2.sub}`).join(", ")}, which the browser loop cannot build: ${sdk.unsupported.map((u2) => `${u2.sub} needs ${u2.builtin}`).join("; ")}. The page compiles in a tab with no node builtins. Run \`himi test\` without --browser for this screen.`,
@@ -179280,7 +179387,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
179280
179387
  const sp = await runShotsPass2({
179281
179388
  descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
179282
179389
  tokens: outcome.tokens,
179283
- outDir: join82(dir, ".himi", "shots"),
179390
+ outDir: join83(dir, ".himi", "shots"),
179284
179391
  width: 390,
179285
179392
  layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
179286
179393
  ...budgetMs ? { budgetMs } : {},
@@ -179320,7 +179427,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
179320
179427
  releaseId: result.releaseId,
179321
179428
  releasePayload: release2,
179322
179429
  descriptors: attestedDescriptors,
179323
- screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join82(dir, ".himi", "shots", name)])),
179430
+ screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join83(dir, ".himi", "shots", name)])),
179324
179431
  coverage: {
179325
179432
  screens: crawledScreens.size,
179326
179433
  actionsDispatched: result.actions.exercised,
@@ -179445,7 +179552,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
179445
179552
  return 2;
179446
179553
  }
179447
179554
  try {
179448
- const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync98(stateArg.replace(/^@/, ""), "utf8");
179555
+ const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync99(stateArg.replace(/^@/, ""), "utf8");
179449
179556
  injectedState = JSON.parse(raw);
179450
179557
  } catch (e2) {
179451
179558
  io2.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e2.message}` }));
@@ -179460,7 +179567,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
179460
179567
  return 2;
179461
179568
  }
179462
179569
  try {
179463
- const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync98(inputArg.replace(/^@/, ""), "utf8");
179570
+ const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync99(inputArg.replace(/^@/, ""), "utf8");
179464
179571
  const parsed = JSON.parse(raw);
179465
179572
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
179466
179573
  injectedInput = parsed;
@@ -179542,7 +179649,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
179542
179649
  const diagnostics = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
179543
179650
  let pngFile;
179544
179651
  let attestationPngFile;
179545
- const shotPath = join82(dir, ".himi", "shots", `${screenId}.png`);
179652
+ const shotPath = join83(dir, ".himi", "shots", `${screenId}.png`);
179546
179653
  const pngTarget = typeof flags.png === "string" ? str9(flags.png) : flags.png === true ? shotPath : void 0;
179547
179654
  if (pngTarget && r2.pngBase64) {
179548
179655
  pngFile = writePngFile(pngTarget, r2.pngBase64);
@@ -179914,7 +180021,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
179914
180021
  io2.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
179915
180022
  return 1;
179916
180023
  }
179917
- if (replace && occupied && !existsSync80(join82(dest, "himalaya.content.json"))) {
180024
+ if (replace && occupied && !existsSync80(join83(dest, "himalaya.content.json"))) {
179918
180025
  io2.error(JSON.stringify({
179919
180026
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
179920
180027
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -180622,7 +180729,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
180622
180729
  }
180623
180730
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
180624
180731
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
180625
- const built = mkdtempSync5(join82(tmpdir6(), "himi-pack-"));
180732
+ const built = mkdtempSync5(join83(tmpdir6(), "himi-pack-"));
180626
180733
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
180627
180734
  const outcome = await buildReleaseFromContent2(dir, built, {
180628
180735
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -180829,7 +180936,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
180829
180936
  }));
180830
180937
  return 1;
180831
180938
  }
180832
- const archive = readFileSync98(resolve60(file2));
180939
+ const archive = readFileSync99(resolve60(file2));
180833
180940
  const result = await client2().createPackageShare({
180834
180941
  app: opened.header.app,
180835
180942
  releaseId: opened.header.releaseId,
@@ -180926,11 +181033,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
180926
181033
  const app = await appId(dir2);
180927
181034
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
180928
181035
  const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
180929
- temp = mkdtempSync5(join82(tmpdir6(), "himi-run-build-"));
181036
+ temp = mkdtempSync5(join83(tmpdir6(), "himi-run-build-"));
180930
181037
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
180931
181038
  const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
180932
181039
  servedMissing = initial.missingBundles;
180933
- source = join82(temp, app);
181040
+ source = join83(temp, app);
180934
181041
  }
180935
181042
  const chromeArg = str9(flags.chrome) ?? "preview";
180936
181043
  if (chromeArg !== "preview" && chromeArg !== "app") {
@@ -180969,7 +181076,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
180969
181076
  if (!recordKit) return;
180970
181077
  startedAt = (/* @__PURE__ */ new Date()).toISOString();
180971
181078
  const failure = record2(served2, { ok: true, at: startedAt });
180972
- if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join82(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
181079
+ if (!recorded) io2.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join83(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
180973
181080
  await refreshBoard();
180974
181081
  };
180975
181082
  const retract = async () => {
@@ -181005,7 +181112,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181005
181112
  const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
181006
181113
  const hhpPreviewRoute = watch2 ? (await Promise.resolve().then(() => (init_hhp_preview(), hhp_preview_exports))).hhpPreviewResponse : null;
181007
181114
  const bus = watchKit ? new watchKit.ReloadBus() : void 0;
181008
- if (watch2) served = mkdtempSync5(join82(tmpdir6(), "himi-run-served-"));
181115
+ if (watch2) served = mkdtempSync5(join83(tmpdir6(), "himi-run-served-"));
181009
181116
  const running = await runPackage2(source, {
181010
181117
  port,
181011
181118
  chrome: chromeArg,
@@ -181034,8 +181141,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181034
181141
  await announce(running);
181035
181142
  if (watchKit && bus) {
181036
181143
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
181037
- const live3 = join82(running.releaseRoot, running.app);
181038
- const manifestOf = (tree) => JSON.parse(readFileSync98(join82(tree, "release-manifest.json"), "utf8"));
181144
+ const live3 = join83(running.releaseRoot, running.app);
181145
+ const manifestOf = (tree) => JSON.parse(readFileSync99(join83(tree, "release-manifest.json"), "utf8"));
181039
181146
  let current = manifestOf(live3);
181040
181147
  const failed3 = async (message) => {
181041
181148
  if (stopping) return;
@@ -181046,7 +181153,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181046
181153
  };
181047
181154
  rebuild = watchKit.serialize(async () => {
181048
181155
  const t0 = Date.now();
181049
- const next = mkdtempSync5(join82(tmpdir6(), "himi-run-build-"));
181156
+ const next = mkdtempSync5(join83(tmpdir6(), "himi-run-build-"));
181050
181157
  try {
181051
181158
  const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
181052
181159
  if (bres.compileErrors.length) {
@@ -181063,16 +181170,16 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181063
181170
  return;
181064
181171
  }
181065
181172
  if (stopping) return;
181066
- const fresh = manifestOf(join82(next, running.app));
181173
+ const fresh = manifestOf(join83(next, running.app));
181067
181174
  const diff = watchKit.diffReleases(current, fresh);
181068
181175
  const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
181069
- const changes = describeChanges2(live3, join82(next, running.app), diff);
181176
+ const changes = describeChanges2(live3, join83(next, running.app), diff);
181070
181177
  const retired = `${live3}.retired-${Date.now()}`;
181071
181178
  renameSync12(live3, retired);
181072
181179
  try {
181073
- renameSync12(join82(next, running.app), live3);
181180
+ renameSync12(join83(next, running.app), live3);
181074
181181
  } catch {
181075
- cpSync3(join82(next, running.app), live3, { recursive: true });
181182
+ cpSync3(join83(next, running.app), live3, { recursive: true });
181076
181183
  }
181077
181184
  rmSync22(retired, { recursive: true, force: true });
181078
181185
  current = fresh;
@@ -181755,7 +181862,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181755
181862
  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."
181756
181863
  };
181757
181864
  if (kind === "tokens" || kind === "app-config") {
181758
- const body = readFileSync98(file2, "utf8");
181865
+ const body = readFileSync99(file2, "utf8");
181759
181866
  const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
181760
181867
  return runReleasePatch({
181761
181868
  ...common,
@@ -181770,7 +181877,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181770
181877
  io2.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
181771
181878
  return 2;
181772
181879
  }
181773
- const descriptor = readFileSync98(file2, "utf8");
181880
+ const descriptor = readFileSync99(file2, "utf8");
181774
181881
  try {
181775
181882
  JSON.parse(descriptor);
181776
181883
  } catch (e2) {
@@ -181810,7 +181917,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181810
181917
  extra: { kind, screen: id, file: { path: file2, bytes: Buffer.byteLength(descriptor, "utf8") } }
181811
181918
  });
181812
181919
  }
181813
- const bytes2 = readFileSync98(file2);
181920
+ const bytes2 = readFileSync99(file2);
181814
181921
  const sha2 = createHash41("sha256").update(bytes2).digest("hex");
181815
181922
  const forScreens = (str9(flags["for-screen"]) ?? "").split(",").map((s2) => s2.trim()).filter(Boolean);
181816
181923
  if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
@@ -181954,7 +182061,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
181954
182061
  }
181955
182062
  let def;
181956
182063
  try {
181957
- const parsed = JSON.parse(arg.startsWith("@") ? readFileSync98(arg.slice(1), "utf8") : arg);
182064
+ const parsed = JSON.parse(arg.startsWith("@") ? readFileSync99(arg.slice(1), "utf8") : arg);
181958
182065
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
181959
182066
  io2.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
181960
182067
  return 2;
@@ -182236,7 +182343,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
182236
182343
  const rememberLastDist = async (jobs2) => {
182237
182344
  try {
182238
182345
  const dir = contentDir(flags);
182239
- if (!existsSync80(join82(dir, "himalaya.content.json"))) return;
182346
+ if (!existsSync80(join83(dir, "himalaya.content.json"))) return;
182240
182347
  const { lastDistFromJob: lastDistFromJob2, writeLastDist: writeLastDist2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
182241
182348
  const own4 = await appId(dir);
182242
182349
  for (const job of jobs2) {
@@ -182474,7 +182581,7 @@ ${label2}`);
182474
182581
  const platform = str9(flags.platform)?.split(",").map((p2) => p2.trim()).filter(Boolean);
182475
182582
  {
182476
182583
  const distDir = contentDir(flags);
182477
- if (existsSync80(join82(distDir, "himalaya.content.json"))) {
182584
+ if (existsSync80(join83(distDir, "himalaya.content.json"))) {
182478
182585
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
182479
182586
  const errors = issues.filter((i2) => i2.severity === "error");
182480
182587
  for (const i2 of issues.filter((i3) => i3.severity === "warning")) {
@@ -182813,7 +182920,7 @@ ${label2}`);
182813
182920
  const dpxPath = dpxSessionTokenPath();
182814
182921
  let dpx;
182815
182922
  try {
182816
- dpx = readFileSync98(dpxPath, "utf8").trim();
182923
+ dpx = readFileSync99(dpxPath, "utf8").trim();
182817
182924
  } catch {
182818
182925
  io2.error(JSON.stringify({ error: `no dpx session at ${dpxPath} \u2014 run \`dpx auth login\` then \`dpx auth token > ${dpxPath}\` (dpx 2.x keeps its own state in ~/.dpx/auth.json and does NOT write the legacy session file), or omit --dpx` }));
182819
182926
  return 1;
@@ -183234,7 +183341,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
183234
183341
  const path2 = dpxSessionTokenPath();
183235
183342
  let raw;
183236
183343
  try {
183237
- raw = readFileSync98(path2, "utf8");
183344
+ raw = readFileSync99(path2, "utf8");
183238
183345
  } catch {
183239
183346
  io2.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
183240
183347
  return 1;