@saasicat/nest 0.7.0 → 0.9.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 (59) hide show
  1. package/dist/admin/index.cjs +262 -7
  2. package/dist/admin/index.d.cts +6 -4
  3. package/dist/admin/index.d.ts +6 -4
  4. package/dist/admin/index.js +12 -4
  5. package/dist/{admin-manifest.service-Cp6uwvmt.d.cts → admin-manifest.service-BMeSLRW4.d.ts} +1 -1
  6. package/dist/{admin-manifest.service-UGgzR1x-.d.ts → admin-manifest.service-StAQe6QO.d.cts} +1 -1
  7. package/dist/admin-resources.module-BybEjZs-.d.cts +40 -0
  8. package/dist/admin-resources.module-CUCLlUAi.d.ts +40 -0
  9. package/dist/billing/index.cjs +3 -1
  10. package/dist/billing/index.d.cts +5 -287
  11. package/dist/billing/index.d.ts +5 -287
  12. package/dist/billing/index.js +5 -8
  13. package/dist/catalog/index.d.cts +4 -101
  14. package/dist/catalog/index.d.ts +4 -101
  15. package/dist/catalog/index.js +12 -10
  16. package/dist/catalog.module-BKObceo0.d.ts +103 -0
  17. package/dist/catalog.module-Dw2Hrbyu.d.cts +103 -0
  18. package/dist/{chunk-U6HT27J7.js → chunk-3M6VLT5N.js} +257 -6
  19. package/dist/chunk-7K5PT2LX.js +211 -0
  20. package/dist/{chunk-RZU4HIAN.js → chunk-GW2I3JZD.js} +25 -22
  21. package/dist/{chunk-6LP7CDS2.js → chunk-HXAWPPFW.js} +10 -5
  22. package/dist/chunk-OFBDEO45.js +755 -0
  23. package/dist/{chunk-5DDCSGZC.js → chunk-PBQRPDO2.js} +142 -354
  24. package/dist/{chunk-SD3TT2BR.js → chunk-WGVTXSYW.js} +1 -1
  25. package/dist/{chunk-A2QBXDJC.js → chunk-ZZMAHX22.js} +343 -16
  26. package/dist/{enforce-quota.interceptor-Dj1Kusr5.d.ts → enforce-quota.interceptor-B3CL5MSw.d.ts} +94 -12
  27. package/dist/{enforce-quota.interceptor-cv7r80VM.d.cts → enforce-quota.interceptor-SqrQVF91.d.cts} +94 -12
  28. package/dist/entitlement/index.cjs +1 -0
  29. package/dist/entitlement/index.d.cts +3 -1
  30. package/dist/entitlement/index.d.ts +3 -1
  31. package/dist/entitlement/index.js +1 -2
  32. package/dist/index.cjs +3503 -2811
  33. package/dist/index.d.cts +9 -6
  34. package/dist/index.d.ts +9 -6
  35. package/dist/index.js +75 -61
  36. package/dist/module-B5m080F0.d.ts +39 -0
  37. package/dist/module-DeH_Jkcq.d.cts +39 -0
  38. package/dist/platform/index.cjs +11113 -971
  39. package/dist/platform/index.d.cts +41 -7
  40. package/dist/platform/index.d.ts +41 -7
  41. package/dist/platform/index.js +26 -6
  42. package/dist/promo/index.cjs +530 -5
  43. package/dist/promo/index.d.cts +47 -30
  44. package/dist/promo/index.d.ts +47 -30
  45. package/dist/promo/index.js +9 -1
  46. package/dist/{service-DX8KbGXl.d.cts → service-DlhMnYjW.d.cts} +1 -1
  47. package/dist/{service-DX8KbGXl.d.ts → service-DlhMnYjW.d.ts} +1 -1
  48. package/dist/subscription-bundles.module-BQmoozm5.d.ts +291 -0
  49. package/dist/subscription-bundles.module-DCpV-Pb5.d.cts +291 -0
  50. package/dist/testing/index.cjs +11101 -973
  51. package/dist/testing/index.d.cts +9 -4
  52. package/dist/testing/index.d.ts +9 -4
  53. package/dist/testing/index.js +10 -4
  54. package/package.json +4 -4
  55. package/dist/admin-manifest.config-DyrQNT7M.d.cts +0 -10
  56. package/dist/admin-manifest.config-DyrQNT7M.d.ts +0 -10
  57. package/dist/chunk-52UTQRD3.js +0 -326
  58. package/dist/chunk-Q53N43LQ.js +0 -13
  59. /package/dist/{chunk-2FR6ZL7R.js → chunk-HWGIMNWR.js} +0 -0
@@ -0,0 +1,211 @@
1
+ import {
2
+ DiscoverySnapshotNotFoundError,
3
+ loadDiscoverySnapshotFromFile
4
+ } from "./chunk-ABB2CRAS.js";
5
+ import {
6
+ ADVISORY_STRICT_MODE_CODES,
7
+ validateBundleDraft,
8
+ validatePlanDraft
9
+ } from "./chunk-PBQRPDO2.js";
10
+ import {
11
+ __name
12
+ } from "./chunk-SHUYVCID.js";
13
+
14
+ // src/catalog/preflight.ts
15
+ function runPreflight(input) {
16
+ const findings = [];
17
+ const approved = input.approved ?? null;
18
+ for (const pv of input.planVersions) {
19
+ const warns = validatePlanDraft({
20
+ features: pv.features,
21
+ quotas: pv.quotas ?? {}
22
+ }, input.snapshot, /* @__PURE__ */ new Set(), approved);
23
+ for (const w of warns) {
24
+ findings.push({
25
+ kind: "plan",
26
+ versionId: pv.id,
27
+ entityKey: pv.planId,
28
+ version: pv.version,
29
+ warning: w
30
+ });
31
+ }
32
+ }
33
+ for (const bv of input.bundleVersions) {
34
+ const warns = validateBundleDraft({
35
+ features: bv.features,
36
+ quotas: bv.quotas ?? {}
37
+ }, input.snapshot, null, /* @__PURE__ */ new Set(), approved);
38
+ for (const w of warns) {
39
+ findings.push({
40
+ kind: "bundle",
41
+ versionId: bv.id,
42
+ entityKey: bv.bundleKey,
43
+ version: bv.version,
44
+ warning: w
45
+ });
46
+ }
47
+ }
48
+ findings.sort((a, b) => {
49
+ if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);
50
+ if (a.entityKey !== b.entityKey) return a.entityKey.localeCompare(b.entityKey);
51
+ if (a.version !== b.version) return a.version - b.version;
52
+ return a.warning.code.localeCompare(b.warning.code);
53
+ });
54
+ const counts = {
55
+ planFindings: findings.filter((f) => f.kind === "plan").length,
56
+ bundleFindings: findings.filter((f) => f.kind === "bundle").length,
57
+ total: findings.length
58
+ };
59
+ const hasBlockingFinding = findings.some((f) => !ADVISORY_STRICT_MODE_CODES.has(f.warning.code));
60
+ return {
61
+ overall: hasBlockingFinding ? "error" : "ok",
62
+ counts,
63
+ findings
64
+ };
65
+ }
66
+ __name(runPreflight, "runPreflight");
67
+ function formatPreflightReport(report) {
68
+ const lines = [];
69
+ lines.push(`Preflight (Status: ${report.overall.toUpperCase()})`, ` Plans: ${report.counts.planFindings} \xB7 Bundles: ${report.counts.bundleFindings} \xB7 Gesamt: ${report.counts.total}`, "");
70
+ if (report.findings.length === 0) {
71
+ lines.push(" \u2713 Keine Strict-Mode-Verst\xF6\xDFe gefunden.");
72
+ return lines.join("\n");
73
+ }
74
+ let lastEntity = "";
75
+ for (const f of report.findings) {
76
+ const entityHeader = `${f.kind} ${f.entityKey} v${f.version}`;
77
+ if (entityHeader !== lastEntity) {
78
+ lines.push(` \u2717 ${entityHeader} (${f.versionId})`);
79
+ lastEntity = entityHeader;
80
+ }
81
+ const fieldHint = f.warning.field ? ` [${f.warning.field}]` : "";
82
+ lines.push(` ${f.warning.code}${fieldHint}: ${f.warning.message}`);
83
+ }
84
+ return lines.join("\n");
85
+ }
86
+ __name(formatPreflightReport, "formatPreflightReport");
87
+ function preflightExitCode(report) {
88
+ return report.overall === "error" ? 4 : 0;
89
+ }
90
+ __name(preflightExitCode, "preflightExitCode");
91
+
92
+ // src/catalog/seed-gate.ts
93
+ function validateSeedAgainstSnapshot(input) {
94
+ const findings = [];
95
+ for (const plan of input.plans ?? []) {
96
+ const warns = validatePlanDraft({
97
+ features: plan.features,
98
+ quotas: plan.quotas ?? {}
99
+ }, input.snapshot, /* @__PURE__ */ new Set(), input.approved ?? null);
100
+ for (const warning of warns) {
101
+ findings.push({
102
+ kind: "plan",
103
+ entityKey: plan.planKey,
104
+ warning
105
+ });
106
+ }
107
+ }
108
+ for (const bundle of input.bundles ?? []) {
109
+ const warns = validateBundleDraft({
110
+ features: bundle.features,
111
+ quotas: bundle.quotas ?? {}
112
+ }, input.snapshot, null, /* @__PURE__ */ new Set(), input.approved ?? null);
113
+ for (const warning of warns) {
114
+ findings.push({
115
+ kind: "bundle",
116
+ entityKey: bundle.bundleKey,
117
+ warning
118
+ });
119
+ }
120
+ }
121
+ findings.sort((a, b) => {
122
+ if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);
123
+ if (a.entityKey !== b.entityKey) return a.entityKey.localeCompare(b.entityKey);
124
+ return a.warning.code.localeCompare(b.warning.code);
125
+ });
126
+ const counts = {
127
+ planFindings: findings.filter((f) => f.kind === "plan").length,
128
+ bundleFindings: findings.filter((f) => f.kind === "bundle").length,
129
+ total: findings.length
130
+ };
131
+ const hasBlockingFinding = findings.some((f) => !ADVISORY_STRICT_MODE_CODES.has(f.warning.code));
132
+ return {
133
+ overall: hasBlockingFinding ? "error" : "ok",
134
+ counts,
135
+ findings
136
+ };
137
+ }
138
+ __name(validateSeedAgainstSnapshot, "validateSeedAgainstSnapshot");
139
+ function formatSeedGateReport(report) {
140
+ const lines = [];
141
+ lines.push(`Seed-Gate (Status: ${report.overall.toUpperCase()})`, ` Plans: ${report.counts.planFindings} \xB7 Bundles: ${report.counts.bundleFindings} \xB7 Gesamt: ${report.counts.total}`, "");
142
+ if (report.findings.length === 0) {
143
+ lines.push(" \u2713 Alle geseedeten Plan-/Bundle-Features sind discovered (und, sofern gepr\xFCft, approved).");
144
+ return lines.join("\n");
145
+ }
146
+ let lastEntity = "";
147
+ for (const f of report.findings) {
148
+ const entityHeader = `${f.kind} ${f.entityKey}`;
149
+ if (entityHeader !== lastEntity) {
150
+ lines.push(` \u2717 ${entityHeader}`);
151
+ lastEntity = entityHeader;
152
+ }
153
+ const fieldHint = f.warning.field ? ` [${f.warning.field}]` : "";
154
+ lines.push(` ${f.warning.code}${fieldHint}: ${f.warning.message}`);
155
+ }
156
+ return lines.join("\n");
157
+ }
158
+ __name(formatSeedGateReport, "formatSeedGateReport");
159
+ function seedGateExitCode(report) {
160
+ return report.overall === "error" ? 4 : 0;
161
+ }
162
+ __name(seedGateExitCode, "seedGateExitCode");
163
+
164
+ // src/catalog/seed-gate-runner.ts
165
+ function runSeedGateFromFile(options) {
166
+ const mode = options.mode ?? "report-only";
167
+ const log = options.log ?? ((line) => console.log(line));
168
+ const warn = options.warn ?? ((line) => console.warn(line));
169
+ const error = options.error ?? ((line) => console.error(line));
170
+ const exit = options.exit ?? ((code) => process.exit(code));
171
+ let snapshot;
172
+ try {
173
+ snapshot = loadDiscoverySnapshotFromFile(options.snapshotPath);
174
+ } catch (err) {
175
+ if (err instanceof DiscoverySnapshotNotFoundError) {
176
+ if (mode === "blocking") {
177
+ error(`[seed-gate] FEHLER: Kein Discovery-Snapshot unter ${options.snapshotPath} \u2014 im blocking-Modus Pflicht (Headless-Scan vor dem Seed ausf\xFChren, #23).`);
178
+ return exit(4);
179
+ }
180
+ warn(`[seed-gate] Kein Discovery-Snapshot unter ${options.snapshotPath} \u2014 \xFCbersprungen (report-only).`);
181
+ return null;
182
+ }
183
+ throw err;
184
+ }
185
+ const report = validateSeedAgainstSnapshot({
186
+ snapshot,
187
+ plans: options.plans,
188
+ bundles: options.bundles,
189
+ approved: options.approved ?? null
190
+ });
191
+ log(formatSeedGateReport(report));
192
+ if (report.overall === "error") {
193
+ if (mode === "blocking") {
194
+ error("[seed-gate] blocking: Verst\xF6\xDFe gefunden \u2014 Seed wird abgebrochen (#23).");
195
+ return exit(seedGateExitCode(report));
196
+ }
197
+ warn("[seed-gate] report-only: Verst\xF6\xDFe gefunden, Seed l\xE4uft trotzdem weiter.");
198
+ }
199
+ return report;
200
+ }
201
+ __name(runSeedGateFromFile, "runSeedGateFromFile");
202
+
203
+ export {
204
+ runPreflight,
205
+ formatPreflightReport,
206
+ preflightExitCode,
207
+ validateSeedAgainstSnapshot,
208
+ formatSeedGateReport,
209
+ seedGateExitCode,
210
+ runSeedGateFromFile
211
+ };
@@ -25,10 +25,6 @@ import {
25
25
  __name
26
26
  } from "./chunk-SHUYVCID.js";
27
27
 
28
- // src/billing/subscription-bundles.tokens.ts
29
- var SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SubscriptionBundleRepository");
30
- var SUBSCRIPTION_BUNDLE_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SubscriptionBundleConfig");
31
-
32
28
  // src/entitlement/aggregation.ts
33
29
  function filterActiveSubscriptionBundles(bundles, now) {
34
30
  return bundles.filter((b) => b.canceledEffectiveAt === null || b.canceledEffectiveAt > now);
@@ -222,6 +218,24 @@ function assertNoReplacesCycle(index) {
222
218
  }
223
219
  __name(assertNoReplacesCycle, "assertNoReplacesCycle");
224
220
 
221
+ // src/entitlement/plan-resolution.ts
222
+ function resolveEntitlementPlan(input, config, now) {
223
+ if (input.isPilot && config.pilotEntitlementPlan !== void 0) {
224
+ return config.pilotEntitlementPlan;
225
+ }
226
+ if (input.status === "TRIAL") {
227
+ return input.trialEntitlementPlan ?? config.defaultTrialEntitlementPlan ?? input.plan;
228
+ }
229
+ if (input.status === "PENDING_SALES" && config.pendingSalesEntitlementPlan !== void 0) {
230
+ return config.pendingSalesEntitlementPlan;
231
+ }
232
+ if (input.pendingPlan && input.pendingEffectiveAt && input.pendingEffectiveAt <= now) {
233
+ return input.pendingPlan;
234
+ }
235
+ return input.plan;
236
+ }
237
+ __name(resolveEntitlementPlan, "resolveEntitlementPlan");
238
+
225
239
  // src/entitlement/limit-exceeded-error.ts
226
240
  var LIMIT_EXCEEDED = "LIMIT_EXCEEDED";
227
241
  var LimitExceededError = class extends Error {
@@ -242,26 +256,14 @@ function isLimitExceededError(err) {
242
256
  }
243
257
  __name(isLimitExceededError, "isLimitExceededError");
244
258
 
245
- // src/entitlement/plan-resolution.ts
246
- function resolveEntitlementPlan(input, config, now) {
247
- if (input.isPilot && config.pilotEntitlementPlan !== void 0) {
248
- return config.pilotEntitlementPlan;
249
- }
250
- if (input.status === "TRIAL") {
251
- return input.trialEntitlementPlan ?? config.defaultTrialEntitlementPlan ?? input.plan;
252
- }
253
- if (input.status === "PENDING_SALES" && config.pendingSalesEntitlementPlan !== void 0) {
254
- return config.pendingSalesEntitlementPlan;
255
- }
256
- if (input.pendingPlan && input.pendingEffectiveAt && input.pendingEffectiveAt <= now) {
257
- return input.pendingPlan;
258
- }
259
- return input.plan;
260
- }
261
- __name(resolveEntitlementPlan, "resolveEntitlementPlan");
262
-
263
259
  // src/entitlement/service.ts
264
260
  import { Inject, Injectable, NotFoundException, Optional } from "@nestjs/common";
261
+
262
+ // src/billing/subscription-bundles.tokens.ts
263
+ var SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SubscriptionBundleRepository");
264
+ var SUBSCRIPTION_BUNDLE_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SubscriptionBundleConfig");
265
+
266
+ // src/entitlement/service.ts
265
267
  function _ts_decorate(decorators, target, key, desc) {
266
268
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
267
269
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -552,6 +554,7 @@ var EntitlementModule = class _EntitlementModule {
552
554
  return {
553
555
  module: _EntitlementModule,
554
556
  global: options.global ?? false,
557
+ imports: options.imports ?? [],
555
558
  providers,
556
559
  exports: [
557
560
  EntitlementService,
@@ -16,9 +16,6 @@ import {
16
16
  USER_EMAIL_RESOLVER_TOKEN,
17
17
  USER_ID_RESOLVER_TOKEN
18
18
  } from "./chunk-WPUVJRIN.js";
19
- import {
20
- REQUIRE_FEATURE_KEY
21
- } from "./chunk-Q53N43LQ.js";
22
19
  import {
23
20
  AdminAuditService
24
21
  } from "./chunk-E56W4U2P.js";
@@ -28,7 +25,7 @@ import {
28
25
  SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN,
29
26
  isLimitExceededError,
30
27
  toEffectiveLimitsSnapshot
31
- } from "./chunk-RZU4HIAN.js";
28
+ } from "./chunk-GW2I3JZD.js";
32
29
  import {
33
30
  PLAN_CATALOG_TOKEN,
34
31
  findPlan,
@@ -171,6 +168,11 @@ function computeNextPeriod(sub, now) {
171
168
  }
172
169
  __name(computeNextPeriod, "computeNextPeriod");
173
170
 
171
+ // src/billing/require-feature.decorator.ts
172
+ import { SetMetadata } from "@nestjs/common";
173
+ var REQUIRE_FEATURE_KEY = "require-feature";
174
+ var RequireFeature = /* @__PURE__ */ __name((...features) => SetMetadata(REQUIRE_FEATURE_KEY, features), "RequireFeature");
175
+
174
176
  // src/billing/feature-guard.tokens.ts
175
177
  var FEATURE_GUARD_CONFIG_TOKEN = /* @__PURE__ */ Symbol("FEATURE_GUARD_CONFIG");
176
178
 
@@ -2560,7 +2562,8 @@ var TenantBillingModule = class _TenantBillingModule {
2560
2562
  ] : [],
2561
2563
  ...hasContractFreeze ? [
2562
2564
  CONTRACT_FREEZE_PORT_TOKEN
2563
- ] : []
2565
+ ] : [],
2566
+ ...options.extraExports ?? []
2564
2567
  ]
2565
2568
  };
2566
2569
  }
@@ -3270,6 +3273,8 @@ export {
3270
3273
  decideRenewal,
3271
3274
  clearPendingPlanVersionFields,
3272
3275
  computeNextPeriod,
3276
+ REQUIRE_FEATURE_KEY,
3277
+ RequireFeature,
3273
3278
  FEATURE_GUARD_CONFIG_TOKEN,
3274
3279
  UPSELL_OFFER_RESOLVER_TOKEN,
3275
3280
  UPSELL_OFFER_CURRENCY_TOKEN,