@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/react/index.cjs
CHANGED
|
@@ -1909,6 +1909,9 @@ function toFiniteNumber(v) {
|
|
|
1909
1909
|
const n = Number(v);
|
|
1910
1910
|
return Number.isFinite(n) ? n : NaN;
|
|
1911
1911
|
}
|
|
1912
|
+
function isValidServiceIdRef(value) {
|
|
1913
|
+
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
1914
|
+
}
|
|
1912
1915
|
function constraintFitOk(svcMap, candidate, constraints) {
|
|
1913
1916
|
const cap = getServiceCapability(svcMap, candidate);
|
|
1914
1917
|
if (!cap) return false;
|
|
@@ -1917,18 +1920,32 @@ function constraintFitOk(svcMap, candidate, constraints) {
|
|
|
1917
1920
|
return !(constraints.cancel === true && !cap.cancel);
|
|
1918
1921
|
}
|
|
1919
1922
|
function getServiceCapability(svcMap, candidate) {
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
if (
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1923
|
+
var _a;
|
|
1924
|
+
return (_a = getServiceCapabilityEntry(svcMap, candidate)) == null ? void 0 : _a.capability;
|
|
1925
|
+
}
|
|
1926
|
+
function getServiceCapabilityCanonicalRef(svcMap, candidate) {
|
|
1927
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1928
|
+
if (!entry) return void 0;
|
|
1929
|
+
return getCanonicalServiceRef(entry.key, entry.capability);
|
|
1930
|
+
}
|
|
1931
|
+
function getServiceCapabilityAliases(svcMap, candidate) {
|
|
1932
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1933
|
+
if (!entry) return [];
|
|
1934
|
+
return collectServiceRefAliases(entry.key, entry.capability);
|
|
1935
|
+
}
|
|
1936
|
+
function isSameServiceCapabilityRef(svcMap, left, right) {
|
|
1937
|
+
if (!isValidServiceIdRef(left) || !isValidServiceIdRef(right)) return false;
|
|
1938
|
+
const leftAliases = new Set(
|
|
1939
|
+
getServiceCapabilityAliases(svcMap, left).map((value) => String(value))
|
|
1940
|
+
);
|
|
1941
|
+
if (!leftAliases.size) {
|
|
1942
|
+
leftAliases.add(String(left));
|
|
1930
1943
|
}
|
|
1931
|
-
|
|
1944
|
+
const rightAliases = getServiceCapabilityAliases(svcMap, right);
|
|
1945
|
+
if (!rightAliases.length) {
|
|
1946
|
+
return leftAliases.has(String(right));
|
|
1947
|
+
}
|
|
1948
|
+
return rightAliases.some((value) => leftAliases.has(String(value)));
|
|
1932
1949
|
}
|
|
1933
1950
|
function normalizeRatePolicy(policy) {
|
|
1934
1951
|
var _a;
|
|
@@ -1964,6 +1981,74 @@ function rateOk(svcMap, candidate, primary, policy) {
|
|
|
1964
1981
|
if (!Number.isFinite(cRate) || !Number.isFinite(pRate)) return false;
|
|
1965
1982
|
return passesRatePolicy(policy.ratePolicy, pRate, cRate);
|
|
1966
1983
|
}
|
|
1984
|
+
function getServiceCapabilityEntry(svcMap, candidate) {
|
|
1985
|
+
if (candidate === void 0 || candidate === null) return void 0;
|
|
1986
|
+
const direct = svcMap[candidate];
|
|
1987
|
+
if (direct) {
|
|
1988
|
+
return { key: String(candidate), capability: direct };
|
|
1989
|
+
}
|
|
1990
|
+
const byString = svcMap[String(candidate)];
|
|
1991
|
+
if (byString) {
|
|
1992
|
+
return { key: String(candidate), capability: byString };
|
|
1993
|
+
}
|
|
1994
|
+
if (typeof candidate === "string") {
|
|
1995
|
+
const maybeNumber = Number(candidate);
|
|
1996
|
+
if (Number.isFinite(maybeNumber)) {
|
|
1997
|
+
const byNumber = svcMap[maybeNumber];
|
|
1998
|
+
if (byNumber) {
|
|
1999
|
+
return { key: String(maybeNumber), capability: byNumber };
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
const target = String(candidate);
|
|
2004
|
+
for (const [key, capability] of Object.entries(svcMap != null ? svcMap : {})) {
|
|
2005
|
+
if (collectServiceRefAliases(key, capability).some(
|
|
2006
|
+
(alias) => String(alias) === target
|
|
2007
|
+
)) {
|
|
2008
|
+
return { key, capability };
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
return void 0;
|
|
2012
|
+
}
|
|
2013
|
+
function collectServiceRefAliases(key, capability) {
|
|
2014
|
+
const out = [];
|
|
2015
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2016
|
+
const push = (value) => {
|
|
2017
|
+
if (!isValidServiceIdRef(value)) return;
|
|
2018
|
+
const normalized = normalizeServiceRef(value);
|
|
2019
|
+
if (!normalized) return;
|
|
2020
|
+
const aliasKey = String(normalized);
|
|
2021
|
+
if (seen.has(aliasKey)) return;
|
|
2022
|
+
seen.add(aliasKey);
|
|
2023
|
+
out.push(normalized);
|
|
2024
|
+
};
|
|
2025
|
+
push(getCanonicalServiceRef(key, capability));
|
|
2026
|
+
push(capability.service);
|
|
2027
|
+
push(capability.key);
|
|
2028
|
+
push(capability.id);
|
|
2029
|
+
return out;
|
|
2030
|
+
}
|
|
2031
|
+
function getCanonicalServiceRef(key, capability) {
|
|
2032
|
+
const explicitRefs = [capability.service, capability.key, capability.id];
|
|
2033
|
+
for (const ref of explicitRefs) {
|
|
2034
|
+
if (!isValidServiceIdRef(ref)) continue;
|
|
2035
|
+
if (String(ref) === key) {
|
|
2036
|
+
return ref;
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
return normalizeServiceRef(key);
|
|
2040
|
+
}
|
|
2041
|
+
function normalizeServiceRef(value) {
|
|
2042
|
+
if (!isValidServiceIdRef(value)) return void 0;
|
|
2043
|
+
if (typeof value === "number") return value;
|
|
2044
|
+
const trimmed = value.trim();
|
|
2045
|
+
if (!trimmed) return void 0;
|
|
2046
|
+
const asNumber = Number(trimmed);
|
|
2047
|
+
if (Number.isFinite(asNumber) && String(asNumber) === trimmed) {
|
|
2048
|
+
return asNumber;
|
|
2049
|
+
}
|
|
2050
|
+
return trimmed;
|
|
2051
|
+
}
|
|
1967
2052
|
|
|
1968
2053
|
// src/core/validate/steps/rates.ts
|
|
1969
2054
|
function validateRates(v) {
|
|
@@ -3409,7 +3494,7 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3409
3494
|
const s = { ...DEFAULT_SETTINGS, ...settings != null ? settings : {} };
|
|
3410
3495
|
const out = [];
|
|
3411
3496
|
const fb = (_a = props.fallbacks) != null ? _a : {};
|
|
3412
|
-
const primaryRate = (
|
|
3497
|
+
const primaryRate = (primary) => rateOf(services, primary);
|
|
3413
3498
|
for (const [nodeId, list] of Object.entries((_b = fb.nodes) != null ? _b : {})) {
|
|
3414
3499
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3415
3500
|
if (!primary) {
|
|
@@ -3422,34 +3507,34 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3422
3507
|
});
|
|
3423
3508
|
continue;
|
|
3424
3509
|
}
|
|
3425
|
-
for (const
|
|
3426
|
-
const
|
|
3427
|
-
if (!
|
|
3510
|
+
for (const candidate of list) {
|
|
3511
|
+
const capability = getCap(services, candidate);
|
|
3512
|
+
if (!capability) {
|
|
3428
3513
|
out.push({
|
|
3429
3514
|
scope: "node",
|
|
3430
3515
|
nodeId,
|
|
3431
3516
|
primary,
|
|
3432
|
-
candidate
|
|
3517
|
+
candidate,
|
|
3433
3518
|
reason: "unknown_service"
|
|
3434
3519
|
});
|
|
3435
3520
|
continue;
|
|
3436
3521
|
}
|
|
3437
|
-
if (
|
|
3522
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
3438
3523
|
out.push({
|
|
3439
3524
|
scope: "node",
|
|
3440
3525
|
nodeId,
|
|
3441
3526
|
primary,
|
|
3442
|
-
candidate
|
|
3527
|
+
candidate,
|
|
3443
3528
|
reason: "cycle"
|
|
3444
3529
|
});
|
|
3445
3530
|
continue;
|
|
3446
3531
|
}
|
|
3447
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
3532
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
3448
3533
|
out.push({
|
|
3449
3534
|
scope: "node",
|
|
3450
3535
|
nodeId,
|
|
3451
3536
|
primary,
|
|
3452
|
-
candidate
|
|
3537
|
+
candidate,
|
|
3453
3538
|
reason: "rate_violation"
|
|
3454
3539
|
});
|
|
3455
3540
|
continue;
|
|
@@ -3459,58 +3544,55 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3459
3544
|
scope: "node",
|
|
3460
3545
|
nodeId,
|
|
3461
3546
|
primary,
|
|
3462
|
-
candidate
|
|
3547
|
+
candidate,
|
|
3463
3548
|
reason: "no_tag_context"
|
|
3464
3549
|
});
|
|
3465
3550
|
continue;
|
|
3466
3551
|
}
|
|
3467
|
-
let anyPass = false;
|
|
3468
|
-
let anyFail = false;
|
|
3469
3552
|
for (const tagId of tagContexts) {
|
|
3470
|
-
const
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3553
|
+
const fitsConstraints = s.requireConstraintFit ? satisfiesTagConstraints(
|
|
3554
|
+
tagId,
|
|
3555
|
+
{ services, props },
|
|
3556
|
+
capability
|
|
3557
|
+
) : true;
|
|
3558
|
+
if (fitsConstraints) continue;
|
|
3559
|
+
out.push({
|
|
3560
|
+
scope: "node",
|
|
3561
|
+
nodeId,
|
|
3562
|
+
primary,
|
|
3563
|
+
candidate,
|
|
3564
|
+
tagContext: tagId,
|
|
3565
|
+
reason: "constraint_mismatch"
|
|
3566
|
+
});
|
|
3483
3567
|
}
|
|
3484
|
-
void anyPass;
|
|
3485
|
-
void anyFail;
|
|
3486
3568
|
}
|
|
3487
3569
|
}
|
|
3488
3570
|
for (const [primary, list] of Object.entries((_c = fb.global) != null ? _c : {})) {
|
|
3489
|
-
for (const
|
|
3490
|
-
const
|
|
3491
|
-
if (!
|
|
3571
|
+
for (const candidate of list) {
|
|
3572
|
+
const capability = getCap(services, candidate);
|
|
3573
|
+
if (!capability) {
|
|
3492
3574
|
out.push({
|
|
3493
3575
|
scope: "global",
|
|
3494
3576
|
primary,
|
|
3495
|
-
candidate
|
|
3577
|
+
candidate,
|
|
3496
3578
|
reason: "unknown_service"
|
|
3497
3579
|
});
|
|
3498
3580
|
continue;
|
|
3499
3581
|
}
|
|
3500
|
-
if (
|
|
3582
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
3501
3583
|
out.push({
|
|
3502
3584
|
scope: "global",
|
|
3503
3585
|
primary,
|
|
3504
|
-
candidate
|
|
3586
|
+
candidate,
|
|
3505
3587
|
reason: "cycle"
|
|
3506
3588
|
});
|
|
3507
3589
|
continue;
|
|
3508
3590
|
}
|
|
3509
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
3591
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
3510
3592
|
out.push({
|
|
3511
3593
|
scope: "global",
|
|
3512
3594
|
primary,
|
|
3513
|
-
candidate
|
|
3595
|
+
candidate,
|
|
3514
3596
|
reason: "rate_violation"
|
|
3515
3597
|
});
|
|
3516
3598
|
}
|
|
@@ -3519,52 +3601,61 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3519
3601
|
return out;
|
|
3520
3602
|
}
|
|
3521
3603
|
function rateOf(map, id) {
|
|
3522
|
-
var _a;
|
|
3604
|
+
var _a, _b;
|
|
3523
3605
|
if (id === void 0 || id === null) return void 0;
|
|
3524
|
-
|
|
3525
|
-
return (_a = c == null ? void 0 : c.rate) != null ? _a : void 0;
|
|
3606
|
+
return (_b = (_a = getCap(map, id)) == null ? void 0 : _a.rate) != null ? _b : void 0;
|
|
3526
3607
|
}
|
|
3527
|
-
function passesRate(policy, primaryRate,
|
|
3528
|
-
if (typeof
|
|
3608
|
+
function passesRate(policy, primaryRate, candidateRate) {
|
|
3609
|
+
if (typeof candidateRate !== "number" || !Number.isFinite(candidateRate)) {
|
|
3529
3610
|
return false;
|
|
3530
|
-
|
|
3611
|
+
}
|
|
3612
|
+
if (typeof primaryRate !== "number" || !Number.isFinite(primaryRate)) {
|
|
3531
3613
|
return false;
|
|
3532
|
-
|
|
3614
|
+
}
|
|
3615
|
+
return passesRatePolicy(
|
|
3616
|
+
normalizeRatePolicy(policy),
|
|
3617
|
+
primaryRate,
|
|
3618
|
+
candidateRate
|
|
3619
|
+
);
|
|
3533
3620
|
}
|
|
3534
3621
|
function getCap(map, id) {
|
|
3535
3622
|
return getServiceCapability(map, id);
|
|
3536
3623
|
}
|
|
3537
|
-
function isCapFlagEnabled(
|
|
3624
|
+
function isCapFlagEnabled(capability, flagId) {
|
|
3538
3625
|
var _a, _b;
|
|
3539
|
-
const fromFlags = (_b = (_a =
|
|
3626
|
+
const fromFlags = (_b = (_a = capability.flags) == null ? void 0 : _a[flagId]) == null ? void 0 : _b.enabled;
|
|
3540
3627
|
if (fromFlags === true) return true;
|
|
3541
3628
|
if (fromFlags === false) return false;
|
|
3542
|
-
const legacy =
|
|
3629
|
+
const legacy = capability[flagId];
|
|
3543
3630
|
return legacy === true;
|
|
3544
3631
|
}
|
|
3545
|
-
function satisfiesTagConstraints(tagId, ctx,
|
|
3546
|
-
const tag = ctx.props.filters.find((
|
|
3547
|
-
const
|
|
3548
|
-
if (!
|
|
3549
|
-
for (const [key, value] of Object.entries(
|
|
3550
|
-
if (value === true && !isCapFlagEnabled(
|
|
3632
|
+
function satisfiesTagConstraints(tagId, ctx, capability) {
|
|
3633
|
+
const tag = ctx.props.filters.find((item) => item.id === tagId);
|
|
3634
|
+
const effectiveConstraints2 = tag == null ? void 0 : tag.constraints;
|
|
3635
|
+
if (!effectiveConstraints2) return true;
|
|
3636
|
+
for (const [key, value] of Object.entries(effectiveConstraints2)) {
|
|
3637
|
+
if (value === true && !isCapFlagEnabled(capability, key)) {
|
|
3551
3638
|
return false;
|
|
3552
3639
|
}
|
|
3553
3640
|
}
|
|
3554
3641
|
return true;
|
|
3555
3642
|
}
|
|
3556
3643
|
function primaryForNode(props, nodeId) {
|
|
3557
|
-
const tag = props.filters.find((
|
|
3644
|
+
const tag = props.filters.find((item) => item.id === nodeId);
|
|
3558
3645
|
if (tag) {
|
|
3559
3646
|
return { primary: tag.service_id, tagContexts: [tag.id] };
|
|
3560
3647
|
}
|
|
3561
3648
|
const field = props.fields.find(
|
|
3562
|
-
(
|
|
3649
|
+
(item) => Array.isArray(item.options) && item.options.some((option2) => option2.id === nodeId)
|
|
3563
3650
|
);
|
|
3564
|
-
if (!field)
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3651
|
+
if (!field) {
|
|
3652
|
+
return { tagContexts: [], reasonNoPrimary: "no_parent_field" };
|
|
3653
|
+
}
|
|
3654
|
+
const option = field.options.find((item) => item.id === nodeId);
|
|
3655
|
+
return {
|
|
3656
|
+
primary: option.service_id,
|
|
3657
|
+
tagContexts: bindIdsToArray(field.bind_id)
|
|
3658
|
+
};
|
|
3568
3659
|
}
|
|
3569
3660
|
function bindIdsToArray(bind) {
|
|
3570
3661
|
if (!bind) return [];
|
|
@@ -3574,43 +3665,54 @@ function getEligibleFallbacks(params) {
|
|
|
3574
3665
|
var _a, _b, _c, _d, _e, _f;
|
|
3575
3666
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
3576
3667
|
const { primary, nodeId, tagId, services } = params;
|
|
3577
|
-
const
|
|
3578
|
-
const
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3668
|
+
const excludes = /* @__PURE__ */ new Set();
|
|
3669
|
+
for (const ref of (_b = params.exclude) != null ? _b : []) {
|
|
3670
|
+
addComparableServiceRef(excludes, services, ref);
|
|
3671
|
+
}
|
|
3672
|
+
addComparableServiceRef(excludes, services, primary);
|
|
3673
|
+
const source = (_c = params.source) != null ? _c : "registered";
|
|
3674
|
+
const candidateLists = source === "all_services" ? [listServicePoolCandidates(services)] : listRegisteredFallbackCandidates(
|
|
3675
|
+
(_d = params.fallbacks) != null ? _d : {},
|
|
3676
|
+
primary,
|
|
3677
|
+
nodeId,
|
|
3678
|
+
services
|
|
3679
|
+
);
|
|
3680
|
+
if (!candidateLists.length) return [];
|
|
3585
3681
|
const primaryRate = rateOf(services, primary);
|
|
3586
3682
|
const seen = /* @__PURE__ */ new Set();
|
|
3587
3683
|
const eligible = [];
|
|
3588
|
-
for (const list of
|
|
3589
|
-
for (const
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
if (
|
|
3593
|
-
|
|
3594
|
-
const
|
|
3595
|
-
|
|
3596
|
-
|
|
3684
|
+
for (const list of candidateLists) {
|
|
3685
|
+
for (const candidate of list) {
|
|
3686
|
+
if (hasComparableServiceRef(excludes, services, candidate)) continue;
|
|
3687
|
+
const capability = getCap(services, candidate);
|
|
3688
|
+
if (!capability) continue;
|
|
3689
|
+
const candidateId = (_e = getServiceCapabilityCanonicalRef(services, candidate)) != null ? _e : candidate;
|
|
3690
|
+
const candidateIdentity = getComparableServiceRefKey(
|
|
3691
|
+
services,
|
|
3692
|
+
candidateId
|
|
3693
|
+
);
|
|
3694
|
+
if (((_f = params.unique) != null ? _f : true) && seen.has(candidateIdentity)) continue;
|
|
3695
|
+
seen.add(candidateIdentity);
|
|
3696
|
+
if (!passesRate(s.ratePolicy, primaryRate, capability.rate)) {
|
|
3697
|
+
continue;
|
|
3698
|
+
}
|
|
3597
3699
|
if (s.requireConstraintFit && tagId) {
|
|
3598
|
-
const
|
|
3700
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
3599
3701
|
tagId,
|
|
3600
3702
|
{ props: params.props, services },
|
|
3601
|
-
|
|
3703
|
+
capability
|
|
3602
3704
|
);
|
|
3603
|
-
if (!
|
|
3705
|
+
if (!fitsConstraints) continue;
|
|
3604
3706
|
}
|
|
3605
|
-
eligible.push(
|
|
3707
|
+
eligible.push(candidateId);
|
|
3606
3708
|
}
|
|
3607
3709
|
}
|
|
3608
3710
|
if (s.selectionStrategy === "cheapest") {
|
|
3609
|
-
eligible.sort((
|
|
3711
|
+
eligible.sort((left, right) => {
|
|
3610
3712
|
var _a2, _b2;
|
|
3611
|
-
const
|
|
3612
|
-
const
|
|
3613
|
-
return
|
|
3713
|
+
const leftRate = (_a2 = rateOf(services, left)) != null ? _a2 : Infinity;
|
|
3714
|
+
const rightRate = (_b2 = rateOf(services, right)) != null ? _b2 : Infinity;
|
|
3715
|
+
return leftRate - rightRate;
|
|
3614
3716
|
});
|
|
3615
3717
|
}
|
|
3616
3718
|
if (typeof params.limit === "number" && params.limit >= 0) {
|
|
@@ -3618,10 +3720,104 @@ function getEligibleFallbacks(params) {
|
|
|
3618
3720
|
}
|
|
3619
3721
|
return eligible;
|
|
3620
3722
|
}
|
|
3723
|
+
function getAssignedServiceIds(params) {
|
|
3724
|
+
var _a, _b, _c, _d, _e;
|
|
3725
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3726
|
+
const out = [];
|
|
3727
|
+
const push = (value) => {
|
|
3728
|
+
if (!isValidServiceIdRef(value)) return;
|
|
3729
|
+
const key = String(value);
|
|
3730
|
+
if (seen.has(key)) return;
|
|
3731
|
+
seen.add(key);
|
|
3732
|
+
out.push(value);
|
|
3733
|
+
};
|
|
3734
|
+
const props = params.props;
|
|
3735
|
+
if (props) {
|
|
3736
|
+
for (const tag of (_a = props.filters) != null ? _a : []) {
|
|
3737
|
+
push(tag.service_id);
|
|
3738
|
+
}
|
|
3739
|
+
for (const field of (_b = props.fields) != null ? _b : []) {
|
|
3740
|
+
const fieldService = field.service_id;
|
|
3741
|
+
if (field.button === true) {
|
|
3742
|
+
push(fieldService);
|
|
3743
|
+
}
|
|
3744
|
+
for (const option of (_c = field.options) != null ? _c : []) {
|
|
3745
|
+
if (option.pricing_role === "utility") continue;
|
|
3746
|
+
push(option.service_id);
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
const snapshot = params.snapshot;
|
|
3751
|
+
if (snapshot) {
|
|
3752
|
+
for (const serviceId of (_d = snapshot.services) != null ? _d : []) {
|
|
3753
|
+
push(serviceId);
|
|
3754
|
+
}
|
|
3755
|
+
for (const list of Object.values((_e = snapshot.serviceMap) != null ? _e : {})) {
|
|
3756
|
+
for (const serviceId of list != null ? list : []) {
|
|
3757
|
+
push(serviceId);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
return out;
|
|
3762
|
+
}
|
|
3621
3763
|
function getFallbackRegistrationInfo(props, nodeId) {
|
|
3622
3764
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3623
3765
|
return { primary, tagContexts };
|
|
3624
3766
|
}
|
|
3767
|
+
function listRegisteredFallbackCandidates(fallbacks, primary, nodeId, services) {
|
|
3768
|
+
var _a, _b;
|
|
3769
|
+
const lists = [];
|
|
3770
|
+
if (nodeId && ((_a = fallbacks.nodes) == null ? void 0 : _a[nodeId])) {
|
|
3771
|
+
lists.push(fallbacks.nodes[nodeId]);
|
|
3772
|
+
}
|
|
3773
|
+
for (const [registeredPrimary, list] of Object.entries((_b = fallbacks.global) != null ? _b : {})) {
|
|
3774
|
+
if (!isMatchingServiceRef(services, registeredPrimary, primary)) continue;
|
|
3775
|
+
lists.push(list);
|
|
3776
|
+
}
|
|
3777
|
+
return lists;
|
|
3778
|
+
}
|
|
3779
|
+
function listServicePoolCandidates(services) {
|
|
3780
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3781
|
+
const out = [];
|
|
3782
|
+
for (const [key, capability] of Object.entries(services != null ? services : {})) {
|
|
3783
|
+
const candidate = getServicePoolCandidateId(key, capability);
|
|
3784
|
+
if (!isValidServiceIdRef(candidate)) continue;
|
|
3785
|
+
const identity = getComparableServiceRefKey(services, candidate);
|
|
3786
|
+
if (seen.has(identity)) continue;
|
|
3787
|
+
seen.add(identity);
|
|
3788
|
+
out.push(candidate);
|
|
3789
|
+
}
|
|
3790
|
+
return out;
|
|
3791
|
+
}
|
|
3792
|
+
function getServicePoolCandidateId(key, capability) {
|
|
3793
|
+
var _a;
|
|
3794
|
+
return (_a = getServiceCapabilityCanonicalRef({ [key]: capability }, key)) != null ? _a : key;
|
|
3795
|
+
}
|
|
3796
|
+
function addComparableServiceRef(target, services, value) {
|
|
3797
|
+
for (const ref of getComparableServiceRefs(services, value)) {
|
|
3798
|
+
target.add(ref);
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
function hasComparableServiceRef(target, services, value) {
|
|
3802
|
+
return getComparableServiceRefs(services, value).some((ref) => target.has(ref));
|
|
3803
|
+
}
|
|
3804
|
+
function getComparableServiceRefKey(services, value) {
|
|
3805
|
+
if (!isValidServiceIdRef(value)) return "";
|
|
3806
|
+
const canonical = getServiceCapabilityCanonicalRef(services, value);
|
|
3807
|
+
return String(canonical != null ? canonical : value);
|
|
3808
|
+
}
|
|
3809
|
+
function getComparableServiceRefs(services, value) {
|
|
3810
|
+
if (!isValidServiceIdRef(value)) return [];
|
|
3811
|
+
const aliases = getServiceCapabilityAliases(services, value);
|
|
3812
|
+
if (!aliases.length) {
|
|
3813
|
+
return [String(value)];
|
|
3814
|
+
}
|
|
3815
|
+
return aliases.map((ref) => String(ref));
|
|
3816
|
+
}
|
|
3817
|
+
function isMatchingServiceRef(services, left, right) {
|
|
3818
|
+
if (!services) return String(left) === String(right);
|
|
3819
|
+
return isSameServiceCapabilityRef(services, left, right);
|
|
3820
|
+
}
|
|
3625
3821
|
|
|
3626
3822
|
// src/core/tag-relations.ts
|
|
3627
3823
|
var toId = (x) => typeof x === "string" ? x : x.id;
|
|
@@ -5160,6 +5356,7 @@ function createFallbackEditor(options = {}) {
|
|
|
5160
5356
|
const original = cloneFallbacks(options.fallbacks);
|
|
5161
5357
|
let current = cloneFallbacks(options.fallbacks);
|
|
5162
5358
|
const props = options.props;
|
|
5359
|
+
const snapshot = options.snapshot;
|
|
5163
5360
|
const services = (_a = options.services) != null ? _a : {};
|
|
5164
5361
|
const settings = (_b = options.settings) != null ? _b : {};
|
|
5165
5362
|
function state() {
|
|
@@ -5254,7 +5451,11 @@ function createFallbackEditor(options = {}) {
|
|
|
5254
5451
|
const allowed2 = [];
|
|
5255
5452
|
for (const candidate of normalized) {
|
|
5256
5453
|
const reasons = [];
|
|
5257
|
-
if (
|
|
5454
|
+
if (isSameServiceCapabilityRef(
|
|
5455
|
+
services,
|
|
5456
|
+
candidate,
|
|
5457
|
+
context.primary
|
|
5458
|
+
)) {
|
|
5258
5459
|
reasons.push("self_reference");
|
|
5259
5460
|
}
|
|
5260
5461
|
if (reasons.length) {
|
|
@@ -5342,7 +5543,19 @@ function createFallbackEditor(options = {}) {
|
|
|
5342
5543
|
return writeScope(context, []);
|
|
5343
5544
|
}
|
|
5344
5545
|
function eligible(context, opt) {
|
|
5546
|
+
var _a2, _b2;
|
|
5345
5547
|
if (!props) return [];
|
|
5548
|
+
const source = (_a2 = opt == null ? void 0 : opt.source) != null ? _a2 : "all_services";
|
|
5549
|
+
const exclude2 = normalizeCandidateList(
|
|
5550
|
+
[
|
|
5551
|
+
...(_b2 = opt == null ? void 0 : opt.exclude) != null ? _b2 : [],
|
|
5552
|
+
...source === "all_services" ? [
|
|
5553
|
+
...getAssignedServiceIds({ props, snapshot }),
|
|
5554
|
+
...getScope(context)
|
|
5555
|
+
] : []
|
|
5556
|
+
],
|
|
5557
|
+
true
|
|
5558
|
+
);
|
|
5346
5559
|
if (context.scope === "global") {
|
|
5347
5560
|
return getEligibleFallbacks({
|
|
5348
5561
|
primary: context.primary,
|
|
@@ -5350,9 +5563,10 @@ function createFallbackEditor(options = {}) {
|
|
|
5350
5563
|
fallbacks: current,
|
|
5351
5564
|
settings,
|
|
5352
5565
|
props,
|
|
5353
|
-
exclude:
|
|
5566
|
+
exclude: exclude2,
|
|
5354
5567
|
unique: opt == null ? void 0 : opt.unique,
|
|
5355
|
-
limit: opt == null ? void 0 : opt.limit
|
|
5568
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
5569
|
+
source
|
|
5356
5570
|
});
|
|
5357
5571
|
}
|
|
5358
5572
|
const info = getFallbackRegistrationInfo(props, context.nodeId);
|
|
@@ -5360,14 +5574,19 @@ function createFallbackEditor(options = {}) {
|
|
|
5360
5574
|
return getEligibleFallbacks({
|
|
5361
5575
|
primary: info.primary,
|
|
5362
5576
|
nodeId: context.nodeId,
|
|
5363
|
-
tagId:
|
|
5577
|
+
tagId: resolveNodeTagContext({
|
|
5578
|
+
nodeId: context.nodeId,
|
|
5579
|
+
snapshot,
|
|
5580
|
+
fallbackTagContexts: info.tagContexts
|
|
5581
|
+
}),
|
|
5364
5582
|
services,
|
|
5365
5583
|
fallbacks: current,
|
|
5366
5584
|
settings,
|
|
5367
5585
|
props,
|
|
5368
|
-
exclude:
|
|
5586
|
+
exclude: exclude2,
|
|
5369
5587
|
unique: opt == null ? void 0 : opt.unique,
|
|
5370
|
-
limit: opt == null ? void 0 : opt.limit
|
|
5588
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
5589
|
+
source
|
|
5371
5590
|
});
|
|
5372
5591
|
}
|
|
5373
5592
|
function writeScope(context, nextList) {
|
|
@@ -5425,14 +5644,14 @@ function sameFallbacks(a, b) {
|
|
|
5425
5644
|
function normalizeCandidateList(input, preserveOrder) {
|
|
5426
5645
|
const out = [];
|
|
5427
5646
|
for (const item of input != null ? input : []) {
|
|
5428
|
-
if (!
|
|
5647
|
+
if (!isValidServiceIdRef2(item)) continue;
|
|
5429
5648
|
const exists = out.some((x) => String(x) === String(item));
|
|
5430
5649
|
if (exists) continue;
|
|
5431
5650
|
out.push(item);
|
|
5432
5651
|
}
|
|
5433
5652
|
return preserveOrder ? out : out;
|
|
5434
5653
|
}
|
|
5435
|
-
function
|
|
5654
|
+
function isValidServiceIdRef2(value) {
|
|
5436
5655
|
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
5437
5656
|
}
|
|
5438
5657
|
function clamp(n, min, max) {
|
|
@@ -5441,7 +5660,7 @@ function clamp(n, min, max) {
|
|
|
5441
5660
|
function getNodeRegistrationInfo(props, nodeId) {
|
|
5442
5661
|
const tag = props.filters.find((t) => t.id === nodeId);
|
|
5443
5662
|
if (tag) {
|
|
5444
|
-
if (!
|
|
5663
|
+
if (!isValidServiceIdRef2(tag.service_id)) {
|
|
5445
5664
|
return { ok: false, reasons: ["no_primary"] };
|
|
5446
5665
|
}
|
|
5447
5666
|
return {
|
|
@@ -5454,7 +5673,7 @@ function getNodeRegistrationInfo(props, nodeId) {
|
|
|
5454
5673
|
if (!hit) {
|
|
5455
5674
|
return { ok: false, reasons: ["node_not_found"] };
|
|
5456
5675
|
}
|
|
5457
|
-
if (!
|
|
5676
|
+
if (!isValidServiceIdRef2(hit.option.service_id)) {
|
|
5458
5677
|
return { ok: false, reasons: ["no_primary"] };
|
|
5459
5678
|
}
|
|
5460
5679
|
return {
|
|
@@ -5476,6 +5695,15 @@ function bindIdsToArray2(v) {
|
|
|
5476
5695
|
if (Array.isArray(v)) return v.filter(Boolean);
|
|
5477
5696
|
return v ? [v] : [];
|
|
5478
5697
|
}
|
|
5698
|
+
function resolveNodeTagContext(params) {
|
|
5699
|
+
var _a, _b, _c;
|
|
5700
|
+
const nodeContexts = (_c = (_b = (_a = params.snapshot) == null ? void 0 : _a.meta) == null ? void 0 : _b.context) == null ? void 0 : _c.nodeContexts;
|
|
5701
|
+
if (nodeContexts && Object.prototype.hasOwnProperty.call(nodeContexts, params.nodeId)) {
|
|
5702
|
+
const tagId = nodeContexts[params.nodeId];
|
|
5703
|
+
return typeof tagId === "string" && tagId.trim().length > 0 ? tagId : void 0;
|
|
5704
|
+
}
|
|
5705
|
+
return params.fallbackTagContexts[0];
|
|
5706
|
+
}
|
|
5479
5707
|
function mapDiagReason(reason) {
|
|
5480
5708
|
switch (String(reason)) {
|
|
5481
5709
|
case "unknown_service":
|
|
@@ -12167,10 +12395,10 @@ function FallbackEditorInner({ className }) {
|
|
|
12167
12395
|
"div",
|
|
12168
12396
|
{
|
|
12169
12397
|
className: [
|
|
12170
|
-
"min-h-
|
|
12398
|
+
"h-full min-h-0 overflow-hidden bg-zinc-100 p-4 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100",
|
|
12171
12399
|
className
|
|
12172
12400
|
].filter(Boolean).join(" "),
|
|
12173
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "
|
|
12401
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex h-full min-h-0 flex-col gap-4", children: [
|
|
12174
12402
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
12175
12403
|
FallbackEditorHeader,
|
|
12176
12404
|
{
|
|
@@ -12182,9 +12410,9 @@ function FallbackEditorInner({ className }) {
|
|
|
12182
12410
|
saving: headerSaving
|
|
12183
12411
|
}
|
|
12184
12412
|
),
|
|
12185
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
12413
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid min-h-0 flex-1 gap-4 overflow-hidden xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
12186
12414
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackServiceSidebar, {}),
|
|
12187
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
12415
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-col gap-4 overflow-y-auto", children: [
|
|
12188
12416
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
12189
12417
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
12190
12418
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: activeServiceId !== void 0 ? `Service #${String(activeServiceId)}` : "No service selected" }),
|
|
@@ -12328,7 +12556,7 @@ function FallbackDetailsPanel() {
|
|
|
12328
12556
|
() => services.find((s) => String(s.id) === String(activeServiceId)),
|
|
12329
12557
|
[services, activeServiceId]
|
|
12330
12558
|
);
|
|
12331
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
12559
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { className: "flex min-h-0 flex-col gap-4 overflow-y-auto", children: [
|
|
12332
12560
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12333
12561
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary service info" }),
|
|
12334
12562
|
!service ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "mt-3 text-sm text-zinc-500 dark:text-zinc-400", children: "No service selected." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-3 space-y-2 text-sm", children: [
|
|
@@ -12490,7 +12718,7 @@ function FallbackSettingsPanel() {
|
|
|
12490
12718
|
kind: "lte_primary",
|
|
12491
12719
|
pct: 5
|
|
12492
12720
|
};
|
|
12493
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 overflow-y-auto", children: [
|
|
12494
12722
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
12495
12723
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
12496
12724
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Fallback settings" }),
|
|
@@ -12689,7 +12917,7 @@ function FallbackServiceSidebar() {
|
|
|
12689
12917
|
}
|
|
12690
12918
|
);
|
|
12691
12919
|
}, [query, services]);
|
|
12692
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className: "flex min-h-0 flex-col rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className: "flex h-full min-h-0 flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12693
12921
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
12694
12922
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary services" }),
|
|
12695
12923
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Services currently active in the builder/runtime context." })
|
|
@@ -12704,7 +12932,7 @@ function FallbackServiceSidebar() {
|
|
|
12704
12932
|
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
|
12705
12933
|
}
|
|
12706
12934
|
),
|
|
12707
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-3 flex-1 space-y-2 overflow-auto", children: filtered.map((service) => {
|
|
12935
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-3 flex-1 space-y-2 overflow-y-auto", children: filtered.map((service) => {
|
|
12708
12936
|
var _a, _b;
|
|
12709
12937
|
const active = String(service.id) === String(activeServiceId);
|
|
12710
12938
|
const count = get(service.id).length;
|
|
@@ -12745,11 +12973,172 @@ function FallbackServiceSidebar() {
|
|
|
12745
12973
|
}
|
|
12746
12974
|
|
|
12747
12975
|
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
12748
|
-
var import_react23 = __toESM(require("react"), 1);
|
|
12749
|
-
|
|
12750
|
-
// src/react/fallback-editor/FallbackAddCandidatesDialog.tsx
|
|
12751
12976
|
var import_react21 = __toESM(require("react"), 1);
|
|
12752
12977
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
12978
|
+
function FallbackRegistrationsPanel() {
|
|
12979
|
+
const { activeServiceId, remove: remove2, clear, check } = useFallbackEditor();
|
|
12980
|
+
const registrations = useActiveFallbackRegistrations();
|
|
12981
|
+
const eligibleServices = useEligibleServiceList();
|
|
12982
|
+
const [candidatePickerOpen, setCandidatePickerOpen] = import_react21.default.useState(false);
|
|
12983
|
+
const [candidateContext, setCandidateContext] = import_react21.default.useState(null);
|
|
12984
|
+
const [candidatePrimaryId, setCandidatePrimaryId] = import_react21.default.useState(void 0);
|
|
12985
|
+
const [registrationDialogOpen, setRegistrationDialogOpen] = import_react21.default.useState(false);
|
|
12986
|
+
const makeContext = import_react21.default.useCallback(
|
|
12987
|
+
(registration) => {
|
|
12988
|
+
if (registration.scope === "global") {
|
|
12989
|
+
return {
|
|
12990
|
+
scope: "global",
|
|
12991
|
+
primary: registration.primary
|
|
12992
|
+
};
|
|
12993
|
+
}
|
|
12994
|
+
return {
|
|
12995
|
+
scope: "node",
|
|
12996
|
+
nodeId: registration.scopeId
|
|
12997
|
+
};
|
|
12998
|
+
},
|
|
12999
|
+
[]
|
|
13000
|
+
);
|
|
13001
|
+
const openCandidatePicker = import_react21.default.useCallback(
|
|
13002
|
+
(context, primaryId) => {
|
|
13003
|
+
setCandidateContext(context);
|
|
13004
|
+
setCandidatePrimaryId(primaryId);
|
|
13005
|
+
setCandidatePickerOpen(true);
|
|
13006
|
+
},
|
|
13007
|
+
[]
|
|
13008
|
+
);
|
|
13009
|
+
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
13010
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 ", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "Select a primary service to start editing." }) });
|
|
13011
|
+
}
|
|
13012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
13013
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 overflow-y-auto", children: [
|
|
13014
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
13015
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
13016
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
13017
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
13018
|
+
] }),
|
|
13019
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13020
|
+
"button",
|
|
13021
|
+
{
|
|
13022
|
+
type: "button",
|
|
13023
|
+
onClick: () => setRegistrationDialogOpen(true),
|
|
13024
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13025
|
+
children: "Add registration"
|
|
13026
|
+
}
|
|
13027
|
+
)
|
|
13028
|
+
] }),
|
|
13029
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "No registrations yet for this primary service." }) : registrations.map((reg, index) => {
|
|
13030
|
+
var _a;
|
|
13031
|
+
const context = makeContext(reg);
|
|
13032
|
+
const candidates = reg.services;
|
|
13033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
13034
|
+
"div",
|
|
13035
|
+
{
|
|
13036
|
+
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
13037
|
+
children: [
|
|
13038
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
13039
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
13040
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
13041
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
13042
|
+
"Primary #",
|
|
13043
|
+
String(reg.primary)
|
|
13044
|
+
] })
|
|
13045
|
+
] }),
|
|
13046
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rounded-full border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300", children: [
|
|
13047
|
+
reg.scope,
|
|
13048
|
+
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
13049
|
+
] })
|
|
13050
|
+
] }),
|
|
13051
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
13052
|
+
var _a2;
|
|
13053
|
+
const preview = check(context, [
|
|
13054
|
+
candidate
|
|
13055
|
+
]);
|
|
13056
|
+
const rejected = preview.rejected[0];
|
|
13057
|
+
const tone = rejected ? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300" : "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
|
13058
|
+
const service = eligibleServices.find(
|
|
13059
|
+
(s) => String(s.id) === String(candidate)
|
|
13060
|
+
);
|
|
13061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
13062
|
+
"div",
|
|
13063
|
+
{
|
|
13064
|
+
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
13065
|
+
children: [
|
|
13066
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
13067
|
+
rejected ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
13068
|
+
", "
|
|
13069
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
13070
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13071
|
+
"button",
|
|
13072
|
+
{
|
|
13073
|
+
type: "button",
|
|
13074
|
+
onClick: () => remove2(
|
|
13075
|
+
context,
|
|
13076
|
+
candidate
|
|
13077
|
+
),
|
|
13078
|
+
className: "text-current/70 hover:text-current",
|
|
13079
|
+
children: "\xD7"
|
|
13080
|
+
}
|
|
13081
|
+
)
|
|
13082
|
+
]
|
|
13083
|
+
},
|
|
13084
|
+
String(candidate)
|
|
13085
|
+
);
|
|
13086
|
+
}) }),
|
|
13087
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-4 flex gap-2", children: [
|
|
13088
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13089
|
+
"button",
|
|
13090
|
+
{
|
|
13091
|
+
type: "button",
|
|
13092
|
+
onClick: () => openCandidatePicker(
|
|
13093
|
+
context,
|
|
13094
|
+
reg.primary
|
|
13095
|
+
),
|
|
13096
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13097
|
+
children: "Add fallback"
|
|
13098
|
+
}
|
|
13099
|
+
),
|
|
13100
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13101
|
+
"button",
|
|
13102
|
+
{
|
|
13103
|
+
type: "button",
|
|
13104
|
+
onClick: () => clear(context),
|
|
13105
|
+
className: "rounded-xl border border-red-300 bg-white px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 dark:border-red-900/50 dark:bg-zinc-900 dark:text-red-300 dark:hover:bg-red-950/20",
|
|
13106
|
+
children: "Clear"
|
|
13107
|
+
}
|
|
13108
|
+
)
|
|
13109
|
+
] })
|
|
13110
|
+
]
|
|
13111
|
+
},
|
|
13112
|
+
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
13113
|
+
);
|
|
13114
|
+
}) })
|
|
13115
|
+
] }),
|
|
13116
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13117
|
+
FallbackAddRegistrationDialog,
|
|
13118
|
+
{
|
|
13119
|
+
open: registrationDialogOpen,
|
|
13120
|
+
onClose: () => setRegistrationDialogOpen(false),
|
|
13121
|
+
onSelect: (context, primaryId) => {
|
|
13122
|
+
setRegistrationDialogOpen(false);
|
|
13123
|
+
openCandidatePicker(context, primaryId);
|
|
13124
|
+
}
|
|
13125
|
+
}
|
|
13126
|
+
),
|
|
13127
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13128
|
+
FallbackAddCandidatesDialog,
|
|
13129
|
+
{
|
|
13130
|
+
open: candidatePickerOpen,
|
|
13131
|
+
onClose: () => setCandidatePickerOpen(false),
|
|
13132
|
+
context: candidateContext,
|
|
13133
|
+
primaryId: candidatePrimaryId
|
|
13134
|
+
}
|
|
13135
|
+
)
|
|
13136
|
+
] });
|
|
13137
|
+
}
|
|
13138
|
+
|
|
13139
|
+
// src/react/fallback-editor/FallbackAddCandidatesDialog.tsx
|
|
13140
|
+
var import_react25 = __toESM(require("react"), 1);
|
|
13141
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
12753
13142
|
function FallbackAddCandidatesDialog({
|
|
12754
13143
|
open,
|
|
12755
13144
|
onClose,
|
|
@@ -12758,23 +13147,23 @@ function FallbackAddCandidatesDialog({
|
|
|
12758
13147
|
}) {
|
|
12759
13148
|
const { eligible, addMany } = useFallbackEditor();
|
|
12760
13149
|
const eligibleServices = useEligibleServiceList();
|
|
12761
|
-
const [query, setQuery] =
|
|
12762
|
-
const [filterEligibleOnly, setFilterEligibleOnly] =
|
|
12763
|
-
const [selected, setSelected] =
|
|
12764
|
-
const [submitting, setSubmitting] =
|
|
12765
|
-
|
|
13150
|
+
const [query, setQuery] = import_react25.default.useState("");
|
|
13151
|
+
const [filterEligibleOnly, setFilterEligibleOnly] = import_react25.default.useState(true);
|
|
13152
|
+
const [selected, setSelected] = import_react25.default.useState(/* @__PURE__ */ new Set());
|
|
13153
|
+
const [submitting, setSubmitting] = import_react25.default.useState(false);
|
|
13154
|
+
import_react25.default.useEffect(() => {
|
|
12766
13155
|
if (!open) {
|
|
12767
13156
|
setQuery("");
|
|
12768
13157
|
setFilterEligibleOnly(true);
|
|
12769
13158
|
setSelected(/* @__PURE__ */ new Set());
|
|
12770
13159
|
}
|
|
12771
13160
|
}, [open]);
|
|
12772
|
-
const allowedIds =
|
|
13161
|
+
const allowedIds = import_react25.default.useMemo(() => {
|
|
12773
13162
|
if (!context) return null;
|
|
12774
13163
|
if (!filterEligibleOnly) return null;
|
|
12775
13164
|
return new Set(eligible(context).map((id) => String(id)));
|
|
12776
13165
|
}, [context, filterEligibleOnly, eligible]);
|
|
12777
|
-
const items =
|
|
13166
|
+
const items = import_react25.default.useMemo(() => {
|
|
12778
13167
|
const q = query.trim().toLowerCase();
|
|
12779
13168
|
return eligibleServices.filter((service) => {
|
|
12780
13169
|
var _a, _b;
|
|
@@ -12809,13 +13198,13 @@ function FallbackAddCandidatesDialog({
|
|
|
12809
13198
|
}
|
|
12810
13199
|
}
|
|
12811
13200
|
if (!open || !context) return null;
|
|
12812
|
-
return /* @__PURE__ */ (0,
|
|
12813
|
-
/* @__PURE__ */ (0,
|
|
12814
|
-
/* @__PURE__ */ (0,
|
|
12815
|
-
/* @__PURE__ */ (0,
|
|
13201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex max-h-[85vh] w-full max-w-3xl flex-col rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13202
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13203
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add fallback services" }),
|
|
13204
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Search and select one or more eligible fallback candidates." })
|
|
12816
13205
|
] }),
|
|
12817
|
-
/* @__PURE__ */ (0,
|
|
12818
|
-
/* @__PURE__ */ (0,
|
|
13206
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
|
|
13207
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12819
13208
|
"input",
|
|
12820
13209
|
{
|
|
12821
13210
|
value: query,
|
|
@@ -12824,8 +13213,8 @@ function FallbackAddCandidatesDialog({
|
|
|
12824
13213
|
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
|
12825
13214
|
}
|
|
12826
13215
|
),
|
|
12827
|
-
/* @__PURE__ */ (0,
|
|
12828
|
-
/* @__PURE__ */ (0,
|
|
13216
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "inline-flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [
|
|
13217
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12829
13218
|
"input",
|
|
12830
13219
|
{
|
|
12831
13220
|
type: "checkbox",
|
|
@@ -12836,7 +13225,7 @@ function FallbackAddCandidatesDialog({
|
|
|
12836
13225
|
),
|
|
12837
13226
|
"Filter eligible only"
|
|
12838
13227
|
] }),
|
|
12839
|
-
/* @__PURE__ */ (0,
|
|
13228
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12840
13229
|
VirtualServiceList,
|
|
12841
13230
|
{
|
|
12842
13231
|
items,
|
|
@@ -12846,13 +13235,13 @@ function FallbackAddCandidatesDialog({
|
|
|
12846
13235
|
}
|
|
12847
13236
|
)
|
|
12848
13237
|
] }),
|
|
12849
|
-
/* @__PURE__ */ (0,
|
|
12850
|
-
/* @__PURE__ */ (0,
|
|
13238
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13239
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: [
|
|
12851
13240
|
selected.size,
|
|
12852
13241
|
" selected"
|
|
12853
13242
|
] }),
|
|
12854
|
-
/* @__PURE__ */ (0,
|
|
12855
|
-
/* @__PURE__ */ (0,
|
|
13243
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-2", children: [
|
|
13244
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12856
13245
|
"button",
|
|
12857
13246
|
{
|
|
12858
13247
|
type: "button",
|
|
@@ -12861,7 +13250,7 @@ function FallbackAddCandidatesDialog({
|
|
|
12861
13250
|
children: "Cancel"
|
|
12862
13251
|
}
|
|
12863
13252
|
),
|
|
12864
|
-
/* @__PURE__ */ (0,
|
|
13253
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12865
13254
|
"button",
|
|
12866
13255
|
{
|
|
12867
13256
|
type: "button",
|
|
@@ -12877,8 +13266,8 @@ function FallbackAddCandidatesDialog({
|
|
|
12877
13266
|
}
|
|
12878
13267
|
|
|
12879
13268
|
// src/react/fallback-editor/FallbackAddRegistrationDialog.tsx
|
|
12880
|
-
var
|
|
12881
|
-
var
|
|
13269
|
+
var import_react26 = __toESM(require("react"), 1);
|
|
13270
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
12882
13271
|
function FallbackAddRegistrationDialog({
|
|
12883
13272
|
open,
|
|
12884
13273
|
onClose,
|
|
@@ -12886,23 +13275,23 @@ function FallbackAddRegistrationDialog({
|
|
|
12886
13275
|
}) {
|
|
12887
13276
|
const { activeServiceId, serviceProps, snapshot } = useFallbackEditor();
|
|
12888
13277
|
const registrations = useActiveFallbackRegistrations();
|
|
12889
|
-
const [scope, setScope] =
|
|
12890
|
-
const [nodeId, setNodeId] =
|
|
12891
|
-
const mode =
|
|
13278
|
+
const [scope, setScope] = import_react26.default.useState("global");
|
|
13279
|
+
const [nodeId, setNodeId] = import_react26.default.useState("");
|
|
13280
|
+
const mode = import_react26.default.useMemo(() => {
|
|
12892
13281
|
if (snapshot) return "snapshot";
|
|
12893
13282
|
if (serviceProps) return "props";
|
|
12894
13283
|
return "none";
|
|
12895
13284
|
}, [snapshot, serviceProps]);
|
|
12896
|
-
|
|
13285
|
+
import_react26.default.useEffect(() => {
|
|
12897
13286
|
if (open) {
|
|
12898
13287
|
setScope("global");
|
|
12899
13288
|
setNodeId("");
|
|
12900
13289
|
}
|
|
12901
13290
|
}, [open]);
|
|
12902
|
-
const hasGlobal =
|
|
13291
|
+
const hasGlobal = import_react26.default.useMemo(() => {
|
|
12903
13292
|
return registrations.some((r) => r.scope === "global");
|
|
12904
13293
|
}, [registrations]);
|
|
12905
|
-
const nodeTargets =
|
|
13294
|
+
const nodeTargets = import_react26.default.useMemo(() => {
|
|
12906
13295
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
12907
13296
|
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
12908
13297
|
return [];
|
|
@@ -12992,12 +13381,12 @@ function FallbackAddRegistrationDialog({
|
|
|
12992
13381
|
}
|
|
12993
13382
|
return [];
|
|
12994
13383
|
}, [mode, snapshot, serviceProps, activeServiceId]);
|
|
12995
|
-
|
|
13384
|
+
import_react26.default.useEffect(() => {
|
|
12996
13385
|
if (hasGlobal && scope === "global") {
|
|
12997
13386
|
setScope("node");
|
|
12998
13387
|
}
|
|
12999
13388
|
}, [hasGlobal, scope]);
|
|
13000
|
-
|
|
13389
|
+
import_react26.default.useEffect(() => {
|
|
13001
13390
|
if (scope === "node" && nodeId) {
|
|
13002
13391
|
const exists = nodeTargets.some((node) => node.id === nodeId);
|
|
13003
13392
|
if (!exists) setNodeId("");
|
|
@@ -13028,17 +13417,17 @@ function FallbackAddRegistrationDialog({
|
|
|
13028
13417
|
}
|
|
13029
13418
|
if (!open) return null;
|
|
13030
13419
|
const nodeScopeDisabled = nodeTargets.length === 0;
|
|
13031
|
-
return /* @__PURE__ */ (0,
|
|
13032
|
-
/* @__PURE__ */ (0,
|
|
13033
|
-
/* @__PURE__ */ (0,
|
|
13034
|
-
/* @__PURE__ */ (0,
|
|
13420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "w-full max-w-lg rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13421
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13422
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add registration" }),
|
|
13423
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Choose the registration scope before selecting fallback candidates." })
|
|
13035
13424
|
] }),
|
|
13036
|
-
/* @__PURE__ */ (0,
|
|
13037
|
-
/* @__PURE__ */ (0,
|
|
13038
|
-
/* @__PURE__ */ (0,
|
|
13039
|
-
/* @__PURE__ */ (0,
|
|
13040
|
-
!hasGlobal && /* @__PURE__ */ (0,
|
|
13041
|
-
/* @__PURE__ */ (0,
|
|
13425
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-4 p-4", children: [
|
|
13426
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-2", children: [
|
|
13427
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Scope" }),
|
|
13428
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "grid gap-2", children: [
|
|
13429
|
+
!hasGlobal && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-zinc-200 p-3 dark:border-zinc-800", children: [
|
|
13430
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13042
13431
|
"input",
|
|
13043
13432
|
{
|
|
13044
13433
|
type: "radio",
|
|
@@ -13048,12 +13437,12 @@ function FallbackAddRegistrationDialog({
|
|
|
13048
13437
|
className: "mt-1 h-4 w-4"
|
|
13049
13438
|
}
|
|
13050
13439
|
),
|
|
13051
|
-
/* @__PURE__ */ (0,
|
|
13052
|
-
/* @__PURE__ */ (0,
|
|
13053
|
-
/* @__PURE__ */ (0,
|
|
13440
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
13441
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Global" }),
|
|
13442
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use one global registration for this primary service." })
|
|
13054
13443
|
] })
|
|
13055
13444
|
] }),
|
|
13056
|
-
/* @__PURE__ */ (0,
|
|
13445
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
13057
13446
|
"label",
|
|
13058
13447
|
{
|
|
13059
13448
|
className: [
|
|
@@ -13061,7 +13450,7 @@ function FallbackAddRegistrationDialog({
|
|
|
13061
13450
|
nodeScopeDisabled ? "cursor-not-allowed border-zinc-200 opacity-60 dark:border-zinc-800" : "cursor-pointer border-zinc-200 dark:border-zinc-800"
|
|
13062
13451
|
].join(" "),
|
|
13063
13452
|
children: [
|
|
13064
|
-
/* @__PURE__ */ (0,
|
|
13453
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13065
13454
|
"input",
|
|
13066
13455
|
{
|
|
13067
13456
|
type: "radio",
|
|
@@ -13072,26 +13461,26 @@ function FallbackAddRegistrationDialog({
|
|
|
13072
13461
|
className: "mt-1 h-4 w-4"
|
|
13073
13462
|
}
|
|
13074
13463
|
),
|
|
13075
|
-
/* @__PURE__ */ (0,
|
|
13076
|
-
/* @__PURE__ */ (0,
|
|
13077
|
-
/* @__PURE__ */ (0,
|
|
13464
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
13465
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node" }),
|
|
13466
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: mode === "snapshot" ? "Pick a node currently active in the order snapshot for this primary service." : mode === "props" ? "Pick a tag, field, or option from ServiceProps that maps to this primary service." : "Node-scoped registration is unavailable without OrderSnapshot or ServiceProps." })
|
|
13078
13467
|
] })
|
|
13079
13468
|
]
|
|
13080
13469
|
}
|
|
13081
13470
|
)
|
|
13082
13471
|
] })
|
|
13083
13472
|
] }),
|
|
13084
|
-
scope === "node" && /* @__PURE__ */ (0,
|
|
13085
|
-
/* @__PURE__ */ (0,
|
|
13086
|
-
/* @__PURE__ */ (0,
|
|
13473
|
+
scope === "node" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-2", children: [
|
|
13474
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node id" }),
|
|
13475
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
13087
13476
|
"select",
|
|
13088
13477
|
{
|
|
13089
13478
|
value: nodeId,
|
|
13090
13479
|
onChange: (e) => setNodeId(e.target.value),
|
|
13091
13480
|
className: "w-full rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100",
|
|
13092
13481
|
children: [
|
|
13093
|
-
/* @__PURE__ */ (0,
|
|
13094
|
-
nodeTargets.map((node) => /* @__PURE__ */ (0,
|
|
13482
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "", children: "Select node\u2026" }),
|
|
13483
|
+
nodeTargets.map((node) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("option", { value: node.id, children: [
|
|
13095
13484
|
"[",
|
|
13096
13485
|
node.kind,
|
|
13097
13486
|
"] ",
|
|
@@ -13102,11 +13491,11 @@ function FallbackAddRegistrationDialog({
|
|
|
13102
13491
|
]
|
|
13103
13492
|
}
|
|
13104
13493
|
),
|
|
13105
|
-
nodeScopeDisabled ? /* @__PURE__ */ (0,
|
|
13494
|
+
nodeScopeDisabled ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: mode === "snapshot" ? "No active snapshot nodes were found for this primary service." : mode === "props" ? "No ServiceProps nodes were found for this primary service." : "Node-scoped registration requires either OrderSnapshot or ServiceProps." }) : null
|
|
13106
13495
|
] })
|
|
13107
13496
|
] }),
|
|
13108
|
-
/* @__PURE__ */ (0,
|
|
13109
|
-
/* @__PURE__ */ (0,
|
|
13497
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-end gap-2 border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13498
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13110
13499
|
"button",
|
|
13111
13500
|
{
|
|
13112
13501
|
type: "button",
|
|
@@ -13115,7 +13504,7 @@ function FallbackAddRegistrationDialog({
|
|
|
13115
13504
|
children: "Cancel"
|
|
13116
13505
|
}
|
|
13117
13506
|
),
|
|
13118
|
-
/* @__PURE__ */ (0,
|
|
13507
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13119
13508
|
"button",
|
|
13120
13509
|
{
|
|
13121
13510
|
type: "button",
|
|
@@ -13158,169 +13547,6 @@ function resolveNodeMeta(props, nodeId) {
|
|
|
13158
13547
|
}
|
|
13159
13548
|
return { kind: "node", label: nodeId };
|
|
13160
13549
|
}
|
|
13161
|
-
|
|
13162
|
-
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
13163
|
-
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
13164
|
-
function FallbackRegistrationsPanel() {
|
|
13165
|
-
const { activeServiceId, remove: remove2, clear, check } = useFallbackEditor();
|
|
13166
|
-
const registrations = useActiveFallbackRegistrations();
|
|
13167
|
-
const eligibleServices = useEligibleServiceList();
|
|
13168
|
-
const [candidatePickerOpen, setCandidatePickerOpen] = import_react23.default.useState(false);
|
|
13169
|
-
const [candidateContext, setCandidateContext] = import_react23.default.useState(null);
|
|
13170
|
-
const [candidatePrimaryId, setCandidatePrimaryId] = import_react23.default.useState(void 0);
|
|
13171
|
-
const [registrationDialogOpen, setRegistrationDialogOpen] = import_react23.default.useState(false);
|
|
13172
|
-
const makeContext = import_react23.default.useCallback(
|
|
13173
|
-
(registration) => {
|
|
13174
|
-
if (registration.scope === "global") {
|
|
13175
|
-
return {
|
|
13176
|
-
scope: "global",
|
|
13177
|
-
primary: registration.primary
|
|
13178
|
-
};
|
|
13179
|
-
}
|
|
13180
|
-
return {
|
|
13181
|
-
scope: "node",
|
|
13182
|
-
nodeId: registration.scopeId
|
|
13183
|
-
};
|
|
13184
|
-
},
|
|
13185
|
-
[]
|
|
13186
|
-
);
|
|
13187
|
-
const openCandidatePicker = import_react23.default.useCallback(
|
|
13188
|
-
(context, primaryId) => {
|
|
13189
|
-
setCandidateContext(context);
|
|
13190
|
-
setCandidatePrimaryId(primaryId);
|
|
13191
|
-
setCandidatePickerOpen(true);
|
|
13192
|
-
},
|
|
13193
|
-
[]
|
|
13194
|
-
);
|
|
13195
|
-
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
13196
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "Select a primary service to start editing." }) });
|
|
13197
|
-
}
|
|
13198
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
13199
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13200
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
13201
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
13202
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
13203
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
13204
|
-
] }),
|
|
13205
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13206
|
-
"button",
|
|
13207
|
-
{
|
|
13208
|
-
type: "button",
|
|
13209
|
-
onClick: () => setRegistrationDialogOpen(true),
|
|
13210
|
-
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13211
|
-
children: "Add registration"
|
|
13212
|
-
}
|
|
13213
|
-
)
|
|
13214
|
-
] }),
|
|
13215
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "No registrations yet for this primary service." }) : registrations.map((reg, index) => {
|
|
13216
|
-
var _a;
|
|
13217
|
-
const context = makeContext(reg);
|
|
13218
|
-
const candidates = reg.services;
|
|
13219
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
13220
|
-
"div",
|
|
13221
|
-
{
|
|
13222
|
-
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
13223
|
-
children: [
|
|
13224
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
13225
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
13226
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
13227
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
13228
|
-
"Primary #",
|
|
13229
|
-
String(reg.primary)
|
|
13230
|
-
] })
|
|
13231
|
-
] }),
|
|
13232
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "rounded-full border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300", children: [
|
|
13233
|
-
reg.scope,
|
|
13234
|
-
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
13235
|
-
] })
|
|
13236
|
-
] }),
|
|
13237
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
13238
|
-
var _a2;
|
|
13239
|
-
const preview = check(context, [
|
|
13240
|
-
candidate
|
|
13241
|
-
]);
|
|
13242
|
-
const rejected = preview.rejected[0];
|
|
13243
|
-
const tone = rejected ? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300" : "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
|
13244
|
-
const service = eligibleServices.find(
|
|
13245
|
-
(s) => String(s.id) === String(candidate)
|
|
13246
|
-
);
|
|
13247
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
13248
|
-
"div",
|
|
13249
|
-
{
|
|
13250
|
-
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
13251
|
-
children: [
|
|
13252
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
13253
|
-
rejected ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
13254
|
-
", "
|
|
13255
|
-
) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
13256
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13257
|
-
"button",
|
|
13258
|
-
{
|
|
13259
|
-
type: "button",
|
|
13260
|
-
onClick: () => remove2(
|
|
13261
|
-
context,
|
|
13262
|
-
candidate
|
|
13263
|
-
),
|
|
13264
|
-
className: "text-current/70 hover:text-current",
|
|
13265
|
-
children: "\xD7"
|
|
13266
|
-
}
|
|
13267
|
-
)
|
|
13268
|
-
]
|
|
13269
|
-
},
|
|
13270
|
-
String(candidate)
|
|
13271
|
-
);
|
|
13272
|
-
}) }),
|
|
13273
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-4 flex gap-2", children: [
|
|
13274
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13275
|
-
"button",
|
|
13276
|
-
{
|
|
13277
|
-
type: "button",
|
|
13278
|
-
onClick: () => openCandidatePicker(
|
|
13279
|
-
context,
|
|
13280
|
-
reg.primary
|
|
13281
|
-
),
|
|
13282
|
-
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13283
|
-
children: "Add fallback"
|
|
13284
|
-
}
|
|
13285
|
-
),
|
|
13286
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13287
|
-
"button",
|
|
13288
|
-
{
|
|
13289
|
-
type: "button",
|
|
13290
|
-
onClick: () => clear(context),
|
|
13291
|
-
className: "rounded-xl border border-red-300 bg-white px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 dark:border-red-900/50 dark:bg-zinc-900 dark:text-red-300 dark:hover:bg-red-950/20",
|
|
13292
|
-
children: "Clear"
|
|
13293
|
-
}
|
|
13294
|
-
)
|
|
13295
|
-
] })
|
|
13296
|
-
]
|
|
13297
|
-
},
|
|
13298
|
-
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
13299
|
-
);
|
|
13300
|
-
}) })
|
|
13301
|
-
] }),
|
|
13302
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13303
|
-
FallbackAddRegistrationDialog,
|
|
13304
|
-
{
|
|
13305
|
-
open: registrationDialogOpen,
|
|
13306
|
-
onClose: () => setRegistrationDialogOpen(false),
|
|
13307
|
-
onSelect: (context, primaryId) => {
|
|
13308
|
-
setRegistrationDialogOpen(false);
|
|
13309
|
-
openCandidatePicker(context, primaryId);
|
|
13310
|
-
}
|
|
13311
|
-
}
|
|
13312
|
-
),
|
|
13313
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13314
|
-
FallbackAddCandidatesDialog,
|
|
13315
|
-
{
|
|
13316
|
-
open: candidatePickerOpen,
|
|
13317
|
-
onClose: () => setCandidatePickerOpen(false),
|
|
13318
|
-
context: candidateContext,
|
|
13319
|
-
primaryId: candidatePrimaryId
|
|
13320
|
-
}
|
|
13321
|
-
)
|
|
13322
|
-
] });
|
|
13323
|
-
}
|
|
13324
13550
|
// Annotate the CommonJS export names for ESM import in node:
|
|
13325
13551
|
0 && (module.exports = {
|
|
13326
13552
|
CanvasAPI,
|