@saasicat/nest 0.18.0 → 0.19.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.
Files changed (55) hide show
  1. package/dist/_entries.cjs +1309 -519
  2. package/dist/admin/index.js +1 -1
  3. package/dist/billing/index.d.cts +7 -4
  4. package/dist/billing/index.d.ts +7 -4
  5. package/dist/billing/index.js +6 -6
  6. package/dist/catalog/index.js +4 -4
  7. package/dist/checkout-offer/index.js +2 -2
  8. package/dist/{chunk-Z3FWN3HJ.js → chunk-5ZXBXYXU.js} +3 -3
  9. package/dist/{chunk-RZVSKKXX.js → chunk-6WA4X5U3.js} +46 -45
  10. package/dist/{chunk-V34AA7C7.js → chunk-6WL6VQ7Z.js} +1 -1
  11. package/dist/{chunk-ABB2CRAS.js → chunk-74SCJ4HF.js} +1 -1
  12. package/dist/{chunk-PLJEAUFU.js → chunk-7JIHG53V.js} +76 -39
  13. package/dist/{chunk-7RRWI5LH.js → chunk-AFK2IE2L.js} +10 -10
  14. package/dist/{chunk-32EMXPU2.js → chunk-B7NRY2LV.js} +48 -17
  15. package/dist/{chunk-MDIZUVIK.js → chunk-BSK6YBLI.js} +1 -1
  16. package/dist/{chunk-R2QOSVAA.js → chunk-DQKCK7DX.js} +1 -1
  17. package/dist/{chunk-GLLCB4BP.js → chunk-EUU3B6NB.js} +17 -13
  18. package/dist/{chunk-EXOLOJFZ.js → chunk-F6DCLVBB.js} +29 -8
  19. package/dist/{chunk-5KH2O4SF.js → chunk-I77VS3YH.js} +287 -105
  20. package/dist/{chunk-YITTE646.js → chunk-KUDKD7ZG.js} +34 -14
  21. package/dist/{chunk-P3DP6GJE.js → chunk-LXUBCLRK.js} +486 -160
  22. package/dist/{chunk-GJBXOCRZ.js → chunk-ORWIGSNN.js} +45 -17
  23. package/dist/{chunk-E7AJ42AB.js → chunk-QLJHIIOY.js} +168 -28
  24. package/dist/{chunk-BOADBIGB.js → chunk-YYUXKLXK.js} +2 -2
  25. package/dist/{define-saasicat-Rc0rXrYG.d.ts → define-saasicat-CqkhnHn-.d.ts} +1 -1
  26. package/dist/{define-saasicat-CeDBX9ji.d.cts → define-saasicat-D8c6Bs4T.d.cts} +1 -1
  27. package/dist/discovery/index.d.cts +2 -2
  28. package/dist/discovery/index.d.ts +2 -2
  29. package/dist/discovery/index.js +4 -4
  30. package/dist/{enforce-quota.interceptor-DMw-bPyk.d.cts → enforce-quota.interceptor-Dk0eEtzV.d.cts} +1 -1
  31. package/dist/{enforce-quota.interceptor-CmbWX39L.d.ts → enforce-quota.interceptor-Dp8wTYro.d.ts} +1 -1
  32. package/dist/entitlement/index.js +2 -2
  33. package/dist/index.d.cts +6 -6
  34. package/dist/index.d.ts +6 -6
  35. package/dist/index.js +17 -17
  36. package/dist/{module-DgYJur6f.d.ts → module-BwD-wAor.d.ts} +1 -1
  37. package/dist/{module-CSN8j8Tp.d.cts → module-DsDkbawm.d.cts} +1 -1
  38. package/dist/platform/index.d.cts +8 -8
  39. package/dist/platform/index.d.ts +8 -8
  40. package/dist/platform/index.js +13 -13
  41. package/dist/promo/index.d.cts +3 -3
  42. package/dist/promo/index.d.ts +3 -3
  43. package/dist/promo/index.js +3 -3
  44. package/dist/registration/index.js +1 -1
  45. package/dist/{saas-platform.module-DLhoqKNA.d.ts → saas-platform.module-BQmrDGVU.d.ts} +1 -1
  46. package/dist/{saas-platform.module-D3rUTiho.d.cts → saas-platform.module-DducnQ9s.d.cts} +1 -1
  47. package/dist/{service-DX8KbGXl.d.cts → service-DPZ2W1E-.d.cts} +2 -2
  48. package/dist/{service-DX8KbGXl.d.ts → service-DPZ2W1E-.d.ts} +2 -2
  49. package/dist/subscription-contract/index.js +2 -2
  50. package/dist/{tenant-billing.controller-BwZRnJ3q.d.ts → tenant-billing.controller-b1G1yB09.d.ts} +2 -2
  51. package/dist/{tenant-billing.controller-CG4CaFUP.d.cts → tenant-billing.controller-m42YQ_Ei.d.cts} +2 -2
  52. package/dist/testing/index.d.cts +5 -5
  53. package/dist/testing/index.d.ts +5 -5
  54. package/dist/testing/index.js +33 -33
  55. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  appendImplicitDiscountLineItem
3
- } from "./chunk-MDIZUVIK.js";
3
+ } from "./chunk-BSK6YBLI.js";
4
4
  import {
5
5
  SaaSiCatPublicRoute
6
6
  } from "./chunk-YSC46BGM.js";
@@ -21,7 +21,7 @@ var CHECKOUT_OFFER_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/
21
21
 
22
22
  // src/checkout-offer/checkout-offer.service.ts
23
23
  import { ConflictException, Inject, Injectable, NotFoundException, Optional, UnprocessableEntityException } from "@nestjs/common";
24
- import { buildFeatureRequiresIndex, collectUnsatisfiedRequires, startOfUtcDay } from "@saasicat/types";
24
+ import { CONTRACT_ERROR_CODES, buildFeatureRequiresIndex, collectUnsatisfiedRequires, startOfUtcDay } from "@saasicat/types";
25
25
  function _ts_decorate(decorators, target, key, desc) {
26
26
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
27
27
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -59,7 +59,13 @@ var CheckoutOfferService = class {
59
59
  async getById(id) {
60
60
  const row = await this.repo.findById(id);
61
61
  if (!row) {
62
- throw new NotFoundException(`CheckoutOffer '${id}' nicht gefunden`);
62
+ throw new NotFoundException({
63
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_NOT_FOUND,
64
+ message: `CheckoutOffer '${id}' not found`,
65
+ params: {
66
+ offerId: id
67
+ }
68
+ });
63
69
  }
64
70
  return row;
65
71
  }
@@ -77,7 +83,7 @@ var CheckoutOfferService = class {
77
83
  /** Customization in onboarding — only while the offer is `open`. */
78
84
  async update(id, data) {
79
85
  const existing = await this.getById(id);
80
- this.assertOpen(existing, "\xE4ndern");
86
+ this.assertOpen(existing, "changed");
81
87
  const next = this.normalizeUpdateData(existing, data);
82
88
  await this.assertFeatureRequiresSatisfied({
83
89
  projectKey: existing.projectKey,
@@ -95,7 +101,7 @@ var CheckoutOfferService = class {
95
101
  */
96
102
  async consume(id) {
97
103
  const existing = await this.getById(id);
98
- this.assertOpen(existing, "verbrauchen");
104
+ this.assertOpen(existing, "consumed");
99
105
  await this.assertBundleVersionsStillBookable(existing);
100
106
  return this.repo.consume(id);
101
107
  }
@@ -124,8 +130,8 @@ var CheckoutOfferService = class {
124
130
  ], requiresIndex);
125
131
  if (missingRequires.length > 0) {
126
132
  throw new UnprocessableEntityException({
127
- code: "CHECKOUT_OFFER_FEATURE_DEPENDENCY_UNSATISFIED",
128
- message: `Die Paket-Auswahl deckt nicht alle Feature-Abh\xE4ngigkeiten: [${missingRequires.join(", ")}] fehlen in Plan + gew\xE4hlten Bundles.`,
133
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_FEATURE_DEPENDENCY_UNSATISFIED,
134
+ message: `The selected plan does not cover all feature dependencies: [${missingRequires.join(", ")}] are missing from the plan + selected bundles.`,
129
135
  missingRequires
130
136
  });
131
137
  }
@@ -205,8 +211,8 @@ var CheckoutOfferService = class {
205
211
  }
206
212
  if (violations.length > 0) {
207
213
  throw new UnprocessableEntityException({
208
- code: "CHECKOUT_OFFER_BUNDLE_VERSION_NOT_BOOKABLE",
209
- message: "Mindestens eine BundleVersion aus dem CheckoutOffer ist nicht mehr buchbar.",
214
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_BUNDLE_VERSION_NOT_BOOKABLE,
215
+ message: "At least one bundle version from the checkout offer is no longer bookable.",
210
216
  violations
211
217
  });
212
218
  }
@@ -260,15 +266,15 @@ var CheckoutOfferService = class {
260
266
  const hasPlan = lineItems.some((item) => item.kind === "plan");
261
267
  if (!hasPlan) {
262
268
  throw new UnprocessableEntityException({
263
- code: "CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED",
264
- message: "CheckoutOffer ben\xF6tigt eine eingefrorene Plan-LineItem."
269
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_PLAN_LINE_ITEM_REQUIRED,
270
+ message: "A checkout offer requires a frozen plan line item."
265
271
  });
266
272
  }
267
273
  const missingBundleVersionIds = input.bundleVersionIds.filter((versionId) => !lineItems.some((item) => item.kind === "bundle" && item.sourceVersionId === versionId));
268
274
  if (missingBundleVersionIds.length > 0) {
269
275
  throw new UnprocessableEntityException({
270
- code: "CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED",
271
- message: "Jede ausgew\xE4hlte BundleVersion ben\xF6tigt eine eingefrorene Bundle-LineItem.",
276
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_BUNDLE_LINE_ITEMS_REQUIRED,
277
+ message: "Every selected bundle version requires a frozen bundle line item.",
272
278
  bundleVersionIds: missingBundleVersionIds
273
279
  });
274
280
  }
@@ -300,13 +306,35 @@ var CheckoutOfferService = class {
300
306
  }
301
307
  assertOpen(existing, action) {
302
308
  if (existing.status === "consumed") {
303
- throw new ConflictException(`CheckoutOffer '${existing.id}' ist bereits verbraucht und kann nicht ${action} werden`);
309
+ throw new ConflictException({
310
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_ALREADY_CONSUMED,
311
+ message: `Checkout offer '${existing.id}' has already been consumed and cannot be ${action}`,
312
+ params: {
313
+ offerId: existing.id,
314
+ action
315
+ }
316
+ });
304
317
  }
305
318
  if (existing.status === "expired") {
306
- throw new ConflictException(`CheckoutOffer '${existing.id}' ist abgelaufen und kann nicht ${action} werden`);
319
+ throw new ConflictException({
320
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_EXPIRED,
321
+ message: `Checkout offer '${existing.id}' has expired and cannot be ${action}`,
322
+ params: {
323
+ offerId: existing.id,
324
+ action
325
+ }
326
+ });
307
327
  }
308
328
  if (this.isExpired(existing)) {
309
- throw new ConflictException(`CheckoutOffer '${existing.id}' ist abgelaufen und kann nicht ${action} werden`);
329
+ throw new ConflictException({
330
+ code: CONTRACT_ERROR_CODES.CHECKOUT_OFFER_EXPIRED,
331
+ message: `CheckoutOffer '${existing.id}' has expired and cannot be ${action}`,
332
+ params: {
333
+ offerId: existing.id,
334
+ action,
335
+ validUntil: existing.validUntil ?? null
336
+ }
337
+ });
310
338
  }
311
339
  }
312
340
  isExpired(row) {
@@ -385,7 +413,7 @@ var CreateCheckoutOfferDto = class {
385
413
  _ts_decorate2([
386
414
  IsString(),
387
415
  Matches(PROJECT_KEY_PATTERN, {
388
- message: "projectKey muss kebab-case sein"
416
+ message: "projectKey must be kebab-case"
389
417
  }),
390
418
  MaxLength(64),
391
419
  _ts_metadata2("design:type", String)
@@ -3,7 +3,7 @@ import {
3
3
  computeIncludedVat,
4
4
  getPlanPriceGross,
5
5
  round2
6
- } from "./chunk-R2QOSVAA.js";
6
+ } from "./chunk-DQKCK7DX.js";
7
7
  import {
8
8
  __name
9
9
  } from "./chunk-SHUYVCID.js";
@@ -50,15 +50,15 @@ function buildLabel(code, cycle) {
50
50
  maximumFractionDigits: 2
51
51
  })} \u20AC`;
52
52
  if (code.durationType === "ONCE") {
53
- return `${valueStr} einmalig`;
53
+ return `${valueStr} once`;
54
54
  }
55
55
  if (code.durationType === "MONTHS") {
56
56
  const m = code.durationValue ?? 0;
57
- return m === 1 ? `${valueStr} im ersten Monat` : `${valueStr} f\xFCr ${m} Monate`;
57
+ return m === 1 ? `${valueStr} for the first month` : `${valueStr} for ${m} months`;
58
58
  }
59
59
  const n = code.durationValue ?? 0;
60
- if (n === 1) return cycle === "YEARLY" ? `${valueStr} im ersten Jahr` : `${valueStr} im ersten Monat`;
61
- return cycle === "YEARLY" ? `${valueStr} in den ersten ${n} Jahren` : `${valueStr} in den ersten ${n} Monaten`;
60
+ if (n === 1) return cycle === "YEARLY" ? `${valueStr} for the first year` : `${valueStr} for the first month`;
61
+ return cycle === "YEARLY" ? `${valueStr} for the first ${n} years` : `${valueStr} for the first ${n} months`;
62
62
  }
63
63
  __name(buildLabel, "buildLabel");
64
64
 
@@ -74,6 +74,7 @@ var PROMO_SERVICE_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/Promo
74
74
 
75
75
  // src/promo/service.ts
76
76
  import { BadRequestException, Inject, Injectable, NotFoundException } from "@nestjs/common";
77
+ import { BILLING_ERROR_CODES, PROMO_ERROR_CODES } from "@saasicat/types";
77
78
  function _ts_decorate(decorators, target, key, desc) {
78
79
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
79
80
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -91,7 +92,23 @@ function _ts_param(paramIndex, decorator) {
91
92
  };
92
93
  }
93
94
  __name(_ts_param, "_ts_param");
94
- var CODE_PATTERN = /^[A-Z0-9_-]{4,32}$/;
95
+ var CODE_MIN_LENGTH = 4;
96
+ var CODE_MAX_LENGTH = 32;
97
+ var CODE_PATTERN = new RegExp(`^[A-Z0-9_-]{${CODE_MIN_LENGTH},${CODE_MAX_LENGTH}}$`);
98
+ var PERCENT_MIN_EXCLUSIVE = 0;
99
+ var PERCENT_MAX = 100;
100
+ var DURATION_MIN = 1;
101
+ var DURATION_MAX = 24;
102
+ function notRedeemable(reason) {
103
+ return new BadRequestException({
104
+ code: PROMO_ERROR_CODES.PROMO_CODE_NOT_REDEEMABLE,
105
+ message: `Code cannot be redeemed: ${reason}`,
106
+ params: {
107
+ reason
108
+ }
109
+ });
110
+ }
111
+ __name(notRedeemable, "notRedeemable");
95
112
  var PromoCodesService = class {
96
113
  static {
97
114
  __name(this, "PromoCodesService");
@@ -120,46 +137,118 @@ var PromoCodesService = class {
120
137
  async create(input) {
121
138
  const code = input.code.trim().toUpperCase();
122
139
  if (!CODE_PATTERN.test(code)) {
123
- throw new BadRequestException('Code darf nur Gro\xDFbuchstaben, Ziffern, \u201E-" und \u201E_" enthalten (4\u201332 Zeichen).');
140
+ throw new BadRequestException({
141
+ code: PROMO_ERROR_CODES.PROMO_CODE_FORMAT_INVALID,
142
+ message: 'The code may only contain upper-case letters, digits, "-" and "_" (4\u201332 characters).',
143
+ params: {
144
+ promoCode: code,
145
+ minLength: CODE_MIN_LENGTH,
146
+ maxLength: CODE_MAX_LENGTH
147
+ }
148
+ });
124
149
  }
125
150
  if (input.valueType === "PERCENT") {
126
- if (!(input.value > 0 && input.value <= 100)) {
127
- throw new BadRequestException("Prozentsatz muss zwischen 0 und 100 liegen.");
151
+ if (!(input.value > PERCENT_MIN_EXCLUSIVE && input.value <= PERCENT_MAX)) {
152
+ throw new BadRequestException({
153
+ code: PROMO_ERROR_CODES.PROMO_PERCENT_OUT_OF_RANGE,
154
+ message: "The percentage must be between 0 and 100.",
155
+ params: {
156
+ value: input.value,
157
+ min: PERCENT_MIN_EXCLUSIVE,
158
+ max: PERCENT_MAX
159
+ }
160
+ });
128
161
  }
129
162
  } else if (!(input.value > 0)) {
130
- throw new BadRequestException("Betrag muss positiv sein.");
163
+ throw new BadRequestException({
164
+ code: PROMO_ERROR_CODES.PROMO_AMOUNT_NOT_POSITIVE,
165
+ message: "The amount must be positive.",
166
+ params: {
167
+ value: input.value,
168
+ min: 0
169
+ }
170
+ });
131
171
  }
132
172
  if (input.durationType === "ONCE") {
133
173
  if (input.durationValue != null) {
134
- throw new BadRequestException("Bei einmaligem Rabatt darf keine Laufzeit gesetzt sein.");
174
+ throw new BadRequestException({
175
+ code: PROMO_ERROR_CODES.PROMO_ONE_OFF_WITH_DURATION,
176
+ message: "A one-off discount must not set a duration.",
177
+ params: {
178
+ durationValue: input.durationValue
179
+ }
180
+ });
135
181
  }
136
182
  } else {
137
183
  const v = input.durationValue;
138
- if (v == null || v < 1 || v > 24) {
139
- throw new BadRequestException("Laufzeit ung\xFCltig (max. 24 Monate bzw. Abrechnungsperioden).");
184
+ if (v == null || v < DURATION_MIN || v > DURATION_MAX) {
185
+ throw new BadRequestException({
186
+ code: PROMO_ERROR_CODES.PROMO_DURATION_INVALID,
187
+ message: "Invalid duration (at most 24 months or billing periods).",
188
+ params: {
189
+ durationValue: v ?? null,
190
+ min: DURATION_MIN,
191
+ max: DURATION_MAX
192
+ }
193
+ });
140
194
  }
141
195
  }
142
196
  if (input.validFrom && input.validUntil && input.validFrom >= input.validUntil) {
143
- throw new BadRequestException("G\xFCltigkeits-Fenster ung\xFCltig.");
197
+ throw new BadRequestException({
198
+ code: PROMO_ERROR_CODES.PROMO_VALIDITY_WINDOW_INVALID,
199
+ message: "Invalid validity window.",
200
+ params: {
201
+ validFrom: input.validFrom.toISOString(),
202
+ validUntil: input.validUntil.toISOString()
203
+ }
204
+ });
144
205
  }
145
206
  const plans = input.appliesToPlans ?? [];
146
207
  const blocked = this.config.nonRedeemablePlans ?? [];
147
208
  for (const p of plans) {
148
209
  if (blocked.includes(p)) {
149
- throw new BadRequestException(`${p}-Plan kann nicht rabattiert werden.`);
210
+ throw new BadRequestException({
211
+ code: PROMO_ERROR_CODES.PROMO_PLAN_NOT_DISCOUNTABLE,
212
+ message: `${p}-Plan cannot be discounted.`,
213
+ params: {
214
+ plan: p
215
+ }
216
+ });
150
217
  }
151
218
  }
152
219
  if (input.minimumPlanAmountGross != null && input.minimumPlanAmountGross <= 0) {
153
- throw new BadRequestException("Mindest-Plan-Brutto muss positiv sein.");
220
+ throw new BadRequestException({
221
+ code: PROMO_ERROR_CODES.PROMO_MIN_AMOUNT_NOT_POSITIVE,
222
+ message: "The minimum plan gross amount must be positive.",
223
+ params: {
224
+ value: input.minimumPlanAmountGross,
225
+ min: 0
226
+ }
227
+ });
154
228
  }
155
229
  if (input.valueType === "ABSOLUTE" && !input.allowZeroInvoice) {
156
230
  const lowestApplicableGross = this.lowestApplicablePlanGross(plans);
157
231
  if (lowestApplicableGross != null && input.value >= lowestApplicableGross) {
158
- throw new BadRequestException("Bei Absolutbetr\xE4gen muss der Rabatt unter dem niedrigsten anwendbaren Plan-Preis liegen oder allowZeroInvoice aktiviert sein.");
232
+ throw new BadRequestException({
233
+ code: PROMO_ERROR_CODES.PROMO_WOULD_PRODUCE_ZERO_INVOICE,
234
+ message: "For absolute amounts the discount must stay below the lowest applicable plan price, or allowZeroInvoice must be enabled.",
235
+ params: {
236
+ value: input.value,
237
+ lowestApplicablePlanGross: lowestApplicableGross
238
+ }
239
+ });
159
240
  }
160
241
  }
161
242
  const exists = await this.promoRepo.findByCode(code);
162
- if (exists) throw new BadRequestException("Code existiert bereits.");
243
+ if (exists) {
244
+ throw new BadRequestException({
245
+ code: PROMO_ERROR_CODES.PROMO_CODE_ALREADY_EXISTS,
246
+ message: "The code already exists.",
247
+ params: {
248
+ promoCode: code
249
+ }
250
+ });
251
+ }
163
252
  return this.promoRepo.create({
164
253
  ...input,
165
254
  code
@@ -167,10 +256,25 @@ var PromoCodesService = class {
167
256
  }
168
257
  async update(id, input) {
169
258
  const existing = await this.promoRepo.findById(id);
170
- if (!existing) throw new NotFoundException("Code nicht gefunden");
259
+ if (!existing) {
260
+ throw new NotFoundException({
261
+ code: PROMO_ERROR_CODES.PROMO_CODE_NOT_FOUND,
262
+ message: "Code not found",
263
+ params: {
264
+ promoCodeId: id
265
+ }
266
+ });
267
+ }
171
268
  if (input.maxRedemptions != null && existing.maxRedemptions != null) {
172
269
  if (input.maxRedemptions < existing.maxRedemptions) {
173
- throw new BadRequestException("maxRedemptions kann nicht gesenkt werden.");
270
+ throw new BadRequestException({
271
+ code: PROMO_ERROR_CODES.PROMO_MAX_REDEMPTIONS_LOWERED,
272
+ message: "maxRedemptions cannot be lowered.",
273
+ params: {
274
+ current: existing.maxRedemptions,
275
+ requested: input.maxRedemptions
276
+ }
277
+ });
174
278
  }
175
279
  }
176
280
  return this.promoRepo.update(id, input);
@@ -178,7 +282,14 @@ var PromoCodesService = class {
178
282
  async softDelete(id) {
179
283
  const redemptions = await this.redemptionRepo.countByPromoCode(id);
180
284
  if (redemptions > 0) {
181
- throw new BadRequestException("Code hat bereits Einl\xF6sungen \u2014 Soft-Delete nicht m\xF6glich. Stattdessen pausieren.");
285
+ throw new BadRequestException({
286
+ code: PROMO_ERROR_CODES.PROMO_CODE_HAS_REDEMPTIONS,
287
+ message: "The code already has redemptions \u2014 it cannot be soft-deleted. Pause it instead.",
288
+ params: {
289
+ promoCodeId: id,
290
+ redemptions
291
+ }
292
+ });
182
293
  }
183
294
  await this.promoRepo.softDelete(id);
184
295
  }
@@ -189,7 +300,15 @@ var PromoCodesService = class {
189
300
  async findOne(id) {
190
301
  await this.lazyExpire();
191
302
  const code = await this.promoRepo.findById(id);
192
- if (!code || code.deletedAt) throw new NotFoundException("Code nicht gefunden");
303
+ if (!code || code.deletedAt) {
304
+ throw new NotFoundException({
305
+ code: PROMO_ERROR_CODES.PROMO_CODE_NOT_FOUND,
306
+ message: "Code not found",
307
+ params: {
308
+ promoCodeId: id
309
+ }
310
+ });
311
+ }
193
312
  return code;
194
313
  }
195
314
  async stats(id) {
@@ -317,28 +436,49 @@ var PromoCodesService = class {
317
436
  const code = input.code.trim().toUpperCase();
318
437
  const promo = await this.promoRepo.findByCode(code, tx);
319
438
  if (!promo || promo.deletedAt) {
320
- throw new BadRequestException("Code nicht gefunden");
439
+ throw new BadRequestException({
440
+ code: PROMO_ERROR_CODES.PROMO_CODE_NOT_FOUND,
441
+ message: "Code not found",
442
+ params: {
443
+ promoCode: code
444
+ }
445
+ });
321
446
  }
322
447
  const sub = await this.subscriptionLookup.findById(input.subscriptionId, tx);
323
- if (!sub) throw new NotFoundException("Subscription nicht gefunden");
448
+ if (!sub) {
449
+ throw new NotFoundException({
450
+ code: BILLING_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
451
+ message: "Subscription not found",
452
+ params: {
453
+ subscriptionId: input.subscriptionId
454
+ }
455
+ });
456
+ }
324
457
  if (sub.tenantId !== input.tenantId) {
325
- throw new BadRequestException("Subscription geh\xF6rt nicht zum Tenant");
458
+ throw new BadRequestException({
459
+ code: BILLING_ERROR_CODES.SUBSCRIPTION_TENANT_MISMATCH,
460
+ message: "Subscription does not belong to the tenant",
461
+ params: {
462
+ subscriptionId: sub.id,
463
+ tenantId: input.tenantId
464
+ }
465
+ });
326
466
  }
327
467
  const reason = this.checkEligibility(promo, {
328
468
  code,
329
469
  planId: sub.plan,
330
470
  billingCycle: sub.billingCycle
331
471
  });
332
- if (reason) throw new BadRequestException(`Code nicht einl\xF6sbar: ${reason}`);
472
+ if (reason) throw notRedeemable(reason);
333
473
  const firstTimeReason = await this.checkFirstTimeCustomer(promo, input.email, {
334
474
  requireEmail: true
335
475
  });
336
476
  if (firstTimeReason) {
337
- throw new BadRequestException(`Code nicht einl\xF6sbar: ${firstTimeReason}`);
477
+ throw notRedeemable(firstTimeReason);
338
478
  }
339
479
  const claimed = await this.promoRepo.claimSlot(promo.id, tx);
340
480
  if (!claimed) {
341
- throw new BadRequestException("Code nicht einl\xF6sbar: EXHAUSTED");
481
+ throw notRedeemable("EXHAUSTED");
342
482
  }
343
483
  await this.promoRepo.markExhaustedIfFull(promo.id, tx);
344
484
  const startsAt = sub.startedAt ?? /* @__PURE__ */ new Date();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DiscoveryScanner
3
- } from "./chunk-Z3FWN3HJ.js";
3
+ } from "./chunk-5ZXBXYXU.js";
4
4
  import {
5
5
  DEFINES_QUOTA_KEY,
6
6
  DISCOVERY_SNAPSHOT_TOKEN,
@@ -44,7 +44,7 @@ async function runHeadlessDiscoveryScan(appModule, options = {}) {
44
44
  await app.close();
45
45
  }
46
46
  } catch (err) {
47
- console.error("[discovery-scan] FEHLER:", err instanceof Error ? err.message : err);
47
+ console.error("[discovery-scan] ERROR:", err instanceof Error ? err.message : err);
48
48
  return exit(4);
49
49
  }
50
50
  }
@@ -3,7 +3,7 @@ import { ExecutionContext } from '@nestjs/common';
3
3
  import { Reflector } from '@nestjs/core';
4
4
  import { SuperAdminProvisioningPort, SetupStatusResponse, SetupRequest, SetupResult, SetupConfirmMfaRequest, SetupConfirmMfaResponse } from '@saasicat/types';
5
5
  import { h as MfaService } from './admin-stats.service-Db2exT_d.js';
6
- import { f as SaasPlatformModuleOptions } from './saas-platform.module-DLhoqKNA.js';
6
+ import { f as SaasPlatformModuleOptions } from './saas-platform.module-BQmrDGVU.js';
7
7
 
8
8
  /**
9
9
  * Shared metadata key for endpoints that intentionally run without application
@@ -3,7 +3,7 @@ import { ExecutionContext } from '@nestjs/common';
3
3
  import { Reflector } from '@nestjs/core';
4
4
  import { SuperAdminProvisioningPort, SetupStatusResponse, SetupRequest, SetupResult, SetupConfirmMfaRequest, SetupConfirmMfaResponse } from '@saasicat/types';
5
5
  import { h as MfaService } from './admin-stats.service-HUZIU448.cjs';
6
- import { f as SaasPlatformModuleOptions } from './saas-platform.module-D3rUTiho.cjs';
6
+ import { f as SaasPlatformModuleOptions } from './saas-platform.module-DducnQ9s.cjs';
7
7
 
8
8
  /**
9
9
  * Shared metadata key for endpoints that intentionally run without application
@@ -117,7 +117,7 @@ interface ImplementsCapabilityMetadata extends ImplementsCapabilityOptions {
117
117
  * ```ts
118
118
  * @Post()
119
119
  * @ImplementsCapability('invoice.create', {
120
- * label: 'Rechnung erstellen',
120
+ * label: 'Create invoice',
121
121
  * feature: 'INVOICE_MANAGEMENT',
122
122
  * kind: 'endpoint',
123
123
  * owner: 'accounting',
@@ -157,7 +157,7 @@ declare const RequiresCapability: (...capabilityKeys: string[]) => _nestjs_commo
157
157
  * @Injectable()
158
158
  * @DefinesQuota({
159
159
  * key: 'invoicesPerMonth',
160
- * label: 'Rechnungen pro Monat',
160
+ * label: 'Invoices per month',
161
161
  * unit: 'invoices',
162
162
  * policy: 'monthlyReset',
163
163
  * feature: 'INVOICE_MANAGEMENT',
@@ -117,7 +117,7 @@ interface ImplementsCapabilityMetadata extends ImplementsCapabilityOptions {
117
117
  * ```ts
118
118
  * @Post()
119
119
  * @ImplementsCapability('invoice.create', {
120
- * label: 'Rechnung erstellen',
120
+ * label: 'Create invoice',
121
121
  * feature: 'INVOICE_MANAGEMENT',
122
122
  * kind: 'endpoint',
123
123
  * owner: 'accounting',
@@ -157,7 +157,7 @@ declare const RequiresCapability: (...capabilityKeys: string[]) => _nestjs_commo
157
157
  * @Injectable()
158
158
  * @DefinesQuota({
159
159
  * key: 'invoicesPerMonth',
160
- * label: 'Rechnungen pro Monat',
160
+ * label: 'Invoices per month',
161
161
  * unit: 'invoices',
162
162
  * policy: 'monthlyReset',
163
163
  * feature: 'INVOICE_MANAGEMENT',
@@ -4,21 +4,21 @@ import {
4
4
  ImplementsCapability,
5
5
  RequiresCapability,
6
6
  runHeadlessDiscoveryScan
7
- } from "../chunk-BOADBIGB.js";
7
+ } from "../chunk-YYUXKLXK.js";
8
8
  import {
9
9
  DiscoverySnapshotNotFoundError,
10
10
  loadDiscoverySnapshotFromFile
11
- } from "../chunk-ABB2CRAS.js";
11
+ } from "../chunk-74SCJ4HF.js";
12
12
  import {
13
13
  DiscoveryModule,
14
14
  buildDiscoveryController
15
- } from "../chunk-V34AA7C7.js";
15
+ } from "../chunk-6WL6VQ7Z.js";
16
16
  import {
17
17
  DISCOVERY_APP_INFO_TOKEN,
18
18
  DISCOVERY_SNAPSHOT_PATH_TOKEN,
19
19
  DiscoveryScanner,
20
20
  computeSnapshotHash
21
- } from "../chunk-Z3FWN3HJ.js";
21
+ } from "../chunk-5ZXBXYXU.js";
22
22
  import {
23
23
  DEFINES_QUOTA_KEY,
24
24
  DISCOVERY_SNAPSHOT_TOKEN,
@@ -2,7 +2,7 @@ import { CanActivate, ExecutionContext, NestInterceptor, CallHandler } from '@ne
2
2
  import { Reflector } from '@nestjs/core';
3
3
  import { Observable } from 'rxjs';
4
4
  import { PlanCatalog, QuotaProvider } from '@saasicat/types';
5
- import { p as PlanResolverPort } from './saas-platform.module-D3rUTiho.cjs';
5
+ import { p as PlanResolverPort } from './saas-platform.module-DducnQ9s.cjs';
6
6
 
7
7
  interface StaticEntitlementSnapshot {
8
8
  planId: string | null;
@@ -2,7 +2,7 @@ import { CanActivate, ExecutionContext, NestInterceptor, CallHandler } from '@ne
2
2
  import { Reflector } from '@nestjs/core';
3
3
  import { Observable } from 'rxjs';
4
4
  import { PlanCatalog, QuotaProvider } from '@saasicat/types';
5
- import { p as PlanResolverPort } from './saas-platform.module-DLhoqKNA.js';
5
+ import { p as PlanResolverPort } from './saas-platform.module-BQmrDGVU.js';
6
6
 
7
7
  interface StaticEntitlementSnapshot {
8
8
  planId: string | null;
@@ -19,8 +19,8 @@ import {
19
19
  mergeSubscriptionBundlesIntoLimits,
20
20
  resolveEntitlementPlan,
21
21
  toEffectiveLimitsSnapshot
22
- } from "../chunk-EXOLOJFZ.js";
23
- import "../chunk-R2QOSVAA.js";
22
+ } from "../chunk-F6DCLVBB.js";
23
+ import "../chunk-DQKCK7DX.js";
24
24
  import "../chunk-NYLON2VC.js";
25
25
  import {
26
26
  ENTITLEMENT_RESOLUTION_CONFIG_TOKEN,
package/dist/index.d.cts CHANGED
@@ -1,15 +1,15 @@
1
1
  export { P as ProviderSpec, a as asProvider } from './di-CcNeq9v-.cjs';
2
- import { S as SetupService } from './define-saasicat-CeDBX9ji.cjs';
3
- export { a as SAASICAT_PUBLIC_ROUTE_KEY, b as SETUP_CONFIG_TOKEN, c as SETUP_PROVISIONING_PORT_TOKEN, d as SaaSiCatPublicRoute, e as SetupConfig, f as defineSaaSiCat, i as isSaaSiCatPublicRoute } from './define-saasicat-CeDBX9ji.cjs';
2
+ import { S as SetupService } from './define-saasicat-D8c6Bs4T.cjs';
3
+ export { a as SAASICAT_PUBLIC_ROUTE_KEY, b as SETUP_CONFIG_TOKEN, c as SETUP_PROVISIONING_PORT_TOKEN, d as SaaSiCatPublicRoute, e as SetupConfig, f as defineSaaSiCat, i as isSaaSiCatPublicRoute } from './define-saasicat-D8c6Bs4T.cjs';
4
4
  export { CreatePromoCodeDto, PROMO_CODE_REDEMPTION_REPOSITORY_TOKEN, PROMO_CODE_REPOSITORY_TOKEN, PROMO_CODE_VALIDATION_LOG_REPOSITORY_TOKEN, PROMO_FIRST_TIME_CUSTOMER_CHECK_TOKEN, PROMO_REVENUE_DEDUCTION_AGGREGATOR_TOKEN, PROMO_SERVICE_CONFIG_TOKEN, PROMO_SUBSCRIPTION_LOOKUP_TOKEN, PROMO_TRANSACTION_RUNNER_TOKEN, PreviewPromoCodeDto, PromoCodeExpirer, PromoCodeForCalc, PromoCodePublicController, UpdatePromoCodeDto, addCycles, buildLabel, buildPromoCodeAdminController, computeDiscountGross, computeDiscountedGross, computeIncludedVat, computeRegularStartsAt, grossFromNet, round2 } from './promo/index.cjs';
5
- export { P as PreviewInput, a as PreviewInvalid, b as PreviewReason, c as PreviewResult, d as PreviewValid, e as PromoCodeStats, f as PromoCodesService, g as PromoServiceConfig, R as RedeemInput } from './service-DX8KbGXl.cjs';
5
+ export { P as PreviewInput, a as PreviewInvalid, b as PreviewReason, c as PreviewResult, d as PreviewValid, e as PromoCodeStats, f as PromoCodesService, g as PromoServiceConfig, R as RedeemInput } from './service-DPZ2W1E-.cjs';
6
6
  export { P as PromoCodeRateLimitGuard, h as hashIp, i as ipFingerprint } from './rate-limit.guard-dntqAlfZ.cjs';
7
- export { P as PromoCodesModule, a as PromoCodesModuleOptions } from './module-CSN8j8Tp.cjs';
7
+ export { P as PromoCodesModule, a as PromoCodesModuleOptions } from './module-DsDkbawm.cjs';
8
8
  export { AjvErrorLike, CatalogBundleUpsellResolver, ConfiguratorCatalogBuilder, FEATURE_GUARD_CONFIG_TOKEN, FEATURE_UI_REGISTRY_TOKEN, FeatureGuard, FeatureGuardConfig, LimitExceededFilter, LoadPlanCatalogOptions, MarketingFields, NextPeriodWindow, PLAN_CATALOG_IMPORT_SINK_TOKEN, PLAN_CATALOG_READ_SINK_TOKEN, PLAN_CATALOG_TOKEN, PUBLIC_CATALOG_BUNDLE_REPOSITORY_TOKEN, PUBLIC_CATALOG_MARKETING_REPOSITORY_TOKEN, PUBLIC_CATALOG_PROJECT_KEY_TOKEN, PeriodRollInput, PlanCatalogBuildSettings, PlanCatalogImportDto, PlanCatalogImporterControllerConfig, PlanCatalogImporterModule, PlanCatalogImporterModuleOptions, PlanCatalogImporterService, PlanCatalogModule, PlanCatalogModuleOptions, PlanCatalogValidationError, PlanResponseEntry, PublicBundleEntry, PublicCatalogController, PublicCatalogModule, PublicCatalogModuleOptions, PublishValidationError, PublishablePlanVersion, REQUIRE_FEATURE_KEY, RenewalDecision, RenewalSubInput, RequireFeature, SUBSCRIPTION_BUNDLE_CONFIG_TOKEN, SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN, SubscriptionContractFreezeService, UPSELL_OFFER_CURRENCY_TOKEN, UPSELL_OFFER_RESOLVER_TOKEN, assertBaseVersionFresh, assertChangeNote, assertDraftPublishable, assertOptimisticLockHeld, buildPlanCatalogFromSnapshot, buildPlanCatalogImporterController, buildTenantSubscriptionBundlesController, clearPendingPlanVersionFields, computeCarriedTrialEndsAt, computeNextPeriod, decideRenewal, findPlan, getActiveFeatureKeys, getMarketedPlans, getPlanOrThrow, getPlanPriceGross, getPlanPriceNet, getPlanQuota, initialPeriodWindow, isFeatureInPlan, isFeaturePlannedOnly, loadPlanCatalogFromFile, loadPlanCatalogFromString, periodEndAfter, periodEndWithMinLead } from './billing/index.cjs';
9
9
  import { SetupStatusResponse, SetupResult, SetupConfirmMfaResponse } from '@saasicat/types';
10
10
  export { BundleVersionFields, ChangeDirection, DiffResult, DiscoveredCapability, DiscoveredFeature, DiscoveredQuota, DiscoverySnapshot, PasswordHasher, PlanVersionFields, VersionChange, VersionChangeDirection, classifyBundleVersionDiff, classifyPlanDiff } from '@saasicat/types';
11
11
  export { A as AUDIT_CONTEXT_RESOLVER_TOKEN, a as AuditContextResolver, b as AuthGuardList, C as CONTRACT_FREEZE_PORT_TOKEN, c as CONTRACT_FREEZE_PROJECT_KEY_TOKEN, d as CONTRACT_FREEZE_SOURCE_PORT_TOKEN, e as ContractFreezeBundleSnapshot, f as ContractFreezePort, g as ContractFreezeSourcePort, D as DuePendingPlanChange, P as PENDING_PLAN_QUERY_PORT_TOKEN, h as PendingPlanQueryPort, S as SELF_SERVICE_BLOCKED_BUNDLES_TOKEN, i as SELF_SERVICE_BLOCKED_PLANS_TOKEN, j as SUBSCRIPTION_USAGE_PORT_TOKEN, k as SUBSCRIPTION_WRITE_PORT_TOKEN, l as SelfServiceBlockedBundles, m as SelfServiceBlockedPlans, n as SubscriptionBundleControllerOptions, o as SubscriptionBundleModule, p as SubscriptionBundleModuleOptions, T as TENANT_AUTH_GUARDS_TOKEN, q as TENANT_ID_RESOLVER_TOKEN, r as TRIAL_PROJECTION_PORT_TOKEN, s as TenantBillingModule, t as TenantBillingModuleOptions, u as TenantIdResolver, v as TrialProjectionInput, w as TrialProjectionPort, U as USAGE_SNAPSHOT_PORT_TOKEN, x as USER_EMAIL_RESOLVER_TOKEN, y as USER_ID_RESOLVER_TOKEN, z as UserEmailResolver, B as UserIdResolver } from './subscription-bundles.module-DCpV-Pb5.cjs';
12
- export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, L as LimitsCheckRow, P as PendingPlanMaterializationService, e as PlanChangeContext, f as PlanChangePreviewDto, g as PlanChangePreviewIssue, h as PlanChangePreviewService, i as PlanChangeType, j as PlanSnapshotDto, k as PreviewPlanChangeDto, l as ProrationDto, m as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, n as SubscriptionBundleCancelPreviewDto, o as SubscriptionBundleConfig, p as SubscriptionBundlePreviewContext, q as SubscriptionBundlePreviewIssue, r as SubscriptionBundlePreviewService, s as SubscriptionBundlesService, T as TenantAdminGuard, t as TenantBillingController, U as UsageResponse, u as addMonths, v as computeProration, w as resolveBundleCancelEffectiveAt, x as resolveBundlePriceNet } from './tenant-billing.controller-CG4CaFUP.cjs';
12
+ export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, L as LimitsCheckRow, P as PendingPlanMaterializationService, e as PlanChangeContext, f as PlanChangePreviewDto, g as PlanChangePreviewIssue, h as PlanChangePreviewService, i as PlanChangeType, j as PlanSnapshotDto, k as PreviewPlanChangeDto, l as ProrationDto, m as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, n as SubscriptionBundleCancelPreviewDto, o as SubscriptionBundleConfig, p as SubscriptionBundlePreviewContext, q as SubscriptionBundlePreviewIssue, r as SubscriptionBundlePreviewService, s as SubscriptionBundlesService, T as TenantAdminGuard, t as TenantBillingController, U as UsageResponse, u as addMonths, v as computeProration, w as resolveBundleCancelEffectiveAt, x as resolveBundlePriceNet } from './tenant-billing.controller-m42YQ_Ei.cjs';
13
13
  export { C as CustomLimitsShape, E as EffectiveLimits, a as EffectiveLimitsSnapshot, b as EnforceLimitInput, c as EntitlementService, P as PlanVersionSnapshot, S as SubscriptionBundleSnapshot, d as SubscriptionLimitsInput, e as aggregateContractLineItemEntitlements, f as aggregateLimits, g as aggregateSubscriptionBundleQuotas, h as applyCustomLimits, i as collectSubscriptionBundleFeatures, j as contractBundleVersionIds, k as contractLimits, l as filterActiveSubscriptionBundles, m as filterPlannedOnlyFeatures, n as hasAnyFeature, o as hasFeature, p as mergeSubscriptionBundlesIntoLimits, t as toEffectiveLimitsSnapshot } from './aggregation-SKfXu09x.cjs';
14
14
  export { ENTITLEMENT_RESOLUTION_CONFIG_TOKEN, ENTITLEMENT_SERVICE_TOKEN, EntitlementModule, EntitlementModuleOptions, LimitExceededError, PLAN_VERSION_REPOSITORY_TOKEN, ReplacedByIndex, SUBSCRIPTION_REPOSITORY_TOKEN, TRANSACTION_RUNNER_TOKEN, buildReplacedByIndex, expandReplacedFeatures, isLimitExceededError } from './entitlement/index.cjs';
15
15
  export { E as EntitlementResolutionConfig, a as EntitlementResolutionInput, r as resolveEntitlementPlan } from './plan-resolution-CFCoUkrE.cjs';
@@ -17,7 +17,7 @@ export { ADMIN_STATS_AUDIT_WINDOW_DAYS_TOKEN, AUDIT_PORT_TOKEN, AUDIT_STATS_PORT
17
17
  export { A as AdminBypassRlsInterceptor, a as AdminManifestModule, b as AdminManifestModuleOptions, c as AdminManifestService, d as AdminModule, e as AdminModuleOptions, f as AdminStatsService, g as AdminStatsSnapshot, M as MfaGuard, h as MfaService, P as PLATFORM_CORE_CONTRIBUTION_TOKEN, R as REQUIRE_MFA_KEY, i as RequireMfa, S as SuperAdminGuard, T as TotpSetupResult, V as VerifyTotpInput } from './admin-stats.service-HUZIU448.cjs';
18
18
  export { A as AdminAuditService } from './admin-audit.service-9IqXMlZm.cjs';
19
19
  export { A as ADMIN_MANIFEST_CONFIG, a as ADMIN_RESOURCES_PORT_TOKEN, b as AdminManifestConfig, c as AdminResourcesModule, d as AdminResourcesModuleOptions, e as AdminResourcesService, f as AdminStatsModule, g as AdminStatsModuleOptions, S as SuspendTenantDto } from './admin-resources.module-DGgGSdzN.cjs';
20
- export { S as SaaSiCatModule, a as SaasPlatformAdapters, b as SaasPlatformAdminResourcesOptions, c as SaasPlatformAdminStatsOptions, d as SaasPlatformCatalogOptions, e as SaasPlatformCheckoutOfferOptions, S as SaasPlatformModule, f as SaasPlatformModuleOptions, g as SaasPlatformPromoCodesOptions, h as SaasPlatformSetupOptions, i as SaasPlatformSubscriptionBundlesOptions, j as SaasPlatformSubscriptionContractOptions, k as SaasPlatformTenantAuthGuards, l as SaasPlatformTenantBillingOptions, m as SetupModule, n as SetupModuleOptions } from './saas-platform.module-D3rUTiho.cjs';
20
+ export { S as SaaSiCatModule, a as SaasPlatformAdapters, b as SaasPlatformAdminResourcesOptions, c as SaasPlatformAdminStatsOptions, d as SaasPlatformCatalogOptions, e as SaasPlatformCheckoutOfferOptions, S as SaasPlatformModule, f as SaasPlatformModuleOptions, g as SaasPlatformPromoCodesOptions, h as SaasPlatformSetupOptions, i as SaasPlatformSubscriptionBundlesOptions, j as SaasPlatformSubscriptionContractOptions, k as SaasPlatformTenantAuthGuards, l as SaasPlatformTenantBillingOptions, m as SetupModule, n as SetupModuleOptions } from './saas-platform.module-DducnQ9s.cjs';
21
21
  export { ACTIVATION_ORCHESTRATOR_TOKEN, BaseIpRateLimitGuard, ContinueRegistrationDto, PASSWORD_HASHER_TOKEN, PAYMENT_EVENT_LOG_TOKEN, PAYMENT_PROVIDER_TOKEN, PENDING_REGISTRATION_REPOSITORY_TOKEN, PLAN_CATALOG_LOOKUP_TOKEN, PaymentWebhookDto, PendingRegistrationService, PreviewRegistrationPromoDto, PromoEvaluation, REGISTRATION_AUDIT_LOGGER_TOKEN, REGISTRATION_CONFIGURATOR_LOOKUP_TOKEN, REGISTRATION_CONFIG_TOKEN, REGISTRATION_OTP_DELIVERY_TOKEN, REGISTRATION_PROMO_PREVIEW_TOKEN, REGISTRATION_RESUME_BASE_URL_TOKEN, REGISTRATION_RESUME_DELIVERY_TOKEN, REGISTRATION_RESUME_TOKEN_SIGNER_TOKEN, RegisterStartDto, RegistrationCleanupCron, RegistrationModule, RegistrationModuleOptions, ResendRegistrationOtpDto, SLUG_AVAILABILITY_CHECK_TOKEN, SaveRegistrationConfigDto, SaveRegistrationConfigSelectionDto, SelectRegistrationPlanDto, StartRegistrationCheckoutDto, USER_ACCOUNT_LOOKUP_TOKEN, VerifyRegistrationOtpDto, computeBreakdown, generateOtpCode, hashOtpCode, resolveModel, slugify, verifyOtpCode } from './registration/index.cjs';
22
22
  export { DEFINES_QUOTA_KEY, DISCOVERY_SNAPSHOT_TOKEN, DefinesQuota, DefinesQuotaOptions, DiscoveryControllerConfig, DiscoveryModule, DiscoveryModuleOptions, DiscoverySnapshotNotFoundError, ENFORCE_QUOTA_KEY, EnforceQuota, EnforceQuotaMetadata, EnforceQuotaOptions, HeadlessScanOptions, IMPLEMENTS_CAPABILITY_KEY, ImplementsCapability, ImplementsCapabilityMetadata, ImplementsCapabilityOptions, REQUIRES_CAPABILITY_KEY, RequiresCapability, RequiresCapabilityKeys, buildDiscoveryController, loadDiscoverySnapshotFromFile, runHeadlessDiscoveryScan } from './discovery/index.cjs';
23
23
  export { D as DISCOVERY_APP_INFO_TOKEN, a as DISCOVERY_SNAPSHOT_PATH_TOKEN, b as DiscoveryAppInfo, c as DiscoveryScanner, d as computeSnapshotHash } from './discovery.scanner-DLgEvuoy.cjs';