@wix/himalaya-cli 0.832.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
@@ -5691,8 +5691,8 @@ function unresolvedWixMediaReference(value, allowBareId = false) {
5691
5691
  if (reference.startsWith("wix:image://")) return reference;
5692
5692
  if (isBindingExpr(reference)) return null;
5693
5693
  if (!allowBareId && !DISTINCTIVE_WIX_MEDIA_ID.test(reference)) return null;
5694
- const resolved = wixMediaUrl(reference, null);
5695
- 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;
5696
5696
  }
5697
5697
  var MEDIA_NAMED_PROPERTY, MEDIA_LOCATION_SUFFIX, MEDIA_PATH_SUFFIX, DISTINCTIVE_WIX_MEDIA_ID, WIX_MEDIA_ORIGIN;
5698
5698
  var init_media_value = __esm({
@@ -7001,13 +7001,13 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
7001
7001
  const p = body.props ?? {};
7002
7002
  const cases = Array.isArray(p.cases) ? p.cases : [];
7003
7003
  const ids = cases.map((c) => c?.id).filter((x) => typeof x === "string");
7004
- const resolved = resolveCaseValue(p.casePath);
7005
- 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)) {
7006
7006
  issues.push({
7007
7007
  severity: "warning",
7008
7008
  pass: "bindings",
7009
7009
  path: typeof o.id === "string" ? o.id : at,
7010
- 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.`
7011
7011
  });
7012
7012
  }
7013
7013
  }
@@ -19048,8 +19048,8 @@ function resolveFamilyName(input) {
19048
19048
  return void 0;
19049
19049
  }
19050
19050
  function addReport(appDir2, family) {
19051
- const resolved = resolveFamilyName(family);
19052
- if (!resolved) {
19051
+ const resolved2 = resolveFamilyName(family);
19052
+ if (!resolved2) {
19053
19053
  return {
19054
19054
  ok: false,
19055
19055
  count: 0,
@@ -19058,15 +19058,15 @@ function addReport(appDir2, family) {
19058
19058
  hint: "run `himi fonts list` to see every family, or add it to stdlib/fonts/catalog.source.json"
19059
19059
  };
19060
19060
  }
19061
- const fam = findFamily(resolved);
19061
+ const fam = findFamily(resolved2);
19062
19062
  const bytes2 = fam?.faces.reduce((n, f) => n + f.bytes, 0) ?? 0;
19063
19063
  return {
19064
19064
  ok: true,
19065
19065
  count: 1,
19066
19066
  totalBytes: bytes2,
19067
19067
  problems: [],
19068
- families: [{ family: resolved, license: fam?.license.id ?? "system", copyright: fam?.license.copyright, kb: Math.round(bytes2 / 1024) }],
19069
- 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}` : ""}`
19070
19070
  };
19071
19071
  }
19072
19072
  var DEFAULT_ASSET_BUDGET_BYTES;
@@ -24221,9 +24221,9 @@ function evalEnvExpr(raw, env) {
24221
24221
  return (parsed.op === "==" ? equal : !equal) ? "true" : "false";
24222
24222
  }
24223
24223
  function envHidden(raw, env) {
24224
- const resolved = evalEnvExpr(raw, env);
24225
- if (resolved === void 0) return void 0;
24226
- 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();
24227
24227
  return l === "true" || l === "1";
24228
24228
  }
24229
24229
  var ENV_SENTINEL;
@@ -27790,17 +27790,17 @@ var init_controls = __esm({
27790
27790
  A11ySwitch = ({ props, ctx, wrap }) => {
27791
27791
  const C = ctx.color;
27792
27792
  const bound = useResolvedScalar(props.valuePath, ctx);
27793
- 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";
27794
27794
  const bag = React3.useContext(FormValuesContext);
27795
27795
  const fieldId = props.__formFieldId;
27796
27796
  const inForm = Boolean(bag && fieldId);
27797
27797
  const [formOn, setFormOn] = React3.useState(null);
27798
27798
  const touched = React3.useRef(false);
27799
27799
  React3.useEffect(() => {
27800
- if (touched.current && bag && fieldId) bag.set(fieldId, encodeToggleFieldValue(resolved));
27800
+ if (touched.current && bag && fieldId) bag.set(fieldId, encodeToggleFieldValue(resolved2));
27801
27801
  setFormOn(null);
27802
- }, [resolved]);
27803
- const on3 = inForm && formOn !== null ? formOn : resolved;
27802
+ }, [resolved2]);
27803
+ const on3 = inForm && formOn !== null ? formOn : resolved2;
27804
27804
  const ruleKey = props.validation ? JSON.stringify(props.validation) : "";
27805
27805
  React3.useEffect(() => {
27806
27806
  if (!bag || !fieldId) return;
@@ -29342,9 +29342,9 @@ function useResolvedMediaItems(items, ctx) {
29342
29342
  for (const f of MEDIA_ITEM_BINDABLE) {
29343
29343
  const v = it[f];
29344
29344
  if (typeof v !== "string" || !isBinding(v)) continue;
29345
- 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);
29346
29346
  out = out ?? { ...it };
29347
- out[f] = resolved;
29347
+ out[f] = resolved2;
29348
29348
  }
29349
29349
  return out ?? it;
29350
29350
  }), [items, values, ctx]);
@@ -29808,11 +29808,11 @@ function actionTextButton(ctx, action, label2, color, extra) {
29808
29808
  }
29809
29809
  function dispatchCalendarAction(ctx, action, extra) {
29810
29810
  if (!ctx.onAction || !action) return;
29811
- const resolved = resolveItemDeep2(action, ctx);
29811
+ const resolved2 = resolveItemDeep2(action, ctx);
29812
29812
  ctx.onAction({
29813
- ...resolved,
29814
- args: { ...resolved?.args ?? {}, ...extra },
29815
- 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)])) }
29816
29816
  });
29817
29817
  }
29818
29818
  function calKeyActivate(enabled, activate) {
@@ -29916,8 +29916,8 @@ function renderNodeInner(node, ctx) {
29916
29916
  }
29917
29917
  const accessibilityLabel = node?.modifiers?.accessibilityLabel ?? node?.modifiers?.accessibility_label;
29918
29918
  if (accessibilityLabel != null) {
29919
- const resolved = resolveScalarStatic(accessibilityLabel, ctx);
29920
- 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);
29921
29921
  }
29922
29922
  ensurePressStyles();
29923
29923
  extra["data-himalaya-tap"] = "1";
@@ -30285,8 +30285,8 @@ function renderInner(node, ctx) {
30285
30285
  case "Spacer": {
30286
30286
  if (props.collapseWhenEmpty === true) {
30287
30287
  const raw = props.value;
30288
- const resolved = typeof raw === "string" && isBinding(raw) ? resolveScalarStatic(raw, ctx) : raw;
30289
- 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);
30290
30290
  if (!s || s === "\u2014") return null;
30291
30291
  }
30292
30292
  return /* @__PURE__ */ jsx6("div", { style: { flex: 1 } });
@@ -30821,8 +30821,8 @@ var init_renderNode = __esm({
30821
30821
  asTextL10n = (v, ctx) => typeof v === "string" && v.startsWith(TRANSLATION_PREFIX) ? asText2(resolveTranslation(v, ctx.catalog)) : asText2(v);
30822
30822
  asBoundText = (v, ctx) => isBinding(v) ? asTextL10n(resolveScalarStatic(v, ctx) ?? "", ctx) : asText2(v);
30823
30823
  useBoundString = (v, ctx) => {
30824
- const resolved = useResolvedScalar(v, ctx);
30825
- return isBinding(v) ? asTextL10n(resolved ?? "", ctx) : asText2(v);
30824
+ const resolved2 = useResolvedScalar(v, ctx);
30825
+ return isBinding(v) ? asTextL10n(resolved2 ?? "", ctx) : asText2(v);
30826
30826
  };
30827
30827
  InterpolatedTextView = ({ pattern, params, ctx }) => {
30828
30828
  const bound = Object.entries(params).filter(
@@ -30842,19 +30842,19 @@ var init_renderNode = __esm({
30842
30842
  );
30843
30843
  return () => unsubs.forEach((u) => u());
30844
30844
  }, [ctx.provider, subKey]);
30845
- const resolved = { ...live2 };
30845
+ const resolved2 = { ...live2 };
30846
30846
  for (const [k, v] of Object.entries(params)) {
30847
- 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);
30848
30848
  }
30849
- return /* @__PURE__ */ jsx6(Fragment3, { children: formatInterpolated(pattern, params, resolved, ctx) });
30849
+ return /* @__PURE__ */ jsx6(Fragment3, { children: formatInterpolated(pattern, params, resolved2, ctx) });
30850
30850
  };
30851
30851
  txt = (v, ctx) => {
30852
30852
  if (!isBinding(v)) return asText2(v);
30853
30853
  if (v.startsWith(TRANSLATION_PREFIX)) return asText2(resolveTranslation(v, ctx.catalog));
30854
30854
  if (v.startsWith("$item")) {
30855
30855
  const key2 = v.replace(/^\$item\.?/, "");
30856
- const resolved = ctx.itemScope ? key2 ? ctx.itemScope[key2] : ctx.itemScope : void 0;
30857
- 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);
30858
30858
  }
30859
30859
  if (ctx.provider) return /* @__PURE__ */ jsx6(Bound, { ctx, binding: v, render: (val) => asTextL10n(val, ctx) });
30860
30860
  return bindingPlaceholder(v, ctx);
@@ -31005,11 +31005,11 @@ var init_renderNode = __esm({
31005
31005
  };
31006
31006
  resolvedComponentId = (id, ctx) => {
31007
31007
  if (typeof id !== "string" || !id) return void 0;
31008
- const resolved = id.replace(/\$item(?:\.[A-Za-z0-9_]+)*/g, (binding2) => {
31008
+ const resolved2 = id.replace(/\$item(?:\.[A-Za-z0-9_]+)*/g, (binding2) => {
31009
31009
  const value = resolveScalarStatic(binding2, ctx);
31010
31010
  return value == null ? binding2 : String(value);
31011
31011
  });
31012
- return resolved.includes("$item") ? void 0 : resolved;
31012
+ return resolved2.includes("$item") ? void 0 : resolved2;
31013
31013
  };
31014
31014
  directServiceBindings = (node) => {
31015
31015
  const out = /* @__PURE__ */ new Set();
@@ -33121,12 +33121,12 @@ var init_renderNode = __esm({
33121
33121
  const cLat = userCam?.lat ?? baseLat;
33122
33122
  const cLng = userCam?.lng ?? baseLng;
33123
33123
  React5.useEffect(() => {
33124
- const resolved = resolveCamera(commandedCamera, cLat, cLng, z);
33125
- if (!resolved) return;
33124
+ const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z);
33125
+ if (!resolved2) return;
33126
33126
  setUserCam({
33127
- lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved.latitude)),
33128
- lng: resolved.longitude,
33129
- 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))
33130
33130
  });
33131
33131
  }, [commandedCamera]);
33132
33132
  const originX = mercatorX(cLng, z) - W / 2;
@@ -34098,17 +34098,17 @@ function collectResolvedMediaRecord(record2, path, context) {
34098
34098
  }
34099
34099
  }
34100
34100
  function collectResolvedMediaValues(value, path, context) {
34101
- const resolved = typeof value === "string" ? resolveTreeScalar(value, context.provider, context.itemScope) : value;
34102
- if (typeof resolved === "string") {
34103
- 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;
34104
34104
  return;
34105
34105
  }
34106
- if (Array.isArray(resolved)) {
34107
- resolved.forEach((item, index) => collectResolvedMediaValues(item, `${path}[${index}]`, context));
34106
+ if (Array.isArray(resolved2)) {
34107
+ resolved2.forEach((item, index) => collectResolvedMediaValues(item, `${path}[${index}]`, context));
34108
34108
  return;
34109
34109
  }
34110
- if (resolved && typeof resolved === "object") {
34111
- collectResolvedMediaRecord(resolved, path, context);
34110
+ if (resolved2 && typeof resolved2 === "object") {
34111
+ collectResolvedMediaRecord(resolved2, path, context);
34112
34112
  }
34113
34113
  }
34114
34114
  function collectComponentMediaValues(type, props, context) {
@@ -34737,8 +34737,8 @@ function endpointErrors(endpoint, index, options) {
34737
34737
  if (typeof endpoint.pathPrefix !== "string" || !endpoint.pathPrefix.startsWith("/") || endpoint.pathPrefix.startsWith("//")) {
34738
34738
  errors.push(`${at}.pathPrefix must be an absolute pathname boundary`);
34739
34739
  } else if (origin) {
34740
- const resolved = new URL(endpoint.pathPrefix, origin);
34741
- 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) {
34742
34742
  errors.push(`${at}.pathPrefix must not contain a query, fragment, host, or dot-segment`);
34743
34743
  }
34744
34744
  }
@@ -36284,9 +36284,9 @@ function effectiveAppTokens(req, state) {
36284
36284
  if (motionDefs.length) {
36285
36285
  const cfg = currentFlagConfig(state);
36286
36286
  const assignments = evaluateAll(motionDefs, evalContextFromReq(req, state.appName), cfg?.overrides);
36287
- const resolved = applyMotionFlagOverride(tokens, assignments);
36288
- tokens = resolved.tokens;
36289
- motionToggles = resolved.togglesApplied;
36287
+ const resolved2 = applyMotionFlagOverride(tokens, assignments);
36288
+ tokens = resolved2.tokens;
36289
+ motionToggles = resolved2.togglesApplied;
36290
36290
  }
36291
36291
  } catch {
36292
36292
  }
@@ -38482,13 +38482,13 @@ function createDevServer(opts = {}) {
38482
38482
  const netMocksDisabled = opts.netMocks === false;
38483
38483
  const explicitNetMocksPath = typeof opts.netMocks === "string" ? opts.netMocks : process.env.HIMALAYA_NET_MOCKS;
38484
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);
38485
- const resolved = netMocksDisabled ? null : resolveNetMocks(
38485
+ const resolved2 = netMocksDisabled ? null : resolveNetMocks(
38486
38486
  netMocksPath ? readNetMocksFile(netMocksPath) : null,
38487
38487
  state.app?.meta.devGateway
38488
38488
  );
38489
- if (resolved) {
38490
- const seeded = applyNetMocks(state.wix, resolved.mocks);
38491
- 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`;
38492
38492
  console.error(`[himalaya-dev] net-mocks: seeded ${seeded.rules} rule(s), mode=${seeded.mode} from ${from}`);
38493
38493
  }
38494
38494
  const appScenario = state.app?.meta.devGateway;
@@ -39486,15 +39486,15 @@ async function withStoreNavBundle(text2, address) {
39486
39486
  (r) => !!r && typeof r === "object" && typeof r.url === "string"
39487
39487
  );
39488
39488
  if (refs.length === 0) return text2;
39489
- const resolved = [];
39489
+ const resolved2 = [];
39490
39490
  for (const ref of refs) {
39491
39491
  const name = bundleNameFromUrl(ref.url);
39492
39492
  if (!name) return text2;
39493
39493
  const addressed = await address(name);
39494
39494
  if (!addressed) return text2;
39495
- resolved.push({ ref, url: addressed.url, sri: addressed.sri });
39495
+ resolved2.push({ ref, url: addressed.url, sri: addressed.sri });
39496
39496
  }
39497
- for (const { ref, url, sri: integrity2 } of resolved) {
39497
+ for (const { ref, url, sri: integrity2 } of resolved2) {
39498
39498
  ref.url = url;
39499
39499
  ref.integrity = integrity2;
39500
39500
  }
@@ -40530,6 +40530,140 @@ var init_capability_fixtures = __esm({
40530
40530
  }
40531
40531
  });
40532
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
+
40533
40667
  // ../../core/dev-server/src/crawl-relations.ts
40534
40668
  function inversePartner(action, declared) {
40535
40669
  if (/^toggle/i.test(action)) return null;
@@ -40688,11 +40822,15 @@ __export(screen_crawl_exports, {
40688
40822
  });
40689
40823
  function actionSites(payload) {
40690
40824
  const out = [];
40691
- const visit = (node, ownerId, itemsPath) => {
40692
- 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));
40693
40827
  if (!node || typeof node !== "object") return;
40694
40828
  const rec = node;
40695
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;
40696
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;
40697
40835
  const ambient = ownItems ?? itemsPath;
40698
40836
  for (const [k, v] of Object.entries(rec)) {
@@ -40705,15 +40843,28 @@ function actionSites(payload) {
40705
40843
  actionId: a.actionId,
40706
40844
  params: a.params ?? {},
40707
40845
  ...a.args ? { args: a.args } : {},
40708
- ...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 } : {} } } : {}
40709
40851
  });
40710
40852
  }
40711
40853
  continue;
40712
40854
  }
40713
- 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
+ );
40714
40865
  }
40715
40866
  };
40716
- visit(payload, null, void 0);
40867
+ visit(payload, null, void 0, null, void 0);
40717
40868
  return out;
40718
40869
  }
40719
40870
  function actionSitesForDescriptor(descriptor) {
@@ -41251,15 +41402,16 @@ async function crawlScreenInner(opts) {
41251
41402
  const navEdges = [];
41252
41403
  const unobservedActions = [];
41253
41404
  let observations;
41405
+ let seedWords = [];
41254
41406
  const harvestStaticEdges = (state) => {
41255
41407
  const provider = new FakeServiceProvider(state);
41256
41408
  for (const site of sites) {
41257
41409
  if (site.actionId !== "himi.open") continue;
41258
- const resolved = resolveActionServiceParams(
41410
+ const resolved2 = resolveActionServiceParams(
41259
41411
  { actionId: site.actionId, params: site.params, args: site.args },
41260
41412
  provider
41261
41413
  );
41262
- const merged = { ...resolved.params ?? {}, ...resolved.args ?? {} };
41414
+ const merged = { ...resolved2.params ?? {}, ...resolved2.args ?? {} };
41263
41415
  const row0 = firstRowFor(site.itemsPath, (p) => provider.value(p));
41264
41416
  const resolveItem = (v) => {
41265
41417
  if (typeof v !== "string" || !v.startsWith("$item")) return v;
@@ -41460,8 +41612,8 @@ async function crawlScreenInner(opts) {
41460
41612
  const before = { ...site.params ?? {}, ...site.args ?? {} };
41461
41613
  const bound = Object.entries(before).filter(([, v]) => typeof v === "string" && v.startsWith("$service:"));
41462
41614
  if (!bound.length) continue;
41463
- const resolved = resolveActionServiceParams({ actionId: site.actionId, params: site.params, args: site.args }, provider);
41464
- 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 ?? {} };
41465
41617
  for (const [k, v] of bound) {
41466
41618
  if (!(k in after)) {
41467
41619
  findings.push({
@@ -41496,6 +41648,7 @@ async function crawlScreenInner(opts) {
41496
41648
  if (first.deadLifecycle) reportDeadLifecycle(first.deadLifecycle);
41497
41649
  check("boot", first.state, first.errors, first.defects);
41498
41650
  observations = collectObservations(descriptor, first.state);
41651
+ seedWords = seedTokens(first.state);
41499
41652
  harvestStaticEdges(first.state);
41500
41653
  drainWorkerEdges(first, "worker:boot");
41501
41654
  drainPollDirectives(first, "boot");
@@ -41574,16 +41727,19 @@ async function crawlScreenInner(opts) {
41574
41727
  continue;
41575
41728
  }
41576
41729
  const trigger = { tap: site.componentId, key: site.key, action: site.actionId };
41577
- const effective = effectiveSiteFor(site, snapshot(w).state);
41730
+ const preState = snapshot(w).state;
41731
+ const effective = effectiveSiteFor(site, preState);
41578
41732
  if (!effective) {
41579
41733
  actionsSkipped.push({ action: site.actionId, why: "no-row-value" });
41580
41734
  continue;
41581
41735
  }
41582
- 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);
41583
41739
  const callsBefore = w.calls.length;
41584
41740
  const errors = [];
41585
41741
  try {
41586
- await handle.dispatch(parsed.action, ...workerArgs(effective));
41742
+ await handle.dispatch(parsed.action, ...workerArgs(dispatched));
41587
41743
  } catch (e) {
41588
41744
  errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e)}`, ...e.stack ? { stack: e.stack } : {} });
41589
41745
  }
@@ -41594,11 +41750,25 @@ async function crawlScreenInner(opts) {
41594
41750
  drainWorkerEdges(w, `worker:${site.actionId}`);
41595
41751
  drainPollDirectives(w, trigger);
41596
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
+ }
41597
41767
  unobservedActions.push({
41598
41768
  action: site.actionId,
41599
41769
  componentId: site.componentId,
41600
41770
  key: site.key,
41601
- argless: workerArgs(effective).length === 0
41771
+ argless: workerArgs(dispatched).length === 0
41602
41772
  });
41603
41773
  }
41604
41774
  } finally {
@@ -41948,6 +42118,23 @@ function effectiveSiteForRow(site, row) {
41948
42118
  }
41949
42119
  return { ...site, params: substituted, args: void 0 };
41950
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
+ }
41951
42138
  function isRowBound(site) {
41952
42139
  const payload = { ...site.params ?? {}, ...site.args ?? {} };
41953
42140
  return Object.values(payload).some((v) => typeof v === "string" && (v === "$item" || v.startsWith("$item.")));
@@ -42154,6 +42341,7 @@ var init_screen_crawl = __esm({
42154
42341
  init_actionParams();
42155
42342
  init_implications();
42156
42343
  init_capability_fixtures();
42344
+ init_crawl_input();
42157
42345
  init_crawl_relations();
42158
42346
  ACTION_KEYS = [
42159
42347
  "action",
@@ -45281,9 +45469,9 @@ function assertKey(key2) {
45281
45469
  if (typeof key2 !== "string" || key2.length < 1 || key2.length > 256) throw new Error("KV key must contain 1 to 256 characters");
45282
45470
  }
45283
45471
  function ttl(spec, value) {
45284
- const resolved = value ?? spec.defaultTtlSeconds;
45285
- 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}`);
45286
- 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;
45287
45475
  }
45288
45476
  function logicalCollection(spec, app) {
45289
45477
  return spec.wixId ?? ownedName(spec, app) ?? "";
@@ -47350,16 +47538,16 @@ ${releaseId}`;
47350
47538
  if (request.method !== "GET") return json3(405, { error: "method_not_allowed" });
47351
47539
  const cfg = await appConfigFor(app2, resolvePin(request, url));
47352
47540
  if (!cfg.ok) return cfg.response;
47353
- const resolved = wixMemberAuthOf(utf8Decode(cfg.bytes), callbackUrlFor(url));
47354
- 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 });
47355
47543
  const returnTo = safeReturnPath(url.searchParams.get("return"), `/preview/a/${encodeURIComponent(app2)}`);
47356
47544
  const state = randomToken(16);
47357
47545
  const pkce = await generatePkce();
47358
47546
  let authUrl;
47359
47547
  try {
47360
- const visitor = await webwixTokens.token(resolved.config.clientId);
47548
+ const visitor = await webwixTokens.token(resolved2.config.clientId);
47361
47549
  authUrl = await hostedAuthUrl(
47362
- { ...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 },
47363
47551
  visitor,
47364
47552
  webwixFetch
47365
47553
  );
@@ -47374,7 +47562,7 @@ ${releaseId}`;
47374
47562
  verifier: pkce.verifier,
47375
47563
  state,
47376
47564
  returnTo,
47377
- auth: resolved.config,
47565
+ auth: resolved2.config,
47378
47566
  expiresAt: Date.now() + PENDING_LOGIN_TTL_MS
47379
47567
  });
47380
47568
  return new Response(null, {
@@ -47465,9 +47653,9 @@ ${releaseId}`;
47465
47653
  return json3(502, { error: "webwix_bridge_upstream_failed", detail: msg.slice(0, 200) });
47466
47654
  }
47467
47655
  }
47468
- const resolved = wixClientIdOf(utf8Decode(cfgBytes));
47469
- if ("error" in resolved) {
47470
- 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 });
47471
47659
  }
47472
47660
  const memberStore = memberSessions();
47473
47661
  const memberBoundApp = memberApp(request);
@@ -47487,11 +47675,11 @@ ${releaseId}`;
47487
47675
  }
47488
47676
  }
47489
47677
  try {
47490
- const token = await webwixTokens.token(resolved.clientId);
47678
+ const token = await webwixTokens.token(resolved2.clientId);
47491
47679
  const first = await wixVisitorCall(method, reqPath, body, token, webwixFetch, forwardedHeaders);
47492
47680
  if (first.status !== 401) return json3(200, first);
47493
- webwixTokens.invalidate(resolved.clientId);
47494
- const fresh = await webwixTokens.token(resolved.clientId);
47681
+ webwixTokens.invalidate(resolved2.clientId);
47682
+ const fresh = await webwixTokens.token(resolved2.clientId);
47495
47683
  return json3(200, await wixVisitorCall(method, reqPath, body, fresh, webwixFetch, forwardedHeaders));
47496
47684
  } catch (e) {
47497
47685
  const msg = String(e?.message ?? e);
@@ -48351,18 +48539,18 @@ function openBrowser(url) {
48351
48539
  }
48352
48540
  }
48353
48541
  async function runPackage(source, opts = {}) {
48354
- const resolved = await resolvePackage(source, opts.workDir);
48542
+ const resolved2 = await resolvePackage(source, opts.workDir);
48355
48543
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
48356
48544
  if (!opts.spa && assets.size === 0) {
48357
- if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
48545
+ if (resolved2.temp) rmSync8(resolved2.temp, { recursive: true, force: true });
48358
48546
  throw new Error(NO_SPA_MESSAGE);
48359
48547
  }
48360
48548
  const handler = makePackageRunHandler({
48361
- releaseRoot: resolved.releaseRoot,
48362
- app: resolved.app,
48549
+ releaseRoot: resolved2.releaseRoot,
48550
+ app: resolved2.app,
48363
48551
  assets,
48364
48552
  chrome: opts.chrome,
48365
- header: resolved.header
48553
+ header: resolved2.header
48366
48554
  });
48367
48555
  const server = nodeAdapter(handler);
48368
48556
  const host = opts.host ?? "127.0.0.1";
@@ -48374,17 +48562,17 @@ async function runPackage(source, opts = {}) {
48374
48562
  });
48375
48563
  });
48376
48564
  const origin = `http://${host}:${port}`;
48377
- 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);
48378
48566
  if (opts.open) openBrowser(url);
48379
48567
  return {
48380
- app: resolved.app,
48381
- releaseId: resolved.releaseId,
48568
+ app: resolved2.app,
48569
+ releaseId: resolved2.releaseId,
48382
48570
  port,
48383
48571
  url,
48384
- warnings: resolved.warnings,
48572
+ warnings: resolved2.warnings,
48385
48573
  close: () => new Promise((done) => {
48386
48574
  server.close(() => {
48387
- if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
48575
+ if (resolved2.temp) rmSync8(resolved2.temp, { recursive: true, force: true });
48388
48576
  done();
48389
48577
  });
48390
48578
  })
@@ -57936,9 +58124,9 @@ async function cmsIssues(dir, app, strict, opts) {
57936
58124
  try {
57937
58125
  const cfg = await loadAppConfigModule(dir);
57938
58126
  if (cfg) {
57939
- const resolved = mergeDataResources({ cms: cfg.cms, data: cfg.data });
57940
- data = { kv: resolved.kv, collections: resolved.collections, ...resolved.memberGated ? { memberGated: true } : {} };
57941
- 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 } : {} };
57942
58130
  bootAsVisitor = bootsAsVisitor(cfg.auth);
57943
58131
  hasSignInSurface = !!cfg.screens && cfg.screens.signIn !== false;
57944
58132
  }
@@ -60015,8 +60203,8 @@ async function loadDataResources(dir) {
60015
60203
  try {
60016
60204
  const cfg = await loadAppConfigModule2(dir);
60017
60205
  if (!cfg?.cms && !cfg?.data) return void 0;
60018
- const resolved = mergeDataResources({ cms: cfg.cms, data: cfg.data });
60019
- 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 } : {} };
60020
60208
  } catch (e) {
60021
60209
  throw new ConfigLoadError(p, e);
60022
60210
  }
@@ -62306,8 +62494,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
62306
62494
  if (flags.browser === true) {
62307
62495
  const { runInBrowser: runInBrowser2 } = await Promise.resolve().then(() => (init_run_browser(), run_browser_exports));
62308
62496
  const { resolvePackage: resolvePackage2 } = await Promise.resolve().then(() => (init_run(), run_exports));
62309
- const resolved = await resolvePackage2(source);
62310
- 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, {
62311
62499
  ...port !== void 0 ? { port } : {},
62312
62500
  chrome: chromeArg,
62313
62501
  open: flags["no-open"] !== true
@@ -63540,17 +63728,17 @@ ${label2}`);
63540
63728
  const target = str5(flags.target) ?? process.env.HIMI_SERVE_TARGET ?? "local";
63541
63729
  const timeoutMs = Number(str5(flags.timeout)) > 0 ? Number(str5(flags.timeout)) : DOCTOR_TIMEOUT_MS;
63542
63730
  const dataUrl = str5(flags["data-url"]) ?? process.env.HIMI_DATA_URL ?? PUBLIC_WIX_API_BASE;
63543
- let resolved;
63731
+ let resolved2;
63544
63732
  let serveUrl = "";
63545
63733
  let targetError;
63546
63734
  try {
63547
- resolved = resolveTarget({
63735
+ resolved2 = resolveTarget({
63548
63736
  target: str5(flags.target),
63549
63737
  serveUrl: str5(flags["serve-url"]),
63550
63738
  controlUrl: str5(flags["control-url"]),
63551
63739
  controlToken: str5(flags["control-token"])
63552
63740
  });
63553
- serveUrl = resolved.serve;
63741
+ serveUrl = resolved2.serve;
63554
63742
  } catch (e) {
63555
63743
  targetError = e.message;
63556
63744
  }
@@ -63560,9 +63748,9 @@ ${label2}`);
63560
63748
  flags["skip-version-check"] === true ? Promise.resolve(void 0) : doctorVersionReport(cliVersion())
63561
63749
  ]);
63562
63750
  const dpxPath = dpxSessionTokenPath();
63563
- const tokenHealth = inspectControlToken(resolved?.controlToken);
63564
- if (tokenHealth.present && tokenHealth.valid && serve.reachable && resolved?.control && resolved.controlToken) {
63565
- 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 });
63566
63754
  if (probed.unauthorized) {
63567
63755
  tokenHealth.valid = false;
63568
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.832.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": "e11f7e039210de169e2608faa2fcb6cdbd90f8df91336bcba6398dbe"
66
+ "falconPackageHash": "893b5fd00f0e645919e4a81af83fe3b09ab87b1e966341010aedd5a8"
67
67
  }