@saasicat/core 1.0.0-rc.6 → 1.0.0-rc.7
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/README.md +2 -1
- package/dist/.build-stamp +1 -1
- package/dist/index.cjs +229 -12
- package/dist/index.d.cts +679 -448
- package/dist/index.d.ts +679 -448
- package/dist/index.js +217 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
function startOfUtcDay(date) {
|
|
3
3
|
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
|
4
4
|
}
|
|
5
|
+
function previousUtcDay(value) {
|
|
6
|
+
const result = new Date(value);
|
|
7
|
+
result.setUTCDate(result.getUTCDate() - 1);
|
|
8
|
+
return result;
|
|
9
|
+
}
|
|
5
10
|
function buildActivePlanVersionWhere(asOf, options = {}) {
|
|
6
11
|
const asOfDayStart = startOfUtcDay(asOf);
|
|
7
12
|
const validityWindow = [
|
|
@@ -18,6 +23,53 @@ function buildActivePlanVersionWhere(asOf, options = {}) {
|
|
|
18
23
|
}
|
|
19
24
|
var buildActiveVersionWhere = buildActivePlanVersionWhere;
|
|
20
25
|
|
|
26
|
+
// src/bundle-draft-defaults.ts
|
|
27
|
+
function bundleDraftDefaults(data) {
|
|
28
|
+
return {
|
|
29
|
+
baseVersionId: data.baseVersionId ?? null,
|
|
30
|
+
features: data.features,
|
|
31
|
+
quotas: data.quotas ?? {},
|
|
32
|
+
compatibility: data.compatibility ?? {},
|
|
33
|
+
pricingOverrides: data.pricingOverrides ?? [],
|
|
34
|
+
monthlyNet: data.monthlyNet ?? null,
|
|
35
|
+
yearlyNet: data.yearlyNet ?? null,
|
|
36
|
+
marketed: data.marketed ?? true,
|
|
37
|
+
changeNote: data.changeNote ?? "",
|
|
38
|
+
createdByUserId: data.createdByUserId ?? null
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function bundleStemDefaults(data) {
|
|
42
|
+
return {
|
|
43
|
+
bundleKey: data.bundleKey,
|
|
44
|
+
label: data.label,
|
|
45
|
+
description: data.description ?? null,
|
|
46
|
+
icon: data.icon ?? null,
|
|
47
|
+
sortOrder: data.sortOrder ?? 0,
|
|
48
|
+
i18n: data.i18n ?? {}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function toBundleStemRow(row) {
|
|
52
|
+
return {
|
|
53
|
+
id: row.id,
|
|
54
|
+
bundleKey: row.bundleKey,
|
|
55
|
+
label: row.label,
|
|
56
|
+
description: row.description,
|
|
57
|
+
icon: row.icon,
|
|
58
|
+
sortOrder: row.sortOrder,
|
|
59
|
+
i18n: row.i18n !== null && typeof row.i18n === "object" && !Array.isArray(row.i18n) ? row.i18n : {},
|
|
60
|
+
createdAt: row.createdAt.toISOString(),
|
|
61
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
62
|
+
deletedAt: row.deletedAt?.toISOString() ?? null
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function definedFields(data, keys) {
|
|
66
|
+
const patch = {};
|
|
67
|
+
for (const key of keys) {
|
|
68
|
+
if (data[key] !== void 0) patch[key] = data[key];
|
|
69
|
+
}
|
|
70
|
+
return patch;
|
|
71
|
+
}
|
|
72
|
+
|
|
21
73
|
// src/catalog-entry.types.ts
|
|
22
74
|
var MARKETING_PRIORITY_MIN = 0;
|
|
23
75
|
var MARKETING_PRIORITY_MAX = 1e4;
|
|
@@ -273,6 +325,8 @@ var CATALOG_ERROR_CODES = {
|
|
|
273
325
|
BUNDLE_VERSION_SUPERSEDED: "BUNDLE_VERSION_SUPERSEDED",
|
|
274
326
|
BUNDLE_VERSION_REGRESSION: "BUNDLE_VERSION_REGRESSION",
|
|
275
327
|
BUNDLE_VERSION_ZERO_PRICE: "BUNDLE_VERSION_ZERO_PRICE",
|
|
328
|
+
BUNDLE_VERSION_NO_PRICE: "BUNDLE_VERSION_NO_PRICE",
|
|
329
|
+
BUNDLE_VERSION_NOT_PRICED_FOR_PLAN: "BUNDLE_VERSION_NOT_PRICED_FOR_PLAN",
|
|
276
330
|
BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED: "BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED",
|
|
277
331
|
BUNDLE_VERSION_VALID_FROM_REQUIRED: "BUNDLE_VERSION_VALID_FROM_REQUIRED",
|
|
278
332
|
BUNDLE_VERSION_VALID_FROM_INVALID: "BUNDLE_VERSION_VALID_FROM_INVALID",
|
|
@@ -319,6 +373,8 @@ var BILLING_ERROR_CODES = {
|
|
|
319
373
|
BUNDLE_ALREADY_SUBSCRIBED: "BUNDLE_ALREADY_SUBSCRIBED",
|
|
320
374
|
BUNDLE_INCOMPATIBLE_WITH_PLAN: "BUNDLE_INCOMPATIBLE_WITH_PLAN",
|
|
321
375
|
BUNDLE_NOT_SELF_SERVICE: "BUNDLE_NOT_SELF_SERVICE",
|
|
376
|
+
BUNDLE_CYCLE_EXCEEDS_PLAN: "BUNDLE_CYCLE_EXCEEDS_PLAN",
|
|
377
|
+
BUNDLE_NOT_PRICED_FOR_THIS_PLAN: "BUNDLE_NOT_PRICED_FOR_THIS_PLAN",
|
|
322
378
|
SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED: "SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED",
|
|
323
379
|
SUBSCRIPTION_BUNDLE_NOT_CANCELLED: "SUBSCRIPTION_BUNDLE_NOT_CANCELLED",
|
|
324
380
|
SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE: "SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE",
|
|
@@ -525,6 +581,137 @@ var REGISTRATION_STEP_BY_STATUS = {
|
|
|
525
581
|
};
|
|
526
582
|
var REGISTRATION_RESUME_TTL_MINUTES = 60;
|
|
527
583
|
|
|
584
|
+
// src/plan-mapping.ts
|
|
585
|
+
function toPlanRow(row) {
|
|
586
|
+
return {
|
|
587
|
+
id: row.id,
|
|
588
|
+
planKey: row.planKey,
|
|
589
|
+
label: row.label,
|
|
590
|
+
description: row.description,
|
|
591
|
+
icon: row.icon,
|
|
592
|
+
sortOrder: row.sortOrder,
|
|
593
|
+
createdAt: row.createdAt.toISOString(),
|
|
594
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
595
|
+
deletedAt: toIsoOrNull(row.deletedAt)
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function toPlanVersionRow(row, planKey, fields) {
|
|
599
|
+
const mapped = {
|
|
600
|
+
id: row.id,
|
|
601
|
+
version: row.version,
|
|
602
|
+
baseVersionId: row.baseVersionId,
|
|
603
|
+
planId: planKey,
|
|
604
|
+
features: toFeatureKeys(row.features),
|
|
605
|
+
quotas: toQuotaEffects(row.quotas),
|
|
606
|
+
monthlyNet: String(row.monthlyNet),
|
|
607
|
+
yearlyNet: String(row.yearlyNet),
|
|
608
|
+
marketed: row.marketed,
|
|
609
|
+
publishedAt: toIsoOrNull(row.publishedAt),
|
|
610
|
+
supersededAt: toIsoOrNull(row.supersededAt),
|
|
611
|
+
publishedChanges: Array.isArray(row.publishedChanges) ? row.publishedChanges : null,
|
|
612
|
+
changeNote: row.changeNote,
|
|
613
|
+
nonRegressive: row.nonRegressive,
|
|
614
|
+
validFrom: fields.validityWindows ? toIsoOrNull(row.validFrom) : null,
|
|
615
|
+
validUntil: fields.validityWindows ? toIsoOrNull(row.validUntil) : null,
|
|
616
|
+
createdByUserId: row.createdByUserId,
|
|
617
|
+
publishedByUserId: row.publishedByUserId,
|
|
618
|
+
createdAt: row.createdAt.toISOString(),
|
|
619
|
+
updatedAt: row.updatedAt.toISOString()
|
|
620
|
+
};
|
|
621
|
+
if (fields.endsAt) {
|
|
622
|
+
mapped.endsAt = toIsoOrNull(row.endsAt);
|
|
623
|
+
}
|
|
624
|
+
return mapped;
|
|
625
|
+
}
|
|
626
|
+
function toIsoOrNull(value) {
|
|
627
|
+
return value ? value.toISOString() : null;
|
|
628
|
+
}
|
|
629
|
+
function toFeatureKeys(value) {
|
|
630
|
+
if (!Array.isArray(value)) return [];
|
|
631
|
+
return value.filter((entry) => typeof entry === "string");
|
|
632
|
+
}
|
|
633
|
+
function toQuotaEffects(value) {
|
|
634
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
635
|
+
return {};
|
|
636
|
+
}
|
|
637
|
+
const quotas = {};
|
|
638
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
639
|
+
if (typeof entry === "number") quotas[key] = entry;
|
|
640
|
+
}
|
|
641
|
+
return quotas;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// src/subscription-contract-mapping.ts
|
|
645
|
+
function toSubscriptionContractRecord(row, lineItems) {
|
|
646
|
+
return {
|
|
647
|
+
id: row.id,
|
|
648
|
+
tenantId: row.tenantId,
|
|
649
|
+
status: row.status,
|
|
650
|
+
effectiveFrom: row.effectiveFrom,
|
|
651
|
+
effectiveUntil: row.effectiveUntil,
|
|
652
|
+
originalOfferId: row.originalOfferId,
|
|
653
|
+
originalPlanVersionId: row.originalPlanVersionId,
|
|
654
|
+
originalBundleVersionIds: toStringArray(row.originalBundleVersionIds),
|
|
655
|
+
entitlementSnapshot: isPlainObject(row.entitlementSnapshot) ? row.entitlementSnapshot : null,
|
|
656
|
+
priceSnapshot: row.priceSnapshot,
|
|
657
|
+
promotionSnapshots: toUnknownArray(row.promotionSnapshots),
|
|
658
|
+
promoCodeSnapshots: toUnknownArray(row.promoCodeSnapshots),
|
|
659
|
+
termsSnapshot: toRecordOrNull(row.termsSnapshot),
|
|
660
|
+
lineItems: lineItems.map(toContractLineItemRecord),
|
|
661
|
+
createdAt: row.createdAt,
|
|
662
|
+
updatedAt: row.updatedAt
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function toContractLineItemRecord(row) {
|
|
666
|
+
return {
|
|
667
|
+
id: row.id,
|
|
668
|
+
contractId: row.contractId,
|
|
669
|
+
kind: row.kind,
|
|
670
|
+
sourceKey: row.sourceKey,
|
|
671
|
+
sourceVersionId: row.sourceVersionId,
|
|
672
|
+
titleSnapshot: row.titleSnapshot,
|
|
673
|
+
descriptionSnapshot: row.descriptionSnapshot,
|
|
674
|
+
quantity: row.quantity,
|
|
675
|
+
unit: row.unit,
|
|
676
|
+
priceNet: Number(row.priceNet),
|
|
677
|
+
priceGross: Number(row.priceGross),
|
|
678
|
+
billingCycle: row.billingCycle,
|
|
679
|
+
minimumTermUntil: row.minimumTermUntil,
|
|
680
|
+
featuresSnapshot: toStringArray(row.featuresSnapshot),
|
|
681
|
+
quotaEffectsSnapshot: toQuotaEffects2(row.quotaEffectsSnapshot),
|
|
682
|
+
metadata: toRecordOrNull(row.metadata),
|
|
683
|
+
createdAt: row.createdAt
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function isPlainObject(value) {
|
|
687
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
688
|
+
}
|
|
689
|
+
function toUnknownArray(value) {
|
|
690
|
+
return Array.isArray(value) ? value : [];
|
|
691
|
+
}
|
|
692
|
+
function toRecordOrNull(value) {
|
|
693
|
+
return isPlainObject(value) ? value : null;
|
|
694
|
+
}
|
|
695
|
+
function toStringArray(value) {
|
|
696
|
+
if (!Array.isArray(value)) return [];
|
|
697
|
+
return value.filter((entry) => typeof entry === "string");
|
|
698
|
+
}
|
|
699
|
+
function toQuotaEffects2(value) {
|
|
700
|
+
if (!isPlainObject(value)) return {};
|
|
701
|
+
const effects = {};
|
|
702
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
703
|
+
if (typeof entry === "number") effects[key] = entry;
|
|
704
|
+
}
|
|
705
|
+
return effects;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/subscription-contract.types.ts
|
|
709
|
+
var BUNDLE_PRICE_LOOKUP_LIMIT = 200;
|
|
710
|
+
var ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES = [
|
|
711
|
+
"active",
|
|
712
|
+
"scheduled"
|
|
713
|
+
];
|
|
714
|
+
|
|
528
715
|
// src/version-editability.ts
|
|
529
716
|
function isVersionEditable(v, now = /* @__PURE__ */ new Date()) {
|
|
530
717
|
if (v.publishedAt === null) {
|
|
@@ -596,6 +783,8 @@ var ERROR_MESSAGES_EN = {
|
|
|
596
783
|
BUNDLE_VERSION_SUPERSEDED: "BundleVersion '{bundleVersionId}' has been superseded by a newer version.",
|
|
597
784
|
BUNDLE_VERSION_REGRESSION: "This bundle version is regressive (feature removed / quota lowered / price raised). Publishing requires an explicit `forceRegressive: true` (UI confirmation dialog with MFA).",
|
|
598
785
|
BUNDLE_VERSION_ZERO_PRICE: "A bundle version cannot be published with an explicit price of 0.00 (guard against seed placeholders). For free bundles leave it null, or set allowZeroPrice.",
|
|
786
|
+
BUNDLE_VERSION_NO_PRICE: "This bundle version cannot be published without a price: neither a base price nor any plan override resolves one.",
|
|
787
|
+
BUNDLE_VERSION_NOT_PRICED_FOR_PLAN: "This bundle is offered to plan '{planKey}', which is sold {billingCycle}, and no {billingCycle} price resolves for it \u2014 neither a base price nor a plan override.",
|
|
599
788
|
BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED: "Discard is not implemented in the current repository. Implement BundleRepository.deleteDraft.",
|
|
600
789
|
BUNDLE_VERSION_VALID_FROM_REQUIRED: "Published bundle versions must keep a validFrom. Set a new future date, or edit the draft before publishing.",
|
|
601
790
|
BUNDLE_VERSION_VALID_FROM_INVALID: "validFrom '{validFrom}' is not a valid date",
|
|
@@ -609,12 +798,12 @@ var ERROR_MESSAGES_EN = {
|
|
|
609
798
|
PLAN_VERSION_NOT_FOUND: "PlanVersion '{versionId}' not found",
|
|
610
799
|
BUNDLE_NOT_FOUND: "Bundle '{bundleId}' not found",
|
|
611
800
|
BUNDLE_VERSION_NOT_FOUND: "BundleVersion '{bundleVersionId}' not found",
|
|
612
|
-
FEATURE_NOT_FOUND: "Feature '{featureKey}' not found
|
|
613
|
-
QUOTA_NOT_FOUND: "Quota '{quotaKey}' not found
|
|
801
|
+
FEATURE_NOT_FOUND: "Feature '{featureKey}' not found",
|
|
802
|
+
QUOTA_NOT_FOUND: "Quota '{quotaKey}' not found",
|
|
614
803
|
PROMOTION_NOT_FOUND: "Promotion '{promotionId}' not found",
|
|
615
804
|
MARKETING_PROJECTION_NOT_FOUND: "MarketingProjection '{projectionId}' not found",
|
|
616
|
-
PLAN_ALREADY_EXISTS: "Plan '{planKey}' already exists
|
|
617
|
-
BUNDLE_ALREADY_EXISTS: "Bundle '{bundleKey}' already exists
|
|
805
|
+
PLAN_ALREADY_EXISTS: "Plan '{planKey}' already exists",
|
|
806
|
+
BUNDLE_ALREADY_EXISTS: "Bundle '{bundleKey}' already exists",
|
|
618
807
|
MARKETING_PROJECTION_ALREADY_EXISTS: "Marketing projection for {targetType}/{targetVersionId}/{locale} already exists \u2014 use PATCH to edit it",
|
|
619
808
|
PLAN_DRAFT_ALREADY_EXISTS: "Plan '{planKey}' already has a draft version v{draftVersion}; publish or discard it first",
|
|
620
809
|
BUNDLE_DRAFT_ALREADY_EXISTS: "Bundle '{bundleKey}' already has a draft version v{draftVersion}; publish or discard it first",
|
|
@@ -628,6 +817,8 @@ var ERROR_MESSAGES_EN = {
|
|
|
628
817
|
BUNDLE_ALREADY_SUBSCRIBED: "Subscription '{subscriptionId}' has already actively booked this bundle.",
|
|
629
818
|
BUNDLE_INCOMPATIBLE_WITH_PLAN: "BundleVersion '{bundleVersionId}' is not compatible with plan '{planKey}'. Allowed: [{allowedPlanKeys}].",
|
|
630
819
|
BUNDLE_NOT_SELF_SERVICE: "Bundle '{bundleKey}' is only activated via a special contract. Please contact the contract manager.",
|
|
820
|
+
BUNDLE_CYCLE_EXCEEDS_PLAN: "A {billingCycle} bundle cannot run beside a {planCycle} plan: it would still be committed on every day the plan could end.",
|
|
821
|
+
BUNDLE_NOT_PRICED_FOR_THIS_PLAN: "This bundle has no {billingCycle} price for the {planKey} plan, so it cannot be booked from here.",
|
|
631
822
|
SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED: "SubscriptionBundle '{subscriptionBundleId}' is already cancelled.",
|
|
632
823
|
SUBSCRIPTION_BUNDLE_NOT_CANCELLED: "SubscriptionBundle '{subscriptionBundleId}' is not cancelled.",
|
|
633
824
|
SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE: "Cancellation already in effect \u2014 book the bundle again.",
|
|
@@ -636,7 +827,7 @@ var ERROR_MESSAGES_EN = {
|
|
|
636
827
|
SUBSCRIPTION_BUNDLE_NOT_FOUND: "SubscriptionBundle '{subscriptionBundleId}' not found",
|
|
637
828
|
TENANT_NOT_FOUND: "Tenant {slug} not found",
|
|
638
829
|
NO_ACTIVE_PLAN_VERSION: "No plan version for {planId} active as of {asOf} \u2014 neither the validFrom window is satisfied nor is a latest-live version available.",
|
|
639
|
-
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" is not in the catalog
|
|
830
|
+
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" is not in the catalog',
|
|
640
831
|
PLAN_NOT_SELF_SERVICE: "{planKey} is not activated via self-service.",
|
|
641
832
|
PLAN_CHANGE_BLOCKED: "Plan change during onboarding is blocked.",
|
|
642
833
|
NO_PENDING_PLAN_VERSION: "There is no pending plan version awaiting confirmation.",
|
|
@@ -756,6 +947,8 @@ var ERROR_MESSAGES_DE = {
|
|
|
756
947
|
BUNDLE_VERSION_SUPERSEDED: "BundleVersion '{bundleVersionId}' wurde durch eine neuere Version abgel\xF6st.",
|
|
757
948
|
BUNDLE_VERSION_REGRESSION: "Diese Bundle-Version ist regressiv (Feature entfernt / Quota gesenkt / Preis erh\xF6ht). Das Ver\xF6ffentlichen erfordert ein ausdr\xFCckliches `forceRegressive: true` (Best\xE4tigungsdialog in der UI mit MFA).",
|
|
758
949
|
BUNDLE_VERSION_ZERO_PRICE: "Eine Bundle-Version l\xE4sst sich nicht mit einem ausdr\xFCcklichen Preis von 0,00 ver\xF6ffentlichen (Schutz vor Seed-Platzhaltern). Kostenlose Bundles l\xE4sst du auf null, oder du setzt allowZeroPrice.",
|
|
950
|
+
BUNDLE_VERSION_NO_PRICE: "Diese Bundle-Version kann ohne Preis nicht ver\xF6ffentlicht werden: weder ein Grundpreis noch eine Plan-\xDCberschreibung ergibt einen.",
|
|
951
|
+
BUNDLE_VERSION_NOT_PRICED_FOR_PLAN: "Dieses Bundle wird dem Plan '{planKey}' angeboten, der {billingCycle} verkauft wird, und daf\xFCr ergibt sich kein {billingCycle} Preis \u2014 weder als Grundpreis noch als Plan-\xDCberschreibung.",
|
|
759
952
|
BUNDLE_VERSION_DISCARD_NOT_IMPLEMENTED: "Das Verwerfen ist im aktuellen Repository nicht implementiert. Implementiere BundleRepository.deleteDraft.",
|
|
760
953
|
BUNDLE_VERSION_VALID_FROM_REQUIRED: "Ver\xF6ffentlichte Bundle-Versionen m\xFCssen ein validFrom behalten. Setze ein neues Datum in der Zukunft, oder bearbeite den Entwurf vor dem Ver\xF6ffentlichen.",
|
|
761
954
|
BUNDLE_VERSION_VALID_FROM_INVALID: "validFrom '{validFrom}' ist kein g\xFCltiges Datum",
|
|
@@ -769,12 +962,12 @@ var ERROR_MESSAGES_DE = {
|
|
|
769
962
|
PLAN_VERSION_NOT_FOUND: "PlanVersion '{versionId}' nicht gefunden",
|
|
770
963
|
BUNDLE_NOT_FOUND: "Bundle '{bundleId}' nicht gefunden",
|
|
771
964
|
BUNDLE_VERSION_NOT_FOUND: "BundleVersion '{bundleVersionId}' nicht gefunden",
|
|
772
|
-
FEATURE_NOT_FOUND: "Feature '{featureKey}'
|
|
773
|
-
QUOTA_NOT_FOUND: "Quota '{quotaKey}'
|
|
965
|
+
FEATURE_NOT_FOUND: "Feature '{featureKey}' nicht gefunden",
|
|
966
|
+
QUOTA_NOT_FOUND: "Quota '{quotaKey}' nicht gefunden",
|
|
774
967
|
PROMOTION_NOT_FOUND: "Promotion '{promotionId}' nicht gefunden",
|
|
775
968
|
MARKETING_PROJECTION_NOT_FOUND: "MarketingProjection '{projectionId}' nicht gefunden",
|
|
776
|
-
PLAN_ALREADY_EXISTS: "Plan '{planKey}' gibt es
|
|
777
|
-
BUNDLE_ALREADY_EXISTS: "Bundle '{bundleKey}' gibt es
|
|
969
|
+
PLAN_ALREADY_EXISTS: "Plan '{planKey}' gibt es bereits",
|
|
970
|
+
BUNDLE_ALREADY_EXISTS: "Bundle '{bundleKey}' gibt es bereits",
|
|
778
971
|
MARKETING_PROJECTION_ALREADY_EXISTS: "F\xFCr {targetType}/{targetVersionId}/{locale} gibt es bereits eine Marketing-Projektion \u2014 bearbeite sie per PATCH",
|
|
779
972
|
PLAN_DRAFT_ALREADY_EXISTS: "Plan '{planKey}' hat bereits die Entwurfsversion v{draftVersion}; ver\xF6ffentliche oder verwirf sie zuerst",
|
|
780
973
|
BUNDLE_DRAFT_ALREADY_EXISTS: "Bundle '{bundleKey}' hat bereits die Entwurfsversion v{draftVersion}; ver\xF6ffentliche oder verwirf sie zuerst",
|
|
@@ -788,6 +981,8 @@ var ERROR_MESSAGES_DE = {
|
|
|
788
981
|
BUNDLE_ALREADY_SUBSCRIBED: "Abonnement '{subscriptionId}' hat dieses Bundle bereits aktiv gebucht.",
|
|
789
982
|
BUNDLE_INCOMPATIBLE_WITH_PLAN: "BundleVersion '{bundleVersionId}' passt nicht zum Plan '{planKey}'. Erlaubt: [{allowedPlanKeys}].",
|
|
790
983
|
BUNDLE_NOT_SELF_SERVICE: "Bundle '{bundleKey}' wird nur \xFCber einen Sondervertrag freigeschaltet. Bitte wende dich an die Vertragsverwaltung.",
|
|
984
|
+
BUNDLE_CYCLE_EXCEEDS_PLAN: "Ein {billingCycle} abgerechnetes Bundle passt nicht zu einem {planCycle} abgerechneten Plan: es w\xE4re an jedem Tag gebunden, an dem der Plan enden kann.",
|
|
985
|
+
BUNDLE_NOT_PRICED_FOR_THIS_PLAN: "F\xFCr dieses Bundle ist im Plan {planKey} kein {billingCycle} Preis hinterlegt, es kann hier deshalb nicht gebucht werden.",
|
|
791
986
|
SUBSCRIPTION_BUNDLE_ALREADY_CANCELLED: "SubscriptionBundle '{subscriptionBundleId}' ist bereits gek\xFCndigt.",
|
|
792
987
|
SUBSCRIPTION_BUNDLE_NOT_CANCELLED: "SubscriptionBundle '{subscriptionBundleId}' ist nicht gek\xFCndigt.",
|
|
793
988
|
SUBSCRIPTION_BUNDLE_CANCELLATION_EFFECTIVE: "Die K\xFCndigung ist bereits wirksam \u2014 buche das Bundle einfach neu.",
|
|
@@ -796,7 +991,7 @@ var ERROR_MESSAGES_DE = {
|
|
|
796
991
|
SUBSCRIPTION_BUNDLE_NOT_FOUND: "SubscriptionBundle '{subscriptionBundleId}' nicht gefunden",
|
|
797
992
|
TENANT_NOT_FOUND: "Mandant {slug} nicht gefunden",
|
|
798
993
|
NO_ACTIVE_PLAN_VERSION: "Zum {asOf} ist keine Planversion f\xFCr {planId} aktiv \u2014 weder ist das validFrom-Fenster erf\xFCllt, noch steht eine j\xFCngste Live-Version bereit.",
|
|
799
|
-
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" steht nicht im Katalog
|
|
994
|
+
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" steht nicht im Katalog',
|
|
800
995
|
PLAN_NOT_SELF_SERVICE: "{planKey} wird nicht per Self-Service freigeschaltet.",
|
|
801
996
|
PLAN_CHANGE_BLOCKED: "W\xE4hrend des Onboardings ist ein Planwechsel gesperrt.",
|
|
802
997
|
NO_PENDING_PLAN_VERSION: "Es wartet keine Planversion auf eine Best\xE4tigung.",
|
|
@@ -857,8 +1052,10 @@ var ERROR_MESSAGES_DE = {
|
|
|
857
1052
|
[FEATURE_NOT_LICENSED]: "Das Feature {featureKeys} ist im aktuellen Plan nicht enthalten."
|
|
858
1053
|
};
|
|
859
1054
|
export {
|
|
1055
|
+
ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES,
|
|
860
1056
|
AUTH_ERROR_CODES,
|
|
861
1057
|
BILLING_ERROR_CODES,
|
|
1058
|
+
BUNDLE_PRICE_LOOKUP_LIMIT,
|
|
862
1059
|
CATALOG_ERROR_CODES,
|
|
863
1060
|
CONTRACT_ERROR_CODES,
|
|
864
1061
|
ERROR_MESSAGES_DE,
|
|
@@ -887,19 +1084,28 @@ export {
|
|
|
887
1084
|
buildActivePlanVersionWhere,
|
|
888
1085
|
buildActiveVersionWhere,
|
|
889
1086
|
buildFeatureRequiresIndex,
|
|
1087
|
+
bundleDraftDefaults,
|
|
1088
|
+
bundleStemDefaults,
|
|
890
1089
|
classifyBundleVersionDiff,
|
|
891
1090
|
classifyPlanDiff,
|
|
892
1091
|
collectUnsatisfiedRequires,
|
|
893
1092
|
coverageExcludingSelf,
|
|
1093
|
+
definedFields,
|
|
894
1094
|
formatErrorMessage,
|
|
895
1095
|
isBundleRedundant,
|
|
896
1096
|
isPlatformUserExistsError,
|
|
897
1097
|
isVersionEditable,
|
|
898
1098
|
missingRequiresFor,
|
|
899
1099
|
pickActivePromo,
|
|
1100
|
+
previousUtcDay,
|
|
900
1101
|
promoStatus,
|
|
901
1102
|
resolveBundleAvailability,
|
|
902
1103
|
resolveErrorMessage,
|
|
903
1104
|
selectChargeableBundles,
|
|
904
|
-
startOfUtcDay
|
|
1105
|
+
startOfUtcDay,
|
|
1106
|
+
toBundleStemRow,
|
|
1107
|
+
toContractLineItemRecord,
|
|
1108
|
+
toPlanRow,
|
|
1109
|
+
toPlanVersionRow,
|
|
1110
|
+
toSubscriptionContractRecord
|
|
905
1111
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saasicat/core",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.7",
|
|
4
4
|
"description": "TypeScript contracts for SaaSiCat — capabilities, catalogs, subscriptions, entitlements, admin manifests, persistence ports — and the pure domain logic both server and browser run: error catalogues, plan-diff classification, promo arithmetic, feature requirements.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|