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