@saasicat/nest 0.7.0 → 0.9.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 (59) hide show
  1. package/dist/admin/index.cjs +262 -7
  2. package/dist/admin/index.d.cts +6 -4
  3. package/dist/admin/index.d.ts +6 -4
  4. package/dist/admin/index.js +12 -4
  5. package/dist/{admin-manifest.service-Cp6uwvmt.d.cts → admin-manifest.service-BMeSLRW4.d.ts} +1 -1
  6. package/dist/{admin-manifest.service-UGgzR1x-.d.ts → admin-manifest.service-StAQe6QO.d.cts} +1 -1
  7. package/dist/admin-resources.module-BybEjZs-.d.cts +40 -0
  8. package/dist/admin-resources.module-CUCLlUAi.d.ts +40 -0
  9. package/dist/billing/index.cjs +3 -1
  10. package/dist/billing/index.d.cts +5 -287
  11. package/dist/billing/index.d.ts +5 -287
  12. package/dist/billing/index.js +5 -8
  13. package/dist/catalog/index.d.cts +4 -101
  14. package/dist/catalog/index.d.ts +4 -101
  15. package/dist/catalog/index.js +12 -10
  16. package/dist/catalog.module-BKObceo0.d.ts +103 -0
  17. package/dist/catalog.module-Dw2Hrbyu.d.cts +103 -0
  18. package/dist/{chunk-U6HT27J7.js → chunk-3M6VLT5N.js} +257 -6
  19. package/dist/chunk-7K5PT2LX.js +211 -0
  20. package/dist/{chunk-RZU4HIAN.js → chunk-GW2I3JZD.js} +25 -22
  21. package/dist/{chunk-6LP7CDS2.js → chunk-HXAWPPFW.js} +10 -5
  22. package/dist/chunk-OFBDEO45.js +755 -0
  23. package/dist/{chunk-5DDCSGZC.js → chunk-PBQRPDO2.js} +142 -354
  24. package/dist/{chunk-SD3TT2BR.js → chunk-WGVTXSYW.js} +1 -1
  25. package/dist/{chunk-A2QBXDJC.js → chunk-ZZMAHX22.js} +343 -16
  26. package/dist/{enforce-quota.interceptor-Dj1Kusr5.d.ts → enforce-quota.interceptor-B3CL5MSw.d.ts} +94 -12
  27. package/dist/{enforce-quota.interceptor-cv7r80VM.d.cts → enforce-quota.interceptor-SqrQVF91.d.cts} +94 -12
  28. package/dist/entitlement/index.cjs +1 -0
  29. package/dist/entitlement/index.d.cts +3 -1
  30. package/dist/entitlement/index.d.ts +3 -1
  31. package/dist/entitlement/index.js +1 -2
  32. package/dist/index.cjs +3503 -2811
  33. package/dist/index.d.cts +9 -6
  34. package/dist/index.d.ts +9 -6
  35. package/dist/index.js +75 -61
  36. package/dist/module-B5m080F0.d.ts +39 -0
  37. package/dist/module-DeH_Jkcq.d.cts +39 -0
  38. package/dist/platform/index.cjs +11113 -971
  39. package/dist/platform/index.d.cts +41 -7
  40. package/dist/platform/index.d.ts +41 -7
  41. package/dist/platform/index.js +26 -6
  42. package/dist/promo/index.cjs +530 -5
  43. package/dist/promo/index.d.cts +47 -30
  44. package/dist/promo/index.d.ts +47 -30
  45. package/dist/promo/index.js +9 -1
  46. package/dist/{service-DX8KbGXl.d.cts → service-DlhMnYjW.d.cts} +1 -1
  47. package/dist/{service-DX8KbGXl.d.ts → service-DlhMnYjW.d.ts} +1 -1
  48. package/dist/subscription-bundles.module-BQmoozm5.d.ts +291 -0
  49. package/dist/subscription-bundles.module-DCpV-Pb5.d.cts +291 -0
  50. package/dist/testing/index.cjs +11101 -973
  51. package/dist/testing/index.d.cts +9 -4
  52. package/dist/testing/index.d.ts +9 -4
  53. package/dist/testing/index.js +10 -4
  54. package/package.json +4 -4
  55. package/dist/admin-manifest.config-DyrQNT7M.d.cts +0 -10
  56. package/dist/admin-manifest.config-DyrQNT7M.d.ts +0 -10
  57. package/dist/chunk-52UTQRD3.js +0 -326
  58. package/dist/chunk-Q53N43LQ.js +0 -13
  59. /package/dist/{chunk-2FR6ZL7R.js → chunk-HWGIMNWR.js} +0 -0
@@ -0,0 +1,755 @@
1
+ import {
2
+ PROMO_CODE_REDEMPTION_REPOSITORY_TOKEN,
3
+ PROMO_CODE_REPOSITORY_TOKEN,
4
+ PROMO_CODE_VALIDATION_LOG_REPOSITORY_TOKEN,
5
+ PROMO_FIRST_TIME_CUSTOMER_CHECK_TOKEN,
6
+ PROMO_REVENUE_DEDUCTION_AGGREGATOR_TOKEN,
7
+ PROMO_SERVICE_CONFIG_TOKEN,
8
+ PROMO_SUBSCRIPTION_LOOKUP_TOKEN,
9
+ PROMO_TRANSACTION_RUNNER_TOKEN,
10
+ PromoCodesService
11
+ } from "./chunk-ZLUGQE5D.js";
12
+ import {
13
+ AdminAuditService
14
+ } from "./chunk-E56W4U2P.js";
15
+ import {
16
+ asProvider
17
+ } from "./chunk-SABTXESR.js";
18
+ import {
19
+ __name
20
+ } from "./chunk-SHUYVCID.js";
21
+
22
+ // src/promo/expirer.ts
23
+ import { Inject, Injectable, Logger } from "@nestjs/common";
24
+ import { Cron, CronExpression } from "@nestjs/schedule";
25
+ function _ts_decorate(decorators, target, key, desc) {
26
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
27
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
28
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
29
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
30
+ }
31
+ __name(_ts_decorate, "_ts_decorate");
32
+ function _ts_metadata(k, v) {
33
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
34
+ }
35
+ __name(_ts_metadata, "_ts_metadata");
36
+ function _ts_param(paramIndex, decorator) {
37
+ return function(target, key) {
38
+ decorator(target, key, paramIndex);
39
+ };
40
+ }
41
+ __name(_ts_param, "_ts_param");
42
+ var PromoCodeExpirer = class _PromoCodeExpirer {
43
+ static {
44
+ __name(this, "PromoCodeExpirer");
45
+ }
46
+ promoRepo;
47
+ redemptionRepo;
48
+ logger = new Logger(_PromoCodeExpirer.name);
49
+ constructor(promoRepo, redemptionRepo) {
50
+ this.promoRepo = promoRepo;
51
+ this.redemptionRepo = redemptionRepo;
52
+ }
53
+ async expirePromoCodes() {
54
+ const now = /* @__PURE__ */ new Date();
55
+ const codes = await this.promoRepo.expireDueCodes(now);
56
+ const redemptions = await this.redemptionRepo.expireDueRedemptions(now);
57
+ if (codes > 0 || redemptions > 0) {
58
+ this.logger.log(`PromoCodeExpirer: ${codes} Codes, ${redemptions} Redemptions abgelaufen.`);
59
+ }
60
+ }
61
+ };
62
+ _ts_decorate([
63
+ Cron(CronExpression.EVERY_DAY_AT_3AM, {
64
+ name: "promoCodeExpirer",
65
+ timeZone: "Europe/Berlin"
66
+ }),
67
+ _ts_metadata("design:type", Function),
68
+ _ts_metadata("design:paramtypes", []),
69
+ _ts_metadata("design:returntype", Promise)
70
+ ], PromoCodeExpirer.prototype, "expirePromoCodes", null);
71
+ PromoCodeExpirer = _ts_decorate([
72
+ Injectable(),
73
+ _ts_param(0, Inject(PROMO_CODE_REPOSITORY_TOKEN)),
74
+ _ts_param(1, Inject(PROMO_CODE_REDEMPTION_REPOSITORY_TOKEN)),
75
+ _ts_metadata("design:type", Function),
76
+ _ts_metadata("design:paramtypes", [
77
+ typeof PromoCodeRepository === "undefined" ? Object : PromoCodeRepository,
78
+ typeof PromoCodeRedemptionRepository === "undefined" ? Object : PromoCodeRedemptionRepository
79
+ ])
80
+ ], PromoCodeExpirer);
81
+
82
+ // src/promo/rate-limit.guard.ts
83
+ import { HttpException, HttpStatus, Injectable as Injectable2 } from "@nestjs/common";
84
+ function _ts_decorate2(decorators, target, key, desc) {
85
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
86
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
87
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
88
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
89
+ }
90
+ __name(_ts_decorate2, "_ts_decorate");
91
+ var IP_WINDOW_MS = 6e4;
92
+ var IP_LIMIT = 20;
93
+ var SESSION_WINDOW_MS = 60 * 6e4;
94
+ var SESSION_LIMIT = 50;
95
+ var PromoCodeRateLimitGuard = class {
96
+ static {
97
+ __name(this, "PromoCodeRateLimitGuard");
98
+ }
99
+ ipBuckets = /* @__PURE__ */ new Map();
100
+ sessionBuckets = /* @__PURE__ */ new Map();
101
+ canActivate(context) {
102
+ const req = context.switchToHttp().getRequest();
103
+ const ipKey = ipFingerprint(req);
104
+ const sessionKey = req.user?.id ?? null;
105
+ if (this.exceeded(this.ipBuckets, ipKey, IP_WINDOW_MS, IP_LIMIT)) {
106
+ throw new HttpException({
107
+ valid: false,
108
+ reason: "RATE_LIMITED"
109
+ }, HttpStatus.TOO_MANY_REQUESTS);
110
+ }
111
+ if (sessionKey && this.exceeded(this.sessionBuckets, sessionKey, SESSION_WINDOW_MS, SESSION_LIMIT)) {
112
+ throw new HttpException({
113
+ valid: false,
114
+ reason: "RATE_LIMITED"
115
+ }, HttpStatus.TOO_MANY_REQUESTS);
116
+ }
117
+ return true;
118
+ }
119
+ exceeded(map, key, windowMs, limit) {
120
+ const now = Date.now();
121
+ const b = map.get(key);
122
+ if (!b || now - b.windowStart > windowMs) {
123
+ map.set(key, {
124
+ count: 1,
125
+ windowStart: now
126
+ });
127
+ return false;
128
+ }
129
+ b.count += 1;
130
+ return b.count > limit;
131
+ }
132
+ };
133
+ PromoCodeRateLimitGuard = _ts_decorate2([
134
+ Injectable2()
135
+ ], PromoCodeRateLimitGuard);
136
+ function ipFingerprint(req) {
137
+ const fwd = req.headers["x-forwarded-for"];
138
+ const first = Array.isArray(fwd) ? fwd[0] : fwd?.split(",")[0]?.trim();
139
+ return first || req.ip || "unknown";
140
+ }
141
+ __name(ipFingerprint, "ipFingerprint");
142
+ function hashIp(req) {
143
+ const fp = ipFingerprint(req);
144
+ let h = 0;
145
+ for (let i = 0; i < fp.length; i++) {
146
+ h = h * 31 + fp.charCodeAt(i) | 0;
147
+ }
148
+ return `ip${(h >>> 0).toString(16)}`;
149
+ }
150
+ __name(hashIp, "hashIp");
151
+
152
+ // src/promo/dto/promo-public.dto.ts
153
+ import { IsEmail, IsOptional, IsString, Matches, MaxLength } from "class-validator";
154
+ function _ts_decorate3(decorators, target, key, desc) {
155
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
156
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
157
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
158
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
159
+ }
160
+ __name(_ts_decorate3, "_ts_decorate");
161
+ function _ts_metadata2(k, v) {
162
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
163
+ }
164
+ __name(_ts_metadata2, "_ts_metadata");
165
+ var PLAN_OR_CYCLE_PATTERN = /^[A-Z][A-Z0-9_]*$/;
166
+ var CODE_PATTERN = /^[A-Z0-9_-]{4,32}$/i;
167
+ var PreviewPromoCodeDto = class {
168
+ static {
169
+ __name(this, "PreviewPromoCodeDto");
170
+ }
171
+ code;
172
+ plan;
173
+ billingCycle;
174
+ email;
175
+ };
176
+ _ts_decorate3([
177
+ IsString(),
178
+ Matches(CODE_PATTERN, {
179
+ message: 'code muss aus A\u2013Z, 0\u20139, "-" und "_" bestehen (4\u201332 Zeichen)'
180
+ }),
181
+ _ts_metadata2("design:type", String)
182
+ ], PreviewPromoCodeDto.prototype, "code", void 0);
183
+ _ts_decorate3([
184
+ IsString(),
185
+ Matches(PLAN_OR_CYCLE_PATTERN, {
186
+ message: "plan muss SCREAMING_SNAKE_CASE sein"
187
+ }),
188
+ _ts_metadata2("design:type", String)
189
+ ], PreviewPromoCodeDto.prototype, "plan", void 0);
190
+ _ts_decorate3([
191
+ IsString(),
192
+ Matches(PLAN_OR_CYCLE_PATTERN, {
193
+ message: "billingCycle muss SCREAMING_SNAKE_CASE sein (z. B. MONTHLY, YEARLY)"
194
+ }),
195
+ _ts_metadata2("design:type", String)
196
+ ], PreviewPromoCodeDto.prototype, "billingCycle", void 0);
197
+ _ts_decorate3([
198
+ IsOptional(),
199
+ IsEmail(),
200
+ MaxLength(254),
201
+ _ts_metadata2("design:type", String)
202
+ ], PreviewPromoCodeDto.prototype, "email", void 0);
203
+
204
+ // src/promo/controller.ts
205
+ import { Body, Controller, HttpCode, HttpStatus as HttpStatus2, Inject as Inject2, Post, Req, UseGuards } from "@nestjs/common";
206
+ function _ts_decorate4(decorators, target, key, desc) {
207
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
208
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
209
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
210
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
211
+ }
212
+ __name(_ts_decorate4, "_ts_decorate");
213
+ function _ts_metadata3(k, v) {
214
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
215
+ }
216
+ __name(_ts_metadata3, "_ts_metadata");
217
+ function _ts_param2(paramIndex, decorator) {
218
+ return function(target, key) {
219
+ decorator(target, key, paramIndex);
220
+ };
221
+ }
222
+ __name(_ts_param2, "_ts_param");
223
+ var PromoCodePublicController = class {
224
+ static {
225
+ __name(this, "PromoCodePublicController");
226
+ }
227
+ promo;
228
+ constructor(promo) {
229
+ this.promo = promo;
230
+ }
231
+ async preview(dto, req) {
232
+ return this.promo.preview({
233
+ code: dto.code,
234
+ planId: dto.plan,
235
+ billingCycle: dto.billingCycle,
236
+ email: dto.email,
237
+ ipHash: hashIp(req),
238
+ sessionId: req.user?.id ?? req.user?.sub
239
+ });
240
+ }
241
+ };
242
+ _ts_decorate4([
243
+ Post("preview"),
244
+ HttpCode(HttpStatus2.OK),
245
+ UseGuards(PromoCodeRateLimitGuard),
246
+ _ts_param2(0, Body()),
247
+ _ts_param2(1, Req()),
248
+ _ts_metadata3("design:type", Function),
249
+ _ts_metadata3("design:paramtypes", [
250
+ typeof PreviewPromoCodeDto === "undefined" ? Object : PreviewPromoCodeDto,
251
+ typeof RequestLike === "undefined" ? Object : RequestLike
252
+ ]),
253
+ _ts_metadata3("design:returntype", Promise)
254
+ ], PromoCodePublicController.prototype, "preview", null);
255
+ PromoCodePublicController = _ts_decorate4([
256
+ Controller("billing/promo"),
257
+ _ts_param2(0, Inject2(PromoCodesService)),
258
+ _ts_metadata3("design:type", Function),
259
+ _ts_metadata3("design:paramtypes", [
260
+ typeof PromoCodesService === "undefined" ? Object : PromoCodesService
261
+ ])
262
+ ], PromoCodePublicController);
263
+
264
+ // src/promo/dto/promo-admin.dto.ts
265
+ import { ArrayUnique, IsArray, IsBoolean, IsIn, IsInt, IsNotEmpty, IsNumber, IsOptional as IsOptional2, IsString as IsString2, MaxLength as MaxLength2, Min } from "class-validator";
266
+ function _ts_decorate5(decorators, target, key, desc) {
267
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
268
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
269
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
270
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
271
+ }
272
+ __name(_ts_decorate5, "_ts_decorate");
273
+ function _ts_metadata4(k, v) {
274
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
275
+ }
276
+ __name(_ts_metadata4, "_ts_metadata");
277
+ var VALUE_TYPES = [
278
+ "PERCENT",
279
+ "ABSOLUTE"
280
+ ];
281
+ var DURATION_TYPES = [
282
+ "ONCE",
283
+ "MONTHS",
284
+ "BILLING_CYCLES"
285
+ ];
286
+ var STATUSES = [
287
+ "ACTIVE",
288
+ "PAUSED"
289
+ ];
290
+ var BILLING_CYCLES = [
291
+ "MONTHLY",
292
+ "YEARLY"
293
+ ];
294
+ var CreatePromoCodeDto = class {
295
+ static {
296
+ __name(this, "CreatePromoCodeDto");
297
+ }
298
+ code;
299
+ valueType;
300
+ value;
301
+ durationType;
302
+ durationValue;
303
+ maxRedemptions;
304
+ validFrom;
305
+ validUntil;
306
+ appliesToPlans;
307
+ appliesToBilling;
308
+ firstTimeCustomersOnly;
309
+ minimumPlanAmountGross;
310
+ allowZeroInvoice;
311
+ revenueDeductionAccount;
312
+ campaignTag;
313
+ description;
314
+ };
315
+ _ts_decorate5([
316
+ IsString2(),
317
+ IsNotEmpty(),
318
+ MaxLength2(64),
319
+ _ts_metadata4("design:type", String)
320
+ ], CreatePromoCodeDto.prototype, "code", void 0);
321
+ _ts_decorate5([
322
+ IsIn(VALUE_TYPES),
323
+ _ts_metadata4("design:type", Object)
324
+ ], CreatePromoCodeDto.prototype, "valueType", void 0);
325
+ _ts_decorate5([
326
+ IsNumber(),
327
+ Min(0),
328
+ _ts_metadata4("design:type", Number)
329
+ ], CreatePromoCodeDto.prototype, "value", void 0);
330
+ _ts_decorate5([
331
+ IsIn(DURATION_TYPES),
332
+ _ts_metadata4("design:type", Object)
333
+ ], CreatePromoCodeDto.prototype, "durationType", void 0);
334
+ _ts_decorate5([
335
+ IsOptional2(),
336
+ IsInt(),
337
+ Min(1),
338
+ _ts_metadata4("design:type", Object)
339
+ ], CreatePromoCodeDto.prototype, "durationValue", void 0);
340
+ _ts_decorate5([
341
+ IsOptional2(),
342
+ IsInt(),
343
+ Min(1),
344
+ _ts_metadata4("design:type", Object)
345
+ ], CreatePromoCodeDto.prototype, "maxRedemptions", void 0);
346
+ _ts_decorate5([
347
+ IsOptional2(),
348
+ IsString2(),
349
+ _ts_metadata4("design:type", Object)
350
+ ], CreatePromoCodeDto.prototype, "validFrom", void 0);
351
+ _ts_decorate5([
352
+ IsOptional2(),
353
+ IsString2(),
354
+ _ts_metadata4("design:type", Object)
355
+ ], CreatePromoCodeDto.prototype, "validUntil", void 0);
356
+ _ts_decorate5([
357
+ IsOptional2(),
358
+ IsArray(),
359
+ IsString2({
360
+ each: true
361
+ }),
362
+ ArrayUnique(),
363
+ _ts_metadata4("design:type", Array)
364
+ ], CreatePromoCodeDto.prototype, "appliesToPlans", void 0);
365
+ _ts_decorate5([
366
+ IsOptional2(),
367
+ IsIn(BILLING_CYCLES),
368
+ _ts_metadata4("design:type", Object)
369
+ ], CreatePromoCodeDto.prototype, "appliesToBilling", void 0);
370
+ _ts_decorate5([
371
+ IsOptional2(),
372
+ IsBoolean(),
373
+ _ts_metadata4("design:type", Boolean)
374
+ ], CreatePromoCodeDto.prototype, "firstTimeCustomersOnly", void 0);
375
+ _ts_decorate5([
376
+ IsOptional2(),
377
+ IsNumber(),
378
+ Min(0),
379
+ _ts_metadata4("design:type", Object)
380
+ ], CreatePromoCodeDto.prototype, "minimumPlanAmountGross", void 0);
381
+ _ts_decorate5([
382
+ IsOptional2(),
383
+ IsBoolean(),
384
+ _ts_metadata4("design:type", Boolean)
385
+ ], CreatePromoCodeDto.prototype, "allowZeroInvoice", void 0);
386
+ _ts_decorate5([
387
+ IsOptional2(),
388
+ IsString2(),
389
+ MaxLength2(32),
390
+ _ts_metadata4("design:type", Object)
391
+ ], CreatePromoCodeDto.prototype, "revenueDeductionAccount", void 0);
392
+ _ts_decorate5([
393
+ IsOptional2(),
394
+ IsString2(),
395
+ MaxLength2(64),
396
+ _ts_metadata4("design:type", Object)
397
+ ], CreatePromoCodeDto.prototype, "campaignTag", void 0);
398
+ _ts_decorate5([
399
+ IsOptional2(),
400
+ IsString2(),
401
+ MaxLength2(500),
402
+ _ts_metadata4("design:type", Object)
403
+ ], CreatePromoCodeDto.prototype, "description", void 0);
404
+ var UpdatePromoCodeDto = class {
405
+ static {
406
+ __name(this, "UpdatePromoCodeDto");
407
+ }
408
+ status;
409
+ valueType;
410
+ value;
411
+ durationType;
412
+ durationValue;
413
+ maxRedemptions;
414
+ validFrom;
415
+ validUntil;
416
+ appliesToPlans;
417
+ appliesToBilling;
418
+ firstTimeCustomersOnly;
419
+ minimumPlanAmountGross;
420
+ allowZeroInvoice;
421
+ description;
422
+ campaignTag;
423
+ revenueDeductionAccount;
424
+ };
425
+ _ts_decorate5([
426
+ IsOptional2(),
427
+ IsIn(STATUSES),
428
+ _ts_metadata4("design:type", Object)
429
+ ], UpdatePromoCodeDto.prototype, "status", void 0);
430
+ _ts_decorate5([
431
+ IsOptional2(),
432
+ IsIn(VALUE_TYPES),
433
+ _ts_metadata4("design:type", Object)
434
+ ], UpdatePromoCodeDto.prototype, "valueType", void 0);
435
+ _ts_decorate5([
436
+ IsOptional2(),
437
+ IsNumber(),
438
+ Min(0),
439
+ _ts_metadata4("design:type", Number)
440
+ ], UpdatePromoCodeDto.prototype, "value", void 0);
441
+ _ts_decorate5([
442
+ IsOptional2(),
443
+ IsIn(DURATION_TYPES),
444
+ _ts_metadata4("design:type", Object)
445
+ ], UpdatePromoCodeDto.prototype, "durationType", void 0);
446
+ _ts_decorate5([
447
+ IsOptional2(),
448
+ IsInt(),
449
+ Min(1),
450
+ _ts_metadata4("design:type", Object)
451
+ ], UpdatePromoCodeDto.prototype, "durationValue", void 0);
452
+ _ts_decorate5([
453
+ IsOptional2(),
454
+ IsInt(),
455
+ Min(1),
456
+ _ts_metadata4("design:type", Object)
457
+ ], UpdatePromoCodeDto.prototype, "maxRedemptions", void 0);
458
+ _ts_decorate5([
459
+ IsOptional2(),
460
+ IsString2(),
461
+ _ts_metadata4("design:type", Object)
462
+ ], UpdatePromoCodeDto.prototype, "validFrom", void 0);
463
+ _ts_decorate5([
464
+ IsOptional2(),
465
+ IsString2(),
466
+ _ts_metadata4("design:type", Object)
467
+ ], UpdatePromoCodeDto.prototype, "validUntil", void 0);
468
+ _ts_decorate5([
469
+ IsOptional2(),
470
+ IsArray(),
471
+ IsString2({
472
+ each: true
473
+ }),
474
+ ArrayUnique(),
475
+ _ts_metadata4("design:type", Array)
476
+ ], UpdatePromoCodeDto.prototype, "appliesToPlans", void 0);
477
+ _ts_decorate5([
478
+ IsOptional2(),
479
+ IsIn(BILLING_CYCLES),
480
+ _ts_metadata4("design:type", Object)
481
+ ], UpdatePromoCodeDto.prototype, "appliesToBilling", void 0);
482
+ _ts_decorate5([
483
+ IsOptional2(),
484
+ IsBoolean(),
485
+ _ts_metadata4("design:type", Boolean)
486
+ ], UpdatePromoCodeDto.prototype, "firstTimeCustomersOnly", void 0);
487
+ _ts_decorate5([
488
+ IsOptional2(),
489
+ IsNumber(),
490
+ Min(0),
491
+ _ts_metadata4("design:type", Object)
492
+ ], UpdatePromoCodeDto.prototype, "minimumPlanAmountGross", void 0);
493
+ _ts_decorate5([
494
+ IsOptional2(),
495
+ IsBoolean(),
496
+ _ts_metadata4("design:type", Boolean)
497
+ ], UpdatePromoCodeDto.prototype, "allowZeroInvoice", void 0);
498
+ _ts_decorate5([
499
+ IsOptional2(),
500
+ IsString2(),
501
+ MaxLength2(500),
502
+ _ts_metadata4("design:type", Object)
503
+ ], UpdatePromoCodeDto.prototype, "description", void 0);
504
+ _ts_decorate5([
505
+ IsOptional2(),
506
+ IsString2(),
507
+ MaxLength2(64),
508
+ _ts_metadata4("design:type", Object)
509
+ ], UpdatePromoCodeDto.prototype, "campaignTag", void 0);
510
+ _ts_decorate5([
511
+ IsOptional2(),
512
+ IsString2(),
513
+ MaxLength2(32),
514
+ _ts_metadata4("design:type", Object)
515
+ ], UpdatePromoCodeDto.prototype, "revenueDeductionAccount", void 0);
516
+
517
+ // src/promo/admin-controller.ts
518
+ import { Body as Body2, Controller as Controller2, Delete, Get, Inject as Inject3, Param, Patch, Post as Post2, Query, Req as Req2, UseGuards as UseGuards2 } from "@nestjs/common";
519
+ function _ts_decorate6(decorators, target, key, desc) {
520
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
521
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
522
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
523
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
524
+ }
525
+ __name(_ts_decorate6, "_ts_decorate");
526
+ function _ts_metadata5(k, v) {
527
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
528
+ }
529
+ __name(_ts_metadata5, "_ts_metadata");
530
+ function _ts_param3(paramIndex, decorator) {
531
+ return function(target, key) {
532
+ decorator(target, key, paramIndex);
533
+ };
534
+ }
535
+ __name(_ts_param3, "_ts_param");
536
+ function buildPromoCodeAdminController(guards) {
537
+ let GeneratedPromoCodeAdminController = class GeneratedPromoCodeAdminController {
538
+ static {
539
+ __name(this, "GeneratedPromoCodeAdminController");
540
+ }
541
+ promos;
542
+ audit;
543
+ constructor(promos, audit) {
544
+ this.promos = promos;
545
+ this.audit = audit;
546
+ }
547
+ findAll(query) {
548
+ return this.promos.findAll(query);
549
+ }
550
+ async create(request, dto) {
551
+ const actor = actorFromRequest(request);
552
+ const created = await this.promos.create(toCreateData(dto, actor.userId));
553
+ await this.audit.log({
554
+ actor,
555
+ entity: "PromoCode",
556
+ entityId: created.id,
557
+ action: "PROMO_CODE_CREATE",
558
+ changes: {
559
+ code: created.code
560
+ }
561
+ });
562
+ return created;
563
+ }
564
+ async update(request, id, dto) {
565
+ const actor = actorFromRequest(request);
566
+ const updated = await this.promos.update(id, toUpdateData(dto));
567
+ await this.audit.log({
568
+ actor,
569
+ entity: "PromoCode",
570
+ entityId: id,
571
+ action: "PROMO_CODE_UPDATE",
572
+ changes: {
573
+ fields: Object.keys(dto)
574
+ }
575
+ });
576
+ return updated;
577
+ }
578
+ async remove(request, id) {
579
+ const actor = actorFromRequest(request);
580
+ await this.promos.softDelete(id);
581
+ await this.audit.log({
582
+ actor,
583
+ entity: "PromoCode",
584
+ entityId: id,
585
+ action: "PROMO_CODE_DELETE"
586
+ });
587
+ return {
588
+ ok: true
589
+ };
590
+ }
591
+ };
592
+ _ts_decorate6([
593
+ Get(),
594
+ _ts_param3(0, Query()),
595
+ _ts_metadata5("design:type", Function),
596
+ _ts_metadata5("design:paramtypes", [
597
+ Object
598
+ ]),
599
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
600
+ ], GeneratedPromoCodeAdminController.prototype, "findAll", null);
601
+ _ts_decorate6([
602
+ Post2(),
603
+ _ts_param3(0, Req2()),
604
+ _ts_param3(1, Body2()),
605
+ _ts_metadata5("design:type", Function),
606
+ _ts_metadata5("design:paramtypes", [
607
+ typeof AdminRequest === "undefined" ? Object : AdminRequest,
608
+ typeof CreatePromoCodeDto === "undefined" ? Object : CreatePromoCodeDto
609
+ ]),
610
+ _ts_metadata5("design:returntype", Promise)
611
+ ], GeneratedPromoCodeAdminController.prototype, "create", null);
612
+ _ts_decorate6([
613
+ Patch(":id"),
614
+ _ts_param3(0, Req2()),
615
+ _ts_param3(1, Param("id")),
616
+ _ts_param3(2, Body2()),
617
+ _ts_metadata5("design:type", Function),
618
+ _ts_metadata5("design:paramtypes", [
619
+ typeof AdminRequest === "undefined" ? Object : AdminRequest,
620
+ String,
621
+ typeof UpdatePromoCodeDto === "undefined" ? Object : UpdatePromoCodeDto
622
+ ]),
623
+ _ts_metadata5("design:returntype", Promise)
624
+ ], GeneratedPromoCodeAdminController.prototype, "update", null);
625
+ _ts_decorate6([
626
+ Delete(":id"),
627
+ _ts_param3(0, Req2()),
628
+ _ts_param3(1, Param("id")),
629
+ _ts_metadata5("design:type", Function),
630
+ _ts_metadata5("design:paramtypes", [
631
+ typeof AdminRequest === "undefined" ? Object : AdminRequest,
632
+ String
633
+ ]),
634
+ _ts_metadata5("design:returntype", Promise)
635
+ ], GeneratedPromoCodeAdminController.prototype, "remove", null);
636
+ GeneratedPromoCodeAdminController = _ts_decorate6([
637
+ Controller2("admin/promo-codes"),
638
+ UseGuards2(...guards),
639
+ _ts_param3(0, Inject3(PromoCodesService)),
640
+ _ts_param3(1, Inject3(AdminAuditService)),
641
+ _ts_metadata5("design:type", Function),
642
+ _ts_metadata5("design:paramtypes", [
643
+ typeof PromoCodesService === "undefined" ? Object : PromoCodesService,
644
+ typeof AdminAuditService === "undefined" ? Object : AdminAuditService
645
+ ])
646
+ ], GeneratedPromoCodeAdminController);
647
+ return GeneratedPromoCodeAdminController;
648
+ }
649
+ __name(buildPromoCodeAdminController, "buildPromoCodeAdminController");
650
+ function actorFromRequest(request) {
651
+ const userId = request.user?.id ?? request.user?.userId ?? "unknown";
652
+ return {
653
+ userId,
654
+ email: request.user?.email ?? `${userId}@unknown`,
655
+ source: "web",
656
+ context: request.user?.sessionId ?? "unknown"
657
+ };
658
+ }
659
+ __name(actorFromRequest, "actorFromRequest");
660
+ function toCreateData(dto, createdById) {
661
+ return {
662
+ ...dto,
663
+ validFrom: parseDate(dto.validFrom),
664
+ validUntil: parseDate(dto.validUntil),
665
+ createdById
666
+ };
667
+ }
668
+ __name(toCreateData, "toCreateData");
669
+ function toUpdateData(dto) {
670
+ const { validFrom, validUntil, ...fields } = dto;
671
+ const data = fields;
672
+ if (validFrom !== void 0) data.validFrom = parseDate(validFrom);
673
+ if (validUntil !== void 0) data.validUntil = parseDate(validUntil);
674
+ return data;
675
+ }
676
+ __name(toUpdateData, "toUpdateData");
677
+ function parseDate(value) {
678
+ if (!value) return null;
679
+ const date = new Date(value);
680
+ return Number.isNaN(date.getTime()) ? null : date;
681
+ }
682
+ __name(parseDate, "parseDate");
683
+
684
+ // src/promo/module.ts
685
+ import { Module } from "@nestjs/common";
686
+ function _ts_decorate7(decorators, target, key, desc) {
687
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
688
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
689
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
690
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
691
+ }
692
+ __name(_ts_decorate7, "_ts_decorate");
693
+ var PromoCodesModule = class _PromoCodesModule {
694
+ static {
695
+ __name(this, "PromoCodesModule");
696
+ }
697
+ static forRoot(options) {
698
+ const includeCron = options.includeExpirerCron ?? true;
699
+ const includePublic = options.includePublicController ?? true;
700
+ const controllers = includePublic ? [
701
+ PromoCodePublicController
702
+ ] : [];
703
+ if (options.adminController) {
704
+ controllers.push(buildPromoCodeAdminController(options.adminController.guards));
705
+ }
706
+ const providers = [
707
+ asProvider(PROMO_CODE_REPOSITORY_TOKEN, options.promoCodeRepository),
708
+ asProvider(PROMO_CODE_REDEMPTION_REPOSITORY_TOKEN, options.redemptionRepository),
709
+ asProvider(PROMO_CODE_VALIDATION_LOG_REPOSITORY_TOKEN, options.validationLogRepository),
710
+ asProvider(PROMO_FIRST_TIME_CUSTOMER_CHECK_TOKEN, options.firstTimeCustomerCheck),
711
+ asProvider(PROMO_SUBSCRIPTION_LOOKUP_TOKEN, options.subscriptionLookup),
712
+ asProvider(PROMO_REVENUE_DEDUCTION_AGGREGATOR_TOKEN, options.revenueAggregator),
713
+ asProvider(PROMO_TRANSACTION_RUNNER_TOKEN, options.transactionRunner),
714
+ {
715
+ provide: PROMO_SERVICE_CONFIG_TOKEN,
716
+ useValue: options.config ?? {}
717
+ },
718
+ PromoCodesService,
719
+ PromoCodeRateLimitGuard
720
+ ];
721
+ if (includeCron) {
722
+ providers.push(PromoCodeExpirer);
723
+ }
724
+ return {
725
+ module: _PromoCodesModule,
726
+ global: options.global ?? false,
727
+ imports: options.imports ?? [],
728
+ controllers,
729
+ providers,
730
+ exports: [
731
+ PromoCodesService,
732
+ PromoCodeRateLimitGuard,
733
+ PROMO_CODE_REPOSITORY_TOKEN,
734
+ PROMO_CODE_REDEMPTION_REPOSITORY_TOKEN,
735
+ PROMO_CODE_VALIDATION_LOG_REPOSITORY_TOKEN
736
+ ]
737
+ };
738
+ }
739
+ };
740
+ PromoCodesModule = _ts_decorate7([
741
+ Module({})
742
+ ], PromoCodesModule);
743
+
744
+ export {
745
+ PromoCodeExpirer,
746
+ PromoCodeRateLimitGuard,
747
+ ipFingerprint,
748
+ hashIp,
749
+ PreviewPromoCodeDto,
750
+ PromoCodePublicController,
751
+ CreatePromoCodeDto,
752
+ UpdatePromoCodeDto,
753
+ buildPromoCodeAdminController,
754
+ PromoCodesModule
755
+ };