@saasicat/nest 0.13.0 → 0.15.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 (63) hide show
  1. package/dist/_entries.cjs +1529 -1345
  2. package/dist/admin/index.d.cts +8 -6
  3. package/dist/admin/index.d.ts +8 -6
  4. package/dist/admin/index.js +13 -12
  5. package/dist/{admin-resources.module-Cms8MY6h.d.ts → admin-resources.module-BY5r_1MG.d.ts} +29 -3
  6. package/dist/{admin-resources.module-BZN_yBFj.d.cts → admin-resources.module-DGgGSdzN.d.cts} +29 -3
  7. package/dist/{admin-stats.module-15ac5KY3.d.ts → admin-stats.service-Db2exT_d.d.ts} +2 -23
  8. package/dist/{admin-stats.module-v4SVvWzj.d.cts → admin-stats.service-HUZIU448.d.cts} +2 -23
  9. package/dist/{aggregation-CfI0bOsQ.d.cts → aggregation-SKfXu09x.d.cts} +35 -3
  10. package/dist/{aggregation-BibpEO0t.d.ts → aggregation-o0LMenvl.d.ts} +35 -3
  11. package/dist/billing/index.d.cts +2 -2
  12. package/dist/billing/index.d.ts +2 -2
  13. package/dist/billing/index.js +4 -3
  14. package/dist/catalog/index.js +3 -2
  15. package/dist/checkout-offer/index.d.cts +2 -1
  16. package/dist/checkout-offer/index.d.ts +2 -1
  17. package/dist/checkout-offer/index.js +2 -1
  18. package/dist/checkout-offer.module-Ca3_TieR.d.ts +39 -0
  19. package/dist/checkout-offer.module-DmlpPevf.d.cts +39 -0
  20. package/dist/{checkout-offer.module-Y0hDOVrq.d.ts → checkout-offer.service-BX51dljL.d.cts} +1 -37
  21. package/dist/{checkout-offer.module-ZYF5IsDY.d.cts → checkout-offer.service-BX51dljL.d.ts} +1 -37
  22. package/dist/{chunk-2PNX2QL2.js → chunk-32EMXPU2.js} +1 -0
  23. package/dist/{chunk-DVFPKVLO.js → chunk-5KH2O4SF.js} +16 -4
  24. package/dist/{chunk-TXDH4FUA.js → chunk-7RRWI5LH.js} +1 -1
  25. package/dist/chunk-EWPF57AG.js +13 -0
  26. package/dist/{chunk-2WNM5THV.js → chunk-EXOLOJFZ.js} +58 -15
  27. package/dist/{chunk-HBFU5AN3.js → chunk-GJBXOCRZ.js} +4 -0
  28. package/dist/{chunk-IRWZC3GC.js → chunk-GLLCB4BP.js} +4 -0
  29. package/dist/{chunk-33TP26MR.js → chunk-P3DP6GJE.js} +4 -0
  30. package/dist/{chunk-FVT7KTUI.js → chunk-PLJEAUFU.js} +275 -61
  31. package/dist/{chunk-J3BMIR4W.js → chunk-YITTE646.js} +463 -83
  32. package/dist/chunk-YSC46BGM.js +21 -0
  33. package/dist/define-saasicat-CeDBX9ji.d.cts +46 -0
  34. package/dist/define-saasicat-Rc0rXrYG.d.ts +46 -0
  35. package/dist/enforce-quota.interceptor-CmbWX39L.d.ts +60 -0
  36. package/dist/enforce-quota.interceptor-DMw-bPyk.d.cts +60 -0
  37. package/dist/entitlement/index.d.cts +1 -1
  38. package/dist/entitlement/index.d.ts +1 -1
  39. package/dist/entitlement/index.js +7 -1
  40. package/dist/index.d.cts +12 -10
  41. package/dist/index.d.ts +12 -10
  42. package/dist/index.js +40 -19
  43. package/dist/platform/index.d.cts +13 -17
  44. package/dist/platform/index.d.ts +13 -17
  45. package/dist/platform/index.js +25 -26
  46. package/dist/promo/index.js +2 -1
  47. package/dist/{enforce-quota.interceptor-Dse3jSpU.d.cts → saas-platform.module-D3rUTiho.d.cts} +69 -62
  48. package/dist/{enforce-quota.interceptor-DMEvL-bE.d.ts → saas-platform.module-DLhoqKNA.d.ts} +69 -62
  49. package/dist/subscription-contract/index.d.cts +1 -1
  50. package/dist/subscription-contract/index.d.ts +1 -1
  51. package/dist/subscription-contract/index.js +1 -1
  52. package/dist/{subscription-contract.module-CG9fPKAr.d.cts → subscription-contract.module-B2uNvUJL.d.cts} +3 -1
  53. package/dist/{subscription-contract.module-CVebZzHR.d.ts → subscription-contract.module-edyhBr4n.d.ts} +3 -1
  54. package/dist/{subscription-bundle-preview.service-DBbrE_cw.d.ts → tenant-billing.controller-BwZRnJ3q.d.ts} +106 -106
  55. package/dist/{subscription-bundle-preview.service-BkJXHAeP.d.cts → tenant-billing.controller-CG4CaFUP.d.cts} +106 -106
  56. package/dist/testing/index.d.cts +6 -3
  57. package/dist/testing/index.d.ts +6 -3
  58. package/dist/testing/index.js +9 -7
  59. package/package.json +3 -3
  60. package/dist/chunk-LZHLGUQI.js +0 -190
  61. package/dist/chunk-WJ6BMDL3.js +0 -313
  62. package/dist/setup.service-BPwJ7My_.d.cts +0 -45
  63. package/dist/setup.service-D2mrdDDB.d.ts +0 -45
@@ -1,9 +1,11 @@
1
- import { Provider, DynamicModule } from '@nestjs/common';
1
+ import { Type, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
2
2
  import { SubscriptionContractRepository } from '@saasicat/types';
3
3
  import { P as ProviderSpec } from './di-CcNeq9v-.cjs';
4
4
 
5
5
  interface SubscriptionContractModuleOptions {
6
6
  subscriptionContractRepository: ProviderSpec<SubscriptionContractRepository>;
7
+ /** Modules that provide dependencies used by the repository factory. */
8
+ imports?: Array<Type<unknown> | DynamicModule | Promise<DynamicModule> | ForwardReference>;
7
9
  extraProviders?: Provider[];
8
10
  global?: boolean;
9
11
  }
@@ -1,9 +1,11 @@
1
- import { Provider, DynamicModule } from '@nestjs/common';
1
+ import { Type, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
2
2
  import { SubscriptionContractRepository } from '@saasicat/types';
3
3
  import { P as ProviderSpec } from './di-CcNeq9v-.js';
4
4
 
5
5
  interface SubscriptionContractModuleOptions {
6
6
  subscriptionContractRepository: ProviderSpec<SubscriptionContractRepository>;
7
+ /** Modules that provide dependencies used by the repository factory. */
8
+ imports?: Array<Type<unknown> | DynamicModule | Promise<DynamicModule> | ForwardReference>;
7
9
  extraProviders?: Provider[];
8
10
  global?: boolean;
9
11
  }
@@ -1,7 +1,7 @@
1
1
  import { CanActivate, ExecutionContext } from '@nestjs/common';
2
2
  import { b as AuthGuardList, m as SelfServiceBlockedPlans, w as TrialProjectionPort, h as PendingPlanQueryPort, f as ContractFreezePort, l as SelfServiceBlockedBundles, u as TenantIdResolver, B as UserIdResolver, z as UserEmailResolver, a as AuditContextResolver } from './subscription-bundles.module-BQmoozm5.js';
3
- import { PlanCatalog, SubscriptionUsagePort, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionBundleRepository, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, SubscriptionUsageRecord, OnboardingSelectionResponse, PlanRepository, CatalogEntryRepository, BundleVersionRow } from '@saasicat/types';
4
- import { c as EntitlementService, a as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-BibpEO0t.js';
3
+ import { PlanCatalog, SubscriptionUsagePort, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionBundleRepository, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, PlanRepository, CatalogEntryRepository, BundleVersionRow, SubscriptionUsageRecord, OnboardingSelectionResponse } from '@saasicat/types';
4
+ import { c as EntitlementService, a as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-o0LMenvl.js';
5
5
  import { f as PromoCodesService } from './service-DX8KbGXl.js';
6
6
  import { A as AdminAuditService } from './admin-audit.service-9IqXMlZm.js';
7
7
 
@@ -224,6 +224,110 @@ declare function resolveBundleCancelEffectiveAt(input: {
224
224
  */
225
225
  declare function addMonths(date: Date, months: number): Date;
226
226
 
227
+ interface SubscriptionBundlePreviewIssue {
228
+ code: string;
229
+ message: string;
230
+ }
231
+ /** Subscription context — the controller reads it from the SubscriptionUsagePort. */
232
+ interface SubscriptionBundlePreviewContext {
233
+ subscriptionId: string;
234
+ /** PlanKey of the current subscription (plan compatibility + redundancy source). */
235
+ currentPlanKey: string;
236
+ /** 'MONTHLY' | 'YEARLY' (port convention). */
237
+ billingCycle: string;
238
+ /** Subscription status (TRIAL/ACTIVE/...). No proration during TRIAL. */
239
+ status: string;
240
+ startedAt: Date | null;
241
+ currentPeriodStart: Date | null;
242
+ currentPeriodEnd: Date | null;
243
+ }
244
+ interface BundlePreviewSnapshot {
245
+ bundleKey: string;
246
+ label: string;
247
+ bundleVersionId: string;
248
+ features: string[];
249
+ quotas: Record<string, number>;
250
+ }
251
+ /** AK-13: feature is already paid for elsewhere — double-payment hint. */
252
+ interface RedundantFeatureHint {
253
+ featureKey: string;
254
+ coveredBy: 'PLAN' | 'BUNDLE';
255
+ /** planKey or bundleKey of the covering source. */
256
+ coveredByKey: string;
257
+ }
258
+ interface SubscriptionBundleAddPreviewDto {
259
+ action: 'add';
260
+ bundle: BundlePreviewSnapshot;
261
+ billingCycle: string;
262
+ /**
263
+ * Prorated amount until period end. `null` during TRIAL (no paid
264
+ * period yet) or without a list price for the cycle.
265
+ */
266
+ proration: ProrationDto | null;
267
+ /** List price per follow-up period in the current cycle; null = no price maintained. */
268
+ nextPeriodPriceNet: number | null;
269
+ minimumTermMonths: number;
270
+ /** Projected minimum-term end from `now`; null = no minimum term. */
271
+ minimumTermEndsAt: Date | null;
272
+ redundantFeatures: RedundantFeatureHint[];
273
+ /**
274
+ * requires-features (#35) that neither the plan nor active bundles nor the
275
+ * bundle itself cover. Non-empty ⇒ blocker
276
+ * BUNDLE_FEATURE_DEPENDENCY_UNSATISFIED.
277
+ */
278
+ missingRequires: string[];
279
+ blockers: SubscriptionBundlePreviewIssue[];
280
+ warnings: SubscriptionBundlePreviewIssue[];
281
+ }
282
+ interface SubscriptionBundleCancelPreviewDto {
283
+ action: 'cancel';
284
+ subscriptionBundleId: string;
285
+ bundle: BundlePreviewSnapshot;
286
+ billingCycle: string;
287
+ /** Effective date = max(currentPeriodEnd, minimumTermEndsAt). */
288
+ effectiveAt: Date;
289
+ /** Savings per period from the effective date; null = no price maintained. */
290
+ nextPeriodSavingsNet: number | null;
291
+ blockers: SubscriptionBundlePreviewIssue[];
292
+ warnings: SubscriptionBundlePreviewIssue[];
293
+ }
294
+ declare class SubscriptionBundlePreviewService {
295
+ private readonly subscriptionBundles;
296
+ private readonly bundles;
297
+ private readonly plans;
298
+ private readonly catalogEntries;
299
+ private readonly blockedBundles;
300
+ private readonly defaultMinTermMonths;
301
+ constructor(subscriptionBundles: SubscriptionBundleRepository, bundles: BundleRepository, plans?: PlanRepository | null, catalogEntries?: CatalogEntryRepository | null, blockedBundles?: SelfServiceBlockedBundles | null, config?: SubscriptionBundleConfig);
302
+ previewAdd(ctx: SubscriptionBundlePreviewContext, input: {
303
+ bundleVersionId: string;
304
+ minimumTermMonths?: number;
305
+ }, now?: Date): Promise<SubscriptionBundleAddPreviewDto>;
306
+ previewCancel(ctx: SubscriptionBundlePreviewContext, input: {
307
+ subscriptionBundleId: string;
308
+ }, now?: Date): Promise<SubscriptionBundleCancelPreviewDto>;
309
+ /** Bookability checks — same codes as `addBundleToSubscription` (422 path). */
310
+ private collectBookabilityBlockers;
311
+ /** Versions of the active bundle bookings (for redundancy + requires coverage). */
312
+ private loadActiveBundleVersions;
313
+ /** Features of the currently live PlanVersion state; empty without PlanRepository. */
314
+ private resolvePlanFeatures;
315
+ private collectRedundantFeatures;
316
+ /**
317
+ * requires of the new bundle that neither the bundle itself nor plan ∪
318
+ * active bundles cover (#35). Empty without CatalogEntryRepository.
319
+ */
320
+ private collectMissingRequires;
321
+ /** `projectKey` lives on the bundle stem, not on the version. */
322
+ private resolveProjectKey;
323
+ }
324
+ /**
325
+ * List price (net) for the billing cycle including plan-specific
326
+ * pricing override (BundlePricingOverride with `planId`). null = no price
327
+ * maintained for the cycle.
328
+ */
329
+ declare function resolveBundlePriceNet(bundleVersion: BundleVersionRow, planKey: string, billingCycle: string): number | null;
330
+
227
331
  interface RequestLike {
228
332
  user?: {
229
333
  tenantId?: string;
@@ -331,108 +435,4 @@ declare class TenantBillingController {
331
435
  private auditLog;
332
436
  }
333
437
 
334
- interface SubscriptionBundlePreviewIssue {
335
- code: string;
336
- message: string;
337
- }
338
- /** Subscription context — the controller reads it from the SubscriptionUsagePort. */
339
- interface SubscriptionBundlePreviewContext {
340
- subscriptionId: string;
341
- /** PlanKey of the current subscription (plan compatibility + redundancy source). */
342
- currentPlanKey: string;
343
- /** 'MONTHLY' | 'YEARLY' (port convention). */
344
- billingCycle: string;
345
- /** Subscription status (TRIAL/ACTIVE/...). No proration during TRIAL. */
346
- status: string;
347
- startedAt: Date | null;
348
- currentPeriodStart: Date | null;
349
- currentPeriodEnd: Date | null;
350
- }
351
- interface BundlePreviewSnapshot {
352
- bundleKey: string;
353
- label: string;
354
- bundleVersionId: string;
355
- features: string[];
356
- quotas: Record<string, number>;
357
- }
358
- /** AK-13: feature is already paid for elsewhere — double-payment hint. */
359
- interface RedundantFeatureHint {
360
- featureKey: string;
361
- coveredBy: 'PLAN' | 'BUNDLE';
362
- /** planKey or bundleKey of the covering source. */
363
- coveredByKey: string;
364
- }
365
- interface SubscriptionBundleAddPreviewDto {
366
- action: 'add';
367
- bundle: BundlePreviewSnapshot;
368
- billingCycle: string;
369
- /**
370
- * Prorated amount until period end. `null` during TRIAL (no paid
371
- * period yet) or without a list price for the cycle.
372
- */
373
- proration: ProrationDto | null;
374
- /** List price per follow-up period in the current cycle; null = no price maintained. */
375
- nextPeriodPriceNet: number | null;
376
- minimumTermMonths: number;
377
- /** Projected minimum-term end from `now`; null = no minimum term. */
378
- minimumTermEndsAt: Date | null;
379
- redundantFeatures: RedundantFeatureHint[];
380
- /**
381
- * requires-features (#35) that neither the plan nor active bundles nor the
382
- * bundle itself cover. Non-empty ⇒ blocker
383
- * BUNDLE_FEATURE_DEPENDENCY_UNSATISFIED.
384
- */
385
- missingRequires: string[];
386
- blockers: SubscriptionBundlePreviewIssue[];
387
- warnings: SubscriptionBundlePreviewIssue[];
388
- }
389
- interface SubscriptionBundleCancelPreviewDto {
390
- action: 'cancel';
391
- subscriptionBundleId: string;
392
- bundle: BundlePreviewSnapshot;
393
- billingCycle: string;
394
- /** Effective date = max(currentPeriodEnd, minimumTermEndsAt). */
395
- effectiveAt: Date;
396
- /** Savings per period from the effective date; null = no price maintained. */
397
- nextPeriodSavingsNet: number | null;
398
- blockers: SubscriptionBundlePreviewIssue[];
399
- warnings: SubscriptionBundlePreviewIssue[];
400
- }
401
- declare class SubscriptionBundlePreviewService {
402
- private readonly subscriptionBundles;
403
- private readonly bundles;
404
- private readonly plans;
405
- private readonly catalogEntries;
406
- private readonly blockedBundles;
407
- private readonly defaultMinTermMonths;
408
- constructor(subscriptionBundles: SubscriptionBundleRepository, bundles: BundleRepository, plans?: PlanRepository | null, catalogEntries?: CatalogEntryRepository | null, blockedBundles?: SelfServiceBlockedBundles | null, config?: SubscriptionBundleConfig);
409
- previewAdd(ctx: SubscriptionBundlePreviewContext, input: {
410
- bundleVersionId: string;
411
- minimumTermMonths?: number;
412
- }, now?: Date): Promise<SubscriptionBundleAddPreviewDto>;
413
- previewCancel(ctx: SubscriptionBundlePreviewContext, input: {
414
- subscriptionBundleId: string;
415
- }, now?: Date): Promise<SubscriptionBundleCancelPreviewDto>;
416
- /** Bookability checks — same codes as `addBundleToSubscription` (422 path). */
417
- private collectBookabilityBlockers;
418
- /** Versions of the active bundle bookings (for redundancy + requires coverage). */
419
- private loadActiveBundleVersions;
420
- /** Features of the currently live PlanVersion state; empty without PlanRepository. */
421
- private resolvePlanFeatures;
422
- private collectRedundantFeatures;
423
- /**
424
- * requires of the new bundle that neither the bundle itself nor plan ∪
425
- * active bundles cover (#35). Empty without CatalogEntryRepository.
426
- */
427
- private collectMissingRequires;
428
- /** `projectKey` lives on the bundle stem, not on the version. */
429
- private resolveProjectKey;
430
- }
431
- /**
432
- * List price (net) for the billing cycle including plan-specific
433
- * pricing override (BundlePricingOverride with `planId`). null = no price
434
- * maintained for the cycle.
435
- */
436
- declare function resolveBundlePriceNet(bundleVersion: BundleVersionRow, planKey: string, billingCycle: string): number | null;
437
-
438
438
  export { type AddBundleToSubscriptionInput as A, type BundlePreviewSnapshot as B, type CancelBundleFromSubscriptionInput as C, type LimitsCheckRow as L, PendingPlanMaterializationService as P, type RedundantFeatureHint as R, type SubscriptionBundleAddPreviewDto as S, TenantAdminGuard as T, type UsageResponse as U, CancelSubscriptionDto as a, ChangePlanDto as b, CompleteOnboardingSubscriptionDto as c, ComposedTenantAuthGuard as d, type PlanChangeContext as e, type PlanChangePreviewDto as f, type PlanChangePreviewIssue as g, PlanChangePreviewService as h, type PlanChangeType as i, type PlanSnapshotDto as j, PreviewPlanChangeDto as k, type ProrationDto as l, type ProrationInput as m, type SubscriptionBundleCancelPreviewDto as n, type SubscriptionBundleConfig as o, type SubscriptionBundlePreviewContext as p, type SubscriptionBundlePreviewIssue as q, SubscriptionBundlePreviewService as r, SubscriptionBundlesService as s, TenantBillingController as t, addMonths as u, computeProration as v, resolveBundleCancelEffectiveAt as w, resolveBundlePriceNet as x };
@@ -1,7 +1,7 @@
1
1
  import { CanActivate, ExecutionContext } from '@nestjs/common';
2
2
  import { b as AuthGuardList, m as SelfServiceBlockedPlans, w as TrialProjectionPort, h as PendingPlanQueryPort, f as ContractFreezePort, l as SelfServiceBlockedBundles, u as TenantIdResolver, B as UserIdResolver, z as UserEmailResolver, a as AuditContextResolver } from './subscription-bundles.module-DCpV-Pb5.cjs';
3
- import { PlanCatalog, SubscriptionUsagePort, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionBundleRepository, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, SubscriptionUsageRecord, OnboardingSelectionResponse, PlanRepository, CatalogEntryRepository, BundleVersionRow } from '@saasicat/types';
4
- import { c as EntitlementService, a as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-CfI0bOsQ.cjs';
3
+ import { PlanCatalog, SubscriptionUsagePort, UsageSnapshotPort, TenantSubscriptionWritePort, SubscriptionBundleRepository, BundleRepository, SubscriptionBundleView, SubscriptionBundleRecord, PlanRepository, CatalogEntryRepository, BundleVersionRow, SubscriptionUsageRecord, OnboardingSelectionResponse } from '@saasicat/types';
4
+ import { c as EntitlementService, a as EffectiveLimitsSnapshot, t as toEffectiveLimitsSnapshot } from './aggregation-SKfXu09x.cjs';
5
5
  import { f as PromoCodesService } from './service-DX8KbGXl.cjs';
6
6
  import { A as AdminAuditService } from './admin-audit.service-9IqXMlZm.cjs';
7
7
 
@@ -224,6 +224,110 @@ declare function resolveBundleCancelEffectiveAt(input: {
224
224
  */
225
225
  declare function addMonths(date: Date, months: number): Date;
226
226
 
227
+ interface SubscriptionBundlePreviewIssue {
228
+ code: string;
229
+ message: string;
230
+ }
231
+ /** Subscription context — the controller reads it from the SubscriptionUsagePort. */
232
+ interface SubscriptionBundlePreviewContext {
233
+ subscriptionId: string;
234
+ /** PlanKey of the current subscription (plan compatibility + redundancy source). */
235
+ currentPlanKey: string;
236
+ /** 'MONTHLY' | 'YEARLY' (port convention). */
237
+ billingCycle: string;
238
+ /** Subscription status (TRIAL/ACTIVE/...). No proration during TRIAL. */
239
+ status: string;
240
+ startedAt: Date | null;
241
+ currentPeriodStart: Date | null;
242
+ currentPeriodEnd: Date | null;
243
+ }
244
+ interface BundlePreviewSnapshot {
245
+ bundleKey: string;
246
+ label: string;
247
+ bundleVersionId: string;
248
+ features: string[];
249
+ quotas: Record<string, number>;
250
+ }
251
+ /** AK-13: feature is already paid for elsewhere — double-payment hint. */
252
+ interface RedundantFeatureHint {
253
+ featureKey: string;
254
+ coveredBy: 'PLAN' | 'BUNDLE';
255
+ /** planKey or bundleKey of the covering source. */
256
+ coveredByKey: string;
257
+ }
258
+ interface SubscriptionBundleAddPreviewDto {
259
+ action: 'add';
260
+ bundle: BundlePreviewSnapshot;
261
+ billingCycle: string;
262
+ /**
263
+ * Prorated amount until period end. `null` during TRIAL (no paid
264
+ * period yet) or without a list price for the cycle.
265
+ */
266
+ proration: ProrationDto | null;
267
+ /** List price per follow-up period in the current cycle; null = no price maintained. */
268
+ nextPeriodPriceNet: number | null;
269
+ minimumTermMonths: number;
270
+ /** Projected minimum-term end from `now`; null = no minimum term. */
271
+ minimumTermEndsAt: Date | null;
272
+ redundantFeatures: RedundantFeatureHint[];
273
+ /**
274
+ * requires-features (#35) that neither the plan nor active bundles nor the
275
+ * bundle itself cover. Non-empty ⇒ blocker
276
+ * BUNDLE_FEATURE_DEPENDENCY_UNSATISFIED.
277
+ */
278
+ missingRequires: string[];
279
+ blockers: SubscriptionBundlePreviewIssue[];
280
+ warnings: SubscriptionBundlePreviewIssue[];
281
+ }
282
+ interface SubscriptionBundleCancelPreviewDto {
283
+ action: 'cancel';
284
+ subscriptionBundleId: string;
285
+ bundle: BundlePreviewSnapshot;
286
+ billingCycle: string;
287
+ /** Effective date = max(currentPeriodEnd, minimumTermEndsAt). */
288
+ effectiveAt: Date;
289
+ /** Savings per period from the effective date; null = no price maintained. */
290
+ nextPeriodSavingsNet: number | null;
291
+ blockers: SubscriptionBundlePreviewIssue[];
292
+ warnings: SubscriptionBundlePreviewIssue[];
293
+ }
294
+ declare class SubscriptionBundlePreviewService {
295
+ private readonly subscriptionBundles;
296
+ private readonly bundles;
297
+ private readonly plans;
298
+ private readonly catalogEntries;
299
+ private readonly blockedBundles;
300
+ private readonly defaultMinTermMonths;
301
+ constructor(subscriptionBundles: SubscriptionBundleRepository, bundles: BundleRepository, plans?: PlanRepository | null, catalogEntries?: CatalogEntryRepository | null, blockedBundles?: SelfServiceBlockedBundles | null, config?: SubscriptionBundleConfig);
302
+ previewAdd(ctx: SubscriptionBundlePreviewContext, input: {
303
+ bundleVersionId: string;
304
+ minimumTermMonths?: number;
305
+ }, now?: Date): Promise<SubscriptionBundleAddPreviewDto>;
306
+ previewCancel(ctx: SubscriptionBundlePreviewContext, input: {
307
+ subscriptionBundleId: string;
308
+ }, now?: Date): Promise<SubscriptionBundleCancelPreviewDto>;
309
+ /** Bookability checks — same codes as `addBundleToSubscription` (422 path). */
310
+ private collectBookabilityBlockers;
311
+ /** Versions of the active bundle bookings (for redundancy + requires coverage). */
312
+ private loadActiveBundleVersions;
313
+ /** Features of the currently live PlanVersion state; empty without PlanRepository. */
314
+ private resolvePlanFeatures;
315
+ private collectRedundantFeatures;
316
+ /**
317
+ * requires of the new bundle that neither the bundle itself nor plan ∪
318
+ * active bundles cover (#35). Empty without CatalogEntryRepository.
319
+ */
320
+ private collectMissingRequires;
321
+ /** `projectKey` lives on the bundle stem, not on the version. */
322
+ private resolveProjectKey;
323
+ }
324
+ /**
325
+ * List price (net) for the billing cycle including plan-specific
326
+ * pricing override (BundlePricingOverride with `planId`). null = no price
327
+ * maintained for the cycle.
328
+ */
329
+ declare function resolveBundlePriceNet(bundleVersion: BundleVersionRow, planKey: string, billingCycle: string): number | null;
330
+
227
331
  interface RequestLike {
228
332
  user?: {
229
333
  tenantId?: string;
@@ -331,108 +435,4 @@ declare class TenantBillingController {
331
435
  private auditLog;
332
436
  }
333
437
 
334
- interface SubscriptionBundlePreviewIssue {
335
- code: string;
336
- message: string;
337
- }
338
- /** Subscription context — the controller reads it from the SubscriptionUsagePort. */
339
- interface SubscriptionBundlePreviewContext {
340
- subscriptionId: string;
341
- /** PlanKey of the current subscription (plan compatibility + redundancy source). */
342
- currentPlanKey: string;
343
- /** 'MONTHLY' | 'YEARLY' (port convention). */
344
- billingCycle: string;
345
- /** Subscription status (TRIAL/ACTIVE/...). No proration during TRIAL. */
346
- status: string;
347
- startedAt: Date | null;
348
- currentPeriodStart: Date | null;
349
- currentPeriodEnd: Date | null;
350
- }
351
- interface BundlePreviewSnapshot {
352
- bundleKey: string;
353
- label: string;
354
- bundleVersionId: string;
355
- features: string[];
356
- quotas: Record<string, number>;
357
- }
358
- /** AK-13: feature is already paid for elsewhere — double-payment hint. */
359
- interface RedundantFeatureHint {
360
- featureKey: string;
361
- coveredBy: 'PLAN' | 'BUNDLE';
362
- /** planKey or bundleKey of the covering source. */
363
- coveredByKey: string;
364
- }
365
- interface SubscriptionBundleAddPreviewDto {
366
- action: 'add';
367
- bundle: BundlePreviewSnapshot;
368
- billingCycle: string;
369
- /**
370
- * Prorated amount until period end. `null` during TRIAL (no paid
371
- * period yet) or without a list price for the cycle.
372
- */
373
- proration: ProrationDto | null;
374
- /** List price per follow-up period in the current cycle; null = no price maintained. */
375
- nextPeriodPriceNet: number | null;
376
- minimumTermMonths: number;
377
- /** Projected minimum-term end from `now`; null = no minimum term. */
378
- minimumTermEndsAt: Date | null;
379
- redundantFeatures: RedundantFeatureHint[];
380
- /**
381
- * requires-features (#35) that neither the plan nor active bundles nor the
382
- * bundle itself cover. Non-empty ⇒ blocker
383
- * BUNDLE_FEATURE_DEPENDENCY_UNSATISFIED.
384
- */
385
- missingRequires: string[];
386
- blockers: SubscriptionBundlePreviewIssue[];
387
- warnings: SubscriptionBundlePreviewIssue[];
388
- }
389
- interface SubscriptionBundleCancelPreviewDto {
390
- action: 'cancel';
391
- subscriptionBundleId: string;
392
- bundle: BundlePreviewSnapshot;
393
- billingCycle: string;
394
- /** Effective date = max(currentPeriodEnd, minimumTermEndsAt). */
395
- effectiveAt: Date;
396
- /** Savings per period from the effective date; null = no price maintained. */
397
- nextPeriodSavingsNet: number | null;
398
- blockers: SubscriptionBundlePreviewIssue[];
399
- warnings: SubscriptionBundlePreviewIssue[];
400
- }
401
- declare class SubscriptionBundlePreviewService {
402
- private readonly subscriptionBundles;
403
- private readonly bundles;
404
- private readonly plans;
405
- private readonly catalogEntries;
406
- private readonly blockedBundles;
407
- private readonly defaultMinTermMonths;
408
- constructor(subscriptionBundles: SubscriptionBundleRepository, bundles: BundleRepository, plans?: PlanRepository | null, catalogEntries?: CatalogEntryRepository | null, blockedBundles?: SelfServiceBlockedBundles | null, config?: SubscriptionBundleConfig);
409
- previewAdd(ctx: SubscriptionBundlePreviewContext, input: {
410
- bundleVersionId: string;
411
- minimumTermMonths?: number;
412
- }, now?: Date): Promise<SubscriptionBundleAddPreviewDto>;
413
- previewCancel(ctx: SubscriptionBundlePreviewContext, input: {
414
- subscriptionBundleId: string;
415
- }, now?: Date): Promise<SubscriptionBundleCancelPreviewDto>;
416
- /** Bookability checks — same codes as `addBundleToSubscription` (422 path). */
417
- private collectBookabilityBlockers;
418
- /** Versions of the active bundle bookings (for redundancy + requires coverage). */
419
- private loadActiveBundleVersions;
420
- /** Features of the currently live PlanVersion state; empty without PlanRepository. */
421
- private resolvePlanFeatures;
422
- private collectRedundantFeatures;
423
- /**
424
- * requires of the new bundle that neither the bundle itself nor plan ∪
425
- * active bundles cover (#35). Empty without CatalogEntryRepository.
426
- */
427
- private collectMissingRequires;
428
- /** `projectKey` lives on the bundle stem, not on the version. */
429
- private resolveProjectKey;
430
- }
431
- /**
432
- * List price (net) for the billing cycle including plan-specific
433
- * pricing override (BundlePricingOverride with `planId`). null = no price
434
- * maintained for the cycle.
435
- */
436
- declare function resolveBundlePriceNet(bundleVersion: BundleVersionRow, planKey: string, billingCycle: string): number | null;
437
-
438
438
  export { type AddBundleToSubscriptionInput as A, type BundlePreviewSnapshot as B, type CancelBundleFromSubscriptionInput as C, type LimitsCheckRow as L, PendingPlanMaterializationService as P, type RedundantFeatureHint as R, type SubscriptionBundleAddPreviewDto as S, TenantAdminGuard as T, type UsageResponse as U, CancelSubscriptionDto as a, ChangePlanDto as b, CompleteOnboardingSubscriptionDto as c, ComposedTenantAuthGuard as d, type PlanChangeContext as e, type PlanChangePreviewDto as f, type PlanChangePreviewIssue as g, PlanChangePreviewService as h, type PlanChangeType as i, type PlanSnapshotDto as j, PreviewPlanChangeDto as k, type ProrationDto as l, type ProrationInput as m, type SubscriptionBundleCancelPreviewDto as n, type SubscriptionBundleConfig as o, type SubscriptionBundlePreviewContext as p, type SubscriptionBundlePreviewIssue as q, SubscriptionBundlePreviewService as r, SubscriptionBundlesService as s, TenantBillingController as t, addMonths as u, computeProration as v, resolveBundleCancelEffectiveAt as w, resolveBundlePriceNet as x };
@@ -1,16 +1,19 @@
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, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, CreateSubscriptionContractData, TerminateSubscriptionContractData, SubscriptionRepository, SubscriptionRecord, TransactionRunner, PlanCatalog, QuotaProvider } from '@saasicat/types';
2
2
  import { Type, DynamicModule } from '@nestjs/common';
3
- import { S as SaasPlatformAdapters } from '../enforce-quota.interceptor-Dse3jSpU.cjs';
4
- export { E as EnforceQuotaInterceptor, P as PLAN_RESOLVER_PORT_TOKEN, a as StaticEntitlementService, b as StaticFeatureGuard, c as StaticPlanResolver } from '../enforce-quota.interceptor-Dse3jSpU.cjs';
3
+ import { a as SaasPlatformAdapters } from '../saas-platform.module-D3rUTiho.cjs';
4
+ export { P as PLAN_RESOLVER_PORT_TOKEN, o as StaticPlanResolver } from '../saas-platform.module-D3rUTiho.cjs';
5
+ export { E as EnforceQuotaInterceptor, S as StaticEntitlementService, a as StaticFeatureGuard } from '../enforce-quota.interceptor-DMw-bPyk.cjs';
5
6
  import '../di-CcNeq9v-.cjs';
6
- import '../admin-resources.module-BZN_yBFj.cjs';
7
+ import '../admin-resources.module-DGgGSdzN.cjs';
7
8
  import '../admin-audit.service-9IqXMlZm.cjs';
8
9
  import '../plan-resolution-CFCoUkrE.cjs';
10
+ import '../subscription-contract.module-B2uNvUJL.cjs';
9
11
  import '../module-CSN8j8Tp.cjs';
10
12
  import '../service-DX8KbGXl.cjs';
11
13
  import '../discovery.scanner-DLgEvuoy.cjs';
12
14
  import '@nestjs/core';
13
15
  import '../catalog.module-Dw2Hrbyu.cjs';
16
+ import '../checkout-offer.module-DmlpPevf.cjs';
14
17
  import '../subscription-bundles.module-DCpV-Pb5.cjs';
15
18
  import 'rxjs';
16
19
 
@@ -1,16 +1,19 @@
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, SubscriptionBundleRepository, SubscriptionBundleRecord, CreateSubscriptionBundleData, CancelSubscriptionBundleData, SubscriptionContractRepository, SubscriptionContractFilter, SubscriptionContractRecord, CreateSubscriptionContractData, TerminateSubscriptionContractData, SubscriptionRepository, SubscriptionRecord, TransactionRunner, PlanCatalog, QuotaProvider } from '@saasicat/types';
2
2
  import { Type, DynamicModule } from '@nestjs/common';
3
- import { S as SaasPlatformAdapters } from '../enforce-quota.interceptor-DMEvL-bE.js';
4
- export { E as EnforceQuotaInterceptor, P as PLAN_RESOLVER_PORT_TOKEN, a as StaticEntitlementService, b as StaticFeatureGuard, c as StaticPlanResolver } from '../enforce-quota.interceptor-DMEvL-bE.js';
3
+ import { a as SaasPlatformAdapters } from '../saas-platform.module-DLhoqKNA.js';
4
+ export { P as PLAN_RESOLVER_PORT_TOKEN, o as StaticPlanResolver } from '../saas-platform.module-DLhoqKNA.js';
5
+ export { E as EnforceQuotaInterceptor, S as StaticEntitlementService, a as StaticFeatureGuard } from '../enforce-quota.interceptor-CmbWX39L.js';
5
6
  import '../di-CcNeq9v-.js';
6
- import '../admin-resources.module-Cms8MY6h.js';
7
+ import '../admin-resources.module-BY5r_1MG.js';
7
8
  import '../admin-audit.service-9IqXMlZm.js';
8
9
  import '../plan-resolution-CFCoUkrE.js';
10
+ import '../subscription-contract.module-edyhBr4n.js';
9
11
  import '../module-DgYJur6f.js';
10
12
  import '../service-DX8KbGXl.js';
11
13
  import '../discovery.scanner-DLgEvuoy.js';
12
14
  import '@nestjs/core';
13
15
  import '../catalog.module-BKObceo0.js';
16
+ import '../checkout-offer.module-Ca3_TieR.js';
14
17
  import '../subscription-bundles.module-BQmoozm5.js';
15
18
  import 'rxjs';
16
19
 
@@ -5,19 +5,21 @@ import {
5
5
  StaticEntitlementService,
6
6
  StaticFeatureGuard,
7
7
  StaticPlanResolver
8
- } from "../chunk-J3BMIR4W.js";
9
- import "../chunk-IRWZC3GC.js";
10
- import "../chunk-FVT7KTUI.js";
11
- import "../chunk-DVFPKVLO.js";
8
+ } from "../chunk-YITTE646.js";
9
+ import "../chunk-GLLCB4BP.js";
10
+ import "../chunk-PLJEAUFU.js";
11
+ import "../chunk-5KH2O4SF.js";
12
12
  import "../chunk-E7AJ42AB.js";
13
- import "../chunk-2PNX2QL2.js";
14
- import "../chunk-33TP26MR.js";
13
+ import "../chunk-32EMXPU2.js";
14
+ import "../chunk-P3DP6GJE.js";
15
15
  import "../chunk-WPUVJRIN.js";
16
16
  import "../chunk-E56W4U2P.js";
17
+ import "../chunk-GJBXOCRZ.js";
17
18
  import "../chunk-MDIZUVIK.js";
19
+ import "../chunk-YSC46BGM.js";
18
20
  import "../chunk-V34AA7C7.js";
19
21
  import "../chunk-Z3FWN3HJ.js";
20
- import "../chunk-2WNM5THV.js";
22
+ import "../chunk-EXOLOJFZ.js";
21
23
  import "../chunk-R2QOSVAA.js";
22
24
  import "../chunk-NYLON2VC.js";
23
25
  import "../chunk-WKVBNTYC.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/nest",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
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",
@@ -137,8 +137,8 @@
137
137
  "js-yaml": "^4.1.0",
138
138
  "otplib": "^13.4.1",
139
139
  "qrcode": "^1.5.4",
140
- "@saasicat/spec": "^0.13.0",
141
- "@saasicat/types": "^0.13.0"
140
+ "@saasicat/spec": "^0.15.0",
141
+ "@saasicat/types": "^0.15.0"
142
142
  },
143
143
  "peerDependencies": {
144
144
  "@nestjs/common": "^11.0.0",