@saasicat/core 1.0.0-rc.21 → 1.0.0-rc.23
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 +1 -1
- package/dist/index.cjs +291 -16
- package/dist/index.d.cts +563 -6
- package/dist/index.d.ts +563 -6
- package/dist/index.js +275 -16
- package/package.json +1 -1
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
f3fb737468397b73304896bb7a522f80e2155d9d8df9a49bb3c83267b5014d3d
|
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,10 @@ __export(index_exports, {
|
|
|
32
32
|
FEATURE_NOT_LICENSED: () => FEATURE_NOT_LICENSED,
|
|
33
33
|
ForeignPaymentMethodReferenceError: () => ForeignPaymentMethodReferenceError,
|
|
34
34
|
LEGAL_IDENTITY_FIELDS: () => LEGAL_IDENTITY_FIELDS,
|
|
35
|
+
MAINTENANCE_CAPABILITY: () => MAINTENANCE_CAPABILITY,
|
|
36
|
+
MAINTENANCE_ERROR_CODES: () => MAINTENANCE_ERROR_CODES,
|
|
37
|
+
MAINTENANCE_MESSAGE_MAX_LENGTH: () => MAINTENANCE_MESSAGE_MAX_LENGTH,
|
|
38
|
+
MAINTENANCE_STATE_MAX_AGE_SECONDS: () => MAINTENANCE_STATE_MAX_AGE_SECONDS,
|
|
35
39
|
MARKETING_PRIORITY_MAX: () => MARKETING_PRIORITY_MAX,
|
|
36
40
|
MARKETING_PRIORITY_MIN: () => MARKETING_PRIORITY_MIN,
|
|
37
41
|
OTP_RATE_LIMIT_MAX_SENDS: () => OTP_RATE_LIMIT_MAX_SENDS,
|
|
@@ -54,6 +58,7 @@ __export(index_exports, {
|
|
|
54
58
|
REGISTRATION_STEP_BY_STATUS: () => REGISTRATION_STEP_BY_STATUS,
|
|
55
59
|
SETTINGS_ERROR_CODES: () => SETTINGS_ERROR_CODES,
|
|
56
60
|
SETUP_ERROR_CODES: () => SETUP_ERROR_CODES,
|
|
61
|
+
SUBSCRIBER_ACCOUNT_CAPABILITY: () => SUBSCRIBER_ACCOUNT_CAPABILITY,
|
|
57
62
|
SUBSCRIBER_ERROR_CODES: () => SUBSCRIBER_ERROR_CODES,
|
|
58
63
|
applyPromo: () => applyPromo,
|
|
59
64
|
assertPersistenceCapabilities: () => assertPersistenceCapabilities,
|
|
@@ -76,13 +81,20 @@ __export(index_exports, {
|
|
|
76
81
|
identityCorrectionDelta: () => identityCorrectionDelta,
|
|
77
82
|
isBundleRedundant: () => isBundleRedundant,
|
|
78
83
|
isForeignPaymentMethodReferenceError: () => isForeignPaymentMethodReferenceError,
|
|
84
|
+
isMaintenanceAnnouncementLapsed: () => isMaintenanceAnnouncementLapsed,
|
|
85
|
+
isMaintenanceOverrun: () => isMaintenanceOverrun,
|
|
79
86
|
isPaymentCallbackRejectedError: () => isPaymentCallbackRejectedError,
|
|
80
87
|
isPlatformUserExistsError: () => isPlatformUserExistsError,
|
|
81
88
|
isVersionEditable: () => isVersionEditable,
|
|
82
89
|
issuerIdentityOf: () => issuerIdentityOf,
|
|
83
90
|
keepOneRecommended: () => keepOneRecommended,
|
|
91
|
+
maintenanceRetryAfterSeconds: () => maintenanceRetryAfterSeconds,
|
|
92
|
+
maintenanceStatusOf: () => maintenanceStatusOf,
|
|
93
|
+
maintenanceWindowStatusOf: () => maintenanceWindowStatusOf,
|
|
94
|
+
maintenanceWindowViewOf: () => maintenanceWindowViewOf,
|
|
84
95
|
missingRequiresFor: () => missingRequiresFor,
|
|
85
96
|
movedIdentityFields: () => movedIdentityFields,
|
|
97
|
+
parseZonedInstant: () => parseZonedInstant,
|
|
86
98
|
pickActivePromo: () => pickActivePromo,
|
|
87
99
|
planCatalogSettingsOf: () => planCatalogSettingsOf,
|
|
88
100
|
previousUtcDay: () => previousUtcDay,
|
|
@@ -98,16 +110,20 @@ __export(index_exports, {
|
|
|
98
110
|
selectChargeableBundles: () => selectChargeableBundles,
|
|
99
111
|
settingsSubtreeOf: () => settingsSubtreeOf,
|
|
100
112
|
startOfUtcDay: () => startOfUtcDay,
|
|
113
|
+
subscriberChargeColumns: () => subscriberChargeColumns,
|
|
101
114
|
subscriberFromRegistration: () => subscriberFromRegistration,
|
|
102
115
|
subscriberPaymentMethodColumns: () => subscriberPaymentMethodColumns,
|
|
103
116
|
toBundleStemRow: () => toBundleStemRow,
|
|
104
117
|
toContractLineItemRecord: () => toContractLineItemRecord,
|
|
118
|
+
toMaintenanceWindowRecord: () => toMaintenanceWindowRecord,
|
|
105
119
|
toPlanRow: () => toPlanRow,
|
|
106
120
|
toPlanVersionRow: () => toPlanVersionRow,
|
|
107
121
|
toRunningContractIssuer: () => toRunningContractIssuer,
|
|
122
|
+
toSubscriberChargeRecord: () => toSubscriberChargeRecord,
|
|
108
123
|
toSubscriberCorrectionRecord: () => toSubscriberCorrectionRecord,
|
|
109
124
|
toSubscriberPaymentMethodRecord: () => toSubscriberPaymentMethodRecord,
|
|
110
125
|
toSubscriberRecord: () => toSubscriberRecord,
|
|
126
|
+
toSubscriptionBundleRecord: () => toSubscriptionBundleRecord,
|
|
111
127
|
toSubscriptionContractRecord: () => toSubscriptionContractRecord
|
|
112
128
|
});
|
|
113
129
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -397,6 +413,100 @@ function appendNullableDecimalChange(out, field, oldValue, newValue, polarity) {
|
|
|
397
413
|
appendDecimalChange(out, field, oldValue, newValue, polarity);
|
|
398
414
|
}
|
|
399
415
|
|
|
416
|
+
// src/maintenance-window.types.ts
|
|
417
|
+
var MAINTENANCE_MESSAGE_MAX_LENGTH = 500;
|
|
418
|
+
var MAINTENANCE_STATE_MAX_AGE_SECONDS = 5;
|
|
419
|
+
var MAINTENANCE_CAPABILITY = "maintenance.manage";
|
|
420
|
+
|
|
421
|
+
// src/maintenance-window-mapping.ts
|
|
422
|
+
function toMaintenanceWindowRecord(row) {
|
|
423
|
+
return {
|
|
424
|
+
id: row.id,
|
|
425
|
+
startsAt: row.startsAt,
|
|
426
|
+
endsAt: row.endsAt,
|
|
427
|
+
message: row.message,
|
|
428
|
+
createdAt: row.createdAt,
|
|
429
|
+
createdBy: row.createdBy,
|
|
430
|
+
lockedAt: row.lockedAt,
|
|
431
|
+
lockedBy: row.lockedBy,
|
|
432
|
+
endedAt: row.endedAt,
|
|
433
|
+
endedBy: row.endedBy
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/maintenance-window-views.ts
|
|
438
|
+
var RETRY_AFTER_WITHOUT_END_SECONDS = 60;
|
|
439
|
+
var iso = (date) => date ? date.toISOString() : null;
|
|
440
|
+
function maintenanceWindowStatusOf(window) {
|
|
441
|
+
if (window.endedAt) return window.lockedAt ? "ended" : "cancelled";
|
|
442
|
+
return window.lockedAt ? "locked" : "announced";
|
|
443
|
+
}
|
|
444
|
+
function isMaintenanceOverrun(window, now) {
|
|
445
|
+
return maintenanceWindowStatusOf(window) === "locked" && window.endsAt !== null && window.endsAt.getTime() <= now.getTime();
|
|
446
|
+
}
|
|
447
|
+
function isMaintenanceAnnouncementLapsed(window, now) {
|
|
448
|
+
return maintenanceWindowStatusOf(window) === "announced" && window.endsAt !== null && window.endsAt.getTime() <= now.getTime();
|
|
449
|
+
}
|
|
450
|
+
function maintenanceStatusOf(open, now) {
|
|
451
|
+
if (!open) return { state: "none" };
|
|
452
|
+
const status = maintenanceWindowStatusOf(open);
|
|
453
|
+
if (status === "locked" && open.lockedAt) {
|
|
454
|
+
return {
|
|
455
|
+
state: "locked",
|
|
456
|
+
lockedAt: open.lockedAt.toISOString(),
|
|
457
|
+
endsAt: iso(open.endsAt),
|
|
458
|
+
message: open.message,
|
|
459
|
+
overrun: isMaintenanceOverrun(open, now)
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
if (status === "announced" && open.startsAt && open.endsAt && !isMaintenanceAnnouncementLapsed(open, now)) {
|
|
463
|
+
return {
|
|
464
|
+
state: "announced",
|
|
465
|
+
startsAt: open.startsAt.toISOString(),
|
|
466
|
+
endsAt: open.endsAt.toISOString(),
|
|
467
|
+
message: open.message
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
return { state: "none" };
|
|
471
|
+
}
|
|
472
|
+
function maintenanceWindowViewOf(window, now) {
|
|
473
|
+
return {
|
|
474
|
+
id: window.id,
|
|
475
|
+
status: maintenanceWindowStatusOf(window),
|
|
476
|
+
startsAt: iso(window.startsAt),
|
|
477
|
+
endsAt: iso(window.endsAt),
|
|
478
|
+
message: window.message,
|
|
479
|
+
createdAt: window.createdAt.toISOString(),
|
|
480
|
+
createdBy: window.createdBy,
|
|
481
|
+
lockedAt: iso(window.lockedAt),
|
|
482
|
+
lockedBy: window.lockedBy,
|
|
483
|
+
endedAt: iso(window.endedAt),
|
|
484
|
+
endedBy: window.endedBy,
|
|
485
|
+
overrun: isMaintenanceOverrun(window, now),
|
|
486
|
+
lapsed: isMaintenanceAnnouncementLapsed(window, now)
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function maintenanceRetryAfterSeconds(window, now) {
|
|
490
|
+
if (!window.endsAt || window.endsAt.getTime() <= now.getTime()) {
|
|
491
|
+
return RETRY_AFTER_WITHOUT_END_SECONDS;
|
|
492
|
+
}
|
|
493
|
+
return Math.max(1, Math.ceil((window.endsAt.getTime() - now.getTime()) / 1e3));
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// src/zoned-instant.ts
|
|
497
|
+
function endsInOffset(text) {
|
|
498
|
+
const sign = text.charAt(text.length - 6);
|
|
499
|
+
return (sign === "+" || sign === "-") && text.charAt(text.length - 3) === ":";
|
|
500
|
+
}
|
|
501
|
+
function parseZonedInstant(text) {
|
|
502
|
+
const value = text.trim();
|
|
503
|
+
if (!value.includes("T")) return null;
|
|
504
|
+
const zoned = value.endsWith("Z") || value.endsWith("z") || endsInOffset(value);
|
|
505
|
+
if (!zoned) return null;
|
|
506
|
+
const moment = new Date(value);
|
|
507
|
+
return Number.isNaN(moment.getTime()) ? null : moment;
|
|
508
|
+
}
|
|
509
|
+
|
|
400
510
|
// src/settings-subtree.ts
|
|
401
511
|
var CATALOGUE_KEYS = /* @__PURE__ */ new Set([
|
|
402
512
|
"schemaVersion",
|
|
@@ -727,7 +837,15 @@ var CONTRACT_ERROR_CODES = {
|
|
|
727
837
|
CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED",
|
|
728
838
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND",
|
|
729
839
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT",
|
|
730
|
-
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED"
|
|
840
|
+
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED",
|
|
841
|
+
/**
|
|
842
|
+
* A successor would run beside another contract of the tenant: the
|
|
843
|
+
* contract in force moved while it was being written — another successor
|
|
844
|
+
* took its place, or a cancellation capped it — and kept moving on a
|
|
845
|
+
* second attempt, or a contract begins after the moment the successor
|
|
846
|
+
* would take effect. Nothing was written.
|
|
847
|
+
*/
|
|
848
|
+
SUBSCRIPTION_CONTRACT_CHANGED: "SUBSCRIPTION_CONTRACT_CHANGED"
|
|
731
849
|
};
|
|
732
850
|
var SUBSCRIBER_ERROR_CODES = {
|
|
733
851
|
/**
|
|
@@ -825,12 +943,37 @@ var PAYMENT_ERROR_CODES = {
|
|
|
825
943
|
* A success or cancel URL at an origin `config/saas.yaml#payments.returnUrlOrigins`
|
|
826
944
|
* does not name. Carries `field`.
|
|
827
945
|
*/
|
|
828
|
-
PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED"
|
|
946
|
+
PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED",
|
|
947
|
+
/**
|
|
948
|
+
* The gateway failed — unreachable, refusing the account's keys, or
|
|
949
|
+
* answering with an error — while opening its form or reading a callback
|
|
950
|
+
* back. Answered with 502; what the gateway answered stays in the server
|
|
951
|
+
* log.
|
|
952
|
+
*/
|
|
953
|
+
PAYMENT_GATEWAY_FAILED: "PAYMENT_GATEWAY_FAILED"
|
|
829
954
|
};
|
|
830
955
|
var SETTINGS_ERROR_CODES = {
|
|
831
956
|
/** No recorded change has this id, or the installation keeps no record at all. */
|
|
832
957
|
SETTINGS_CHANGE_NOT_FOUND: "SETTINGS_CHANGE_NOT_FOUND"
|
|
833
958
|
};
|
|
959
|
+
var MAINTENANCE_ERROR_CODES = {
|
|
960
|
+
/** The application is locked for maintenance; the body carries the window. */
|
|
961
|
+
MAINTENANCE: "MAINTENANCE",
|
|
962
|
+
/** A window is already open: move or cancel it before announcing another. */
|
|
963
|
+
MAINTENANCE_WINDOW_ALREADY_OPEN: "MAINTENANCE_WINDOW_ALREADY_OPEN",
|
|
964
|
+
/** No open window has this id — it ended, or it never existed. */
|
|
965
|
+
MAINTENANCE_WINDOW_NOT_OPEN: "MAINTENANCE_WINDOW_NOT_OPEN",
|
|
966
|
+
/** The window is locked: its start is history, and unlocking is what ends it. */
|
|
967
|
+
MAINTENANCE_WINDOW_LOCKED: "MAINTENANCE_WINDOW_LOCKED",
|
|
968
|
+
/** The announced end is not after the announced start. */
|
|
969
|
+
MAINTENANCE_WINDOW_END_NOT_AFTER_START: "MAINTENANCE_WINDOW_END_NOT_AFTER_START",
|
|
970
|
+
/** The announced end has already passed. */
|
|
971
|
+
MAINTENANCE_WINDOW_END_IN_PAST: "MAINTENANCE_WINDOW_END_IN_PAST",
|
|
972
|
+
/** A time without its zone, or not a date and time at all; `field` names which. */
|
|
973
|
+
MAINTENANCE_TIME_INVALID: "MAINTENANCE_TIME_INVALID",
|
|
974
|
+
/** The message is longer than `MAINTENANCE_MESSAGE_MAX_LENGTH`. */
|
|
975
|
+
MAINTENANCE_MESSAGE_TOO_LONG: "MAINTENANCE_MESSAGE_TOO_LONG"
|
|
976
|
+
};
|
|
834
977
|
var PLATFORM_ERROR_CODES = {
|
|
835
978
|
...SETUP_ERROR_CODES,
|
|
836
979
|
...AUTH_ERROR_CODES,
|
|
@@ -841,7 +984,8 @@ var PLATFORM_ERROR_CODES = {
|
|
|
841
984
|
...SUBSCRIBER_ERROR_CODES,
|
|
842
985
|
...REGISTRATION_ERROR_CODES,
|
|
843
986
|
...PAYMENT_ERROR_CODES,
|
|
844
|
-
...SETTINGS_ERROR_CODES
|
|
987
|
+
...SETTINGS_ERROR_CODES,
|
|
988
|
+
...MAINTENANCE_ERROR_CODES
|
|
845
989
|
};
|
|
846
990
|
|
|
847
991
|
// src/errors.ts
|
|
@@ -1091,6 +1235,83 @@ function textOrNull(value) {
|
|
|
1091
1235
|
return trimmed === "" ? null : trimmed;
|
|
1092
1236
|
}
|
|
1093
1237
|
|
|
1238
|
+
// src/closed-value.ts
|
|
1239
|
+
function oneOf(allowed, value, source) {
|
|
1240
|
+
const match = allowed.find((entry) => entry === value);
|
|
1241
|
+
if (match === void 0) {
|
|
1242
|
+
throw new Error(
|
|
1243
|
+
`${source.table} row '${source.id}' holds ${source.column} '${value}', which is none of ${allowed.join(", ")}.`
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
return match;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
// src/subscriber-ledger-mapping.ts
|
|
1250
|
+
var ORIGINS = {
|
|
1251
|
+
activation: true,
|
|
1252
|
+
renewal: true,
|
|
1253
|
+
planChange: true,
|
|
1254
|
+
bundleBooking: true,
|
|
1255
|
+
credit: true,
|
|
1256
|
+
correction: true
|
|
1257
|
+
};
|
|
1258
|
+
var SOURCES = {
|
|
1259
|
+
plan: true,
|
|
1260
|
+
bundle: true,
|
|
1261
|
+
discount: true
|
|
1262
|
+
};
|
|
1263
|
+
var TABLE = "subscriber_ledger_entries";
|
|
1264
|
+
var CENT_TOLERANCE = 1e-6;
|
|
1265
|
+
function toSubscriberChargeRecord(row) {
|
|
1266
|
+
const where = (column) => ({ table: TABLE, column, id: row.id });
|
|
1267
|
+
return {
|
|
1268
|
+
id: row.id,
|
|
1269
|
+
subscriberId: row.subscriberId,
|
|
1270
|
+
tenantId: row.tenantId,
|
|
1271
|
+
subscriptionId: row.subscriptionId,
|
|
1272
|
+
contractId: row.contractId,
|
|
1273
|
+
contractLineItemId: row.contractLineItemId,
|
|
1274
|
+
origin: oneOf(keysOf(ORIGINS), row.origin, where("origin")),
|
|
1275
|
+
source: oneOf(keysOf(SOURCES), row.source, where("source")),
|
|
1276
|
+
sourceRef: row.sourceRef,
|
|
1277
|
+
periodStart: row.periodStart,
|
|
1278
|
+
periodEnd: row.periodEnd,
|
|
1279
|
+
currency: row.currency,
|
|
1280
|
+
amountNet: Number(row.amountNet),
|
|
1281
|
+
bookedAt: row.bookedAt,
|
|
1282
|
+
createdAt: row.createdAt
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
function subscriberChargeColumns(charge) {
|
|
1286
|
+
const cents = charge.amountNet * 100;
|
|
1287
|
+
if (!Number.isFinite(cents) || Math.abs(cents - Math.round(cents)) > CENT_TOLERANCE) {
|
|
1288
|
+
throw new Error(
|
|
1289
|
+
`A charge of ${charge.amountNet} is not a whole number of cents; round it once where it is derived, before it is written.`
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
return {
|
|
1293
|
+
subscriberId: charge.subscriberId,
|
|
1294
|
+
tenantId: charge.tenantId,
|
|
1295
|
+
subscriptionId: charge.subscriptionId,
|
|
1296
|
+
contractId: charge.contractId,
|
|
1297
|
+
contractLineItemId: charge.contractLineItemId,
|
|
1298
|
+
origin: charge.origin,
|
|
1299
|
+
source: charge.source,
|
|
1300
|
+
sourceRef: charge.sourceRef,
|
|
1301
|
+
periodStart: charge.periodStart,
|
|
1302
|
+
periodEnd: charge.periodEnd,
|
|
1303
|
+
currency: charge.currency,
|
|
1304
|
+
amountNet: charge.amountNet.toFixed(2),
|
|
1305
|
+
bookedAt: charge.bookedAt
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
function keysOf(record) {
|
|
1309
|
+
return Object.keys(record);
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
// src/subscriber-ledger.types.ts
|
|
1313
|
+
var SUBSCRIBER_ACCOUNT_CAPABILITY = "charges.read";
|
|
1314
|
+
|
|
1094
1315
|
// src/subscriber-mapping.ts
|
|
1095
1316
|
function formatCustomerNumber(prefix, sequence) {
|
|
1096
1317
|
return `${prefix}${sequence}`;
|
|
@@ -1206,6 +1427,7 @@ function toIdentityValues(value) {
|
|
|
1206
1427
|
// src/subscriber-payment-method-mapping.ts
|
|
1207
1428
|
var PAYMENT_METHOD_TYPES = ["card", "sepa_debit"];
|
|
1208
1429
|
var STATUSES = ["ACTIVE", "REPLACED"];
|
|
1430
|
+
var TABLE2 = "subscriber_payment_methods";
|
|
1209
1431
|
function toSubscriberPaymentMethodRecord(row) {
|
|
1210
1432
|
return {
|
|
1211
1433
|
id: row.id,
|
|
@@ -1214,7 +1436,7 @@ function toSubscriberPaymentMethodRecord(row) {
|
|
|
1214
1436
|
provider: row.provider,
|
|
1215
1437
|
customerRef: row.customerRef,
|
|
1216
1438
|
paymentMethodRef: row.paymentMethodRef,
|
|
1217
|
-
type: oneOf(PAYMENT_METHOD_TYPES, row.type, "type", row.id),
|
|
1439
|
+
type: oneOf(PAYMENT_METHOD_TYPES, row.type, { table: TABLE2, column: "type", id: row.id }),
|
|
1218
1440
|
brand: row.brand,
|
|
1219
1441
|
last4: row.last4,
|
|
1220
1442
|
expiryMonth: row.expiryMonth,
|
|
@@ -1222,7 +1444,7 @@ function toSubscriberPaymentMethodRecord(row) {
|
|
|
1222
1444
|
country: row.country,
|
|
1223
1445
|
bankCode: row.bankCode,
|
|
1224
1446
|
mandateReference: row.mandateReference,
|
|
1225
|
-
status: oneOf(STATUSES, row.status, "status", row.id),
|
|
1447
|
+
status: oneOf(STATUSES, row.status, { table: TABLE2, column: "status", id: row.id }),
|
|
1226
1448
|
confirmedAt: row.confirmedAt,
|
|
1227
1449
|
replacedAt: row.replacedAt,
|
|
1228
1450
|
createdAt: row.createdAt
|
|
@@ -1246,15 +1468,6 @@ function subscriberPaymentMethodColumns(data) {
|
|
|
1246
1468
|
confirmedAt: data.confirmedAt
|
|
1247
1469
|
};
|
|
1248
1470
|
}
|
|
1249
|
-
function oneOf(allowed, value, column, id) {
|
|
1250
|
-
const match = allowed.find((entry) => entry === value);
|
|
1251
|
-
if (match === void 0) {
|
|
1252
|
-
throw new Error(
|
|
1253
|
-
`subscriber_payment_methods row '${id}' holds ${column} '${value}', which is none of ${allowed.join(", ")}.`
|
|
1254
|
-
);
|
|
1255
|
-
}
|
|
1256
|
-
return match;
|
|
1257
|
-
}
|
|
1258
1471
|
var FOREIGN_PAYMENT_METHOD_REFERENCE = "FOREIGN_PAYMENT_METHOD_REFERENCE";
|
|
1259
1472
|
var ForeignPaymentMethodReferenceError = class extends Error {
|
|
1260
1473
|
constructor(gatewayAccount, paymentMethodRef) {
|
|
@@ -1280,6 +1493,30 @@ function refuseForeignPaymentMethodReference(recorded, subscriberId) {
|
|
|
1280
1493
|
);
|
|
1281
1494
|
}
|
|
1282
1495
|
|
|
1496
|
+
// src/subscription-bundle-mapping.ts
|
|
1497
|
+
var BILLING_CYCLES = ["MONTHLY", "YEARLY"];
|
|
1498
|
+
function toSubscriptionBundleRecord(row) {
|
|
1499
|
+
const billingCycle = row.billingCycle ?? null;
|
|
1500
|
+
return {
|
|
1501
|
+
id: row.id,
|
|
1502
|
+
subscriptionId: row.subscriptionId,
|
|
1503
|
+
bundleVersionId: row.bundleVersionId,
|
|
1504
|
+
startedAt: row.startedAt,
|
|
1505
|
+
minimumTermEndsAt: row.minimumTermEndsAt,
|
|
1506
|
+
billingCycle: billingCycle === null ? null : oneOf(BILLING_CYCLES, billingCycle, {
|
|
1507
|
+
table: "subscription_bundles",
|
|
1508
|
+
column: "billingCycle",
|
|
1509
|
+
id: row.id
|
|
1510
|
+
}),
|
|
1511
|
+
currentPeriodStart: row.currentPeriodStart ?? null,
|
|
1512
|
+
currentPeriodEnd: row.currentPeriodEnd ?? null,
|
|
1513
|
+
canceledAt: row.canceledAt,
|
|
1514
|
+
canceledEffectiveAt: row.canceledEffectiveAt,
|
|
1515
|
+
createdAt: row.createdAt,
|
|
1516
|
+
updatedAt: row.updatedAt
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1283
1520
|
// src/subscription-contract-mapping.ts
|
|
1284
1521
|
function toSubscriptionContractRecord(row, lineItems) {
|
|
1285
1522
|
return {
|
|
@@ -1584,6 +1821,7 @@ var ERROR_MESSAGES_EN = {
|
|
|
1584
1821
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' not found",
|
|
1585
1822
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "No active subscription contract for tenant {tenantId}",
|
|
1586
1823
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' is already closed",
|
|
1824
|
+
SUBSCRIPTION_CONTRACT_CHANGED: "The contracts of tenant '{tenantId}' changed while a successor was being written, or one begins after the moment it would take effect, so it would run beside another. Nothing was written.",
|
|
1587
1825
|
// ── subscriber ──
|
|
1588
1826
|
SUBSCRIBER_REQUIRED: "Tenant '{tenantId}' has no subscriber. Nothing is agreed or charged without the party to it: create the tenant's subscriber first.",
|
|
1589
1827
|
SUBSCRIBER_ALREADY_EXISTS: "Tenant '{tenantId}' already has a subscriber.",
|
|
@@ -1615,10 +1853,20 @@ var ERROR_MESSAGES_EN = {
|
|
|
1615
1853
|
PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "No payment gateway account is configured under '{account}'.",
|
|
1616
1854
|
PAYMENT_CALLBACK_REJECTED: "The payment callback could not be verified.",
|
|
1617
1855
|
PAYMENT_RETURN_URL_NOT_ALLOWED: "The {field} leads to a site this installation does not return to.",
|
|
1856
|
+
PAYMENT_GATEWAY_FAILED: "The payment provider did not answer as expected. Please try again in a few minutes.",
|
|
1618
1857
|
// ── entitlement (code lives in upsell.types.ts) ──
|
|
1619
1858
|
[FEATURE_NOT_LICENSED]: "Feature {featureKeys} is not included in the current plan.",
|
|
1620
1859
|
// ── settings ──
|
|
1621
|
-
SETTINGS_CHANGE_NOT_FOUND: "No recorded settings change has this id."
|
|
1860
|
+
SETTINGS_CHANGE_NOT_FOUND: "No recorded settings change has this id.",
|
|
1861
|
+
// ── maintenance ──
|
|
1862
|
+
MAINTENANCE: "The application is under maintenance.",
|
|
1863
|
+
MAINTENANCE_WINDOW_ALREADY_OPEN: "A maintenance window is already open. Move or cancel it before announcing another.",
|
|
1864
|
+
MAINTENANCE_WINDOW_NOT_OPEN: "No open maintenance window has this id.",
|
|
1865
|
+
MAINTENANCE_WINDOW_LOCKED: "This maintenance window is locked. Its start cannot move, and unlocking is what ends it.",
|
|
1866
|
+
MAINTENANCE_WINDOW_END_NOT_AFTER_START: "The end of a maintenance window has to be after its start.",
|
|
1867
|
+
MAINTENANCE_WINDOW_END_IN_PAST: "The end of a maintenance window cannot be in the past.",
|
|
1868
|
+
MAINTENANCE_TIME_INVALID: "The {field} has to be a date and time with its zone, such as 2026-10-02T22:00+02:00.",
|
|
1869
|
+
MAINTENANCE_MESSAGE_TOO_LONG: "The message may be at most {max} characters long."
|
|
1622
1870
|
};
|
|
1623
1871
|
function formatErrorMessage(template, params = {}) {
|
|
1624
1872
|
return template.replace(/\{(\w+)\}/g, (match, name) => {
|
|
@@ -1794,6 +2042,7 @@ var ERROR_MESSAGES_DE = {
|
|
|
1794
2042
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' nicht gefunden",
|
|
1795
2043
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "Kein aktiver Abo-Vertrag f\xFCr Mandant {tenantId}",
|
|
1796
2044
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' ist bereits geschlossen",
|
|
2045
|
+
SUBSCRIPTION_CONTRACT_CHANGED: "Die Vertr\xE4ge von Mandant '{tenantId}' haben sich ge\xE4ndert, w\xE4hrend ein Nachfolger geschrieben wurde, oder einer beginnt nach dem Zeitpunkt, ab dem er g\xE4lte, sodass er neben einem anderen liefe. Es wurde nichts geschrieben.",
|
|
1797
2046
|
// ── subscriber ──
|
|
1798
2047
|
SUBSCRIBER_REQUIRED: "Mandant '{tenantId}' hat keinen Vertragspartner. Ohne ihn wird nichts vereinbart oder berechnet: Zuerst muss der Vertragspartner des Mandanten angelegt werden.",
|
|
1799
2048
|
SUBSCRIBER_ALREADY_EXISTS: "Mandant '{tenantId}' hat bereits einen Vertragspartner.",
|
|
@@ -1825,10 +2074,20 @@ var ERROR_MESSAGES_DE = {
|
|
|
1825
2074
|
PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "Unter '{account}' ist kein Konto eines Zahlungsanbieters eingerichtet.",
|
|
1826
2075
|
PAYMENT_CALLBACK_REJECTED: "Die R\xFCckmeldung des Zahlungsanbieters lie\xDF sich nicht pr\xFCfen.",
|
|
1827
2076
|
PAYMENT_RETURN_URL_NOT_ALLOWED: "Die {field} f\xFChrt auf eine Seite, zu der diese Installation nicht zur\xFCckleitet.",
|
|
2077
|
+
PAYMENT_GATEWAY_FAILED: "Der Zahlungsanbieter hat nicht wie erwartet geantwortet. Bitte versuche es in ein paar Minuten noch einmal.",
|
|
1828
2078
|
// ── entitlement (code lives in upsell.types.ts) ──
|
|
1829
2079
|
[FEATURE_NOT_LICENSED]: "Das Feature {featureKeys} ist im aktuellen Plan nicht enthalten.",
|
|
1830
2080
|
// ── settings ──
|
|
1831
|
-
SETTINGS_CHANGE_NOT_FOUND: "Keine aufgezeichnete Einstellungs\xE4nderung hat diese ID."
|
|
2081
|
+
SETTINGS_CHANGE_NOT_FOUND: "Keine aufgezeichnete Einstellungs\xE4nderung hat diese ID.",
|
|
2082
|
+
// ── maintenance ──
|
|
2083
|
+
MAINTENANCE: "Die Anwendung wird gerade gewartet.",
|
|
2084
|
+
MAINTENANCE_WINDOW_ALREADY_OPEN: "Es ist bereits ein Wartungsfenster offen. Verschiebe oder streiche es, bevor du ein weiteres ank\xFCndigst.",
|
|
2085
|
+
MAINTENANCE_WINDOW_NOT_OPEN: "Kein offenes Wartungsfenster hat diese ID.",
|
|
2086
|
+
MAINTENANCE_WINDOW_LOCKED: "Dieses Wartungsfenster ist gesperrt. Sein Beginn l\xE4sst sich nicht mehr verschieben, und beendet wird es durch Entsperren.",
|
|
2087
|
+
MAINTENANCE_WINDOW_END_NOT_AFTER_START: "Das Ende eines Wartungsfensters muss nach seinem Beginn liegen.",
|
|
2088
|
+
MAINTENANCE_WINDOW_END_IN_PAST: "Das Ende eines Wartungsfensters darf nicht in der Vergangenheit liegen.",
|
|
2089
|
+
MAINTENANCE_TIME_INVALID: "{field} muss Datum und Uhrzeit mit Zeitzone sein, etwa 2026-10-02T22:00+02:00.",
|
|
2090
|
+
MAINTENANCE_MESSAGE_TOO_LONG: "Die Nachricht darf h\xF6chstens {max} Zeichen lang sein."
|
|
1832
2091
|
};
|
|
1833
2092
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1834
2093
|
0 && (module.exports = {
|
|
@@ -1844,6 +2103,10 @@ var ERROR_MESSAGES_DE = {
|
|
|
1844
2103
|
FEATURE_NOT_LICENSED,
|
|
1845
2104
|
ForeignPaymentMethodReferenceError,
|
|
1846
2105
|
LEGAL_IDENTITY_FIELDS,
|
|
2106
|
+
MAINTENANCE_CAPABILITY,
|
|
2107
|
+
MAINTENANCE_ERROR_CODES,
|
|
2108
|
+
MAINTENANCE_MESSAGE_MAX_LENGTH,
|
|
2109
|
+
MAINTENANCE_STATE_MAX_AGE_SECONDS,
|
|
1847
2110
|
MARKETING_PRIORITY_MAX,
|
|
1848
2111
|
MARKETING_PRIORITY_MIN,
|
|
1849
2112
|
OTP_RATE_LIMIT_MAX_SENDS,
|
|
@@ -1866,6 +2129,7 @@ var ERROR_MESSAGES_DE = {
|
|
|
1866
2129
|
REGISTRATION_STEP_BY_STATUS,
|
|
1867
2130
|
SETTINGS_ERROR_CODES,
|
|
1868
2131
|
SETUP_ERROR_CODES,
|
|
2132
|
+
SUBSCRIBER_ACCOUNT_CAPABILITY,
|
|
1869
2133
|
SUBSCRIBER_ERROR_CODES,
|
|
1870
2134
|
applyPromo,
|
|
1871
2135
|
assertPersistenceCapabilities,
|
|
@@ -1888,13 +2152,20 @@ var ERROR_MESSAGES_DE = {
|
|
|
1888
2152
|
identityCorrectionDelta,
|
|
1889
2153
|
isBundleRedundant,
|
|
1890
2154
|
isForeignPaymentMethodReferenceError,
|
|
2155
|
+
isMaintenanceAnnouncementLapsed,
|
|
2156
|
+
isMaintenanceOverrun,
|
|
1891
2157
|
isPaymentCallbackRejectedError,
|
|
1892
2158
|
isPlatformUserExistsError,
|
|
1893
2159
|
isVersionEditable,
|
|
1894
2160
|
issuerIdentityOf,
|
|
1895
2161
|
keepOneRecommended,
|
|
2162
|
+
maintenanceRetryAfterSeconds,
|
|
2163
|
+
maintenanceStatusOf,
|
|
2164
|
+
maintenanceWindowStatusOf,
|
|
2165
|
+
maintenanceWindowViewOf,
|
|
1896
2166
|
missingRequiresFor,
|
|
1897
2167
|
movedIdentityFields,
|
|
2168
|
+
parseZonedInstant,
|
|
1898
2169
|
pickActivePromo,
|
|
1899
2170
|
planCatalogSettingsOf,
|
|
1900
2171
|
previousUtcDay,
|
|
@@ -1910,15 +2181,19 @@ var ERROR_MESSAGES_DE = {
|
|
|
1910
2181
|
selectChargeableBundles,
|
|
1911
2182
|
settingsSubtreeOf,
|
|
1912
2183
|
startOfUtcDay,
|
|
2184
|
+
subscriberChargeColumns,
|
|
1913
2185
|
subscriberFromRegistration,
|
|
1914
2186
|
subscriberPaymentMethodColumns,
|
|
1915
2187
|
toBundleStemRow,
|
|
1916
2188
|
toContractLineItemRecord,
|
|
2189
|
+
toMaintenanceWindowRecord,
|
|
1917
2190
|
toPlanRow,
|
|
1918
2191
|
toPlanVersionRow,
|
|
1919
2192
|
toRunningContractIssuer,
|
|
2193
|
+
toSubscriberChargeRecord,
|
|
1920
2194
|
toSubscriberCorrectionRecord,
|
|
1921
2195
|
toSubscriberPaymentMethodRecord,
|
|
1922
2196
|
toSubscriberRecord,
|
|
2197
|
+
toSubscriptionBundleRecord,
|
|
1923
2198
|
toSubscriptionContractRecord
|
|
1924
2199
|
});
|