@wix/himalaya-cli 0.1422.0 → 0.1423.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
@@ -10165,6 +10165,65 @@ var init_rich_content = __esm({
10165
10165
  }
10166
10166
  });
10167
10167
 
10168
+ // ../../core/dev-server/src/raw-json-depth.ts
10169
+ function rawJsonDepthFinding(value, limit = RAW_JSON_MAX_DEPTH) {
10170
+ const EXIT = Symbol("exit");
10171
+ const stack = [];
10172
+ const trail = [];
10173
+ const onTrail = /* @__PURE__ */ new Set();
10174
+ let max = 0;
10175
+ let path2;
10176
+ if (value && typeof value === "object") stack.push({ v: value, depth: 1, key: "" });
10177
+ while (stack.length) {
10178
+ const step = stack.pop();
10179
+ if (step === EXIT) {
10180
+ onTrail.delete(trail.pop());
10181
+ trail.pop();
10182
+ continue;
10183
+ }
10184
+ const v2 = step.v;
10185
+ if (onTrail.has(v2)) continue;
10186
+ onTrail.add(v2);
10187
+ trail.push(step.key, v2);
10188
+ stack.push(EXIT);
10189
+ if (step.depth > max) max = step.depth;
10190
+ if (step.depth > limit && path2 === void 0) {
10191
+ let p2 = "$";
10192
+ for (let i2 = 2; i2 < trail.length; i2 += 2) {
10193
+ const k2 = trail[i2];
10194
+ p2 += typeof k2 === "number" ? `[${k2}]` : /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(k2) ? `.${k2}` : `[${JSON.stringify(k2)}]`;
10195
+ }
10196
+ path2 = p2;
10197
+ }
10198
+ if (Array.isArray(v2)) {
10199
+ for (let i2 = v2.length - 1; i2 >= 0; i2--) {
10200
+ const c2 = v2[i2];
10201
+ if (c2 && typeof c2 === "object") stack.push({ v: c2, depth: step.depth + 1, key: i2 });
10202
+ }
10203
+ } else {
10204
+ const keys = Object.keys(v2);
10205
+ for (let i2 = keys.length - 1; i2 >= 0; i2--) {
10206
+ const c2 = v2[keys[i2]];
10207
+ if (c2 && typeof c2 === "object") stack.push({ v: c2, depth: step.depth + 1, key: keys[i2] });
10208
+ }
10209
+ }
10210
+ }
10211
+ if (path2 === void 0) return null;
10212
+ return {
10213
+ measure: "json",
10214
+ path: path2,
10215
+ limit,
10216
+ actual: max,
10217
+ message: `JSON nests ${max} levels deep; the limit is ${limit} (it crosses the limit at ${path2}). Native decoders recurse once per level and iOS refuses JSON nested past 512 \u2014 flatten that value (store it as a flat list or a string) or move it out of the descriptor`
10218
+ };
10219
+ }
10220
+ var RAW_JSON_MAX_DEPTH;
10221
+ var init_raw_json_depth = __esm({
10222
+ "../../core/dev-server/src/raw-json-depth.ts"() {
10223
+ RAW_JSON_MAX_DEPTH = 256;
10224
+ }
10225
+ });
10226
+
10168
10227
  // ../../core/dev-server/src/realm-parity.ts
10169
10228
  function withheldGlobalsSource(hide) {
10170
10229
  if (!hide?.length) return "";
@@ -10204,6 +10263,7 @@ __export(validate_descriptor_core_exports, {
10204
10263
  NATIVE_NESTED_PROPS: () => NATIVE_NESTED_PROPS,
10205
10264
  NATIVE_PROP_ENUMS: () => NATIVE_PROP_ENUMS,
10206
10265
  NATIVE_REQUIRED_PROPS: () => NATIVE_REQUIRED_PROPS,
10266
+ RAW_JSON_MAX_DEPTH: () => RAW_JSON_MAX_DEPTH,
10207
10267
  SERVICE_ONLY_BINDING_PROPS: () => SERVICE_ONLY_BINDING_PROPS,
10208
10268
  WHOLE_VALUE_BINDING: () => WHOLE_VALUE_BINDING,
10209
10269
  bareNestedClass: () => bareNestedClass,
@@ -10229,10 +10289,12 @@ __export(validate_descriptor_core_exports, {
10229
10289
  pathCrossesOpaqueAuthorJson: () => pathCrossesOpaqueAuthorJson,
10230
10290
  pathValue: () => pathValue,
10231
10291
  pinnedIntrinsicsSource: () => pinnedIntrinsicsSource,
10292
+ rawJsonDepthFinding: () => rawJsonDepthFinding,
10232
10293
  realmInstallsIntl: () => realmInstallsIntl,
10233
10294
  resolveActionEvaluator: () => resolveActionEvaluator,
10234
10295
  resolveBootEvaluator: () => resolveBootEvaluator,
10235
10296
  resolveEvaluator: () => resolveEvaluator,
10297
+ screenDepthFindings: () => screenDepthFindings,
10236
10298
  serviceOnlyBindingValues: () => serviceOnlyBindingValues,
10237
10299
  setActionEvaluator: () => setActionEvaluator,
10238
10300
  setBootEvaluator: () => setBootEvaluator,
@@ -11721,6 +11783,10 @@ function bottomSheetFindings(descriptor) {
11721
11783
  visit(descriptor, "", true);
11722
11784
  return out2;
11723
11785
  }
11786
+ function screenDepthFindings(descriptor) {
11787
+ const raw = rawJsonDepthFinding(descriptor);
11788
+ return raw ? [raw] : depthBudgetFindings(descriptor);
11789
+ }
11724
11790
  function depthBudgetIssues(findings) {
11725
11791
  return findings.map((f2) => ({
11726
11792
  severity: "error",
@@ -11966,9 +12032,9 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
11966
12032
  const issues = [];
11967
12033
  const strict = opts.strict ?? false;
11968
12034
  const hygiene = strict ? "error" : "warning";
11969
- const depthFindings = depthBudgetFindings(descriptor);
12035
+ const depthFindings = screenDepthFindings(descriptor);
11970
12036
  const depthIssues = depthBudgetIssues(depthFindings);
11971
- if (depthFindings.some((f2) => f2.measure === "depth" && f2.actual > UNSAFE_TO_RECURSE_DEPTH)) {
12037
+ if (depthFindings.some((f2) => f2.measure === "json" || f2.measure === "depth" && f2.actual > UNSAFE_TO_RECURSE_DEPTH)) {
11972
12038
  return { screenId, ok: false, strict, issues: depthIssues, services: [] };
11973
12039
  }
11974
12040
  const fixture = new FixtureValidator({ tokens: opts.tokens, allowedComponents: opts.allowedComponents });
@@ -12590,6 +12656,7 @@ var init_validate_descriptor_core = __esm({
12590
12656
  init_frame_limits();
12591
12657
  init_rich_content();
12592
12658
  init_worker_subtree();
12659
+ init_raw_json_depth();
12593
12660
  init_realm_parity();
12594
12661
  CRAWL_BLOCKING_PASSES = /* @__PURE__ */ new Set([
12595
12662
  // A screen whose bindings do not resolve has no state to crawl.
@@ -14171,6 +14238,7 @@ __export(validate_descriptor_exports, {
14171
14238
  NATIVE_NESTED_PROPS: () => NATIVE_NESTED_PROPS,
14172
14239
  NATIVE_PROP_ENUMS: () => NATIVE_PROP_ENUMS,
14173
14240
  NATIVE_REQUIRED_PROPS: () => NATIVE_REQUIRED_PROPS,
14241
+ RAW_JSON_MAX_DEPTH: () => RAW_JSON_MAX_DEPTH,
14174
14242
  SERVICE_ONLY_BINDING_PROPS: () => SERVICE_ONLY_BINDING_PROPS,
14175
14243
  WHOLE_VALUE_BINDING: () => WHOLE_VALUE_BINDING,
14176
14244
  appWorkerActionsFor: () => appWorkerActionsFor,
@@ -14202,6 +14270,7 @@ __export(validate_descriptor_exports, {
14202
14270
  pathCrossesOpaqueAuthorJson: () => pathCrossesOpaqueAuthorJson,
14203
14271
  pathValue: () => pathValue,
14204
14272
  pinnedIntrinsicsSource: () => pinnedIntrinsicsSource,
14273
+ rawJsonDepthFinding: () => rawJsonDepthFinding,
14205
14274
  readBuiltBundle: () => readBuiltBundle,
14206
14275
  readBuiltBundleMap: () => readBuiltBundleMap,
14207
14276
  realmInstallsIntl: () => realmInstallsIntl,
@@ -14209,6 +14278,7 @@ __export(validate_descriptor_exports, {
14209
14278
  resolveActionEvaluator: () => resolveActionEvaluator,
14210
14279
  resolveBootEvaluator: () => resolveBootEvaluator,
14211
14280
  resolveEvaluator: () => resolveEvaluator,
14281
+ screenDepthFindings: () => screenDepthFindings,
14212
14282
  serviceOnlyBindingValues: () => serviceOnlyBindingValues,
14213
14283
  setActionEvaluator: () => setActionEvaluator,
14214
14284
  setBootEvaluator: () => setBootEvaluator,
@@ -130765,6 +130835,10 @@ function composeStickyTree(payload, header, footer) {
130765
130835
  }
130766
130836
  async function renderDescriptorWeb(descriptor, tokens2, scheme, wantPng, services = null, width, isRTL, idiomContext) {
130767
130837
  const desc = descriptor;
130838
+ const tooDeep = rawJsonDepthFinding(descriptor);
130839
+ if (tooDeep) return { renderable: false, reason: `depth_budget_exceeded: ${tooDeep.message}` };
130840
+ const tooDeepState = services ? rawJsonDepthFinding(services) : null;
130841
+ if (tooDeepState) return { renderable: false, reason: `depth_budget_exceeded: worker state \u2014 ${tooDeepState.message}` };
130768
130842
  const payload = desc.payload;
130769
130843
  if (!payload || typeof payload !== "object" || !payload.body) {
130770
130844
  const renderer = desc.renderer ?? "unknown";
@@ -130932,6 +131006,7 @@ var init_render_descriptor = __esm({
130932
131006
  init_FakeServiceProvider();
130933
131007
  init_env();
130934
131008
  init_media_value();
131009
+ init_raw_json_depth();
130935
131010
  init_message_format();
130936
131011
  init_a11y_contract();
130937
131012
  A11Y_MODIFIER_KEYS = [
@@ -132515,15 +132590,22 @@ async function handleBootRequest(req, res, state) {
132515
132590
  const tokenDocument = effectiveAppTokens(req, state);
132516
132591
  const homeScreenId = config.homeScreenId ?? state.app.meta.homeScreenId ?? null;
132517
132592
  let screen = null;
132593
+ let homeScreenRefusal;
132518
132594
  if (homeScreenId) {
132519
132595
  const evalCtx = evalContextFromReq(req, state.appName);
132520
132596
  const caller = await resolveCaller(state.app.module, req);
132521
- const descriptor = await buildDescriptorForScreenId(
132522
- reqState,
132523
- homeScreenId,
132524
- new URLSearchParams(),
132525
- { ctx: evalCtx, caller }
132526
- );
132597
+ let descriptor = null;
132598
+ try {
132599
+ descriptor = await buildDescriptorForScreenId(
132600
+ reqState,
132601
+ homeScreenId,
132602
+ new URLSearchParams(),
132603
+ { ctx: evalCtx, caller }
132604
+ );
132605
+ } catch (err) {
132606
+ if (!(err instanceof DescriptorDepthRefusal)) throw err;
132607
+ homeScreenRefusal = { error: "depth_budget_exceeded", screenId: err.screenId, finding: err.finding };
132608
+ }
132527
132609
  if (descriptor && typeof descriptor === "object") {
132528
132610
  assignStableIds(descriptor);
132529
132611
  const acceptLanguage = req.headers["accept-language"];
@@ -132540,7 +132622,8 @@ async function handleBootRequest(req, res, state) {
132540
132622
  tokens: tokenDocument?.tokens ?? null,
132541
132623
  homeScreenId,
132542
132624
  screen,
132543
- homeBundle: null
132625
+ homeBundle: null,
132626
+ ...homeScreenRefusal ? { screenRefusal: homeScreenRefusal } : {}
132544
132627
  };
132545
132628
  const body = JSON.stringify(payload);
132546
132629
  const etag = makeEtag(body);
@@ -132738,10 +132821,15 @@ function descriptorCacheKey(reqBaseUrl, localeKey, flagKey, caller) {
132738
132821
  const who = caller.memberId ? `::mid=${caller.memberId}` : "";
132739
132822
  return `${reqBaseUrl}::${localeKey}::${flagKey}::ent=${caller.entitled ? 1 : 0}${who}`;
132740
132823
  }
132824
+ function refuseTooDeep(screenId, descriptor) {
132825
+ const finding = rawJsonDepthFinding(descriptor);
132826
+ if (finding) throw new DescriptorDepthRefusal(screenId, finding);
132827
+ return descriptor;
132828
+ }
132741
132829
  async function buildDescriptorForScreenId(state, screenId, query = new URLSearchParams(), options = {}) {
132742
132830
  if (!options.skipOverride) {
132743
132831
  const preview = state.localOverrides.get(screenId);
132744
- if (preview) return { ...preview, screenId };
132832
+ if (preview) return refuseTooDeep(screenId, { ...preview, screenId });
132745
132833
  }
132746
132834
  if (state.app) {
132747
132835
  await state.flagSync.refresh(state.app?.dir, state.flagStore, Date.now());
@@ -132767,7 +132855,7 @@ async function buildDescriptorForScreenId(state, screenId, query = new URLSearch
132767
132855
  }
132768
132856
  return null;
132769
132857
  })();
132770
- return built ? postprocessDescriptor(built, {
132858
+ return built ? postprocessDescriptor(refuseTooDeep(screenId, built), {
132771
132859
  config: uiConfig(state.app.module.config),
132772
132860
  flagDefinitions: state.flagStore.list(),
132773
132861
  evalContext: evalCtx,
@@ -135488,6 +135576,9 @@ function createDevServer(opts = {}) {
135488
135576
  send(res, 404, "not found");
135489
135577
  } catch (err) {
135490
135578
  console.error("[himalaya-dev] handler error:", err);
135579
+ if (err instanceof DescriptorDepthRefusal) {
135580
+ return sendJson(res, 422, { error: "depth_budget_exceeded", screenId: err.screenId, finding: err.finding });
135581
+ }
135491
135582
  if (isContainedCapabilityRefusal(err)) {
135492
135583
  return sendJson(res, 422, {
135493
135584
  error: "contained_capability_refused",
@@ -135539,7 +135630,7 @@ ${err.message}`);
135539
135630
  });
135540
135631
  return httpServer;
135541
135632
  }
135542
- var ROOT6, TIER3_ROOT, TIER4_ROOT, tier4Verifier, TIER5_ROOT2, ACTION_HANDLERS_ROOT, SAMPLES_ROOT, TELEMETRY_BUFFER_CAP, overrideHistorySeq, CACHE_CONTROL, TIER5_SRC_ROOT, HMR_TMP_DIR, appReloadSeq, appReloadChain, WEBWIX_CLIENT_ID, WEBWIX_REDIRECT, WEBWIX_COOKIE, webOwnerPreviewInstances, webAccountMemberInstances, MIME, widgetOverrides;
135633
+ var ROOT6, TIER3_ROOT, TIER4_ROOT, tier4Verifier, TIER5_ROOT2, ACTION_HANDLERS_ROOT, SAMPLES_ROOT, TELEMETRY_BUFFER_CAP, overrideHistorySeq, CACHE_CONTROL, DescriptorDepthRefusal, TIER5_SRC_ROOT, HMR_TMP_DIR, appReloadSeq, appReloadChain, WEBWIX_CLIENT_ID, WEBWIX_REDIRECT, WEBWIX_COOKIE, webOwnerPreviewInstances, webAccountMemberInstances, MIME, widgetOverrides;
135543
135634
  var init_src6 = __esm({
135544
135635
  "../../core/dev-server/src/index.ts"() {
135545
135636
  init_inject();
@@ -135568,6 +135659,7 @@ var init_src6 = __esm({
135568
135659
  init_player_proxy();
135569
135660
  init_app_icon();
135570
135661
  init_app_assets();
135662
+ init_raw_json_depth();
135571
135663
  init_app_module();
135572
135664
  init_provisioning_facts();
135573
135665
  init_validate();
@@ -135594,6 +135686,14 @@ var init_src6 = __esm({
135594
135686
  TELEMETRY_BUFFER_CAP = 1e3;
135595
135687
  overrideHistorySeq = 0;
135596
135688
  CACHE_CONTROL = "max-age=600, stale-while-revalidate=86400";
135689
+ DescriptorDepthRefusal = class extends Error {
135690
+ constructor(screenId, finding) {
135691
+ super(finding.message);
135692
+ this.screenId = screenId;
135693
+ this.finding = finding;
135694
+ this.name = "DescriptorDepthRefusal";
135695
+ }
135696
+ };
135597
135697
  TIER5_SRC_ROOT = resolve38(ROOT6, "core/dev-server/tier5-bundles-src");
135598
135698
  HMR_TMP_DIR = resolve38(ROOT6, "node_modules/.cache/himalaya-hmr");
135599
135699
  appReloadSeq = 0;
@@ -139631,11 +139731,33 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
139631
139731
  base = BAKE_OFFLINE_BASE;
139632
139732
  }
139633
139733
  const devFetch = (url, init) => dev.inject(new Request(url, init));
139734
+ const depthRefusalFromText = (status, text9) => {
139735
+ if (status !== 422) return null;
139736
+ try {
139737
+ const body = JSON.parse(text9);
139738
+ return body?.error === "depth_budget_exceeded" && body.finding ? body.finding : null;
139739
+ } catch {
139740
+ return null;
139741
+ }
139742
+ };
139743
+ const depthRefusalOf = async (res) => depthRefusalFromText(res.status, await res.text());
139744
+ const recordUnbuilt = async (screenId, res) => {
139745
+ const text9 = await res.text();
139746
+ const finding = depthRefusalFromText(res.status, text9);
139747
+ if (finding) {
139748
+ failedToBuild.push({ screenId, status: res.status, error: finding.message });
139749
+ if (collect2?.lint && !lint.some((l2) => l2.screenId === screenId)) {
139750
+ lint.push({ screenId, ok: false, issues: depthBudgetIssues([finding]) });
139751
+ }
139752
+ return;
139753
+ }
139754
+ failedToBuild.push({ screenId, status: res.status, error: text9.slice(0, 2e3) });
139755
+ };
139634
139756
  try {
139635
139757
  for (const screenId of screenIds) {
139636
139758
  const res = await devFetch(`${base}/v1/screen/${screenId}`, { headers: { "X-Himalaya-App": app } });
139637
139759
  if (!res.ok) {
139638
- failedToBuild.push({ screenId, status: res.status, error: (await res.text()).slice(0, 2e3) });
139760
+ await recordUnbuilt(screenId, res);
139639
139761
  continue;
139640
139762
  }
139641
139763
  const descriptor = await res.json();
@@ -139728,6 +139850,10 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
139728
139850
  const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
139729
139851
  const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
139730
139852
  renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
139853
+ } else if (res.status === 422 && collect2?.lint) {
139854
+ const finding = await depthRefusalOf(res);
139855
+ const recorded = lint.some((l2) => l2.screenId === wantedRender) || failedToBuild.some((f2) => f2.screenId === wantedRender);
139856
+ if (finding && !recorded) lint.push({ screenId: wantedRender, ok: false, issues: depthBudgetIssues([finding]) });
139731
139857
  }
139732
139858
  }
139733
139859
  for (const t2 of preloaded.module.screens.templated ?? []) {
@@ -139782,7 +139908,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
139782
139908
  if (screenId.includes("/") || screenId.includes("..")) continue;
139783
139909
  const res = await devFetch(`${base}/v1/screen/${encodeURIComponent(screenId)}`, { headers: { "X-Himalaya-App": app } });
139784
139910
  if (!res.ok) {
139785
- failedToBuild.push({ screenId, status: res.status, error: (await res.text()).slice(0, 2e3) });
139911
+ await recordUnbuilt(screenId, res);
139786
139912
  continue;
139787
139913
  }
139788
139914
  const descriptor = await res.json();
@@ -180791,7 +180917,7 @@ var NONDETERMINISTIC_FIX = "move those clock or random values out of the service
180791
180917
  function depthBudgetExceeded(report3) {
180792
180918
  return (report3.issues ?? []).some((i2) => i2.severity === "error" && i2.pass === "depth-budget");
180793
180919
  }
180794
- var DEPTH_BUDGET_HINT = "a screen or row template is over the depth budget (see the depth-budget issues' path and limit) \u2014 flatten it; `--force` does not override this";
180920
+ var DEPTH_BUDGET_HINT = "a screen or row template nests too many components, or JSON in its props, modifiers, `input` or action `args` nests past the 256-level ceiling (see the depth-budget issues' path and limit) \u2014 flatten it; `--force` does not override this";
180795
180921
  function summarizeLint(app, bres, outcome, strict, extraIssues = []) {
180796
180922
  const issues = (outcome.lint ?? []).flatMap((s2) => s2.issues.map((i2) => ({ screen: s2.screenId, ...i2 })));
180797
180923
  issues.push(...extraIssues);
@@ -186198,7 +186324,8 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
186198
186324
  });
186199
186325
  const r2 = (outcome.renders ?? [])[0];
186200
186326
  if (!r2) {
186201
- print({ ok: false, screenId, error: "screen not found or did not build", failedToBuild: outcome.failedToBuild });
186327
+ const why = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
186328
+ print({ ok: false, screenId, error: "screen not found or did not build", failedToBuild: outcome.failedToBuild, ...why.length ? { issues: why.map((i2) => ({ screen: screenId, ...i2 })) } : {} });
186202
186329
  return 1;
186203
186330
  }
186204
186331
  const diagnostics = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
@@ -188449,8 +188576,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
188449
188576
  io2.error(JSON.stringify({ ok: false, error: "invalid_descriptor", file: file2, screen: id, message: `${file2} is not valid JSON: ${e2.message}` }));
188450
188577
  return 1;
188451
188578
  }
188452
- const { depthBudgetFindings: depthBudgetFindings2, depthBudgetIssues: depthBudgetIssues2 } = await Promise.resolve().then(() => (init_validate_descriptor_core(), validate_descriptor_core_exports));
188453
- const tooDeep = depthBudgetIssues2(depthBudgetFindings2(parsed));
188579
+ const { screenDepthFindings: screenDepthFindings2, depthBudgetIssues: depthBudgetIssues2 } = await Promise.resolve().then(() => (init_validate_descriptor_core(), validate_descriptor_core_exports));
188580
+ const tooDeep = depthBudgetIssues2(screenDepthFindings2(parsed));
188454
188581
  if (tooDeep.length > 0) {
188455
188582
  io2.error(JSON.stringify({
188456
188583
  ok: false,
@@ -188461,7 +188588,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
188461
188588
  screen: id,
188462
188589
  file: file2,
188463
188590
  issues: tooDeep,
188464
- hint: "flatten the descriptor below the depth budget (see each issue's path and limit); `--force` does not override this"
188591
+ hint: DEPTH_BUDGET_HINT
188465
188592
  }, null, 2));
188466
188593
  return 1;
188467
188594
  }
@@ -47,7 +47,7 @@ keeps its existing fields and adds the code:
47
47
  | `ux_evidence_inherited_screens` | A partial push inherits screens not covered by local UX evidence. |
48
48
  | `ux_evidence_unreadable` | The UX evidence artifact cannot be read. |
49
49
  | `lint_errors` | Build/lint validation found errors. |
50
- | `depth_budget_exceeded` | A screen or a bound list/grid row template nests deeper, or has more components, than the depth budget (`depth-budget` validator pass). Each `issues[]` entry with `pass: "depth-budget"` carries the JSON `path` of the deepest node (or the tree root for a node count), the `limit` and the `actual` value. Takes precedence over `lint_errors`, and `--force` does not override it: content over the budget overflows the renderer's stack on devices already in the field. Flatten the layout and push again. `himi patch screen` refuses an over-deep raw descriptor with the same code, before any network request, and `himi pack` / `himi template publish` refuse with it even under `--force`. |
50
+ | `depth_budget_exceeded` | A screen or a bound list/grid row template nests deeper, or has more components, than the depth budget (`depth-budget` validator pass), or any of its JSON — props, modifiers, `input`, action `args` — nests past the raw-JSON ceiling of 256 levels. Each `issues[]` entry with `pass: "depth-budget"` carries the JSON `path` of the deepest node (the tree root for a node count, the first value past the ceiling for raw JSON), the `limit` and the `actual` value. Takes precedence over `lint_errors`, and `--force` does not override it: content over the budget overflows the renderer's stack on devices already in the field. Flatten the layout and push again. `himi patch screen` refuses an over-deep raw descriptor with the same code, before any network request, and `himi pack` / `himi template publish` refuse with it even under `--force`. |
51
51
  | `control_token_expired` | The selected control token has expired. |
52
52
  | `app_source_contains_secrets` | Source archiving detected a possible credential. |
53
53
  | `app_source_too_large` | The encoded source archive exceeds its limit. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1422.0",
3
+ "version": "0.1423.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -71,5 +71,5 @@
71
71
  "artifactId": "himalaya-cli"
72
72
  }
73
73
  },
74
- "falconPackageHash": "1e2ddc2aad76a7124c849d88d5862e6b66a03a169e9c066cea398548"
74
+ "falconPackageHash": "843d4fd1bc22694e9fd665efd8f59bb6fd4e4e9aa78612885a3ce661"
75
75
  }