@timeax/digital-service-engine 0.2.1 → 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 +364 -119
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +8 -11
- package/dist/core/index.d.ts +8 -11
- package/dist/core/index.js +363 -119
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +561 -335
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +561 -335
- package/dist/react/index.js.map +1 -1
- package/dist/schema/index.d.cts +12 -1
- package/dist/schema/index.d.ts +12 -1
- package/dist/workspace/index.cjs +154 -68
- package/dist/workspace/index.cjs.map +1 -1
- package/dist/workspace/index.js +154 -68
- 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,6 +1304,74 @@ 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) {
|
|
@@ -2738,27 +2824,42 @@ var DEFAULT_SETTINGS = {
|
|
|
2738
2824
|
mode: "strict"
|
|
2739
2825
|
};
|
|
2740
2826
|
function resolveServiceFallback(params) {
|
|
2741
|
-
var _a, _b
|
|
2827
|
+
var _a, _b;
|
|
2742
2828
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
2743
2829
|
const { primary, nodeId, tagId, services } = params;
|
|
2744
|
-
const
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2830
|
+
const fallbackLists = listRegisteredFallbackCandidates(
|
|
2831
|
+
(_b = params.fallbacks) != null ? _b : {},
|
|
2832
|
+
primary,
|
|
2833
|
+
nodeId,
|
|
2834
|
+
services
|
|
2835
|
+
);
|
|
2836
|
+
const tried = /* @__PURE__ */ new Set();
|
|
2749
2837
|
const primaryRate = rateOf(services, primary);
|
|
2750
|
-
for (const list of
|
|
2751
|
-
for (const
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
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
|
+
}
|
|
2757
2854
|
if (s.requireConstraintFit && tagId) {
|
|
2758
|
-
const
|
|
2759
|
-
|
|
2855
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
2856
|
+
tagId,
|
|
2857
|
+
params,
|
|
2858
|
+
capability
|
|
2859
|
+
);
|
|
2860
|
+
if (!fitsConstraints) continue;
|
|
2760
2861
|
}
|
|
2761
|
-
return
|
|
2862
|
+
return candidate;
|
|
2762
2863
|
}
|
|
2763
2864
|
}
|
|
2764
2865
|
return null;
|
|
@@ -2768,7 +2869,7 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2768
2869
|
const s = { ...DEFAULT_SETTINGS, ...settings != null ? settings : {} };
|
|
2769
2870
|
const out = [];
|
|
2770
2871
|
const fb = (_a = props.fallbacks) != null ? _a : {};
|
|
2771
|
-
const primaryRate = (
|
|
2872
|
+
const primaryRate = (primary) => rateOf(services, primary);
|
|
2772
2873
|
for (const [nodeId, list] of Object.entries((_b = fb.nodes) != null ? _b : {})) {
|
|
2773
2874
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
2774
2875
|
if (!primary) {
|
|
@@ -2781,34 +2882,34 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2781
2882
|
});
|
|
2782
2883
|
continue;
|
|
2783
2884
|
}
|
|
2784
|
-
for (const
|
|
2785
|
-
const
|
|
2786
|
-
if (!
|
|
2885
|
+
for (const candidate of list) {
|
|
2886
|
+
const capability = getCap(services, candidate);
|
|
2887
|
+
if (!capability) {
|
|
2787
2888
|
out.push({
|
|
2788
2889
|
scope: "node",
|
|
2789
2890
|
nodeId,
|
|
2790
2891
|
primary,
|
|
2791
|
-
candidate
|
|
2892
|
+
candidate,
|
|
2792
2893
|
reason: "unknown_service"
|
|
2793
2894
|
});
|
|
2794
2895
|
continue;
|
|
2795
2896
|
}
|
|
2796
|
-
if (
|
|
2897
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
2797
2898
|
out.push({
|
|
2798
2899
|
scope: "node",
|
|
2799
2900
|
nodeId,
|
|
2800
2901
|
primary,
|
|
2801
|
-
candidate
|
|
2902
|
+
candidate,
|
|
2802
2903
|
reason: "cycle"
|
|
2803
2904
|
});
|
|
2804
2905
|
continue;
|
|
2805
2906
|
}
|
|
2806
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
2907
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
2807
2908
|
out.push({
|
|
2808
2909
|
scope: "node",
|
|
2809
2910
|
nodeId,
|
|
2810
2911
|
primary,
|
|
2811
|
-
candidate
|
|
2912
|
+
candidate,
|
|
2812
2913
|
reason: "rate_violation"
|
|
2813
2914
|
});
|
|
2814
2915
|
continue;
|
|
@@ -2818,58 +2919,55 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2818
2919
|
scope: "node",
|
|
2819
2920
|
nodeId,
|
|
2820
2921
|
primary,
|
|
2821
|
-
candidate
|
|
2922
|
+
candidate,
|
|
2822
2923
|
reason: "no_tag_context"
|
|
2823
2924
|
});
|
|
2824
2925
|
continue;
|
|
2825
2926
|
}
|
|
2826
|
-
let anyPass = false;
|
|
2827
|
-
let anyFail = false;
|
|
2828
2927
|
for (const tagId of tagContexts) {
|
|
2829
|
-
const
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
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
|
+
});
|
|
2842
2942
|
}
|
|
2843
|
-
void anyPass;
|
|
2844
|
-
void anyFail;
|
|
2845
2943
|
}
|
|
2846
2944
|
}
|
|
2847
2945
|
for (const [primary, list] of Object.entries((_c = fb.global) != null ? _c : {})) {
|
|
2848
|
-
for (const
|
|
2849
|
-
const
|
|
2850
|
-
if (!
|
|
2946
|
+
for (const candidate of list) {
|
|
2947
|
+
const capability = getCap(services, candidate);
|
|
2948
|
+
if (!capability) {
|
|
2851
2949
|
out.push({
|
|
2852
2950
|
scope: "global",
|
|
2853
2951
|
primary,
|
|
2854
|
-
candidate
|
|
2952
|
+
candidate,
|
|
2855
2953
|
reason: "unknown_service"
|
|
2856
2954
|
});
|
|
2857
2955
|
continue;
|
|
2858
2956
|
}
|
|
2859
|
-
if (
|
|
2957
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
2860
2958
|
out.push({
|
|
2861
2959
|
scope: "global",
|
|
2862
2960
|
primary,
|
|
2863
|
-
candidate
|
|
2961
|
+
candidate,
|
|
2864
2962
|
reason: "cycle"
|
|
2865
2963
|
});
|
|
2866
2964
|
continue;
|
|
2867
2965
|
}
|
|
2868
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
2966
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
2869
2967
|
out.push({
|
|
2870
2968
|
scope: "global",
|
|
2871
2969
|
primary,
|
|
2872
|
-
candidate
|
|
2970
|
+
candidate,
|
|
2873
2971
|
reason: "rate_violation"
|
|
2874
2972
|
});
|
|
2875
2973
|
}
|
|
@@ -2878,52 +2976,61 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
2878
2976
|
return out;
|
|
2879
2977
|
}
|
|
2880
2978
|
function rateOf(map, id) {
|
|
2881
|
-
var _a;
|
|
2979
|
+
var _a, _b;
|
|
2882
2980
|
if (id === void 0 || id === null) return void 0;
|
|
2883
|
-
|
|
2884
|
-
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;
|
|
2885
2982
|
}
|
|
2886
|
-
function passesRate(policy, primaryRate,
|
|
2887
|
-
if (typeof
|
|
2983
|
+
function passesRate(policy, primaryRate, candidateRate) {
|
|
2984
|
+
if (typeof candidateRate !== "number" || !Number.isFinite(candidateRate)) {
|
|
2888
2985
|
return false;
|
|
2889
|
-
|
|
2986
|
+
}
|
|
2987
|
+
if (typeof primaryRate !== "number" || !Number.isFinite(primaryRate)) {
|
|
2890
2988
|
return false;
|
|
2891
|
-
|
|
2989
|
+
}
|
|
2990
|
+
return passesRatePolicy(
|
|
2991
|
+
normalizeRatePolicy(policy),
|
|
2992
|
+
primaryRate,
|
|
2993
|
+
candidateRate
|
|
2994
|
+
);
|
|
2892
2995
|
}
|
|
2893
2996
|
function getCap(map, id) {
|
|
2894
2997
|
return getServiceCapability(map, id);
|
|
2895
2998
|
}
|
|
2896
|
-
function isCapFlagEnabled(
|
|
2999
|
+
function isCapFlagEnabled(capability, flagId) {
|
|
2897
3000
|
var _a, _b;
|
|
2898
|
-
const fromFlags = (_b = (_a =
|
|
3001
|
+
const fromFlags = (_b = (_a = capability.flags) == null ? void 0 : _a[flagId]) == null ? void 0 : _b.enabled;
|
|
2899
3002
|
if (fromFlags === true) return true;
|
|
2900
3003
|
if (fromFlags === false) return false;
|
|
2901
|
-
const legacy =
|
|
3004
|
+
const legacy = capability[flagId];
|
|
2902
3005
|
return legacy === true;
|
|
2903
3006
|
}
|
|
2904
|
-
function satisfiesTagConstraints(tagId, ctx,
|
|
2905
|
-
const tag = ctx.props.filters.find((
|
|
2906
|
-
const
|
|
2907
|
-
if (!
|
|
2908
|
-
for (const [key, value] of Object.entries(
|
|
2909
|
-
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)) {
|
|
2910
3013
|
return false;
|
|
2911
3014
|
}
|
|
2912
3015
|
}
|
|
2913
3016
|
return true;
|
|
2914
3017
|
}
|
|
2915
3018
|
function primaryForNode(props, nodeId) {
|
|
2916
|
-
const tag = props.filters.find((
|
|
3019
|
+
const tag = props.filters.find((item) => item.id === nodeId);
|
|
2917
3020
|
if (tag) {
|
|
2918
3021
|
return { primary: tag.service_id, tagContexts: [tag.id] };
|
|
2919
3022
|
}
|
|
2920
3023
|
const field = props.fields.find(
|
|
2921
|
-
(
|
|
3024
|
+
(item) => Array.isArray(item.options) && item.options.some((option2) => option2.id === nodeId)
|
|
2922
3025
|
);
|
|
2923
|
-
if (!field)
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
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
|
+
};
|
|
2927
3034
|
}
|
|
2928
3035
|
function bindIdsToArray(bind) {
|
|
2929
3036
|
if (!bind) return [];
|
|
@@ -2933,43 +3040,54 @@ function getEligibleFallbacks(params) {
|
|
|
2933
3040
|
var _a, _b, _c, _d, _e, _f;
|
|
2934
3041
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
2935
3042
|
const { primary, nodeId, tagId, services } = params;
|
|
2936
|
-
const
|
|
2937
|
-
const
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
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 [];
|
|
2944
3056
|
const primaryRate = rateOf(services, primary);
|
|
2945
3057
|
const seen = /* @__PURE__ */ new Set();
|
|
2946
3058
|
const eligible = [];
|
|
2947
|
-
for (const list of
|
|
2948
|
-
for (const
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
if (
|
|
2952
|
-
|
|
2953
|
-
const
|
|
2954
|
-
|
|
2955
|
-
|
|
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
|
+
}
|
|
2956
3074
|
if (s.requireConstraintFit && tagId) {
|
|
2957
|
-
const
|
|
3075
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
2958
3076
|
tagId,
|
|
2959
3077
|
{ props: params.props, services },
|
|
2960
|
-
|
|
3078
|
+
capability
|
|
2961
3079
|
);
|
|
2962
|
-
if (!
|
|
3080
|
+
if (!fitsConstraints) continue;
|
|
2963
3081
|
}
|
|
2964
|
-
eligible.push(
|
|
3082
|
+
eligible.push(candidateId);
|
|
2965
3083
|
}
|
|
2966
3084
|
}
|
|
2967
3085
|
if (s.selectionStrategy === "cheapest") {
|
|
2968
|
-
eligible.sort((
|
|
3086
|
+
eligible.sort((left, right) => {
|
|
2969
3087
|
var _a2, _b2;
|
|
2970
|
-
const
|
|
2971
|
-
const
|
|
2972
|
-
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;
|
|
2973
3091
|
});
|
|
2974
3092
|
}
|
|
2975
3093
|
if (typeof params.limit === "number" && params.limit >= 0) {
|
|
@@ -2977,10 +3095,104 @@ function getEligibleFallbacks(params) {
|
|
|
2977
3095
|
}
|
|
2978
3096
|
return eligible;
|
|
2979
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
|
+
}
|
|
2980
3138
|
function getFallbackRegistrationInfo(props, nodeId) {
|
|
2981
3139
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
2982
3140
|
return { primary, tagContexts };
|
|
2983
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
|
+
}
|
|
2984
3196
|
|
|
2985
3197
|
// src/core/tag-relations.ts
|
|
2986
3198
|
var toId = (x) => typeof x === "string" ? x : x.id;
|
|
@@ -4519,6 +4731,7 @@ function createFallbackEditor(options = {}) {
|
|
|
4519
4731
|
const original = cloneFallbacks(options.fallbacks);
|
|
4520
4732
|
let current = cloneFallbacks(options.fallbacks);
|
|
4521
4733
|
const props = options.props;
|
|
4734
|
+
const snapshot = options.snapshot;
|
|
4522
4735
|
const services = (_a = options.services) != null ? _a : {};
|
|
4523
4736
|
const settings = (_b = options.settings) != null ? _b : {};
|
|
4524
4737
|
function state() {
|
|
@@ -4613,7 +4826,11 @@ function createFallbackEditor(options = {}) {
|
|
|
4613
4826
|
const allowed2 = [];
|
|
4614
4827
|
for (const candidate of normalized) {
|
|
4615
4828
|
const reasons = [];
|
|
4616
|
-
if (
|
|
4829
|
+
if (isSameServiceCapabilityRef(
|
|
4830
|
+
services,
|
|
4831
|
+
candidate,
|
|
4832
|
+
context.primary
|
|
4833
|
+
)) {
|
|
4617
4834
|
reasons.push("self_reference");
|
|
4618
4835
|
}
|
|
4619
4836
|
if (reasons.length) {
|
|
@@ -4701,7 +4918,19 @@ function createFallbackEditor(options = {}) {
|
|
|
4701
4918
|
return writeScope(context, []);
|
|
4702
4919
|
}
|
|
4703
4920
|
function eligible(context, opt) {
|
|
4921
|
+
var _a2, _b2;
|
|
4704
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
|
+
);
|
|
4705
4934
|
if (context.scope === "global") {
|
|
4706
4935
|
return getEligibleFallbacks({
|
|
4707
4936
|
primary: context.primary,
|
|
@@ -4709,9 +4938,10 @@ function createFallbackEditor(options = {}) {
|
|
|
4709
4938
|
fallbacks: current,
|
|
4710
4939
|
settings,
|
|
4711
4940
|
props,
|
|
4712
|
-
exclude
|
|
4941
|
+
exclude,
|
|
4713
4942
|
unique: opt == null ? void 0 : opt.unique,
|
|
4714
|
-
limit: opt == null ? void 0 : opt.limit
|
|
4943
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
4944
|
+
source
|
|
4715
4945
|
});
|
|
4716
4946
|
}
|
|
4717
4947
|
const info = getFallbackRegistrationInfo(props, context.nodeId);
|
|
@@ -4719,14 +4949,19 @@ function createFallbackEditor(options = {}) {
|
|
|
4719
4949
|
return getEligibleFallbacks({
|
|
4720
4950
|
primary: info.primary,
|
|
4721
4951
|
nodeId: context.nodeId,
|
|
4722
|
-
tagId:
|
|
4952
|
+
tagId: resolveNodeTagContext({
|
|
4953
|
+
nodeId: context.nodeId,
|
|
4954
|
+
snapshot,
|
|
4955
|
+
fallbackTagContexts: info.tagContexts
|
|
4956
|
+
}),
|
|
4723
4957
|
services,
|
|
4724
4958
|
fallbacks: current,
|
|
4725
4959
|
settings,
|
|
4726
4960
|
props,
|
|
4727
|
-
exclude
|
|
4961
|
+
exclude,
|
|
4728
4962
|
unique: opt == null ? void 0 : opt.unique,
|
|
4729
|
-
limit: opt == null ? void 0 : opt.limit
|
|
4963
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
4964
|
+
source
|
|
4730
4965
|
});
|
|
4731
4966
|
}
|
|
4732
4967
|
function writeScope(context, nextList) {
|
|
@@ -4784,14 +5019,14 @@ function sameFallbacks(a, b) {
|
|
|
4784
5019
|
function normalizeCandidateList(input, preserveOrder) {
|
|
4785
5020
|
const out = [];
|
|
4786
5021
|
for (const item of input != null ? input : []) {
|
|
4787
|
-
if (!
|
|
5022
|
+
if (!isValidServiceIdRef2(item)) continue;
|
|
4788
5023
|
const exists = out.some((x) => String(x) === String(item));
|
|
4789
5024
|
if (exists) continue;
|
|
4790
5025
|
out.push(item);
|
|
4791
5026
|
}
|
|
4792
5027
|
return preserveOrder ? out : out;
|
|
4793
5028
|
}
|
|
4794
|
-
function
|
|
5029
|
+
function isValidServiceIdRef2(value) {
|
|
4795
5030
|
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
4796
5031
|
}
|
|
4797
5032
|
function clamp(n, min, max) {
|
|
@@ -4800,7 +5035,7 @@ function clamp(n, min, max) {
|
|
|
4800
5035
|
function getNodeRegistrationInfo(props, nodeId) {
|
|
4801
5036
|
const tag = props.filters.find((t) => t.id === nodeId);
|
|
4802
5037
|
if (tag) {
|
|
4803
|
-
if (!
|
|
5038
|
+
if (!isValidServiceIdRef2(tag.service_id)) {
|
|
4804
5039
|
return { ok: false, reasons: ["no_primary"] };
|
|
4805
5040
|
}
|
|
4806
5041
|
return {
|
|
@@ -4813,7 +5048,7 @@ function getNodeRegistrationInfo(props, nodeId) {
|
|
|
4813
5048
|
if (!hit) {
|
|
4814
5049
|
return { ok: false, reasons: ["node_not_found"] };
|
|
4815
5050
|
}
|
|
4816
|
-
if (!
|
|
5051
|
+
if (!isValidServiceIdRef2(hit.option.service_id)) {
|
|
4817
5052
|
return { ok: false, reasons: ["no_primary"] };
|
|
4818
5053
|
}
|
|
4819
5054
|
return {
|
|
@@ -4835,6 +5070,15 @@ function bindIdsToArray2(v) {
|
|
|
4835
5070
|
if (Array.isArray(v)) return v.filter(Boolean);
|
|
4836
5071
|
return v ? [v] : [];
|
|
4837
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
|
+
}
|
|
4838
5082
|
function mapDiagReason(reason) {
|
|
4839
5083
|
switch (String(reason)) {
|
|
4840
5084
|
case "unknown_service":
|
|
@@ -4861,6 +5105,7 @@ function mapDiagReason(reason) {
|
|
|
4861
5105
|
createFallbackEditor,
|
|
4862
5106
|
createNodeIndex,
|
|
4863
5107
|
filterServicesForVisibleGroup,
|
|
5108
|
+
getAssignedServiceIds,
|
|
4864
5109
|
getEligibleFallbacks,
|
|
4865
5110
|
getFallbackRegistrationInfo,
|
|
4866
5111
|
normalise,
|