@saasicat/core 1.0.0-rc.16 → 1.0.0-rc.17

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/.build-stamp CHANGED
@@ -1 +1 @@
1
- ac1a4c0280cf9333a264b4d84b290ab32ab44dd67287ec6d1abd99c01bc863b9
1
+ 5a529cc8f17f234940c3b0844d6f20fce18fadd196d3b3485274b711635819af
package/dist/index.cjs CHANGED
@@ -37,11 +37,14 @@ __export(index_exports, {
37
37
  OTP_TTL_MINUTES: () => OTP_TTL_MINUTES,
38
38
  OTP_VERIFY_MAX_ATTEMPTS: () => OTP_VERIFY_MAX_ATTEMPTS,
39
39
  PASSWORD_RESET_TTL_MINUTES: () => PASSWORD_RESET_TTL_MINUTES,
40
+ PAYMENT_ERROR_CODES: () => PAYMENT_ERROR_CODES,
41
+ PAYMENT_METHOD_TYPES: () => PAYMENT_METHOD_TYPES,
40
42
  PENDING_CHECKOUT_TTL_DAYS: () => PENDING_CHECKOUT_TTL_DAYS,
41
43
  PENDING_EMAIL_TTL_HOURS: () => PENDING_EMAIL_TTL_HOURS,
42
44
  PENDING_ONBOARDING_TTL_DAYS: () => PENDING_ONBOARDING_TTL_DAYS,
43
45
  PLATFORM_ERROR_CODES: () => PLATFORM_ERROR_CODES,
44
46
  PROMO_ERROR_CODES: () => PROMO_ERROR_CODES,
47
+ PaymentCallbackRejectedError: () => PaymentCallbackRejectedError,
45
48
  PersistenceCapabilityError: () => PersistenceCapabilityError,
46
49
  PlatformUserExistsError: () => PlatformUserExistsError,
47
50
  REGISTRATION_ERROR_CODES: () => REGISTRATION_ERROR_CODES,
@@ -70,6 +73,7 @@ __export(index_exports, {
70
73
  formatErrorMessage: () => formatErrorMessage,
71
74
  identityCorrectionDelta: () => identityCorrectionDelta,
72
75
  isBundleRedundant: () => isBundleRedundant,
76
+ isPaymentCallbackRejectedError: () => isPaymentCallbackRejectedError,
73
77
  isPlatformUserExistsError: () => isPlatformUserExistsError,
74
78
  isVersionEditable: () => isVersionEditable,
75
79
  keepOneRecommended: () => keepOneRecommended,
@@ -86,11 +90,13 @@ __export(index_exports, {
86
90
  settingsSubtreeOf: () => settingsSubtreeOf,
87
91
  startOfUtcDay: () => startOfUtcDay,
88
92
  subscriberFromRegistration: () => subscriberFromRegistration,
93
+ subscriberPaymentMethodColumns: () => subscriberPaymentMethodColumns,
89
94
  toBundleStemRow: () => toBundleStemRow,
90
95
  toContractLineItemRecord: () => toContractLineItemRecord,
91
96
  toPlanRow: () => toPlanRow,
92
97
  toPlanVersionRow: () => toPlanVersionRow,
93
98
  toSubscriberCorrectionRecord: () => toSubscriberCorrectionRecord,
99
+ toSubscriberPaymentMethodRecord: () => toSubscriberPaymentMethodRecord,
94
100
  toSubscriberRecord: () => toSubscriberRecord,
95
101
  toSubscriptionContractRecord: () => toSubscriptionContractRecord
96
102
  });
@@ -697,7 +703,10 @@ var SUBSCRIBER_ERROR_CODES = {
697
703
  SUBSCRIBER_ALREADY_EXISTS: "SUBSCRIBER_ALREADY_EXISTS",
698
704
  SUBSCRIBER_NOT_FOUND: "SUBSCRIBER_NOT_FOUND",
699
705
  SUBSCRIBER_LEGAL_NAME_REQUIRED: "SUBSCRIBER_LEGAL_NAME_REQUIRED",
700
- /** A detail that has a form — the country, the invoice email — is not in it. Carries `field`. */
706
+ /**
707
+ * A detail that has a form — the country, the invoice email — is not in it,
708
+ * or one sign-up requires — the billing address — is missing. Carries `field`.
709
+ */
701
710
  SUBSCRIBER_DETAIL_INVALID: "SUBSCRIBER_DETAIL_INVALID",
702
711
  /** A contact change named a field of the legal identity. Carries `field`. */
703
712
  SUBSCRIBER_IDENTITY_NOT_A_CONTACT: "SUBSCRIBER_IDENTITY_NOT_A_CONTACT",
@@ -732,6 +741,12 @@ var AUTH_ERROR_CODES = {
732
741
  /** Neither `tenantId` nor `userId` could be resolved from the request. */
733
742
  TENANT_CONTEXT_MISSING: "TENANT_CONTEXT_MISSING",
734
743
  TENANT_ADMIN_REQUIRED: "TENANT_ADMIN_REQUIRED",
744
+ /**
745
+ * The tenant's billing area — its payment method, and later its invoices
746
+ * and account — needs the billing permission, which the application maps
747
+ * to its roles and the tenant's administrator holds by default.
748
+ */
749
+ BILLING_PERMISSION_REQUIRED: "BILLING_PERMISSION_REQUIRED",
735
750
  SUPER_ADMIN_REQUIRED: "SUPER_ADMIN_REQUIRED",
736
751
  /** TOTP MFA has never been set up for this user. */
737
752
  MFA_NOT_SET_UP: "MFA_NOT_SET_UP",
@@ -759,6 +774,22 @@ var PROMO_ERROR_CODES = {
759
774
  PROMO_WOULD_PRODUCE_ZERO_INVOICE: "PROMO_WOULD_PRODUCE_ZERO_INVOICE",
760
775
  PROMO_MAX_REDEMPTIONS_LOWERED: "PROMO_MAX_REDEMPTIONS_LOWERED"
761
776
  };
777
+ var PAYMENT_ERROR_CODES = {
778
+ /**
779
+ * No gateway account takes new payment methods:
780
+ * `config/saas.yaml#payments.newPaymentMethods` names none.
781
+ */
782
+ PAYMENTS_NOT_CONFIGURED: "PAYMENTS_NOT_CONFIGURED",
783
+ /** A callback arrived for an account `config/saas.yaml#payments.accounts` does not name. Carries `account`. */
784
+ PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "PAYMENT_GATEWAY_ACCOUNT_UNKNOWN",
785
+ /** A callback the gateway did not send: its signature does not verify. */
786
+ PAYMENT_CALLBACK_REJECTED: "PAYMENT_CALLBACK_REJECTED",
787
+ /**
788
+ * A success or cancel URL at an origin `config/saas.yaml#payments.returnUrlOrigins`
789
+ * does not name. Carries `field`.
790
+ */
791
+ PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED"
792
+ };
762
793
  var SETTINGS_ERROR_CODES = {
763
794
  /** No recorded change has this id, or the installation keeps no record at all. */
764
795
  SETTINGS_CHANGE_NOT_FOUND: "SETTINGS_CHANGE_NOT_FOUND"
@@ -772,6 +803,7 @@ var PLATFORM_ERROR_CODES = {
772
803
  ...CONTRACT_ERROR_CODES,
773
804
  ...SUBSCRIBER_ERROR_CODES,
774
805
  ...REGISTRATION_ERROR_CODES,
806
+ ...PAYMENT_ERROR_CODES,
775
807
  ...SETTINGS_ERROR_CODES
776
808
  };
777
809
 
@@ -851,6 +883,19 @@ function selectChargeableBundles(planFeatures, selectedBundles) {
851
883
  }
852
884
  }
853
885
 
886
+ // src/payment-gateway.types.ts
887
+ var PAYMENT_CALLBACK_REJECTED = "PAYMENT_CALLBACK_REJECTED";
888
+ var PaymentCallbackRejectedError = class extends Error {
889
+ code = PAYMENT_CALLBACK_REJECTED;
890
+ constructor(reason) {
891
+ super(`Payment callback rejected: ${reason}`);
892
+ this.name = "PaymentCallbackRejectedError";
893
+ }
894
+ };
895
+ function isPaymentCallbackRejectedError(err) {
896
+ return err instanceof Error && err.code === PAYMENT_CALLBACK_REJECTED;
897
+ }
898
+
854
899
  // src/registration.types.ts
855
900
  var PENDING_EMAIL_TTL_HOURS = 72;
856
901
  var PENDING_ONBOARDING_TTL_DAYS = 14;
@@ -1014,7 +1059,17 @@ function issuerPartyOf(issuer) {
1014
1059
  };
1015
1060
  }
1016
1061
  function subscriberFromRegistration(pending) {
1017
- return { legalName: pending.tenantName, invoiceEmail: pending.email };
1062
+ return {
1063
+ legalName: pending.tenantName,
1064
+ invoiceEmail: pending.email,
1065
+ addressLine1: pending.addressLine1,
1066
+ addressLine2: pending.addressLine2,
1067
+ postalCode: pending.postalCode,
1068
+ city: pending.city,
1069
+ country: pending.country,
1070
+ vatId: pending.vatId,
1071
+ taxNumber: pending.taxNumber
1072
+ };
1018
1073
  }
1019
1074
  function toIdentityValues(value) {
1020
1075
  if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
@@ -1028,6 +1083,59 @@ function toIdentityValues(value) {
1028
1083
  return values;
1029
1084
  }
1030
1085
 
1086
+ // src/subscriber-payment-method-mapping.ts
1087
+ var PAYMENT_METHOD_TYPES = ["card", "sepa_debit"];
1088
+ var STATUSES = ["ACTIVE", "REPLACED"];
1089
+ function toSubscriberPaymentMethodRecord(row) {
1090
+ return {
1091
+ id: row.id,
1092
+ subscriberId: row.subscriberId,
1093
+ gatewayAccount: row.gatewayAccount,
1094
+ provider: row.provider,
1095
+ customerRef: row.customerRef,
1096
+ paymentMethodRef: row.paymentMethodRef,
1097
+ type: oneOf(PAYMENT_METHOD_TYPES, row.type, "type", row.id),
1098
+ brand: row.brand,
1099
+ last4: row.last4,
1100
+ expiryMonth: row.expiryMonth,
1101
+ expiryYear: row.expiryYear,
1102
+ country: row.country,
1103
+ bankCode: row.bankCode,
1104
+ mandateReference: row.mandateReference,
1105
+ status: oneOf(STATUSES, row.status, "status", row.id),
1106
+ confirmedAt: row.confirmedAt,
1107
+ replacedAt: row.replacedAt,
1108
+ createdAt: row.createdAt
1109
+ };
1110
+ }
1111
+ function subscriberPaymentMethodColumns(data) {
1112
+ return {
1113
+ subscriberId: data.subscriberId,
1114
+ gatewayAccount: data.gatewayAccount,
1115
+ provider: data.provider,
1116
+ customerRef: data.customerRef,
1117
+ paymentMethodRef: data.paymentMethodRef,
1118
+ type: data.type,
1119
+ brand: data.brand,
1120
+ last4: data.last4,
1121
+ expiryMonth: data.expiryMonth,
1122
+ expiryYear: data.expiryYear,
1123
+ country: data.country,
1124
+ bankCode: data.bankCode,
1125
+ mandateReference: data.mandateReference,
1126
+ confirmedAt: data.confirmedAt
1127
+ };
1128
+ }
1129
+ function oneOf(allowed, value, column, id) {
1130
+ const match = allowed.find((entry) => entry === value);
1131
+ if (match === void 0) {
1132
+ throw new Error(
1133
+ `subscriber_payment_methods row '${id}' holds ${column} '${value}', which is none of ${allowed.join(", ")}.`
1134
+ );
1135
+ }
1136
+ return match;
1137
+ }
1138
+
1031
1139
  // src/subscription-contract-mapping.ts
1032
1140
  function toSubscriptionContractRecord(row, lineItems) {
1033
1141
  return {
@@ -1178,6 +1286,7 @@ var ERROR_MESSAGES_EN = {
1178
1286
  NO_TENANT_ASSIGNED: "No tenant assigned",
1179
1287
  TENANT_CONTEXT_MISSING: "No tenant ID found on the request",
1180
1288
  TENANT_ADMIN_REQUIRED: "This action requires the TENANT_ADMIN role.",
1289
+ BILLING_PERMISSION_REQUIRED: "This part of the billing area requires the billing permission.",
1181
1290
  SUPER_ADMIN_REQUIRED: "Only the SUPER_ADMIN role is allowed",
1182
1291
  MFA_NOT_SET_UP: "Run the MFA setup via the CLI first.",
1183
1292
  MFA_REQUIRED: "TOTP code required in the X-Mfa-Code header.",
@@ -1345,6 +1454,11 @@ var ERROR_MESSAGES_EN = {
1345
1454
  PLAN_NOT_AVAILABLE: "This plan is not available.",
1346
1455
  PLAN_NOT_SELECTED: "Please select a plan first.",
1347
1456
  MODEL_NOT_AVAILABLE: "This option is not available.",
1457
+ // ── payments ──
1458
+ PAYMENTS_NOT_CONFIGURED: "Payment methods cannot be set up here yet.",
1459
+ PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "No payment gateway account is configured under '{account}'.",
1460
+ PAYMENT_CALLBACK_REJECTED: "The payment callback could not be verified.",
1461
+ PAYMENT_RETURN_URL_NOT_ALLOWED: "The {field} leads to a site this installation does not return to.",
1348
1462
  // ── entitlement (code lives in upsell.types.ts) ──
1349
1463
  [FEATURE_NOT_LICENSED]: "Feature {featureKeys} is not included in the current plan.",
1350
1464
  // ── settings ──
@@ -1379,6 +1493,7 @@ var ERROR_MESSAGES_DE = {
1379
1493
  NO_TENANT_ASSIGNED: "Kein Mandant zugeordnet",
1380
1494
  TENANT_CONTEXT_MISSING: "Am Request wurde keine Mandanten-ID gefunden",
1381
1495
  TENANT_ADMIN_REQUIRED: "Diese Aktion erfordert die Rolle TENANT_ADMIN.",
1496
+ BILLING_PERMISSION_REQUIRED: "Dieser Teil der Abrechnung erfordert die Abrechnungs-Berechtigung.",
1382
1497
  SUPER_ADMIN_REQUIRED: "Nur die Rolle SUPER_ADMIN ist zugelassen",
1383
1498
  MFA_NOT_SET_UP: "Richte MFA zuerst \xFCber die CLI ein.",
1384
1499
  MFA_REQUIRED: "TOTP-Code im Header X-Mfa-Code erforderlich.",
@@ -1546,6 +1661,11 @@ var ERROR_MESSAGES_DE = {
1546
1661
  PLAN_NOT_AVAILABLE: "Dieser Plan steht nicht zur Verf\xFCgung.",
1547
1662
  PLAN_NOT_SELECTED: "Bitte w\xE4hle zuerst einen Plan aus.",
1548
1663
  MODEL_NOT_AVAILABLE: "Diese Option steht nicht zur Verf\xFCgung.",
1664
+ // ── payments ──
1665
+ PAYMENTS_NOT_CONFIGURED: "Zahlungsmethoden k\xF6nnen hier noch nicht hinterlegt werden.",
1666
+ PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "Unter '{account}' ist kein Konto eines Zahlungsanbieters eingerichtet.",
1667
+ PAYMENT_CALLBACK_REJECTED: "Die R\xFCckmeldung des Zahlungsanbieters lie\xDF sich nicht pr\xFCfen.",
1668
+ PAYMENT_RETURN_URL_NOT_ALLOWED: "Die {field} f\xFChrt auf eine Seite, zu der diese Installation nicht zur\xFCckleitet.",
1549
1669
  // ── entitlement (code lives in upsell.types.ts) ──
1550
1670
  [FEATURE_NOT_LICENSED]: "Das Feature {featureKeys} ist im aktuellen Plan nicht enthalten.",
1551
1671
  // ── settings ──
@@ -1570,11 +1690,14 @@ var ERROR_MESSAGES_DE = {
1570
1690
  OTP_TTL_MINUTES,
1571
1691
  OTP_VERIFY_MAX_ATTEMPTS,
1572
1692
  PASSWORD_RESET_TTL_MINUTES,
1693
+ PAYMENT_ERROR_CODES,
1694
+ PAYMENT_METHOD_TYPES,
1573
1695
  PENDING_CHECKOUT_TTL_DAYS,
1574
1696
  PENDING_EMAIL_TTL_HOURS,
1575
1697
  PENDING_ONBOARDING_TTL_DAYS,
1576
1698
  PLATFORM_ERROR_CODES,
1577
1699
  PROMO_ERROR_CODES,
1700
+ PaymentCallbackRejectedError,
1578
1701
  PersistenceCapabilityError,
1579
1702
  PlatformUserExistsError,
1580
1703
  REGISTRATION_ERROR_CODES,
@@ -1603,6 +1726,7 @@ var ERROR_MESSAGES_DE = {
1603
1726
  formatErrorMessage,
1604
1727
  identityCorrectionDelta,
1605
1728
  isBundleRedundant,
1729
+ isPaymentCallbackRejectedError,
1606
1730
  isPlatformUserExistsError,
1607
1731
  isVersionEditable,
1608
1732
  keepOneRecommended,
@@ -1619,11 +1743,13 @@ var ERROR_MESSAGES_DE = {
1619
1743
  settingsSubtreeOf,
1620
1744
  startOfUtcDay,
1621
1745
  subscriberFromRegistration,
1746
+ subscriberPaymentMethodColumns,
1622
1747
  toBundleStemRow,
1623
1748
  toContractLineItemRecord,
1624
1749
  toPlanRow,
1625
1750
  toPlanVersionRow,
1626
1751
  toSubscriberCorrectionRecord,
1752
+ toSubscriberPaymentMethodRecord,
1627
1753
  toSubscriberRecord,
1628
1754
  toSubscriptionContractRecord
1629
1755
  });