@saasicat/nest 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.cjs +3 -8
- package/dist/admin/index.d.cts +5 -33
- package/dist/admin/index.d.ts +5 -33
- package/dist/admin/index.js +2 -2
- package/dist/{admin-manifest.config-DxTfZ8-L.d.cts → admin-manifest.config-DyrQNT7M.d.cts} +1 -1
- package/dist/{admin-manifest.config-DxTfZ8-L.d.ts → admin-manifest.config-DyrQNT7M.d.ts} +1 -1
- package/dist/admin-manifest.service-Cp6uwvmt.d.cts +33 -0
- package/dist/admin-manifest.service-UGgzR1x-.d.ts +33 -0
- package/dist/{aggregation-DGCyoN5d.d.ts → aggregation-BibpEO0t.d.ts} +6 -59
- package/dist/{aggregation-Bt1i_whS.d.cts → aggregation-CfI0bOsQ.d.cts} +6 -59
- package/dist/billing/index.cjs +19 -107
- package/dist/billing/index.d.cts +8 -30
- package/dist/billing/index.d.ts +8 -30
- package/dist/billing/index.js +6 -8
- package/dist/catalog/index.cjs +1160 -1985
- package/dist/catalog/index.d.cts +9 -124
- package/dist/catalog/index.d.ts +9 -124
- package/dist/catalog/index.js +3 -25
- package/dist/checkout-offer/index.js +2 -2
- package/dist/{chunk-2VNZYRDV.js → chunk-52UTQRD3.js} +1 -1
- package/dist/{chunk-V7HUZ6UQ.js → chunk-5DDCSGZC.js} +1106 -1919
- package/dist/{chunk-S2OZ5RIM.js → chunk-6LP7CDS2.js} +15 -68
- package/dist/{chunk-NWLOILP6.js → chunk-A2QBXDJC.js} +15 -7
- package/dist/{chunk-XSGU2Y2O.js → chunk-CK54YKVK.js} +2 -33
- package/dist/{chunk-SYEVGPFC.js → chunk-K3OPNVFR.js} +1 -1
- package/dist/{chunk-XCZ3TTFK.js → chunk-N3WANKSA.js} +0 -2
- package/dist/{chunk-MV6LW5UB.js → chunk-R2QOSVAA.js} +2 -2
- package/dist/{chunk-NFOSITWB.js → chunk-RZU4HIAN.js} +12 -45
- package/dist/{chunk-YNEW3L63.js → chunk-SD3TT2BR.js} +1 -1
- package/dist/{chunk-P6MYZMXQ.js → chunk-U6HT27J7.js} +3 -8
- package/dist/{chunk-7MLGHWKO.js → chunk-WKVBNTYC.js} +2 -0
- package/dist/{chunk-ZL4LLE2Z.js → chunk-ZLUGQE5D.js} +1 -1
- package/dist/{enforce-quota.interceptor-3HmbeHTM.d.ts → enforce-quota.interceptor-Dj1Kusr5.d.ts} +9 -4
- package/dist/{enforce-quota.interceptor-HmdZFg41.d.cts → enforce-quota.interceptor-cv7r80VM.d.cts} +9 -4
- package/dist/entitlement/index.cjs +13 -46
- package/dist/entitlement/index.d.cts +4 -3
- package/dist/entitlement/index.d.ts +4 -3
- package/dist/entitlement/index.js +6 -8
- package/dist/index.cjs +1348 -2300
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +14 -42
- package/dist/platform/index.cjs +28 -54
- package/dist/platform/index.d.cts +4 -3
- package/dist/platform/index.d.ts +4 -3
- package/dist/platform/index.js +9 -6
- package/dist/promo/index.cjs +2 -2
- package/dist/promo/index.js +3 -3
- package/dist/registration/index.cjs +2 -34
- package/dist/registration/index.d.cts +3 -21
- package/dist/registration/index.d.ts +3 -21
- package/dist/registration/index.js +1 -3
- package/dist/testing/index.cjs +26 -255
- package/dist/testing/index.d.cts +5 -37
- package/dist/testing/index.d.ts +5 -37
- package/dist/testing/index.js +6 -206
- package/package.json +3 -3
package/dist/testing/index.cjs
CHANGED
|
@@ -33,7 +33,6 @@ var testing_exports = {};
|
|
|
33
33
|
__export(testing_exports, {
|
|
34
34
|
EnforceQuotaInterceptor: () => EnforceQuotaInterceptor,
|
|
35
35
|
FakeBundleRepository: () => FakeBundleRepository,
|
|
36
|
-
FakeBusinessTypeRepository: () => FakeBusinessTypeRepository,
|
|
37
36
|
FakeMarketingProjectionRepository: () => FakeMarketingProjectionRepository,
|
|
38
37
|
FakePlanRepository: () => FakePlanRepository,
|
|
39
38
|
FakePlanVersionRepository: () => FakePlanVersionRepository,
|
|
@@ -574,205 +573,6 @@ var FakeBundleRepository = class {
|
|
|
574
573
|
return published;
|
|
575
574
|
}
|
|
576
575
|
};
|
|
577
|
-
var FakeBusinessTypeRepository = class {
|
|
578
|
-
static {
|
|
579
|
-
__name(this, "FakeBusinessTypeRepository");
|
|
580
|
-
}
|
|
581
|
-
types = /* @__PURE__ */ new Map();
|
|
582
|
-
versions = /* @__PURE__ */ new Map();
|
|
583
|
-
nextId = 1;
|
|
584
|
-
genId(prefix) {
|
|
585
|
-
const n = this.nextId++;
|
|
586
|
-
const suffix = n.toString(16).padStart(12, "0");
|
|
587
|
-
return `${prefix}aaaa-aaaa-aaaa-aaaa-${suffix}`;
|
|
588
|
-
}
|
|
589
|
-
nowIso() {
|
|
590
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
591
|
-
}
|
|
592
|
-
seedBusinessType(row) {
|
|
593
|
-
this.types.set(row.id, row);
|
|
594
|
-
}
|
|
595
|
-
seedVersion(row) {
|
|
596
|
-
this.versions.set(row.id, row);
|
|
597
|
-
}
|
|
598
|
-
clear() {
|
|
599
|
-
this.types.clear();
|
|
600
|
-
this.versions.clear();
|
|
601
|
-
}
|
|
602
|
-
async list(filter) {
|
|
603
|
-
const excludeDeleted = filter.excludeDeleted ?? true;
|
|
604
|
-
return [
|
|
605
|
-
...this.types.values()
|
|
606
|
-
].filter((t) => t.projectKey === filter.projectKey && (!excludeDeleted || t.deletedAt === null));
|
|
607
|
-
}
|
|
608
|
-
async findById(businessTypeId) {
|
|
609
|
-
return this.types.get(businessTypeId) ?? null;
|
|
610
|
-
}
|
|
611
|
-
async findByKey(projectKey, businessTypeKey) {
|
|
612
|
-
for (const t of this.types.values()) {
|
|
613
|
-
if (t.projectKey === projectKey && t.businessTypeKey === businessTypeKey && t.deletedAt === null) {
|
|
614
|
-
return t;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return null;
|
|
618
|
-
}
|
|
619
|
-
async create(data) {
|
|
620
|
-
const now = this.nowIso();
|
|
621
|
-
const row = {
|
|
622
|
-
id: this.genId("cccc"),
|
|
623
|
-
projectKey: data.projectKey,
|
|
624
|
-
businessTypeKey: data.businessTypeKey,
|
|
625
|
-
label: data.label,
|
|
626
|
-
description: data.description ?? null,
|
|
627
|
-
icon: data.icon ?? null,
|
|
628
|
-
sortOrder: data.sortOrder ?? 0,
|
|
629
|
-
createdAt: now,
|
|
630
|
-
updatedAt: now,
|
|
631
|
-
deletedAt: null
|
|
632
|
-
};
|
|
633
|
-
this.types.set(row.id, row);
|
|
634
|
-
return row;
|
|
635
|
-
}
|
|
636
|
-
async update(businessTypeId, data) {
|
|
637
|
-
const existing = this.types.get(businessTypeId);
|
|
638
|
-
if (!existing) throw new Error(`BusinessType '${businessTypeId}' nicht gefunden`);
|
|
639
|
-
const updated = {
|
|
640
|
-
...existing,
|
|
641
|
-
label: data.label ?? existing.label,
|
|
642
|
-
description: data.description !== void 0 ? data.description : existing.description,
|
|
643
|
-
icon: data.icon !== void 0 ? data.icon : existing.icon,
|
|
644
|
-
sortOrder: data.sortOrder ?? existing.sortOrder,
|
|
645
|
-
updatedAt: this.nowIso()
|
|
646
|
-
};
|
|
647
|
-
this.types.set(businessTypeId, updated);
|
|
648
|
-
return updated;
|
|
649
|
-
}
|
|
650
|
-
async softDelete(businessTypeId) {
|
|
651
|
-
const existing = this.types.get(businessTypeId);
|
|
652
|
-
if (!existing) throw new Error(`BusinessType '${businessTypeId}' nicht gefunden`);
|
|
653
|
-
this.types.set(businessTypeId, {
|
|
654
|
-
...existing,
|
|
655
|
-
deletedAt: this.nowIso()
|
|
656
|
-
});
|
|
657
|
-
}
|
|
658
|
-
async listVersions(businessTypeId) {
|
|
659
|
-
return [
|
|
660
|
-
...this.versions.values()
|
|
661
|
-
].filter((v) => v.businessTypeId === businessTypeId).sort((a, b) => a.version - b.version);
|
|
662
|
-
}
|
|
663
|
-
async findVersionById(versionId) {
|
|
664
|
-
return this.versions.get(versionId) ?? null;
|
|
665
|
-
}
|
|
666
|
-
async findCurrentDraft(businessTypeId) {
|
|
667
|
-
for (const v of this.versions.values()) {
|
|
668
|
-
if (v.businessTypeId === businessTypeId && v.publishedAt === null) return v;
|
|
669
|
-
}
|
|
670
|
-
return null;
|
|
671
|
-
}
|
|
672
|
-
async findLatestLive(businessTypeId) {
|
|
673
|
-
for (const v of this.versions.values()) {
|
|
674
|
-
if (v.businessTypeId === businessTypeId && v.publishedAt !== null && v.supersededAt === null) {
|
|
675
|
-
return v;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
return null;
|
|
679
|
-
}
|
|
680
|
-
async createDraft(data) {
|
|
681
|
-
const draft = await this.findCurrentDraft(data.businessTypeId);
|
|
682
|
-
if (draft) {
|
|
683
|
-
throw new Error(`BusinessType '${data.businessTypeId}' hat bereits eine Draft-Version v${draft.version}`);
|
|
684
|
-
}
|
|
685
|
-
const all = await this.listVersions(data.businessTypeId);
|
|
686
|
-
const nextVersion = all.length === 0 ? 1 : Math.max(...all.map((v) => v.version)) + 1;
|
|
687
|
-
const now = this.nowIso();
|
|
688
|
-
const businessType = this.types.get(data.businessTypeId);
|
|
689
|
-
const bundles = data.bundles.map((b) => ({
|
|
690
|
-
bundleVersionId: b.bundleVersionId,
|
|
691
|
-
bundleKey: "",
|
|
692
|
-
bundleLabel: "",
|
|
693
|
-
bundleVersion: 0,
|
|
694
|
-
sortOrder: b.sortOrder ?? 0
|
|
695
|
-
}));
|
|
696
|
-
const row = {
|
|
697
|
-
id: this.genId("wwww"),
|
|
698
|
-
version: nextVersion,
|
|
699
|
-
baseVersionId: data.baseVersionId ?? null,
|
|
700
|
-
publishedAt: null,
|
|
701
|
-
supersededAt: null,
|
|
702
|
-
publishedChanges: null,
|
|
703
|
-
changeNote: data.changeNote ?? "",
|
|
704
|
-
nonRegressive: true,
|
|
705
|
-
createdByUserId: data.createdByUserId ?? null,
|
|
706
|
-
publishedByUserId: null,
|
|
707
|
-
validFrom: null,
|
|
708
|
-
validUntil: null,
|
|
709
|
-
createdAt: now,
|
|
710
|
-
updatedAt: now,
|
|
711
|
-
businessTypeId: data.businessTypeId,
|
|
712
|
-
businessTypeKey: businessType?.businessTypeKey ?? "",
|
|
713
|
-
label: businessType?.label ?? "",
|
|
714
|
-
quotaOverrides: data.quotaOverrides ?? {},
|
|
715
|
-
monthlyNet: data.monthlyNet ?? null,
|
|
716
|
-
yearlyNet: data.yearlyNet ?? null,
|
|
717
|
-
marketed: data.marketed ?? true,
|
|
718
|
-
bundles
|
|
719
|
-
};
|
|
720
|
-
this.versions.set(row.id, row);
|
|
721
|
-
return row;
|
|
722
|
-
}
|
|
723
|
-
async updateDraft(versionId, data) {
|
|
724
|
-
const existing = this.versions.get(versionId);
|
|
725
|
-
if (!existing) throw new Error(`BusinessTypeVersion '${versionId}' nicht gefunden`);
|
|
726
|
-
if (existing.publishedAt !== null) {
|
|
727
|
-
throw new Error(`BusinessTypeVersion '${versionId}' ist bereits published`);
|
|
728
|
-
}
|
|
729
|
-
const bundles = data.bundles ? data.bundles.map((b) => ({
|
|
730
|
-
bundleVersionId: b.bundleVersionId,
|
|
731
|
-
bundleKey: "",
|
|
732
|
-
bundleLabel: "",
|
|
733
|
-
bundleVersion: 0,
|
|
734
|
-
sortOrder: b.sortOrder ?? 0
|
|
735
|
-
})) : existing.bundles;
|
|
736
|
-
const updated = {
|
|
737
|
-
...existing,
|
|
738
|
-
quotaOverrides: data.quotaOverrides ?? existing.quotaOverrides,
|
|
739
|
-
monthlyNet: data.monthlyNet !== void 0 ? data.monthlyNet : existing.monthlyNet,
|
|
740
|
-
yearlyNet: data.yearlyNet !== void 0 ? data.yearlyNet : existing.yearlyNet,
|
|
741
|
-
marketed: data.marketed ?? existing.marketed,
|
|
742
|
-
changeNote: data.changeNote ?? existing.changeNote,
|
|
743
|
-
bundles,
|
|
744
|
-
updatedAt: this.nowIso()
|
|
745
|
-
};
|
|
746
|
-
this.versions.set(versionId, updated);
|
|
747
|
-
return updated;
|
|
748
|
-
}
|
|
749
|
-
async publishDraft(versionId, publishMeta) {
|
|
750
|
-
const draft = this.versions.get(versionId);
|
|
751
|
-
if (!draft) throw new Error(`BusinessTypeVersion '${versionId}' nicht gefunden`);
|
|
752
|
-
if (draft.publishedAt !== null) {
|
|
753
|
-
throw new Error(`BusinessTypeVersion '${versionId}' ist bereits published`);
|
|
754
|
-
}
|
|
755
|
-
const now = this.nowIso();
|
|
756
|
-
const previous = await this.findLatestLive(draft.businessTypeId);
|
|
757
|
-
if (previous) {
|
|
758
|
-
this.versions.set(previous.id, {
|
|
759
|
-
...previous,
|
|
760
|
-
supersededAt: now,
|
|
761
|
-
updatedAt: now
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
const published = {
|
|
765
|
-
...draft,
|
|
766
|
-
publishedAt: now,
|
|
767
|
-
publishedChanges: publishMeta.publishedChanges,
|
|
768
|
-
nonRegressive: publishMeta.nonRegressive,
|
|
769
|
-
publishedByUserId: publishMeta.publishedByUserId,
|
|
770
|
-
updatedAt: now
|
|
771
|
-
};
|
|
772
|
-
this.versions.set(versionId, published);
|
|
773
|
-
return published;
|
|
774
|
-
}
|
|
775
|
-
};
|
|
776
576
|
var FakeMarketingProjectionRepository = class {
|
|
777
577
|
static {
|
|
778
578
|
__name(this, "FakeMarketingProjectionRepository");
|
|
@@ -1496,7 +1296,8 @@ var SuperAdminGuard = class {
|
|
|
1496
1296
|
canActivate(context) {
|
|
1497
1297
|
const request = context.switchToHttp().getRequest();
|
|
1498
1298
|
if (!request.user) throw new import_common5.ForbiddenException("Nicht authentifiziert");
|
|
1499
|
-
|
|
1299
|
+
const role = request.user.platformRole ?? request.user.role;
|
|
1300
|
+
if (role !== "SUPER_ADMIN") {
|
|
1500
1301
|
throw new import_common5.ForbiddenException("Nur SUPER_ADMIN-Rolle erlaubt");
|
|
1501
1302
|
}
|
|
1502
1303
|
return true;
|
|
@@ -1775,7 +1576,7 @@ var PLATFORM_CORE_MANIFEST_CONTRIBUTION = {
|
|
|
1775
1576
|
// section, see `DEFAULT_NAV_SECTIONS` in the nav-builder). The order per
|
|
1776
1577
|
// section is deliberately curated:
|
|
1777
1578
|
// Overview: dashboard
|
|
1778
|
-
// Product catalog: discovery → bundles →
|
|
1579
|
+
// Product catalog: discovery → bundles → plans →
|
|
1779
1580
|
// planVersions → marketingCatalog → promoCodes
|
|
1780
1581
|
// (promoCodes is appended by the app contributions
|
|
1781
1582
|
// and therefore lands at the end of the section)
|
|
@@ -1800,12 +1601,6 @@ var PLATFORM_CORE_MANIFEST_CONTRIBUTION = {
|
|
|
1800
1601
|
enabled: true,
|
|
1801
1602
|
requiredCapability: "bundles.read"
|
|
1802
1603
|
},
|
|
1803
|
-
// SPEC_V2 §11.1 M3 — BusinessType editor in SuperAdmin.
|
|
1804
|
-
// Apps with domain verticals set `businessTypes.read = true`.
|
|
1805
|
-
businessTypes: {
|
|
1806
|
-
enabled: true,
|
|
1807
|
-
requiredCapability: "businessTypes.read"
|
|
1808
|
-
},
|
|
1809
1604
|
plans: {
|
|
1810
1605
|
enabled: true,
|
|
1811
1606
|
requiredCapability: "plans.read"
|
|
@@ -2239,8 +2034,8 @@ function _ts_decorate10(decorators, target, key, desc) {
|
|
|
2239
2034
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2240
2035
|
}
|
|
2241
2036
|
__name(_ts_decorate10, "_ts_decorate");
|
|
2242
|
-
var PLAN_CATALOG_TOKEN = /* @__PURE__ */ Symbol("PLAN_CATALOG");
|
|
2243
|
-
var PLAN_CATALOG_READ_SINK_TOKEN = /* @__PURE__ */ Symbol("PLAN_CATALOG_READ_SINK");
|
|
2037
|
+
var PLAN_CATALOG_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/PLAN_CATALOG");
|
|
2038
|
+
var PLAN_CATALOG_READ_SINK_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/PLAN_CATALOG_READ_SINK");
|
|
2244
2039
|
var PlanCatalogModule = class _PlanCatalogModule {
|
|
2245
2040
|
static {
|
|
2246
2041
|
__name(this, "PlanCatalogModule");
|
|
@@ -2775,25 +2570,6 @@ function isFeaturePlannedOnly(catalog, featureKey) {
|
|
|
2775
2570
|
__name(isFeaturePlannedOnly, "isFeaturePlannedOnly");
|
|
2776
2571
|
|
|
2777
2572
|
// src/entitlement/aggregation.ts
|
|
2778
|
-
function aggregateBusinessTypeQuotas(snapshot) {
|
|
2779
|
-
const sums = {};
|
|
2780
|
-
for (const bundle of snapshot.bundles) {
|
|
2781
|
-
for (const [key, value] of Object.entries(bundle.quotas)) {
|
|
2782
|
-
if (sums[key] === -1 || value === -1) {
|
|
2783
|
-
sums[key] = -1;
|
|
2784
|
-
} else {
|
|
2785
|
-
sums[key] = (sums[key] ?? 0) + value;
|
|
2786
|
-
}
|
|
2787
|
-
}
|
|
2788
|
-
}
|
|
2789
|
-
for (const [key, value] of Object.entries(snapshot.quotaOverrides)) {
|
|
2790
|
-
if (value !== void 0) {
|
|
2791
|
-
sums[key] = value;
|
|
2792
|
-
}
|
|
2793
|
-
}
|
|
2794
|
-
return sums;
|
|
2795
|
-
}
|
|
2796
|
-
__name(aggregateBusinessTypeQuotas, "aggregateBusinessTypeQuotas");
|
|
2797
2573
|
function filterActiveSubscriptionBundles(bundles, now) {
|
|
2798
2574
|
return bundles.filter((b) => b.canceledEffectiveAt === null || b.canceledEffectiveAt > now);
|
|
2799
2575
|
}
|
|
@@ -2844,16 +2620,6 @@ function aggregateContractLineItemEntitlements(lineItems, fallbackPlan = "UNKNOW
|
|
|
2844
2620
|
};
|
|
2845
2621
|
}
|
|
2846
2622
|
__name(aggregateContractLineItemEntitlements, "aggregateContractLineItemEntitlements");
|
|
2847
|
-
function collectBusinessTypeFeatures(snapshot) {
|
|
2848
|
-
const set = /* @__PURE__ */ new Set();
|
|
2849
|
-
for (const bundle of snapshot.bundles) {
|
|
2850
|
-
for (const f of bundle.features) {
|
|
2851
|
-
set.add(f);
|
|
2852
|
-
}
|
|
2853
|
-
}
|
|
2854
|
-
return Array.from(set);
|
|
2855
|
-
}
|
|
2856
|
-
__name(collectBusinessTypeFeatures, "collectBusinessTypeFeatures");
|
|
2857
2623
|
function filterPlannedOnlyFeatures(features, catalog) {
|
|
2858
2624
|
const out = /* @__PURE__ */ new Set();
|
|
2859
2625
|
for (const f of features) {
|
|
@@ -2886,8 +2652,6 @@ function applyCustomLimits(base, custom) {
|
|
|
2886
2652
|
}
|
|
2887
2653
|
__name(applyCustomLimits, "applyCustomLimits");
|
|
2888
2654
|
function aggregateLimits(input, catalog, now) {
|
|
2889
|
-
const businessTypeQuotas = input.businessTypeVersion ? aggregateBusinessTypeQuotas(input.businessTypeVersion) : {};
|
|
2890
|
-
const businessTypeFeatures = input.businessTypeVersion ? collectBusinessTypeFeatures(input.businessTypeVersion) : [];
|
|
2891
2655
|
const activeBundles = filterActiveSubscriptionBundles(input.subscriptionBundles ?? [], now);
|
|
2892
2656
|
const subBundleQuotas = aggregateSubscriptionBundleQuotas(activeBundles);
|
|
2893
2657
|
const subBundleFeatures = collectSubscriptionBundleFeatures(activeBundles);
|
|
@@ -2895,13 +2659,6 @@ function aggregateLimits(input, catalog, now) {
|
|
|
2895
2659
|
for (const [k, v] of Object.entries(input.planVersion.quotas)) {
|
|
2896
2660
|
quotas[k] = v;
|
|
2897
2661
|
}
|
|
2898
|
-
for (const [k, v] of Object.entries(businessTypeQuotas)) {
|
|
2899
|
-
if (quotas[k] === -1 || v === -1) {
|
|
2900
|
-
quotas[k] = -1;
|
|
2901
|
-
} else {
|
|
2902
|
-
quotas[k] = (quotas[k] ?? 0) + v;
|
|
2903
|
-
}
|
|
2904
|
-
}
|
|
2905
2662
|
for (const [k, v] of Object.entries(subBundleQuotas)) {
|
|
2906
2663
|
if (quotas[k] === -1 || v === -1) {
|
|
2907
2664
|
quotas[k] = -1;
|
|
@@ -2911,7 +2668,6 @@ function aggregateLimits(input, catalog, now) {
|
|
|
2911
2668
|
}
|
|
2912
2669
|
const features = /* @__PURE__ */ new Set([
|
|
2913
2670
|
...input.planVersion.features,
|
|
2914
|
-
...businessTypeFeatures,
|
|
2915
2671
|
...subBundleFeatures
|
|
2916
2672
|
]);
|
|
2917
2673
|
const withCustom = applyCustomLimits({
|
|
@@ -3023,6 +2779,7 @@ function resolveEntitlementPlan(input, config, now) {
|
|
|
3023
2779
|
__name(resolveEntitlementPlan, "resolveEntitlementPlan");
|
|
3024
2780
|
|
|
3025
2781
|
// src/entitlement/tokens.ts
|
|
2782
|
+
var ENTITLEMENT_SERVICE_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/EntitlementService");
|
|
3026
2783
|
var SUBSCRIPTION_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SubscriptionRepository");
|
|
3027
2784
|
var PLAN_VERSION_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/PlanVersionRepository");
|
|
3028
2785
|
var TRANSACTION_RUNNER_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/TransactionRunner");
|
|
@@ -3292,7 +3049,13 @@ var EntitlementModule = class _EntitlementModule {
|
|
|
3292
3049
|
asProvider(SUBSCRIPTION_REPOSITORY_TOKEN, options.subscriptionRepository),
|
|
3293
3050
|
asProvider(PLAN_VERSION_REPOSITORY_TOKEN, options.planVersionRepository),
|
|
3294
3051
|
asProvider(TRANSACTION_RUNNER_TOKEN, options.transactionRunner),
|
|
3295
|
-
EntitlementService
|
|
3052
|
+
EntitlementService,
|
|
3053
|
+
// Cross-bundle-stable alias so consumers in other subpath bundles
|
|
3054
|
+
// (billing/TenantBillingModule) can inject the same instance.
|
|
3055
|
+
{
|
|
3056
|
+
provide: ENTITLEMENT_SERVICE_TOKEN,
|
|
3057
|
+
useExisting: EntitlementService
|
|
3058
|
+
}
|
|
3296
3059
|
];
|
|
3297
3060
|
if (options.resolutionConfig) {
|
|
3298
3061
|
providers.push({
|
|
@@ -3315,6 +3078,7 @@ var EntitlementModule = class _EntitlementModule {
|
|
|
3315
3078
|
providers,
|
|
3316
3079
|
exports: [
|
|
3317
3080
|
EntitlementService,
|
|
3081
|
+
ENTITLEMENT_SERVICE_TOKEN,
|
|
3318
3082
|
SUBSCRIPTION_REPOSITORY_TOKEN
|
|
3319
3083
|
]
|
|
3320
3084
|
};
|
|
@@ -3771,6 +3535,9 @@ var SaasPlatformModule = class _SaasPlatformModule {
|
|
|
3771
3535
|
if (missingCore.length) {
|
|
3772
3536
|
throw new Error(`SaasPlatformModule.forRoot: adapters missing (provide them via \`adapters\` or a \`persistence\` bundle): ${missingCore.join(", ")}`);
|
|
3773
3537
|
}
|
|
3538
|
+
const mfaPort = adapters.mfa;
|
|
3539
|
+
const auditPort = adapters.audit;
|
|
3540
|
+
const rlsBypassPort = adapters.rlsBypass;
|
|
3774
3541
|
if (!options.planCatalog && (!adapters.planCatalogReadSink || !options.dbCatalog)) {
|
|
3775
3542
|
throw new Error("SaasPlatformModule.forRoot: either set `planCatalog` (quickstart YAML path) or, for DB hydration, BOTH a planCatalogReadSink (`adapters`/`persistence`) AND `dbCatalog` ({ projectKey, currency, vatRate }).");
|
|
3776
3543
|
}
|
|
@@ -3816,15 +3583,20 @@ var SaasPlatformModule = class _SaasPlatformModule {
|
|
|
3816
3583
|
snapshotPath: options.discoverySnapshotPath === void 0 ? "var/discovery-snapshot.json" : options.discoverySnapshotPath
|
|
3817
3584
|
}),
|
|
3818
3585
|
AdminModule.forRoot({
|
|
3819
|
-
mfaPort
|
|
3820
|
-
auditPort
|
|
3821
|
-
rlsBypassPort
|
|
3586
|
+
mfaPort,
|
|
3587
|
+
auditPort,
|
|
3588
|
+
rlsBypassPort,
|
|
3822
3589
|
global: true
|
|
3823
3590
|
}),
|
|
3824
3591
|
AdminManifestModule.forRoot({
|
|
3825
3592
|
config: options.adminManifestConfig ?? buildMinimalManifestConfig(),
|
|
3826
3593
|
guards: options.controller.guards,
|
|
3827
|
-
reloadGuards: options.reloadGuards
|
|
3594
|
+
reloadGuards: options.reloadGuards,
|
|
3595
|
+
// Global like AdminModule above: apps register their manifest
|
|
3596
|
+
// contribution by injecting AdminManifestService into one of
|
|
3597
|
+
// their own modules (handbook §6.6). Re-exporting the module
|
|
3598
|
+
// from here does not make that injection resolvable.
|
|
3599
|
+
global: true
|
|
3828
3600
|
})
|
|
3829
3601
|
];
|
|
3830
3602
|
if (options.entitlement) {
|
|
@@ -3970,7 +3742,6 @@ __name(createSaasPlatformTestModule, "createSaasPlatformTestModule");
|
|
|
3970
3742
|
0 && (module.exports = {
|
|
3971
3743
|
EnforceQuotaInterceptor,
|
|
3972
3744
|
FakeBundleRepository,
|
|
3973
|
-
FakeBusinessTypeRepository,
|
|
3974
3745
|
FakeMarketingProjectionRepository,
|
|
3975
3746
|
FakePlanRepository,
|
|
3976
3747
|
FakePlanVersionRepository,
|
package/dist/testing/index.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { BundleRepository, BundleRow, BundleVersionRow, BundleListFilter, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange,
|
|
1
|
+
import { BundleRepository, BundleRow, BundleVersionRow, BundleListFilter, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange, MarketingProjectionRepository, MarketingProjectionRow, MarketingProjectionFilter, CreateMarketingProjectionData, UpdateMarketingProjectionData, PlanRepository, PlanRow, PlanVersionRow, PlanListFilter, CreatePlanData, UpdatePlanData, CreatePlanVersionDraftData, UpdatePlanVersionDraftData, PlanVersionRepository, PlanVersionRecord, TransactionContext, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, CreateSubscriptionContractData, TerminateSubscriptionContractData, SubscriptionRepository, SubscriptionRecord, TransactionRunner, PlanCatalog, QuotaProvider } from '@saasicat/types';
|
|
2
2
|
import { Type, DynamicModule } from '@nestjs/common';
|
|
3
|
-
import { c as SaasPlatformAdapters } from '../enforce-quota.interceptor-
|
|
4
|
-
export { E as EnforceQuotaInterceptor, P as PLAN_RESOLVER_PORT_TOKEN, S as StaticEntitlementService, g as StaticFeatureGuard, i as StaticPlanResolver } from '../enforce-quota.interceptor-
|
|
3
|
+
import { c as SaasPlatformAdapters } from '../enforce-quota.interceptor-cv7r80VM.cjs';
|
|
4
|
+
export { E as EnforceQuotaInterceptor, P as PLAN_RESOLVER_PORT_TOKEN, S as StaticEntitlementService, g as StaticFeatureGuard, i as StaticPlanResolver } from '../enforce-quota.interceptor-cv7r80VM.cjs';
|
|
5
5
|
import '../di-CcNeq9v-.cjs';
|
|
6
|
-
import '../admin-manifest.config-
|
|
6
|
+
import '../admin-manifest.config-DyrQNT7M.cjs';
|
|
7
7
|
import '../discovery.scanner-DLgEvuoy.cjs';
|
|
8
8
|
import '@nestjs/core';
|
|
9
9
|
import '../plan-resolution-CFCoUkrE.cjs';
|
|
@@ -143,38 +143,6 @@ declare class FakeBundleRepository implements BundleRepository {
|
|
|
143
143
|
validUntil: Date | null;
|
|
144
144
|
}): Promise<BundleVersionRow>;
|
|
145
145
|
}
|
|
146
|
-
/**
|
|
147
|
-
* In-memory implementation of `BusinessTypeRepository`. Keeps the
|
|
148
|
-
* BusinessTypeBundle junction directly inside the BusinessTypeVersionRow objects
|
|
149
|
-
* (analogous to the wire-format convention).
|
|
150
|
-
*/
|
|
151
|
-
declare class FakeBusinessTypeRepository implements BusinessTypeRepository {
|
|
152
|
-
private readonly types;
|
|
153
|
-
private readonly versions;
|
|
154
|
-
private nextId;
|
|
155
|
-
private genId;
|
|
156
|
-
private nowIso;
|
|
157
|
-
seedBusinessType(row: BusinessTypeRow): void;
|
|
158
|
-
seedVersion(row: BusinessTypeVersionRow): void;
|
|
159
|
-
clear(): void;
|
|
160
|
-
list(filter: BusinessTypeListFilter): Promise<BusinessTypeRow[]>;
|
|
161
|
-
findById(businessTypeId: string): Promise<BusinessTypeRow | null>;
|
|
162
|
-
findByKey(projectKey: string, businessTypeKey: string): Promise<BusinessTypeRow | null>;
|
|
163
|
-
create(data: CreateBusinessTypeData): Promise<BusinessTypeRow>;
|
|
164
|
-
update(businessTypeId: string, data: UpdateBusinessTypeData): Promise<BusinessTypeRow>;
|
|
165
|
-
softDelete(businessTypeId: string): Promise<void>;
|
|
166
|
-
listVersions(businessTypeId: string): Promise<BusinessTypeVersionRow[]>;
|
|
167
|
-
findVersionById(versionId: string): Promise<BusinessTypeVersionRow | null>;
|
|
168
|
-
findCurrentDraft(businessTypeId: string): Promise<BusinessTypeVersionRow | null>;
|
|
169
|
-
findLatestLive(businessTypeId: string): Promise<BusinessTypeVersionRow | null>;
|
|
170
|
-
createDraft(data: CreateBusinessTypeVersionDraftData): Promise<BusinessTypeVersionRow>;
|
|
171
|
-
updateDraft(versionId: string, data: UpdateBusinessTypeVersionDraftData): Promise<BusinessTypeVersionRow>;
|
|
172
|
-
publishDraft(versionId: string, publishMeta: {
|
|
173
|
-
publishedByUserId: string | null;
|
|
174
|
-
publishedChanges: VersionChange[];
|
|
175
|
-
nonRegressive: boolean;
|
|
176
|
-
}): Promise<BusinessTypeVersionRow>;
|
|
177
|
-
}
|
|
178
146
|
/**
|
|
179
147
|
* In-memory implementation of `MarketingProjectionRepository`. Enforces
|
|
180
148
|
* uniqueness over (`targetType`, `targetVersionId`, `locale`) like the
|
|
@@ -274,4 +242,4 @@ interface CreateSaasPlatformTestModuleOptions {
|
|
|
274
242
|
*/
|
|
275
243
|
declare function createSaasPlatformTestModule(options: CreateSaasPlatformTestModuleOptions): DynamicModule;
|
|
276
244
|
|
|
277
|
-
export { type CreateSaasPlatformTestModuleOptions, FakeBundleRepository,
|
|
245
|
+
export { type CreateSaasPlatformTestModuleOptions, FakeBundleRepository, FakeMarketingProjectionRepository, FakePlanRepository, FakePlanVersionRepository, FakeSubscriptionBundleRepository, FakeSubscriptionContractRepository, FakeSubscriptionRepository, FakeTransactionRunner, StubAuditPort, StubMfaPort, StubRlsBypassPort, createSaasPlatformTestModule };
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { BundleRepository, BundleRow, BundleVersionRow, BundleListFilter, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange,
|
|
1
|
+
import { BundleRepository, BundleRow, BundleVersionRow, BundleListFilter, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange, MarketingProjectionRepository, MarketingProjectionRow, MarketingProjectionFilter, CreateMarketingProjectionData, UpdateMarketingProjectionData, PlanRepository, PlanRow, PlanVersionRow, PlanListFilter, CreatePlanData, UpdatePlanData, CreatePlanVersionDraftData, UpdatePlanVersionDraftData, PlanVersionRepository, PlanVersionRecord, TransactionContext, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, CreateSubscriptionContractData, TerminateSubscriptionContractData, SubscriptionRepository, SubscriptionRecord, TransactionRunner, PlanCatalog, QuotaProvider } from '@saasicat/types';
|
|
2
2
|
import { Type, DynamicModule } from '@nestjs/common';
|
|
3
|
-
import { c as SaasPlatformAdapters } from '../enforce-quota.interceptor-
|
|
4
|
-
export { E as EnforceQuotaInterceptor, P as PLAN_RESOLVER_PORT_TOKEN, S as StaticEntitlementService, g as StaticFeatureGuard, i as StaticPlanResolver } from '../enforce-quota.interceptor-
|
|
3
|
+
import { c as SaasPlatformAdapters } from '../enforce-quota.interceptor-Dj1Kusr5.js';
|
|
4
|
+
export { E as EnforceQuotaInterceptor, P as PLAN_RESOLVER_PORT_TOKEN, S as StaticEntitlementService, g as StaticFeatureGuard, i as StaticPlanResolver } from '../enforce-quota.interceptor-Dj1Kusr5.js';
|
|
5
5
|
import '../di-CcNeq9v-.js';
|
|
6
|
-
import '../admin-manifest.config-
|
|
6
|
+
import '../admin-manifest.config-DyrQNT7M.js';
|
|
7
7
|
import '../discovery.scanner-DLgEvuoy.js';
|
|
8
8
|
import '@nestjs/core';
|
|
9
9
|
import '../plan-resolution-CFCoUkrE.js';
|
|
@@ -143,38 +143,6 @@ declare class FakeBundleRepository implements BundleRepository {
|
|
|
143
143
|
validUntil: Date | null;
|
|
144
144
|
}): Promise<BundleVersionRow>;
|
|
145
145
|
}
|
|
146
|
-
/**
|
|
147
|
-
* In-memory implementation of `BusinessTypeRepository`. Keeps the
|
|
148
|
-
* BusinessTypeBundle junction directly inside the BusinessTypeVersionRow objects
|
|
149
|
-
* (analogous to the wire-format convention).
|
|
150
|
-
*/
|
|
151
|
-
declare class FakeBusinessTypeRepository implements BusinessTypeRepository {
|
|
152
|
-
private readonly types;
|
|
153
|
-
private readonly versions;
|
|
154
|
-
private nextId;
|
|
155
|
-
private genId;
|
|
156
|
-
private nowIso;
|
|
157
|
-
seedBusinessType(row: BusinessTypeRow): void;
|
|
158
|
-
seedVersion(row: BusinessTypeVersionRow): void;
|
|
159
|
-
clear(): void;
|
|
160
|
-
list(filter: BusinessTypeListFilter): Promise<BusinessTypeRow[]>;
|
|
161
|
-
findById(businessTypeId: string): Promise<BusinessTypeRow | null>;
|
|
162
|
-
findByKey(projectKey: string, businessTypeKey: string): Promise<BusinessTypeRow | null>;
|
|
163
|
-
create(data: CreateBusinessTypeData): Promise<BusinessTypeRow>;
|
|
164
|
-
update(businessTypeId: string, data: UpdateBusinessTypeData): Promise<BusinessTypeRow>;
|
|
165
|
-
softDelete(businessTypeId: string): Promise<void>;
|
|
166
|
-
listVersions(businessTypeId: string): Promise<BusinessTypeVersionRow[]>;
|
|
167
|
-
findVersionById(versionId: string): Promise<BusinessTypeVersionRow | null>;
|
|
168
|
-
findCurrentDraft(businessTypeId: string): Promise<BusinessTypeVersionRow | null>;
|
|
169
|
-
findLatestLive(businessTypeId: string): Promise<BusinessTypeVersionRow | null>;
|
|
170
|
-
createDraft(data: CreateBusinessTypeVersionDraftData): Promise<BusinessTypeVersionRow>;
|
|
171
|
-
updateDraft(versionId: string, data: UpdateBusinessTypeVersionDraftData): Promise<BusinessTypeVersionRow>;
|
|
172
|
-
publishDraft(versionId: string, publishMeta: {
|
|
173
|
-
publishedByUserId: string | null;
|
|
174
|
-
publishedChanges: VersionChange[];
|
|
175
|
-
nonRegressive: boolean;
|
|
176
|
-
}): Promise<BusinessTypeVersionRow>;
|
|
177
|
-
}
|
|
178
146
|
/**
|
|
179
147
|
* In-memory implementation of `MarketingProjectionRepository`. Enforces
|
|
180
148
|
* uniqueness over (`targetType`, `targetVersionId`, `locale`) like the
|
|
@@ -274,4 +242,4 @@ interface CreateSaasPlatformTestModuleOptions {
|
|
|
274
242
|
*/
|
|
275
243
|
declare function createSaasPlatformTestModule(options: CreateSaasPlatformTestModuleOptions): DynamicModule;
|
|
276
244
|
|
|
277
|
-
export { type CreateSaasPlatformTestModuleOptions, FakeBundleRepository,
|
|
245
|
+
export { type CreateSaasPlatformTestModuleOptions, FakeBundleRepository, FakeMarketingProjectionRepository, FakePlanRepository, FakePlanVersionRepository, FakeSubscriptionBundleRepository, FakeSubscriptionContractRepository, FakeSubscriptionRepository, FakeTransactionRunner, StubAuditPort, StubMfaPort, StubRlsBypassPort, createSaasPlatformTestModule };
|