@wix/himalaya-cli 0.833.0 → 0.834.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
@@ -4593,6 +4593,7 @@ function resolveTranslation(value, catalog, sourceCatalog) {
4593
4593
  var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
4594
4594
  var init_bindings = __esm({
4595
4595
  "../../core/ts/src/bindings.ts"() {
4596
+ "use strict";
4596
4597
  BINDING_SIGILS = ["service", "flag", "item", "t"];
4597
4598
  BINDING_SIGIL_RE = new RegExp(
4598
4599
  `^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
@@ -5690,8 +5691,8 @@ function unresolvedWixMediaReference(value, allowBareId = false) {
5690
5691
  if (reference.startsWith("wix:image://")) return reference;
5691
5692
  if (isBindingExpr(reference)) return null;
5692
5693
  if (!allowBareId && !DISTINCTIVE_WIX_MEDIA_ID.test(reference)) return null;
5693
- const resolved = wixMediaUrl(reference, null);
5694
- return resolved !== reference && resolved.startsWith(WIX_MEDIA_ORIGIN) ? reference : null;
5694
+ const resolved2 = wixMediaUrl(reference, null);
5695
+ return resolved2 !== reference && resolved2.startsWith(WIX_MEDIA_ORIGIN) ? reference : null;
5695
5696
  }
5696
5697
  var MEDIA_NAMED_PROPERTY, MEDIA_LOCATION_SUFFIX, MEDIA_PATH_SUFFIX, DISTINCTIVE_WIX_MEDIA_ID, WIX_MEDIA_ORIGIN;
5697
5698
  var init_media_value = __esm({
@@ -7000,13 +7001,13 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
7000
7001
  const p = body.props ?? {};
7001
7002
  const cases = Array.isArray(p.cases) ? p.cases : [];
7002
7003
  const ids = cases.map((c) => c?.id).filter((x) => typeof x === "string");
7003
- const resolved = resolveCaseValue(p.casePath);
7004
- if (resolved !== void 0 && ids.length > 0 && !ids.includes(resolved)) {
7004
+ const resolved2 = resolveCaseValue(p.casePath);
7005
+ if (resolved2 !== void 0 && ids.length > 0 && !ids.includes(resolved2)) {
7005
7006
  issues.push({
7006
7007
  severity: "warning",
7007
7008
  pass: "bindings",
7008
7009
  path: typeof o.id === "string" ? o.id : at,
7009
- message: `FragmentSlot casePath resolves to "${resolved}" which matches no case id (${ids.join(", ")}) \u2014 it renders the ${typeof p.defaultCase === "string" ? `defaultCase "${p.defaultCase}"` : "empty/first case"}. A case \`id\` must EQUAL the casePath value, not a component id.`
7010
+ message: `FragmentSlot casePath resolves to "${resolved2}" which matches no case id (${ids.join(", ")}) \u2014 it renders the ${typeof p.defaultCase === "string" ? `defaultCase "${p.defaultCase}"` : "empty/first case"}. A case \`id\` must EQUAL the casePath value, not a component id.`
7010
7011
  });
7011
7012
  }
7012
7013
  }
@@ -19047,8 +19048,8 @@ function resolveFamilyName(input) {
19047
19048
  return void 0;
19048
19049
  }
19049
19050
  function addReport(appDir2, family) {
19050
- const resolved = resolveFamilyName(family);
19051
- if (!resolved) {
19051
+ const resolved2 = resolveFamilyName(family);
19052
+ if (!resolved2) {
19052
19053
  return {
19053
19054
  ok: false,
19054
19055
  count: 0,
@@ -19057,15 +19058,15 @@ function addReport(appDir2, family) {
19057
19058
  hint: "run `himi fonts list` to see every family, or add it to stdlib/fonts/catalog.source.json"
19058
19059
  };
19059
19060
  }
19060
- const fam = findFamily(resolved);
19061
+ const fam = findFamily(resolved2);
19061
19062
  const bytes2 = fam?.faces.reduce((n, f) => n + f.bytes, 0) ?? 0;
19062
19063
  return {
19063
19064
  ok: true,
19064
19065
  count: 1,
19065
19066
  totalBytes: bytes2,
19066
19067
  problems: [],
19067
- families: [{ family: resolved, license: fam?.license.id ?? "system", copyright: fam?.license.copyright, kb: Math.round(bytes2 / 1024) }],
19068
- hint: `add "${resolved}" to ${join23(appDir2, "fonts.json")} under "families" (or name it in tokens.json typography), then run gen.sh. Licence: ${fam?.license.id ?? "system"}${fam?.license.copyright ? ` \u2014 ${fam.license.copyright}` : ""}`
19068
+ families: [{ family: resolved2, license: fam?.license.id ?? "system", copyright: fam?.license.copyright, kb: Math.round(bytes2 / 1024) }],
19069
+ hint: `add "${resolved2}" to ${join23(appDir2, "fonts.json")} under "families" (or name it in tokens.json typography), then run gen.sh. Licence: ${fam?.license.id ?? "system"}${fam?.license.copyright ? ` \u2014 ${fam.license.copyright}` : ""}`
19069
19070
  };
19070
19071
  }
19071
19072
  var DEFAULT_ASSET_BUDGET_BYTES;
@@ -24220,9 +24221,9 @@ function evalEnvExpr(raw, env) {
24220
24221
  return (parsed.op === "==" ? equal : !equal) ? "true" : "false";
24221
24222
  }
24222
24223
  function envHidden(raw, env) {
24223
- const resolved = evalEnvExpr(raw, env);
24224
- if (resolved === void 0) return void 0;
24225
- const l = resolved.trim().toLowerCase();
24224
+ const resolved2 = evalEnvExpr(raw, env);
24225
+ if (resolved2 === void 0) return void 0;
24226
+ const l = resolved2.trim().toLowerCase();
24226
24227
  return l === "true" || l === "1";
24227
24228
  }
24228
24229
  var ENV_SENTINEL;
@@ -25257,6 +25258,7 @@ function shouldRevealError(args) {
25257
25258
  var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
25258
25259
  var init_validation = __esm({
25259
25260
  "../../core/ts/src/validation.ts"() {
25261
+ "use strict";
25260
25262
  EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
25261
25263
  URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
25262
25264
  INTEGER_RE = /^[+-]?[0-9]+$/;
@@ -27788,17 +27790,17 @@ var init_controls = __esm({
27788
27790
  A11ySwitch = ({ props, ctx, wrap }) => {
27789
27791
  const C = ctx.color;
27790
27792
  const bound = useResolvedScalar(props.valuePath, ctx);
27791
- const resolved = ctx.empty ? false : props.valuePath != null ? encodeToggleFieldValue(bound) === "true" : encodeToggleFieldValue(props.value, props.on === true) === "true";
27793
+ const resolved2 = ctx.empty ? false : props.valuePath != null ? encodeToggleFieldValue(bound) === "true" : encodeToggleFieldValue(props.value, props.on === true) === "true";
27792
27794
  const bag = React3.useContext(FormValuesContext);
27793
27795
  const fieldId = props.__formFieldId;
27794
27796
  const inForm = Boolean(bag && fieldId);
27795
27797
  const [formOn, setFormOn] = React3.useState(null);
27796
27798
  const touched = React3.useRef(false);
27797
27799
  React3.useEffect(() => {
27798
- if (touched.current && bag && fieldId) bag.set(fieldId, encodeToggleFieldValue(resolved));
27800
+ if (touched.current && bag && fieldId) bag.set(fieldId, encodeToggleFieldValue(resolved2));
27799
27801
  setFormOn(null);
27800
- }, [resolved]);
27801
- const on3 = inForm && formOn !== null ? formOn : resolved;
27802
+ }, [resolved2]);
27803
+ const on3 = inForm && formOn !== null ? formOn : resolved2;
27802
27804
  const ruleKey = props.validation ? JSON.stringify(props.validation) : "";
27803
27805
  React3.useEffect(() => {
27804
27806
  if (!bag || !fieldId) return;
@@ -28646,6 +28648,7 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
28646
28648
  var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
28647
28649
  var init_worker_subtree = __esm({
28648
28650
  "../../core/ts/src/worker-subtree.ts"() {
28651
+ "use strict";
28649
28652
  init_worker_subtree_safe_types_generated();
28650
28653
  WORKER_SUBTREE_CEILINGS = Object.freeze({
28651
28654
  maxEncodedBytes: 65536,
@@ -29339,9 +29342,9 @@ function useResolvedMediaItems(items, ctx) {
29339
29342
  for (const f of MEDIA_ITEM_BINDABLE) {
29340
29343
  const v = it[f];
29341
29344
  if (typeof v !== "string" || !isBinding(v)) continue;
29342
- const resolved = v.startsWith("$service:") ? ctx.provider ? values[servicePath(v)] ?? void 0 : void 0 : resolveScalarStatic(v, ctx);
29345
+ const resolved2 = v.startsWith("$service:") ? ctx.provider ? values[servicePath(v)] ?? void 0 : void 0 : resolveScalarStatic(v, ctx);
29343
29346
  out = out ?? { ...it };
29344
- out[f] = resolved;
29347
+ out[f] = resolved2;
29345
29348
  }
29346
29349
  return out ?? it;
29347
29350
  }), [items, values, ctx]);
@@ -29805,11 +29808,11 @@ function actionTextButton(ctx, action, label2, color, extra) {
29805
29808
  }
29806
29809
  function dispatchCalendarAction(ctx, action, extra) {
29807
29810
  if (!ctx.onAction || !action) return;
29808
- const resolved = resolveItemDeep2(action, ctx);
29811
+ const resolved2 = resolveItemDeep2(action, ctx);
29809
29812
  ctx.onAction({
29810
- ...resolved,
29811
- args: { ...resolved?.args ?? {}, ...extra },
29812
- params: { ...resolved?.params ?? {}, ...Object.fromEntries(Object.entries(extra).map(([k, v]) => [k, String(v)])) }
29813
+ ...resolved2,
29814
+ args: { ...resolved2?.args ?? {}, ...extra },
29815
+ params: { ...resolved2?.params ?? {}, ...Object.fromEntries(Object.entries(extra).map(([k, v]) => [k, String(v)])) }
29813
29816
  });
29814
29817
  }
29815
29818
  function calKeyActivate(enabled, activate) {
@@ -29913,8 +29916,8 @@ function renderNodeInner(node, ctx) {
29913
29916
  }
29914
29917
  const accessibilityLabel = node?.modifiers?.accessibilityLabel ?? node?.modifiers?.accessibility_label;
29915
29918
  if (accessibilityLabel != null) {
29916
- const resolved = resolveScalarStatic(accessibilityLabel, ctx);
29917
- if (resolved != null && String(resolved).trim()) extra["aria-label"] = String(resolved);
29919
+ const resolved2 = resolveScalarStatic(accessibilityLabel, ctx);
29920
+ if (resolved2 != null && String(resolved2).trim()) extra["aria-label"] = String(resolved2);
29918
29921
  }
29919
29922
  ensurePressStyles();
29920
29923
  extra["data-himalaya-tap"] = "1";
@@ -30282,8 +30285,8 @@ function renderInner(node, ctx) {
30282
30285
  case "Spacer": {
30283
30286
  if (props.collapseWhenEmpty === true) {
30284
30287
  const raw = props.value;
30285
- const resolved = typeof raw === "string" && isBinding(raw) ? resolveScalarStatic(raw, ctx) : raw;
30286
- const s = resolved == null ? "" : String(resolved);
30288
+ const resolved2 = typeof raw === "string" && isBinding(raw) ? resolveScalarStatic(raw, ctx) : raw;
30289
+ const s = resolved2 == null ? "" : String(resolved2);
30287
30290
  if (!s || s === "\u2014") return null;
30288
30291
  }
30289
30292
  return /* @__PURE__ */ jsx6("div", { style: { flex: 1 } });
@@ -30818,8 +30821,8 @@ var init_renderNode = __esm({
30818
30821
  asTextL10n = (v, ctx) => typeof v === "string" && v.startsWith(TRANSLATION_PREFIX) ? asText2(resolveTranslation(v, ctx.catalog)) : asText2(v);
30819
30822
  asBoundText = (v, ctx) => isBinding(v) ? asTextL10n(resolveScalarStatic(v, ctx) ?? "", ctx) : asText2(v);
30820
30823
  useBoundString = (v, ctx) => {
30821
- const resolved = useResolvedScalar(v, ctx);
30822
- return isBinding(v) ? asTextL10n(resolved ?? "", ctx) : asText2(v);
30824
+ const resolved2 = useResolvedScalar(v, ctx);
30825
+ return isBinding(v) ? asTextL10n(resolved2 ?? "", ctx) : asText2(v);
30823
30826
  };
30824
30827
  InterpolatedTextView = ({ pattern, params, ctx }) => {
30825
30828
  const bound = Object.entries(params).filter(
@@ -30839,19 +30842,19 @@ var init_renderNode = __esm({
30839
30842
  );
30840
30843
  return () => unsubs.forEach((u) => u());
30841
30844
  }, [ctx.provider, subKey]);
30842
- const resolved = { ...live2 };
30845
+ const resolved2 = { ...live2 };
30843
30846
  for (const [k, v] of Object.entries(params)) {
30844
- if (typeof v === "string" && v.startsWith("$item")) resolved[k] = resolveScalarStatic(v, ctx);
30847
+ if (typeof v === "string" && v.startsWith("$item")) resolved2[k] = resolveScalarStatic(v, ctx);
30845
30848
  }
30846
- return /* @__PURE__ */ jsx6(Fragment3, { children: formatInterpolated(pattern, params, resolved, ctx) });
30849
+ return /* @__PURE__ */ jsx6(Fragment3, { children: formatInterpolated(pattern, params, resolved2, ctx) });
30847
30850
  };
30848
30851
  txt = (v, ctx) => {
30849
30852
  if (!isBinding(v)) return asText2(v);
30850
30853
  if (v.startsWith(TRANSLATION_PREFIX)) return asText2(resolveTranslation(v, ctx.catalog));
30851
30854
  if (v.startsWith("$item")) {
30852
30855
  const key2 = v.replace(/^\$item\.?/, "");
30853
- const resolved = ctx.itemScope ? key2 ? ctx.itemScope[key2] : ctx.itemScope : void 0;
30854
- return resolved != null ? asTextL10n(resolved, ctx) : bindingPlaceholder(v, ctx);
30856
+ const resolved2 = ctx.itemScope ? key2 ? ctx.itemScope[key2] : ctx.itemScope : void 0;
30857
+ return resolved2 != null ? asTextL10n(resolved2, ctx) : bindingPlaceholder(v, ctx);
30855
30858
  }
30856
30859
  if (ctx.provider) return /* @__PURE__ */ jsx6(Bound, { ctx, binding: v, render: (val) => asTextL10n(val, ctx) });
30857
30860
  return bindingPlaceholder(v, ctx);
@@ -31002,11 +31005,11 @@ var init_renderNode = __esm({
31002
31005
  };
31003
31006
  resolvedComponentId = (id, ctx) => {
31004
31007
  if (typeof id !== "string" || !id) return void 0;
31005
- const resolved = id.replace(/\$item(?:\.[A-Za-z0-9_]+)*/g, (binding2) => {
31008
+ const resolved2 = id.replace(/\$item(?:\.[A-Za-z0-9_]+)*/g, (binding2) => {
31006
31009
  const value = resolveScalarStatic(binding2, ctx);
31007
31010
  return value == null ? binding2 : String(value);
31008
31011
  });
31009
- return resolved.includes("$item") ? void 0 : resolved;
31012
+ return resolved2.includes("$item") ? void 0 : resolved2;
31010
31013
  };
31011
31014
  directServiceBindings = (node) => {
31012
31015
  const out = /* @__PURE__ */ new Set();
@@ -33118,12 +33121,12 @@ var init_renderNode = __esm({
33118
33121
  const cLat = userCam?.lat ?? baseLat;
33119
33122
  const cLng = userCam?.lng ?? baseLng;
33120
33123
  React5.useEffect(() => {
33121
- const resolved = resolveCamera(commandedCamera, cLat, cLng, z);
33122
- if (!resolved) return;
33124
+ const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z);
33125
+ if (!resolved2) return;
33123
33126
  setUserCam({
33124
- lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved.latitude)),
33125
- lng: resolved.longitude,
33126
- z: Math.max(1, Math.min(19, resolved.zoom ?? z))
33127
+ lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
33128
+ lng: resolved2.longitude,
33129
+ z: Math.max(1, Math.min(19, resolved2.zoom ?? z))
33127
33130
  });
33128
33131
  }, [commandedCamera]);
33129
33132
  const originX = mercatorX(cLng, z) - W / 2;
@@ -34095,17 +34098,17 @@ function collectResolvedMediaRecord(record2, path, context) {
34095
34098
  }
34096
34099
  }
34097
34100
  function collectResolvedMediaValues(value, path, context) {
34098
- const resolved = typeof value === "string" ? resolveTreeScalar(value, context.provider, context.itemScope) : value;
34099
- if (typeof resolved === "string") {
34100
- if (context.insideMediaProperty) context.values[path] = resolved;
34101
+ const resolved2 = typeof value === "string" ? resolveTreeScalar(value, context.provider, context.itemScope) : value;
34102
+ if (typeof resolved2 === "string") {
34103
+ if (context.insideMediaProperty) context.values[path] = resolved2;
34101
34104
  return;
34102
34105
  }
34103
- if (Array.isArray(resolved)) {
34104
- resolved.forEach((item, index) => collectResolvedMediaValues(item, `${path}[${index}]`, context));
34106
+ if (Array.isArray(resolved2)) {
34107
+ resolved2.forEach((item, index) => collectResolvedMediaValues(item, `${path}[${index}]`, context));
34105
34108
  return;
34106
34109
  }
34107
- if (resolved && typeof resolved === "object") {
34108
- collectResolvedMediaRecord(resolved, path, context);
34110
+ if (resolved2 && typeof resolved2 === "object") {
34111
+ collectResolvedMediaRecord(resolved2, path, context);
34109
34112
  }
34110
34113
  }
34111
34114
  function collectComponentMediaValues(type, props, context) {
@@ -34734,8 +34737,8 @@ function endpointErrors(endpoint, index, options) {
34734
34737
  if (typeof endpoint.pathPrefix !== "string" || !endpoint.pathPrefix.startsWith("/") || endpoint.pathPrefix.startsWith("//")) {
34735
34738
  errors.push(`${at}.pathPrefix must be an absolute pathname boundary`);
34736
34739
  } else if (origin) {
34737
- const resolved = new URL(endpoint.pathPrefix, origin);
34738
- if (resolved.origin !== origin.origin || resolved.pathname !== endpoint.pathPrefix || resolved.search || resolved.hash) {
34740
+ const resolved2 = new URL(endpoint.pathPrefix, origin);
34741
+ if (resolved2.origin !== origin.origin || resolved2.pathname !== endpoint.pathPrefix || resolved2.search || resolved2.hash) {
34739
34742
  errors.push(`${at}.pathPrefix must not contain a query, fragment, host, or dot-segment`);
34740
34743
  }
34741
34744
  }
@@ -36281,9 +36284,9 @@ function effectiveAppTokens(req, state) {
36281
36284
  if (motionDefs.length) {
36282
36285
  const cfg = currentFlagConfig(state);
36283
36286
  const assignments = evaluateAll(motionDefs, evalContextFromReq(req, state.appName), cfg?.overrides);
36284
- const resolved = applyMotionFlagOverride(tokens, assignments);
36285
- tokens = resolved.tokens;
36286
- motionToggles = resolved.togglesApplied;
36287
+ const resolved2 = applyMotionFlagOverride(tokens, assignments);
36288
+ tokens = resolved2.tokens;
36289
+ motionToggles = resolved2.togglesApplied;
36287
36290
  }
36288
36291
  } catch {
36289
36292
  }
@@ -38479,13 +38482,13 @@ function createDevServer(opts = {}) {
38479
38482
  const netMocksDisabled = opts.netMocks === false;
38480
38483
  const explicitNetMocksPath = typeof opts.netMocks === "string" ? opts.netMocks : process.env.HIMALAYA_NET_MOCKS;
38481
38484
  const netMocksPath = netMocksDisabled ? void 0 : explicitNetMocksPath ?? (state.app?.meta.devGateway?.enabled === false ? void 0 : state.app ? resolve28(state.app.dir, "dev/net-mocks.json") : void 0);
38482
- const resolved = netMocksDisabled ? null : resolveNetMocks(
38485
+ const resolved2 = netMocksDisabled ? null : resolveNetMocks(
38483
38486
  netMocksPath ? readNetMocksFile(netMocksPath) : null,
38484
38487
  state.app?.meta.devGateway
38485
38488
  );
38486
- if (resolved) {
38487
- const seeded = applyNetMocks(state.wix, resolved.mocks);
38488
- const from = resolved.source === "file" ? netMocksPath : `${state.appName} devGateway.rules`;
38489
+ if (resolved2) {
38490
+ const seeded = applyNetMocks(state.wix, resolved2.mocks);
38491
+ const from = resolved2.source === "file" ? netMocksPath : `${state.appName} devGateway.rules`;
38489
38492
  console.error(`[himalaya-dev] net-mocks: seeded ${seeded.rules} rule(s), mode=${seeded.mode} from ${from}`);
38490
38493
  }
38491
38494
  const appScenario = state.app?.meta.devGateway;
@@ -39483,15 +39486,15 @@ async function withStoreNavBundle(text2, address) {
39483
39486
  (r) => !!r && typeof r === "object" && typeof r.url === "string"
39484
39487
  );
39485
39488
  if (refs.length === 0) return text2;
39486
- const resolved = [];
39489
+ const resolved2 = [];
39487
39490
  for (const ref of refs) {
39488
39491
  const name = bundleNameFromUrl(ref.url);
39489
39492
  if (!name) return text2;
39490
39493
  const addressed = await address(name);
39491
39494
  if (!addressed) return text2;
39492
- resolved.push({ ref, url: addressed.url, sri: addressed.sri });
39495
+ resolved2.push({ ref, url: addressed.url, sri: addressed.sri });
39493
39496
  }
39494
- for (const { ref, url, sri: integrity2 } of resolved) {
39497
+ for (const { ref, url, sri: integrity2 } of resolved2) {
39495
39498
  ref.url = url;
39496
39499
  ref.integrity = integrity2;
39497
39500
  }
@@ -40527,6 +40530,140 @@ var init_capability_fixtures = __esm({
40527
40530
  }
40528
40531
  });
40529
40532
 
40533
+ // ../../core/dev-server/src/crawl-input.ts
40534
+ function resolved(v, resolve41) {
40535
+ if (typeof v === "string") return v.startsWith("$service:") ? resolve41(v) : v;
40536
+ if (Array.isArray(v)) {
40537
+ const out = v.flatMap((el) => {
40538
+ if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
40539
+ const r = resolve41(el);
40540
+ return Array.isArray(r) ? r : [r];
40541
+ });
40542
+ return out;
40543
+ }
40544
+ return v;
40545
+ }
40546
+ function hasRowBinding(props) {
40547
+ const itemToken = (v) => typeof v === "string" && v.startsWith("$item");
40548
+ return VALUE_PROPS.some((k) => {
40549
+ const v = props[k];
40550
+ return itemToken(v) || Array.isArray(v) && v.some(itemToken);
40551
+ });
40552
+ }
40553
+ function declaredOptionIds(props, resolve41) {
40554
+ const literal = props.options ?? props.tabs ?? props.chips;
40555
+ const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve41) : void 0;
40556
+ const raw = Array.isArray(bound) ? bound : literal;
40557
+ if (!Array.isArray(raw)) return [];
40558
+ const out = [];
40559
+ for (const o of raw) {
40560
+ const id = o && typeof o === "object" ? o.id : o;
40561
+ if (typeof id === "string" && id && !id.startsWith("$")) out.push(id);
40562
+ }
40563
+ return out;
40564
+ }
40565
+ function seedTokens(state, limit = 48) {
40566
+ const out = [];
40567
+ const seen = /* @__PURE__ */ new Set();
40568
+ let budget = 4e3;
40569
+ const take = (s) => {
40570
+ for (const raw of s.split(/[^\p{L}'-]+/u)) {
40571
+ if (out.length >= limit) return;
40572
+ const tok = raw.replace(/^['-]+/, "").replace(/['-]+$/, "");
40573
+ if (tok.length < 3 || tok.length > 24) continue;
40574
+ if (!new RegExp("^\\p{L}[\\p{L}'-]*$", "u").test(tok)) continue;
40575
+ if (NEVER_TYPED.has(tok)) continue;
40576
+ if (seen.has(tok)) continue;
40577
+ seen.add(tok);
40578
+ out.push(tok);
40579
+ }
40580
+ };
40581
+ const walk2 = (node, depth) => {
40582
+ if (out.length >= limit || budget-- <= 0 || depth > 6) return;
40583
+ if (typeof node === "string") {
40584
+ if (node.length <= 200 && !node.includes("://") && !node.startsWith("$")) take(node);
40585
+ return;
40586
+ }
40587
+ if (Array.isArray(node)) {
40588
+ for (const el of node) walk2(el, depth + 1);
40589
+ return;
40590
+ }
40591
+ if (node && typeof node === "object") {
40592
+ for (const v of Object.values(node)) walk2(v, depth + 1);
40593
+ }
40594
+ };
40595
+ walk2(state, 0);
40596
+ return out;
40597
+ }
40598
+ function synthesizeInput(control, resolve41, tokens) {
40599
+ const id = `${control.type}.${control.callback}`;
40600
+ const row = SYNTHESIZED_CONTROLS[id];
40601
+ if (!row) return null;
40602
+ const props = control.props;
40603
+ if (hasRowBinding(props)) return null;
40604
+ if (row.from === "declared-options") {
40605
+ const ids = declaredOptionIds(props, resolve41);
40606
+ if (!ids.length) return null;
40607
+ if (row.encoding === "string-array") {
40608
+ const currentRaw2 = resolved(props.selectedIds, resolve41);
40609
+ const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
40610
+ const pick4 = ids.find((o) => !current3.includes(o));
40611
+ if (pick4 === void 0) return null;
40612
+ const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
40613
+ return { key: row.key, value, from: row.from, current: current3, control: id };
40614
+ }
40615
+ const currentRaw = resolved(props.selectedId, resolve41);
40616
+ const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
40617
+ const pick3 = ids.find((o) => o !== current2);
40618
+ if (pick3 === void 0) return null;
40619
+ return { key: row.key, value: pick3, from: row.from, current: current2, control: id };
40620
+ }
40621
+ if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
40622
+ const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
40623
+ const bound = binding2 === void 0 ? void 0 : resolve41(binding2);
40624
+ const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
40625
+ const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
40626
+ const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
40627
+ const pick2 = tokens().find((t) => t !== current && (max === void 0 || t.length <= max));
40628
+ if (pick2 === void 0) return null;
40629
+ return { key: row.key, value: pick2, from: row.from, current, control: id };
40630
+ }
40631
+ function acceptsWords(props) {
40632
+ if (props.secure === true) return false;
40633
+ const keyboard = props.keyboard;
40634
+ if (typeof keyboard === "string" && NON_WORD_KEYBOARDS.has(keyboard)) return false;
40635
+ const v = props.validation;
40636
+ if (v && typeof v === "object") {
40637
+ const rules = v;
40638
+ if (rules.type !== void 0 || rules.regex !== void 0) return false;
40639
+ if (rules.minValue !== void 0 || rules.maxValue !== void 0) return false;
40640
+ }
40641
+ return true;
40642
+ }
40643
+ var SYNTHESIZED_CONTROLS, FORM_FIELD_CONTROL, VALUE_PROPS, NEVER_TYPED, NON_WORD_KEYBOARDS;
40644
+ var init_crawl_input = __esm({
40645
+ "../../core/dev-server/src/crawl-input.ts"() {
40646
+ SYNTHESIZED_CONTROLS = {
40647
+ "TextField.onChange": { key: "value", encoding: "string", from: "seed-text" },
40648
+ "SearchField.onChange": { key: "value", encoding: "string", from: "seed-text" },
40649
+ "Picker.onChange": { key: "selectedId", encoding: "string", from: "declared-options" },
40650
+ "SegmentedControl.onChange": { key: "selectedId", encoding: "string", from: "declared-options" },
40651
+ "Tabs.onChange": { key: "selectedId", encoding: "string", from: "declared-options" },
40652
+ "FilterChips.onChange": { key: "selectedIds", encoding: "string-array", from: "declared-options" }
40653
+ };
40654
+ FORM_FIELD_CONTROL = {
40655
+ text: "TextField",
40656
+ picker: "Picker",
40657
+ toggle: "Toggle",
40658
+ stepper: "Stepper",
40659
+ date: "DatePicker"
40660
+ };
40661
+ VALUE_PROPS = ["valuePath", "value", "selectedId", "selectedIds", "optionsPath", "options", "tabs", "chips"];
40662
+ NEVER_TYPED = /* @__PURE__ */ new Set(["NaN", "undefined", "null", "Infinity", "object", "Object"]);
40663
+ NON_WORD_KEYBOARDS = /* @__PURE__ */ new Set(["number", "decimal", "email", "phone", "url"]);
40664
+ }
40665
+ });
40666
+
40530
40667
  // ../../core/dev-server/src/crawl-relations.ts
40531
40668
  function inversePartner(action, declared) {
40532
40669
  if (/^toggle/i.test(action)) return null;
@@ -40685,11 +40822,15 @@ __export(screen_crawl_exports, {
40685
40822
  });
40686
40823
  function actionSites(payload) {
40687
40824
  const out = [];
40688
- const visit = (node, ownerId, itemsPath) => {
40689
- if (Array.isArray(node)) return node.forEach((n) => visit(n, ownerId, itemsPath));
40825
+ const visit = (node, ownerId, itemsPath, type, wrapper) => {
40826
+ if (Array.isArray(node)) return node.forEach((n) => visit(n, ownerId, itemsPath, type, wrapper));
40690
40827
  if (!node || typeof node !== "object") return;
40691
40828
  const rec = node;
40692
40829
  const id = typeof rec.id === "string" ? rec.id : ownerId;
40830
+ const body = rec.body;
40831
+ const isComponent = body != null && typeof body === "object" && typeof body.type === "string";
40832
+ const ownType = isComponent ? body.type : type;
40833
+ const ownWrapper = isComponent ? void 0 : wrapper;
40693
40834
  const ownItems = typeof rec.itemsPath === "string" ? rec.itemsPath.startsWith("$service:") ? rec.itemsPath : rec.itemsPath.startsWith("$item.") && itemsPath && itemsPath !== UNTRACKED_ITEMS && !itemsPath.includes(NESTED_ITEMS_SEP) ? `${itemsPath}${NESTED_ITEMS_SEP}${rec.itemsPath.slice("$item.".length)}` : UNTRACKED_ITEMS : void 0;
40694
40835
  const ambient = ownItems ?? itemsPath;
40695
40836
  for (const [k, v] of Object.entries(rec)) {
@@ -40702,15 +40843,28 @@ function actionSites(payload) {
40702
40843
  actionId: a.actionId,
40703
40844
  params: a.params ?? {},
40704
40845
  ...a.args ? { args: a.args } : {},
40705
- ...ambient ? { itemsPath: ambient } : {}
40846
+ ...ambient ? { itemsPath: ambient } : {},
40847
+ // `rec` IS the prop bag that carries this callback — for a plain node that is
40848
+ // `body.props`, and for a FormField variant the nested `text`/`picker`/… object, which
40849
+ // is exactly where the option list or value binding lives.
40850
+ ...ownType ? { control: { type: ownType, props: rec, ...ownWrapper ? { wrapper: ownWrapper } : {} } } : {}
40706
40851
  });
40707
40852
  }
40708
40853
  continue;
40709
40854
  }
40710
- visit(v, id, ambient);
40855
+ const intoVariant = ownType === "FormField" && k in FORM_FIELD_CONTROL;
40856
+ visit(
40857
+ v,
40858
+ id,
40859
+ ambient,
40860
+ intoVariant ? FORM_FIELD_CONTROL[k] : ownType,
40861
+ // Descending into a FormField's variant: `rec` is the FormField's own props, and its
40862
+ // `validation` constrains the control being rendered inside.
40863
+ intoVariant ? rec : ownWrapper
40864
+ );
40711
40865
  }
40712
40866
  };
40713
- visit(payload, null, void 0);
40867
+ visit(payload, null, void 0, null, void 0);
40714
40868
  return out;
40715
40869
  }
40716
40870
  function actionSitesForDescriptor(descriptor) {
@@ -41248,15 +41402,16 @@ async function crawlScreenInner(opts) {
41248
41402
  const navEdges = [];
41249
41403
  const unobservedActions = [];
41250
41404
  let observations;
41405
+ let seedWords = [];
41251
41406
  const harvestStaticEdges = (state) => {
41252
41407
  const provider = new FakeServiceProvider(state);
41253
41408
  for (const site of sites) {
41254
41409
  if (site.actionId !== "himi.open") continue;
41255
- const resolved = resolveActionServiceParams(
41410
+ const resolved2 = resolveActionServiceParams(
41256
41411
  { actionId: site.actionId, params: site.params, args: site.args },
41257
41412
  provider
41258
41413
  );
41259
- const merged = { ...resolved.params ?? {}, ...resolved.args ?? {} };
41414
+ const merged = { ...resolved2.params ?? {}, ...resolved2.args ?? {} };
41260
41415
  const row0 = firstRowFor(site.itemsPath, (p) => provider.value(p));
41261
41416
  const resolveItem = (v) => {
41262
41417
  if (typeof v !== "string" || !v.startsWith("$item")) return v;
@@ -41457,8 +41612,8 @@ async function crawlScreenInner(opts) {
41457
41612
  const before = { ...site.params ?? {}, ...site.args ?? {} };
41458
41613
  const bound = Object.entries(before).filter(([, v]) => typeof v === "string" && v.startsWith("$service:"));
41459
41614
  if (!bound.length) continue;
41460
- const resolved = resolveActionServiceParams({ actionId: site.actionId, params: site.params, args: site.args }, provider);
41461
- const after = { ...resolved.params ?? {}, ...resolved.args ?? {} };
41615
+ const resolved2 = resolveActionServiceParams({ actionId: site.actionId, params: site.params, args: site.args }, provider);
41616
+ const after = { ...resolved2.params ?? {}, ...resolved2.args ?? {} };
41462
41617
  for (const [k, v] of bound) {
41463
41618
  if (!(k in after)) {
41464
41619
  findings.push({
@@ -41493,6 +41648,7 @@ async function crawlScreenInner(opts) {
41493
41648
  if (first.deadLifecycle) reportDeadLifecycle(first.deadLifecycle);
41494
41649
  check("boot", first.state, first.errors, first.defects);
41495
41650
  observations = collectObservations(descriptor, first.state);
41651
+ seedWords = seedTokens(first.state);
41496
41652
  harvestStaticEdges(first.state);
41497
41653
  drainWorkerEdges(first, "worker:boot");
41498
41654
  drainPollDirectives(first, "boot");
@@ -41571,16 +41727,19 @@ async function crawlScreenInner(opts) {
41571
41727
  continue;
41572
41728
  }
41573
41729
  const trigger = { tap: site.componentId, key: site.key, action: site.actionId };
41574
- const effective = effectiveSiteFor(site, snapshot(w).state);
41730
+ const preState = snapshot(w).state;
41731
+ const effective = effectiveSiteFor(site, preState);
41575
41732
  if (!effective) {
41576
41733
  actionsSkipped.push({ action: site.actionId, why: "no-row-value" });
41577
41734
  continue;
41578
41735
  }
41579
- const before = JSON.stringify(snapshot(w).state);
41736
+ const typed = synthesizedFor(site, effective, preState, () => seedWords);
41737
+ const dispatched = typed ? { ...effective, args: { ...effective.args ?? {}, [typed.key]: typed.value } } : effective;
41738
+ const before = JSON.stringify(preState);
41580
41739
  const callsBefore = w.calls.length;
41581
41740
  const errors = [];
41582
41741
  try {
41583
- await handle.dispatch(parsed.action, ...workerArgs(effective));
41742
+ await handle.dispatch(parsed.action, ...workerArgs(dispatched));
41584
41743
  } catch (e) {
41585
41744
  errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e)}`, ...e.stack ? { stack: e.stack } : {} });
41586
41745
  }
@@ -41591,11 +41750,25 @@ async function crawlScreenInner(opts) {
41591
41750
  drainWorkerEdges(w, `worker:${site.actionId}`);
41592
41751
  drainPollDirectives(w, trigger);
41593
41752
  if (!errors.length && navEdges.length === navCountBefore && w.calls.length === callsBefore && JSON.stringify(state) === before) {
41753
+ if (typed) {
41754
+ findings.push({
41755
+ screen: screenId,
41756
+ trigger,
41757
+ invariant: "typed-value-ignored",
41758
+ severity: "warning",
41759
+ axis: "input",
41760
+ ...site.componentId ? { at: site.componentId } : {},
41761
+ field: typed.key,
41762
+ actual: JSON.stringify(typed.value),
41763
+ message: `${typed.control} carried ${typed.key}=${JSON.stringify(typed.value)} into ${site.actionId} and nothing changed \u2014 no state delta, no navigation, no request`,
41764
+ hint: `core/schema/action-payload-contract.json declares ${typed.control} injects "${typed.key}", and every renderer sends it \u2014 a reducer whose result does not depend on it cannot work on device (check the key it reads off its payload). The value came from ${typed.from === "declared-options" ? "this control's own option list" : "the worker's own seeded state"}; the control currently shows ${JSON.stringify(typed.current)}. If the no-op is deliberate, silence it in himi-test.json: {"skip":[{"invariant":"typed-value-ignored","reason":"\u2026"}]}.`
41765
+ });
41766
+ }
41594
41767
  unobservedActions.push({
41595
41768
  action: site.actionId,
41596
41769
  componentId: site.componentId,
41597
41770
  key: site.key,
41598
- argless: workerArgs(effective).length === 0
41771
+ argless: workerArgs(dispatched).length === 0
41599
41772
  });
41600
41773
  }
41601
41774
  } finally {
@@ -41945,6 +42118,23 @@ function effectiveSiteForRow(site, row) {
41945
42118
  }
41946
42119
  return { ...site, params: substituted, args: void 0 };
41947
42120
  }
42121
+ function synthesizedFor(site, effective, state, tokens) {
42122
+ if (!site.control) return null;
42123
+ const provider = new FakeServiceProvider(state);
42124
+ const candidate = synthesizeInput(
42125
+ {
42126
+ type: site.control.type,
42127
+ callback: site.key,
42128
+ props: site.control.props,
42129
+ ...site.control.wrapper ? { wrapper: site.control.wrapper } : {}
42130
+ },
42131
+ (p) => provider.value(p),
42132
+ tokens
42133
+ );
42134
+ if (!candidate) return null;
42135
+ const declared = { ...effective.params ?? {}, ...effective.args ?? {} };
42136
+ return candidate.key in declared ? null : candidate;
42137
+ }
41948
42138
  function isRowBound(site) {
41949
42139
  const payload = { ...site.params ?? {}, ...site.args ?? {} };
41950
42140
  return Object.values(payload).some((v) => typeof v === "string" && (v === "$item" || v.startsWith("$item.")));
@@ -42151,6 +42341,7 @@ var init_screen_crawl = __esm({
42151
42341
  init_actionParams();
42152
42342
  init_implications();
42153
42343
  init_capability_fixtures();
42344
+ init_crawl_input();
42154
42345
  init_crawl_relations();
42155
42346
  ACTION_KEYS = [
42156
42347
  "action",
@@ -45278,9 +45469,9 @@ function assertKey(key2) {
45278
45469
  if (typeof key2 !== "string" || key2.length < 1 || key2.length > 256) throw new Error("KV key must contain 1 to 256 characters");
45279
45470
  }
45280
45471
  function ttl(spec, value) {
45281
- const resolved = value ?? spec.defaultTtlSeconds;
45282
- if (resolved !== void 0 && (!Number.isInteger(resolved) || resolved < 1 || resolved > KV_MAX_TTL_SECONDS)) throw new Error(`KV ttlSeconds must be an integer from 1 to ${KV_MAX_TTL_SECONDS}`);
45283
- return resolved;
45472
+ const resolved2 = value ?? spec.defaultTtlSeconds;
45473
+ if (resolved2 !== void 0 && (!Number.isInteger(resolved2) || resolved2 < 1 || resolved2 > KV_MAX_TTL_SECONDS)) throw new Error(`KV ttlSeconds must be an integer from 1 to ${KV_MAX_TTL_SECONDS}`);
45474
+ return resolved2;
45284
45475
  }
45285
45476
  function logicalCollection(spec, app) {
45286
45477
  return spec.wixId ?? ownedName(spec, app) ?? "";
@@ -47347,16 +47538,16 @@ ${releaseId}`;
47347
47538
  if (request.method !== "GET") return json3(405, { error: "method_not_allowed" });
47348
47539
  const cfg = await appConfigFor(app2, resolvePin(request, url));
47349
47540
  if (!cfg.ok) return cfg.response;
47350
- const resolved = wixMemberAuthOf(utf8Decode(cfg.bytes), callbackUrlFor(url));
47351
- if (!resolved.ok) return json3(501, { error: `member_auth_${resolved.error}`, app: app2 });
47541
+ const resolved2 = wixMemberAuthOf(utf8Decode(cfg.bytes), callbackUrlFor(url));
47542
+ if (!resolved2.ok) return json3(501, { error: `member_auth_${resolved2.error}`, app: app2 });
47352
47543
  const returnTo = safeReturnPath(url.searchParams.get("return"), `/preview/a/${encodeURIComponent(app2)}`);
47353
47544
  const state = randomToken(16);
47354
47545
  const pkce = await generatePkce();
47355
47546
  let authUrl;
47356
47547
  try {
47357
- const visitor = await webwixTokens.token(resolved.config.clientId);
47548
+ const visitor = await webwixTokens.token(resolved2.config.clientId);
47358
47549
  authUrl = await hostedAuthUrl(
47359
- { ...resolved.config, mode: path.endsWith("/register") ? "signup" : "login", state, challenge: pkce.challenge },
47550
+ { ...resolved2.config, mode: path.endsWith("/register") ? "signup" : "login", state, challenge: pkce.challenge },
47360
47551
  visitor,
47361
47552
  webwixFetch
47362
47553
  );
@@ -47371,7 +47562,7 @@ ${releaseId}`;
47371
47562
  verifier: pkce.verifier,
47372
47563
  state,
47373
47564
  returnTo,
47374
- auth: resolved.config,
47565
+ auth: resolved2.config,
47375
47566
  expiresAt: Date.now() + PENDING_LOGIN_TTL_MS
47376
47567
  });
47377
47568
  return new Response(null, {
@@ -47462,9 +47653,9 @@ ${releaseId}`;
47462
47653
  return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
47463
47654
  }
47464
47655
  }
47465
- const resolved = wixClientIdOf(utf8Decode(cfgBytes));
47466
- if ("error" in resolved) {
47467
- return json3(501, { error: `webwix_bridge_${resolved.error}`, app: app2 });
47656
+ const resolved2 = wixClientIdOf(utf8Decode(cfgBytes));
47657
+ if ("error" in resolved2) {
47658
+ return json3(501, { error: `webwix_bridge_${resolved2.error}`, app: app2 });
47468
47659
  }
47469
47660
  const memberStore = memberSessions();
47470
47661
  const memberBoundApp = memberApp(request);
@@ -47484,11 +47675,11 @@ ${releaseId}`;
47484
47675
  }
47485
47676
  }
47486
47677
  try {
47487
- const token = await webwixTokens.token(resolved.clientId);
47678
+ const token = await webwixTokens.token(resolved2.clientId);
47488
47679
  const first = await wixVisitorCall(method, reqPath, body, token, webwixFetch, forwardedHeaders);
47489
47680
  if (first.status !== 401) return json3(200, first);
47490
- webwixTokens.invalidate(resolved.clientId);
47491
- const fresh = await webwixTokens.token(resolved.clientId);
47681
+ webwixTokens.invalidate(resolved2.clientId);
47682
+ const fresh = await webwixTokens.token(resolved2.clientId);
47492
47683
  return json3(200, await wixVisitorCall(method, reqPath, body, fresh, webwixFetch, forwardedHeaders));
47493
47684
  } catch (e) {
47494
47685
  const msg = String(e?.message ?? e);
@@ -48348,18 +48539,18 @@ function openBrowser(url) {
48348
48539
  }
48349
48540
  }
48350
48541
  async function runPackage(source, opts = {}) {
48351
- const resolved = await resolvePackage(source, opts.workDir);
48542
+ const resolved2 = await resolvePackage(source, opts.workDir);
48352
48543
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
48353
48544
  if (!opts.spa && assets.size === 0) {
48354
- if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
48545
+ if (resolved2.temp) rmSync8(resolved2.temp, { recursive: true, force: true });
48355
48546
  throw new Error(NO_SPA_MESSAGE);
48356
48547
  }
48357
48548
  const handler = makePackageRunHandler({
48358
- releaseRoot: resolved.releaseRoot,
48359
- app: resolved.app,
48549
+ releaseRoot: resolved2.releaseRoot,
48550
+ app: resolved2.app,
48360
48551
  assets,
48361
48552
  chrome: opts.chrome,
48362
- header: resolved.header
48553
+ header: resolved2.header
48363
48554
  });
48364
48555
  const server = nodeAdapter(handler);
48365
48556
  const host = opts.host ?? "127.0.0.1";
@@ -48371,17 +48562,17 @@ async function runPackage(source, opts = {}) {
48371
48562
  });
48372
48563
  });
48373
48564
  const origin = `http://${host}:${port}`;
48374
- const url = opts.spa ? `${packageUrl(opts.spa, resolved.app, opts)}${opts.surface ? "&" : "?"}api=${encodeURIComponent(origin)}` : packageUrl(origin, resolved.app, opts);
48565
+ const url = opts.spa ? `${packageUrl(opts.spa, resolved2.app, opts)}${opts.surface ? "&" : "?"}api=${encodeURIComponent(origin)}` : packageUrl(origin, resolved2.app, opts);
48375
48566
  if (opts.open) openBrowser(url);
48376
48567
  return {
48377
- app: resolved.app,
48378
- releaseId: resolved.releaseId,
48568
+ app: resolved2.app,
48569
+ releaseId: resolved2.releaseId,
48379
48570
  port,
48380
48571
  url,
48381
- warnings: resolved.warnings,
48572
+ warnings: resolved2.warnings,
48382
48573
  close: () => new Promise((done) => {
48383
48574
  server.close(() => {
48384
- if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
48575
+ if (resolved2.temp) rmSync8(resolved2.temp, { recursive: true, force: true });
48385
48576
  done();
48386
48577
  });
48387
48578
  })
@@ -57933,9 +58124,9 @@ async function cmsIssues(dir, app, strict, opts) {
57933
58124
  try {
57934
58125
  const cfg = await loadAppConfigModule(dir);
57935
58126
  if (cfg) {
57936
- const resolved = mergeDataResources({ cms: cfg.cms, data: cfg.data });
57937
- data = { kv: resolved.kv, collections: resolved.collections, ...resolved.memberGated ? { memberGated: true } : {} };
57938
- cms = { collections: resolved.collections, ...resolved.memberGated ? { memberGated: true } : {} };
58127
+ const resolved2 = mergeDataResources({ cms: cfg.cms, data: cfg.data });
58128
+ data = { kv: resolved2.kv, collections: resolved2.collections, ...resolved2.memberGated ? { memberGated: true } : {} };
58129
+ cms = { collections: resolved2.collections, ...resolved2.memberGated ? { memberGated: true } : {} };
57939
58130
  bootAsVisitor = bootsAsVisitor(cfg.auth);
57940
58131
  hasSignInSurface = !!cfg.screens && cfg.screens.signIn !== false;
57941
58132
  }
@@ -60012,8 +60203,8 @@ async function loadDataResources(dir) {
60012
60203
  try {
60013
60204
  const cfg = await loadAppConfigModule2(dir);
60014
60205
  if (!cfg?.cms && !cfg?.data) return void 0;
60015
- const resolved = mergeDataResources({ cms: cfg.cms, data: cfg.data });
60016
- return { kv: resolved.kv, collections: resolved.collections, ...resolved.memberGated ? { memberGated: true } : {} };
60206
+ const resolved2 = mergeDataResources({ cms: cfg.cms, data: cfg.data });
60207
+ return { kv: resolved2.kv, collections: resolved2.collections, ...resolved2.memberGated ? { memberGated: true } : {} };
60017
60208
  } catch (e) {
60018
60209
  throw new ConfigLoadError(p, e);
60019
60210
  }
@@ -62303,8 +62494,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
62303
62494
  if (flags.browser === true) {
62304
62495
  const { runInBrowser: runInBrowser2 } = await Promise.resolve().then(() => (init_run_browser(), run_browser_exports));
62305
62496
  const { resolvePackage: resolvePackage2 } = await Promise.resolve().then(() => (init_run(), run_exports));
62306
- const resolved = await resolvePackage2(source);
62307
- const run2 = await runInBrowser2(resolved.releaseRoot, resolved.app, resolved.header, {
62497
+ const resolved2 = await resolvePackage2(source);
62498
+ const run2 = await runInBrowser2(resolved2.releaseRoot, resolved2.app, resolved2.header, {
62308
62499
  ...port !== void 0 ? { port } : {},
62309
62500
  chrome: chromeArg,
62310
62501
  open: flags["no-open"] !== true
@@ -63537,17 +63728,17 @@ ${label2}`);
63537
63728
  const target = str5(flags.target) ?? process.env.HIMI_SERVE_TARGET ?? "local";
63538
63729
  const timeoutMs = Number(str5(flags.timeout)) > 0 ? Number(str5(flags.timeout)) : DOCTOR_TIMEOUT_MS;
63539
63730
  const dataUrl = str5(flags["data-url"]) ?? process.env.HIMI_DATA_URL ?? PUBLIC_WIX_API_BASE;
63540
- let resolved;
63731
+ let resolved2;
63541
63732
  let serveUrl = "";
63542
63733
  let targetError;
63543
63734
  try {
63544
- resolved = resolveTarget({
63735
+ resolved2 = resolveTarget({
63545
63736
  target: str5(flags.target),
63546
63737
  serveUrl: str5(flags["serve-url"]),
63547
63738
  controlUrl: str5(flags["control-url"]),
63548
63739
  controlToken: str5(flags["control-token"])
63549
63740
  });
63550
- serveUrl = resolved.serve;
63741
+ serveUrl = resolved2.serve;
63551
63742
  } catch (e) {
63552
63743
  targetError = e.message;
63553
63744
  }
@@ -63557,9 +63748,9 @@ ${label2}`);
63557
63748
  flags["skip-version-check"] === true ? Promise.resolve(void 0) : doctorVersionReport(cliVersion())
63558
63749
  ]);
63559
63750
  const dpxPath = dpxSessionTokenPath();
63560
- const tokenHealth = inspectControlToken(resolved?.controlToken);
63561
- if (tokenHealth.present && tokenHealth.valid && serve.reachable && resolved?.control && resolved.controlToken) {
63562
- const probed = await probeControlToken(resolved.control, resolved.controlToken, { timeoutMs });
63751
+ const tokenHealth = inspectControlToken(resolved2?.controlToken);
63752
+ if (tokenHealth.present && tokenHealth.valid && serve.reachable && resolved2?.control && resolved2.controlToken) {
63753
+ const probed = await probeControlToken(resolved2.control, resolved2.controlToken, { timeoutMs });
63563
63754
  if (probed.unauthorized) {
63564
63755
  tokenHealth.valid = false;
63565
63756
  tokenHealth.hint = STALE_TOKEN_HINT;
@@ -66,9 +66,15 @@ CLI orchestration: `tools/himi-cli/src/test.ts`.
66
66
 
67
67
  ## Typed form journeys
68
68
 
69
- The automatic form axis intentionally dispatches the descriptor's default (often empty)
70
- value. For a flow where the real proof is **typed value → submit → visible completion**,
71
- add a short screen-local journey to `himi-test.json`:
69
+ The crawl types into a control **only when it can read a legal value off the app itself** — an id
70
+ from the control's own `options`/`optionsPath` that is not the one selected, or a word from the
71
+ booted worker's own seeded state that is not what the field already shows — and only for a control
72
+ the payload contract names. A `Slider`, `Stepper`, `Toggle` or `DatePicker` has no such source, so
73
+ those still dispatch with the descriptor's default (often empty) value, and the gap ledger says so
74
+ per screen.
75
+
76
+ For a flow where the real proof is **typed value → submit → visible completion** — several fields,
77
+ in order, ending in a rendered result — add a short screen-local journey to `himi-test.json`:
72
78
 
73
79
  ```json
74
80
  {
@@ -111,6 +117,7 @@ Only **unambiguous** defects, so a green run stays worth trusting:
111
117
  | `refresh-not-idempotent` | **warning** | `refresh` from a fresh boot settles somewhere other than the boot did, on identical data — usually a refresh that appends instead of replacing. |
112
118
  | `list-shrank-on-load-more` | **warning** | A "load more" returned FEWER rows than before it ran: the new page replaced the list instead of extending it. |
113
119
  | `list-grew-on-filter` | **warning** | A filter, search or sort made a list longer. Narrowing can reorder or remove, never add. |
120
+ | `typed-value-ignored` | **warning** | The crawl typed the value a control really carries — the payload key every renderer injects for that control — and the dispatch changed **nothing**: no state, no navigation, no request. The value is read off the app itself (an id from the control's own options, or a word from the worker's seeded state) and is always one the control is *not* already showing, so a reducer that ignores it cannot work on device. A warning because the input is the crawl's: a reducer that legitimately no-ops on a value is possible, and `himi-test.json` `skip[]` takes the invariant. |
114
121
 
115
122
  **Deliberately never reported:** an empty collection · an `error` state (often the correct
116
123
  answer to empty input) · a `null` optional · whether a nav target *exists* (approximating
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.833.0",
3
+ "version": "0.834.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": [
@@ -63,5 +63,5 @@
63
63
  "artifactId": "himalaya-cli"
64
64
  }
65
65
  },
66
- "falconPackageHash": "a2c1ef13eceb008115d02b8e16b9dd82c4a1040e822600be9b93647c"
66
+ "falconPackageHash": "893b5fd00f0e645919e4a81af83fe3b09ab87b1e966341010aedd5a8"
67
67
  }