@saasicat/nest 1.0.0-rc.2 → 1.0.0-rc.21

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 (154) hide show
  1. package/README.md +44 -8
  2. package/dist/.build-stamp +1 -1
  3. package/dist/_entries.cjs +10214 -4796
  4. package/dist/admin/index.d.cts +5 -4
  5. package/dist/admin/index.d.ts +5 -4
  6. package/dist/admin/index.js +13 -9
  7. package/dist/{admin-resources.module-CpvzcfCc.d.cts → admin-resources.module-B4XNvdH-.d.cts} +1 -2
  8. package/dist/{admin-resources.module-DF5_Q7RD.d.ts → admin-resources.module-CWqdI9BV.d.ts} +1 -2
  9. package/dist/{admin-stats.service-TYiSUwIR.d.ts → admin-stats.service-CsLNt19Z.d.ts} +11 -7
  10. package/dist/{admin-stats.service-DfKupywR.d.cts → admin-stats.service-DrZrU8IJ.d.cts} +11 -7
  11. package/dist/{aggregation-B3CD0v_d.d.cts → aggregation-ChpZDh0g.d.ts} +39 -6
  12. package/dist/{aggregation-BFzW07DE.d.ts → aggregation-OpnhwzF5.d.cts} +39 -6
  13. package/dist/billing/index.d.cts +448 -108
  14. package/dist/billing/index.d.ts +448 -108
  15. package/dist/billing/index.js +108 -41
  16. package/dist/catalog/index.d.cts +74 -45
  17. package/dist/catalog/index.d.ts +74 -45
  18. package/dist/catalog/index.js +21 -13
  19. package/dist/catalog.module-C9O7BxRq.d.ts +180 -0
  20. package/dist/catalog.module-T-I5Ricz.d.cts +180 -0
  21. package/dist/checkout-offer/index.d.cts +17 -22
  22. package/dist/checkout-offer/index.d.ts +17 -22
  23. package/dist/checkout-offer/index.js +21 -7
  24. package/dist/checkout-offer.module-DFhGy6JO.d.cts +58 -0
  25. package/dist/checkout-offer.module-x7SP_dX4.d.ts +58 -0
  26. package/dist/checkout-offer.service-BeHgYikI.d.ts +242 -0
  27. package/dist/checkout-offer.service-CCVxG9b2.d.cts +242 -0
  28. package/dist/chunk-34XVPR6P.js +222 -0
  29. package/dist/{chunk-AOQJEYOL.js → chunk-3QVGA6JX.js} +3 -1
  30. package/dist/chunk-3RLWML2S.js +896 -0
  31. package/dist/{chunk-TXC3LHHB.js → chunk-4SDSYV4A.js} +21 -13
  32. package/dist/chunk-55QEDAMX.js +946 -0
  33. package/dist/chunk-5CKC7O52.js +140 -0
  34. package/dist/chunk-6PJE7EWO.js +185 -0
  35. package/dist/chunk-7NJKVC5X.js +353 -0
  36. package/dist/{chunk-RUNZ3X4C.js → chunk-AOS2JPDD.js} +1263 -185
  37. package/dist/{chunk-WOVQPXV4.js → chunk-CQ2ZZMTD.js} +702 -725
  38. package/dist/{chunk-NA6O63B7.js → chunk-F5X66HF5.js} +5 -5
  39. package/dist/chunk-FEQZCWUL.js +174 -0
  40. package/dist/{chunk-VIJ5NJWC.js → chunk-G6EZWECL.js} +107 -31
  41. package/dist/chunk-G7RQO2XO.js +0 -0
  42. package/dist/{chunk-N3L3AICU.js → chunk-GPQWGA6B.js} +5 -6
  43. package/dist/chunk-GZTL64QK.js +7 -0
  44. package/dist/{chunk-SABTXESR.js → chunk-J7NJRK3K.js} +17 -1
  45. package/dist/{chunk-SEPN52AD.js → chunk-JBCC6C3M.js} +566 -307
  46. package/dist/{chunk-I7GTA3RX.js → chunk-JQRA724W.js} +1 -1
  47. package/dist/{chunk-WXYJHZCN.js → chunk-JVAEKTJ4.js} +2 -14
  48. package/dist/chunk-KPEMTBOP.js +26 -0
  49. package/dist/chunk-LF6J4YYN.js +301 -0
  50. package/dist/{chunk-LTT736P3.js → chunk-LLYVYRGJ.js} +228 -387
  51. package/dist/{chunk-6Z7JR4EW.js → chunk-M47BNEY2.js} +1897 -633
  52. package/dist/{chunk-KFT5AIIH.js → chunk-NDLC5GYK.js} +206 -24
  53. package/dist/{chunk-O2J2HDXA.js → chunk-OOTEXP47.js} +3 -8
  54. package/dist/chunk-QPVDCKYS.js +702 -0
  55. package/dist/{chunk-NHVDCYK5.js → chunk-R5YCJBHY.js} +71 -106
  56. package/dist/{chunk-XBYAFEOR.js → chunk-S33SO5XX.js} +1 -1
  57. package/dist/chunk-SZ7RFPXA.js +10 -0
  58. package/dist/chunk-TBBZWZQT.js +98 -0
  59. package/dist/chunk-TOEFN7DN.js +295 -0
  60. package/dist/{chunk-7ZEGFL42.js → chunk-WHJSYKNC.js} +6 -6
  61. package/dist/chunk-WOEJ6K7M.js +55 -0
  62. package/dist/{chunk-AU3OOREM.js → chunk-XSSWYPP5.js} +16 -3
  63. package/dist/contract-line-item-money-B0Z3Ogur.d.cts +43 -0
  64. package/dist/contract-line-item-money-B0Z3Ogur.d.ts +43 -0
  65. package/dist/discovery/index.d.cts +2 -2
  66. package/dist/discovery/index.d.ts +2 -2
  67. package/dist/discovery/index.js +6 -6
  68. package/dist/{discovery.scanner-9cMqF95o.d.cts → discovery.scanner-DXKc6JkV.d.cts} +1 -1
  69. package/dist/{discovery.scanner-9cMqF95o.d.ts → discovery.scanner-DXKc6JkV.d.ts} +1 -1
  70. package/dist/{enforce-quota.interceptor-Df0e3OWe.d.cts → enforce-quota.interceptor-BFyVdWe8.d.cts} +6 -6
  71. package/dist/{enforce-quota.interceptor-DW3etVyI.d.ts → enforce-quota.interceptor-GaBXboGx.d.ts} +6 -6
  72. package/dist/entitlement/index.d.cts +27 -4
  73. package/dist/entitlement/index.d.ts +27 -4
  74. package/dist/entitlement/index.js +13 -8
  75. package/dist/index.d.cts +209 -28
  76. package/dist/index.d.ts +209 -28
  77. package/dist/index.js +285 -163
  78. package/dist/issuer-identity.check-CBO0vcsq.d.cts +197 -0
  79. package/dist/issuer-identity.check-Cz9CEMkZ.d.ts +197 -0
  80. package/dist/{module-options-COSEb0VW.d.ts → module-options-DmQ3G4sZ.d.ts} +135 -41
  81. package/dist/{module-options-BG3MzQva.d.cts → module-options-qAOwinHR.d.cts} +135 -41
  82. package/dist/payment-callback.service-CR84Xw1Z.d.cts +125 -0
  83. package/dist/payment-callback.service-CR84Xw1Z.d.ts +125 -0
  84. package/dist/payments/index.cjs +4 -0
  85. package/dist/payments/index.d.cts +187 -0
  86. package/dist/payments/index.d.ts +187 -0
  87. package/dist/payments/index.js +141 -0
  88. package/dist/payments.module-BdUq9ot_.d.cts +57 -0
  89. package/dist/payments.module-CQGv_VG7.d.ts +57 -0
  90. package/dist/plan-catalog-source-DWe-BGY1.d.cts +21 -0
  91. package/dist/plan-catalog-source-DWe-BGY1.d.ts +21 -0
  92. package/dist/{plan-resolution-Cgo_TR1H.d.cts → plan-resolution-CwUy_OqC.d.cts} +14 -0
  93. package/dist/{plan-resolution-Cgo_TR1H.d.ts → plan-resolution-CwUy_OqC.d.ts} +14 -0
  94. package/dist/{plan-versions.service-DChhbK6h.d.ts → plan-versions.service-C0N-Em2W.d.ts} +38 -64
  95. package/dist/{plan-versions.service-TPEtbN0r.d.cts → plan-versions.service-DARLh-qI.d.cts} +38 -64
  96. package/dist/platform/index.d.cts +52 -23
  97. package/dist/platform/index.d.ts +52 -23
  98. package/dist/platform/index.js +57 -36
  99. package/dist/promo/index.d.cts +23 -8
  100. package/dist/promo/index.d.ts +23 -8
  101. package/dist/promo/index.js +15 -7
  102. package/dist/{promo.module-DtvIycpt.d.cts → promo.module-CKkECmU8.d.cts} +9 -3
  103. package/dist/{promo.module-Z8h1PNX-.d.ts → promo.module-DuIJdK3U.d.ts} +9 -3
  104. package/dist/promo.service-BYBu6dy3.d.cts +215 -0
  105. package/dist/promo.service-CFjfF0Xm.d.ts +215 -0
  106. package/dist/registration/index.d.cts +104 -47
  107. package/dist/registration/index.d.ts +104 -47
  108. package/dist/registration/index.js +15 -9
  109. package/dist/subscriber/index.cjs +4 -0
  110. package/dist/subscriber/index.d.cts +28 -0
  111. package/dist/subscriber/index.d.ts +28 -0
  112. package/dist/subscriber/index.js +16 -0
  113. package/dist/subscriber.service-5W6Gi-1B.d.cts +68 -0
  114. package/dist/subscriber.service-5W6Gi-1B.d.ts +68 -0
  115. package/dist/subscription-contract/index.d.cts +4 -2
  116. package/dist/subscription-contract/index.d.ts +4 -2
  117. package/dist/subscription-contract/index.js +13 -5
  118. package/dist/{subscription-contract.module-fDFdQ0jm.d.ts → subscription-contract.module-BfIRpc1o.d.ts} +8 -2
  119. package/dist/{subscription-contract.module-CEK8HS5-.d.cts → subscription-contract.module-DTMuUJYd.d.cts} +8 -2
  120. package/dist/{subscription-contract.service-hD87MKyg.d.cts → subscription-contract.service-CPZrTM9C.d.ts} +32 -3
  121. package/dist/{subscription-contract.service-hD87MKyg.d.ts → subscription-contract.service-CfNApLuP.d.cts} +32 -3
  122. package/dist/tenant-billing.controller-BLqbsONe.d.ts +812 -0
  123. package/dist/tenant-billing.controller-DKbAqTbM.d.cts +812 -0
  124. package/dist/tenant-billing.module-ClbjzocC.d.cts +364 -0
  125. package/dist/tenant-billing.module-DohgJJ2m.d.ts +364 -0
  126. package/dist/tenant-billing.tokens-G-1xOlMr.d.cts +129 -0
  127. package/dist/tenant-billing.tokens-G-1xOlMr.d.ts +129 -0
  128. package/dist/testing/index.d.cts +44 -17
  129. package/dist/testing/index.d.ts +44 -17
  130. package/dist/testing/index.js +189 -40
  131. package/package.json +24 -4
  132. package/dist/catalog.module-BDDO6iwq.d.cts +0 -103
  133. package/dist/catalog.module-BTnMsE6u.d.ts +0 -103
  134. package/dist/checkout-offer.module-CMtiQJTT.d.ts +0 -39
  135. package/dist/checkout-offer.module-CVpWrzbe.d.cts +0 -39
  136. package/dist/checkout-offer.service-BLOv2HOo.d.cts +0 -49
  137. package/dist/checkout-offer.service-BLOv2HOo.d.ts +0 -49
  138. package/dist/chunk-57V6ZTI6.js +0 -22
  139. package/dist/chunk-BSK6YBLI.js +0 -87
  140. package/dist/chunk-DQKCK7DX.js +0 -217
  141. package/dist/chunk-VXEYLNIB.js +0 -632
  142. package/dist/chunk-WUDYIPYH.js +0 -715
  143. package/dist/define-saasicat-DROBe-b1.d.ts +0 -69
  144. package/dist/define-saasicat-vGBCkFys.d.cts +0 -69
  145. package/dist/promo.service-BJbKAmw3.d.cts +0 -112
  146. package/dist/promo.service-BJbKAmw3.d.ts +0 -112
  147. package/dist/tenant-billing.controller-BQ67mlmI.d.ts +0 -438
  148. package/dist/tenant-billing.controller-DS8kB8a7.d.cts +0 -438
  149. package/dist/tenant-billing.module-BznC3XtW.d.cts +0 -299
  150. package/dist/tenant-billing.module-wUbsQSFG.d.ts +0 -299
  151. /package/dist/{chunk-2FR6ZL7R.js → chunk-BHZOH2DY.js} +0 -0
  152. /package/dist/{chunk-2SLTRKXC.js → chunk-DFOW3JVO.js} +0 -0
  153. /package/dist/{chunk-DBZGV3HC.js → chunk-DU56UKEH.js} +0 -0
  154. /package/dist/{chunk-OYNHOY45.js → chunk-GAUEVIAE.js} +0 -0
@@ -1,69 +0,0 @@
1
- import * as _nestjs_common from '@nestjs/common';
2
- import { ExecutionContext, DynamicModule } from '@nestjs/common';
3
- import { Reflector } from '@nestjs/core';
4
- import { SuperAdminProvisioningPort, SetupStatusResponse, SetupRequest, SetupResult, SetupConfirmMfaRequest, SetupConfirmMfaResponse } from '@saasicat/core';
5
- import { h as MfaService } from './admin-stats.service-TYiSUwIR.js';
6
- import { e as SaaSiCatModuleOptions } from './module-options-COSEb0VW.js';
7
-
8
- /**
9
- * Shared metadata key for endpoints that intentionally run without application
10
- * authentication. `Symbol.for` keeps the marker stable across package entries.
11
- */
12
- declare const SAASICAT_PUBLIC_ROUTE_KEY: unique symbol;
13
- /** Marks a SaaSiCat controller or handler as intentionally public. */
14
- declare const SaaSiCatPublicRoute: () => _nestjs_common.CustomDecorator<typeof SAASICAT_PUBLIC_ROUTE_KEY>;
15
- /** Returns whether the current endpoint is marked as a public SaaSiCat route. */
16
- declare function isSaaSiCatPublicRoute(reflector: Reflector, context: ExecutionContext): boolean;
17
-
18
- declare const SETUP_PROVISIONING_PORT_TOKEN: unique symbol;
19
- declare const SETUP_CONFIG_TOKEN: unique symbol;
20
- interface SetupConfig {
21
- /** Env-var name of the setup token. Without the var set, setup is disabled. */
22
- setupTokenEnvVar: string;
23
- /** Authenticator issuer for the MFA enrollment in the wizard. */
24
- mfaIssuer: string;
25
- }
26
-
27
- declare class SetupService {
28
- private readonly users;
29
- private readonly config;
30
- private readonly mfa;
31
- constructor(users: SuperAdminProvisioningPort, config: SetupConfig, mfa: MfaService);
32
- status(): Promise<SetupStatusResponse>;
33
- setup(req: SetupRequest): Promise<SetupResult>;
34
- confirmMfa(req: SetupConfirmMfaRequest): Promise<SetupConfirmMfaResponse>;
35
- private assertToken;
36
- private assertNoSuperAdmin;
37
- }
38
-
39
- /**
40
- * Bundles the complete standard SaaSiCat backend stack into a single
41
- * `forRoot({...})` call. Reduces AppModule boilerplate and eliminates the
42
- * ordering trap.
43
- *
44
- * Quickstart path (Prisma + PostgreSQL on the canonical schema):
45
- *
46
- * ```ts
47
- * SaaSiCatModule.forRoot({
48
- * planCatalog: loadPlanCatalogFromFile({ path: 'config/saas.yaml' }),
49
- * controller: { guards: [JwtAuthGuard] },
50
- * imports: [AuthModule],
51
- * persistence: prismaPersistence({ client: PrismaService }), // @saasicat/adapter-prisma
52
- * })
53
- * ```
54
- *
55
- * Individual `adapters` entries stay supported (custom schema / other ORM)
56
- * and override bundle slices field by field.
57
- */
58
- declare class SaaSiCatModule {
59
- static forRoot(options: SaaSiCatModuleOptions): DynamicModule;
60
- }
61
-
62
- /**
63
- * Typed identity helper for the high-level SaaSiCat configuration. It keeps
64
- * literal types and gives editors one place for completion without adding
65
- * runtime behavior.
66
- */
67
- declare function defineSaaSiCat<const T extends SaaSiCatModuleOptions>(options: T): T;
68
-
69
- export { SetupService as S, SAASICAT_PUBLIC_ROUTE_KEY as a, SETUP_CONFIG_TOKEN as b, SETUP_PROVISIONING_PORT_TOKEN as c, SaaSiCatModule as d, SaaSiCatPublicRoute as e, type SetupConfig as f, defineSaaSiCat as g, isSaaSiCatPublicRoute as i };
@@ -1,69 +0,0 @@
1
- import * as _nestjs_common from '@nestjs/common';
2
- import { ExecutionContext, DynamicModule } from '@nestjs/common';
3
- import { Reflector } from '@nestjs/core';
4
- import { SuperAdminProvisioningPort, SetupStatusResponse, SetupRequest, SetupResult, SetupConfirmMfaRequest, SetupConfirmMfaResponse } from '@saasicat/core';
5
- import { h as MfaService } from './admin-stats.service-DfKupywR.cjs';
6
- import { e as SaaSiCatModuleOptions } from './module-options-BG3MzQva.cjs';
7
-
8
- /**
9
- * Shared metadata key for endpoints that intentionally run without application
10
- * authentication. `Symbol.for` keeps the marker stable across package entries.
11
- */
12
- declare const SAASICAT_PUBLIC_ROUTE_KEY: unique symbol;
13
- /** Marks a SaaSiCat controller or handler as intentionally public. */
14
- declare const SaaSiCatPublicRoute: () => _nestjs_common.CustomDecorator<typeof SAASICAT_PUBLIC_ROUTE_KEY>;
15
- /** Returns whether the current endpoint is marked as a public SaaSiCat route. */
16
- declare function isSaaSiCatPublicRoute(reflector: Reflector, context: ExecutionContext): boolean;
17
-
18
- declare const SETUP_PROVISIONING_PORT_TOKEN: unique symbol;
19
- declare const SETUP_CONFIG_TOKEN: unique symbol;
20
- interface SetupConfig {
21
- /** Env-var name of the setup token. Without the var set, setup is disabled. */
22
- setupTokenEnvVar: string;
23
- /** Authenticator issuer for the MFA enrollment in the wizard. */
24
- mfaIssuer: string;
25
- }
26
-
27
- declare class SetupService {
28
- private readonly users;
29
- private readonly config;
30
- private readonly mfa;
31
- constructor(users: SuperAdminProvisioningPort, config: SetupConfig, mfa: MfaService);
32
- status(): Promise<SetupStatusResponse>;
33
- setup(req: SetupRequest): Promise<SetupResult>;
34
- confirmMfa(req: SetupConfirmMfaRequest): Promise<SetupConfirmMfaResponse>;
35
- private assertToken;
36
- private assertNoSuperAdmin;
37
- }
38
-
39
- /**
40
- * Bundles the complete standard SaaSiCat backend stack into a single
41
- * `forRoot({...})` call. Reduces AppModule boilerplate and eliminates the
42
- * ordering trap.
43
- *
44
- * Quickstart path (Prisma + PostgreSQL on the canonical schema):
45
- *
46
- * ```ts
47
- * SaaSiCatModule.forRoot({
48
- * planCatalog: loadPlanCatalogFromFile({ path: 'config/saas.yaml' }),
49
- * controller: { guards: [JwtAuthGuard] },
50
- * imports: [AuthModule],
51
- * persistence: prismaPersistence({ client: PrismaService }), // @saasicat/adapter-prisma
52
- * })
53
- * ```
54
- *
55
- * Individual `adapters` entries stay supported (custom schema / other ORM)
56
- * and override bundle slices field by field.
57
- */
58
- declare class SaaSiCatModule {
59
- static forRoot(options: SaaSiCatModuleOptions): DynamicModule;
60
- }
61
-
62
- /**
63
- * Typed identity helper for the high-level SaaSiCat configuration. It keeps
64
- * literal types and gives editors one place for completion without adding
65
- * runtime behavior.
66
- */
67
- declare function defineSaaSiCat<const T extends SaaSiCatModuleOptions>(options: T): T;
68
-
69
- export { SetupService as S, SAASICAT_PUBLIC_ROUTE_KEY as a, SETUP_CONFIG_TOKEN as b, SETUP_PROVISIONING_PORT_TOKEN as c, SaaSiCatModule as d, SaaSiCatPublicRoute as e, type SetupConfig as f, defineSaaSiCat as g, isSaaSiCatPublicRoute as i };
@@ -1,112 +0,0 @@
1
- import { PromoCodeRepository, PromoCodeRedemptionRepository, PromoCodeValidationLogRepository, FirstTimeCustomerCheck, PromoSubscriptionLookup, PromoRevenueDeductionAggregator, TransactionRunner, PlanCatalog, CreatePromoCodeData, PromoCodeRecord, UpdatePromoCodeData, PromoCodeFilter, PromoCodeRedemptionListItem, BillingCycle, PromoPreviewInvalidReason, PromoCodeRedemptionRecord, TransactionContext } from '@saasicat/core';
2
-
3
- declare const CODE_MIN_LENGTH = 4;
4
- declare const CODE_MAX_LENGTH = 32;
5
- declare const CODE_PATTERN: RegExp;
6
- type PreviewReason = PromoPreviewInvalidReason;
7
- type PreviewInvalid = {
8
- valid: false;
9
- reason: PreviewReason;
10
- };
11
- interface PreviewValid {
12
- valid: true;
13
- code: string;
14
- label: string;
15
- discount: {
16
- valueType: PromoCodeRecord['valueType'];
17
- value: string;
18
- durationType: PromoCodeRecord['durationType'];
19
- durationValue: number | null;
20
- };
21
- price: {
22
- originalGross: string;
23
- discountGross: string;
24
- discountedGross: string;
25
- includedVat: string;
26
- nextRegularAmountGross: string;
27
- regularStartsAt: string | null;
28
- };
29
- }
30
- type PreviewResult = PreviewValid | PreviewInvalid;
31
- interface PreviewInput {
32
- code: string;
33
- planId: string;
34
- billingCycle: BillingCycle;
35
- /** For the firstTimeCustomersOnly check. */
36
- email?: string;
37
- ipHash?: string;
38
- sessionId?: string;
39
- }
40
- interface RedeemInput {
41
- code: string;
42
- subscriptionId: string;
43
- tenantId: string;
44
- /** For the firstTimeCustomersOnly check in the final redeem path. */
45
- email?: string;
46
- }
47
- interface PromoServiceConfig {
48
- /** Plans that are not discountable (e.g. 'ENTERPRISE'). */
49
- nonRedeemablePlans?: readonly string[];
50
- }
51
- interface PromoCodeStats {
52
- code: PromoCodeRecord;
53
- validations: number;
54
- redemptions: {
55
- active: number;
56
- total: number;
57
- reversed: number;
58
- expired: number;
59
- };
60
- /** Decimal-as-string ('0.00' if no aggregator is available). */
61
- revenueDeductionGross: string;
62
- }
63
- declare class PromoCodesService {
64
- private readonly promoRepo;
65
- private readonly redemptionRepo;
66
- private readonly validationLogRepo;
67
- private readonly firstTimeCheck;
68
- private readonly subscriptionLookup;
69
- private readonly revenueAggregator;
70
- private readonly transactionRunner;
71
- private readonly planCatalog;
72
- private readonly config;
73
- constructor(promoRepo: PromoCodeRepository, redemptionRepo: PromoCodeRedemptionRepository, validationLogRepo: PromoCodeValidationLogRepository, firstTimeCheck: FirstTimeCustomerCheck, subscriptionLookup: PromoSubscriptionLookup, revenueAggregator: PromoRevenueDeductionAggregator, transactionRunner: TransactionRunner, planCatalog: PlanCatalog, config: PromoServiceConfig);
74
- create(input: CreatePromoCodeData): Promise<PromoCodeRecord>;
75
- update(id: string, input: UpdatePromoCodeData): Promise<PromoCodeRecord>;
76
- softDelete(id: string): Promise<void>;
77
- findAll(filter?: PromoCodeFilter): Promise<PromoCodeRecord[]>;
78
- findOne(id: string): Promise<PromoCodeRecord>;
79
- stats(id: string): Promise<PromoCodeStats>;
80
- listRedemptions(promoCodeId: string): Promise<PromoCodeRedemptionListItem[]>;
81
- preview(input: PreviewInput): Promise<PreviewResult>;
82
- /**
83
- * Wraps `redeemInTransaction` in its own transaction-runner call —
84
- * the default path when the caller has no external tx context
85
- * (e.g. POST /billing/promo/redeem as a stand-alone endpoint).
86
- */
87
- redeem(input: RedeemInput): Promise<PromoCodeRedemptionRecord>;
88
- /**
89
- * Redeems a promo code within an EXTERNAL transaction — the caller
90
- * (typically `TenantSubscriptionWritePort.applyOnboardingSelection`)
91
- * already has `prisma.$transaction(...)` open and passes the `tx`
92
- * context through. This lands plan change, add-on insert, and redemption
93
- * insert in a single DB transaction (P10.1.1).
94
- */
95
- redeemInTransaction(input: RedeemInput, tx: TransactionContext): Promise<PromoCodeRedemptionRecord>;
96
- reverse(subscriptionId: string): Promise<PromoCodeRedemptionRecord | null>;
97
- private checkEligibility;
98
- private checkFirstTimeCustomer;
99
- /**
100
- * Lazy expiry: sets codes whose validUntil has passed to EXPIRED.
101
- * Called before every find/preview — defense-in-depth alongside the cron.
102
- */
103
- private lazyExpire;
104
- /**
105
- * Lowest applicable plan price. With a whitelist it takes the minimum
106
- * from the whitelist, otherwise across all marketed plans of the catalog
107
- * (except non-redeemable).
108
- */
109
- private lowestApplicablePlanGross;
110
- }
111
-
112
- export { CODE_MAX_LENGTH as C, type PromoServiceConfig as P, type RedeemInput as R, CODE_MIN_LENGTH as a, CODE_PATTERN as b, type PreviewInput as c, type PreviewInvalid as d, type PreviewReason as e, type PreviewResult as f, type PreviewValid as g, type PromoCodeStats as h, PromoCodesService as i };
@@ -1,112 +0,0 @@
1
- import { PromoCodeRepository, PromoCodeRedemptionRepository, PromoCodeValidationLogRepository, FirstTimeCustomerCheck, PromoSubscriptionLookup, PromoRevenueDeductionAggregator, TransactionRunner, PlanCatalog, CreatePromoCodeData, PromoCodeRecord, UpdatePromoCodeData, PromoCodeFilter, PromoCodeRedemptionListItem, BillingCycle, PromoPreviewInvalidReason, PromoCodeRedemptionRecord, TransactionContext } from '@saasicat/core';
2
-
3
- declare const CODE_MIN_LENGTH = 4;
4
- declare const CODE_MAX_LENGTH = 32;
5
- declare const CODE_PATTERN: RegExp;
6
- type PreviewReason = PromoPreviewInvalidReason;
7
- type PreviewInvalid = {
8
- valid: false;
9
- reason: PreviewReason;
10
- };
11
- interface PreviewValid {
12
- valid: true;
13
- code: string;
14
- label: string;
15
- discount: {
16
- valueType: PromoCodeRecord['valueType'];
17
- value: string;
18
- durationType: PromoCodeRecord['durationType'];
19
- durationValue: number | null;
20
- };
21
- price: {
22
- originalGross: string;
23
- discountGross: string;
24
- discountedGross: string;
25
- includedVat: string;
26
- nextRegularAmountGross: string;
27
- regularStartsAt: string | null;
28
- };
29
- }
30
- type PreviewResult = PreviewValid | PreviewInvalid;
31
- interface PreviewInput {
32
- code: string;
33
- planId: string;
34
- billingCycle: BillingCycle;
35
- /** For the firstTimeCustomersOnly check. */
36
- email?: string;
37
- ipHash?: string;
38
- sessionId?: string;
39
- }
40
- interface RedeemInput {
41
- code: string;
42
- subscriptionId: string;
43
- tenantId: string;
44
- /** For the firstTimeCustomersOnly check in the final redeem path. */
45
- email?: string;
46
- }
47
- interface PromoServiceConfig {
48
- /** Plans that are not discountable (e.g. 'ENTERPRISE'). */
49
- nonRedeemablePlans?: readonly string[];
50
- }
51
- interface PromoCodeStats {
52
- code: PromoCodeRecord;
53
- validations: number;
54
- redemptions: {
55
- active: number;
56
- total: number;
57
- reversed: number;
58
- expired: number;
59
- };
60
- /** Decimal-as-string ('0.00' if no aggregator is available). */
61
- revenueDeductionGross: string;
62
- }
63
- declare class PromoCodesService {
64
- private readonly promoRepo;
65
- private readonly redemptionRepo;
66
- private readonly validationLogRepo;
67
- private readonly firstTimeCheck;
68
- private readonly subscriptionLookup;
69
- private readonly revenueAggregator;
70
- private readonly transactionRunner;
71
- private readonly planCatalog;
72
- private readonly config;
73
- constructor(promoRepo: PromoCodeRepository, redemptionRepo: PromoCodeRedemptionRepository, validationLogRepo: PromoCodeValidationLogRepository, firstTimeCheck: FirstTimeCustomerCheck, subscriptionLookup: PromoSubscriptionLookup, revenueAggregator: PromoRevenueDeductionAggregator, transactionRunner: TransactionRunner, planCatalog: PlanCatalog, config: PromoServiceConfig);
74
- create(input: CreatePromoCodeData): Promise<PromoCodeRecord>;
75
- update(id: string, input: UpdatePromoCodeData): Promise<PromoCodeRecord>;
76
- softDelete(id: string): Promise<void>;
77
- findAll(filter?: PromoCodeFilter): Promise<PromoCodeRecord[]>;
78
- findOne(id: string): Promise<PromoCodeRecord>;
79
- stats(id: string): Promise<PromoCodeStats>;
80
- listRedemptions(promoCodeId: string): Promise<PromoCodeRedemptionListItem[]>;
81
- preview(input: PreviewInput): Promise<PreviewResult>;
82
- /**
83
- * Wraps `redeemInTransaction` in its own transaction-runner call —
84
- * the default path when the caller has no external tx context
85
- * (e.g. POST /billing/promo/redeem as a stand-alone endpoint).
86
- */
87
- redeem(input: RedeemInput): Promise<PromoCodeRedemptionRecord>;
88
- /**
89
- * Redeems a promo code within an EXTERNAL transaction — the caller
90
- * (typically `TenantSubscriptionWritePort.applyOnboardingSelection`)
91
- * already has `prisma.$transaction(...)` open and passes the `tx`
92
- * context through. This lands plan change, add-on insert, and redemption
93
- * insert in a single DB transaction (P10.1.1).
94
- */
95
- redeemInTransaction(input: RedeemInput, tx: TransactionContext): Promise<PromoCodeRedemptionRecord>;
96
- reverse(subscriptionId: string): Promise<PromoCodeRedemptionRecord | null>;
97
- private checkEligibility;
98
- private checkFirstTimeCustomer;
99
- /**
100
- * Lazy expiry: sets codes whose validUntil has passed to EXPIRED.
101
- * Called before every find/preview — defense-in-depth alongside the cron.
102
- */
103
- private lazyExpire;
104
- /**
105
- * Lowest applicable plan price. With a whitelist it takes the minimum
106
- * from the whitelist, otherwise across all marketed plans of the catalog
107
- * (except non-redeemable).
108
- */
109
- private lowestApplicablePlanGross;
110
- }
111
-
112
- export { CODE_MAX_LENGTH as C, type PromoServiceConfig as P, type RedeemInput as R, CODE_MIN_LENGTH as a, CODE_PATTERN as b, type PreviewInput as c, type PreviewInvalid as d, type PreviewReason as e, type PreviewResult as f, type PreviewValid as g, type PromoCodeStats as h, PromoCodesService as i };