@saasicat/nest 0.8.0 → 0.10.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 (95) hide show
  1. package/dist/_entries.cjs +17678 -0
  2. package/dist/admin/index.cjs +4 -1274
  3. package/dist/admin/index.d.cts +10 -171
  4. package/dist/admin/index.d.ts +10 -171
  5. package/dist/admin/index.js +13 -4
  6. package/dist/admin-resources.module-BZN_yBFj.d.cts +40 -0
  7. package/dist/admin-resources.module-Cms8MY6h.d.ts +40 -0
  8. package/dist/admin-stats.module-15ac5KY3.d.ts +201 -0
  9. package/dist/admin-stats.module-v4SVvWzj.d.cts +201 -0
  10. package/dist/billing/index.cjs +4 -5128
  11. package/dist/billing/index.d.cts +8 -719
  12. package/dist/billing/index.d.ts +8 -719
  13. package/dist/billing/index.js +7 -10
  14. package/dist/catalog/index.cjs +4 -5624
  15. package/dist/catalog/index.d.cts +7 -427
  16. package/dist/catalog/index.d.ts +7 -427
  17. package/dist/catalog/index.js +14 -12
  18. package/dist/catalog.module-BKObceo0.d.ts +103 -0
  19. package/dist/catalog.module-Dw2Hrbyu.d.cts +103 -0
  20. package/dist/checkout-offer/index.cjs +4 -807
  21. package/dist/checkout-offer/index.d.cts +5 -84
  22. package/dist/checkout-offer/index.d.ts +5 -84
  23. package/dist/checkout-offer/index.js +3 -2
  24. package/dist/checkout-offer.module-Y0hDOVrq.d.ts +85 -0
  25. package/dist/checkout-offer.module-ZYF5IsDY.d.cts +85 -0
  26. package/dist/{chunk-5DDCSGZC.js → chunk-33TP26MR.js} +144 -356
  27. package/dist/{chunk-CK54YKVK.js → chunk-75JABGZK.js} +16 -16
  28. package/dist/{chunk-HRU3CP57.js → chunk-BOADBIGB.js} +1 -1
  29. package/dist/{chunk-ZLUGQE5D.js → chunk-E7AJ42AB.js} +8 -8
  30. package/dist/{chunk-6LP7CDS2.js → chunk-F3VV6EXG.js} +18 -13
  31. package/dist/{chunk-PLDHI6NA.js → chunk-FVT7KTUI.js} +258 -3
  32. package/dist/{chunk-RZU4HIAN.js → chunk-GBDUH6DO.js} +26 -23
  33. package/dist/{chunk-K3OPNVFR.js → chunk-HBFU5AN3.js} +5 -9
  34. package/dist/chunk-HWGIMNWR.js +0 -0
  35. package/dist/chunk-IRWZC3GC.js +755 -0
  36. package/dist/chunk-L4KTQ6CL.js +20 -0
  37. package/dist/{chunk-T5SXXAKG.js → chunk-LZHLGUQI.js} +1 -1
  38. package/dist/{chunk-YHHE4KDA.js → chunk-PUXLPUVH.js} +351 -21
  39. package/dist/chunk-TXDH4FUA.js +211 -0
  40. package/dist/chunk-UF53DWWR.js +0 -0
  41. package/dist/{chunk-AJ3EPELS.js → chunk-V34AA7C7.js} +1 -1
  42. package/dist/chunk-WJ6BMDL3.js +313 -0
  43. package/dist/{chunk-M6CZQYPY.js → chunk-Z3FWN3HJ.js} +2 -2
  44. package/dist/discovery/index.cjs +4 -588
  45. package/dist/discovery/index.js +3 -3
  46. package/dist/{enforce-quota.interceptor-cv7r80VM.d.cts → enforce-quota.interceptor-BhkX5nq2.d.cts} +127 -12
  47. package/dist/{enforce-quota.interceptor-Dj1Kusr5.d.ts → enforce-quota.interceptor-CcqZc0Yu.d.ts} +127 -12
  48. package/dist/entitlement/index.cjs +4 -780
  49. package/dist/entitlement/index.d.cts +3 -1
  50. package/dist/entitlement/index.d.ts +3 -1
  51. package/dist/entitlement/index.js +2 -3
  52. package/dist/index.cjs +4 -14975
  53. package/dist/index.d.cts +22 -54
  54. package/dist/index.d.ts +22 -54
  55. package/dist/index.js +88 -369
  56. package/dist/module-CSN8j8Tp.d.cts +39 -0
  57. package/dist/module-DgYJur6f.d.ts +39 -0
  58. package/dist/plan-versions.service-BB36Q1bg.d.ts +329 -0
  59. package/dist/plan-versions.service-CUR2Whyr.d.cts +329 -0
  60. package/dist/platform/index.cjs +4 -2779
  61. package/dist/platform/index.d.cts +50 -8
  62. package/dist/platform/index.d.ts +50 -8
  63. package/dist/platform/index.js +116 -12
  64. package/dist/promo/index.cjs +4 -995
  65. package/dist/promo/index.d.cts +48 -46
  66. package/dist/promo/index.d.ts +48 -46
  67. package/dist/promo/index.js +10 -2
  68. package/dist/rate-limit.guard-dntqAlfZ.d.cts +19 -0
  69. package/dist/rate-limit.guard-dntqAlfZ.d.ts +19 -0
  70. package/dist/registration/index.cjs +4 -1655
  71. package/dist/registration/index.js +1 -1
  72. package/dist/setup.service-BPwJ7My_.d.cts +45 -0
  73. package/dist/setup.service-D2mrdDDB.d.ts +45 -0
  74. package/dist/subscription-bundle-preview.service-BkJXHAeP.d.cts +438 -0
  75. package/dist/subscription-bundle-preview.service-DBbrE_cw.d.ts +438 -0
  76. package/dist/subscription-bundles.module-BQmoozm5.d.ts +291 -0
  77. package/dist/subscription-bundles.module-DCpV-Pb5.d.cts +291 -0
  78. package/dist/subscription-contract/index.cjs +4 -471
  79. package/dist/subscription-contract/index.d.cts +5 -13
  80. package/dist/subscription-contract/index.d.ts +5 -13
  81. package/dist/subscription-contract.module-CG9fPKAr.d.cts +14 -0
  82. package/dist/subscription-contract.module-CVebZzHR.d.ts +14 -0
  83. package/dist/testing/index.cjs +4 -3756
  84. package/dist/testing/index.d.cts +9 -4
  85. package/dist/testing/index.d.ts +9 -4
  86. package/dist/testing/index.js +13 -7
  87. package/package.json +5 -5
  88. package/dist/admin-manifest.config-DyrQNT7M.d.cts +0 -10
  89. package/dist/admin-manifest.config-DyrQNT7M.d.ts +0 -10
  90. package/dist/admin-manifest.service-Cp6uwvmt.d.cts +0 -33
  91. package/dist/admin-manifest.service-UGgzR1x-.d.ts +0 -33
  92. package/dist/chunk-52UTQRD3.js +0 -326
  93. package/dist/chunk-N3WANKSA.js +0 -20
  94. package/dist/chunk-Q53N43LQ.js +0 -13
  95. /package/dist/{chunk-2FR6ZL7R.js → chunk-DBZGV3HC.js} +0 -0
@@ -1,341 +1,19 @@
1
- import { BundleRepository, DiscoverySnapshot, SubscriptionRepository, PlanRepository, CatalogEntryRepository, BundleRow, BundleVersionRow, CreateBundleData, UpdateBundleData, CreateBundleVersionDraftData, BundleVersionMutationResult, UpdateBundleVersionDraftData, PublishBundleVersionData, MarketingProjectionRepository, MarketingProjectionFilter, MarketingProjectionRow, CreateMarketingProjectionData, UpdateMarketingProjectionData, FeatureUiRegistry, CapabilityCatalogEntryRow, FeatureCatalogEntryRow, QuotaCatalogEntryRow, ReviewCatalogEntryData, CatalogEntryI18n, UpdateCatalogEntryBaseData, SyncDiscoveryResult, PromotionRepository, PromotionRow, CreatePromotionData, UpdatePromotionData, MarketingSettingsRepository, MarketingSettingsRow, UpdateMarketingSettingsData, PublicMarketingCatalogResponse, PlanRow, CreatePlanData, UpdatePlanData, PlanVersionRow, CreatePlanVersionDraftData, PlanVersionMutationResult, UpdatePlanVersionDraftData, PublishPlanVersionData, StrictModeWarningCode, StrictModeWarning, ApprovedCatalogKeys, DiscoveredQuota, DiscoveryStatus, PromotionType, PromotionValue, PromotionTargetType, PromotionBillingCycle, PromotionI18n } from '@saasicat/types';
2
- import { c as DiscoveryScanner } from '../discovery.scanner-DLgEvuoy.cjs';
3
- import { OnApplicationBootstrap, Type, CanActivate, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
4
- import { P as ProviderSpec } from '../di-CcNeq9v-.cjs';
1
+ export { B as BundlesService, C as CatalogEntriesService, a as CatalogServiceConfig, M as MarketingProjectionsService, b as MarketingSettingsService, P as PlanVersionsService, c as PlansService, d as PromotionsService, e as PublicMarketingCatalogService } from '../plan-versions.service-CUR2Whyr.cjs';
2
+ import { Type, CanActivate } from '@nestjs/common';
3
+ export { C as CatalogControllerConfig, a as CatalogModule, b as CatalogModuleOptions } from '../catalog.module-Dw2Hrbyu.cjs';
4
+ import { StrictModeWarningCode, StrictModeWarning, DiscoverySnapshot, ApprovedCatalogKeys, DiscoveredQuota, CatalogEntryRepository, PlanVersionRow, BundleVersionRow, DiscoveryStatus, CatalogEntryI18n, PromotionType, PromotionValue, PromotionTargetType, PromotionBillingCycle, PromotionI18n } from '@saasicat/types';
5
+ import '../discovery.scanner-DLgEvuoy.cjs';
5
6
  import '@nestjs/core';
6
-
7
- /**
8
- * Configuration for the mutating operations.
9
- */
10
- interface CatalogServiceConfig {
11
- /** Active mode for the strict-mode check. Default `'blocking'` (#12). */
12
- strictModeCheckMode?: 'warn-only' | 'blocking';
13
- /**
14
- * Discovery→Catalog auto-sync at boot (#12). Default `true` — runs when a
15
- * `DiscoverySnapshot` is available. Set to `false` to disable the boot
16
- * sync; the manual `POST /admin/catalog/discovery/sync` is unaffected.
17
- */
18
- autoSyncDiscoveryAtBoot?: boolean;
19
- /**
20
- * Feature keys the catalog is deliberately allowed to carry WITHOUT them
21
- * existing in the discovery snapshot (= in code via @ImplementsCapability) —
22
- * marketed non-code features such as support SLAs (e.g. PRIORITY_SUPPORT).
23
- * The strict-mode check does NOT report them as BUNDLE_/PLAN_FEATURE_UNKNOWN.
24
- * Use sparingly: this is the only legitimate exception to "code is the
25
- * source of truth"; not-yet-built features do NOT belong here but should be
26
- * removed from the catalog until they are implemented.
27
- */
28
- marketedOnlyFeatures?: string[];
29
- }
30
- declare class BundlesService {
31
- private readonly repo;
32
- private readonly snapshot;
33
- private readonly subscriptions;
34
- private readonly planRepo;
35
- private readonly scanner;
36
- private readonly catalogEntries;
37
- private readonly logger;
38
- private mode;
39
- private readonly marketedOnly;
40
- constructor(repo: BundleRepository, snapshot?: DiscoverySnapshot | null, config?: CatalogServiceConfig, subscriptions?: SubscriptionRepository | null, planRepo?: PlanRepository | null, scanner?: DiscoveryScanner | null, catalogEntries?: CatalogEntryRepository | null);
41
- listBundles(projectKey: string): Promise<BundleRow[]>;
42
- getBundle(bundleId: string): Promise<{
43
- bundle: BundleRow;
44
- versions: BundleVersionRow[];
45
- }>;
46
- createBundle(data: CreateBundleData): Promise<BundleRow>;
47
- updateBundle(bundleId: string, data: UpdateBundleData): Promise<BundleRow>;
48
- softDeleteBundle(bundleId: string): Promise<void>;
49
- /**
50
- * Hard-deletes a draft BundleVersion (`publishedAt === null`) from the
51
- * DB. Published versions stay immutable (contract-protection P1) — the
52
- * service throws 422 with code `BUNDLE_VERSION_ALREADY_PUBLISHED`.
53
- */
54
- discardBundleDraft(versionId: string): Promise<void>;
55
- listBundleVersions(bundleId: string): Promise<BundleVersionRow[]>;
56
- getBundleVersion(versionId: string): Promise<BundleVersionRow>;
57
- /**
58
- * Annotates each BundleVersion with `isLatestInChain` (highest version
59
- * number in the chain) + `subscriptionCount` so that UI and backend make
60
- * the same editability decision. `subscriptionCount` stays `undefined`
61
- * when no SubscriptionRepository is registered or the method was not
62
- * implemented — `isVersionEditable` interprets that fail-closed
63
- * (= frozen).
64
- */
65
- private annotateEditability;
66
- /**
67
- * Creates a new draft BundleVersion. Throws when a draft already exists
68
- * for the same bundle (repository constraint).
69
- *
70
- * The strict-mode check runs on the input; in `warn-only` warnings are
71
- * returned, in `blocking` the service throws HTTP 422.
72
- */
73
- createBundleDraft(data: CreateBundleVersionDraftData): Promise<BundleVersionMutationResult>;
74
- /**
75
- * Updates a draft version or — as a deliberate relaxation of
76
- * contract-protection P1 — a published-but-future BundleVersion that is
77
- * latest-in-chain and does not yet bind any subscription. Once
78
- * `validFrom` is reached or a booking references it, the version freezes
79
- * again. The concrete decision is made by the `isVersionEditable` helper,
80
- * which is mirrored by the UI.
81
- */
82
- updateBundleDraft(versionId: string, data: UpdateBundleVersionDraftData): Promise<BundleVersionMutationResult>;
83
- /**
84
- * Publishes a draft version atomically. Steps:
85
- * 1. Strict check on the draft definition (warn-only or blocking)
86
- * 2. Enforce validFrom requirement + ordering against the predecessor
87
- * (SPEC_V2 §4.2 + §11.1 M6 Pack 2c, analogous to PlanVersion)
88
- * 3. Compute the diff against the predecessor version (latest live) →
89
- * `publishedChanges` + `nonRegressive` via `classifyBundleVersionDiff`
90
- * 4. Call Repository.publishDraft with the diff result + validity dates
91
- * (transaction; auto-succession sets the previous validUntil)
92
- */
93
- publishBundleVersion(versionId: string, publishMeta: PublishBundleVersionData): Promise<BundleVersionMutationResult>;
94
- private runStrictCheck;
95
- private gateOrPass;
96
- private assertBundleVersionWindowUpdate;
97
- private findPreviousBundleVersion;
98
- private parseOptionalBundleDate;
99
- private parseRequiredBundleDate;
100
- }
101
-
102
- declare class MarketingProjectionsService {
103
- private readonly repo;
104
- constructor(repo: MarketingProjectionRepository);
105
- list(filter: MarketingProjectionFilter): Promise<MarketingProjectionRow[]>;
106
- getById(id: string): Promise<MarketingProjectionRow>;
107
- create(data: CreateMarketingProjectionData): Promise<MarketingProjectionRow>;
108
- update(id: string, data: UpdateMarketingProjectionData): Promise<MarketingProjectionRow>;
109
- delete(id: string): Promise<void>;
110
- }
111
-
112
- declare class CatalogEntriesService implements OnApplicationBootstrap {
113
- private readonly repo;
114
- private readonly snapshot;
115
- private readonly scanner;
116
- private readonly featureUiRegistry;
117
- private readonly logger;
118
- private readonly autoSyncAtBoot;
119
- constructor(repo: CatalogEntryRepository, snapshot?: DiscoverySnapshot | null, config?: CatalogServiceConfig, scanner?: DiscoveryScanner | null, featureUiRegistry?: FeatureUiRegistry | null);
120
- /**
121
- * Mirrors the discovery snapshot into the catalog entries at boot
122
- * (discovery-as-SSOT, #12). Runs only when a snapshot is available and
123
- * the kill switch `autoSyncDiscoveryAtBoot` is not set to `false`. A
124
- * sync error deliberately does not abort the boot — the manual endpoint
125
- * `POST /admin/catalog/discovery/sync` remains as a fallback.
126
- */
127
- onApplicationBootstrap(): Promise<void>;
128
- listCapabilities(projectKey: string, codeStatus?: string): Promise<CapabilityCatalogEntryRow[]>;
129
- listFeatures(projectKey: string, discoveryStatus?: string): Promise<FeatureCatalogEntryRow[]>;
130
- listQuotas(projectKey: string, discoveryStatus?: string): Promise<QuotaCatalogEntryRow[]>;
131
- /**
132
- * Approval transition of a feature (#20). Validates the state machine;
133
- * `approved` persists the approval signature from the current
134
- * snapshot, `pending` (revoke/reactivate) deletes it, `outdated`/
135
- * `obsolete` keep the last approval as history.
136
- */
137
- reviewFeature(projectKey: string, featureKey: string, data: ReviewCatalogEntryData, reviewedBy: string | null): Promise<FeatureCatalogEntryRow>;
138
- /** Approval transition of a quota — same state machine as features (#20). */
139
- reviewQuota(projectKey: string, quotaKey: string, data: ReviewCatalogEntryData, reviewedBy: string | null): Promise<QuotaCatalogEntryRow>;
140
- private resolveReviewUpdate;
141
- setFeatureI18n(projectKey: string, featureKey: string, i18n: CatalogEntryI18n): Promise<FeatureCatalogEntryRow>;
142
- setQuotaI18n(projectKey: string, quotaKey: string, i18n: CatalogEntryI18n): Promise<QuotaCatalogEntryRow>;
143
- /** Sets the editable default-locale label/description of a feature. */
144
- setFeatureBase(projectKey: string, featureKey: string, data: UpdateCatalogEntryBaseData): Promise<FeatureCatalogEntryRow>;
145
- /** Sets the editable default-locale label/description of a quota. */
146
- setQuotaBase(projectKey: string, quotaKey: string, data: UpdateCatalogEntryBaseData): Promise<QuotaCatalogEntryRow>;
147
- /**
148
- * Synchronizes the catalog entries from a discovery snapshot.
149
- * Idempotent — can run against the same snapshot any number of times.
150
- */
151
- syncFromSnapshot(snapshot: DiscoverySnapshot): Promise<SyncDiscoveryResult>;
152
- /**
153
- * `replaced` semantics (#39): if a key disappears from the snapshot AND
154
- * another snapshot key claims it via `replaces`, the old entry gets
155
- * the successor pointer — `obsolete` (from `retireMissing`)
156
- * + `successorKey` instead of a bare `obsolete`. If a key reappears in
157
- * the code, an existing pointer is deleted. A missing key
158
- * without a claimant remains untouched (deleted without replacement).
159
- */
160
- private applySuccessorPointers;
161
- }
7
+ import '../di-CcNeq9v-.cjs';
162
8
 
163
9
  declare function buildCatalogEntriesController(guards: Array<Type<CanActivate>>): Type;
164
10
 
165
- declare class PromotionsService {
166
- private readonly repo;
167
- constructor(repo: PromotionRepository);
168
- list(projectKey: string): Promise<PromotionRow[]>;
169
- getById(id: string): Promise<PromotionRow>;
170
- create(data: CreatePromotionData): Promise<PromotionRow>;
171
- update(id: string, data: UpdatePromotionData): Promise<PromotionRow>;
172
- delete(id: string): Promise<void>;
173
- }
174
-
175
11
  declare function buildPromotionsController(guards: Array<Type<CanActivate>>): Type;
176
12
 
177
- declare class MarketingSettingsService {
178
- private readonly repo;
179
- constructor(repo: MarketingSettingsRepository);
180
- /** Returns the stored config or `null` (in which case the full pool applies). */
181
- get(projectKey: string): Promise<MarketingSettingsRow | null>;
182
- upsert(projectKey: string, data: UpdateMarketingSettingsData): Promise<MarketingSettingsRow>;
183
- }
184
-
185
13
  declare function buildMarketingSettingsController(guards: Array<Type<CanActivate>>): Type;
186
14
 
187
- declare class PublicMarketingCatalogService {
188
- private readonly planRepo;
189
- private readonly marketingRepo;
190
- private readonly promotionRepo;
191
- private readonly catalogEntryRepo;
192
- private readonly bundleRepo;
193
- constructor(planRepo: PlanRepository, marketingRepo: MarketingProjectionRepository, promotionRepo: PromotionRepository, catalogEntryRepo?: CatalogEntryRepository | null, bundleRepo?: BundleRepository | null);
194
- getCatalog(projectKey: string, locale: string, currency: string, vatRate: number, asOf?: Date): Promise<PublicMarketingCatalogResponse>;
195
- /**
196
- * Loads all published-and-live bundle versions for a project and
197
- * filters on `marketed === true`. Without a registered
198
- * `BundleRepository` (apps without the SuperAdmin bundle editor) the
199
- * list is empty — the public catalog stays plan-only.
200
- */
201
- private loadMarketedBundles;
202
- /**
203
- * Maps BundleVersionRow → PublicMarketingBundle. Locale resolution
204
- * runs via `MarketingProjectionRepository.findByTarget('BUNDLE',
205
- * bundleVersionId, locale)` — on a miss it falls back to
206
- * `DEFAULT_LOCALE`. If the fallback is missing too, label/description
207
- * come directly from the bundle root (denormalized in `BundleVersionRow`).
208
- *
209
- * If the marketing projection is `visible === false`, the bundle is
210
- * hidden from the public response (preparation phase).
211
- */
212
- private toPublicBundle;
213
- /**
214
- * Labels for bundle features ∪ their requires (#48): `comparison.features`
215
- * only covers the plan-feature union — bundle-only features would
216
- * otherwise get no label in the public payload. Curated keys only;
217
- * without a CatalogEntryRepository the map stays empty (frontends fall
218
- * back to the key).
219
- */
220
- private resolveBundleFeatureLabels;
221
- /** Loads the translated feature/quota labels (+ sortOrder) for a locale. */
222
- private loadLabelMeta;
223
- /**
224
- * Resolves the displayed label of a top feature: the `label` override
225
- * wins; otherwise the translated label of the referenced `key`.
226
- */
227
- private resolveTopFeature;
228
- /** Row definitions of the comparison matrix (feature/quota union + labels). */
229
- private buildComparison;
230
- private resolvePromo;
231
- }
232
-
233
15
  declare function buildPublicMarketingCatalogController(guards: Array<Type<CanActivate>>, projectKey: string, currency: string, vatRate: number): Type;
234
16
 
235
- declare class PlansService {
236
- private readonly repo;
237
- private readonly subscriptions;
238
- constructor(repo: PlanRepository, subscriptions?: SubscriptionRepository | null);
239
- /**
240
- * Platform-wide count of active (ACTIVE/TRIAL) subscriptions per `planKey`,
241
- * across versions and across all tenants (RLS-exempt). Plans without a
242
- * subscription are absent from the map. Returns `{}` when no
243
- * `SubscriptionRepository` is registered or it does not implement
244
- * `countActiveByPlanKey`.
245
- */
246
- getTenantCounts(projectKey: string): Promise<Record<string, number>>;
247
- listPlans(projectKey: string, opts?: {
248
- onlyPublished?: boolean;
249
- }): Promise<PlanRow[]>;
250
- getPlan(planId: string): Promise<PlanRow>;
251
- createPlan(data: CreatePlanData): Promise<PlanRow>;
252
- updatePlan(planId: string, data: UpdatePlanData): Promise<PlanRow>;
253
- softDeletePlan(planId: string): Promise<void>;
254
- /**
255
- * Hard-deletes the plan master record. Only allowed for plans without
256
- * `PlanVersion` entries — published versions are immutable under
257
- * contract protection P1 (existing subscriptions reference them). The
258
- * caller must discard drafts beforehand via `DELETE plan-versions/:id`.
259
- *
260
- * If the repository does not implement `hardDelete`, the endpoint
261
- * responds with 422 `PLAN_HARD_DELETE_NOT_IMPLEMENTED` — consumers can
262
- * then fall back to `softDelete`.
263
- */
264
- hardDeletePlan(planId: string): Promise<void>;
265
- /**
266
- * Platform invariant (contract protection P1): once a plan has ever had a
267
- * published version, its plan master record is retained — regardless of
268
- * whether the version has since been superseded. Subscriptions still
269
- * reference it via the version, and the audit log must be able to resolve
270
- * the plan.
271
- */
272
- private assertNoPublishedVersions;
273
- private assertNoDrafts;
274
- }
275
-
276
- declare class PlanVersionsService {
277
- private readonly repo;
278
- private readonly snapshot;
279
- private readonly subscriptions;
280
- private readonly scanner;
281
- private readonly catalogEntries;
282
- private readonly logger;
283
- private mode;
284
- private readonly marketedOnly;
285
- constructor(repo: PlanRepository, snapshot?: DiscoverySnapshot | null, config?: CatalogServiceConfig, subscriptions?: SubscriptionRepository | null, scanner?: DiscoveryScanner | null, catalogEntries?: CatalogEntryRepository | null);
286
- /**
287
- * Discards a draft version. Allowed only while the version has not yet
288
- * been published — published versions are preserved immutably,
289
- * because existing subscriptions reference them (contract protection P1).
290
- *
291
- * If the repository does not implement the method, the endpoint
292
- * responds with 501 Not Implemented (consumers without the editor stack
293
- * should not register `PlanVersionsService` anyway).
294
- */
295
- discardPlanDraft(versionId: string): Promise<void>;
296
- /**
297
- * @param planUuid UUID of the plan root (Plan.id) — resolved to planKey
298
- * before the repo call (lifecycle methods work with planKey because
299
- * PlanVersion.planId is a string in the schema).
300
- */
301
- listPlanVersions(planUuid: string): Promise<PlanVersionRow[]>;
302
- getPlanVersion(versionId: string): Promise<PlanVersionRow>;
303
- /**
304
- * Annotates each version with `isLatestInChain` (highest version number
305
- * in the root) + `subscriptionCount` so that UI and backend make the same
306
- * editability decision. `subscriptionCount` stays
307
- * `undefined` when no SubscriptionRepository is registered —
308
- * `isVersionEditable` interprets that fail-closed (= frozen).
309
- */
310
- private annotateEditability;
311
- /**
312
- * @param data.planId — the plan UUID from the controller. Resolved to
313
- * planKey before the repo call.
314
- */
315
- createPlanDraft(data: CreatePlanVersionDraftData): Promise<PlanVersionMutationResult>;
316
- updatePlanDraft(versionId: string, data: UpdatePlanVersionDraftData): Promise<PlanVersionMutationResult>;
317
- publishPlanVersion(versionId: string, publishMeta: PublishPlanVersionData): Promise<PlanVersionMutationResult>;
318
- /**
319
- * Terminates a **live** PlanVersion by setting `endsAt`.
320
- * Unlike auto-succession (validUntil), this is an explicit
321
- * user action: the version is not replaced by a successor version
322
- * but expires on the chosen date. Existing subscriptions
323
- * (P1) stay bound — this only affects new bookings.
324
- *
325
- * Idempotent — a second call with a different date overwrites.
326
- *
327
- * Preconditions:
328
- * - Version must be live (`publishedAt != null && supersededAt == null`).
329
- * - `endsAt` must lie in the future (`endsAt > now`).
330
- *
331
- * If the repository does not implement the method, the endpoint
332
- * responds with 422 `PLAN_TERMINATE_NOT_IMPLEMENTED`.
333
- */
334
- terminatePlanVersion(versionId: string, endsAt: Date): Promise<PlanVersionRow>;
335
- private runStrictCheck;
336
- private gateOrPass;
337
- }
338
-
339
17
  /**
340
18
  * Builds the controller class at boot time with the guards configured by the
341
19
  * consumer. Pattern analogous to `buildDiscoveryController`.
@@ -358,104 +36,6 @@ declare function buildPlansController(guards: Array<Type<CanActivate>>): Type;
358
36
  */
359
37
  declare function buildPlanVersionsController(guards: Array<Type<CanActivate>>): Type;
360
38
 
361
- interface CatalogControllerConfig {
362
- /**
363
- * Class-level guards for `BundlesController` and `BundleVersionsController`.
364
- * REQUIRED — otherwise `forRoot()` throws at boot. Pass `[]` explicitly
365
- * if the endpoints should intentionally be auth-free.
366
- */
367
- guards: Array<Type<CanActivate>>;
368
- }
369
- interface CatalogModuleOptions {
370
- /** Adapter for `bundles` + `bundle_versions` persistence. */
371
- bundleRepository: ProviderSpec<BundleRepository>;
372
- /**
373
- * Adapter for `marketing_projections` persistence. Optional — if
374
- * omitted, MarketingProjectionsService + controller are not
375
- * registered.
376
- */
377
- marketingProjectionRepository?: ProviderSpec<MarketingProjectionRepository>;
378
- /**
379
- * Adapter for `capability_/feature_/quota_catalog_entries` persistence
380
- * (discovery review, SPEC_V2 §6.3). Optional — if omitted,
381
- * CatalogEntriesService + controller are not registered.
382
- */
383
- catalogEntryRepository?: ProviderSpec<CatalogEntryRepository>;
384
- /**
385
- * Adapter for `promotions` persistence (SPEC_V2 §9a). Optional — if
386
- * omitted, PromotionsService + controller are not registered.
387
- */
388
- promotionRepository?: ProviderSpec<PromotionRepository>;
389
- /**
390
- * Adapter for `marketing_settings` persistence (SPEC_V2 §6.5 —
391
- * `activeLocales`). Optional.
392
- */
393
- marketingSettingsRepository?: ProviderSpec<MarketingSettingsRepository>;
394
- /**
395
- * Auth-free pricing-page endpoint `GET /public/marketing-catalog`
396
- * (SPEC_V2 §9). Registered only when plan-, marketingProjection-
397
- * and promotionRepository are set. `guards` is usually `[]`.
398
- */
399
- publicMarketingCatalog?: {
400
- guards: Array<Type<CanActivate>>;
401
- projectKey: string;
402
- currency: string;
403
- vatRate: number;
404
- };
405
- /**
406
- * SPEC_V2 §11.1 M6 (Pack 1) — adapter for `plans` master-record persistence.
407
- * Optional; if omitted, PlansService + controller are not
408
- * registered (apps without a need for the plan editor stay unchanged).
409
- */
410
- planRepository?: ProviderSpec<PlanRepository>;
411
- /**
412
- * Controller mount for `/admin/catalog/bundles` + `/admin/catalog/bundle-versions`.
413
- * If omitted, the endpoints are not registered — but the services remain usable via DI.
414
- */
415
- controller?: CatalogControllerConfig;
416
- /**
417
- * Strict-mode mode. `blocking` (default, #12) throws HTTP 422 on
418
- * violations and requires a DiscoverySnapshot; `warn-only` returns them
419
- * only as a warning (transition until 100% discovery coverage).
420
- */
421
- strictModeCheckMode?: 'warn-only' | 'blocking';
422
- /**
423
- * Discovery→catalog auto-sync at boot (#12). Default `true` — as soon as a
424
- * `catalogEntryRepository` is wired and a DiscoverySnapshot is available,
425
- * `CatalogEntriesService` mirrors the discovery into the DB at startup. `false`
426
- * disables the boot sync; the manual sync endpoint remains usable.
427
- */
428
- autoSyncDiscoveryAtBoot?: boolean;
429
- /**
430
- * Feature keys the catalog is deliberately allowed to carry without them
431
- * existing in the discovery snapshot (marketed non-code features such as
432
- * support SLAs, e.g. `['PRIORITY_SUPPORT']`). The strict-mode check excludes
433
- * them from BUNDLE_/PLAN_FEATURE_UNKNOWN. Use sparingly.
434
- */
435
- marketedOnlyFeatures?: string[];
436
- /**
437
- * Optional consumer-curated FeatureUiRegistry (label/description/icon
438
- * per feature — the same one passed to `PublicCatalogModule.forRoot`). The
439
- * discovery auto-sync seeds EMPTY `FeatureCatalogEntry` fields
440
- * (label/description/icon) from it at boot; SuperAdmin edits stay untouched. This
441
- * makes `FeatureCatalogEntry` the SSOT for UI metadata (SPEC_V2 §6.3 / #12).
442
- */
443
- featureUiRegistry?: FeatureUiRegistry;
444
- /**
445
- * Modules whose providers must be visible in the DI scope of this
446
- * DynamicModule — typically: `AuthModule`/`PlatformAdminModule`, because the
447
- * controller guards come from there.
448
- */
449
- imports?: Array<Type<unknown> | DynamicModule | Promise<DynamicModule> | ForwardReference>;
450
- /** Additional providers registered in the DynamicModule itself. */
451
- extraProviders?: Provider[];
452
- /** Register the module globally — default `false`. */
453
- global?: boolean;
454
- }
455
- declare class CatalogModule {
456
- static forRoot(options: CatalogModuleOptions): DynamicModule;
457
- }
458
-
459
39
  /** Repository for `plans` (SPEC_V2 §11.1 M6 — Plan master CRUD). */
460
40
  declare const PLAN_REPOSITORY_TOKEN: unique symbol;
461
41
  /** Repository for `bundles` + `bundle_versions`. */
@@ -955,4 +535,4 @@ declare class PublishPlanVersionDto {
955
535
  validUntil?: string | null;
956
536
  }
957
537
 
958
- export { ADVISORY_STRICT_MODE_CODES, BUNDLE_REPOSITORY_TOKEN, BundlesService, CATALOG_ENTRY_REPOSITORY_TOKEN, CATALOG_SERVICE_CONFIG_TOKEN, type CatalogControllerConfig, CatalogEntriesService, CatalogModule, type CatalogModuleOptions, type CatalogServiceConfig, CreateBundleDto, CreateBundleVersionDraftDto, CreateMarketingProjectionDto, CreatePlanDto, CreatePlanVersionDraftDto, CreatePromotionDto, ListCatalogEntriesQueryDto, ListMarketingProjectionsQueryDto, ListMarketingSettingsQueryDto, ListPromotionsQueryDto, MARKETING_PROJECTION_REPOSITORY_TOKEN, MARKETING_SETTINGS_REPOSITORY_TOKEN, MarketingProjectionsService, MarketingSettingsService, PLAN_REPOSITORY_TOKEN, PROMOTION_REPOSITORY_TOKEN, PlanVersionsService, PlansService, type PreflightFinding, type PreflightInput, type PreflightReport, PromotionsService, PublicMarketingCatalogService, PublishBundleVersionDto, PublishPlanVersionDto, ReviewCatalogEntryDto, type SeedBundleDraft, type SeedGateFinding, type SeedGateInput, type SeedGateMode, type SeedGateReport, type SeedGateRunOptions, type SeedPlanDraft, SyncDiscoveryDto, UpdateBundleDto, UpdateBundleVersionDraftDto, UpdateCatalogEntryI18nDto, UpdateMarketingProjectionDto, UpdateMarketingSettingsDto, UpdatePlanDto, UpdatePlanVersionDraftDto, UpdatePromotionDto, blockingStrictModeWarnings, buildBundleVersionsController, buildBundlesController, buildCatalogEntriesController, buildMarketingProjectionsController, buildMarketingSettingsController, buildPlanVersionsController, buildPlansController, buildPromotionsController, buildPublicMarketingCatalogController, featureApprovalSignature, formatPreflightReport, formatSeedGateReport, loadApprovedCatalogKeys, preflightExitCode, quotaApprovalSignature, runPreflight, runSeedGateFromFile, seedGateExitCode, validateBundleDraft, validatePlanDraft, validateSeedAgainstSnapshot };
538
+ export { ADVISORY_STRICT_MODE_CODES, BUNDLE_REPOSITORY_TOKEN, CATALOG_ENTRY_REPOSITORY_TOKEN, CATALOG_SERVICE_CONFIG_TOKEN, CreateBundleDto, CreateBundleVersionDraftDto, CreateMarketingProjectionDto, CreatePlanDto, CreatePlanVersionDraftDto, CreatePromotionDto, ListCatalogEntriesQueryDto, ListMarketingProjectionsQueryDto, ListMarketingSettingsQueryDto, ListPromotionsQueryDto, MARKETING_PROJECTION_REPOSITORY_TOKEN, MARKETING_SETTINGS_REPOSITORY_TOKEN, PLAN_REPOSITORY_TOKEN, PROMOTION_REPOSITORY_TOKEN, type PreflightFinding, type PreflightInput, type PreflightReport, PublishBundleVersionDto, PublishPlanVersionDto, ReviewCatalogEntryDto, type SeedBundleDraft, type SeedGateFinding, type SeedGateInput, type SeedGateMode, type SeedGateReport, type SeedGateRunOptions, type SeedPlanDraft, SyncDiscoveryDto, UpdateBundleDto, UpdateBundleVersionDraftDto, UpdateCatalogEntryI18nDto, UpdateMarketingProjectionDto, UpdateMarketingSettingsDto, UpdatePlanDto, UpdatePlanVersionDraftDto, UpdatePromotionDto, blockingStrictModeWarnings, buildBundleVersionsController, buildBundlesController, buildCatalogEntriesController, buildMarketingProjectionsController, buildMarketingSettingsController, buildPlanVersionsController, buildPlansController, buildPromotionsController, buildPublicMarketingCatalogController, featureApprovalSignature, formatPreflightReport, formatSeedGateReport, loadApprovedCatalogKeys, preflightExitCode, quotaApprovalSignature, runPreflight, runSeedGateFromFile, seedGateExitCode, validateBundleDraft, validatePlanDraft, validateSeedAgainstSnapshot };