@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 +298 -110
- package/guides/himi-test.md +10 -3
- package/package.json +2 -2
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
|
|
5695
|
-
return
|
|
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
|
|
7005
|
-
if (
|
|
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 "${
|
|
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
|
|
19052
|
-
if (!
|
|
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(
|
|
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:
|
|
19069
|
-
hint: `add "${
|
|
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
|
|
24225
|
-
if (
|
|
24226
|
-
const l =
|
|
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
|
|
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(
|
|
27800
|
+
if (touched.current && bag && fieldId) bag.set(fieldId, encodeToggleFieldValue(resolved2));
|
|
27801
27801
|
setFormOn(null);
|
|
27802
|
-
}, [
|
|
27803
|
-
const on3 = inForm && formOn !== null ? formOn :
|
|
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
|
|
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] =
|
|
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
|
|
29811
|
+
const resolved2 = resolveItemDeep2(action, ctx);
|
|
29812
29812
|
ctx.onAction({
|
|
29813
|
-
...
|
|
29814
|
-
args: { ...
|
|
29815
|
-
params: { ...
|
|
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
|
|
29920
|
-
if (
|
|
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
|
|
30289
|
-
const s =
|
|
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
|
|
30825
|
-
return isBinding(v) ? asTextL10n(
|
|
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
|
|
30845
|
+
const resolved2 = { ...live2 };
|
|
30846
30846
|
for (const [k, v] of Object.entries(params)) {
|
|
30847
|
-
if (typeof v === "string" && v.startsWith("$item"))
|
|
30847
|
+
if (typeof v === "string" && v.startsWith("$item")) resolved2[k] = resolveScalarStatic(v, ctx);
|
|
30848
30848
|
}
|
|
30849
|
-
return /* @__PURE__ */ jsx6(Fragment3, { children: formatInterpolated(pattern, params,
|
|
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
|
|
30857
|
-
return
|
|
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
|
|
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
|
|
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
|
|
33125
|
-
if (!
|
|
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,
|
|
33128
|
-
lng:
|
|
33129
|
-
z: Math.max(1, Math.min(19,
|
|
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
|
|
34102
|
-
if (typeof
|
|
34103
|
-
if (context.insideMediaProperty) context.values[path] =
|
|
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(
|
|
34107
|
-
|
|
34106
|
+
if (Array.isArray(resolved2)) {
|
|
34107
|
+
resolved2.forEach((item, index) => collectResolvedMediaValues(item, `${path}[${index}]`, context));
|
|
34108
34108
|
return;
|
|
34109
34109
|
}
|
|
34110
|
-
if (
|
|
34111
|
-
collectResolvedMediaRecord(
|
|
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
|
|
34741
|
-
if (
|
|
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
|
|
36288
|
-
tokens =
|
|
36289
|
-
motionToggles =
|
|
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
|
|
38485
|
+
const resolved2 = netMocksDisabled ? null : resolveNetMocks(
|
|
38486
38486
|
netMocksPath ? readNetMocksFile(netMocksPath) : null,
|
|
38487
38487
|
state.app?.meta.devGateway
|
|
38488
38488
|
);
|
|
38489
|
-
if (
|
|
38490
|
-
const seeded = applyNetMocks(state.wix,
|
|
38491
|
-
const from =
|
|
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
|
|
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
|
-
|
|
39495
|
+
resolved2.push({ ref, url: addressed.url, sri: addressed.sri });
|
|
39496
39496
|
}
|
|
39497
|
-
for (const { ref, url, sri: integrity2 } of
|
|
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
|
-
|
|
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
|
|
41410
|
+
const resolved2 = resolveActionServiceParams(
|
|
41259
41411
|
{ actionId: site.actionId, params: site.params, args: site.args },
|
|
41260
41412
|
provider
|
|
41261
41413
|
);
|
|
41262
|
-
const merged = { ...
|
|
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
|
|
41464
|
-
const after = { ...
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
45285
|
-
if (
|
|
45286
|
-
return
|
|
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
|
|
47354
|
-
if (!
|
|
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(
|
|
47548
|
+
const visitor = await webwixTokens.token(resolved2.config.clientId);
|
|
47361
47549
|
authUrl = await hostedAuthUrl(
|
|
47362
|
-
{ ...
|
|
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:
|
|
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
|
|
47469
|
-
if ("error" in
|
|
47470
|
-
return json3(501, { error: `webwix_bridge_${
|
|
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(
|
|
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(
|
|
47494
|
-
const fresh = await webwixTokens.token(
|
|
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
|
|
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 (
|
|
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:
|
|
48362
|
-
app:
|
|
48549
|
+
releaseRoot: resolved2.releaseRoot,
|
|
48550
|
+
app: resolved2.app,
|
|
48363
48551
|
assets,
|
|
48364
48552
|
chrome: opts.chrome,
|
|
48365
|
-
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,
|
|
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:
|
|
48381
|
-
releaseId:
|
|
48568
|
+
app: resolved2.app,
|
|
48569
|
+
releaseId: resolved2.releaseId,
|
|
48382
48570
|
port,
|
|
48383
48571
|
url,
|
|
48384
|
-
warnings:
|
|
48572
|
+
warnings: resolved2.warnings,
|
|
48385
48573
|
close: () => new Promise((done) => {
|
|
48386
48574
|
server.close(() => {
|
|
48387
|
-
if (
|
|
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
|
|
57940
|
-
data = { kv:
|
|
57941
|
-
cms = { collections:
|
|
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
|
|
60019
|
-
return { kv:
|
|
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
|
|
62310
|
-
const run2 = await runInBrowser2(
|
|
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
|
|
63731
|
+
let resolved2;
|
|
63544
63732
|
let serveUrl = "";
|
|
63545
63733
|
let targetError;
|
|
63546
63734
|
try {
|
|
63547
|
-
|
|
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 =
|
|
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(
|
|
63564
|
-
if (tokenHealth.present && tokenHealth.valid && serve.reachable &&
|
|
63565
|
-
const probed = await probeControlToken(
|
|
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;
|
package/guides/himi-test.md
CHANGED
|
@@ -66,9 +66,15 @@ CLI orchestration: `tools/himi-cli/src/test.ts`.
|
|
|
66
66
|
|
|
67
67
|
## Typed form journeys
|
|
68
68
|
|
|
69
|
-
The
|
|
70
|
-
|
|
71
|
-
|
|
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.
|
|
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": "
|
|
66
|
+
"falconPackageHash": "893b5fd00f0e645919e4a81af83fe3b09ab87b1e966341010aedd5a8"
|
|
67
67
|
}
|