@wix/himalaya-cli 0.809.0 → 0.811.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -445,7 +445,7 @@ var WIX_COLLECTION_ID_MAX_LENGTH, SAFE_APP_ID, KV_NAME;
445
445
  var init_ownership = __esm({
446
446
  "../../core/data-resources/src/ownership.ts"() {
447
447
  init_schema();
448
- WIX_COLLECTION_ID_MAX_LENGTH = 36;
448
+ WIX_COLLECTION_ID_MAX_LENGTH = 256;
449
449
  SAFE_APP_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*(?:\.[a-z0-9]+(?:-[a-z0-9]+)*)?$/;
450
450
  KV_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
451
451
  }
@@ -807,7 +807,13 @@ var init_source_deny = __esm({
807
807
  /^\.env\./,
808
808
  /^\.DS_Store$/,
809
809
  /^id_rsa($|\.)/,
810
- /\.(pem|p8|p12|keystore|jks|mobileprovision)$/i
810
+ /\.(pem|p8|p12|keystore|jks|mobileprovision)$/i,
811
+ // `.git` IS NOT ALWAYS A DIRECTORY. In a linked worktree or a submodule it is a FILE holding
812
+ // `gitdir: …`, and DENY_DIRS is consulted for directories only — so at a package root it was
813
+ // denied by nothing: `himi push` archived the pointer, and `himi pull --replace` would delete
814
+ // it back out of a checkout whose release predates it (#2437). The guarantee that a restore
815
+ // cannot cost you a git history has to hold for both shapes of `.git`, not just the common one.
816
+ /^\.git$/
811
817
  ];
812
818
  }
813
819
  });
@@ -1954,7 +1960,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
1954
1960
  tokenCache.set(cacheKey, fromEnv);
1955
1961
  return fromEnv;
1956
1962
  }
1957
- const token = await new Promise((resolve40, reject) => {
1963
+ const token = await new Promise((resolve41, reject) => {
1958
1964
  let child;
1959
1965
  try {
1960
1966
  child = spawnImpl("wix", [...args]);
@@ -1983,12 +1989,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
1983
1989
  child.stdout?.on("data", (d) => {
1984
1990
  out += String(d);
1985
1991
  const m = out.match(TOKEN_RE);
1986
- if (m) done(() => resolve40(m[0]));
1992
+ if (m) done(() => resolve41(m[0]));
1987
1993
  });
1988
1994
  child.stderr?.on("data", (d) => {
1989
1995
  out += String(d);
1990
1996
  const m = out.match(TOKEN_RE);
1991
- if (m) done(() => resolve40(m[0]));
1997
+ if (m) done(() => resolve41(m[0]));
1992
1998
  });
1993
1999
  child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
1994
2000
  child.on("exit", (code) => done(() => reject(new Error(
@@ -7350,7 +7356,7 @@ async function injectRequest(listener, request) {
7350
7356
  req.headers.host ??= url.host;
7351
7357
  if (body && body.length > 0) req.push(body);
7352
7358
  req.push(null);
7353
- return await new Promise((resolve40, reject) => {
7359
+ return await new Promise((resolve41, reject) => {
7354
7360
  const streamed = () => {
7355
7361
  queueMicrotask(() => {
7356
7362
  req.emit("close");
@@ -7366,7 +7372,7 @@ async function injectRequest(listener, request) {
7366
7372
  else headers2.set(name, value);
7367
7373
  }
7368
7374
  const bodyless = out.status === 204 || out.status === 304 || request.method === "HEAD";
7369
- resolve40(new Response(bodyless ? null : out.body, { status: out.status, headers: headers2 }));
7375
+ resolve41(new Response(bodyless ? null : out.body, { status: out.status, headers: headers2 }));
7370
7376
  }, streamed);
7371
7377
  res.on("inject-error", reject);
7372
7378
  try {
@@ -9738,12 +9744,12 @@ function finalizeRecording(key2, rec) {
9738
9744
  if (rec.finalize) return rec.finalize;
9739
9745
  rec.finalize = (async () => {
9740
9746
  clearTimeout(rec.autoStop);
9741
- await new Promise((resolve40) => {
9747
+ await new Promise((resolve41) => {
9742
9748
  let done = false;
9743
9749
  const finish2 = () => {
9744
9750
  if (!done) {
9745
9751
  done = true;
9746
- resolve40();
9752
+ resolve41();
9747
9753
  }
9748
9754
  };
9749
9755
  rec.child.once("close", finish2);
@@ -9854,7 +9860,7 @@ var init_preview = __esm({
9854
9860
  DEVICE_LIST_TIMEOUT_MS = 5e3;
9855
9861
  defaultRunner2 = {
9856
9862
  capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
9857
- return new Promise((resolve40, reject) => {
9863
+ return new Promise((resolve41, reject) => {
9858
9864
  const child = spawn2(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
9859
9865
  const out = [];
9860
9866
  const err = [];
@@ -9876,7 +9882,7 @@ var init_preview = __esm({
9876
9882
  child.stderr.on("data", (b) => err.push(b));
9877
9883
  child.on("error", (e) => settle(reject, e));
9878
9884
  child.on("close", (code) => {
9879
- if (code === 0) settle(resolve40, Buffer.concat(out));
9885
+ if (code === 0) settle(resolve41, Buffer.concat(out));
9880
9886
  else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
9881
9887
  });
9882
9888
  });
@@ -11453,7 +11459,6 @@ function shouldRevealError(args) {
11453
11459
  var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
11454
11460
  var init_validation = __esm({
11455
11461
  "../../core/ts/src/validation.ts"() {
11456
- "use strict";
11457
11462
  EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
11458
11463
  URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
11459
11464
  INTEGER_RE = /^[+-]?[0-9]+$/;
@@ -14799,7 +14804,6 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
14799
14804
  var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
14800
14805
  var init_worker_subtree = __esm({
14801
14806
  "../../core/ts/src/worker-subtree.ts"() {
14802
- "use strict";
14803
14807
  init_worker_subtree_safe_types_generated();
14804
14808
  WORKER_SUBTREE_CEILINGS = Object.freeze({
14805
14809
  maxEncodedBytes: 65536,
@@ -20185,7 +20189,7 @@ async function stabilizePngPage(page, scheme) {
20185
20189
  const browser = globalThis;
20186
20190
  browser.document.documentElement.style.colorScheme = selected;
20187
20191
  await browser.document.fonts?.ready;
20188
- await new Promise((resolve40) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve40())));
20192
+ await new Promise((resolve41) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve41())));
20189
20193
  }, scheme);
20190
20194
  }
20191
20195
  async function renderPngBatch(items) {
@@ -25751,7 +25755,7 @@ async function handleWebWix(req, res, state) {
25751
25755
  const match = state.wix.mode === "mock" ? matchRuleEx(state.wix.rules, method, target.pathname, { host: target.host, query, body }) : void 0;
25752
25756
  if (match && (match.rule.kind ?? "mock") === "mock") {
25753
25757
  const mocked = match.rule.response;
25754
- if (mocked.delayMs) await new Promise((resolve40) => setTimeout(resolve40, mocked.delayMs));
25758
+ if (mocked.delayMs) await new Promise((resolve41) => setTimeout(resolve41, mocked.delayMs));
25755
25759
  const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
25756
25760
  recordWixTraffic(state.wix, state.appName, state.adminUrl, {
25757
25761
  ts: started,
@@ -31245,38 +31249,49 @@ var app_source_exports = {};
31245
31249
  __export(app_source_exports, {
31246
31250
  MAX_APP_SOURCE_BYTES: () => MAX_APP_SOURCE_BYTES,
31247
31251
  collectAppSource: () => collectAppSource,
31252
+ deniedArchivePaths: () => deniedArchivePaths,
31248
31253
  isDeniedSourcePath: () => isDeniedSourcePath,
31249
31254
  readAppSource: () => readAppSource,
31255
+ removeStaleSource: () => removeStaleSource,
31250
31256
  secretFindings: () => secretFindings,
31257
+ staleSourcePaths: () => staleSourcePaths,
31251
31258
  writeAppSource: () => writeAppSource,
31259
+ writeConflicts: () => writeConflicts,
31252
31260
  zipAppSource: () => zipAppSource
31253
31261
  });
31254
- import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as readFileSync43, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14 } from "node:fs";
31255
- import { join as join36, dirname as dirname24, sep as sep7 } from "node:path";
31256
- function collectAppSource(dir) {
31257
- const entries = [];
31258
- const skipped = [];
31262
+ import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as readFileSync43, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14, existsSync as existsSync36, rmSync as rmSync6, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
31263
+ import { join as join36, resolve as resolve32, sep as sep7 } from "node:path";
31264
+ function walkSourceTree(dir, file, skip) {
31259
31265
  const walk2 = (relDir) => {
31260
31266
  for (const name of readdirSync20(join36(dir, relDir))) {
31261
31267
  const rel = relDir ? join36(relDir, name) : name;
31262
31268
  const st = lstatSync4(join36(dir, rel));
31263
31269
  if (st.isSymbolicLink()) {
31264
- skipped.push(rel);
31270
+ skip(rel);
31265
31271
  continue;
31266
31272
  }
31267
31273
  if (st.isDirectory()) {
31268
- if (isDeniedSourceDir(name)) skipped.push(rel);
31274
+ if (isDeniedSourceDir(name)) skip(rel);
31269
31275
  else walk2(rel);
31270
31276
  continue;
31271
31277
  }
31272
31278
  if (isDeniedSourcePath(rel)) {
31273
- skipped.push(rel);
31279
+ skip(rel);
31274
31280
  continue;
31275
31281
  }
31276
- entries.push({ path: rel.split(sep7).join("/"), bytes: readFileSync43(join36(dir, rel)) });
31282
+ file(rel.split(sep7).join("/"), rel);
31277
31283
  }
31278
31284
  };
31279
31285
  walk2("");
31286
+ }
31287
+ function collectAppSource(dir) {
31288
+ const entries = [];
31289
+ const skipped = [];
31290
+ walkSourceTree(
31291
+ dir,
31292
+ (archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync43(join36(dir, hostRel)) }),
31293
+ (hostRel) => skipped.push(hostRel)
31294
+ );
31280
31295
  entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
31281
31296
  skipped.sort();
31282
31297
  return { entries, skipped };
@@ -31296,16 +31311,115 @@ function zipAppSource(entries) {
31296
31311
  function readAppSource(zip) {
31297
31312
  return [...readZip(zip)].map(([path, bytes2]) => ({ path, bytes: bytes2 }));
31298
31313
  }
31314
+ function pathKind(p) {
31315
+ try {
31316
+ return lstatSync4(p);
31317
+ } catch {
31318
+ return null;
31319
+ }
31320
+ }
31299
31321
  function writeAppSource(entries, destDir) {
31322
+ const root = resolve32(destDir);
31323
+ mkdirSync18(root, { recursive: true });
31300
31324
  const written = [];
31301
31325
  for (const entry of entries) {
31302
- const target = join36(destDir, ...entry.path.split("/"));
31303
- mkdirSync18(dirname24(target), { recursive: true });
31326
+ if (isDeniedSourcePath(entry.path)) continue;
31327
+ const segments = entry.path.split("/");
31328
+ let dir = root;
31329
+ for (const segment of segments.slice(0, -1)) {
31330
+ dir = join36(dir, segment);
31331
+ const kind = pathKind(dir);
31332
+ if (kind?.isSymbolicLink()) unlinkSync3(dir);
31333
+ else if (kind) continue;
31334
+ mkdirSync18(dir);
31335
+ }
31336
+ const target = join36(root, ...segments);
31337
+ if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
31304
31338
  writeFileSync14(target, entry.bytes);
31305
31339
  written.push(entry.path);
31306
31340
  }
31307
31341
  return written;
31308
31342
  }
31343
+ function staleSourcePaths(entries, destDir) {
31344
+ if (!existsSync36(destDir)) return [];
31345
+ const archived = new Set(entries.map((e) => e.path));
31346
+ const stale = [];
31347
+ walkSourceTree(destDir, (archivePath) => {
31348
+ if (!archived.has(archivePath)) stale.push(archivePath);
31349
+ }, () => {
31350
+ });
31351
+ return stale.sort();
31352
+ }
31353
+ function deniedArchivePaths(entries) {
31354
+ return entries.filter((e) => isDeniedSourcePath(e.path)).map((e) => e.path).sort();
31355
+ }
31356
+ function writeConflicts(entries, destDir) {
31357
+ const root = resolve32(destDir);
31358
+ const conflicts = [];
31359
+ const seen = /* @__PURE__ */ new Set();
31360
+ const say = (rel, what) => {
31361
+ if (seen.has(rel)) return;
31362
+ seen.add(rel);
31363
+ conflicts.push(`${rel} ${what}`);
31364
+ };
31365
+ for (const entry of entries) {
31366
+ if (isDeniedSourcePath(entry.path)) continue;
31367
+ const segments = entry.path.split("/");
31368
+ let dir = root;
31369
+ let stop = false;
31370
+ for (const [i, segment] of segments.slice(0, -1).entries()) {
31371
+ dir = join36(dir, segment);
31372
+ const kind2 = pathKind(dir);
31373
+ if (!kind2 || kind2.isSymbolicLink()) {
31374
+ stop = true;
31375
+ break;
31376
+ }
31377
+ if (kind2.isDirectory()) continue;
31378
+ say(segments.slice(0, i + 1).join("/"), "is a file here, but the release has a directory at that path");
31379
+ stop = true;
31380
+ break;
31381
+ }
31382
+ if (stop) continue;
31383
+ const kind = pathKind(join36(root, ...segments));
31384
+ if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
31385
+ say(entry.path, "is a directory here, but the release has a file at that path");
31386
+ }
31387
+ }
31388
+ return conflicts;
31389
+ }
31390
+ function removeStaleSource(entries, destDir) {
31391
+ const root = resolve32(destDir);
31392
+ const removed = staleSourcePaths(entries, root);
31393
+ for (const rel of removed) rmSync6(join36(root, ...rel.split("/")), { force: true });
31394
+ const needed = /* @__PURE__ */ new Set();
31395
+ for (const entry of entries) {
31396
+ if (isDeniedSourcePath(entry.path)) continue;
31397
+ const segments = entry.path.split("/");
31398
+ for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
31399
+ }
31400
+ if (existsSync36(root)) pruneEmptyDirs(root, "", needed, removed);
31401
+ return removed.sort();
31402
+ }
31403
+ function pruneEmptyDirs(root, rel, needed, removed) {
31404
+ let empty = true;
31405
+ for (const name of readdirSync20(rel ? join36(root, rel) : root)) {
31406
+ const childRel = rel ? join36(rel, name) : name;
31407
+ const posix3 = childRel.split(sep7).join("/");
31408
+ const kind = lstatSync4(join36(root, childRel));
31409
+ if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name)) {
31410
+ empty = false;
31411
+ continue;
31412
+ }
31413
+ const childEmpty = pruneEmptyDirs(root, childRel, needed, removed);
31414
+ if (!childEmpty || needed.has(posix3)) {
31415
+ empty = false;
31416
+ continue;
31417
+ }
31418
+ rmdirSync(join36(root, childRel));
31419
+ removed.push(`${posix3}/`);
31420
+ }
31421
+ return empty;
31422
+ }
31309
31423
  var MAX_APP_SOURCE_BYTES, SECRET_PATTERNS;
31310
31424
  var init_app_source = __esm({
31311
31425
  "src/app-source.ts"() {
@@ -31329,13 +31443,13 @@ __export(eject_exports, {
31329
31443
  EJECTABLE: () => EJECTABLE,
31330
31444
  ejectModule: () => ejectModule
31331
31445
  });
31332
- import { existsSync as existsSync36, mkdirSync as mkdirSync19, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
31333
- import { dirname as dirname25, join as join37, relative as relative4, resolve as resolve32, sep as sep8 } from "node:path";
31446
+ import { existsSync as existsSync37, mkdirSync as mkdirSync19, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
31447
+ import { dirname as dirname24, join as join37, relative as relative4, resolve as resolve33, sep as sep8 } from "node:path";
31334
31448
  function locate(repoRootOrCwd, mod) {
31335
- const inRepo = resolve32(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
31336
- if (existsSync36(inRepo)) return { path: inRepo, form: "source" };
31337
- const dist = resolve32(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
31338
- if (existsSync36(dist)) return { path: dist, form: "bundle" };
31449
+ const inRepo = resolve33(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
31450
+ if (existsSync37(inRepo)) return { path: inRepo, form: "source" };
31451
+ const dist = resolve33(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
31452
+ if (existsSync37(dist)) return { path: dist, form: "bundle" };
31339
31453
  return null;
31340
31454
  }
31341
31455
  function specifiersFor(mod) {
@@ -31360,7 +31474,7 @@ function ejectModule(opts) {
31360
31474
  }
31361
31475
  const ext = found.form === "source" ? "ts" : "mjs";
31362
31476
  const target = join37(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
31363
- mkdirSync19(dirname25(target), { recursive: true });
31477
+ mkdirSync19(dirname24(target), { recursive: true });
31364
31478
  const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
31365
31479
  //
31366
31480
  // Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
@@ -31380,10 +31494,10 @@ function ejectModule(opts) {
31380
31494
  writeFileSync15(target, banner + normalized);
31381
31495
  const rewired = [];
31382
31496
  for (const f of files) {
31383
- if (!existsSync36(f)) continue;
31497
+ if (!existsSync37(f)) continue;
31384
31498
  const before = readFileSync44(f, "utf8");
31385
31499
  let after = before;
31386
- let rel = relative4(dirname25(f), target).split(sep8).join("/").replace(/\.tsx?$/, ".js");
31500
+ let rel = relative4(dirname24(f), target).split(sep8).join("/").replace(/\.tsx?$/, ".js");
31387
31501
  if (!rel.startsWith(".")) rel = `./${rel}`;
31388
31502
  for (const spec of specifiersFor(mod)) {
31389
31503
  const q = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -31429,11 +31543,11 @@ __export(test_exports, {
31429
31543
  scopeDescriptors: () => scopeDescriptors,
31430
31544
  writeRecordedMocks: () => writeRecordedMocks
31431
31545
  });
31432
- import { existsSync as existsSync37, mkdirSync as mkdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync16 } from "node:fs";
31433
- import { join as join38, resolve as resolve33 } from "node:path";
31546
+ import { existsSync as existsSync38, mkdirSync as mkdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync16 } from "node:fs";
31547
+ import { join as join38, resolve as resolve34 } from "node:path";
31434
31548
  function readTestConfig(dir) {
31435
- const p = resolve33(dir, TEST_CONFIG_FILE);
31436
- if (!existsSync37(p)) return {};
31549
+ const p = resolve34(dir, TEST_CONFIG_FILE);
31550
+ if (!existsSync38(p)) return {};
31437
31551
  let parsed;
31438
31552
  try {
31439
31553
  parsed = JSON.parse(readFileSync45(p, "utf8"));
@@ -31499,8 +31613,8 @@ function readNetRules(path) {
31499
31613
  }
31500
31614
  function defaultNetRules(dir) {
31501
31615
  for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
31502
- const p = resolve33(dir, rel);
31503
- if (existsSync37(p)) {
31616
+ const p = resolve34(dir, rel);
31617
+ if (existsSync38(p)) {
31504
31618
  const rules = readNetRules(p);
31505
31619
  if (rules.length) return { rules, from: rel };
31506
31620
  }
@@ -31672,7 +31786,7 @@ async function runCrawl(opts) {
31672
31786
  if (list.length > 1) collapsed.push({ representative: rep.screenId, instances: list.length });
31673
31787
  }
31674
31788
  }
31675
- const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(resolve33(opts.netPath)), from: opts.netPath } : defaultNetRules(opts.dir);
31789
+ const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(resolve34(opts.netPath)), from: opts.netPath } : defaultNetRules(opts.dir);
31676
31790
  const suppressions = opts.config?.skip ?? [];
31677
31791
  const suppressed = [];
31678
31792
  const matchSuppression = (screen, actionId, componentId, invariant) => suppressions.find((s) => (s.screen === void 0 || s.screen === screen) && (s.action === void 0 || s.action === actionId) && (s.component === void 0 || s.component === componentId) && (s.invariant === void 0 || s.invariant === invariant));
@@ -32049,11 +32163,11 @@ var mobile_ux_lint_exports = {};
32049
32163
  __export(mobile_ux_lint_exports, {
32050
32164
  mobileUxIssues: () => mobileUxIssues
32051
32165
  });
32052
- import { existsSync as existsSync38, readFileSync as readFileSync46 } from "node:fs";
32166
+ import { existsSync as existsSync39, readFileSync as readFileSync46 } from "node:fs";
32053
32167
  import { join as join39 } from "node:path";
32054
32168
  function mobileUxIssues(dir, strict) {
32055
32169
  const file = join39(dir, "MOBILE-UX.md");
32056
- if (!existsSync38(file)) return [];
32170
+ if (!existsSync39(file)) return [];
32057
32171
  let text2;
32058
32172
  try {
32059
32173
  text2 = readFileSync46(file, "utf8");
@@ -32335,7 +32449,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
32335
32449
  const headers2 = Object.fromEntries(new Headers(init.headers).entries());
32336
32450
  const request = url.protocol === "https:" ? httpsRequest : httpRequest;
32337
32451
  const hostname = url.hostname.replace(/^\[|\]$/g, "");
32338
- return await new Promise((resolve40, reject) => {
32452
+ return await new Promise((resolve41, reject) => {
32339
32453
  let settled = false;
32340
32454
  const finish2 = (fn) => {
32341
32455
  if (settled) return;
@@ -32372,7 +32486,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
32372
32486
  }
32373
32487
  const responseHeaders = new Headers();
32374
32488
  for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
32375
- resolve40(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
32489
+ resolve41(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
32376
32490
  }));
32377
32491
  });
32378
32492
  req.once("error", (error) => finish2(() => reject(error)));
@@ -32672,7 +32786,7 @@ function createLocalTestSandbox() {
32672
32786
  }
32673
32787
  })();
32674
32788
  `;
32675
- return await new Promise((resolve40, reject) => {
32789
+ return await new Promise((resolve41, reject) => {
32676
32790
  const { port1, port2 } = new MessageChannel();
32677
32791
  const serializableContext = {
32678
32792
  auth: context.auth,
@@ -32748,7 +32862,7 @@ function createLocalTestSandbox() {
32748
32862
  timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
32749
32863
  return;
32750
32864
  }
32751
- if (message.ok) finish2(() => resolve40({ value: message.value, durationMs: Date.now() - started }));
32865
+ if (message.ok) finish2(() => resolve41({ value: message.value, durationMs: Date.now() - started }));
32752
32866
  else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
32753
32867
  });
32754
32868
  worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
@@ -33715,8 +33829,8 @@ __export(functions_exports, {
33715
33829
  resolveFunctionsTarget: () => resolveFunctionsTarget,
33716
33830
  runRemoteFunctionOperation: () => runRemoteFunctionOperation
33717
33831
  });
33718
- import { readFileSync as readFileSync47, existsSync as existsSync39 } from "node:fs";
33719
- import { join as join40, resolve as resolve34 } from "node:path";
33832
+ import { readFileSync as readFileSync47, existsSync as existsSync40 } from "node:fs";
33833
+ import { join as join40, resolve as resolve35 } from "node:path";
33720
33834
  function resolveFunctionsTarget(input) {
33721
33835
  const explicitUrl = input.functionsUrl?.trim();
33722
33836
  if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
@@ -33728,14 +33842,14 @@ function resolveFunctionsTarget(input) {
33728
33842
  return { mode: "local" };
33729
33843
  }
33730
33844
  async function loadFunctionsApp(dir) {
33731
- const loaded = await loadContent(resolve34(dir));
33845
+ const loaded = await loadContent(resolve35(dir));
33732
33846
  const config = loaded.module.config;
33733
33847
  if (config.kind !== "functions" || !Array.isArray(config.functions?.functions)) {
33734
33848
  throw new Error(`content package "${dir}" is not a functions-only app`);
33735
33849
  }
33736
33850
  const sources = {};
33737
33851
  for (const definition of config.functions.functions) {
33738
- const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join40(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync39);
33852
+ const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join40(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync40);
33739
33853
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
33740
33854
  sources[definition.name] = readFileSync47(source, "utf8");
33741
33855
  }
@@ -33891,7 +34005,7 @@ __export(native_decode_exports, {
33891
34005
  runNativeDecode: () => runNativeDecode
33892
34006
  });
33893
34007
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
33894
- import { existsSync as existsSync40, mkdtempSync as mkdtempSync2, readFileSync as readFileSync48, rmSync as rmSync6, writeFileSync as writeFileSync17 } from "node:fs";
34008
+ import { existsSync as existsSync41, mkdtempSync as mkdtempSync2, readFileSync as readFileSync48, rmSync as rmSync7, writeFileSync as writeFileSync17 } from "node:fs";
33895
34009
  import { tmpdir as tmpdir3 } from "node:os";
33896
34010
  import { join as join41 } from "node:path";
33897
34011
  import { fileURLToPath as fileURLToPath19 } from "node:url";
@@ -33909,7 +34023,7 @@ function detectNativeDecode(options = {}) {
33909
34023
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
33910
34024
  }
33911
34025
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
33912
- const packageAvailable = options.packageAvailable ?? existsSync40(join41(packageDir, "Package.swift"));
34026
+ const packageAvailable = options.packageAvailable ?? existsSync41(join41(packageDir, "Package.swift"));
33913
34027
  if (!packageAvailable) {
33914
34028
  return {
33915
34029
  platform: "ios",
@@ -33930,7 +34044,7 @@ function localPropertiesSdk(harnessDir) {
33930
34044
  function detectAndroidNativeDecode(options = {}) {
33931
34045
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
33932
34046
  const gradlew = join41(harnessDir, "gradlew");
33933
- const gradlewAvailable = options.gradlewAvailable ?? existsSync40(gradlew);
34047
+ const gradlewAvailable = options.gradlewAvailable ?? existsSync41(gradlew);
33934
34048
  if (!gradlewAvailable) {
33935
34049
  return {
33936
34050
  platform: "android",
@@ -33940,7 +34054,7 @@ function detectAndroidNativeDecode(options = {}) {
33940
34054
  }
33941
34055
  const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
33942
34056
  const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
33943
- const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync40(sdk));
34057
+ const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync41(sdk));
33944
34058
  if (!sdkAvailable) {
33945
34059
  return {
33946
34060
  platform: "android",
@@ -34045,7 +34159,7 @@ function runNativeDecode(options) {
34045
34159
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
34046
34160
  throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
34047
34161
  } finally {
34048
- rmSync6(descriptorDir, { recursive: true, force: true });
34162
+ rmSync7(descriptorDir, { recursive: true, force: true });
34049
34163
  }
34050
34164
  }
34051
34165
  function runAndroidNativeDecode(options) {
@@ -34083,7 +34197,7 @@ function runAndroidNativeDecode(options) {
34083
34197
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
34084
34198
  throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
34085
34199
  } finally {
34086
- rmSync6(descriptorDir, { recursive: true, force: true });
34200
+ rmSync7(descriptorDir, { recursive: true, force: true });
34087
34201
  }
34088
34202
  }
34089
34203
  function fieldAt(path) {
@@ -34143,7 +34257,7 @@ __export(browser_authoring_exports, {
34143
34257
  import { createServer as createServer3 } from "node:http";
34144
34258
  import { createHash as createHash22, randomBytes as randomBytes5 } from "node:crypto";
34145
34259
  import { execFile as execFile2 } from "node:child_process";
34146
- import { existsSync as existsSync41, readdirSync as readdirSync21, readFileSync as readFileSync49, realpathSync as realpathSync4, statSync as statSync9 } from "node:fs";
34260
+ import { existsSync as existsSync42, readdirSync as readdirSync21, readFileSync as readFileSync49, realpathSync as realpathSync4, statSync as statSync9 } from "node:fs";
34147
34261
  import { join as join42, posix, relative as relative5, sep as sep9 } from "node:path";
34148
34262
  function humanMs(ms) {
34149
34263
  return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
@@ -34166,7 +34280,7 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
34166
34280
  }
34167
34281
  }
34168
34282
  };
34169
- if (!existsSync41(root)) return null;
34283
+ if (!existsSync42(root)) return null;
34170
34284
  walk2(root, `/tier5-src/${bundleName}`);
34171
34285
  const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
34172
34286
  if (!entry) return null;
@@ -34193,7 +34307,7 @@ function collectRelativeSiblings(files, tier5SrcDir) {
34193
34307
  join42(onDisk, "index.js")
34194
34308
  ];
34195
34309
  for (const abs of candidates) {
34196
- if (!existsSync41(abs) || statSync9(abs).isDirectory()) continue;
34310
+ if (!existsSync42(abs) || statSync9(abs).isDirectory()) continue;
34197
34311
  const key2 = `/tier5-src/${relative5(tier5SrcDir, abs).split(sep9).join(posix.sep)}`;
34198
34312
  if (key2 in files) break;
34199
34313
  files[key2] = readFileSync49(abs, "utf8");
@@ -34228,10 +34342,10 @@ function collectSdkModules(files, resolveSubpath) {
34228
34342
  for (const source of Object.values(files)) visit(source);
34229
34343
  return { modules, unsupported };
34230
34344
  }
34231
- function sdkSubpathReader(resolve40) {
34345
+ function sdkSubpathReader(resolve41) {
34232
34346
  return (sub) => {
34233
34347
  try {
34234
- return readFileSync49(resolve40(`@wix/himalaya/${sub}`), "utf8");
34348
+ return readFileSync49(resolve41(`@wix/himalaya/${sub}`), "utf8");
34235
34349
  } catch {
34236
34350
  return null;
34237
34351
  }
@@ -34312,7 +34426,7 @@ async function runBrowserAuthoring(opts) {
34312
34426
  const token = mintToken2(payload);
34313
34427
  const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
34314
34428
  if (unusable) throw new Error(unusable);
34315
- return await new Promise((resolve40, reject) => {
34429
+ return await new Promise((resolve41, reject) => {
34316
34430
  let settled = false;
34317
34431
  let url = "";
34318
34432
  const server = createServer3();
@@ -34364,7 +34478,7 @@ async function runBrowserAuthoring(opts) {
34364
34478
  }
34365
34479
  res.writeHead(200, { "content-type": "text/plain" }).end("ok");
34366
34480
  const report = body.result;
34367
- finish2(() => resolve40({ report, url }));
34481
+ finish2(() => resolve41({ report, url }));
34368
34482
  })();
34369
34483
  });
34370
34484
  server.on("error", (e) => finish2(() => reject(e)));
@@ -34404,8 +34518,8 @@ __export(coverage_exports, {
34404
34518
  formatLedger: () => formatLedger,
34405
34519
  trendAndStore: () => trendAndStore
34406
34520
  });
34407
- import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync50, writeFileSync as writeFileSync18 } from "node:fs";
34408
- import { dirname as dirname26, join as join43 } from "node:path";
34521
+ import { existsSync as existsSync43, mkdirSync as mkdirSync21, readFileSync as readFileSync50, writeFileSync as writeFileSync18 } from "node:fs";
34522
+ import { dirname as dirname25, join as join43 } from "node:path";
34409
34523
  function assembleLedger(r) {
34410
34524
  const out = [];
34411
34525
  for (const c of r.crawled ?? []) {
@@ -34574,7 +34688,7 @@ function trendAndStore(dir, entries) {
34574
34688
  const p = join43(dir, LEDGER_FILE);
34575
34689
  let previous = null;
34576
34690
  try {
34577
- if (existsSync42(p)) {
34691
+ if (existsSync43(p)) {
34578
34692
  const parsed = JSON.parse(readFileSync50(p, "utf8"));
34579
34693
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
34580
34694
  }
@@ -34582,7 +34696,7 @@ function trendAndStore(dir, entries) {
34582
34696
  }
34583
34697
  const current = entries.map((e) => e.key);
34584
34698
  try {
34585
- mkdirSync21(dirname26(p), { recursive: true });
34699
+ mkdirSync21(dirname25(p), { recursive: true });
34586
34700
  writeFileSync18(p, JSON.stringify({ keys: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
34587
34701
  } catch {
34588
34702
  return null;
@@ -34615,7 +34729,7 @@ function diffAndStoreObservations(dir, current) {
34615
34729
  const p = join43(dir, OBS_FILE);
34616
34730
  let previous = null;
34617
34731
  try {
34618
- if (existsSync42(p)) {
34732
+ if (existsSync43(p)) {
34619
34733
  const parsed = JSON.parse(readFileSync50(p, "utf8"));
34620
34734
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
34621
34735
  (v) => Array.isArray(v) && v.every((l) => typeof l === "string")
@@ -34626,7 +34740,7 @@ function diffAndStoreObservations(dir, current) {
34626
34740
  } catch {
34627
34741
  }
34628
34742
  try {
34629
- mkdirSync21(dirname26(p), { recursive: true });
34743
+ mkdirSync21(dirname25(p), { recursive: true });
34630
34744
  writeFileSync18(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
34631
34745
  } catch {
34632
34746
  return null;
@@ -35869,7 +35983,7 @@ __export(run_exports, {
35869
35983
  runPackage: () => runPackage,
35870
35984
  withoutProdServe: () => withoutProdServe
35871
35985
  });
35872
- import { cpSync, existsSync as existsSync43, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync3, readFileSync as readFileSync52, rmSync as rmSync7, statSync as statSync10 } from "node:fs";
35986
+ import { cpSync, existsSync as existsSync44, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync3, readFileSync as readFileSync52, rmSync as rmSync8, statSync as statSync10 } from "node:fs";
35873
35987
  import { tmpdir as tmpdir4 } from "node:os";
35874
35988
  import { join as join44 } from "node:path";
35875
35989
  import { spawn as spawn3 } from "node:child_process";
@@ -35889,9 +36003,9 @@ async function fetchBytes(url) {
35889
36003
  }
35890
36004
  async function resolvePackage(source, workDir) {
35891
36005
  const isUrl2 = /^https?:\/\//i.test(source);
35892
- if (!isUrl2 && existsSync43(source) && statSync10(source).isDirectory()) {
36006
+ if (!isUrl2 && existsSync44(source) && statSync10(source).isDirectory()) {
35893
36007
  const appDirManifest = join44(source, "release-manifest.json");
35894
- if (existsSync43(appDirManifest)) {
36008
+ if (existsSync44(appDirManifest)) {
35895
36009
  const opened2 = openPackageDir(source);
35896
36010
  if (!opened2.validation.ok) {
35897
36011
  throw new Error(`package is not valid:
@@ -35904,7 +36018,7 @@ async function resolvePackage(source, workDir) {
35904
36018
  const target = join44(root2, app2);
35905
36019
  if (join44(source) !== target) {
35906
36020
  mkdirSync22(root2, { recursive: true });
35907
- rmSync7(target, { recursive: true, force: true });
36021
+ rmSync8(target, { recursive: true, force: true });
35908
36022
  cpSync(source, target, { recursive: true });
35909
36023
  }
35910
36024
  return {
@@ -35924,7 +36038,7 @@ async function resolvePackage(source, workDir) {
35924
36038
  const { app, appDir: appDir2 } = unpackTo(bytes2, root);
35925
36039
  const opened = openPackageDir(appDir2);
35926
36040
  if (!opened.validation.ok) {
35927
- rmSync7(workDir ? appDir2 : root, { recursive: true, force: true });
36041
+ rmSync8(workDir ? appDir2 : root, { recursive: true, force: true });
35928
36042
  throw new Error(`package is not valid:
35929
36043
  ${opened.validation.errors.join("\n ")}`);
35930
36044
  }
@@ -35963,7 +36077,7 @@ async function runPackage(source, opts = {}) {
35963
36077
  const resolved = await resolvePackage(source, opts.workDir);
35964
36078
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
35965
36079
  if (!opts.spa && assets.size === 0) {
35966
- if (resolved.temp) rmSync7(resolved.temp, { recursive: true, force: true });
36080
+ if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
35967
36081
  throw new Error(NO_SPA_MESSAGE);
35968
36082
  }
35969
36083
  const handler = makePackageRunHandler({
@@ -35993,7 +36107,7 @@ async function runPackage(source, opts = {}) {
35993
36107
  warnings: resolved.warnings,
35994
36108
  close: () => new Promise((done) => {
35995
36109
  server.close(() => {
35996
- if (resolved.temp) rmSync7(resolved.temp, { recursive: true, force: true });
36110
+ if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
35997
36111
  done();
35998
36112
  });
35999
36113
  })
@@ -36020,19 +36134,19 @@ __export(run_browser_exports, {
36020
36134
  runInBrowser: () => runInBrowser
36021
36135
  });
36022
36136
  import { createServer as createServer5 } from "node:http";
36023
- import { existsSync as existsSync44, readFileSync as readFileSync53 } from "node:fs";
36137
+ import { existsSync as existsSync45, readFileSync as readFileSync53 } from "node:fs";
36024
36138
  import { spawnSync as spawnSync3, execFile as execFile3 } from "node:child_process";
36025
- import { dirname as dirname27, resolve as resolve35 } from "node:path";
36139
+ import { dirname as dirname26, resolve as resolve36 } from "node:path";
36026
36140
  import { fileURLToPath as fileURLToPath20 } from "node:url";
36027
36141
  function stagedDir() {
36028
- return process.env.HIMI_BROWSER_PLANE_OUT ? resolve35(process.env.HIMI_BROWSER_PLANE_OUT) : resolve35(REPO, "packages", "serve", "dist", "browser-plane");
36142
+ return process.env.HIMI_BROWSER_PLANE_OUT ? resolve36(process.env.HIMI_BROWSER_PLANE_OUT) : resolve36(REPO, "packages", "serve", "dist", "browser-plane");
36029
36143
  }
36030
36144
  function missingStaged() {
36031
- return [...SERVED].filter((f) => !existsSync44(resolve35(stagedDir(), f))).sort();
36145
+ return [...SERVED].filter((f) => !existsSync45(resolve36(stagedDir(), f))).sort();
36032
36146
  }
36033
36147
  function ensureBrowserPlaneStaged() {
36034
36148
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
36035
- const r = spawnSync3(process.execPath, [resolve35(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
36149
+ const r = spawnSync3(process.execPath, [resolve36(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
36036
36150
  cwd: REPO,
36037
36151
  encoding: "utf8"
36038
36152
  });
@@ -36118,7 +36232,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
36118
36232
  }
36119
36233
  const name = path === "/" || path === "/index.html" ? "host.html" : path.slice(1);
36120
36234
  if (SERVED.has(name)) {
36121
- if (!existsSync44(resolve35(stagedDir(), name))) {
36235
+ if (!existsSync45(resolve36(stagedDir(), name))) {
36122
36236
  const restaged = ensureBrowserPlaneStaged();
36123
36237
  if (!restaged.ok) {
36124
36238
  res.writeHead(503, { "content-type": "application/json" });
@@ -36128,7 +36242,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
36128
36242
  }
36129
36243
  let bytes2;
36130
36244
  try {
36131
- bytes2 = readFileSync53(resolve35(stagedDir(), name));
36245
+ bytes2 = readFileSync53(resolve36(stagedDir(), name));
36132
36246
  } catch (e) {
36133
36247
  res.writeHead(503, { "content-type": "application/json" });
36134
36248
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
@@ -36171,8 +36285,8 @@ var HERE, REPO, SERVED;
36171
36285
  var init_run_browser = __esm({
36172
36286
  "src/run-browser.ts"() {
36173
36287
  init_file_store();
36174
- HERE = dirname27(fileURLToPath20(import.meta.url));
36175
- REPO = resolve35(HERE, "..", "..", "..");
36288
+ HERE = dirname26(fileURLToPath20(import.meta.url));
36289
+ REPO = resolve36(HERE, "..", "..", "..");
36176
36290
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
36177
36291
  }
36178
36292
  });
@@ -36546,10 +36660,10 @@ __export(preflight_exports, {
36546
36660
  parseStoreConfig: () => parseStoreConfig,
36547
36661
  requireEnv: () => requireEnv
36548
36662
  });
36549
- import { existsSync as existsSync45, readFileSync as readFileSync54 } from "node:fs";
36550
- import { isAbsolute as isAbsolute2, relative as relative6, resolve as resolve36 } from "node:path";
36663
+ import { existsSync as existsSync46, readFileSync as readFileSync54 } from "node:fs";
36664
+ import { isAbsolute as isAbsolute2, relative as relative6, resolve as resolve37 } from "node:path";
36551
36665
  function isInsideRepo(p) {
36552
- const rel = relative6(REPO_ROOT3, resolve36(p));
36666
+ const rel = relative6(REPO_ROOT3, resolve37(p));
36553
36667
  return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
36554
36668
  }
36555
36669
  function assertCredentialOutsideRepo(label2, p) {
@@ -36603,7 +36717,7 @@ function parseStoreConfig(text2) {
36603
36717
  }
36604
36718
  function loadStoreConfig(app) {
36605
36719
  const p = storeConfigPath(app);
36606
- if (!existsSync45(p)) {
36720
+ if (!existsSync46(p)) {
36607
36721
  throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
36608
36722
  }
36609
36723
  return parseStoreConfig(readFileSync54(p, "utf8"));
@@ -36629,7 +36743,7 @@ __export(preflight_app_exports, {
36629
36743
  pngSize: () => pngSize,
36630
36744
  preflightApp: () => preflightApp
36631
36745
  });
36632
- import { readFileSync as readFileSync55, existsSync as existsSync46, readdirSync as readdirSync22, statSync as statSync11 } from "node:fs";
36746
+ import { readFileSync as readFileSync55, existsSync as existsSync47, readdirSync as readdirSync22, statSync as statSync11 } from "node:fs";
36633
36747
  import { createHash as createHash23 } from "node:crypto";
36634
36748
  import { join as join45 } from "node:path";
36635
36749
  function analyze(projectYml, storeConfig, icon) {
@@ -36679,8 +36793,8 @@ function analyze(projectYml, storeConfig, icon) {
36679
36793
  return f;
36680
36794
  }
36681
36795
  async function preflightApp(app) {
36682
- const projectYml = existsSync46(iosProjectYml(app)) ? readFileSync55(iosProjectYml(app), "utf8") : "";
36683
- const storeConfig = existsSync46(storeConfigPath(app)) ? readFileSync55(storeConfigPath(app), "utf8") : "";
36796
+ const projectYml = existsSync47(iosProjectYml(app)) ? readFileSync55(iosProjectYml(app), "utf8") : "";
36797
+ const storeConfig = existsSync47(storeConfigPath(app)) ? readFileSync55(storeConfigPath(app), "utf8") : "";
36684
36798
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
36685
36799
  const findings = analyze(projectYml, storeConfig, await appIconState(join45(appDir(app), "ios")));
36686
36800
  findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
@@ -36711,15 +36825,15 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
36711
36825
  function appLevelMetadataFiles(app, locale = "en-US") {
36712
36826
  const root = join45(storeDir(app), "metadata");
36713
36827
  const out = /* @__PURE__ */ new Set();
36714
- if (existsSync46(root)) {
36828
+ if (existsSync47(root)) {
36715
36829
  for (const n of readdirSync22(root)) if (n.endsWith(".txt")) out.add(n);
36716
36830
  }
36717
- if (existsSync46(join45(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
36831
+ if (existsSync47(join45(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
36718
36832
  return out;
36719
36833
  }
36720
36834
  function reviewInfoFiles(app) {
36721
36835
  const dir = join45(storeDir(app), "review_information");
36722
- if (!existsSync46(dir)) return /* @__PURE__ */ new Set();
36836
+ if (!existsSync47(dir)) return /* @__PURE__ */ new Set();
36723
36837
  return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
36724
36838
  }
36725
36839
  function isValidAppStoreSize(w, h) {
@@ -36866,20 +36980,20 @@ function analyzeListing(metaFiles, shots) {
36866
36980
  }
36867
36981
  function metadataFilesPresent(app, locale = "en-US") {
36868
36982
  const dir = join45(storeDir(app), "metadata", locale);
36869
- if (!existsSync46(dir)) return /* @__PURE__ */ new Set();
36983
+ if (!existsSync47(dir)) return /* @__PURE__ */ new Set();
36870
36984
  return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
36871
36985
  }
36872
36986
  function listScreenshots(app, locale = "en-US") {
36873
36987
  const out = [];
36874
36988
  const flat = join45(storeDir(app), "screenshots", locale);
36875
- if (existsSync46(flat)) {
36989
+ if (existsSync47(flat)) {
36876
36990
  for (const png of readdirSync22(flat).filter((n) => n.endsWith(".png"))) {
36877
36991
  const sz = pngSize(readFileSync55(join45(flat, png)));
36878
36992
  if (sz) out.push({ name: png, w: sz.w, h: sz.h });
36879
36993
  }
36880
36994
  }
36881
36995
  const legacy = join45(storeDir(app), "metadata", locale, "screenshots");
36882
- if (existsSync46(legacy)) {
36996
+ if (existsSync47(legacy)) {
36883
36997
  for (const deviceDir of readdirSync22(legacy)) {
36884
36998
  const d = join45(legacy, deviceDir);
36885
36999
  if (!statSync11(d).isDirectory()) continue;
@@ -36893,7 +37007,7 @@ function listScreenshots(app, locale = "en-US") {
36893
37007
  }
36894
37008
  function placeholderHashes2() {
36895
37009
  const templateIos = join45(appDir("_template"), "ios");
36896
- if (!existsSync46(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
37010
+ if (!existsSync47(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
36897
37011
  for (const target of readdirSync22(templateIos)) {
36898
37012
  const p = join45(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
36899
37013
  try {
@@ -36929,7 +37043,7 @@ async function pixelIssues(bytes2) {
36929
37043
  }
36930
37044
  }
36931
37045
  async function appIconState(iosDir) {
36932
- if (!existsSync46(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
37046
+ if (!existsSync47(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
36933
37047
  for (const target of readdirSync22(iosDir)) {
36934
37048
  const p = join45(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
36935
37049
  try {
@@ -37004,7 +37118,7 @@ __export(credential_profile_exports, {
37004
37118
  profilePath: () => profilePath,
37005
37119
  resolveStoreCredentials: () => resolveStoreCredentials
37006
37120
  });
37007
- import { existsSync as existsSync47, readFileSync as readFileSync56 } from "node:fs";
37121
+ import { existsSync as existsSync48, readFileSync as readFileSync56 } from "node:fs";
37008
37122
  import { homedir as homedir6 } from "node:os";
37009
37123
  import { join as join46 } from "node:path";
37010
37124
  function credentialsDir(home = homedir6()) {
@@ -37039,7 +37153,7 @@ function resolveStoreCredentials(opts) {
37039
37153
  const env = opts.env ?? process.env;
37040
37154
  const home = opts.home ?? homedir6();
37041
37155
  const read = opts.readProfile ?? ((p) => readFileSync56(p, "utf8"));
37042
- const exists = opts.profileExists ?? existsSync47;
37156
+ const exists = opts.profileExists ?? existsSync48;
37043
37157
  const ios = cfg.ios ?? {};
37044
37158
  const flagName = opts.profileFlag?.trim();
37045
37159
  const named = flagName || ios.credentialProfile?.trim();
@@ -40331,10 +40445,10 @@ function isFetchableFontUrl(raw) {
40331
40445
  return true;
40332
40446
  }
40333
40447
  function resolveAll(hostname) {
40334
- return new Promise((resolve40, reject) => {
40448
+ return new Promise((resolve41, reject) => {
40335
40449
  dnsLookup(hostname, { all: true, verbatim: true }, (err, addresses) => {
40336
40450
  if (err) reject(err);
40337
- else resolve40(addresses);
40451
+ else resolve41(addresses);
40338
40452
  });
40339
40453
  });
40340
40454
  }
@@ -40342,13 +40456,13 @@ function withAbort(start, signal, what) {
40342
40456
  if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
40343
40457
  const work = start();
40344
40458
  if (!signal) return work;
40345
- return new Promise((resolve40, reject) => {
40459
+ return new Promise((resolve41, reject) => {
40346
40460
  const onAbort = () => reject(new Error(`${what} aborted`));
40347
40461
  signal.addEventListener("abort", onAbort, { once: true });
40348
- work.then(resolve40, reject).finally(() => signal.removeEventListener("abort", onAbort));
40462
+ work.then(resolve41, reject).finally(() => signal.removeEventListener("abort", onAbort));
40349
40463
  });
40350
40464
  }
40351
- async function pinAddress(url, resolve40 = resolveAll, signal) {
40465
+ async function pinAddress(url, resolve41 = resolveAll, signal) {
40352
40466
  const host = url.hostname.replace(/^\[|\]$/g, "");
40353
40467
  if (ipv4Octets(host)) {
40354
40468
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
@@ -40358,7 +40472,7 @@ async function pinAddress(url, resolve40 = resolveAll, signal) {
40358
40472
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
40359
40473
  return { address: host, family: 6 };
40360
40474
  }
40361
- const addresses = await withAbort(() => resolve40(host), signal, `${host} lookup`);
40475
+ const addresses = await withAbort(() => resolve41(host), signal, `${host} lookup`);
40362
40476
  if (!addresses.length) throw new Error(`${host} resolved to no address`);
40363
40477
  const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
40364
40478
  if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
@@ -40381,7 +40495,7 @@ function decodedBody(res, hasBody) {
40381
40495
  return out;
40382
40496
  }
40383
40497
  function requestOnce(url, pinned, init) {
40384
- return new Promise((resolve40, reject) => {
40498
+ return new Promise((resolve41, reject) => {
40385
40499
  const headers2 = { host: url.host, "accept-encoding": "identity" };
40386
40500
  new Headers(init.headers ?? {}).forEach((value, key2) => {
40387
40501
  if (key2.toLowerCase() !== "host") headers2[key2] = value;
@@ -40415,7 +40529,7 @@ function requestOnce(url, pinned, init) {
40415
40529
  reject(err);
40416
40530
  return;
40417
40531
  }
40418
- resolve40(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out }));
40532
+ resolve41(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out }));
40419
40533
  }
40420
40534
  );
40421
40535
  req.on("error", reject);
@@ -41015,15 +41129,15 @@ var init_home_descriptor = __esm({
41015
41129
  });
41016
41130
 
41017
41131
  // src/site-analyze/apply.ts
41018
- import { existsSync as existsSync48, readFileSync as readFileSync60, writeFileSync as writeFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync24, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
41019
- import { dirname as dirname28, isAbsolute as isAbsolute3, join as join48, resolve as resolve37, sep as sep10 } from "node:path";
41132
+ import { existsSync as existsSync49, readFileSync as readFileSync60, writeFileSync as writeFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync24, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
41133
+ import { dirname as dirname27, isAbsolute as isAbsolute3, join as join48, resolve as resolve38, sep as sep10 } from "node:path";
41020
41134
  import { spawnSync as spawnSync4 } from "node:child_process";
41021
41135
  function unpairedRedirectNote(overlay) {
41022
41136
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
41023
41137
  return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
41024
41138
  }
41025
41139
  function posix2(p) {
41026
- return resolve37(p).replace(/\\/g, "/");
41140
+ return resolve38(p).replace(/\\/g, "/");
41027
41141
  }
41028
41142
  function committedShellProvisioning(path) {
41029
41143
  return committedShellFor(posix2(path));
@@ -41031,8 +41145,8 @@ function committedShellProvisioning(path) {
41031
41145
  function findRepoRoot(cwd) {
41032
41146
  let dir = cwd;
41033
41147
  for (let i = 0; i < 8; i++) {
41034
- if (SHELL_NAMES2.some((name) => existsSync48(join48(dir, shellAppDir(name), "package.json")))) return dir;
41035
- const next = dirname28(dir);
41148
+ if (SHELL_NAMES2.some((name) => existsSync49(join48(dir, shellAppDir(name), "package.json")))) return dir;
41149
+ const next = dirname27(dir);
41036
41150
  if (next === dir) break;
41037
41151
  dir = next;
41038
41152
  }
@@ -41057,7 +41171,7 @@ function assertNotCommitted(path, forbidden) {
41057
41171
  `refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
41058
41172
  );
41059
41173
  }
41060
- if (forbidden && resolve37(path) === resolve37(forbidden)) {
41174
+ if (forbidden && resolve38(path) === resolve38(forbidden)) {
41061
41175
  const named = committedShellProvisioning(forbidden);
41062
41176
  throw new Error(
41063
41177
  `refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
@@ -41100,7 +41214,7 @@ function mergeCustomerOwned(committed, overlay) {
41100
41214
  function buildMergedContract(options) {
41101
41215
  const { appDir: appDir2, packageDir, overlay } = options;
41102
41216
  const committedPath = join48(appDir2, "provisioning.json");
41103
- if (!existsSync48(committedPath)) {
41217
+ if (!existsSync49(committedPath)) {
41104
41218
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
41105
41219
  }
41106
41220
  const committed = JSON.parse(readFileSync60(committedPath, "utf8"));
@@ -41110,13 +41224,13 @@ function buildMergedContract(options) {
41110
41224
  const staged = [];
41111
41225
  const contained = (root, rel) => {
41112
41226
  if (isAbsolute3(rel)) return void 0;
41113
- const full = resolve37(root, rel);
41114
- return full.startsWith(resolve37(root) + sep10) ? full : void 0;
41227
+ const full = resolve38(root, rel);
41228
+ return full.startsWith(resolve38(root) + sep10) ? full : void 0;
41115
41229
  };
41116
41230
  const stage = (fromRel, toRel) => {
41117
41231
  const from = contained(packageDir, fromRel);
41118
41232
  const to = contained(join48(appDir2, STAGED), toRel.slice(STAGED.length + 1));
41119
- if (!from || !to || !existsSync48(from)) return void 0;
41233
+ if (!from || !to || !existsSync49(from)) return void 0;
41120
41234
  let real;
41121
41235
  let realRoot;
41122
41236
  try {
@@ -41128,7 +41242,7 @@ function buildMergedContract(options) {
41128
41242
  if (!real.startsWith(realRoot + sep10)) return void 0;
41129
41243
  try {
41130
41244
  if (!statSync12(real).isFile()) return void 0;
41131
- mkdirSync24(dirname28(to), { recursive: true });
41245
+ mkdirSync24(dirname27(to), { recursive: true });
41132
41246
  copyFileSync3(real, to);
41133
41247
  } catch {
41134
41248
  return void 0;
@@ -41139,7 +41253,7 @@ function buildMergedContract(options) {
41139
41253
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
41140
41254
  if (icon) branding.appIconPath = icon;
41141
41255
  const facesPath = join48(packageDir, "media/fonts/faces.json");
41142
- if (existsSync48(facesPath)) {
41256
+ if (existsSync49(facesPath)) {
41143
41257
  let faces = [];
41144
41258
  try {
41145
41259
  const parsed = JSON.parse(readFileSync60(facesPath, "utf8"));
@@ -41166,13 +41280,13 @@ function buildMergedContract(options) {
41166
41280
  const path = join48(packageDir, "provisioning.contract.json");
41167
41281
  writeFileSync21(path, body);
41168
41282
  const localPath = join48(appDir2, LOCAL_CONTRACT_REL);
41169
- mkdirSync24(dirname28(localPath), { recursive: true });
41283
+ mkdirSync24(dirname27(localPath), { recursive: true });
41170
41284
  writeFileSync21(localPath, body);
41171
41285
  staged.push(localPath);
41172
41286
  return { path, staged };
41173
41287
  }
41174
41288
  async function applyOverlays(input) {
41175
- const cwd = resolve37(input.cwd);
41289
+ const cwd = resolve38(input.cwd);
41176
41290
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
41177
41291
  assertKnownShell(shell);
41178
41292
  const overlay = JSON.parse(readFileSync60(input.overlayPath, "utf8"));
@@ -41187,7 +41301,7 @@ async function applyOverlays(input) {
41187
41301
  );
41188
41302
  }
41189
41303
  const appDir2 = join48(repoRoot2, shellAppDir(shell));
41190
- const packageDir = dirname28(resolve37(input.overlayPath));
41304
+ const packageDir = dirname27(resolve38(input.overlayPath));
41191
41305
  const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
41192
41306
  wrote.push(...staged);
41193
41307
  const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -41210,7 +41324,7 @@ async function applyOverlays(input) {
41210
41324
  }
41211
41325
  const pkgProv = join48(cwd, "provisioning.json");
41212
41326
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
41213
- if (existsSync48(pkgProv)) {
41327
+ if (existsSync49(pkgProv)) {
41214
41328
  const cur = JSON.parse(readFileSync60(pkgProv, "utf8"));
41215
41329
  const merged = deepMerge3(cur, overlay);
41216
41330
  writeFileSync21(pkgProv, JSON.stringify(merged, null, 2) + "\n");
@@ -41220,7 +41334,7 @@ async function applyOverlays(input) {
41220
41334
  wrote.push(pkgProv);
41221
41335
  }
41222
41336
  const pkgTokens = join48(cwd, "tokens.json");
41223
- if (existsSync48(pkgTokens) && (tokens.colors || tokens.typography)) {
41337
+ if (existsSync49(pkgTokens) && (tokens.colors || tokens.typography)) {
41224
41338
  const cur = JSON.parse(readFileSync60(pkgTokens, "utf8"));
41225
41339
  const merged = deepMerge3(cur, tokens);
41226
41340
  writeFileSync21(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
@@ -41228,7 +41342,7 @@ async function applyOverlays(input) {
41228
41342
  }
41229
41343
  const homeAction = homeRefreshActionId(shell);
41230
41344
  const homeSrc = join48(cwd, "dev/index.ts");
41231
- if (homeAction && existsSync48(homeSrc)) {
41345
+ if (homeAction && existsSync49(homeSrc)) {
41232
41346
  const prev = readFileSync60(homeSrc, "utf8");
41233
41347
  const patched = patchBrandParams(prev, overlay, homeAction);
41234
41348
  let next = patched.src;
@@ -41249,13 +41363,13 @@ async function applyOverlays(input) {
41249
41363
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
41250
41364
  }
41251
41365
  }
41252
- if (!input.iconPath || !existsSync48(input.iconPath)) {
41253
- const book = input.iconPath ? dirname28(dirname28(resolve37(input.iconPath))) : void 0;
41366
+ if (!input.iconPath || !existsSync49(input.iconPath)) {
41367
+ const book = input.iconPath ? dirname27(dirname27(resolve38(input.iconPath))) : void 0;
41254
41368
  notes.push(
41255
41369
  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"
41256
41370
  );
41257
41371
  }
41258
- if (input.iconPath && existsSync48(input.iconPath)) {
41372
+ if (input.iconPath && existsSync49(input.iconPath)) {
41259
41373
  try {
41260
41374
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
41261
41375
  wrote.push(...installed.wrote);
@@ -42390,12 +42504,12 @@ __export(cli_exports, {
42390
42504
  runSiteFunctionCli: () => runSiteFunctionCli
42391
42505
  });
42392
42506
  import { readFileSync as readFileSync61 } from "node:fs";
42393
- import { resolve as resolve38 } from "node:path";
42507
+ import { resolve as resolve39 } from "node:path";
42394
42508
  async function runSiteAnalyze(opts) {
42395
42509
  const fetchImpl = opts.fetchImpl ?? fetch;
42396
42510
  const assetFetch = opts.fetchImpl ?? pinnedFetch2;
42397
42511
  const cwd = opts.cwd ?? process.cwd();
42398
- const outDir = resolve38(cwd, opts.outDir ?? ".himi/business-book");
42512
+ const outDir = resolve39(cwd, opts.outDir ?? ".himi/business-book");
42399
42513
  let ownerAuth;
42400
42514
  let msid;
42401
42515
  try {
@@ -42432,9 +42546,9 @@ async function runSiteAnalyze(opts) {
42432
42546
  if (opts.apply) {
42433
42547
  applied = await applyOverlays({
42434
42548
  cwd,
42435
- overlayPath: resolve38(outDir, "provisioning.overlay.json"),
42436
- tokensPath: resolve38(outDir, "tokens.overlay.json"),
42437
- iconPath: resolve38(outDir, "media/icon.png"),
42549
+ overlayPath: resolve39(outDir, "provisioning.overlay.json"),
42550
+ tokensPath: resolve39(outDir, "tokens.overlay.json"),
42551
+ iconPath: resolve39(outDir, "media/icon.png"),
42438
42552
  shell: opts.shell
42439
42553
  });
42440
42554
  const note = noteWithWarnings(applied.note, warnings);
@@ -42470,7 +42584,7 @@ async function runSiteFunctionCli(opts) {
42470
42584
  const token = opts.token ?? await siteToken(msid);
42471
42585
  let source;
42472
42586
  if (opts.sourcePath) {
42473
- const p = resolve38(opts.cwd ?? process.cwd(), opts.sourcePath);
42587
+ const p = resolve39(opts.cwd ?? process.cwd(), opts.sourcePath);
42474
42588
  source = readFileSync61(p, "utf8");
42475
42589
  }
42476
42590
  let body;
@@ -42522,7 +42636,7 @@ async function accountToken2(spawnImpl = spawn4) {
42522
42636
  cached2 = fromEnv;
42523
42637
  return fromEnv;
42524
42638
  }
42525
- const token = await new Promise((resolve40, reject) => {
42639
+ const token = await new Promise((resolve41, reject) => {
42526
42640
  let child;
42527
42641
  try {
42528
42642
  child = spawnImpl("wix", ["token"]);
@@ -42551,7 +42665,7 @@ async function accountToken2(spawnImpl = spawn4) {
42551
42665
  const scan = (d) => {
42552
42666
  out += String(d);
42553
42667
  const m = out.match(TOKEN_RE2);
42554
- if (m) done(() => resolve40(m[0]));
42668
+ if (m) done(() => resolve41(m[0]));
42555
42669
  };
42556
42670
  child.stdout?.on("data", scan);
42557
42671
  child.stderr?.on("data", scan);
@@ -42728,7 +42842,7 @@ __export(site_create_exports, {
42728
42842
  runSiteList: () => runSiteList,
42729
42843
  writeProvisioningBinding: () => writeProvisioningBinding
42730
42844
  });
42731
- import { existsSync as existsSync49, readFileSync as readFileSync62, writeFileSync as writeFileSync22 } from "node:fs";
42845
+ import { existsSync as existsSync50, readFileSync as readFileSync62, writeFileSync as writeFileSync22 } from "node:fs";
42732
42846
  import { resolve as resolvePath2 } from "node:path";
42733
42847
  function oauthClientName(projectName) {
42734
42848
  return `${projectName} client`;
@@ -42877,7 +42991,7 @@ async function runSiteCreate(opts) {
42877
42991
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
42878
42992
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
42879
42993
  }
42880
- function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync49, readFileSync: readFileSync62, writeFileSync: writeFileSync22 }) {
42994
+ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync50, readFileSync: readFileSync62, writeFileSync: writeFileSync22 }) {
42881
42995
  const msid = binding2.siteId;
42882
42996
  const path = resolvePath2(target);
42883
42997
  const committed = committedShellProvisioning(path);
@@ -43211,11 +43325,11 @@ var init_site_oauth_client = __esm({
43211
43325
  });
43212
43326
 
43213
43327
  // src/cli.ts
43214
- import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync63, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync50, rmSync as rmSync8, readdirSync as readdirSync23, statSync as statSync13 } from "node:fs";
43328
+ import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync63, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync51, rmSync as rmSync9, readdirSync as readdirSync23, statSync as statSync13 } from "node:fs";
43215
43329
  import { execFileSync as execFileSync6 } from "node:child_process";
43216
43330
  import { createHash as createHash24 } from "node:crypto";
43217
43331
  import { tmpdir as tmpdir5 } from "node:os";
43218
- import { join as join49, resolve as resolve39, basename as basename8, dirname as dirname29 } from "node:path";
43332
+ import { join as join49, resolve as resolve40, basename as basename8, dirname as dirname28 } from "node:path";
43219
43333
  import { fileURLToPath as fileURLToPath21 } from "node:url";
43220
43334
 
43221
43335
  // ../serve-cli/src/client.ts
@@ -44724,7 +44838,7 @@ async function browserLogin(opts) {
44724
44838
  const log = opts.log ?? (() => {
44725
44839
  });
44726
44840
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
44727
- return await new Promise((resolve40, reject) => {
44841
+ return await new Promise((resolve41, reject) => {
44728
44842
  let settled = false;
44729
44843
  let loginUrl = "";
44730
44844
  const server = createServer();
@@ -44788,7 +44902,7 @@ async function browserLogin(opts) {
44788
44902
  return;
44789
44903
  }
44790
44904
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
44791
- finish2(() => resolve40({ token, loginUrl }));
44905
+ finish2(() => resolve41({ token, loginUrl }));
44792
44906
  });
44793
44907
  });
44794
44908
  server.on("error", (err) => finish2(() => reject(err)));
@@ -46512,7 +46626,7 @@ function writeAgentContext(targetDir) {
46512
46626
  // src/cli.ts
46513
46627
  init_wix_placeholders();
46514
46628
  var defaultIO = { log: (l) => console.log(l), error: (l) => console.error(l), isTTY: process.stdout.isTTY === true };
46515
- var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["browser", "no-open", "yes", "json", "deep", "quiet", "force", "watch", "no-claim", "new"]);
46629
+ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["browser", "no-open", "yes", "json", "deep", "quiet", "force", "replace", "watch", "no-claim", "new"]);
46516
46630
  var SHELL_ENUM = SHELL_NAMES2.join("|");
46517
46631
  function parseFlags(argv) {
46518
46632
  const _ = [];
@@ -46701,7 +46815,7 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
46701
46815
  Never archives .himi/, .env*, node_modules/, dist/ or key
46702
46816
  material, and REFUSES the push if a file it would archive
46703
46817
  looks like it holds a credential.
46704
- himi pull <app> [--release <id>] [--out <dir>] [--name <new>] [--force] [--target <t>]
46818
+ himi pull <app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]
46705
46819
  restore an app's SOURCE from the serve plane into an editable
46706
46820
  content package \u2014 the other half of push, which archives it.
46707
46821
  Owner or editor only: a viewer may download the running app,
@@ -46709,6 +46823,14 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
46709
46823
  retention window prune() keeps (current + newest ~20).
46710
46824
  --name re-substitutes the app identity, so the restored tree is
46711
46825
  a NEW app rather than a second copy of the same one.
46826
+ A non-empty destination is refused unless you say which you mean:
46827
+ --force MERGES \u2014 it keeps files the release does not have and
46828
+ NAMES them (left: [...]), so a hybrid tree is never silent.
46829
+ --replace restores exactly what was archived: it removes those
46830
+ files first (removed: [...]) and implies --force. It refuses
46831
+ a directory with no himalaya.content.json, and can only remove
46832
+ what a push would have archived \u2014 .git/, node_modules/, dist/,
46833
+ .env* and key material are never touched.
46712
46834
  himi pack [--content <dir>] [--out <file|dir>] [--format zip|dir] [--name <title>] [--snapshot]
46713
46835
  write the app as a PORTABLE .himi package \u2014 one self-contained
46714
46836
  file (screens, T5 bundles, tokens, assets, app-config) you can
@@ -46956,7 +47078,7 @@ var COMMANDS = [
46956
47078
  { name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
46957
47079
  { name: "push", summary: "lint + build + publish a release (default --draft: servable via ?release= but NOT live). REFUSES to publish on any error unless --force; --strict promotes warnings. Prints preview + agent-context links. The published slug is NAMESPACED per owner \u2014 `<ownerPrefix>.<name>`, composed offline from the control token's ownerPrefix claim, so the CLI and the server derive the identical string and himalaya.content.json is NOT rewritten (a legacy token with no ownerPrefix publishes the declared name unchanged). An app claimed BEFORE namespacing is stored under its FLAT slug, so the claim route answers `alreadyYours` naming that slug and the push adopts it \u2014 reported as `adoptedSlug`, since it is the one case where the published `app` differs from what the declared name composes to. `--no-claim` skips the route that knows this, so a pre-namespacing app pushed with it still fails 403. --visibility public|unlisted decides whether /v1/apps + the Himi Player picker LIST the app (also declarable as `visibility` in himalaya.content.json; omitted, a brand-new app defaults to unlisted \u2014 share by link \u2014 and an existing setting is kept). --account-id names which account owns the app when your Wix session resolves to several (the auto-claim of a brand-new slug cannot guess \u2014 without it a multi-account caller is told to name one).", required: "[--content <dir>] [--draft] [--force] [--strict] [--label] [--notes] [--visibility public|unlisted] [--no-claim] [--account-id <id>] (--control-token)" },
46958
47080
  { name: "pack", summary: "write the app as a PORTABLE .himi package \u2014 one self-contained file holding every screen, Tier-5 bundle, token, asset and the app-config. Packages are live by default: they boot bundled content offline, then Himi Player follows its baked-in production ring. `--snapshot` makes a frozen reproducible artifact. Package-supplied origins are never trusted. --format dir writes the same tree unpacked, for static hosting. --release-dir packs a release that is already built on disk (needs --app) instead of rebuilding from source.", required: "[--content <dir>] [--out <file|dir>] [--format zip|dir] [--name <title>] [--snapshot] [--strict] [--force] | --release-dir <dir> --app <a>" },
46959
- { name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force] [--target <t>]" },
47081
+ { name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone. A NON-EMPTY destination is refused unless you say which you mean: `--force` merges and reports \u2014 it writes the archive over what is there, keeps files the release does not carry, and NAMES every one of them as `left: [...]` so a tree that matches no release is never silent (#2437); `--replace` restores exactly what was archived, removing those files first (`removed: [...]`) and implying `--force`. `--replace` refuses a directory holding no `himalaya.content.json`, so a mistyped `--out` cannot clear an unrelated tree, and the only paths it can remove are the ones a push would have archived \u2014 `.git/`, `node_modules/`, `dist/`, `.env*` and key material are out of its reach by construction.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]" },
46960
47082
  { name: "share", summary: "publish or revoke a content-addressed `.himi` share link. The package must be a validated archive for an already-published release; the resulting https URL is safe to QR, copy, or open in Himi Player.", required: "--file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>" },
46961
47083
  { name: "run", summary: "serve a .himi package on localhost and open it in a browser \u2014 no serve plane, no dev-server, no setup. Given no argument it builds the current content package first, so `himi run` is the inner loop: edit, run, look at it. The SPA and /v1 are served from ONE origin because Tier-5 bundle fetches on web are same-origin-only. --chrome preview frames the app in a device chassis; --chrome app serves it as a plain web app. Blocks until Ctrl-C, like any dev server. --browser runs the whole plane INSIDE the tab (service worker + in-memory store) so no app code executes in this process or on any pod.", required: "[<package.himi|dir|url>] [--browser] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
46962
47084
  { name: "preview", summary: "print the shareable web URL + himi:// deep link + agent /v1/preview JSON URLs for an app+release; --surface frames the web preview as any catalog surface (?surface=)", required: "--app --release [--screen] [--surface]" },
@@ -47010,11 +47132,11 @@ function packageVersion(path) {
47010
47132
  }
47011
47133
  }
47012
47134
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
47013
- let dir = resolve39(fromDir);
47135
+ let dir = resolve40(fromDir);
47014
47136
  for (; ; ) {
47015
47137
  const version = packageVersion(join49(dir, "node_modules", "@wix", "himalaya", "package.json"));
47016
47138
  if (version) return { version, source: "local" };
47017
- const parent = dirname29(dir);
47139
+ const parent = dirname28(dir);
47018
47140
  if (parent === dir) break;
47019
47141
  dir = parent;
47020
47142
  }
@@ -47383,7 +47505,7 @@ async function nativeConfigAdvisories(app, configSource) {
47383
47505
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
47384
47506
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
47385
47507
  const iosYmlPath = iosProjectYml2(app);
47386
- const iosYml = existsSync50(iosYmlPath) ? readFileSync63(iosYmlPath, "utf8") : "";
47508
+ const iosYml = existsSync51(iosYmlPath) ? readFileSync63(iosYmlPath, "utf8") : "";
47387
47509
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
47388
47510
  if (!optedIn) {
47389
47511
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -47403,13 +47525,13 @@ function readConfigSource(dir) {
47403
47525
  }
47404
47526
  }
47405
47527
  function writePngFile(path, base64) {
47406
- mkdirSync25(dirname29(path), { recursive: true });
47528
+ mkdirSync25(dirname28(path), { recursive: true });
47407
47529
  writeFileSync23(path, Buffer.from(base64, "base64"));
47408
47530
  return path;
47409
47531
  }
47410
47532
  async function initFromRemoteTemplate(name, parentDir, template, c) {
47411
- const dir = resolve39(parentDir, name);
47412
- if (existsSync50(join49(dir, "himalaya.content.json"))) {
47533
+ const dir = resolve40(parentDir, name);
47534
+ if (existsSync51(join49(dir, "himalaya.content.json"))) {
47413
47535
  throw new Error(`content package already exists at ${dir}`);
47414
47536
  }
47415
47537
  const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -47421,13 +47543,13 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
47421
47543
  return finishScaffold(materializeSource(archive.files, name, dir), template);
47422
47544
  }
47423
47545
  function contentDir(flags) {
47424
- return resolve39(str5(flags.content) ?? process.cwd());
47546
+ return resolve40(str5(flags.content) ?? process.cwd());
47425
47547
  }
47426
47548
  function isHimalayaMonorepoCheckout(start) {
47427
- let dir = resolve39(start);
47549
+ let dir = resolve40(start);
47428
47550
  for (; ; ) {
47429
- if (existsSync50(join49(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync50(join49(dir, "core", "serve", "src", "server.ts"))) return true;
47430
- const parent = dirname29(dir);
47551
+ if (existsSync51(join49(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync51(join49(dir, "core", "serve", "src", "server.ts"))) return true;
47552
+ const parent = dirname28(dir);
47431
47553
  if (parent === dir) return false;
47432
47554
  dir = parent;
47433
47555
  }
@@ -47456,9 +47578,9 @@ function materializeForPreview(appDir2, slug, displayName) {
47456
47578
  const forBuild = Object.fromEntries(
47457
47579
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
47458
47580
  );
47459
- const repoRoot2 = resolve39(fileURLToPath21(new URL("../../..", import.meta.url)));
47581
+ const repoRoot2 = resolve40(fileURLToPath21(new URL("../../..", import.meta.url)));
47460
47582
  const dest = join49(repoRoot2, "node_modules", ".cache", "himi-template-preview", slug);
47461
- rmSync8(dest, { recursive: true, force: true });
47583
+ rmSync9(dest, { recursive: true, force: true });
47462
47584
  mkdirSync25(dest, { recursive: true });
47463
47585
  materializeSource(forBuild, displayName, dest, slug);
47464
47586
  return dest;
@@ -47676,7 +47798,7 @@ Seed your coding agent with \`himi agent-init\`. Portal: ${idx.portalUrl}`);
47676
47798
  return 0;
47677
47799
  }
47678
47800
  case "agent-init": {
47679
- const dir = resolve39(str5(flags.dir) ?? process.cwd());
47801
+ const dir = resolve40(str5(flags.dir) ?? process.cwd());
47680
47802
  const res = writeAgentContext(dir);
47681
47803
  print({ ok: true, dir: res.dir, files: res.files, portalUrl: idx.portalUrl });
47682
47804
  return 0;
@@ -47782,7 +47904,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
47782
47904
  return 2;
47783
47905
  }
47784
47906
  const template = str5(flags.template);
47785
- const parentDir = resolve39(str5(flags.dir) ?? process.cwd());
47907
+ const parentDir = resolve40(str5(flags.dir) ?? process.cwd());
47786
47908
  if (template && flags.remote === true) {
47787
47909
  try {
47788
47910
  const res2 = await initFromRemoteTemplate(name, parentDir, template, client3());
@@ -47873,8 +47995,8 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
47873
47995
  return 0;
47874
47996
  }
47875
47997
  if (sub === "publish") {
47876
- const appDir2 = resolve39(str5(flags.dir) ?? process.cwd());
47877
- const sourceDir = resolve39(str5(flags["source-dir"]) ?? appDir2);
47998
+ const appDir2 = resolve40(str5(flags.dir) ?? process.cwd());
47999
+ const sourceDir = resolve40(str5(flags["source-dir"]) ?? appDir2);
47878
48000
  let meta;
47879
48001
  try {
47880
48002
  meta = JSON.parse(readFileSync63(join49(sourceDir, TEMPLATE_META_FILE), "utf8"));
@@ -47928,7 +48050,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
47928
48050
  }));
47929
48051
  return 1;
47930
48052
  }
47931
- const iconPath = str5(flags.icon) ? resolve39(str5(flags.icon)) : templateIconPath(name);
48053
+ const iconPath = str5(flags.icon) ? resolve40(str5(flags.icon)) : templateIconPath(name);
47932
48054
  let iconHash;
47933
48055
  if (iconPath) {
47934
48056
  try {
@@ -48246,7 +48368,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
48246
48368
  case "test": {
48247
48369
  const dir = contentDir(flags);
48248
48370
  const structuredOutput = flags.json === true || io.isTTY !== true;
48249
- if (existsSync50(join49(dir, "functions"))) {
48371
+ if (existsSync51(join49(dir, "functions"))) {
48250
48372
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
48251
48373
  const loaded = await loadFunctionsApp2(dir);
48252
48374
  const results = [];
@@ -48545,7 +48667,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
48545
48667
  renderDescriptorWeb: renderDescriptorWeb2,
48546
48668
  renderPngBatch: renderPngBatch2,
48547
48669
  writePng: (path, base64) => writePngFile(path, base64),
48548
- clearDir: (d) => rmSync8(d, { recursive: true, force: true })
48670
+ clearDir: (d) => rmSync9(d, { recursive: true, force: true })
48549
48671
  }
48550
48672
  });
48551
48673
  writtenShots = sp.written;
@@ -49034,8 +49156,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49034
49156
  return 2;
49035
49157
  }
49036
49158
  const renamed = str5(flags.name);
49037
- const dest = resolve39(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
49038
- if (existsSync50(dest)) {
49159
+ const dest = resolve40(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
49160
+ const replace = flags.replace === true;
49161
+ const force = replace || flags.force === true;
49162
+ if (existsSync51(dest)) {
49039
49163
  if (!statSync13(dest).isDirectory()) {
49040
49164
  io.error(JSON.stringify({
49041
49165
  error: `${dest} exists and is not a directory`,
@@ -49043,8 +49167,16 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49043
49167
  }));
49044
49168
  return 1;
49045
49169
  }
49046
- if (readdirSync23(dest).length > 0 && flags.force !== true) {
49047
- io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway, or --out/--name to land somewhere else" }));
49170
+ const occupied = readdirSync23(dest).length > 0;
49171
+ if (occupied && !force) {
49172
+ io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
49173
+ return 1;
49174
+ }
49175
+ if (replace && occupied && !existsSync51(join49(dest, "himalaya.content.json"))) {
49176
+ io.error(JSON.stringify({
49177
+ error: `${dest} is not a content package \u2014 refusing to --replace it`,
49178
+ hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
49179
+ }));
49048
49180
  return 1;
49049
49181
  }
49050
49182
  }
@@ -49053,7 +49185,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49053
49185
  io.error(JSON.stringify({ ok: false, app: wanted, status: pulled.status, ...pulled.json ?? {} }));
49054
49186
  return 1;
49055
49187
  }
49056
- const { readAppSource: readAppSource2, writeAppSource: writeAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
49188
+ const { readAppSource: readAppSource2, writeAppSource: writeAppSource2, staleSourcePaths: staleSourcePaths2, removeStaleSource: removeStaleSource2, deniedArchivePaths: deniedArchivePaths2, writeConflicts: writeConflicts2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
49057
49189
  let restored;
49058
49190
  try {
49059
49191
  restored = readAppSource2(pulled.bytes);
@@ -49080,6 +49212,31 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49080
49212
  if (body !== void 0) entry.bytes = Buffer.from(substituteIdentity(body, renamed), "utf8");
49081
49213
  }
49082
49214
  }
49215
+ if (restored.length === 0) {
49216
+ io.error(JSON.stringify({
49217
+ ok: false,
49218
+ app: wanted,
49219
+ error: "app_source_empty",
49220
+ hint: "the plane returned an archive with no entries \u2014 nothing was changed. Re-push the app, then pull again"
49221
+ }));
49222
+ return 1;
49223
+ }
49224
+ const conflicts = writeConflicts2(restored, dest);
49225
+ if (conflicts.length) {
49226
+ io.error(JSON.stringify({
49227
+ ok: false,
49228
+ app: wanted,
49229
+ error: "destination_shape_conflicts",
49230
+ conflicts,
49231
+ hint: "nothing was changed \u2014 remove or rename those paths, or pass --out/--name to land somewhere else"
49232
+ }));
49233
+ return 1;
49234
+ }
49235
+ let left = [];
49236
+ let removed = [];
49237
+ if (replace) removed = removeStaleSource2(restored, dest);
49238
+ else left = staleSourcePaths2(restored, dest);
49239
+ const refused = deniedArchivePaths2(restored);
49083
49240
  const written = writeAppSource2(restored, dest);
49084
49241
  print({
49085
49242
  ok: true,
@@ -49087,6 +49244,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49087
49244
  dir: dest,
49088
49245
  files: written.length,
49089
49246
  ...renamed ? { renamedTo: renamed } : {},
49247
+ ...removed.length ? { removed } : {},
49248
+ ...refused.length ? {
49249
+ refused,
49250
+ refusedNote: "this archive carries paths a restore will not write (the deny-list has grown since it was published) \u2014 they were skipped, not written over"
49251
+ } : {},
49252
+ // EVERY path, not a count and not a sample: the whole failure was that a hybrid tree
49253
+ // looked like a restore, and a list you have to go and generate yourself is the same
49254
+ // silence with extra steps.
49255
+ ...left.length ? {
49256
+ left,
49257
+ warning: `${left.length} file(s) already in ${dest} are not in this release and were KEPT \u2014 this tree is a merge of both, and matches no release. Remove them, or re-run with --replace.`
49258
+ } : {},
49090
49259
  next: `cd ${dest} && himi validate`
49091
49260
  });
49092
49261
  return 0;
@@ -49376,7 +49545,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49376
49545
  return 2;
49377
49546
  }
49378
49547
  try {
49379
- const res = writePack(resolve39(releaseDir), only, resolve39(str5(flags.out) ?? process.cwd()));
49548
+ const res = writePack(resolve40(releaseDir), only, resolve40(str5(flags.out) ?? process.cwd()));
49380
49549
  print({
49381
49550
  ok: true,
49382
49551
  app: res.app,
@@ -49414,12 +49583,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49414
49583
  ...fontIssues(dir, strict)
49415
49584
  ]);
49416
49585
  if (hasErrors && !force) {
49417
- rmSync8(built, { recursive: true, force: true });
49586
+ rmSync9(built, { recursive: true, force: true });
49418
49587
  print({ ...report, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
49419
49588
  return 1;
49420
49589
  }
49421
49590
  try {
49422
- const res = writePack(built, app, resolve39(str5(flags.out) ?? dir));
49591
+ const res = writePack(built, app, resolve40(str5(flags.out) ?? dir));
49423
49592
  print({
49424
49593
  ok: true,
49425
49594
  app: res.app,
@@ -49444,7 +49613,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49444
49613
  io.error(JSON.stringify({ error: e.message }));
49445
49614
  return 1;
49446
49615
  } finally {
49447
- rmSync8(built, { recursive: true, force: true });
49616
+ rmSync9(built, { recursive: true, force: true });
49448
49617
  }
49449
49618
  }
49450
49619
  // ---- himi share — publish/revoke a content-addressed package link ----
@@ -49472,12 +49641,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49472
49641
  }
49473
49642
  try {
49474
49643
  const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
49475
- const opened = openPackageFile2(resolve39(file));
49644
+ const opened = openPackageFile2(resolve40(file));
49476
49645
  if (!opened.validation.ok || !opened.header) {
49477
49646
  io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
49478
49647
  return 1;
49479
49648
  }
49480
- const archive = readFileSync63(resolve39(file));
49649
+ const archive = readFileSync63(resolve40(file));
49481
49650
  const result = await client3().createPackageShare({
49482
49651
  app: opened.header.app,
49483
49652
  releaseId: opened.header.releaseId,
@@ -49542,9 +49711,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49542
49711
  open: flags["no-open"] !== true
49543
49712
  });
49544
49713
  print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
49545
- await new Promise((resolve40) => {
49714
+ await new Promise((resolve41) => {
49546
49715
  const stop = () => {
49547
- void run2.close().finally(() => resolve40());
49716
+ void run2.close().finally(() => resolve41());
49548
49717
  };
49549
49718
  process.once("SIGINT", stop);
49550
49719
  process.once("SIGTERM", stop);
@@ -49580,7 +49749,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
49580
49749
  io.error(JSON.stringify({ error: e.message }));
49581
49750
  return 1;
49582
49751
  } finally {
49583
- if (temp) rmSync8(temp, { recursive: true, force: true });
49752
+ if (temp) rmSync9(temp, { recursive: true, force: true });
49584
49753
  }
49585
49754
  }
49586
49755
  case "preview": {
@@ -50315,7 +50484,7 @@ ${label2}`);
50315
50484
  const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
50316
50485
  {
50317
50486
  const distDir = contentDir(flags);
50318
- if (existsSync50(join49(distDir, "himalaya.content.json"))) {
50487
+ if (existsSync51(join49(distDir, "himalaya.content.json"))) {
50319
50488
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
50320
50489
  const errors = issues.filter((i) => i.severity === "error");
50321
50490
  for (const i of issues.filter((i2) => i2.severity === "warning")) {