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

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 (64) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/_entries.cjs +4887 -3609
  3. package/dist/admin/index.js +7 -5
  4. package/dist/{aggregation-ChpZDh0g.d.ts → aggregation-6fPkeV8i.d.ts} +39 -4
  5. package/dist/{aggregation-OpnhwzF5.d.cts → aggregation-DjQUc7yd.d.cts} +39 -4
  6. package/dist/billing/index.d.cts +68 -9
  7. package/dist/billing/index.d.ts +68 -9
  8. package/dist/billing/index.js +16 -5
  9. package/dist/checkout-offer/index.d.cts +2 -2
  10. package/dist/checkout-offer/index.d.ts +2 -2
  11. package/dist/checkout-offer/index.js +4 -4
  12. package/dist/{checkout-offer.service-CCVxG9b2.d.cts → checkout-offer.service-DmVGrT4v.d.cts} +1 -1
  13. package/dist/{checkout-offer.service-BeHgYikI.d.ts → checkout-offer.service-Yi30L4ry.d.ts} +1 -1
  14. package/dist/{chunk-WHJSYKNC.js → chunk-3U4N5UYD.js} +1 -1
  15. package/dist/{chunk-M47BNEY2.js → chunk-3YYLOYUT.js} +1373 -266
  16. package/dist/{chunk-G6EZWECL.js → chunk-B4YP7REK.js} +94 -26
  17. package/dist/{chunk-QPVDCKYS.js → chunk-ESEWSAOV.js} +4 -3
  18. package/dist/{chunk-NDLC5GYK.js → chunk-EU4N5LET.js} +4 -3
  19. package/dist/{chunk-LLYVYRGJ.js → chunk-F2PF4IXB.js} +1 -275
  20. package/dist/{chunk-AOS2JPDD.js → chunk-FJIOHAO5.js} +77 -41
  21. package/dist/{chunk-TOEFN7DN.js → chunk-FPMBQDW7.js} +2 -2
  22. package/dist/chunk-OSOP4KWL.js +288 -0
  23. package/dist/{chunk-3RLWML2S.js → chunk-QWKBOLBH.js} +35 -0
  24. package/dist/{chunk-JBCC6C3M.js → chunk-R3I5X262.js} +5 -4
  25. package/dist/{chunk-4SDSYV4A.js → chunk-T6WXDGIU.js} +1 -1
  26. package/dist/{chunk-R5YCJBHY.js → chunk-U5UPEFWC.js} +2 -2
  27. package/dist/{chunk-XSSWYPP5.js → chunk-UMZCOCT5.js} +1 -1
  28. package/dist/{chunk-7NJKVC5X.js → chunk-WQNOCOI2.js} +53 -6
  29. package/dist/{chunk-55QEDAMX.js → chunk-WTAS2CLM.js} +4 -9
  30. package/dist/{enforce-quota.interceptor-BFyVdWe8.d.cts → enforce-quota.interceptor-B9UhCBXx.d.cts} +2 -2
  31. package/dist/{enforce-quota.interceptor-GaBXboGx.d.ts → enforce-quota.interceptor-CR2waXNA.d.ts} +2 -2
  32. package/dist/entitlement/index.d.cts +1 -1
  33. package/dist/entitlement/index.d.ts +1 -1
  34. package/dist/entitlement/index.js +4 -2
  35. package/dist/index.d.cts +11 -11
  36. package/dist/index.d.ts +11 -11
  37. package/dist/index.js +36 -20
  38. package/dist/{issuer-identity.check-CBO0vcsq.d.cts → issuer-identity.check-BntcNdld.d.cts} +1 -1
  39. package/dist/{issuer-identity.check-Cz9CEMkZ.d.ts → issuer-identity.check-DFmS8whs.d.ts} +1 -1
  40. package/dist/{module-options-qAOwinHR.d.cts → module-options-C4S_StYF.d.cts} +2 -2
  41. package/dist/{module-options-DmQ3G4sZ.d.ts → module-options-DxJI-1iH.d.ts} +2 -2
  42. package/dist/payments/index.js +2 -2
  43. package/dist/platform/index.d.cts +25 -16
  44. package/dist/platform/index.d.ts +25 -16
  45. package/dist/platform/index.js +16 -14
  46. package/dist/promo/index.d.cts +11 -4
  47. package/dist/promo/index.d.ts +11 -4
  48. package/dist/promo/index.js +5 -3
  49. package/dist/{promo.module-CKkECmU8.d.cts → promo.module-Ddx-swUV.d.cts} +1 -1
  50. package/dist/{promo.module-DuIJdK3U.d.ts → promo.module-PsIvDcUp.d.ts} +1 -1
  51. package/dist/{promo.service-BYBu6dy3.d.cts → promo.service-BextPvx5.d.cts} +23 -1
  52. package/dist/{promo.service-CFjfF0Xm.d.ts → promo.service-Dqqh0JXn.d.ts} +23 -1
  53. package/dist/registration/index.d.cts +2 -2
  54. package/dist/registration/index.d.ts +2 -2
  55. package/dist/registration/index.js +5 -5
  56. package/dist/subscription-contract/index.js +2 -2
  57. package/dist/{tenant-billing.controller-DKbAqTbM.d.cts → tenant-billing.controller-BC6-S5cT.d.cts} +91 -10
  58. package/dist/{tenant-billing.controller-BLqbsONe.d.ts → tenant-billing.controller-BuQDQ76i.d.ts} +91 -10
  59. package/dist/{tenant-billing.module-ClbjzocC.d.cts → tenant-billing.module-C6MFfCKq.d.cts} +24 -1
  60. package/dist/{tenant-billing.module-DohgJJ2m.d.ts → tenant-billing.module-CUCQL0-k.d.ts} +24 -1
  61. package/dist/testing/index.d.cts +6 -6
  62. package/dist/testing/index.d.ts +6 -6
  63. package/dist/testing/index.js +33 -31
  64. package/package.json +3 -3
@@ -1,10 +1,10 @@
1
1
  import { CanActivate, ExecutionContext } from '@nestjs/common';
2
2
  import { d as AuthGuardList, a as TrialProjectionPort, P as PendingPlanQueryPort, T as TenantIdResolver, b as UserIdResolver, U as UserEmailResolver, A as AuditContextResolver } from './tenant-billing.tokens-G-1xOlMr.cjs';
3
- import { BillingCycle, CancellationNoticePeriods, SubscriptionUsagePort, UsageSnapshotPort, SelfServiceBlockedPlans, SubscriptionBundleRepository, TenantSubscriptionWritePort, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, PlanRepository, CatalogEntryRepository, SubscriptionUsageRecord, OnboardingSelectionResponse } from '@saasicat/core';
4
- import { c as EntitlementService, a as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-OpnhwzF5.cjs';
5
- import { d as ContractFreezePort, j as SelfServiceBlockedBundles } from './tenant-billing.module-ClbjzocC.cjs';
3
+ import { BillingCycle, CancellationNoticePeriods, SubscriptionUsagePort, UsageSnapshotPort, SelfServiceBlockedPlans, SubscriptionBundleRepository, SubscriptionContractRepository, TenantSubscriptionWritePort, SubscriberLedgerRepository, SubscriberRepository, SubscriberChargeRecord, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, PlanRepository, CatalogEntryRepository, SubscriptionUsageRecord, OnboardingSelectionResponse } from '@saasicat/core';
4
+ import { d as EntitlementService, b as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-DjQUc7yd.cjs';
5
+ import { d as ContractFreezePort, j as SelfServiceBlockedBundles } from './tenant-billing.module-C6MFfCKq.cjs';
6
6
  import { P as PlanCatalogSource } from './plan-catalog-source-DWe-BGY1.cjs';
7
- import { a as PromoCodesService } from './promo.service-BYBu6dy3.cjs';
7
+ import { a as PromoCodesService } from './promo.service-BextPvx5.cjs';
8
8
  import { A as AdminAuditService } from './admin-audit.service-4P3Djdxk.cjs';
9
9
 
10
10
  interface CancellationInput {
@@ -119,7 +119,16 @@ declare class TenantAdminGuard implements CanActivate {
119
119
  canActivate(context: ExecutionContext): boolean;
120
120
  }
121
121
 
122
+ /**
123
+ * How a charge relates to the period already paid.
124
+ *
125
+ * `difference` — the target runs inside it, and the price difference is
126
+ * charged for what is left. `newPeriod` — the target starts a period of its own
127
+ * today, charged in full less the unused remainder of the one it replaces.
128
+ */
129
+ type ProrationBasis = 'difference' | 'newPeriod';
122
130
  interface ProrationDto {
131
+ basis: ProrationBasis;
123
132
  daysRemainingInPeriod: number;
124
133
  daysInPeriod: number;
125
134
  periodStart: Date;
@@ -153,6 +162,12 @@ interface ProrationDto {
153
162
  * them takes that back.
154
163
  */
155
164
  isFree: boolean;
165
+ /**
166
+ * What is left of the replaced period at its own price, net — the amount a
167
+ * `newPeriod` charge is reduced by. Zero on a `difference`, where the
168
+ * remainder is what the difference is taken over.
169
+ */
170
+ remainderNet: number;
156
171
  }
157
172
  interface ProrationInput {
158
173
  periodStart: Date;
@@ -163,6 +178,16 @@ interface ProrationInput {
163
178
  targetPriceNet: number;
164
179
  }
165
180
  declare function computeProration(input: ProrationInput): ProrationDto;
181
+ /**
182
+ * The charge for a target that starts a period of its own today: its full
183
+ * price, less the unused remainder of the period it replaces.
184
+ *
185
+ * `periodStart`/`periodEnd` are the replaced period's, and `currentPriceNet`
186
+ * its price — the remainder is taken at the price that was paid for it. The
187
+ * remainder only reduces this charge: floored at zero like every other
188
+ * proration, it is never paid out.
189
+ */
190
+ declare function computeNewPeriodCharge(input: ProrationInput): ProrationDto;
166
191
 
167
192
  type PlanChangeType = 'UPGRADE' | 'DOWNGRADE' | 'CYCLE_CHANGE' | 'NOOP';
168
193
  /** Where the target plan sits against the running one in the catalog order. */
@@ -294,7 +319,8 @@ declare class PlanChangePreviewService {
294
319
  private readonly blockedPlans;
295
320
  private readonly trialProjection;
296
321
  private readonly subscriptionBundles;
297
- constructor(catalogs: PlanCatalogSource, entitlements: EntitlementService, subscriptions: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, blockedPlans?: SelfServiceBlockedPlans | null, trialProjection?: TrialProjectionPort | null, subscriptionBundles?: SubscriptionBundleRepository | null);
322
+ private readonly contracts;
323
+ constructor(catalogs: PlanCatalogSource, entitlements: EntitlementService, subscriptions: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, blockedPlans?: SelfServiceBlockedPlans | null, trialProjection?: TrialProjectionPort | null, subscriptionBundles?: SubscriptionBundleRepository | null, contracts?: SubscriptionContractRepository | null);
298
324
  preview(tenantId: string, targetPlan: string, targetCycle: string, now?: Date): Promise<PlanChangePreviewDto>;
299
325
  /** Like `preview`, but only the blocker list — for a server-side
300
326
  * pre-check before the `changePlan` mutation (defense-in-depth). */
@@ -323,6 +349,15 @@ declare class PlanChangePreviewService {
323
349
  private planRank;
324
350
  private resolveEffectiveAt;
325
351
  private computeProration;
352
+ /**
353
+ * The net price of the plan line in the contract in force, when it is for
354
+ * `plan` billed in `cycle` — what the customer pays for the period they are
355
+ * in. Null without contracts, or where the line is for another plan or
356
+ * rhythm: a freeze is optional and does not stop the change it follows when
357
+ * it fails, so the contract in force can still describe the plan before.
358
+ * The caller then prices from the catalogue.
359
+ */
360
+ private planPricePaid;
326
361
  }
327
362
 
328
363
  declare class PendingPlanMaterializationService {
@@ -338,6 +373,51 @@ declare class PendingPlanMaterializationService {
338
373
  private tryFreeze;
339
374
  }
340
375
 
376
+ /**
377
+ * Keeps a subscriber's account up to date: the charges its contracts give rise
378
+ * to, one per contract line and period.
379
+ *
380
+ * The platform calls it where it writes a change itself — onboarding, an
381
+ * immediate plan change and an add-on booking. An application calls it where
382
+ * it writes one: when it activates a subscription, and from the job that renews
383
+ * periods. However often it runs, each charge is written once.
384
+ */
385
+ declare class SubscriberChargeService {
386
+ private readonly ledger;
387
+ private readonly contracts;
388
+ private readonly subscribers;
389
+ private readonly subscriptions;
390
+ private readonly bookings;
391
+ private readonly freeze;
392
+ private readonly logger;
393
+ constructor(ledger: SubscriberLedgerRepository, contracts: SubscriptionContractRepository, subscribers: SubscriberRepository, subscriptions: SubscriptionUsagePort, bookings?: SubscriptionBundleRepository | null, freeze?: ContractFreezePort | null);
394
+ /**
395
+ * Writes every charge the tenant's records give rise to by `now` that is
396
+ * not written yet, and returns those.
397
+ *
398
+ * Nothing is charged without a contract (a charge points at a contract
399
+ * line), in a trial, before the plan's current window when the account is
400
+ * still empty, for a period that starts after `now`, or for one that
401
+ * starts on or after the date a cancellation takes effect.
402
+ *
403
+ * A window that moved on before anything charged it is not charged
404
+ * afterwards, so a job that renews periods calls this before it moves a
405
+ * window, and moves it only when the call succeeded.
406
+ */
407
+ recordDueCharges(tenantId: string, now?: Date): Promise<SubscriberChargeRecord[]>;
408
+ /**
409
+ * The tenant's contracts, written once more where the one in force misses
410
+ * a running booking.
411
+ *
412
+ * A booking writes its contract after it is saved, and a failure there does
413
+ * not undo the booking. The booking would then stay uncharged for good,
414
+ * since a charge points at a contract line — so the journal writes the
415
+ * contract the way the booking would have. A failure here is logged and the
416
+ * rest is charged: the next call tries again.
417
+ */
418
+ private contractsNamingEveryBooking;
419
+ }
420
+
341
421
  declare class PreviewPlanChangeDto {
342
422
  plan: string;
343
423
  billingCycle: string;
@@ -487,7 +567,7 @@ declare class SubscriptionBundlesService {
487
567
  * number on the tenant's screen that nobody is charged, and on a yearly
488
568
  * booking it was out by whatever the yearly price is.
489
569
  */
490
- listForSubscription(subscriptionId: string, planKey: string, planCycle: string): Promise<SubscriptionBundleView[]>;
570
+ listForSubscription(subscriptionId: string, planKey: string, planCycle: BillingCycle): Promise<SubscriptionBundleView[]>;
491
571
  /**
492
572
  * List prices for the given bundle versions, in both rhythms, resolved for
493
573
  * one plan.
@@ -546,8 +626,8 @@ interface SubscriptionBundlePreviewContext {
546
626
  subscriptionId: string;
547
627
  /** PlanKey of the current subscription (plan compatibility + redundancy source). */
548
628
  currentPlanKey: string;
549
- /** 'MONTHLY' | 'YEARLY' (port convention). */
550
- billingCycle: string;
629
+ /** The rhythm the plan is billed in. */
630
+ billingCycle: BillingCycle;
551
631
  /** Subscription status (TRIAL/ACTIVE/...). No proration during TRIAL. */
552
632
  status: string;
553
633
  startedAt: Date | null;
@@ -737,7 +817,8 @@ declare class TenantBillingController {
737
817
  private readonly contractFreeze;
738
818
  private readonly trialProjection;
739
819
  private readonly cancellationNoticeDays;
740
- constructor(entitlements: EntitlementService, planPreview: PlanChangePreviewService, subscriptionUsage: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, subscriptionWrite: TenantSubscriptionWritePort, tenantIdResolver?: TenantIdResolver | null, userIdResolver?: UserIdResolver | null, blockedPlans?: SelfServiceBlockedPlans | null, promoCodes?: PromoCodesService | null, auditService?: AdminAuditService | null, userEmailResolver?: UserEmailResolver | null, auditContextResolver?: AuditContextResolver | null, subscriptionBundles?: SubscriptionBundlesService | null, contractFreeze?: ContractFreezePort | null, trialProjection?: TrialProjectionPort | null, cancellationNoticeDays?: CancellationNoticePeriods);
820
+ private readonly charges;
821
+ constructor(entitlements: EntitlementService, planPreview: PlanChangePreviewService, subscriptionUsage: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, subscriptionWrite: TenantSubscriptionWritePort, tenantIdResolver?: TenantIdResolver | null, userIdResolver?: UserIdResolver | null, blockedPlans?: SelfServiceBlockedPlans | null, promoCodes?: PromoCodesService | null, auditService?: AdminAuditService | null, userEmailResolver?: UserEmailResolver | null, auditContextResolver?: AuditContextResolver | null, subscriptionBundles?: SubscriptionBundlesService | null, contractFreeze?: ContractFreezePort | null, trialProjection?: TrialProjectionPort | null, cancellationNoticeDays?: CancellationNoticePeriods, charges?: SubscriberChargeService | null);
741
822
  private readonly logger;
742
823
  getEntitlement(req: RequestLike): Promise<EffectiveLimitsSnapshot>;
743
824
  getUsage(req: RequestLike): Promise<UsageResponse>;
@@ -809,4 +890,4 @@ declare class TenantBillingController {
809
890
  private auditLog;
810
891
  }
811
892
 
812
- export { type AddBundleToSubscriptionInput as A, type BundlePreviewSnapshot as B, type CancelBundleFromSubscriptionInput as C, clampToParent as D, computeProration as E, decideCancellation as F, decideCancellationFor as G, noticeDaysFor as H, resolveBundleCancelEffectiveAt as I, type LimitsCheckRow as L, NO_NOTICE_PERIOD as N, PendingPlanMaterializationService as P, type RedundantFeatureHint as R, type SubscriptionBundleAddPreviewDto as S, TenantAdminGuard as T, type UsageResponse as U, CancelSubscriptionDto as a, type CancellableSubscription as b, type CancellationDecision as c, type CancellationInput as d, ChangePlanDto as e, CompleteOnboardingSubscriptionDto as f, ComposedTenantAuthGuard as g, type CycleDirection as h, type PlanChangeContext as i, type PlanChangePreviewDto as j, type PlanChangePreviewIssue as k, PlanChangePreviewService as l, type PlanChangeType as m, type PlanDirection as n, type PlanSnapshotDto as o, PreviewPlanChangeDto as p, type ProrationDto as q, type ProrationInput as r, type SubscriptionBundleCancelPreviewDto as s, type SubscriptionBundleConfig as t, type SubscriptionBundlePreviewContext as u, type SubscriptionBundlePreviewIssue as v, SubscriptionBundlePreviewService as w, SubscriptionBundlesService as x, TenantBillingController as y, addMonths as z };
893
+ export { type AddBundleToSubscriptionInput as A, type BundlePreviewSnapshot as B, type CancelBundleFromSubscriptionInput as C, TenantBillingController as D, addMonths as E, clampToParent as F, computeNewPeriodCharge as G, computeProration as H, decideCancellation as I, decideCancellationFor as J, noticeDaysFor as K, type LimitsCheckRow as L, resolveBundleCancelEffectiveAt as M, NO_NOTICE_PERIOD as N, PendingPlanMaterializationService as P, type RedundantFeatureHint as R, SubscriberChargeService as S, TenantAdminGuard as T, type UsageResponse as U, CancelSubscriptionDto as a, type CancellableSubscription as b, type CancellationDecision as c, type CancellationInput as d, ChangePlanDto as e, CompleteOnboardingSubscriptionDto as f, ComposedTenantAuthGuard as g, type CycleDirection as h, type PlanChangeContext as i, type PlanChangePreviewDto as j, type PlanChangePreviewIssue as k, PlanChangePreviewService as l, type PlanChangeType as m, type PlanDirection as n, type PlanSnapshotDto as o, PreviewPlanChangeDto as p, type ProrationBasis as q, type ProrationDto as r, type ProrationInput as s, type SubscriptionBundleAddPreviewDto as t, type SubscriptionBundleCancelPreviewDto as u, type SubscriptionBundleConfig as v, type SubscriptionBundlePreviewContext as w, type SubscriptionBundlePreviewIssue as x, SubscriptionBundlePreviewService as y, SubscriptionBundlesService as z };
@@ -1,10 +1,10 @@
1
1
  import { CanActivate, ExecutionContext } from '@nestjs/common';
2
2
  import { d as AuthGuardList, a as TrialProjectionPort, P as PendingPlanQueryPort, T as TenantIdResolver, b as UserIdResolver, U as UserEmailResolver, A as AuditContextResolver } from './tenant-billing.tokens-G-1xOlMr.js';
3
- import { BillingCycle, CancellationNoticePeriods, SubscriptionUsagePort, UsageSnapshotPort, SelfServiceBlockedPlans, SubscriptionBundleRepository, TenantSubscriptionWritePort, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, PlanRepository, CatalogEntryRepository, SubscriptionUsageRecord, OnboardingSelectionResponse } from '@saasicat/core';
4
- import { c as EntitlementService, a as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-ChpZDh0g.js';
5
- import { d as ContractFreezePort, j as SelfServiceBlockedBundles } from './tenant-billing.module-DohgJJ2m.js';
3
+ import { BillingCycle, CancellationNoticePeriods, SubscriptionUsagePort, UsageSnapshotPort, SelfServiceBlockedPlans, SubscriptionBundleRepository, SubscriptionContractRepository, TenantSubscriptionWritePort, SubscriberLedgerRepository, SubscriberRepository, SubscriberChargeRecord, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, PlanRepository, CatalogEntryRepository, SubscriptionUsageRecord, OnboardingSelectionResponse } from '@saasicat/core';
4
+ import { d as EntitlementService, b as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-6fPkeV8i.js';
5
+ import { d as ContractFreezePort, j as SelfServiceBlockedBundles } from './tenant-billing.module-CUCQL0-k.js';
6
6
  import { P as PlanCatalogSource } from './plan-catalog-source-DWe-BGY1.js';
7
- import { a as PromoCodesService } from './promo.service-CFjfF0Xm.js';
7
+ import { a as PromoCodesService } from './promo.service-Dqqh0JXn.js';
8
8
  import { A as AdminAuditService } from './admin-audit.service-4P3Djdxk.js';
9
9
 
10
10
  interface CancellationInput {
@@ -119,7 +119,16 @@ declare class TenantAdminGuard implements CanActivate {
119
119
  canActivate(context: ExecutionContext): boolean;
120
120
  }
121
121
 
122
+ /**
123
+ * How a charge relates to the period already paid.
124
+ *
125
+ * `difference` — the target runs inside it, and the price difference is
126
+ * charged for what is left. `newPeriod` — the target starts a period of its own
127
+ * today, charged in full less the unused remainder of the one it replaces.
128
+ */
129
+ type ProrationBasis = 'difference' | 'newPeriod';
122
130
  interface ProrationDto {
131
+ basis: ProrationBasis;
123
132
  daysRemainingInPeriod: number;
124
133
  daysInPeriod: number;
125
134
  periodStart: Date;
@@ -153,6 +162,12 @@ interface ProrationDto {
153
162
  * them takes that back.
154
163
  */
155
164
  isFree: boolean;
165
+ /**
166
+ * What is left of the replaced period at its own price, net — the amount a
167
+ * `newPeriod` charge is reduced by. Zero on a `difference`, where the
168
+ * remainder is what the difference is taken over.
169
+ */
170
+ remainderNet: number;
156
171
  }
157
172
  interface ProrationInput {
158
173
  periodStart: Date;
@@ -163,6 +178,16 @@ interface ProrationInput {
163
178
  targetPriceNet: number;
164
179
  }
165
180
  declare function computeProration(input: ProrationInput): ProrationDto;
181
+ /**
182
+ * The charge for a target that starts a period of its own today: its full
183
+ * price, less the unused remainder of the period it replaces.
184
+ *
185
+ * `periodStart`/`periodEnd` are the replaced period's, and `currentPriceNet`
186
+ * its price — the remainder is taken at the price that was paid for it. The
187
+ * remainder only reduces this charge: floored at zero like every other
188
+ * proration, it is never paid out.
189
+ */
190
+ declare function computeNewPeriodCharge(input: ProrationInput): ProrationDto;
166
191
 
167
192
  type PlanChangeType = 'UPGRADE' | 'DOWNGRADE' | 'CYCLE_CHANGE' | 'NOOP';
168
193
  /** Where the target plan sits against the running one in the catalog order. */
@@ -294,7 +319,8 @@ declare class PlanChangePreviewService {
294
319
  private readonly blockedPlans;
295
320
  private readonly trialProjection;
296
321
  private readonly subscriptionBundles;
297
- constructor(catalogs: PlanCatalogSource, entitlements: EntitlementService, subscriptions: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, blockedPlans?: SelfServiceBlockedPlans | null, trialProjection?: TrialProjectionPort | null, subscriptionBundles?: SubscriptionBundleRepository | null);
322
+ private readonly contracts;
323
+ constructor(catalogs: PlanCatalogSource, entitlements: EntitlementService, subscriptions: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, blockedPlans?: SelfServiceBlockedPlans | null, trialProjection?: TrialProjectionPort | null, subscriptionBundles?: SubscriptionBundleRepository | null, contracts?: SubscriptionContractRepository | null);
298
324
  preview(tenantId: string, targetPlan: string, targetCycle: string, now?: Date): Promise<PlanChangePreviewDto>;
299
325
  /** Like `preview`, but only the blocker list — for a server-side
300
326
  * pre-check before the `changePlan` mutation (defense-in-depth). */
@@ -323,6 +349,15 @@ declare class PlanChangePreviewService {
323
349
  private planRank;
324
350
  private resolveEffectiveAt;
325
351
  private computeProration;
352
+ /**
353
+ * The net price of the plan line in the contract in force, when it is for
354
+ * `plan` billed in `cycle` — what the customer pays for the period they are
355
+ * in. Null without contracts, or where the line is for another plan or
356
+ * rhythm: a freeze is optional and does not stop the change it follows when
357
+ * it fails, so the contract in force can still describe the plan before.
358
+ * The caller then prices from the catalogue.
359
+ */
360
+ private planPricePaid;
326
361
  }
327
362
 
328
363
  declare class PendingPlanMaterializationService {
@@ -338,6 +373,51 @@ declare class PendingPlanMaterializationService {
338
373
  private tryFreeze;
339
374
  }
340
375
 
376
+ /**
377
+ * Keeps a subscriber's account up to date: the charges its contracts give rise
378
+ * to, one per contract line and period.
379
+ *
380
+ * The platform calls it where it writes a change itself — onboarding, an
381
+ * immediate plan change and an add-on booking. An application calls it where
382
+ * it writes one: when it activates a subscription, and from the job that renews
383
+ * periods. However often it runs, each charge is written once.
384
+ */
385
+ declare class SubscriberChargeService {
386
+ private readonly ledger;
387
+ private readonly contracts;
388
+ private readonly subscribers;
389
+ private readonly subscriptions;
390
+ private readonly bookings;
391
+ private readonly freeze;
392
+ private readonly logger;
393
+ constructor(ledger: SubscriberLedgerRepository, contracts: SubscriptionContractRepository, subscribers: SubscriberRepository, subscriptions: SubscriptionUsagePort, bookings?: SubscriptionBundleRepository | null, freeze?: ContractFreezePort | null);
394
+ /**
395
+ * Writes every charge the tenant's records give rise to by `now` that is
396
+ * not written yet, and returns those.
397
+ *
398
+ * Nothing is charged without a contract (a charge points at a contract
399
+ * line), in a trial, before the plan's current window when the account is
400
+ * still empty, for a period that starts after `now`, or for one that
401
+ * starts on or after the date a cancellation takes effect.
402
+ *
403
+ * A window that moved on before anything charged it is not charged
404
+ * afterwards, so a job that renews periods calls this before it moves a
405
+ * window, and moves it only when the call succeeded.
406
+ */
407
+ recordDueCharges(tenantId: string, now?: Date): Promise<SubscriberChargeRecord[]>;
408
+ /**
409
+ * The tenant's contracts, written once more where the one in force misses
410
+ * a running booking.
411
+ *
412
+ * A booking writes its contract after it is saved, and a failure there does
413
+ * not undo the booking. The booking would then stay uncharged for good,
414
+ * since a charge points at a contract line — so the journal writes the
415
+ * contract the way the booking would have. A failure here is logged and the
416
+ * rest is charged: the next call tries again.
417
+ */
418
+ private contractsNamingEveryBooking;
419
+ }
420
+
341
421
  declare class PreviewPlanChangeDto {
342
422
  plan: string;
343
423
  billingCycle: string;
@@ -487,7 +567,7 @@ declare class SubscriptionBundlesService {
487
567
  * number on the tenant's screen that nobody is charged, and on a yearly
488
568
  * booking it was out by whatever the yearly price is.
489
569
  */
490
- listForSubscription(subscriptionId: string, planKey: string, planCycle: string): Promise<SubscriptionBundleView[]>;
570
+ listForSubscription(subscriptionId: string, planKey: string, planCycle: BillingCycle): Promise<SubscriptionBundleView[]>;
491
571
  /**
492
572
  * List prices for the given bundle versions, in both rhythms, resolved for
493
573
  * one plan.
@@ -546,8 +626,8 @@ interface SubscriptionBundlePreviewContext {
546
626
  subscriptionId: string;
547
627
  /** PlanKey of the current subscription (plan compatibility + redundancy source). */
548
628
  currentPlanKey: string;
549
- /** 'MONTHLY' | 'YEARLY' (port convention). */
550
- billingCycle: string;
629
+ /** The rhythm the plan is billed in. */
630
+ billingCycle: BillingCycle;
551
631
  /** Subscription status (TRIAL/ACTIVE/...). No proration during TRIAL. */
552
632
  status: string;
553
633
  startedAt: Date | null;
@@ -737,7 +817,8 @@ declare class TenantBillingController {
737
817
  private readonly contractFreeze;
738
818
  private readonly trialProjection;
739
819
  private readonly cancellationNoticeDays;
740
- constructor(entitlements: EntitlementService, planPreview: PlanChangePreviewService, subscriptionUsage: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, subscriptionWrite: TenantSubscriptionWritePort, tenantIdResolver?: TenantIdResolver | null, userIdResolver?: UserIdResolver | null, blockedPlans?: SelfServiceBlockedPlans | null, promoCodes?: PromoCodesService | null, auditService?: AdminAuditService | null, userEmailResolver?: UserEmailResolver | null, auditContextResolver?: AuditContextResolver | null, subscriptionBundles?: SubscriptionBundlesService | null, contractFreeze?: ContractFreezePort | null, trialProjection?: TrialProjectionPort | null, cancellationNoticeDays?: CancellationNoticePeriods);
820
+ private readonly charges;
821
+ constructor(entitlements: EntitlementService, planPreview: PlanChangePreviewService, subscriptionUsage: SubscriptionUsagePort, usageSnapshot: UsageSnapshotPort, subscriptionWrite: TenantSubscriptionWritePort, tenantIdResolver?: TenantIdResolver | null, userIdResolver?: UserIdResolver | null, blockedPlans?: SelfServiceBlockedPlans | null, promoCodes?: PromoCodesService | null, auditService?: AdminAuditService | null, userEmailResolver?: UserEmailResolver | null, auditContextResolver?: AuditContextResolver | null, subscriptionBundles?: SubscriptionBundlesService | null, contractFreeze?: ContractFreezePort | null, trialProjection?: TrialProjectionPort | null, cancellationNoticeDays?: CancellationNoticePeriods, charges?: SubscriberChargeService | null);
741
822
  private readonly logger;
742
823
  getEntitlement(req: RequestLike): Promise<EffectiveLimitsSnapshot>;
743
824
  getUsage(req: RequestLike): Promise<UsageResponse>;
@@ -809,4 +890,4 @@ declare class TenantBillingController {
809
890
  private auditLog;
810
891
  }
811
892
 
812
- export { type AddBundleToSubscriptionInput as A, type BundlePreviewSnapshot as B, type CancelBundleFromSubscriptionInput as C, clampToParent as D, computeProration as E, decideCancellation as F, decideCancellationFor as G, noticeDaysFor as H, resolveBundleCancelEffectiveAt as I, type LimitsCheckRow as L, NO_NOTICE_PERIOD as N, PendingPlanMaterializationService as P, type RedundantFeatureHint as R, type SubscriptionBundleAddPreviewDto as S, TenantAdminGuard as T, type UsageResponse as U, CancelSubscriptionDto as a, type CancellableSubscription as b, type CancellationDecision as c, type CancellationInput as d, ChangePlanDto as e, CompleteOnboardingSubscriptionDto as f, ComposedTenantAuthGuard as g, type CycleDirection as h, type PlanChangeContext as i, type PlanChangePreviewDto as j, type PlanChangePreviewIssue as k, PlanChangePreviewService as l, type PlanChangeType as m, type PlanDirection as n, type PlanSnapshotDto as o, PreviewPlanChangeDto as p, type ProrationDto as q, type ProrationInput as r, type SubscriptionBundleCancelPreviewDto as s, type SubscriptionBundleConfig as t, type SubscriptionBundlePreviewContext as u, type SubscriptionBundlePreviewIssue as v, SubscriptionBundlePreviewService as w, SubscriptionBundlesService as x, TenantBillingController as y, addMonths as z };
893
+ export { type AddBundleToSubscriptionInput as A, type BundlePreviewSnapshot as B, type CancelBundleFromSubscriptionInput as C, TenantBillingController as D, addMonths as E, clampToParent as F, computeNewPeriodCharge as G, computeProration as H, decideCancellation as I, decideCancellationFor as J, noticeDaysFor as K, type LimitsCheckRow as L, resolveBundleCancelEffectiveAt as M, NO_NOTICE_PERIOD as N, PendingPlanMaterializationService as P, type RedundantFeatureHint as R, SubscriberChargeService as S, TenantAdminGuard as T, type UsageResponse as U, CancelSubscriptionDto as a, type CancellableSubscription as b, type CancellationDecision as c, type CancellationInput as d, ChangePlanDto as e, CompleteOnboardingSubscriptionDto as f, ComposedTenantAuthGuard as g, type CycleDirection as h, type PlanChangeContext as i, type PlanChangePreviewDto as j, type PlanChangePreviewIssue as k, PlanChangePreviewService as l, type PlanChangeType as m, type PlanDirection as n, type PlanSnapshotDto as o, PreviewPlanChangeDto as p, type ProrationBasis as q, type ProrationDto as r, type ProrationInput as s, type SubscriptionBundleAddPreviewDto as t, type SubscriptionBundleCancelPreviewDto as u, type SubscriptionBundleConfig as v, type SubscriptionBundlePreviewContext as w, type SubscriptionBundlePreviewIssue as x, SubscriptionBundlePreviewService as y, SubscriptionBundlesService as z };
@@ -1,4 +1,4 @@
1
- import { PlanCatalog, BillingCycle, PlanVersionRow, SubscriptionUsagePort, SubscriptionBundleRepository, BundleRepository, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionContractRepository, SubscriberRepository } from '@saasicat/core';
1
+ import { PlanCatalog, BillingCycle, PlanVersionRow, SubscriptionUsagePort, SubscriptionBundleRepository, BundleRepository, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionContractRepository, SubscriberRepository, SubscriberLedgerRepository } from '@saasicat/core';
2
2
  import { Type, CanActivate, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
3
3
  import { P as ProviderSpec } from './di-CcNeq9v-.cjs';
4
4
  import { T as TenantIdResolver, a as TrialProjectionPort, P as PendingPlanQueryPort, b as UserIdResolver, U as UserEmailResolver, A as AuditContextResolver } from './tenant-billing.tokens-G-1xOlMr.cjs';
@@ -198,12 +198,21 @@ interface ContractFreezeSourcePort {
198
198
  * The tenant's active (non-terminated) bundle bookings as line items,
199
199
  * priced in net. Apps without a bundle schema return empty lists.
200
200
  *
201
+ * A booking whose cancellation is declared is still active until its
202
+ * effective date, and it belongs here while it is billed. Its line does not
203
+ * put it into the contract's entitlements: the freeze leaves it out of the
204
+ * snapshot, and the booking grants its features and quotas until that date.
205
+ *
201
206
  * `cycle` is the **plan's** rhythm, not the bookings'. A tenant on a yearly
202
207
  * plan may hold monthly add-ons, so a source prices each booking in the
203
208
  * rhythm that booking was made in and says which one that is on the line's
204
209
  * own `billingCycle`. Pricing every line in the plan's rhythm puts a figure
205
210
  * on the contract that nobody is charged, and the contract is the evidence
206
211
  * of what was agreed.
212
+ *
213
+ * Each line names its booking's bundle version as `sourceVersionId`. The
214
+ * charge journal finds a booking's contract line by it, and a line without
215
+ * it leaves the booking uncharged.
207
216
  */
208
217
  loadBookedBundles(tenantId: string, cycle: 'monthly' | 'yearly'): Promise<ContractFreezeBundleSnapshot>;
209
218
  }
@@ -323,6 +332,20 @@ interface TenantBillingModuleOptions {
323
332
  */
324
333
  subscriberRepository: ProviderSpec<SubscriberRepository>;
325
334
  };
335
+ /**
336
+ * Optional journal of the charges each subscriber's contracts give rise to
337
+ * (`SubscriberChargeService`). Needs `contractFreeze`: a charge points at a
338
+ * contract line, and the contracts and subscribers come from there.
339
+ *
340
+ * The platform brings an account up to date after onboarding, an
341
+ * immediate plan change and an add-on booking; an application calls
342
+ * `recordDueCharges` where it writes a change itself — at activation and
343
+ * from its renewal job. `SubscriberAccountService` reads an account back
344
+ * for the operator.
345
+ */
346
+ chargeJournal?: {
347
+ ledgerRepository: ProviderSpec<SubscriberLedgerRepository>;
348
+ };
326
349
  /** Optional tenant ID resolver. Default: `req.user.tenantId`. */
327
350
  tenantIdResolver?: TenantIdResolver;
328
351
  /** Optional user ID resolver. Default: `req.user.sub ?? req.user.id`. */
@@ -1,4 +1,4 @@
1
- import { PlanCatalog, BillingCycle, PlanVersionRow, SubscriptionUsagePort, SubscriptionBundleRepository, BundleRepository, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionContractRepository, SubscriberRepository } from '@saasicat/core';
1
+ import { PlanCatalog, BillingCycle, PlanVersionRow, SubscriptionUsagePort, SubscriptionBundleRepository, BundleRepository, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionContractRepository, SubscriberRepository, SubscriberLedgerRepository } from '@saasicat/core';
2
2
  import { Type, CanActivate, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
3
3
  import { P as ProviderSpec } from './di-CcNeq9v-.js';
4
4
  import { T as TenantIdResolver, a as TrialProjectionPort, P as PendingPlanQueryPort, b as UserIdResolver, U as UserEmailResolver, A as AuditContextResolver } from './tenant-billing.tokens-G-1xOlMr.js';
@@ -198,12 +198,21 @@ interface ContractFreezeSourcePort {
198
198
  * The tenant's active (non-terminated) bundle bookings as line items,
199
199
  * priced in net. Apps without a bundle schema return empty lists.
200
200
  *
201
+ * A booking whose cancellation is declared is still active until its
202
+ * effective date, and it belongs here while it is billed. Its line does not
203
+ * put it into the contract's entitlements: the freeze leaves it out of the
204
+ * snapshot, and the booking grants its features and quotas until that date.
205
+ *
201
206
  * `cycle` is the **plan's** rhythm, not the bookings'. A tenant on a yearly
202
207
  * plan may hold monthly add-ons, so a source prices each booking in the
203
208
  * rhythm that booking was made in and says which one that is on the line's
204
209
  * own `billingCycle`. Pricing every line in the plan's rhythm puts a figure
205
210
  * on the contract that nobody is charged, and the contract is the evidence
206
211
  * of what was agreed.
212
+ *
213
+ * Each line names its booking's bundle version as `sourceVersionId`. The
214
+ * charge journal finds a booking's contract line by it, and a line without
215
+ * it leaves the booking uncharged.
207
216
  */
208
217
  loadBookedBundles(tenantId: string, cycle: 'monthly' | 'yearly'): Promise<ContractFreezeBundleSnapshot>;
209
218
  }
@@ -323,6 +332,20 @@ interface TenantBillingModuleOptions {
323
332
  */
324
333
  subscriberRepository: ProviderSpec<SubscriberRepository>;
325
334
  };
335
+ /**
336
+ * Optional journal of the charges each subscriber's contracts give rise to
337
+ * (`SubscriberChargeService`). Needs `contractFreeze`: a charge points at a
338
+ * contract line, and the contracts and subscribers come from there.
339
+ *
340
+ * The platform brings an account up to date after onboarding, an
341
+ * immediate plan change and an add-on booking; an application calls
342
+ * `recordDueCharges` where it writes a change itself — at activation and
343
+ * from its renewal job. `SubscriberAccountService` reads an account back
344
+ * for the operator.
345
+ */
346
+ chargeJournal?: {
347
+ ledgerRepository: ProviderSpec<SubscriberLedgerRepository>;
348
+ };
326
349
  /** Optional tenant ID resolver. Default: `req.user.tenantId`. */
327
350
  tenantIdResolver?: TenantIdResolver;
328
351
  /** Optional user ID resolver. Default: `req.user.sub ?? req.user.id`. */
@@ -1,20 +1,20 @@
1
1
  import { BundleRepository, BundleRow, BundleVersionRow, BundleListFilter, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange, MarketingProjectionRepository, MarketingProjectionRow, MarketingProjectionFilter, CreateMarketingProjectionData, UpdateMarketingProjectionData, PlanRepository, PlanRow, PlanVersionRow, PlanListFilter, CreatePlanData, UpdatePlanData, CreatePlanVersionDraftData, UpdatePlanVersionDraftData, PlanVersionRepository, PlanVersionRecord, TransactionContext, SubscriberRepository, CreateSubscriberData, SubscriberRecord, SubscriberContactChange, SubscriberCorrectionData, SubscriberCorrectionResult, SubscriberCorrectionRecord, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, NewSubscriptionContractData, TerminateSubscriptionContractData, RunningContractIssuers, SubscriptionRepository, SubscriptionRecord, TransactionRunner, PlanCatalog, QuotaProvider } from '@saasicat/core';
2
2
  import { Type, DynamicModule } from '@nestjs/common';
3
- import { S as SaaSiCatAdapters } from '../module-options-qAOwinHR.cjs';
4
- export { P as PLAN_RESOLVER_PORT_TOKEN, a as StaticPlanResolver } from '../module-options-qAOwinHR.cjs';
5
- export { E as EnforceQuotaInterceptor, S as StaticEntitlementService, a as StaticFeatureGuard } from '../enforce-quota.interceptor-BFyVdWe8.cjs';
3
+ import { S as SaaSiCatAdapters } from '../module-options-C4S_StYF.cjs';
4
+ export { P as PLAN_RESOLVER_PORT_TOKEN, a as StaticPlanResolver } from '../module-options-C4S_StYF.cjs';
5
+ export { E as EnforceQuotaInterceptor, S as StaticEntitlementService, a as StaticFeatureGuard } from '../enforce-quota.interceptor-B9UhCBXx.cjs';
6
6
  import '../di-CcNeq9v-.cjs';
7
7
  import '../admin-resources.module-B4XNvdH-.cjs';
8
8
  import '../admin-audit.service-4P3Djdxk.cjs';
9
- import '../tenant-billing.module-ClbjzocC.cjs';
9
+ import '../tenant-billing.module-C6MFfCKq.cjs';
10
10
  import '../tenant-billing.tokens-G-1xOlMr.cjs';
11
11
  import '../contract-line-item-money-B0Z3Ogur.cjs';
12
12
  import '../catalog.module-T-I5Ricz.cjs';
13
13
  import '../discovery.scanner-DXKc6JkV.cjs';
14
14
  import '@nestjs/core';
15
15
  import '../plan-resolution-CwUy_OqC.cjs';
16
- import '../promo.module-CKkECmU8.cjs';
17
- import '../promo.service-BYBu6dy3.cjs';
16
+ import '../promo.module-Ddx-swUV.cjs';
17
+ import '../promo.service-BextPvx5.cjs';
18
18
  import '../plan-catalog-source-DWe-BGY1.cjs';
19
19
  import '../checkout-offer.module-DFhGy6JO.cjs';
20
20
  import '../payments.module-BdUq9ot_.cjs';
@@ -1,20 +1,20 @@
1
1
  import { BundleRepository, BundleRow, BundleVersionRow, BundleListFilter, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, UpdateBundleVersionDraftData, VersionChange, MarketingProjectionRepository, MarketingProjectionRow, MarketingProjectionFilter, CreateMarketingProjectionData, UpdateMarketingProjectionData, PlanRepository, PlanRow, PlanVersionRow, PlanListFilter, CreatePlanData, UpdatePlanData, CreatePlanVersionDraftData, UpdatePlanVersionDraftData, PlanVersionRepository, PlanVersionRecord, TransactionContext, SubscriberRepository, CreateSubscriberData, SubscriberRecord, SubscriberContactChange, SubscriberCorrectionData, SubscriberCorrectionResult, SubscriberCorrectionRecord, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, NewSubscriptionContractData, TerminateSubscriptionContractData, RunningContractIssuers, SubscriptionRepository, SubscriptionRecord, TransactionRunner, PlanCatalog, QuotaProvider } from '@saasicat/core';
2
2
  import { Type, DynamicModule } from '@nestjs/common';
3
- import { S as SaaSiCatAdapters } from '../module-options-DmQ3G4sZ.js';
4
- export { P as PLAN_RESOLVER_PORT_TOKEN, a as StaticPlanResolver } from '../module-options-DmQ3G4sZ.js';
5
- export { E as EnforceQuotaInterceptor, S as StaticEntitlementService, a as StaticFeatureGuard } from '../enforce-quota.interceptor-GaBXboGx.js';
3
+ import { S as SaaSiCatAdapters } from '../module-options-DxJI-1iH.js';
4
+ export { P as PLAN_RESOLVER_PORT_TOKEN, a as StaticPlanResolver } from '../module-options-DxJI-1iH.js';
5
+ export { E as EnforceQuotaInterceptor, S as StaticEntitlementService, a as StaticFeatureGuard } from '../enforce-quota.interceptor-CR2waXNA.js';
6
6
  import '../di-CcNeq9v-.js';
7
7
  import '../admin-resources.module-CWqdI9BV.js';
8
8
  import '../admin-audit.service-4P3Djdxk.js';
9
- import '../tenant-billing.module-DohgJJ2m.js';
9
+ import '../tenant-billing.module-CUCQL0-k.js';
10
10
  import '../tenant-billing.tokens-G-1xOlMr.js';
11
11
  import '../contract-line-item-money-B0Z3Ogur.js';
12
12
  import '../catalog.module-C9O7BxRq.js';
13
13
  import '../discovery.scanner-DXKc6JkV.js';
14
14
  import '@nestjs/core';
15
15
  import '../plan-resolution-CwUy_OqC.js';
16
- import '../promo.module-DuIJdK3U.js';
17
- import '../promo.service-CFjfF0Xm.js';
16
+ import '../promo.module-PsIvDcUp.js';
17
+ import '../promo.service-Dqqh0JXn.js';
18
18
  import '../plan-catalog-source-DWe-BGY1.js';
19
19
  import '../checkout-offer.module-x7SP_dX4.js';
20
20
  import '../payments.module-CQGv_VG7.js';
@@ -5,32 +5,33 @@ import {
5
5
  StaticEntitlementService,
6
6
  StaticFeatureGuard,
7
7
  StaticPlanResolver
8
- } from "../chunk-AOS2JPDD.js";
9
- import "../chunk-4SDSYV4A.js";
10
- import "../chunk-XSSWYPP5.js";
11
- import "../chunk-LLYVYRGJ.js";
12
- import "../chunk-M47BNEY2.js";
8
+ } from "../chunk-FJIOHAO5.js";
9
+ import "../chunk-T6WXDGIU.js";
10
+ import "../chunk-UMZCOCT5.js";
11
+ import "../chunk-F2PF4IXB.js";
12
+ import "../chunk-3YYLOYUT.js";
13
+ import "../chunk-OSOP4KWL.js";
13
14
  import "../chunk-CQ2ZZMTD.js";
14
15
  import "../chunk-GZTL64QK.js";
15
16
  import "../chunk-34XVPR6P.js";
16
17
  import "../chunk-OOTEXP47.js";
17
- import "../chunk-TOEFN7DN.js";
18
- import "../chunk-55QEDAMX.js";
19
- import "../chunk-3RLWML2S.js";
20
- import "../chunk-NDLC5GYK.js";
18
+ import "../chunk-FPMBQDW7.js";
19
+ import "../chunk-WTAS2CLM.js";
20
+ import "../chunk-QWKBOLBH.js";
21
+ import "../chunk-EU4N5LET.js";
21
22
  import "../chunk-KPEMTBOP.js";
22
23
  import "../chunk-S33SO5XX.js";
23
24
  import "../chunk-JVAEKTJ4.js";
24
- import "../chunk-WHJSYKNC.js";
25
- import "../chunk-G6EZWECL.js";
25
+ import "../chunk-3U4N5UYD.js";
26
+ import "../chunk-B4YP7REK.js";
26
27
  import "../chunk-OUDSQ3PU.js";
27
28
  import "../chunk-TBBZWZQT.js";
28
29
  import "../chunk-VBRYPU7V.js";
29
30
  import "../chunk-6PJE7EWO.js";
30
31
  import "../chunk-3QVGA6JX.js";
31
32
  import "../chunk-QUZU2M33.js";
32
- import "../chunk-QPVDCKYS.js";
33
- import "../chunk-7NJKVC5X.js";
33
+ import "../chunk-ESEWSAOV.js";
34
+ import "../chunk-WQNOCOI2.js";
34
35
  import "../chunk-5CKC7O52.js";
35
36
  import "../chunk-GPQWGA6B.js";
36
37
  import "../chunk-SZ7RFPXA.js";
@@ -233,15 +234,7 @@ var FakeSubscriptionContractRepository = class {
233
234
  originalBundleVersionIds: [
234
235
  ...data.originalBundleVersionIds ?? []
235
236
  ],
236
- entitlementSnapshot: data.entitlementSnapshot ? {
237
- plan: data.entitlementSnapshot.plan,
238
- quotas: {
239
- ...data.entitlementSnapshot.quotas
240
- },
241
- features: [
242
- ...data.entitlementSnapshot.features
243
- ]
244
- } : null,
237
+ entitlementSnapshot: data.entitlementSnapshot ? cloneEntitlementSnapshot(data.entitlementSnapshot) : null,
245
238
  priceSnapshot: {
246
239
  ...data.priceSnapshot
247
240
  },
@@ -322,15 +315,7 @@ var FakeSubscriptionContractRepository = class {
322
315
  originalBundleVersionIds: [
323
316
  ...row.originalBundleVersionIds
324
317
  ],
325
- entitlementSnapshot: row.entitlementSnapshot ? {
326
- plan: row.entitlementSnapshot.plan,
327
- quotas: {
328
- ...row.entitlementSnapshot.quotas
329
- },
330
- features: [
331
- ...row.entitlementSnapshot.features
332
- ]
333
- } : null,
318
+ entitlementSnapshot: row.entitlementSnapshot ? cloneEntitlementSnapshot(row.entitlementSnapshot) : null,
334
319
  priceSnapshot: {
335
320
  ...row.priceSnapshot
336
321
  },
@@ -1069,6 +1054,23 @@ var FakePlanRepository = class {
1069
1054
  return updated;
1070
1055
  }
1071
1056
  };
1057
+ function cloneEntitlementSnapshot(snapshot) {
1058
+ return {
1059
+ plan: snapshot.plan,
1060
+ quotas: {
1061
+ ...snapshot.quotas
1062
+ },
1063
+ features: [
1064
+ ...snapshot.features
1065
+ ],
1066
+ ...snapshot.leftOutBundleVersionIds ? {
1067
+ leftOutBundleVersionIds: [
1068
+ ...snapshot.leftOutBundleVersionIds
1069
+ ]
1070
+ } : {}
1071
+ };
1072
+ }
1073
+ __name(cloneEntitlementSnapshot, "cloneEntitlementSnapshot");
1072
1074
 
1073
1075
  // src/testing/create-saasicat-test-module.ts
1074
1076
  import { Module } from "@nestjs/common";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/nest",
3
- "version": "1.0.0-rc.21",
3
+ "version": "1.0.0-rc.22",
4
4
  "description": "NestJS implementation of SaaSiCat: capability discovery, catalog packaging, contracts, entitlement enforcement, billing and admin APIs.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -158,8 +158,8 @@
158
158
  "js-yaml": "^4.3.2",
159
159
  "otplib": "^13.4.1",
160
160
  "qrcode": "^1.5.4",
161
- "@saasicat/spec": "^1.0.0-rc.21",
162
- "@saasicat/core": "^1.0.0-rc.21"
161
+ "@saasicat/spec": "^1.0.0-rc.22",
162
+ "@saasicat/core": "^1.0.0-rc.22"
163
163
  },
164
164
  "peerDependencies": {
165
165
  "@nestjs/common": "^11.0.0",