@timeax/digital-service-engine 0.2.0 → 0.2.2
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/core/index.cjs +428 -141
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +17 -11
- package/dist/core/index.d.ts +17 -11
- package/dist/core/index.js +427 -141
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +627 -357
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +11 -0
- package/dist/react/index.d.ts +11 -0
- package/dist/react/index.js +627 -357
- package/dist/react/index.js.map +1 -1
- package/dist/schema/index.d.cts +17 -1
- package/dist/schema/index.d.ts +17 -1
- package/dist/workspace/index.cjs +270 -100
- package/dist/workspace/index.cjs.map +1 -1
- package/dist/workspace/index.d.cts +15 -0
- package/dist/workspace/index.d.ts +15 -0
- package/dist/workspace/index.js +270 -100
- package/dist/workspace/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(core_exports, {
|
|
|
26
26
|
createFallbackEditor: () => createFallbackEditor,
|
|
27
27
|
createNodeIndex: () => createNodeIndex,
|
|
28
28
|
filterServicesForVisibleGroup: () => filterServicesForVisibleGroup,
|
|
29
|
+
getAssignedServiceIds: () => getAssignedServiceIds,
|
|
29
30
|
getEligibleFallbacks: () => getEligibleFallbacks,
|
|
30
31
|
getFallbackRegistrationInfo: () => getFallbackRegistrationInfo,
|
|
31
32
|
normalise: () => normalise,
|
|
@@ -1231,6 +1232,9 @@ function toFiniteNumber(v) {
|
|
|
1231
1232
|
const n = Number(v);
|
|
1232
1233
|
return Number.isFinite(n) ? n : NaN;
|
|
1233
1234
|
}
|
|
1235
|
+
function isValidServiceIdRef(value) {
|
|
1236
|
+
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
1237
|
+
}
|
|
1234
1238
|
function constraintFitOk(svcMap, candidate, constraints) {
|
|
1235
1239
|
const cap = getServiceCapability(svcMap, candidate);
|
|
1236
1240
|
if (!cap) return false;
|
|
@@ -1239,18 +1243,32 @@ function constraintFitOk(svcMap, candidate, constraints) {
|
|
|
1239
1243
|
return !(constraints.cancel === true && !cap.cancel);
|
|
1240
1244
|
}
|
|
1241
1245
|
function getServiceCapability(svcMap, candidate) {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
if (
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1246
|
+
var _a;
|
|
1247
|
+
return (_a = getServiceCapabilityEntry(svcMap, candidate)) == null ? void 0 : _a.capability;
|
|
1248
|
+
}
|
|
1249
|
+
function getServiceCapabilityCanonicalRef(svcMap, candidate) {
|
|
1250
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1251
|
+
if (!entry) return void 0;
|
|
1252
|
+
return getCanonicalServiceRef(entry.key, entry.capability);
|
|
1253
|
+
}
|
|
1254
|
+
function getServiceCapabilityAliases(svcMap, candidate) {
|
|
1255
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1256
|
+
if (!entry) return [];
|
|
1257
|
+
return collectServiceRefAliases(entry.key, entry.capability);
|
|
1258
|
+
}
|
|
1259
|
+
function isSameServiceCapabilityRef(svcMap, left, right) {
|
|
1260
|
+
if (!isValidServiceIdRef(left) || !isValidServiceIdRef(right)) return false;
|
|
1261
|
+
const leftAliases = new Set(
|
|
1262
|
+
getServiceCapabilityAliases(svcMap, left).map((value) => String(value))
|
|
1263
|
+
);
|
|
1264
|
+
if (!leftAliases.size) {
|
|
1265
|
+
leftAliases.add(String(left));
|
|
1252
1266
|
}
|
|
1253
|
-
|
|
1267
|
+
const rightAliases = getServiceCapabilityAliases(svcMap, right);
|
|
1268
|
+
if (!rightAliases.length) {
|
|
1269
|
+
return leftAliases.has(String(right));
|
|
1270
|
+
}
|
|
1271
|
+
return rightAliases.some((value) => leftAliases.has(String(value)));
|
|
1254
1272
|
}
|
|
1255
1273
|
function normalizeRatePolicy(policy) {
|
|
1256
1274
|
var _a;
|
|
@@ -1286,18 +1304,84 @@ function rateOk(svcMap, candidate, primary, policy) {
|
|
|
1286
1304
|
if (!Number.isFinite(cRate) || !Number.isFinite(pRate)) return false;
|
|
1287
1305
|
return passesRatePolicy(policy.ratePolicy, pRate, cRate);
|
|
1288
1306
|
}
|
|
1307
|
+
function getServiceCapabilityEntry(svcMap, candidate) {
|
|
1308
|
+
if (candidate === void 0 || candidate === null) return void 0;
|
|
1309
|
+
const direct = svcMap[candidate];
|
|
1310
|
+
if (direct) {
|
|
1311
|
+
return { key: String(candidate), capability: direct };
|
|
1312
|
+
}
|
|
1313
|
+
const byString = svcMap[String(candidate)];
|
|
1314
|
+
if (byString) {
|
|
1315
|
+
return { key: String(candidate), capability: byString };
|
|
1316
|
+
}
|
|
1317
|
+
if (typeof candidate === "string") {
|
|
1318
|
+
const maybeNumber = Number(candidate);
|
|
1319
|
+
if (Number.isFinite(maybeNumber)) {
|
|
1320
|
+
const byNumber = svcMap[maybeNumber];
|
|
1321
|
+
if (byNumber) {
|
|
1322
|
+
return { key: String(maybeNumber), capability: byNumber };
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
const target = String(candidate);
|
|
1327
|
+
for (const [key, capability] of Object.entries(svcMap != null ? svcMap : {})) {
|
|
1328
|
+
if (collectServiceRefAliases(key, capability).some(
|
|
1329
|
+
(alias) => String(alias) === target
|
|
1330
|
+
)) {
|
|
1331
|
+
return { key, capability };
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
return void 0;
|
|
1335
|
+
}
|
|
1336
|
+
function collectServiceRefAliases(key, capability) {
|
|
1337
|
+
const out = [];
|
|
1338
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1339
|
+
const push = (value) => {
|
|
1340
|
+
if (!isValidServiceIdRef(value)) return;
|
|
1341
|
+
const normalized = normalizeServiceRef(value);
|
|
1342
|
+
if (!normalized) return;
|
|
1343
|
+
const aliasKey = String(normalized);
|
|
1344
|
+
if (seen.has(aliasKey)) return;
|
|
1345
|
+
seen.add(aliasKey);
|
|
1346
|
+
out.push(normalized);
|
|
1347
|
+
};
|
|
1348
|
+
push(getCanonicalServiceRef(key, capability));
|
|
1349
|
+
push(capability.service);
|
|
1350
|
+
push(capability.key);
|
|
1351
|
+
push(capability.id);
|
|
1352
|
+
return out;
|
|
1353
|
+
}
|
|
1354
|
+
function getCanonicalServiceRef(key, capability) {
|
|
1355
|
+
const explicitRefs = [capability.service, capability.key, capability.id];
|
|
1356
|
+
for (const ref of explicitRefs) {
|
|
1357
|
+
if (!isValidServiceIdRef(ref)) continue;
|
|
1358
|
+
if (String(ref) === key) {
|
|
1359
|
+
return ref;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
return normalizeServiceRef(key);
|
|
1363
|
+
}
|
|
1364
|
+
function normalizeServiceRef(value) {
|
|
1365
|
+
if (!isValidServiceIdRef(value)) return void 0;
|
|
1366
|
+
if (typeof value === "number") return value;
|
|
1367
|
+
const trimmed = value.trim();
|
|
1368
|
+
if (!trimmed) return void 0;
|
|
1369
|
+
const asNumber = Number(trimmed);
|
|
1370
|
+
if (Number.isFinite(asNumber) && String(asNumber) === trimmed) {
|
|
1371
|
+
return asNumber;
|
|
1372
|
+
}
|
|
1373
|
+
return trimmed;
|
|
1374
|
+
}
|
|
1289
1375
|
|
|
1290
1376
|
// src/core/validate/steps/rates.ts
|
|
1291
1377
|
function validateRates(v) {
|
|
1292
|
-
var _a, _b, _c
|
|
1293
|
-
const ratePolicy = normalizeRatePolicy(
|
|
1294
|
-
(_a = v.options.fallbackSettings) == null ? void 0 : _a.ratePolicy
|
|
1295
|
-
);
|
|
1378
|
+
var _a, _b, _c;
|
|
1379
|
+
const ratePolicy = normalizeRatePolicy(v.options.ratePolicy);
|
|
1296
1380
|
for (const f of v.fields) {
|
|
1297
1381
|
if (!isMultiField(f)) continue;
|
|
1298
1382
|
const baseRates = [];
|
|
1299
|
-
for (const o of (
|
|
1300
|
-
const role = (
|
|
1383
|
+
for (const o of (_a = f.options) != null ? _a : []) {
|
|
1384
|
+
const role = (_c = (_b = o.pricing_role) != null ? _b : f.pricing_role) != null ? _c : "base";
|
|
1301
1385
|
if (role !== "base") continue;
|
|
1302
1386
|
const sid = o.service_id;
|
|
1303
1387
|
if (!isServiceIdRef(sid)) continue;
|
|
@@ -2071,6 +2155,38 @@ function applyPolicies(errors, props, serviceMap, policies, fieldsVisibleUnder,
|
|
|
2071
2155
|
}
|
|
2072
2156
|
}
|
|
2073
2157
|
|
|
2158
|
+
// src/core/governance.ts
|
|
2159
|
+
var DEFAULT_FALLBACK_SETTINGS = {
|
|
2160
|
+
requireConstraintFit: true,
|
|
2161
|
+
ratePolicy: { kind: "lte_primary", pct: 5 },
|
|
2162
|
+
selectionStrategy: "priority",
|
|
2163
|
+
mode: "strict"
|
|
2164
|
+
};
|
|
2165
|
+
function resolveGlobalRatePolicy(options) {
|
|
2166
|
+
return normalizeRatePolicy(options.ratePolicy);
|
|
2167
|
+
}
|
|
2168
|
+
function resolveFallbackSettings(options) {
|
|
2169
|
+
var _a;
|
|
2170
|
+
return {
|
|
2171
|
+
...DEFAULT_FALLBACK_SETTINGS,
|
|
2172
|
+
...(_a = options.fallbackSettings) != null ? _a : {}
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
function mergeValidatorOptions(defaults = {}, overrides = {}) {
|
|
2176
|
+
var _a, _b, _c, _d;
|
|
2177
|
+
const mergedFallbackSettings = {
|
|
2178
|
+
...(_a = defaults.fallbackSettings) != null ? _a : {},
|
|
2179
|
+
...(_b = overrides.fallbackSettings) != null ? _b : {}
|
|
2180
|
+
};
|
|
2181
|
+
return {
|
|
2182
|
+
...defaults,
|
|
2183
|
+
...overrides,
|
|
2184
|
+
policies: (_c = overrides.policies) != null ? _c : defaults.policies,
|
|
2185
|
+
ratePolicy: (_d = overrides.ratePolicy) != null ? _d : defaults.ratePolicy,
|
|
2186
|
+
fallbackSettings: Object.keys(mergedFallbackSettings).length > 0 ? mergedFallbackSettings : void 0
|
|
2187
|
+
};
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2074
2190
|
// src/core/builder.ts
|
|
2075
2191
|
var import_lodash_es2 = require("lodash-es");
|
|
2076
2192
|
function createBuilder(opts = {}) {
|
|
@@ -2313,7 +2429,7 @@ var BuilderImpl = class {
|
|
|
2313
2429
|
return out;
|
|
2314
2430
|
}
|
|
2315
2431
|
errors() {
|
|
2316
|
-
return validate(this.props, this.options);
|
|
2432
|
+
return validate(this.props, mergeValidatorOptions({}, this.options));
|
|
2317
2433
|
}
|
|
2318
2434
|
getOptions() {
|
|
2319
2435
|
return (0, import_lodash_es2.cloneDeep)(this.options);
|
|
@@ -2600,11 +2716,14 @@ function readVisibilitySimOpts(ctx) {
|
|
|
2600
2716
|
};
|
|
2601
2717
|
}
|
|
2602
2718
|
function validate(props, ctx = {}) {
|
|
2603
|
-
var _a, _b, _c
|
|
2719
|
+
var _a, _b, _c;
|
|
2720
|
+
const options = mergeValidatorOptions({}, ctx);
|
|
2721
|
+
const fallbackSettings = resolveFallbackSettings(options);
|
|
2722
|
+
const ratePolicy = resolveGlobalRatePolicy(options);
|
|
2604
2723
|
const errors = [];
|
|
2605
|
-
const serviceMap = (_a =
|
|
2724
|
+
const serviceMap = (_a = options.serviceMap) != null ? _a : {};
|
|
2606
2725
|
const selectedKeys = new Set(
|
|
2607
|
-
(_b =
|
|
2726
|
+
(_b = options.selectedOptionKeys) != null ? _b : []
|
|
2608
2727
|
);
|
|
2609
2728
|
const tags = Array.isArray(props.filters) ? props.filters : [];
|
|
2610
2729
|
const fields = Array.isArray(props.fields) ? props.fields : [];
|
|
@@ -2614,8 +2733,12 @@ function validate(props, ctx = {}) {
|
|
|
2614
2733
|
for (const f of fields) fieldById.set(f.id, f);
|
|
2615
2734
|
const v = {
|
|
2616
2735
|
props,
|
|
2617
|
-
nodeMap: (_c =
|
|
2618
|
-
options:
|
|
2736
|
+
nodeMap: (_c = options.nodeMap) != null ? _c : buildNodeMap(props),
|
|
2737
|
+
options: {
|
|
2738
|
+
...options,
|
|
2739
|
+
ratePolicy,
|
|
2740
|
+
fallbackSettings
|
|
2741
|
+
},
|
|
2619
2742
|
errors,
|
|
2620
2743
|
serviceMap,
|
|
2621
2744
|
selectedKeys,
|
|
@@ -2630,7 +2753,7 @@ function validate(props, ctx = {}) {
|
|
|
2630
2753
|
validateIdentity(v);
|
|
2631
2754
|
validateOptionMaps(v);
|
|
2632
2755
|
v.fieldsVisibleUnder = createFieldsVisibleUnder(v);
|
|
2633
|
-
const visSim = readVisibilitySimOpts(
|
|
2756
|
+
const visSim = readVisibilitySimOpts(options);
|
|
2634
2757
|
validateVisibility(v, visSim);
|
|
2635
2758
|
applyPolicies(
|
|
2636
2759
|
v.errors,
|
|
@@ -2651,7 +2774,7 @@ function validate(props, ctx = {}) {
|
|
|
2651
2774
|
builder,
|
|
2652
2775
|
services: serviceMap,
|
|
2653
2776
|
tagId: tag.id,
|
|
2654
|
-
ratePolicy
|
|
2777
|
+
ratePolicy,
|
|
2655
2778
|
invalidFieldIds: v.invalidRateFieldIds
|
|
2656
2779
|
});
|
|
2657
2780
|
for (const diag of diags) {
|
|
@@ -2701,27 +2824,42 @@ var DEFAULT_SETTINGS = {
|
|
|
2701
2824
|
mode: "strict"
|
|
2702
2825
|
};
|
|
2703
2826
|
function resolveServiceFallback(params) {
|
|
2704
|
-
var _a, _b
|
|
2827
|
+
var _a, _b;
|
|
2705
2828
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
2706
2829
|
const { primary, nodeId, tagId, services } = params;
|
|
2707
|
-
const
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2830
|
+
const fallbackLists = listRegisteredFallbackCandidates(
|
|
2831
|
+
(_b = params.fallbacks) != null ? _b : {},
|
|
2832
|
+
primary,
|
|
2833
|
+
nodeId,
|
|
2834
|
+
services
|
|
2835
|
+
);
|
|
2836
|
+
const tried = /* @__PURE__ */ new Set();
|
|
2712
2837
|
const primaryRate = rateOf(services, primary);
|
|
2713
|
-
for (const list of
|
|
2714
|
-
for (const
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
if (
|
|
2838
|
+
for (const list of fallbackLists) {
|
|
2839
|
+
for (const candidate of list) {
|
|
2840
|
+
const candidateIdentity = getComparableServiceRefKey(
|
|
2841
|
+
services,
|
|
2842
|
+
candidate
|
|
2843
|
+
);
|
|
2844
|
+
if (tried.has(candidateIdentity)) continue;
|
|
2845
|
+
tried.add(candidateIdentity);
|
|
2846
|
+
const capability = getCap(services, candidate);
|
|
2847
|
+
if (!capability) continue;
|
|
2848
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
2849
|
+
continue;
|
|
2850
|
+
}
|
|
2851
|
+
if (!passesRate(s.ratePolicy, primaryRate, capability.rate)) {
|
|
2852
|
+
continue;
|
|
2853
|
+
}
|
|
2720
2854
|
if (s.requireConstraintFit && tagId) {
|
|
2721
|
-
const
|
|
2722
|
-
|
|
2855
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
2856
|
+
tagId,
|
|
2857
|
+
params,
|
|
2858
|
+
capability
|
|
2859
|
+
);
|
|
2860
|
+
if (!fitsConstraints) continue;
|
|
2723
2861
|
}
|
|
2724
|
-
return
|
|
2862
|
+
return candidate;
|
|
2725
2863
|
}
|
|
2726
2864
|
}
|
|
2727
2865
|
return null;
|
|
@@ -2731,7 +2869,7 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2731
2869
|
const s = { ...DEFAULT_SETTINGS, ...settings != null ? settings : {} };
|
|
2732
2870
|
const out = [];
|
|
2733
2871
|
const fb = (_a = props.fallbacks) != null ? _a : {};
|
|
2734
|
-
const primaryRate = (
|
|
2872
|
+
const primaryRate = (primary) => rateOf(services, primary);
|
|
2735
2873
|
for (const [nodeId, list] of Object.entries((_b = fb.nodes) != null ? _b : {})) {
|
|
2736
2874
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
2737
2875
|
if (!primary) {
|
|
@@ -2744,34 +2882,34 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2744
2882
|
});
|
|
2745
2883
|
continue;
|
|
2746
2884
|
}
|
|
2747
|
-
for (const
|
|
2748
|
-
const
|
|
2749
|
-
if (!
|
|
2885
|
+
for (const candidate of list) {
|
|
2886
|
+
const capability = getCap(services, candidate);
|
|
2887
|
+
if (!capability) {
|
|
2750
2888
|
out.push({
|
|
2751
2889
|
scope: "node",
|
|
2752
2890
|
nodeId,
|
|
2753
2891
|
primary,
|
|
2754
|
-
candidate
|
|
2892
|
+
candidate,
|
|
2755
2893
|
reason: "unknown_service"
|
|
2756
2894
|
});
|
|
2757
2895
|
continue;
|
|
2758
2896
|
}
|
|
2759
|
-
if (
|
|
2897
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
2760
2898
|
out.push({
|
|
2761
2899
|
scope: "node",
|
|
2762
2900
|
nodeId,
|
|
2763
2901
|
primary,
|
|
2764
|
-
candidate
|
|
2902
|
+
candidate,
|
|
2765
2903
|
reason: "cycle"
|
|
2766
2904
|
});
|
|
2767
2905
|
continue;
|
|
2768
2906
|
}
|
|
2769
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
2907
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
2770
2908
|
out.push({
|
|
2771
2909
|
scope: "node",
|
|
2772
2910
|
nodeId,
|
|
2773
2911
|
primary,
|
|
2774
|
-
candidate
|
|
2912
|
+
candidate,
|
|
2775
2913
|
reason: "rate_violation"
|
|
2776
2914
|
});
|
|
2777
2915
|
continue;
|
|
@@ -2781,58 +2919,55 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2781
2919
|
scope: "node",
|
|
2782
2920
|
nodeId,
|
|
2783
2921
|
primary,
|
|
2784
|
-
candidate
|
|
2922
|
+
candidate,
|
|
2785
2923
|
reason: "no_tag_context"
|
|
2786
2924
|
});
|
|
2787
2925
|
continue;
|
|
2788
2926
|
}
|
|
2789
|
-
let anyPass = false;
|
|
2790
|
-
let anyFail = false;
|
|
2791
2927
|
for (const tagId of tagContexts) {
|
|
2792
|
-
const
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2928
|
+
const fitsConstraints = s.requireConstraintFit ? satisfiesTagConstraints(
|
|
2929
|
+
tagId,
|
|
2930
|
+
{ services, props },
|
|
2931
|
+
capability
|
|
2932
|
+
) : true;
|
|
2933
|
+
if (fitsConstraints) continue;
|
|
2934
|
+
out.push({
|
|
2935
|
+
scope: "node",
|
|
2936
|
+
nodeId,
|
|
2937
|
+
primary,
|
|
2938
|
+
candidate,
|
|
2939
|
+
tagContext: tagId,
|
|
2940
|
+
reason: "constraint_mismatch"
|
|
2941
|
+
});
|
|
2805
2942
|
}
|
|
2806
|
-
void anyPass;
|
|
2807
|
-
void anyFail;
|
|
2808
2943
|
}
|
|
2809
2944
|
}
|
|
2810
2945
|
for (const [primary, list] of Object.entries((_c = fb.global) != null ? _c : {})) {
|
|
2811
|
-
for (const
|
|
2812
|
-
const
|
|
2813
|
-
if (!
|
|
2946
|
+
for (const candidate of list) {
|
|
2947
|
+
const capability = getCap(services, candidate);
|
|
2948
|
+
if (!capability) {
|
|
2814
2949
|
out.push({
|
|
2815
2950
|
scope: "global",
|
|
2816
2951
|
primary,
|
|
2817
|
-
candidate
|
|
2952
|
+
candidate,
|
|
2818
2953
|
reason: "unknown_service"
|
|
2819
2954
|
});
|
|
2820
2955
|
continue;
|
|
2821
2956
|
}
|
|
2822
|
-
if (
|
|
2957
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
2823
2958
|
out.push({
|
|
2824
2959
|
scope: "global",
|
|
2825
2960
|
primary,
|
|
2826
|
-
candidate
|
|
2961
|
+
candidate,
|
|
2827
2962
|
reason: "cycle"
|
|
2828
2963
|
});
|
|
2829
2964
|
continue;
|
|
2830
2965
|
}
|
|
2831
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
2966
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
2832
2967
|
out.push({
|
|
2833
2968
|
scope: "global",
|
|
2834
2969
|
primary,
|
|
2835
|
-
candidate
|
|
2970
|
+
candidate,
|
|
2836
2971
|
reason: "rate_violation"
|
|
2837
2972
|
});
|
|
2838
2973
|
}
|
|
@@ -2841,52 +2976,61 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2841
2976
|
return out;
|
|
2842
2977
|
}
|
|
2843
2978
|
function rateOf(map, id) {
|
|
2844
|
-
var _a;
|
|
2979
|
+
var _a, _b;
|
|
2845
2980
|
if (id === void 0 || id === null) return void 0;
|
|
2846
|
-
|
|
2847
|
-
return (_a = c == null ? void 0 : c.rate) != null ? _a : void 0;
|
|
2981
|
+
return (_b = (_a = getCap(map, id)) == null ? void 0 : _a.rate) != null ? _b : void 0;
|
|
2848
2982
|
}
|
|
2849
|
-
function passesRate(policy, primaryRate,
|
|
2850
|
-
if (typeof
|
|
2983
|
+
function passesRate(policy, primaryRate, candidateRate) {
|
|
2984
|
+
if (typeof candidateRate !== "number" || !Number.isFinite(candidateRate)) {
|
|
2851
2985
|
return false;
|
|
2852
|
-
|
|
2986
|
+
}
|
|
2987
|
+
if (typeof primaryRate !== "number" || !Number.isFinite(primaryRate)) {
|
|
2853
2988
|
return false;
|
|
2854
|
-
|
|
2989
|
+
}
|
|
2990
|
+
return passesRatePolicy(
|
|
2991
|
+
normalizeRatePolicy(policy),
|
|
2992
|
+
primaryRate,
|
|
2993
|
+
candidateRate
|
|
2994
|
+
);
|
|
2855
2995
|
}
|
|
2856
2996
|
function getCap(map, id) {
|
|
2857
2997
|
return getServiceCapability(map, id);
|
|
2858
2998
|
}
|
|
2859
|
-
function isCapFlagEnabled(
|
|
2999
|
+
function isCapFlagEnabled(capability, flagId) {
|
|
2860
3000
|
var _a, _b;
|
|
2861
|
-
const fromFlags = (_b = (_a =
|
|
3001
|
+
const fromFlags = (_b = (_a = capability.flags) == null ? void 0 : _a[flagId]) == null ? void 0 : _b.enabled;
|
|
2862
3002
|
if (fromFlags === true) return true;
|
|
2863
3003
|
if (fromFlags === false) return false;
|
|
2864
|
-
const legacy =
|
|
3004
|
+
const legacy = capability[flagId];
|
|
2865
3005
|
return legacy === true;
|
|
2866
3006
|
}
|
|
2867
|
-
function satisfiesTagConstraints(tagId, ctx,
|
|
2868
|
-
const tag = ctx.props.filters.find((
|
|
2869
|
-
const
|
|
2870
|
-
if (!
|
|
2871
|
-
for (const [key, value] of Object.entries(
|
|
2872
|
-
if (value === true && !isCapFlagEnabled(
|
|
3007
|
+
function satisfiesTagConstraints(tagId, ctx, capability) {
|
|
3008
|
+
const tag = ctx.props.filters.find((item) => item.id === tagId);
|
|
3009
|
+
const effectiveConstraints2 = tag == null ? void 0 : tag.constraints;
|
|
3010
|
+
if (!effectiveConstraints2) return true;
|
|
3011
|
+
for (const [key, value] of Object.entries(effectiveConstraints2)) {
|
|
3012
|
+
if (value === true && !isCapFlagEnabled(capability, key)) {
|
|
2873
3013
|
return false;
|
|
2874
3014
|
}
|
|
2875
3015
|
}
|
|
2876
3016
|
return true;
|
|
2877
3017
|
}
|
|
2878
3018
|
function primaryForNode(props, nodeId) {
|
|
2879
|
-
const tag = props.filters.find((
|
|
3019
|
+
const tag = props.filters.find((item) => item.id === nodeId);
|
|
2880
3020
|
if (tag) {
|
|
2881
3021
|
return { primary: tag.service_id, tagContexts: [tag.id] };
|
|
2882
3022
|
}
|
|
2883
3023
|
const field = props.fields.find(
|
|
2884
|
-
(
|
|
3024
|
+
(item) => Array.isArray(item.options) && item.options.some((option2) => option2.id === nodeId)
|
|
2885
3025
|
);
|
|
2886
|
-
if (!field)
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
3026
|
+
if (!field) {
|
|
3027
|
+
return { tagContexts: [], reasonNoPrimary: "no_parent_field" };
|
|
3028
|
+
}
|
|
3029
|
+
const option = field.options.find((item) => item.id === nodeId);
|
|
3030
|
+
return {
|
|
3031
|
+
primary: option.service_id,
|
|
3032
|
+
tagContexts: bindIdsToArray(field.bind_id)
|
|
3033
|
+
};
|
|
2890
3034
|
}
|
|
2891
3035
|
function bindIdsToArray(bind) {
|
|
2892
3036
|
if (!bind) return [];
|
|
@@ -2896,43 +3040,54 @@ function getEligibleFallbacks(params) {
|
|
|
2896
3040
|
var _a, _b, _c, _d, _e, _f;
|
|
2897
3041
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
2898
3042
|
const { primary, nodeId, tagId, services } = params;
|
|
2899
|
-
const
|
|
2900
|
-
const
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
3043
|
+
const excludes = /* @__PURE__ */ new Set();
|
|
3044
|
+
for (const ref of (_b = params.exclude) != null ? _b : []) {
|
|
3045
|
+
addComparableServiceRef(excludes, services, ref);
|
|
3046
|
+
}
|
|
3047
|
+
addComparableServiceRef(excludes, services, primary);
|
|
3048
|
+
const source = (_c = params.source) != null ? _c : "registered";
|
|
3049
|
+
const candidateLists = source === "all_services" ? [listServicePoolCandidates(services)] : listRegisteredFallbackCandidates(
|
|
3050
|
+
(_d = params.fallbacks) != null ? _d : {},
|
|
3051
|
+
primary,
|
|
3052
|
+
nodeId,
|
|
3053
|
+
services
|
|
3054
|
+
);
|
|
3055
|
+
if (!candidateLists.length) return [];
|
|
2907
3056
|
const primaryRate = rateOf(services, primary);
|
|
2908
3057
|
const seen = /* @__PURE__ */ new Set();
|
|
2909
3058
|
const eligible = [];
|
|
2910
|
-
for (const list of
|
|
2911
|
-
for (const
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
if (
|
|
2915
|
-
|
|
2916
|
-
const
|
|
2917
|
-
|
|
2918
|
-
|
|
3059
|
+
for (const list of candidateLists) {
|
|
3060
|
+
for (const candidate of list) {
|
|
3061
|
+
if (hasComparableServiceRef(excludes, services, candidate)) continue;
|
|
3062
|
+
const capability = getCap(services, candidate);
|
|
3063
|
+
if (!capability) continue;
|
|
3064
|
+
const candidateId = (_e = getServiceCapabilityCanonicalRef(services, candidate)) != null ? _e : candidate;
|
|
3065
|
+
const candidateIdentity = getComparableServiceRefKey(
|
|
3066
|
+
services,
|
|
3067
|
+
candidateId
|
|
3068
|
+
);
|
|
3069
|
+
if (((_f = params.unique) != null ? _f : true) && seen.has(candidateIdentity)) continue;
|
|
3070
|
+
seen.add(candidateIdentity);
|
|
3071
|
+
if (!passesRate(s.ratePolicy, primaryRate, capability.rate)) {
|
|
3072
|
+
continue;
|
|
3073
|
+
}
|
|
2919
3074
|
if (s.requireConstraintFit && tagId) {
|
|
2920
|
-
const
|
|
3075
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
2921
3076
|
tagId,
|
|
2922
3077
|
{ props: params.props, services },
|
|
2923
|
-
|
|
3078
|
+
capability
|
|
2924
3079
|
);
|
|
2925
|
-
if (!
|
|
3080
|
+
if (!fitsConstraints) continue;
|
|
2926
3081
|
}
|
|
2927
|
-
eligible.push(
|
|
3082
|
+
eligible.push(candidateId);
|
|
2928
3083
|
}
|
|
2929
3084
|
}
|
|
2930
3085
|
if (s.selectionStrategy === "cheapest") {
|
|
2931
|
-
eligible.sort((
|
|
3086
|
+
eligible.sort((left, right) => {
|
|
2932
3087
|
var _a2, _b2;
|
|
2933
|
-
const
|
|
2934
|
-
const
|
|
2935
|
-
return
|
|
3088
|
+
const leftRate = (_a2 = rateOf(services, left)) != null ? _a2 : Infinity;
|
|
3089
|
+
const rightRate = (_b2 = rateOf(services, right)) != null ? _b2 : Infinity;
|
|
3090
|
+
return leftRate - rightRate;
|
|
2936
3091
|
});
|
|
2937
3092
|
}
|
|
2938
3093
|
if (typeof params.limit === "number" && params.limit >= 0) {
|
|
@@ -2940,10 +3095,104 @@ function getEligibleFallbacks(params) {
|
|
|
2940
3095
|
}
|
|
2941
3096
|
return eligible;
|
|
2942
3097
|
}
|
|
3098
|
+
function getAssignedServiceIds(params) {
|
|
3099
|
+
var _a, _b, _c, _d, _e;
|
|
3100
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3101
|
+
const out = [];
|
|
3102
|
+
const push = (value) => {
|
|
3103
|
+
if (!isValidServiceIdRef(value)) return;
|
|
3104
|
+
const key = String(value);
|
|
3105
|
+
if (seen.has(key)) return;
|
|
3106
|
+
seen.add(key);
|
|
3107
|
+
out.push(value);
|
|
3108
|
+
};
|
|
3109
|
+
const props = params.props;
|
|
3110
|
+
if (props) {
|
|
3111
|
+
for (const tag of (_a = props.filters) != null ? _a : []) {
|
|
3112
|
+
push(tag.service_id);
|
|
3113
|
+
}
|
|
3114
|
+
for (const field of (_b = props.fields) != null ? _b : []) {
|
|
3115
|
+
const fieldService = field.service_id;
|
|
3116
|
+
if (field.button === true) {
|
|
3117
|
+
push(fieldService);
|
|
3118
|
+
}
|
|
3119
|
+
for (const option of (_c = field.options) != null ? _c : []) {
|
|
3120
|
+
if (option.pricing_role === "utility") continue;
|
|
3121
|
+
push(option.service_id);
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
const snapshot = params.snapshot;
|
|
3126
|
+
if (snapshot) {
|
|
3127
|
+
for (const serviceId of (_d = snapshot.services) != null ? _d : []) {
|
|
3128
|
+
push(serviceId);
|
|
3129
|
+
}
|
|
3130
|
+
for (const list of Object.values((_e = snapshot.serviceMap) != null ? _e : {})) {
|
|
3131
|
+
for (const serviceId of list != null ? list : []) {
|
|
3132
|
+
push(serviceId);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
return out;
|
|
3137
|
+
}
|
|
2943
3138
|
function getFallbackRegistrationInfo(props, nodeId) {
|
|
2944
3139
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
2945
3140
|
return { primary, tagContexts };
|
|
2946
3141
|
}
|
|
3142
|
+
function listRegisteredFallbackCandidates(fallbacks, primary, nodeId, services) {
|
|
3143
|
+
var _a, _b;
|
|
3144
|
+
const lists = [];
|
|
3145
|
+
if (nodeId && ((_a = fallbacks.nodes) == null ? void 0 : _a[nodeId])) {
|
|
3146
|
+
lists.push(fallbacks.nodes[nodeId]);
|
|
3147
|
+
}
|
|
3148
|
+
for (const [registeredPrimary, list] of Object.entries((_b = fallbacks.global) != null ? _b : {})) {
|
|
3149
|
+
if (!isMatchingServiceRef(services, registeredPrimary, primary)) continue;
|
|
3150
|
+
lists.push(list);
|
|
3151
|
+
}
|
|
3152
|
+
return lists;
|
|
3153
|
+
}
|
|
3154
|
+
function listServicePoolCandidates(services) {
|
|
3155
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3156
|
+
const out = [];
|
|
3157
|
+
for (const [key, capability] of Object.entries(services != null ? services : {})) {
|
|
3158
|
+
const candidate = getServicePoolCandidateId(key, capability);
|
|
3159
|
+
if (!isValidServiceIdRef(candidate)) continue;
|
|
3160
|
+
const identity = getComparableServiceRefKey(services, candidate);
|
|
3161
|
+
if (seen.has(identity)) continue;
|
|
3162
|
+
seen.add(identity);
|
|
3163
|
+
out.push(candidate);
|
|
3164
|
+
}
|
|
3165
|
+
return out;
|
|
3166
|
+
}
|
|
3167
|
+
function getServicePoolCandidateId(key, capability) {
|
|
3168
|
+
var _a;
|
|
3169
|
+
return (_a = getServiceCapabilityCanonicalRef({ [key]: capability }, key)) != null ? _a : key;
|
|
3170
|
+
}
|
|
3171
|
+
function addComparableServiceRef(target, services, value) {
|
|
3172
|
+
for (const ref of getComparableServiceRefs(services, value)) {
|
|
3173
|
+
target.add(ref);
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
function hasComparableServiceRef(target, services, value) {
|
|
3177
|
+
return getComparableServiceRefs(services, value).some((ref) => target.has(ref));
|
|
3178
|
+
}
|
|
3179
|
+
function getComparableServiceRefKey(services, value) {
|
|
3180
|
+
if (!isValidServiceIdRef(value)) return "";
|
|
3181
|
+
const canonical = getServiceCapabilityCanonicalRef(services, value);
|
|
3182
|
+
return String(canonical != null ? canonical : value);
|
|
3183
|
+
}
|
|
3184
|
+
function getComparableServiceRefs(services, value) {
|
|
3185
|
+
if (!isValidServiceIdRef(value)) return [];
|
|
3186
|
+
const aliases = getServiceCapabilityAliases(services, value);
|
|
3187
|
+
if (!aliases.length) {
|
|
3188
|
+
return [String(value)];
|
|
3189
|
+
}
|
|
3190
|
+
return aliases.map((ref) => String(ref));
|
|
3191
|
+
}
|
|
3192
|
+
function isMatchingServiceRef(services, left, right) {
|
|
3193
|
+
if (!services) return String(left) === String(right);
|
|
3194
|
+
return isSameServiceCapabilityRef(services, left, right);
|
|
3195
|
+
}
|
|
2947
3196
|
|
|
2948
3197
|
// src/core/tag-relations.ts
|
|
2949
3198
|
var toId = (x) => typeof x === "string" ? x : x.id;
|
|
@@ -3562,18 +3811,23 @@ function compilePolicies(raw) {
|
|
|
3562
3811
|
|
|
3563
3812
|
// src/core/service-filter.ts
|
|
3564
3813
|
function filterServicesForVisibleGroup(input, deps) {
|
|
3565
|
-
var _a, _b, _c, _d, _e, _f;
|
|
3814
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
3566
3815
|
const svcMap = (_c = (_b = (_a = deps.builder).getServiceMap) == null ? void 0 : _b.call(_a)) != null ? _c : {};
|
|
3816
|
+
const builderOptions = (_e = (_d = deps.builder).getOptions) == null ? void 0 : _e.call(_d);
|
|
3567
3817
|
const { context } = input;
|
|
3568
3818
|
const usedSet = new Set(context.usedServiceIds.map(String));
|
|
3569
3819
|
const primary = context.usedServiceIds[0];
|
|
3820
|
+
const explicitFallbackSettings = (_f = context.fallbackSettings) != null ? _f : context.fallback;
|
|
3821
|
+
const resolvedRatePolicy = normalizeRatePolicy(
|
|
3822
|
+
(_h = (_g = context.ratePolicy) != null ? _g : explicitFallbackSettings == null ? void 0 : explicitFallbackSettings.ratePolicy) != null ? _h : builderOptions == null ? void 0 : builderOptions.ratePolicy
|
|
3823
|
+
);
|
|
3824
|
+
const fallbackSettingsSource = explicitFallbackSettings != null ? explicitFallbackSettings : builderOptions == null ? void 0 : builderOptions.fallbackSettings;
|
|
3570
3825
|
const fb = {
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
mode: "strict",
|
|
3575
|
-
...(_d = context.fallback) != null ? _d : {}
|
|
3826
|
+
...DEFAULT_FALLBACK_SETTINGS,
|
|
3827
|
+
...fallbackSettingsSource != null ? fallbackSettingsSource : {},
|
|
3828
|
+
ratePolicy: resolvedRatePolicy
|
|
3576
3829
|
};
|
|
3830
|
+
const policySource = (_j = (_i = context.policies) != null ? _i : builderOptions == null ? void 0 : builderOptions.policies) != null ? _j : [];
|
|
3577
3831
|
const visibleServiceIds = context.selectedButtons === void 0 ? void 0 : collectVisibleServiceIds(
|
|
3578
3832
|
deps.builder,
|
|
3579
3833
|
context.tagId,
|
|
@@ -3598,11 +3852,11 @@ function filterServicesForVisibleGroup(input, deps) {
|
|
|
3598
3852
|
const fitsConstraints = constraintFitOk(
|
|
3599
3853
|
svcMap,
|
|
3600
3854
|
cap.id,
|
|
3601
|
-
(
|
|
3855
|
+
(_k = context.effectiveConstraints) != null ? _k : {}
|
|
3602
3856
|
);
|
|
3603
3857
|
const passesRate2 = primary == null ? true : rateOk(svcMap, id, primary, fb);
|
|
3604
3858
|
const polRes = evaluatePoliciesRaw(
|
|
3605
|
-
|
|
3859
|
+
policySource,
|
|
3606
3860
|
[...context.usedServiceIds, id],
|
|
3607
3861
|
svcMap,
|
|
3608
3862
|
context.tagId,
|
|
@@ -4477,6 +4731,7 @@ function createFallbackEditor(options = {}) {
|
|
|
4477
4731
|
const original = cloneFallbacks(options.fallbacks);
|
|
4478
4732
|
let current = cloneFallbacks(options.fallbacks);
|
|
4479
4733
|
const props = options.props;
|
|
4734
|
+
const snapshot = options.snapshot;
|
|
4480
4735
|
const services = (_a = options.services) != null ? _a : {};
|
|
4481
4736
|
const settings = (_b = options.settings) != null ? _b : {};
|
|
4482
4737
|
function state() {
|
|
@@ -4571,7 +4826,11 @@ function createFallbackEditor(options = {}) {
|
|
|
4571
4826
|
const allowed2 = [];
|
|
4572
4827
|
for (const candidate of normalized) {
|
|
4573
4828
|
const reasons = [];
|
|
4574
|
-
if (
|
|
4829
|
+
if (isSameServiceCapabilityRef(
|
|
4830
|
+
services,
|
|
4831
|
+
candidate,
|
|
4832
|
+
context.primary
|
|
4833
|
+
)) {
|
|
4575
4834
|
reasons.push("self_reference");
|
|
4576
4835
|
}
|
|
4577
4836
|
if (reasons.length) {
|
|
@@ -4659,7 +4918,19 @@ function createFallbackEditor(options = {}) {
|
|
|
4659
4918
|
return writeScope(context, []);
|
|
4660
4919
|
}
|
|
4661
4920
|
function eligible(context, opt) {
|
|
4921
|
+
var _a2, _b2;
|
|
4662
4922
|
if (!props) return [];
|
|
4923
|
+
const source = (_a2 = opt == null ? void 0 : opt.source) != null ? _a2 : "all_services";
|
|
4924
|
+
const exclude = normalizeCandidateList(
|
|
4925
|
+
[
|
|
4926
|
+
...(_b2 = opt == null ? void 0 : opt.exclude) != null ? _b2 : [],
|
|
4927
|
+
...source === "all_services" ? [
|
|
4928
|
+
...getAssignedServiceIds({ props, snapshot }),
|
|
4929
|
+
...getScope(context)
|
|
4930
|
+
] : []
|
|
4931
|
+
],
|
|
4932
|
+
true
|
|
4933
|
+
);
|
|
4663
4934
|
if (context.scope === "global") {
|
|
4664
4935
|
return getEligibleFallbacks({
|
|
4665
4936
|
primary: context.primary,
|
|
@@ -4667,9 +4938,10 @@ function createFallbackEditor(options = {}) {
|
|
|
4667
4938
|
fallbacks: current,
|
|
4668
4939
|
settings,
|
|
4669
4940
|
props,
|
|
4670
|
-
exclude
|
|
4941
|
+
exclude,
|
|
4671
4942
|
unique: opt == null ? void 0 : opt.unique,
|
|
4672
|
-
limit: opt == null ? void 0 : opt.limit
|
|
4943
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
4944
|
+
source
|
|
4673
4945
|
});
|
|
4674
4946
|
}
|
|
4675
4947
|
const info = getFallbackRegistrationInfo(props, context.nodeId);
|
|
@@ -4677,14 +4949,19 @@ function createFallbackEditor(options = {}) {
|
|
|
4677
4949
|
return getEligibleFallbacks({
|
|
4678
4950
|
primary: info.primary,
|
|
4679
4951
|
nodeId: context.nodeId,
|
|
4680
|
-
tagId:
|
|
4952
|
+
tagId: resolveNodeTagContext({
|
|
4953
|
+
nodeId: context.nodeId,
|
|
4954
|
+
snapshot,
|
|
4955
|
+
fallbackTagContexts: info.tagContexts
|
|
4956
|
+
}),
|
|
4681
4957
|
services,
|
|
4682
4958
|
fallbacks: current,
|
|
4683
4959
|
settings,
|
|
4684
4960
|
props,
|
|
4685
|
-
exclude
|
|
4961
|
+
exclude,
|
|
4686
4962
|
unique: opt == null ? void 0 : opt.unique,
|
|
4687
|
-
limit: opt == null ? void 0 : opt.limit
|
|
4963
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
4964
|
+
source
|
|
4688
4965
|
});
|
|
4689
4966
|
}
|
|
4690
4967
|
function writeScope(context, nextList) {
|
|
@@ -4742,14 +5019,14 @@ function sameFallbacks(a, b) {
|
|
|
4742
5019
|
function normalizeCandidateList(input, preserveOrder) {
|
|
4743
5020
|
const out = [];
|
|
4744
5021
|
for (const item of input != null ? input : []) {
|
|
4745
|
-
if (!
|
|
5022
|
+
if (!isValidServiceIdRef2(item)) continue;
|
|
4746
5023
|
const exists = out.some((x) => String(x) === String(item));
|
|
4747
5024
|
if (exists) continue;
|
|
4748
5025
|
out.push(item);
|
|
4749
5026
|
}
|
|
4750
5027
|
return preserveOrder ? out : out;
|
|
4751
5028
|
}
|
|
4752
|
-
function
|
|
5029
|
+
function isValidServiceIdRef2(value) {
|
|
4753
5030
|
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
4754
5031
|
}
|
|
4755
5032
|
function clamp(n, min, max) {
|
|
@@ -4758,7 +5035,7 @@ function clamp(n, min, max) {
|
|
|
4758
5035
|
function getNodeRegistrationInfo(props, nodeId) {
|
|
4759
5036
|
const tag = props.filters.find((t) => t.id === nodeId);
|
|
4760
5037
|
if (tag) {
|
|
4761
|
-
if (!
|
|
5038
|
+
if (!isValidServiceIdRef2(tag.service_id)) {
|
|
4762
5039
|
return { ok: false, reasons: ["no_primary"] };
|
|
4763
5040
|
}
|
|
4764
5041
|
return {
|
|
@@ -4771,7 +5048,7 @@ function getNodeRegistrationInfo(props, nodeId) {
|
|
|
4771
5048
|
if (!hit) {
|
|
4772
5049
|
return { ok: false, reasons: ["node_not_found"] };
|
|
4773
5050
|
}
|
|
4774
|
-
if (!
|
|
5051
|
+
if (!isValidServiceIdRef2(hit.option.service_id)) {
|
|
4775
5052
|
return { ok: false, reasons: ["no_primary"] };
|
|
4776
5053
|
}
|
|
4777
5054
|
return {
|
|
@@ -4793,6 +5070,15 @@ function bindIdsToArray2(v) {
|
|
|
4793
5070
|
if (Array.isArray(v)) return v.filter(Boolean);
|
|
4794
5071
|
return v ? [v] : [];
|
|
4795
5072
|
}
|
|
5073
|
+
function resolveNodeTagContext(params) {
|
|
5074
|
+
var _a, _b, _c;
|
|
5075
|
+
const nodeContexts = (_c = (_b = (_a = params.snapshot) == null ? void 0 : _a.meta) == null ? void 0 : _b.context) == null ? void 0 : _c.nodeContexts;
|
|
5076
|
+
if (nodeContexts && Object.prototype.hasOwnProperty.call(nodeContexts, params.nodeId)) {
|
|
5077
|
+
const tagId = nodeContexts[params.nodeId];
|
|
5078
|
+
return typeof tagId === "string" && tagId.trim().length > 0 ? tagId : void 0;
|
|
5079
|
+
}
|
|
5080
|
+
return params.fallbackTagContexts[0];
|
|
5081
|
+
}
|
|
4796
5082
|
function mapDiagReason(reason) {
|
|
4797
5083
|
switch (String(reason)) {
|
|
4798
5084
|
case "unknown_service":
|
|
@@ -4819,6 +5105,7 @@ function mapDiagReason(reason) {
|
|
|
4819
5105
|
createFallbackEditor,
|
|
4820
5106
|
createNodeIndex,
|
|
4821
5107
|
filterServicesForVisibleGroup,
|
|
5108
|
+
getAssignedServiceIds,
|
|
4822
5109
|
getEligibleFallbacks,
|
|
4823
5110
|
getFallbackRegistrationInfo,
|
|
4824
5111
|
normalise,
|