@saasicat/nest 0.2.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 (96) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +53 -0
  3. package/dist/admin/index.cjs +1283 -0
  4. package/dist/admin/index.d.cts +225 -0
  5. package/dist/admin/index.d.ts +225 -0
  6. package/dist/admin/index.js +58 -0
  7. package/dist/admin-audit.service-9IqXMlZm.d.cts +30 -0
  8. package/dist/admin-audit.service-9IqXMlZm.d.ts +30 -0
  9. package/dist/admin-manifest.config-DyrQNT7M.d.cts +10 -0
  10. package/dist/admin-manifest.config-DyrQNT7M.d.ts +10 -0
  11. package/dist/aggregation-CJ3qQf92.d.cts +288 -0
  12. package/dist/aggregation-Dvz9e8X2.d.ts +288 -0
  13. package/dist/billing/index.cjs +5205 -0
  14. package/dist/billing/index.d.cts +1326 -0
  15. package/dist/billing/index.d.ts +1326 -0
  16. package/dist/billing/index.js +197 -0
  17. package/dist/catalog/index.cjs +6449 -0
  18. package/dist/catalog/index.d.cts +1073 -0
  19. package/dist/catalog/index.d.ts +1073 -0
  20. package/dist/catalog/index.js +158 -0
  21. package/dist/checkout-offer/index.cjs +807 -0
  22. package/dist/checkout-offer/index.d.cts +120 -0
  23. package/dist/checkout-offer/index.d.ts +120 -0
  24. package/dist/checkout-offer/index.js +20 -0
  25. package/dist/chunk-2FR6ZL7R.js +0 -0
  26. package/dist/chunk-2PNX2QL2.js +347 -0
  27. package/dist/chunk-2VNZYRDV.js +326 -0
  28. package/dist/chunk-7MLGHWKO.js +12 -0
  29. package/dist/chunk-ABB2CRAS.js +31 -0
  30. package/dist/chunk-AJ3EPELS.js +157 -0
  31. package/dist/chunk-E56W4U2P.js +90 -0
  32. package/dist/chunk-HRU3CP57.js +71 -0
  33. package/dist/chunk-L4SUWH5B.js +14 -0
  34. package/dist/chunk-M6CZQYPY.js +314 -0
  35. package/dist/chunk-MDIZUVIK.js +87 -0
  36. package/dist/chunk-MV6LW5UB.js +217 -0
  37. package/dist/chunk-NYLON2VC.js +6 -0
  38. package/dist/chunk-P6MYZMXQ.js +951 -0
  39. package/dist/chunk-Q53N43LQ.js +13 -0
  40. package/dist/chunk-QJVPRD3R.js +573 -0
  41. package/dist/chunk-RIGLQ4BV.js +3367 -0
  42. package/dist/chunk-SABTXESR.js +24 -0
  43. package/dist/chunk-SHUYVCID.js +6 -0
  44. package/dist/chunk-SYEVGPFC.js +686 -0
  45. package/dist/chunk-V7HUZ6UQ.js +5923 -0
  46. package/dist/chunk-WPUVJRIN.js +29 -0
  47. package/dist/chunk-XCZ3TTFK.js +22 -0
  48. package/dist/chunk-XSGU2Y2O.js +1611 -0
  49. package/dist/chunk-YNEW3L63.js +190 -0
  50. package/dist/chunk-YXGHPILG.js +614 -0
  51. package/dist/chunk-ZL4LLE2Z.js +465 -0
  52. package/dist/di-CcNeq9v-.d.cts +16 -0
  53. package/dist/di-CcNeq9v-.d.ts +16 -0
  54. package/dist/discovery/index.cjs +588 -0
  55. package/dist/discovery/index.d.cts +299 -0
  56. package/dist/discovery/index.d.ts +299 -0
  57. package/dist/discovery/index.js +49 -0
  58. package/dist/discovery.scanner-CUYLKlYT.d.cts +59 -0
  59. package/dist/discovery.scanner-CUYLKlYT.d.ts +59 -0
  60. package/dist/entitlement/index.cjs +805 -0
  61. package/dist/entitlement/index.d.cts +60 -0
  62. package/dist/entitlement/index.d.ts +60 -0
  63. package/dist/entitlement/index.js +57 -0
  64. package/dist/index.cjs +15918 -0
  65. package/dist/index.d.cts +85 -0
  66. package/dist/index.d.ts +85 -0
  67. package/dist/index.js +956 -0
  68. package/dist/plan-resolution-CFCoUkrE.d.cts +41 -0
  69. package/dist/plan-resolution-CFCoUkrE.d.ts +41 -0
  70. package/dist/platform/index.cjs +2772 -0
  71. package/dist/platform/index.d.cts +118 -0
  72. package/dist/platform/index.d.ts +118 -0
  73. package/dist/platform/index.js +37 -0
  74. package/dist/promo/index.cjs +995 -0
  75. package/dist/promo/index.d.cts +121 -0
  76. package/dist/promo/index.d.ts +121 -0
  77. package/dist/promo/index.js +58 -0
  78. package/dist/registration/index.cjs +1687 -0
  79. package/dist/registration/index.d.cts +444 -0
  80. package/dist/registration/index.d.ts +444 -0
  81. package/dist/registration/index.js +82 -0
  82. package/dist/saas-platform.module-CgZ2omgg.d.cts +180 -0
  83. package/dist/saas-platform.module-DT9TnCzk.d.ts +180 -0
  84. package/dist/service-DX8KbGXl.d.cts +109 -0
  85. package/dist/service-DX8KbGXl.d.ts +109 -0
  86. package/dist/subscription-contract/index.cjs +471 -0
  87. package/dist/subscription-contract/index.d.cts +17 -0
  88. package/dist/subscription-contract/index.d.ts +17 -0
  89. package/dist/subscription-contract/index.js +21 -0
  90. package/dist/subscription-contract.service--cm47ZJJ.d.cts +39 -0
  91. package/dist/subscription-contract.service--cm47ZJJ.d.ts +39 -0
  92. package/dist/testing/index.cjs +3942 -0
  93. package/dist/testing/index.d.cts +279 -0
  94. package/dist/testing/index.d.ts +279 -0
  95. package/dist/testing/index.js +1195 -0
  96. package/package.json +185 -0
@@ -0,0 +1,13 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-SHUYVCID.js";
4
+
5
+ // src/billing/require-feature.decorator.ts
6
+ import { SetMetadata } from "@nestjs/common";
7
+ var REQUIRE_FEATURE_KEY = "require-feature";
8
+ var RequireFeature = /* @__PURE__ */ __name((...features) => SetMetadata(REQUIRE_FEATURE_KEY, features), "RequireFeature");
9
+
10
+ export {
11
+ REQUIRE_FEATURE_KEY,
12
+ RequireFeature
13
+ };
@@ -0,0 +1,573 @@
1
+ import {
2
+ ADMIN_MANIFEST_CONFIG,
3
+ AdminManifestModule,
4
+ AdminModule
5
+ } from "./chunk-P6MYZMXQ.js";
6
+ import {
7
+ REQUIRE_FEATURE_KEY
8
+ } from "./chunk-Q53N43LQ.js";
9
+ import {
10
+ DiscoveryModule
11
+ } from "./chunk-AJ3EPELS.js";
12
+ import {
13
+ EntitlementModule,
14
+ LimitExceededError
15
+ } from "./chunk-YXGHPILG.js";
16
+ import {
17
+ PLAN_CATALOG_TOKEN,
18
+ PlanCatalogModule
19
+ } from "./chunk-MV6LW5UB.js";
20
+ import {
21
+ asProvider
22
+ } from "./chunk-SABTXESR.js";
23
+ import {
24
+ ENFORCE_QUOTA_KEY
25
+ } from "./chunk-L4SUWH5B.js";
26
+ import {
27
+ __name
28
+ } from "./chunk-SHUYVCID.js";
29
+
30
+ // src/platform/plan-resolver.port.ts
31
+ var PLAN_RESOLVER_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/PlanResolverPort");
32
+ var StaticPlanResolver = class {
33
+ static {
34
+ __name(this, "StaticPlanResolver");
35
+ }
36
+ planId;
37
+ constructor(planId) {
38
+ this.planId = planId;
39
+ }
40
+ async getPlanIdForTenant() {
41
+ return this.planId;
42
+ }
43
+ };
44
+
45
+ // src/platform/static-entitlement.service.ts
46
+ import { Inject, Injectable } from "@nestjs/common";
47
+ function _ts_decorate(decorators, target, key, desc) {
48
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
49
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
50
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
51
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
52
+ }
53
+ __name(_ts_decorate, "_ts_decorate");
54
+ function _ts_metadata(k, v) {
55
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
56
+ }
57
+ __name(_ts_metadata, "_ts_metadata");
58
+ function _ts_param(paramIndex, decorator) {
59
+ return function(target, key) {
60
+ decorator(target, key, paramIndex);
61
+ };
62
+ }
63
+ __name(_ts_param, "_ts_param");
64
+ var StaticEntitlementService = class {
65
+ static {
66
+ __name(this, "StaticEntitlementService");
67
+ }
68
+ catalog;
69
+ resolver;
70
+ constructor(catalog, resolver) {
71
+ this.catalog = catalog;
72
+ this.resolver = resolver;
73
+ }
74
+ /**
75
+ * Returns the effective features + quotas of a tenant from the
76
+ * plan catalog. When the plan is missing: an empty snapshot (no feature,
77
+ * all quotas at 0).
78
+ */
79
+ async snapshot(tenantId) {
80
+ const planId = await this.resolver.getPlanIdForTenant(tenantId);
81
+ if (!planId) {
82
+ return {
83
+ planId: null,
84
+ features: [],
85
+ quotas: {}
86
+ };
87
+ }
88
+ const plan = this.findPlan(planId);
89
+ if (!plan) {
90
+ return {
91
+ planId,
92
+ features: [],
93
+ quotas: {}
94
+ };
95
+ }
96
+ return {
97
+ planId,
98
+ features: plan.features ?? [],
99
+ quotas: plan.quotas ?? {}
100
+ };
101
+ }
102
+ /** Convenience helper for tests / synchronous checks in the UI manifest. */
103
+ async hasFeature(tenantId, featureKey) {
104
+ const snap = await this.snapshot(tenantId);
105
+ return snap.features.includes(featureKey);
106
+ }
107
+ async quotaLimit(tenantId, quotaKey) {
108
+ const snap = await this.snapshot(tenantId);
109
+ const value = snap.quotas[quotaKey];
110
+ return value === void 0 ? null : value;
111
+ }
112
+ findPlan(planId) {
113
+ return (this.catalog.plans ?? []).find((p) => p.id === planId);
114
+ }
115
+ };
116
+ StaticEntitlementService = _ts_decorate([
117
+ Injectable(),
118
+ _ts_param(0, Inject(PLAN_CATALOG_TOKEN)),
119
+ _ts_param(1, Inject(PLAN_RESOLVER_PORT_TOKEN)),
120
+ _ts_metadata("design:type", Function),
121
+ _ts_metadata("design:paramtypes", [
122
+ typeof PlanCatalog === "undefined" ? Object : PlanCatalog,
123
+ typeof PlanResolverPort === "undefined" ? Object : PlanResolverPort
124
+ ])
125
+ ], StaticEntitlementService);
126
+
127
+ // src/platform/static-feature.guard.ts
128
+ import { ForbiddenException, Inject as Inject2, Injectable as Injectable2, Optional } from "@nestjs/common";
129
+ import { Reflector } from "@nestjs/core";
130
+ function _ts_decorate2(decorators, target, key, desc) {
131
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
132
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
133
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
134
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
135
+ }
136
+ __name(_ts_decorate2, "_ts_decorate");
137
+ function _ts_metadata2(k, v) {
138
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
139
+ }
140
+ __name(_ts_metadata2, "_ts_metadata");
141
+ function _ts_param2(paramIndex, decorator) {
142
+ return function(target, key) {
143
+ decorator(target, key, paramIndex);
144
+ };
145
+ }
146
+ __name(_ts_param2, "_ts_param");
147
+ var STATIC_FEATURE_GUARD_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/StaticFeatureGuardConfig");
148
+ var StaticFeatureGuard = class {
149
+ static {
150
+ __name(this, "StaticFeatureGuard");
151
+ }
152
+ reflector;
153
+ entitlements;
154
+ config;
155
+ constructor(reflector, entitlements, config = null) {
156
+ this.reflector = reflector;
157
+ this.entitlements = entitlements;
158
+ this.config = config;
159
+ }
160
+ async canActivate(context) {
161
+ const required = this.reflector.getAllAndOverride(REQUIRE_FEATURE_KEY, [
162
+ context.getHandler(),
163
+ context.getClass()
164
+ ]);
165
+ if (!required || required.length === 0) return true;
166
+ const request = context.switchToHttp().getRequest();
167
+ const user = request.user;
168
+ if (!user) throw new ForbiddenException("Nicht authentifiziert");
169
+ const role = this.config?.userRoleResolver ? this.config.userRoleResolver(user) : user.role ?? user.platformRole;
170
+ if (role === "SUPER_ADMIN") return true;
171
+ const tenantId = this.config?.tenantIdResolver ? this.config.tenantIdResolver(request) : request.tenantId ?? user.tenantId;
172
+ if (!tenantId) throw new ForbiddenException("Kein Mandant zugeordnet");
173
+ const snap = await this.entitlements.snapshot(tenantId);
174
+ const allowed = required.some((f) => snap.features.includes(f));
175
+ if (!allowed) {
176
+ throw new ForbiddenException(`Feature ${required.join(" / ")} nicht im aktuellen Plan enthalten.`);
177
+ }
178
+ return true;
179
+ }
180
+ };
181
+ StaticFeatureGuard = _ts_decorate2([
182
+ Injectable2(),
183
+ _ts_param2(0, Inject2(Reflector)),
184
+ _ts_param2(1, Inject2(StaticEntitlementService)),
185
+ _ts_param2(2, Optional()),
186
+ _ts_param2(2, Inject2(STATIC_FEATURE_GUARD_CONFIG_TOKEN)),
187
+ _ts_metadata2("design:type", Function),
188
+ _ts_metadata2("design:paramtypes", [
189
+ typeof Reflector === "undefined" ? Object : Reflector,
190
+ typeof StaticEntitlementService === "undefined" ? Object : StaticEntitlementService,
191
+ Object
192
+ ])
193
+ ], StaticFeatureGuard);
194
+
195
+ // src/platform/enforce-quota.interceptor.ts
196
+ import { Inject as Inject3, Injectable as Injectable3, Optional as Optional2 } from "@nestjs/common";
197
+ import { Reflector as Reflector2 } from "@nestjs/core";
198
+ import { from } from "rxjs";
199
+ import { switchMap } from "rxjs/operators";
200
+ function _ts_decorate3(decorators, target, key, desc) {
201
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
202
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
203
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
204
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
205
+ }
206
+ __name(_ts_decorate3, "_ts_decorate");
207
+ function _ts_metadata3(k, v) {
208
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
209
+ }
210
+ __name(_ts_metadata3, "_ts_metadata");
211
+ function _ts_param3(paramIndex, decorator) {
212
+ return function(target, key) {
213
+ decorator(target, key, paramIndex);
214
+ };
215
+ }
216
+ __name(_ts_param3, "_ts_param");
217
+ var QUOTA_PROVIDERS_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/QuotaProviders");
218
+ var EnforceQuotaInterceptor = class {
219
+ static {
220
+ __name(this, "EnforceQuotaInterceptor");
221
+ }
222
+ reflector;
223
+ entitlements;
224
+ providers;
225
+ constructor(reflector, entitlements, providers = null) {
226
+ this.reflector = reflector;
227
+ this.entitlements = entitlements;
228
+ this.providers = providers;
229
+ }
230
+ intercept(context, next) {
231
+ const meta = this.reflector.getAllAndOverride(ENFORCE_QUOTA_KEY, [
232
+ context.getHandler(),
233
+ context.getClass()
234
+ ]);
235
+ if (!meta?.quotaKey) return next.handle();
236
+ return from(this.check(context, meta)).pipe(switchMap(() => next.handle()));
237
+ }
238
+ async check(context, meta) {
239
+ const request = context.switchToHttp().getRequest();
240
+ const user = request.user;
241
+ if (!user) return;
242
+ const role = user.role ?? user.platformRole;
243
+ if (role === "SUPER_ADMIN") return;
244
+ const tenantId = request.tenantId ?? user.tenantId;
245
+ if (!tenantId) return;
246
+ const provider = (this.providers ?? []).find((p) => p.key === meta.quotaKey);
247
+ if (!provider) {
248
+ return;
249
+ }
250
+ const limit = await this.entitlements.quotaLimit(tenantId, meta.quotaKey);
251
+ if (limit === null || limit === -1) return;
252
+ const current = await provider.count(tenantId);
253
+ const delta = meta.incrementBy ?? 1;
254
+ if (current + delta > limit) {
255
+ throw new LimitExceededError(meta.quotaKey, limit, current);
256
+ }
257
+ }
258
+ };
259
+ EnforceQuotaInterceptor = _ts_decorate3([
260
+ Injectable3(),
261
+ _ts_param3(0, Inject3(Reflector2)),
262
+ _ts_param3(1, Inject3(StaticEntitlementService)),
263
+ _ts_param3(2, Optional2()),
264
+ _ts_param3(2, Inject3(QUOTA_PROVIDERS_TOKEN)),
265
+ _ts_metadata3("design:type", Function),
266
+ _ts_metadata3("design:paramtypes", [
267
+ typeof Reflector2 === "undefined" ? Object : Reflector2,
268
+ typeof StaticEntitlementService === "undefined" ? Object : StaticEntitlementService,
269
+ Object
270
+ ])
271
+ ], EnforceQuotaInterceptor);
272
+
273
+ // src/platform/tenant-manifest.service.ts
274
+ import { Injectable as Injectable4 } from "@nestjs/common";
275
+ function _ts_decorate4(decorators, target, key, desc) {
276
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
277
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
278
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
279
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
280
+ }
281
+ __name(_ts_decorate4, "_ts_decorate");
282
+ function _ts_metadata4(k, v) {
283
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
284
+ }
285
+ __name(_ts_metadata4, "_ts_metadata");
286
+ var TenantManifestService = class {
287
+ static {
288
+ __name(this, "TenantManifestService");
289
+ }
290
+ entitlements;
291
+ navItems = [];
292
+ constructor(entitlements) {
293
+ this.entitlements = entitlements;
294
+ }
295
+ /**
296
+ * Call in the app's `OnModuleInit`: registers app navigation for the
297
+ * Tenant UI. Idempotent: the same `id` overwrites.
298
+ */
299
+ registerNavItem(item) {
300
+ const existing = this.navItems.findIndex((i) => i.id === item.id);
301
+ if (existing >= 0) this.navItems[existing] = item;
302
+ else this.navItems.push(item);
303
+ }
304
+ /** Bulk variant. */
305
+ registerNavItems(items) {
306
+ for (const item of items) this.registerNavItem(item);
307
+ }
308
+ /**
309
+ * Returns the filtered manifest for a Tenant. NavItems with
310
+ * `requiresFeature` are filtered out server-side as soon as none of the
311
+ * required features are present in the entitlement snapshot.
312
+ */
313
+ async getManifest(tenantId) {
314
+ const snap = await this.entitlements.snapshot(tenantId);
315
+ const featureSet = new Set(snap.features);
316
+ const visible = this.navItems.filter((item) => isVisible(item, featureSet)).map((item) => ({
317
+ ...item
318
+ })).sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
319
+ return {
320
+ schemaVersion: 1,
321
+ tenant: {
322
+ id: tenantId
323
+ },
324
+ planId: snap.planId,
325
+ features: snap.features,
326
+ quotas: snap.quotas,
327
+ navigation: visible
328
+ };
329
+ }
330
+ };
331
+ TenantManifestService = _ts_decorate4([
332
+ Injectable4(),
333
+ _ts_metadata4("design:type", Function),
334
+ _ts_metadata4("design:paramtypes", [
335
+ typeof StaticEntitlementService === "undefined" ? Object : StaticEntitlementService
336
+ ])
337
+ ], TenantManifestService);
338
+ function isVisible(item, features) {
339
+ if (!item.requiresFeature) return true;
340
+ const required = Array.isArray(item.requiresFeature) ? item.requiresFeature : [
341
+ item.requiresFeature
342
+ ];
343
+ return required.some((f) => features.has(f));
344
+ }
345
+ __name(isVisible, "isVisible");
346
+
347
+ // src/platform/tenant-manifest.controller.ts
348
+ import { Controller, Get, Inject as Inject4, Req, UseGuards } from "@nestjs/common";
349
+ function _ts_decorate5(decorators, target, key, desc) {
350
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
351
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
352
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
353
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
354
+ }
355
+ __name(_ts_decorate5, "_ts_decorate");
356
+ function _ts_metadata5(k, v) {
357
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
358
+ }
359
+ __name(_ts_metadata5, "_ts_metadata");
360
+ function _ts_param4(paramIndex, decorator) {
361
+ return function(target, key) {
362
+ decorator(target, key, paramIndex);
363
+ };
364
+ }
365
+ __name(_ts_param4, "_ts_param");
366
+ function buildTenantManifestController(options) {
367
+ const path = options.path ?? "tenant/manifest";
368
+ let GeneratedTenantManifestController = class GeneratedTenantManifestController {
369
+ static {
370
+ __name(this, "GeneratedTenantManifestController");
371
+ }
372
+ svc;
373
+ constructor(svc) {
374
+ this.svc = svc;
375
+ }
376
+ async get(req) {
377
+ const tenantId = req.user?.tenantId ?? req.tenantId;
378
+ if (!tenantId) {
379
+ throw new Error("Kein Mandant im Request \u2014 TenantManifest braucht user.tenantId.");
380
+ }
381
+ return this.svc.getManifest(tenantId);
382
+ }
383
+ };
384
+ _ts_decorate5([
385
+ Get(),
386
+ _ts_param4(0, Req()),
387
+ _ts_metadata5("design:type", Function),
388
+ _ts_metadata5("design:paramtypes", [
389
+ typeof RequestWithUser === "undefined" ? Object : RequestWithUser
390
+ ]),
391
+ _ts_metadata5("design:returntype", Promise)
392
+ ], GeneratedTenantManifestController.prototype, "get", null);
393
+ GeneratedTenantManifestController = _ts_decorate5([
394
+ Controller(path),
395
+ UseGuards(...options.guards),
396
+ _ts_param4(0, Inject4(TenantManifestService)),
397
+ _ts_metadata5("design:type", Function),
398
+ _ts_metadata5("design:paramtypes", [
399
+ typeof TenantManifestService === "undefined" ? Object : TenantManifestService
400
+ ])
401
+ ], GeneratedTenantManifestController);
402
+ return GeneratedTenantManifestController;
403
+ }
404
+ __name(buildTenantManifestController, "buildTenantManifestController");
405
+
406
+ // src/platform/saas-platform.module.ts
407
+ import { Module } from "@nestjs/common";
408
+ import { APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
409
+ function _ts_decorate6(decorators, target, key, desc) {
410
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
411
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
412
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
413
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
414
+ }
415
+ __name(_ts_decorate6, "_ts_decorate");
416
+ function buildMinimalManifestConfig() {
417
+ return {
418
+ useFactory: /* @__PURE__ */ __name((catalog) => ({
419
+ project: {
420
+ key: catalog.projectKey,
421
+ displayName: catalog.app?.name ?? catalog.projectKey,
422
+ label: catalog.app?.label,
423
+ icon: catalog.app?.icon,
424
+ logoUrl: catalog.app?.logoUrl,
425
+ environment: process.env.NODE_ENV === "production" ? "production" : "development",
426
+ availableLocales: catalog.marketing?.availableLocales,
427
+ defaultLocale: catalog.marketing?.availableLocales?.[0]
428
+ },
429
+ build: {
430
+ platformPackageVersion: "0.0.0",
431
+ appVersion: "0.0.0"
432
+ },
433
+ planCatalogSnapshot: {
434
+ source: "saas-platform-module",
435
+ hash: "sha256-quickstart",
436
+ currency: catalog.currency,
437
+ vatRate: catalog.vatRate,
438
+ plans: catalog.plans ?? [],
439
+ features: catalog.features ?? []
440
+ }
441
+ }), "useFactory"),
442
+ inject: [
443
+ PLAN_CATALOG_TOKEN
444
+ ]
445
+ };
446
+ }
447
+ __name(buildMinimalManifestConfig, "buildMinimalManifestConfig");
448
+ var SaasPlatformModule = class _SaasPlatformModule {
449
+ static {
450
+ __name(this, "SaasPlatformModule");
451
+ }
452
+ static forRoot(options) {
453
+ if (!options.planCatalog && !options.adapters.planCatalogReadSink) {
454
+ throw new Error("SaasPlatformModule.forRoot: entweder `planCatalog` (Quickstart) oder `adapters.planCatalogReadSink` (DB-Hydration) muss gesetzt sein.");
455
+ }
456
+ if (options.entitlement) {
457
+ const missing = [];
458
+ if (!options.adapters.subscriptionRepository) missing.push("subscriptionRepository");
459
+ if (!options.adapters.planVersionRepository) missing.push("planVersionRepository");
460
+ if (!options.adapters.transactionRunner) missing.push("transactionRunner");
461
+ if (missing.length) {
462
+ throw new Error(`SaasPlatformModule.forRoot: entitlement aktiv, aber Adapter fehlen: ${missing.join(", ")}`);
463
+ }
464
+ }
465
+ const planCatalogModule = options.planCatalog ? PlanCatalogModule.forRootWithCatalog(options.planCatalog, {
466
+ global: true
467
+ }) : PlanCatalogModule.forRoot({
468
+ projectKey: "",
469
+ currency: "",
470
+ vatRate: 0,
471
+ sink: options.adapters.planCatalogReadSink,
472
+ imports: options.imports
473
+ });
474
+ const appInfo = options.app ?? {
475
+ key: options.planCatalog?.projectKey ?? "app",
476
+ version: options.planCatalog?.app?.version ?? "0.0.0"
477
+ };
478
+ const imports = [
479
+ planCatalogModule,
480
+ DiscoveryModule.forRoot({
481
+ app: appInfo,
482
+ controller: {
483
+ guards: options.controller.guards
484
+ },
485
+ imports: options.imports,
486
+ snapshotPath: options.discoverySnapshotPath === void 0 ? "var/discovery-snapshot.json" : options.discoverySnapshotPath
487
+ }),
488
+ AdminModule.forRoot({
489
+ mfaPort: options.adapters.mfa,
490
+ auditPort: options.adapters.audit,
491
+ rlsBypassPort: options.adapters.rlsBypass,
492
+ global: true
493
+ }),
494
+ AdminManifestModule.forRoot({
495
+ config: options.adminManifestConfig ?? buildMinimalManifestConfig(),
496
+ guards: options.controller.guards,
497
+ reloadGuards: options.reloadGuards
498
+ })
499
+ ];
500
+ if (options.entitlement) {
501
+ imports.push(EntitlementModule.forRoot({
502
+ subscriptionRepository: options.adapters.subscriptionRepository,
503
+ planVersionRepository: options.adapters.planVersionRepository,
504
+ transactionRunner: options.adapters.transactionRunner,
505
+ resolutionConfig: options.entitlement.resolutionConfig
506
+ }));
507
+ }
508
+ const lightweightProviders = [];
509
+ const lightweightExports = [];
510
+ const hasResolver = !!options.adapters.planResolver;
511
+ const hasFallback = !!options.defaultPlanId;
512
+ if (hasResolver || hasFallback) {
513
+ lightweightProviders.push(hasResolver ? asProvider(PLAN_RESOLVER_PORT_TOKEN, options.adapters.planResolver) : {
514
+ provide: PLAN_RESOLVER_PORT_TOKEN,
515
+ useValue: new StaticPlanResolver(options.defaultPlanId)
516
+ }, StaticEntitlementService, StaticFeatureGuard, EnforceQuotaInterceptor, ...options.quotaProviders ?? [], {
517
+ provide: QUOTA_PROVIDERS_TOKEN,
518
+ useFactory: /* @__PURE__ */ __name((...providers) => providers, "useFactory"),
519
+ inject: options.quotaProviders ?? []
520
+ }, {
521
+ provide: APP_GUARD,
522
+ useExisting: StaticFeatureGuard
523
+ }, {
524
+ provide: APP_INTERCEPTOR,
525
+ useExisting: EnforceQuotaInterceptor
526
+ });
527
+ lightweightExports.push(PLAN_RESOLVER_PORT_TOKEN, StaticEntitlementService, StaticFeatureGuard, EnforceQuotaInterceptor, QUOTA_PROVIDERS_TOKEN);
528
+ }
529
+ const tenantControllers = [];
530
+ if (options.tenantManifest) {
531
+ if (!hasResolver && !hasFallback) {
532
+ throw new Error("SaasPlatformModule.forRoot: tenantManifest erfordert defaultPlanId oder adapters.planResolver, sonst kann das Manifest keine Features aufl\xF6sen.");
533
+ }
534
+ lightweightProviders.push(TenantManifestService);
535
+ lightweightExports.push(TenantManifestService);
536
+ tenantControllers.push(buildTenantManifestController(options.tenantManifest));
537
+ }
538
+ return {
539
+ module: _SaasPlatformModule,
540
+ imports,
541
+ providers: lightweightProviders,
542
+ controllers: tenantControllers,
543
+ exports: [
544
+ PlanCatalogModule,
545
+ DiscoveryModule,
546
+ AdminModule,
547
+ AdminManifestModule,
548
+ ...options.entitlement ? [
549
+ EntitlementModule
550
+ ] : [],
551
+ ADMIN_MANIFEST_CONFIG,
552
+ ...lightweightExports
553
+ ],
554
+ global: true
555
+ };
556
+ }
557
+ };
558
+ SaasPlatformModule = _ts_decorate6([
559
+ Module({})
560
+ ], SaasPlatformModule);
561
+
562
+ export {
563
+ PLAN_RESOLVER_PORT_TOKEN,
564
+ StaticPlanResolver,
565
+ StaticEntitlementService,
566
+ STATIC_FEATURE_GUARD_CONFIG_TOKEN,
567
+ StaticFeatureGuard,
568
+ QUOTA_PROVIDERS_TOKEN,
569
+ EnforceQuotaInterceptor,
570
+ TenantManifestService,
571
+ buildTenantManifestController,
572
+ SaasPlatformModule
573
+ };