@saasicat/nest 0.26.1 → 1.0.0-rc.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.
- package/LICENSE +90 -201
- package/dist/.build-stamp +1 -0
- package/dist/_entries.cjs +3175 -2756
- package/dist/admin/index.d.cts +2 -2
- package/dist/admin/index.d.ts +2 -2
- package/dist/admin/index.js +2 -2
- package/dist/{admin-stats.service-HUZIU448.d.cts → admin-stats.service-BroyovpL.d.cts} +1 -1
- package/dist/{admin-stats.service-Db2exT_d.d.ts → admin-stats.service-G53IEkkt.d.ts} +1 -1
- package/dist/billing/index.d.cts +7 -7
- package/dist/billing/index.d.ts +7 -7
- package/dist/billing/index.js +38 -36
- package/dist/catalog/index.d.cts +13 -1
- package/dist/catalog/index.d.ts +13 -1
- package/dist/catalog/index.js +10 -8
- package/dist/checkout-offer/index.js +2 -2
- package/dist/chunk-2FR6ZL7R.js +0 -0
- package/dist/chunk-2SLTRKXC.js +0 -0
- package/dist/{chunk-7ZPFQXHM.js → chunk-3UZW7TU4.js} +1 -1
- package/dist/{chunk-XTVAFJ3P.js → chunk-AEEK64XD.js} +3 -3
- package/dist/chunk-AOQJEYOL.js +20 -0
- package/dist/chunk-H3W6QDQH.js +85 -0
- package/dist/{chunk-YYUXKLXK.js → chunk-I7GTA3RX.js} +2 -2
- package/dist/{chunk-SN5UOC43.js → chunk-IPOLCDKN.js} +11 -11
- package/dist/{chunk-B7NRY2LV.js → chunk-IVEA6M3B.js} +2 -40
- package/dist/chunk-JCAZT727.js +1883 -0
- package/dist/chunk-JTLKWP3Q.js +792 -0
- package/dist/{chunk-E56W4U2P.js → chunk-O2J2HDXA.js} +4 -4
- package/dist/{chunk-WKVBNTYC.js → chunk-OUDSQ3PU.js} +6 -6
- package/dist/{chunk-MJ32VNZD.js → chunk-P5D5CYO2.js} +18 -18
- package/dist/{chunk-L4SUWH5B.js → chunk-QUZU2M33.js} +2 -2
- package/dist/{chunk-WPUVJRIN.js → chunk-S6BAD5XM.js} +10 -10
- package/dist/{chunk-7X5MSAIL.js → chunk-SH7J5IU7.js} +9 -9
- package/dist/{chunk-37HEKVDH.js → chunk-V4OJ43K2.js} +10 -10
- package/dist/{chunk-NYLON2VC.js → chunk-VBRYPU7V.js} +2 -2
- package/dist/{chunk-B6IWLV7R.js → chunk-VTMCMVYQ.js} +6 -6
- package/dist/{chunk-YWDLYOFN.js → chunk-WSPHIIGS.js} +429 -1205
- package/dist/{chunk-5ZXBXYXU.js → chunk-WXYJHZCN.js} +3 -3
- package/dist/{chunk-6WL6VQ7Z.js → chunk-XBYAFEOR.js} +2 -2
- package/dist/{chunk-NNNXXUPT.js → chunk-XEW6YXL5.js} +28 -93
- package/dist/chunk-Y43SGD5J.js +50 -0
- package/dist/{define-saasicat-BK6RRWWG.d.ts → define-saasicat-BFgeoVG9.d.ts} +28 -5
- package/dist/{define-saasicat-D30I-WET.d.cts → define-saasicat-CNUWjfNK.d.cts} +28 -5
- package/dist/discovery/index.js +4 -4
- package/dist/{enforce-quota.interceptor-B9QueAFf.d.ts → enforce-quota.interceptor-BYqmdFB5.d.ts} +3 -3
- package/dist/{enforce-quota.interceptor-DY6CLjoP.d.cts → enforce-quota.interceptor-BxIR63Wn.d.cts} +3 -3
- package/dist/entitlement/index.js +9 -6
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +61 -52
- package/dist/{saas-platform.module-D1mUZPrz.d.ts → module-options-BymIkAsh.d.ts} +68 -55
- package/dist/{saas-platform.module-CgalxzcT.d.cts → module-options-DgwBKVpC.d.cts} +68 -55
- package/dist/platform/index.d.cts +204 -22
- package/dist/platform/index.d.ts +204 -22
- package/dist/platform/index.js +49 -25
- package/dist/promo/index.d.cts +3 -3
- package/dist/promo/index.d.ts +3 -3
- package/dist/promo/index.js +3 -3
- package/dist/{module-BE17XFLg.d.ts → promo.module-CnzddtJ0.d.ts} +1 -1
- package/dist/{module-CHMIyWlf.d.cts → promo.module-DokmUGmm.d.cts} +1 -1
- package/dist/registration/index.d.cts +1 -1
- package/dist/registration/index.d.ts +1 -1
- package/dist/registration/index.js +1 -1
- package/dist/subscription-contract/index.js +6 -3
- package/dist/{tenant-billing.controller-BSlpFqVA.d.ts → tenant-billing.controller-BQPy5yXh.d.ts} +2 -2
- package/dist/{tenant-billing.controller-DHSUrT_N.d.cts → tenant-billing.controller-CODIYzlI.d.cts} +2 -2
- package/dist/{subscription-bundles.module-BDbODWvA.d.ts → tenant-billing.module-B0stLoJn.d.ts} +51 -51
- package/dist/{subscription-bundles.module-Cfi-lFWF.d.cts → tenant-billing.module-BxJS6fX4.d.cts} +51 -51
- package/dist/testing/index.d.cts +14 -14
- package/dist/testing/index.d.ts +14 -14
- package/dist/testing/index.js +31 -29
- package/package.json +6 -6
- package/dist/chunk-L4KTQ6CL.js +0 -20
- package/dist/chunk-TCBYOFAC.js +0 -1464
- /package/dist/{chunk-FY4EJTV4.js → chunk-OYNHOY45.js} +0 -0
- /package/dist/{service-D48clObR.d.cts → promo.service-D48clObR.d.cts} +0 -0
- /package/dist/{service-D48clObR.d.ts → promo.service-D48clObR.d.ts} +0 -0
package/dist/chunk-TCBYOFAC.js
DELETED
|
@@ -1,1464 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
PromoCodesModule
|
|
3
|
-
} from "./chunk-B6IWLV7R.js";
|
|
4
|
-
import {
|
|
5
|
-
AdminManifestModule,
|
|
6
|
-
AdminManifestService,
|
|
7
|
-
AdminModule,
|
|
8
|
-
AdminResourcesModule,
|
|
9
|
-
AdminStatsModule,
|
|
10
|
-
MfaService,
|
|
11
|
-
SuperAdminGuard
|
|
12
|
-
} from "./chunk-SN5UOC43.js";
|
|
13
|
-
import {
|
|
14
|
-
FEATURE_GUARD_MARKER,
|
|
15
|
-
PublicCatalogModule,
|
|
16
|
-
REQUIRE_FEATURE_KEY,
|
|
17
|
-
SubscriptionBundleModule,
|
|
18
|
-
TenantBillingModule,
|
|
19
|
-
isPlatformFeatureGuard
|
|
20
|
-
} from "./chunk-YWDLYOFN.js";
|
|
21
|
-
import {
|
|
22
|
-
SubscriptionContractModule
|
|
23
|
-
} from "./chunk-B7NRY2LV.js";
|
|
24
|
-
import {
|
|
25
|
-
CatalogModule
|
|
26
|
-
} from "./chunk-7X5MSAIL.js";
|
|
27
|
-
import {
|
|
28
|
-
CheckoutOfferModule
|
|
29
|
-
} from "./chunk-XTVAFJ3P.js";
|
|
30
|
-
import {
|
|
31
|
-
SaaSiCatPublicRoute
|
|
32
|
-
} from "./chunk-YSC46BGM.js";
|
|
33
|
-
import {
|
|
34
|
-
DiscoveryModule
|
|
35
|
-
} from "./chunk-6WL6VQ7Z.js";
|
|
36
|
-
import {
|
|
37
|
-
EntitlementModule,
|
|
38
|
-
LimitExceededError
|
|
39
|
-
} from "./chunk-NNNXXUPT.js";
|
|
40
|
-
import {
|
|
41
|
-
PLAN_CATALOG_TOKEN,
|
|
42
|
-
PlanCatalogModule
|
|
43
|
-
} from "./chunk-DQKCK7DX.js";
|
|
44
|
-
import {
|
|
45
|
-
codedError
|
|
46
|
-
} from "./chunk-EBJJNTW6.js";
|
|
47
|
-
import {
|
|
48
|
-
asProvider
|
|
49
|
-
} from "./chunk-SABTXESR.js";
|
|
50
|
-
import {
|
|
51
|
-
ENFORCE_QUOTA_KEY
|
|
52
|
-
} from "./chunk-L4SUWH5B.js";
|
|
53
|
-
import {
|
|
54
|
-
__name
|
|
55
|
-
} from "./chunk-SHUYVCID.js";
|
|
56
|
-
|
|
57
|
-
// src/setup/tokens.ts
|
|
58
|
-
var SETUP_PROVISIONING_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SetupProvisioningPort");
|
|
59
|
-
var SETUP_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SetupConfig");
|
|
60
|
-
|
|
61
|
-
// src/setup/setup.service.ts
|
|
62
|
-
import { BadRequestException, ConflictException, ForbiddenException, Inject, Injectable, UnauthorizedException } from "@nestjs/common";
|
|
63
|
-
import { isPlatformUserExistsError, SETUP_ERROR_CODES } from "@saasicat/types";
|
|
64
|
-
import { randomBytes, timingSafeEqual } from "crypto";
|
|
65
|
-
import QRCode from "qrcode";
|
|
66
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
67
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
68
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
69
|
-
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;
|
|
70
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
71
|
-
}
|
|
72
|
-
__name(_ts_decorate, "_ts_decorate");
|
|
73
|
-
function _ts_metadata(k, v) {
|
|
74
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
75
|
-
}
|
|
76
|
-
__name(_ts_metadata, "_ts_metadata");
|
|
77
|
-
function _ts_param(paramIndex, decorator) {
|
|
78
|
-
return function(target, key) {
|
|
79
|
-
decorator(target, key, paramIndex);
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
__name(_ts_param, "_ts_param");
|
|
83
|
-
var GENERATED_PASSWORD_BYTES = 12;
|
|
84
|
-
function timingSafeEqualStr(a, b) {
|
|
85
|
-
const ab = Buffer.from(a, "utf8");
|
|
86
|
-
const bb = Buffer.from(b, "utf8");
|
|
87
|
-
if (ab.length !== bb.length) return false;
|
|
88
|
-
return timingSafeEqual(ab, bb);
|
|
89
|
-
}
|
|
90
|
-
__name(timingSafeEqualStr, "timingSafeEqualStr");
|
|
91
|
-
var SetupService = class {
|
|
92
|
-
static {
|
|
93
|
-
__name(this, "SetupService");
|
|
94
|
-
}
|
|
95
|
-
users;
|
|
96
|
-
config;
|
|
97
|
-
mfa;
|
|
98
|
-
constructor(users, config, mfa) {
|
|
99
|
-
this.users = users;
|
|
100
|
-
this.config = config;
|
|
101
|
-
this.mfa = mfa;
|
|
102
|
-
}
|
|
103
|
-
async status() {
|
|
104
|
-
return {
|
|
105
|
-
needsSetup: await this.users.countSuperAdmins() === 0
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
async setup(req) {
|
|
109
|
-
this.assertToken(req.token);
|
|
110
|
-
await this.assertNoSuperAdmin();
|
|
111
|
-
const email = req.email.trim().toLowerCase();
|
|
112
|
-
if (!email.includes("@")) {
|
|
113
|
-
throw new BadRequestException(codedError(SETUP_ERROR_CODES.INVALID_EMAIL));
|
|
114
|
-
}
|
|
115
|
-
const generated = !req.password;
|
|
116
|
-
const password = req.password ?? randomBytes(GENERATED_PASSWORD_BYTES).toString("base64url");
|
|
117
|
-
let user;
|
|
118
|
-
try {
|
|
119
|
-
user = await this.users.createSuperAdmin({
|
|
120
|
-
email,
|
|
121
|
-
password
|
|
122
|
-
});
|
|
123
|
-
} catch (err) {
|
|
124
|
-
if (isPlatformUserExistsError(err)) {
|
|
125
|
-
throw new ConflictException({
|
|
126
|
-
code: SETUP_ERROR_CODES.EMAIL_EXISTS,
|
|
127
|
-
message: err.message
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
throw err;
|
|
131
|
-
}
|
|
132
|
-
const totp = await this.mfa.setup(user.id, user.email, this.config.mfaIssuer);
|
|
133
|
-
const qrDataUrl = await QRCode.toDataURL(totp.otpauthUri, {
|
|
134
|
-
width: 220,
|
|
135
|
-
margin: 1
|
|
136
|
-
});
|
|
137
|
-
return {
|
|
138
|
-
userId: user.id,
|
|
139
|
-
email: user.email,
|
|
140
|
-
otpauthUri: totp.otpauthUri,
|
|
141
|
-
qrDataUrl,
|
|
142
|
-
secret: totp.secret,
|
|
143
|
-
...generated ? {
|
|
144
|
-
generatedPassword: password
|
|
145
|
-
} : {}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
async confirmMfa(req) {
|
|
149
|
-
this.assertToken(req.token);
|
|
150
|
-
const ok = await this.mfa.verify({
|
|
151
|
-
userId: req.userId,
|
|
152
|
-
code: req.code
|
|
153
|
-
});
|
|
154
|
-
return {
|
|
155
|
-
ok
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
assertToken(token) {
|
|
159
|
-
const expected = process.env[this.config.setupTokenEnvVar]?.trim();
|
|
160
|
-
if (!expected) {
|
|
161
|
-
throw new ForbiddenException({
|
|
162
|
-
code: SETUP_ERROR_CODES.SETUP_DISABLED,
|
|
163
|
-
message: `${this.config.setupTokenEnvVar} is not set \u2014 setup is disabled.`,
|
|
164
|
-
params: {
|
|
165
|
-
envVar: this.config.setupTokenEnvVar
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
if (!token || !timingSafeEqualStr(token, expected)) {
|
|
170
|
-
throw new UnauthorizedException(codedError(SETUP_ERROR_CODES.INVALID_SETUP_TOKEN));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
async assertNoSuperAdmin() {
|
|
174
|
-
if (await this.users.countSuperAdmins() > 0) {
|
|
175
|
-
throw new ConflictException(codedError(SETUP_ERROR_CODES.SETUP_ALREADY_DONE));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
SetupService = _ts_decorate([
|
|
180
|
-
Injectable(),
|
|
181
|
-
_ts_param(0, Inject(SETUP_PROVISIONING_PORT_TOKEN)),
|
|
182
|
-
_ts_param(1, Inject(SETUP_CONFIG_TOKEN)),
|
|
183
|
-
_ts_metadata("design:type", Function),
|
|
184
|
-
_ts_metadata("design:paramtypes", [
|
|
185
|
-
typeof SuperAdminProvisioningPort === "undefined" ? Object : SuperAdminProvisioningPort,
|
|
186
|
-
typeof SetupConfig === "undefined" ? Object : SetupConfig,
|
|
187
|
-
typeof MfaService === "undefined" ? Object : MfaService
|
|
188
|
-
])
|
|
189
|
-
], SetupService);
|
|
190
|
-
|
|
191
|
-
// src/setup/setup.controller.ts
|
|
192
|
-
import { Body, Controller, Get, Post } from "@nestjs/common";
|
|
193
|
-
import { IsEmail, IsNotEmpty, IsOptional, IsString, MinLength } from "class-validator";
|
|
194
|
-
function _ts_decorate2(decorators, target, key, desc) {
|
|
195
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
196
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
197
|
-
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;
|
|
198
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
199
|
-
}
|
|
200
|
-
__name(_ts_decorate2, "_ts_decorate");
|
|
201
|
-
function _ts_metadata2(k, v) {
|
|
202
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
203
|
-
}
|
|
204
|
-
__name(_ts_metadata2, "_ts_metadata");
|
|
205
|
-
function _ts_param2(paramIndex, decorator) {
|
|
206
|
-
return function(target, key) {
|
|
207
|
-
decorator(target, key, paramIndex);
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
__name(_ts_param2, "_ts_param");
|
|
211
|
-
var SetupDto = class SetupDto2 {
|
|
212
|
-
static {
|
|
213
|
-
__name(this, "SetupDto");
|
|
214
|
-
}
|
|
215
|
-
token;
|
|
216
|
-
email;
|
|
217
|
-
password;
|
|
218
|
-
};
|
|
219
|
-
_ts_decorate2([
|
|
220
|
-
IsString(),
|
|
221
|
-
IsNotEmpty(),
|
|
222
|
-
_ts_metadata2("design:type", String)
|
|
223
|
-
], SetupDto.prototype, "token", void 0);
|
|
224
|
-
_ts_decorate2([
|
|
225
|
-
IsEmail(),
|
|
226
|
-
_ts_metadata2("design:type", String)
|
|
227
|
-
], SetupDto.prototype, "email", void 0);
|
|
228
|
-
_ts_decorate2([
|
|
229
|
-
IsOptional(),
|
|
230
|
-
IsString(),
|
|
231
|
-
MinLength(8),
|
|
232
|
-
_ts_metadata2("design:type", String)
|
|
233
|
-
], SetupDto.prototype, "password", void 0);
|
|
234
|
-
var SetupConfirmMfaDto = class SetupConfirmMfaDto2 {
|
|
235
|
-
static {
|
|
236
|
-
__name(this, "SetupConfirmMfaDto");
|
|
237
|
-
}
|
|
238
|
-
token;
|
|
239
|
-
userId;
|
|
240
|
-
code;
|
|
241
|
-
};
|
|
242
|
-
_ts_decorate2([
|
|
243
|
-
IsString(),
|
|
244
|
-
IsNotEmpty(),
|
|
245
|
-
_ts_metadata2("design:type", String)
|
|
246
|
-
], SetupConfirmMfaDto.prototype, "token", void 0);
|
|
247
|
-
_ts_decorate2([
|
|
248
|
-
IsString(),
|
|
249
|
-
IsNotEmpty(),
|
|
250
|
-
_ts_metadata2("design:type", String)
|
|
251
|
-
], SetupConfirmMfaDto.prototype, "userId", void 0);
|
|
252
|
-
_ts_decorate2([
|
|
253
|
-
IsString(),
|
|
254
|
-
IsNotEmpty(),
|
|
255
|
-
_ts_metadata2("design:type", String)
|
|
256
|
-
], SetupConfirmMfaDto.prototype, "code", void 0);
|
|
257
|
-
var SetupController = class {
|
|
258
|
-
static {
|
|
259
|
-
__name(this, "SetupController");
|
|
260
|
-
}
|
|
261
|
-
setup;
|
|
262
|
-
constructor(setup) {
|
|
263
|
-
this.setup = setup;
|
|
264
|
-
}
|
|
265
|
-
status() {
|
|
266
|
-
return this.setup.status();
|
|
267
|
-
}
|
|
268
|
-
run(dto) {
|
|
269
|
-
return this.setup.setup(dto);
|
|
270
|
-
}
|
|
271
|
-
confirm(dto) {
|
|
272
|
-
return this.setup.confirmMfa(dto);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
_ts_decorate2([
|
|
276
|
-
Get("status"),
|
|
277
|
-
_ts_metadata2("design:type", Function),
|
|
278
|
-
_ts_metadata2("design:paramtypes", []),
|
|
279
|
-
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
280
|
-
], SetupController.prototype, "status", null);
|
|
281
|
-
_ts_decorate2([
|
|
282
|
-
Post(),
|
|
283
|
-
_ts_param2(0, Body()),
|
|
284
|
-
_ts_metadata2("design:type", Function),
|
|
285
|
-
_ts_metadata2("design:paramtypes", [
|
|
286
|
-
typeof SetupDto === "undefined" ? Object : SetupDto
|
|
287
|
-
]),
|
|
288
|
-
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
289
|
-
], SetupController.prototype, "run", null);
|
|
290
|
-
_ts_decorate2([
|
|
291
|
-
Post("confirm-mfa"),
|
|
292
|
-
_ts_param2(0, Body()),
|
|
293
|
-
_ts_metadata2("design:type", Function),
|
|
294
|
-
_ts_metadata2("design:paramtypes", [
|
|
295
|
-
typeof SetupConfirmMfaDto === "undefined" ? Object : SetupConfirmMfaDto
|
|
296
|
-
]),
|
|
297
|
-
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
298
|
-
], SetupController.prototype, "confirm", null);
|
|
299
|
-
SetupController = _ts_decorate2([
|
|
300
|
-
Controller("admin/setup"),
|
|
301
|
-
SaaSiCatPublicRoute(),
|
|
302
|
-
_ts_metadata2("design:type", Function),
|
|
303
|
-
_ts_metadata2("design:paramtypes", [
|
|
304
|
-
typeof SetupService === "undefined" ? Object : SetupService
|
|
305
|
-
])
|
|
306
|
-
], SetupController);
|
|
307
|
-
|
|
308
|
-
// src/setup/setup.module.ts
|
|
309
|
-
import { Module } from "@nestjs/common";
|
|
310
|
-
function _ts_decorate3(decorators, target, key, desc) {
|
|
311
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
312
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
313
|
-
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;
|
|
314
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
315
|
-
}
|
|
316
|
-
__name(_ts_decorate3, "_ts_decorate");
|
|
317
|
-
var DEFAULT_SETUP_TOKEN_ENV_VAR = "SETUP_TOKEN";
|
|
318
|
-
var DEFAULT_MFA_ISSUER = "SuperAdmin";
|
|
319
|
-
var SetupModule = class _SetupModule {
|
|
320
|
-
static {
|
|
321
|
-
__name(this, "SetupModule");
|
|
322
|
-
}
|
|
323
|
-
static forRoot(options) {
|
|
324
|
-
return {
|
|
325
|
-
module: _SetupModule,
|
|
326
|
-
global: options.global ?? false,
|
|
327
|
-
imports: options.imports ?? [],
|
|
328
|
-
controllers: [
|
|
329
|
-
SetupController
|
|
330
|
-
],
|
|
331
|
-
providers: [
|
|
332
|
-
asProvider(SETUP_PROVISIONING_PORT_TOKEN, options.provisioningPort),
|
|
333
|
-
{
|
|
334
|
-
provide: SETUP_CONFIG_TOKEN,
|
|
335
|
-
useValue: {
|
|
336
|
-
setupTokenEnvVar: options.setupTokenEnvVar ?? DEFAULT_SETUP_TOKEN_ENV_VAR,
|
|
337
|
-
mfaIssuer: options.mfaIssuer ?? DEFAULT_MFA_ISSUER
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
SetupService,
|
|
341
|
-
...options.extraProviders ?? []
|
|
342
|
-
],
|
|
343
|
-
exports: [
|
|
344
|
-
SetupService
|
|
345
|
-
]
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
SetupModule = _ts_decorate3([
|
|
350
|
-
Module({})
|
|
351
|
-
], SetupModule);
|
|
352
|
-
|
|
353
|
-
// src/platform/plan-resolver.port.ts
|
|
354
|
-
var PLAN_RESOLVER_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/PlanResolverPort");
|
|
355
|
-
var StaticPlanResolver = class {
|
|
356
|
-
static {
|
|
357
|
-
__name(this, "StaticPlanResolver");
|
|
358
|
-
}
|
|
359
|
-
planId;
|
|
360
|
-
constructor(planId) {
|
|
361
|
-
this.planId = planId;
|
|
362
|
-
}
|
|
363
|
-
async getPlanIdForTenant() {
|
|
364
|
-
return this.planId;
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
// src/platform/static-entitlement.service.ts
|
|
369
|
-
import { Inject as Inject2, Injectable as Injectable2 } from "@nestjs/common";
|
|
370
|
-
function _ts_decorate4(decorators, target, key, desc) {
|
|
371
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
372
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
373
|
-
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;
|
|
374
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
375
|
-
}
|
|
376
|
-
__name(_ts_decorate4, "_ts_decorate");
|
|
377
|
-
function _ts_metadata3(k, v) {
|
|
378
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
379
|
-
}
|
|
380
|
-
__name(_ts_metadata3, "_ts_metadata");
|
|
381
|
-
function _ts_param3(paramIndex, decorator) {
|
|
382
|
-
return function(target, key) {
|
|
383
|
-
decorator(target, key, paramIndex);
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
__name(_ts_param3, "_ts_param");
|
|
387
|
-
var StaticEntitlementService = class {
|
|
388
|
-
static {
|
|
389
|
-
__name(this, "StaticEntitlementService");
|
|
390
|
-
}
|
|
391
|
-
catalog;
|
|
392
|
-
resolver;
|
|
393
|
-
constructor(catalog, resolver) {
|
|
394
|
-
this.catalog = catalog;
|
|
395
|
-
this.resolver = resolver;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Returns the effective features + quotas of a tenant from the
|
|
399
|
-
* plan catalog. When the plan is missing: an empty snapshot (no feature,
|
|
400
|
-
* all quotas at 0).
|
|
401
|
-
*/
|
|
402
|
-
async snapshot(tenantId) {
|
|
403
|
-
const planId = await this.resolver.getPlanIdForTenant(tenantId);
|
|
404
|
-
if (!planId) {
|
|
405
|
-
return {
|
|
406
|
-
planId: null,
|
|
407
|
-
features: [],
|
|
408
|
-
quotas: {}
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
const plan = this.findPlan(planId);
|
|
412
|
-
if (!plan) {
|
|
413
|
-
return {
|
|
414
|
-
planId,
|
|
415
|
-
features: [],
|
|
416
|
-
quotas: {}
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
planId,
|
|
421
|
-
features: plan.features ?? [],
|
|
422
|
-
quotas: plan.quotas ?? {}
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
/** Convenience helper for tests / synchronous checks in the UI manifest. */
|
|
426
|
-
async hasFeature(tenantId, featureKey) {
|
|
427
|
-
const snap = await this.snapshot(tenantId);
|
|
428
|
-
return snap.features.includes(featureKey);
|
|
429
|
-
}
|
|
430
|
-
async quotaLimit(tenantId, quotaKey) {
|
|
431
|
-
const snap = await this.snapshot(tenantId);
|
|
432
|
-
const value = snap.quotas[quotaKey];
|
|
433
|
-
return value === void 0 ? null : value;
|
|
434
|
-
}
|
|
435
|
-
findPlan(planId) {
|
|
436
|
-
return (this.catalog.plans ?? []).find((p) => p.id === planId);
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
StaticEntitlementService = _ts_decorate4([
|
|
440
|
-
Injectable2(),
|
|
441
|
-
_ts_param3(0, Inject2(PLAN_CATALOG_TOKEN)),
|
|
442
|
-
_ts_param3(1, Inject2(PLAN_RESOLVER_PORT_TOKEN)),
|
|
443
|
-
_ts_metadata3("design:type", Function),
|
|
444
|
-
_ts_metadata3("design:paramtypes", [
|
|
445
|
-
typeof PlanCatalog === "undefined" ? Object : PlanCatalog,
|
|
446
|
-
typeof PlanResolverPort === "undefined" ? Object : PlanResolverPort
|
|
447
|
-
])
|
|
448
|
-
], StaticEntitlementService);
|
|
449
|
-
|
|
450
|
-
// src/platform/feature-guard-coverage.check.ts
|
|
451
|
-
import { Inject as Inject3, Injectable as Injectable3, Logger } from "@nestjs/common";
|
|
452
|
-
import { DiscoveryService, MetadataScanner } from "@nestjs/core";
|
|
453
|
-
function _ts_decorate5(decorators, target, key, desc) {
|
|
454
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
455
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
456
|
-
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;
|
|
457
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
458
|
-
}
|
|
459
|
-
__name(_ts_decorate5, "_ts_decorate");
|
|
460
|
-
function _ts_metadata4(k, v) {
|
|
461
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
462
|
-
}
|
|
463
|
-
__name(_ts_metadata4, "_ts_metadata");
|
|
464
|
-
function _ts_param4(paramIndex, decorator) {
|
|
465
|
-
return function(target, key) {
|
|
466
|
-
decorator(target, key, paramIndex);
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
__name(_ts_param4, "_ts_param");
|
|
470
|
-
var GUARDS_METADATA = "__guards__";
|
|
471
|
-
var METHOD_METADATA = "method";
|
|
472
|
-
var FeatureGuardCoverageCheck = class {
|
|
473
|
-
static {
|
|
474
|
-
__name(this, "FeatureGuardCoverageCheck");
|
|
475
|
-
}
|
|
476
|
-
discoveryService;
|
|
477
|
-
metadataScanner;
|
|
478
|
-
logger = new Logger("SaaSiCat");
|
|
479
|
-
constructor(discoveryService, metadataScanner) {
|
|
480
|
-
this.discoveryService = discoveryService;
|
|
481
|
-
this.metadataScanner = metadataScanner;
|
|
482
|
-
}
|
|
483
|
-
onApplicationBootstrap() {
|
|
484
|
-
const uncovered = this.findUncoveredRoutes();
|
|
485
|
-
if (uncovered.length === 0) return;
|
|
486
|
-
const list = uncovered.map((r) => ` ${r.controller}.${r.handler} \u2014 requires ${r.features.join(" or ")}`).join("\n");
|
|
487
|
-
this.logger.warn(`globalFeatureGuard is off and ${uncovered.length} annotated route(s) have no feature guard in front of them, so they serve unlicensed traffic:
|
|
488
|
-
${list}
|
|
489
|
-
Bind one behind your auth guard \u2014 @UseGuards(JwtAuthGuard, StaticFeatureGuard), or FeatureGuard from @saasicat/nest/billing on the V3 entitlement path. A guard of your own that wraps either one is not recognised here; if that is what these routes use, they are covered.`);
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Annotated handlers whose own guards and whose controller's guards contain
|
|
493
|
-
* no recognisable feature guard.
|
|
494
|
-
*
|
|
495
|
-
* Deliberately conservative in one direction only: an unrecognised wrapper
|
|
496
|
-
* is reported (and the message says so) rather than assumed safe, because
|
|
497
|
-
* the named route is cheap to check. The reverse — staying silent about a
|
|
498
|
-
* route with no guard at all — is the failure this exists to prevent.
|
|
499
|
-
*/
|
|
500
|
-
findUncoveredRoutes() {
|
|
501
|
-
const uncovered = [];
|
|
502
|
-
for (const wrapper of this.discoveryService.getControllers()) {
|
|
503
|
-
const instance = wrapper.instance;
|
|
504
|
-
if (!instance || typeof instance !== "object") continue;
|
|
505
|
-
const ctor = instance.constructor;
|
|
506
|
-
if (!ctor) continue;
|
|
507
|
-
const classGuards = readGuards(ctor);
|
|
508
|
-
const prototype = Object.getPrototypeOf(instance);
|
|
509
|
-
for (const method of this.metadataScanner.getAllMethodNames(prototype)) {
|
|
510
|
-
const handler = instance[method];
|
|
511
|
-
if (typeof handler !== "function") continue;
|
|
512
|
-
if (Reflect.getMetadata(METHOD_METADATA, handler) === void 0) continue;
|
|
513
|
-
const features = readFeatures(handler) ?? readFeatures(ctor) ?? /* not annotated */
|
|
514
|
-
null;
|
|
515
|
-
if (!features || features.length === 0) continue;
|
|
516
|
-
const guards = [
|
|
517
|
-
...classGuards,
|
|
518
|
-
...readGuards(handler)
|
|
519
|
-
];
|
|
520
|
-
if (guards.some(isPlatformFeatureGuard)) continue;
|
|
521
|
-
uncovered.push({
|
|
522
|
-
controller: ctor.name,
|
|
523
|
-
handler: method,
|
|
524
|
-
features
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
return uncovered;
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
FeatureGuardCoverageCheck = _ts_decorate5([
|
|
532
|
-
Injectable3(),
|
|
533
|
-
_ts_param4(0, Inject3(DiscoveryService)),
|
|
534
|
-
_ts_param4(1, Inject3(MetadataScanner)),
|
|
535
|
-
_ts_metadata4("design:type", Function),
|
|
536
|
-
_ts_metadata4("design:paramtypes", [
|
|
537
|
-
typeof DiscoveryService === "undefined" ? Object : DiscoveryService,
|
|
538
|
-
typeof MetadataScanner === "undefined" ? Object : MetadataScanner
|
|
539
|
-
])
|
|
540
|
-
], FeatureGuardCoverageCheck);
|
|
541
|
-
function readFeatures(target) {
|
|
542
|
-
const value = Reflect.getMetadata(REQUIRE_FEATURE_KEY, target);
|
|
543
|
-
return Array.isArray(value) ? value : null;
|
|
544
|
-
}
|
|
545
|
-
__name(readFeatures, "readFeatures");
|
|
546
|
-
function readGuards(target) {
|
|
547
|
-
const value = Reflect.getMetadata(GUARDS_METADATA, target);
|
|
548
|
-
if (!Array.isArray(value)) return [];
|
|
549
|
-
return value.flatMap((guard) => typeof guard === "function" ? [
|
|
550
|
-
guard
|
|
551
|
-
] : [
|
|
552
|
-
guard,
|
|
553
|
-
guard?.constructor
|
|
554
|
-
]);
|
|
555
|
-
}
|
|
556
|
-
__name(readGuards, "readGuards");
|
|
557
|
-
|
|
558
|
-
// src/platform/static-feature.guard.ts
|
|
559
|
-
import { ForbiddenException as ForbiddenException2, Inject as Inject4, Injectable as Injectable4, Optional } from "@nestjs/common";
|
|
560
|
-
import { Reflector } from "@nestjs/core";
|
|
561
|
-
import { AUTH_ERROR_CODES, FEATURE_NOT_LICENSED } from "@saasicat/types";
|
|
562
|
-
function _ts_decorate6(decorators, target, key, desc) {
|
|
563
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
564
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
565
|
-
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;
|
|
566
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
567
|
-
}
|
|
568
|
-
__name(_ts_decorate6, "_ts_decorate");
|
|
569
|
-
function _ts_metadata5(k, v) {
|
|
570
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
571
|
-
}
|
|
572
|
-
__name(_ts_metadata5, "_ts_metadata");
|
|
573
|
-
function _ts_param5(paramIndex, decorator) {
|
|
574
|
-
return function(target, key) {
|
|
575
|
-
decorator(target, key, paramIndex);
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
__name(_ts_param5, "_ts_param");
|
|
579
|
-
var STATIC_FEATURE_GUARD_CONFIG_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/StaticFeatureGuardConfig");
|
|
580
|
-
var StaticFeatureGuard = class {
|
|
581
|
-
static {
|
|
582
|
-
__name(this, "StaticFeatureGuard");
|
|
583
|
-
}
|
|
584
|
-
reflector;
|
|
585
|
-
entitlements;
|
|
586
|
-
config;
|
|
587
|
-
/** Lets `FeatureGuardCoverageCheck` recognise this guard across CJS entries. */
|
|
588
|
-
static [FEATURE_GUARD_MARKER] = true;
|
|
589
|
-
constructor(reflector, entitlements, config = null) {
|
|
590
|
-
this.reflector = reflector;
|
|
591
|
-
this.entitlements = entitlements;
|
|
592
|
-
this.config = config;
|
|
593
|
-
}
|
|
594
|
-
async canActivate(context) {
|
|
595
|
-
const required = this.reflector.getAllAndOverride(REQUIRE_FEATURE_KEY, [
|
|
596
|
-
context.getHandler(),
|
|
597
|
-
context.getClass()
|
|
598
|
-
]);
|
|
599
|
-
if (!required || required.length === 0) return true;
|
|
600
|
-
const request = context.switchToHttp().getRequest();
|
|
601
|
-
const user = request.user;
|
|
602
|
-
if (!user) {
|
|
603
|
-
throw new ForbiddenException2({
|
|
604
|
-
code: AUTH_ERROR_CODES.NOT_AUTHENTICATED,
|
|
605
|
-
message: "Not authenticated"
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
const role = this.config?.userRoleResolver ? this.config.userRoleResolver(user) : user.role ?? user.platformRole;
|
|
609
|
-
if (role === "SUPER_ADMIN") return true;
|
|
610
|
-
const tenantId = this.config?.tenantIdResolver ? this.config.tenantIdResolver(request) : request.tenantId ?? user.tenantId;
|
|
611
|
-
if (!tenantId) {
|
|
612
|
-
throw new ForbiddenException2({
|
|
613
|
-
code: AUTH_ERROR_CODES.NO_TENANT_ASSIGNED,
|
|
614
|
-
message: "No tenant assigned"
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
const snap = await this.entitlements.snapshot(tenantId);
|
|
618
|
-
const allowed = required.some((f) => snap.features.includes(f));
|
|
619
|
-
if (!allowed) {
|
|
620
|
-
const body = {
|
|
621
|
-
code: FEATURE_NOT_LICENSED,
|
|
622
|
-
featureKey: required[0],
|
|
623
|
-
featureKeys: required,
|
|
624
|
-
offers: [],
|
|
625
|
-
message: `Feature ${required.join(" / ")} is not included in the current plan.`
|
|
626
|
-
};
|
|
627
|
-
throw new ForbiddenException2(body);
|
|
628
|
-
}
|
|
629
|
-
return true;
|
|
630
|
-
}
|
|
631
|
-
};
|
|
632
|
-
StaticFeatureGuard = _ts_decorate6([
|
|
633
|
-
Injectable4(),
|
|
634
|
-
_ts_param5(0, Inject4(Reflector)),
|
|
635
|
-
_ts_param5(1, Inject4(StaticEntitlementService)),
|
|
636
|
-
_ts_param5(2, Optional()),
|
|
637
|
-
_ts_param5(2, Inject4(STATIC_FEATURE_GUARD_CONFIG_TOKEN)),
|
|
638
|
-
_ts_metadata5("design:type", Function),
|
|
639
|
-
_ts_metadata5("design:paramtypes", [
|
|
640
|
-
typeof Reflector === "undefined" ? Object : Reflector,
|
|
641
|
-
typeof StaticEntitlementService === "undefined" ? Object : StaticEntitlementService,
|
|
642
|
-
Object
|
|
643
|
-
])
|
|
644
|
-
], StaticFeatureGuard);
|
|
645
|
-
|
|
646
|
-
// src/platform/enforce-quota.interceptor.ts
|
|
647
|
-
import { Inject as Inject5, Injectable as Injectable5, Optional as Optional2 } from "@nestjs/common";
|
|
648
|
-
import { Reflector as Reflector2 } from "@nestjs/core";
|
|
649
|
-
import { from } from "rxjs";
|
|
650
|
-
import { switchMap } from "rxjs/operators";
|
|
651
|
-
function _ts_decorate7(decorators, target, key, desc) {
|
|
652
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
653
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
654
|
-
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;
|
|
655
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
656
|
-
}
|
|
657
|
-
__name(_ts_decorate7, "_ts_decorate");
|
|
658
|
-
function _ts_metadata6(k, v) {
|
|
659
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
660
|
-
}
|
|
661
|
-
__name(_ts_metadata6, "_ts_metadata");
|
|
662
|
-
function _ts_param6(paramIndex, decorator) {
|
|
663
|
-
return function(target, key) {
|
|
664
|
-
decorator(target, key, paramIndex);
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
__name(_ts_param6, "_ts_param");
|
|
668
|
-
var QUOTA_PROVIDERS_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/QuotaProviders");
|
|
669
|
-
var EnforceQuotaInterceptor = class {
|
|
670
|
-
static {
|
|
671
|
-
__name(this, "EnforceQuotaInterceptor");
|
|
672
|
-
}
|
|
673
|
-
reflector;
|
|
674
|
-
entitlements;
|
|
675
|
-
providers;
|
|
676
|
-
constructor(reflector, entitlements, providers = null) {
|
|
677
|
-
this.reflector = reflector;
|
|
678
|
-
this.entitlements = entitlements;
|
|
679
|
-
this.providers = providers;
|
|
680
|
-
}
|
|
681
|
-
intercept(context, next) {
|
|
682
|
-
const meta = this.reflector.getAllAndOverride(ENFORCE_QUOTA_KEY, [
|
|
683
|
-
context.getHandler(),
|
|
684
|
-
context.getClass()
|
|
685
|
-
]);
|
|
686
|
-
if (!meta?.quotaKey) return next.handle();
|
|
687
|
-
return from(this.check(context, meta)).pipe(switchMap(() => next.handle()));
|
|
688
|
-
}
|
|
689
|
-
async check(context, meta) {
|
|
690
|
-
const request = context.switchToHttp().getRequest();
|
|
691
|
-
const user = request.user;
|
|
692
|
-
if (!user) return;
|
|
693
|
-
const role = user.role ?? user.platformRole;
|
|
694
|
-
if (role === "SUPER_ADMIN") return;
|
|
695
|
-
const tenantId = request.tenantId ?? user.tenantId;
|
|
696
|
-
if (!tenantId) return;
|
|
697
|
-
const provider = (this.providers ?? []).find((p) => p.key === meta.quotaKey);
|
|
698
|
-
if (!provider) {
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
const limit = await this.entitlements.quotaLimit(tenantId, meta.quotaKey);
|
|
702
|
-
if (limit === null || limit === -1) return;
|
|
703
|
-
const current = await provider.count(tenantId);
|
|
704
|
-
const delta = meta.incrementBy ?? 1;
|
|
705
|
-
if (current + delta > limit) {
|
|
706
|
-
throw new LimitExceededError(meta.quotaKey, limit, current);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
};
|
|
710
|
-
EnforceQuotaInterceptor = _ts_decorate7([
|
|
711
|
-
Injectable5(),
|
|
712
|
-
_ts_param6(0, Inject5(Reflector2)),
|
|
713
|
-
_ts_param6(1, Inject5(StaticEntitlementService)),
|
|
714
|
-
_ts_param6(2, Optional2()),
|
|
715
|
-
_ts_param6(2, Inject5(QUOTA_PROVIDERS_TOKEN)),
|
|
716
|
-
_ts_metadata6("design:type", Function),
|
|
717
|
-
_ts_metadata6("design:paramtypes", [
|
|
718
|
-
typeof Reflector2 === "undefined" ? Object : Reflector2,
|
|
719
|
-
typeof StaticEntitlementService === "undefined" ? Object : StaticEntitlementService,
|
|
720
|
-
Object
|
|
721
|
-
])
|
|
722
|
-
], EnforceQuotaInterceptor);
|
|
723
|
-
|
|
724
|
-
// src/platform/quota-providers-usage-snapshot.ts
|
|
725
|
-
var QuotaProvidersUsageSnapshot = class {
|
|
726
|
-
static {
|
|
727
|
-
__name(this, "QuotaProvidersUsageSnapshot");
|
|
728
|
-
}
|
|
729
|
-
providers;
|
|
730
|
-
constructor(providers) {
|
|
731
|
-
this.providers = providers;
|
|
732
|
-
}
|
|
733
|
-
async snapshot(tenantId) {
|
|
734
|
-
const entries = await Promise.all(this.providers.map(async (provider) => [
|
|
735
|
-
provider.key,
|
|
736
|
-
await provider.count(tenantId)
|
|
737
|
-
]));
|
|
738
|
-
return Object.fromEntries(entries);
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
|
|
742
|
-
// src/platform/subscription-plan-resolver.ts
|
|
743
|
-
var DEFAULT_ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
744
|
-
"ACTIVE",
|
|
745
|
-
"TRIAL"
|
|
746
|
-
]);
|
|
747
|
-
var SubscriptionPlanResolver = class {
|
|
748
|
-
static {
|
|
749
|
-
__name(this, "SubscriptionPlanResolver");
|
|
750
|
-
}
|
|
751
|
-
subscriptions;
|
|
752
|
-
activeStatuses;
|
|
753
|
-
constructor(subscriptions, activeStatuses = DEFAULT_ACTIVE_STATUSES) {
|
|
754
|
-
this.subscriptions = subscriptions;
|
|
755
|
-
this.activeStatuses = activeStatuses;
|
|
756
|
-
}
|
|
757
|
-
async getPlanIdForTenant(tenantId) {
|
|
758
|
-
const subscription = await this.subscriptions.findByTenantId(tenantId);
|
|
759
|
-
if (!subscription || !this.activeStatuses.has(subscription.status)) return null;
|
|
760
|
-
return subscription.plan;
|
|
761
|
-
}
|
|
762
|
-
};
|
|
763
|
-
|
|
764
|
-
// src/platform/tenant-manifest.service.ts
|
|
765
|
-
import { Injectable as Injectable6 } from "@nestjs/common";
|
|
766
|
-
function _ts_decorate8(decorators, target, key, desc) {
|
|
767
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
768
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
769
|
-
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;
|
|
770
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
771
|
-
}
|
|
772
|
-
__name(_ts_decorate8, "_ts_decorate");
|
|
773
|
-
function _ts_metadata7(k, v) {
|
|
774
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
775
|
-
}
|
|
776
|
-
__name(_ts_metadata7, "_ts_metadata");
|
|
777
|
-
var TenantManifestService = class {
|
|
778
|
-
static {
|
|
779
|
-
__name(this, "TenantManifestService");
|
|
780
|
-
}
|
|
781
|
-
entitlements;
|
|
782
|
-
navItems = [];
|
|
783
|
-
constructor(entitlements) {
|
|
784
|
-
this.entitlements = entitlements;
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Call in the app's `OnModuleInit`: registers app navigation for the
|
|
788
|
-
* Tenant UI. Idempotent: the same `id` overwrites.
|
|
789
|
-
*/
|
|
790
|
-
registerNavItem(item) {
|
|
791
|
-
const existing = this.navItems.findIndex((i) => i.id === item.id);
|
|
792
|
-
if (existing >= 0) this.navItems[existing] = item;
|
|
793
|
-
else this.navItems.push(item);
|
|
794
|
-
}
|
|
795
|
-
/** Bulk variant. */
|
|
796
|
-
registerNavItems(items) {
|
|
797
|
-
for (const item of items) this.registerNavItem(item);
|
|
798
|
-
}
|
|
799
|
-
/**
|
|
800
|
-
* Returns the filtered manifest for a Tenant. NavItems with
|
|
801
|
-
* `requiresFeature` are filtered out server-side as soon as none of the
|
|
802
|
-
* required features are present in the entitlement snapshot.
|
|
803
|
-
*/
|
|
804
|
-
async getManifest(tenantId) {
|
|
805
|
-
const snap = await this.entitlements.snapshot(tenantId);
|
|
806
|
-
const featureSet = new Set(snap.features);
|
|
807
|
-
const visible = this.navItems.filter((item) => isVisible(item, featureSet)).map((item) => ({
|
|
808
|
-
...item
|
|
809
|
-
})).sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
810
|
-
return {
|
|
811
|
-
schemaVersion: 1,
|
|
812
|
-
tenant: {
|
|
813
|
-
id: tenantId
|
|
814
|
-
},
|
|
815
|
-
planId: snap.planId,
|
|
816
|
-
features: snap.features,
|
|
817
|
-
quotas: snap.quotas,
|
|
818
|
-
navigation: visible
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
TenantManifestService = _ts_decorate8([
|
|
823
|
-
Injectable6(),
|
|
824
|
-
_ts_metadata7("design:type", Function),
|
|
825
|
-
_ts_metadata7("design:paramtypes", [
|
|
826
|
-
typeof StaticEntitlementService === "undefined" ? Object : StaticEntitlementService
|
|
827
|
-
])
|
|
828
|
-
], TenantManifestService);
|
|
829
|
-
function isVisible(item, features) {
|
|
830
|
-
if (!item.requiresFeature) return true;
|
|
831
|
-
const required = Array.isArray(item.requiresFeature) ? item.requiresFeature : [
|
|
832
|
-
item.requiresFeature
|
|
833
|
-
];
|
|
834
|
-
return required.some((f) => features.has(f));
|
|
835
|
-
}
|
|
836
|
-
__name(isVisible, "isVisible");
|
|
837
|
-
|
|
838
|
-
// src/platform/tenant-manifest.controller.ts
|
|
839
|
-
import { Controller as Controller2, Get as Get2, Inject as Inject6, Req, UseGuards } from "@nestjs/common";
|
|
840
|
-
function _ts_decorate9(decorators, target, key, desc) {
|
|
841
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
842
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
843
|
-
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;
|
|
844
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
845
|
-
}
|
|
846
|
-
__name(_ts_decorate9, "_ts_decorate");
|
|
847
|
-
function _ts_metadata8(k, v) {
|
|
848
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
849
|
-
}
|
|
850
|
-
__name(_ts_metadata8, "_ts_metadata");
|
|
851
|
-
function _ts_param7(paramIndex, decorator) {
|
|
852
|
-
return function(target, key) {
|
|
853
|
-
decorator(target, key, paramIndex);
|
|
854
|
-
};
|
|
855
|
-
}
|
|
856
|
-
__name(_ts_param7, "_ts_param");
|
|
857
|
-
function buildTenantManifestController(options) {
|
|
858
|
-
const path = options.path ?? "tenant/manifest";
|
|
859
|
-
let GeneratedTenantManifestController = class GeneratedTenantManifestController {
|
|
860
|
-
static {
|
|
861
|
-
__name(this, "GeneratedTenantManifestController");
|
|
862
|
-
}
|
|
863
|
-
svc;
|
|
864
|
-
constructor(svc) {
|
|
865
|
-
this.svc = svc;
|
|
866
|
-
}
|
|
867
|
-
async get(req) {
|
|
868
|
-
const tenantId = req.user?.tenantId ?? req.tenantId;
|
|
869
|
-
if (!tenantId) {
|
|
870
|
-
throw new Error("No tenant on the request \u2014 TenantManifest requires user.tenantId.");
|
|
871
|
-
}
|
|
872
|
-
return this.svc.getManifest(tenantId);
|
|
873
|
-
}
|
|
874
|
-
};
|
|
875
|
-
_ts_decorate9([
|
|
876
|
-
Get2(),
|
|
877
|
-
_ts_param7(0, Req()),
|
|
878
|
-
_ts_metadata8("design:type", Function),
|
|
879
|
-
_ts_metadata8("design:paramtypes", [
|
|
880
|
-
typeof RequestWithUser === "undefined" ? Object : RequestWithUser
|
|
881
|
-
]),
|
|
882
|
-
_ts_metadata8("design:returntype", Promise)
|
|
883
|
-
], GeneratedTenantManifestController.prototype, "get", null);
|
|
884
|
-
GeneratedTenantManifestController = _ts_decorate9([
|
|
885
|
-
Controller2(path),
|
|
886
|
-
UseGuards(...options.guards),
|
|
887
|
-
_ts_param7(0, Inject6(TenantManifestService)),
|
|
888
|
-
_ts_metadata8("design:type", Function),
|
|
889
|
-
_ts_metadata8("design:paramtypes", [
|
|
890
|
-
typeof TenantManifestService === "undefined" ? Object : TenantManifestService
|
|
891
|
-
])
|
|
892
|
-
], GeneratedTenantManifestController);
|
|
893
|
-
return GeneratedTenantManifestController;
|
|
894
|
-
}
|
|
895
|
-
__name(buildTenantManifestController, "buildTenantManifestController");
|
|
896
|
-
|
|
897
|
-
// src/platform/saas-platform.module.ts
|
|
898
|
-
import { Logger as Logger2, Module as Module2 } from "@nestjs/common";
|
|
899
|
-
import { APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
|
|
900
|
-
import { assertPersistenceCapabilities } from "@saasicat/types";
|
|
901
|
-
import { DiscoveryModule as NestDiscoveryModule } from "@nestjs/core";
|
|
902
|
-
function _ts_decorate10(decorators, target, key, desc) {
|
|
903
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
904
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
905
|
-
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;
|
|
906
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
907
|
-
}
|
|
908
|
-
__name(_ts_decorate10, "_ts_decorate");
|
|
909
|
-
var PLATFORM_LOGGER = new Logger2("SaaSiCat");
|
|
910
|
-
var PLATFORM_SUBSCRIPTION_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/PlatformSubscriptionRepository");
|
|
911
|
-
var STANDARD_MANIFEST_REGISTRATION_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform-nest/StandardManifestRegistration");
|
|
912
|
-
function buildStandardManifestContribution(catalog, adminResources, promoCodes) {
|
|
913
|
-
const capabilities = {
|
|
914
|
-
"discovery.read": true
|
|
915
|
-
};
|
|
916
|
-
if (catalog && catalog.adminControllers !== false) {
|
|
917
|
-
Object.assign(capabilities, {
|
|
918
|
-
"plans.read": true,
|
|
919
|
-
"plans.publish": true,
|
|
920
|
-
"bundles.read": true,
|
|
921
|
-
"bundles.write": true,
|
|
922
|
-
"bundles.publish": true,
|
|
923
|
-
"marketingProjections.read": true,
|
|
924
|
-
"marketingProjections.write": true
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
const navigation = {};
|
|
928
|
-
if (adminResources) {
|
|
929
|
-
Object.assign(capabilities, {
|
|
930
|
-
"tenants.read": true,
|
|
931
|
-
"tenants.suspend": true,
|
|
932
|
-
"tenants.reactivate": true,
|
|
933
|
-
"users.read": true,
|
|
934
|
-
"audit.read": true,
|
|
935
|
-
"subscriptions.read": true
|
|
936
|
-
});
|
|
937
|
-
navigation.standardPages = {
|
|
938
|
-
subscriptions: {
|
|
939
|
-
enabled: true,
|
|
940
|
-
requiredCapability: "subscriptions.read"
|
|
941
|
-
}
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
if (promoCodes) {
|
|
945
|
-
Object.assign(capabilities, {
|
|
946
|
-
"promoCodes.read": true,
|
|
947
|
-
"promoCodes.write": true,
|
|
948
|
-
"promoCodes.delete": true
|
|
949
|
-
});
|
|
950
|
-
navigation.standardPages = {
|
|
951
|
-
...navigation.standardPages ?? {},
|
|
952
|
-
promoCodes: {
|
|
953
|
-
enabled: true,
|
|
954
|
-
requiredCapability: "promoCodes.read"
|
|
955
|
-
}
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
return {
|
|
959
|
-
capabilities,
|
|
960
|
-
navigation: navigation.standardPages ? navigation : void 0
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
__name(buildStandardManifestContribution, "buildStandardManifestContribution");
|
|
964
|
-
function normalizeTenantAuthGuards(guards) {
|
|
965
|
-
if (!Array.isArray(guards)) return guards;
|
|
966
|
-
return {
|
|
967
|
-
useFactory: /* @__PURE__ */ __name((...instances) => instances, "useFactory"),
|
|
968
|
-
inject: guards
|
|
969
|
-
};
|
|
970
|
-
}
|
|
971
|
-
__name(normalizeTenantAuthGuards, "normalizeTenantAuthGuards");
|
|
972
|
-
function quotaUsageSnapshotProvider(quotaProviders) {
|
|
973
|
-
return {
|
|
974
|
-
useFactory: /* @__PURE__ */ __name((...providers) => new QuotaProvidersUsageSnapshot(providers), "useFactory"),
|
|
975
|
-
inject: quotaProviders
|
|
976
|
-
};
|
|
977
|
-
}
|
|
978
|
-
__name(quotaUsageSnapshotProvider, "quotaUsageSnapshotProvider");
|
|
979
|
-
function buildMinimalManifestConfig() {
|
|
980
|
-
return {
|
|
981
|
-
useFactory: /* @__PURE__ */ __name((catalog) => ({
|
|
982
|
-
project: {
|
|
983
|
-
key: catalog.projectKey,
|
|
984
|
-
displayName: catalog.app?.name ?? catalog.projectKey,
|
|
985
|
-
label: catalog.app?.label,
|
|
986
|
-
icon: catalog.app?.icon,
|
|
987
|
-
logoUrl: catalog.app?.logoUrl,
|
|
988
|
-
environment: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
989
|
-
availableLocales: catalog.marketing?.availableLocales,
|
|
990
|
-
defaultLocale: catalog.marketing?.availableLocales?.[0]
|
|
991
|
-
},
|
|
992
|
-
build: {
|
|
993
|
-
platformPackageVersion: "0.0.0",
|
|
994
|
-
appVersion: "0.0.0"
|
|
995
|
-
},
|
|
996
|
-
planCatalogSnapshot: {
|
|
997
|
-
source: "saas-platform-module",
|
|
998
|
-
hash: "sha256-quickstart",
|
|
999
|
-
currency: catalog.currency,
|
|
1000
|
-
vatRate: catalog.vatRate,
|
|
1001
|
-
plans: catalog.plans ?? [],
|
|
1002
|
-
features: catalog.features ?? []
|
|
1003
|
-
}
|
|
1004
|
-
}), "useFactory"),
|
|
1005
|
-
inject: [
|
|
1006
|
-
PLAN_CATALOG_TOKEN
|
|
1007
|
-
]
|
|
1008
|
-
};
|
|
1009
|
-
}
|
|
1010
|
-
__name(buildMinimalManifestConfig, "buildMinimalManifestConfig");
|
|
1011
|
-
var SaasPlatformModule = class _SaasPlatformModule {
|
|
1012
|
-
static {
|
|
1013
|
-
__name(this, "SaasPlatformModule");
|
|
1014
|
-
}
|
|
1015
|
-
static forRoot(options) {
|
|
1016
|
-
const explicit = options.adapters ?? {};
|
|
1017
|
-
const persistence = options.persistence;
|
|
1018
|
-
const catalogConfig = options.catalog || null;
|
|
1019
|
-
const tenantBillingConfig = options.tenantBilling || null;
|
|
1020
|
-
const subscriptionBundlesConfig = options.subscriptionBundles || null;
|
|
1021
|
-
const adminResourcesConfig = options.adminResources || null;
|
|
1022
|
-
const promoCodesConfig = options.promoCodes || null;
|
|
1023
|
-
const setupConfig = options.setup || null;
|
|
1024
|
-
const adminStatsConfig = options.adminStats || null;
|
|
1025
|
-
const checkoutOfferConfig = options.checkoutOffer || null;
|
|
1026
|
-
const subscriptionContractConfig = options.subscriptionContract || null;
|
|
1027
|
-
const requiresFullEntitlement = Boolean(options.entitlement || tenantBillingConfig || subscriptionBundlesConfig);
|
|
1028
|
-
const adapters = {
|
|
1029
|
-
mfa: explicit.mfa ?? persistence?.core.mfa,
|
|
1030
|
-
audit: explicit.audit ?? persistence?.core.audit,
|
|
1031
|
-
rlsBypass: explicit.rlsBypass ?? persistence?.core.rlsBypass,
|
|
1032
|
-
planCatalogReadSink: explicit.planCatalogReadSink ?? persistence?.planCatalogReadSink,
|
|
1033
|
-
planResolver: explicit.planResolver,
|
|
1034
|
-
subscriptionRepository: explicit.subscriptionRepository ?? persistence?.entitlement?.subscriptionRepository,
|
|
1035
|
-
planVersionRepository: explicit.planVersionRepository ?? persistence?.entitlement?.planVersionRepository,
|
|
1036
|
-
transactionRunner: explicit.transactionRunner ?? persistence?.core.transactionRunner
|
|
1037
|
-
};
|
|
1038
|
-
const missingCore = [
|
|
1039
|
-
"mfa",
|
|
1040
|
-
"audit",
|
|
1041
|
-
"rlsBypass"
|
|
1042
|
-
].filter((key) => adapters[key] === void 0);
|
|
1043
|
-
if (missingCore.length) {
|
|
1044
|
-
throw new Error(`SaasPlatformModule.forRoot: adapters missing (provide them via \`adapters\` or a \`persistence\` bundle): ${missingCore.join(", ")}`);
|
|
1045
|
-
}
|
|
1046
|
-
const mfaPort = adapters.mfa;
|
|
1047
|
-
const auditPort = adapters.audit;
|
|
1048
|
-
const rlsBypassPort = adapters.rlsBypass;
|
|
1049
|
-
if (!options.planCatalog && (!adapters.planCatalogReadSink || !options.dbCatalog)) {
|
|
1050
|
-
throw new Error("SaasPlatformModule.forRoot: either set `planCatalog` (quickstart YAML path) or, for DB hydration, BOTH a planCatalogReadSink (`adapters`/`persistence`) AND `dbCatalog` ({ projectKey, currency, vatRate }).");
|
|
1051
|
-
}
|
|
1052
|
-
if (catalogConfig && !persistence?.catalog) {
|
|
1053
|
-
throw new Error("SaasPlatformModule.forRoot: catalog is enabled, but `persistence.catalog` is missing. Use a complete persistence bundle or wire CatalogModule directly.");
|
|
1054
|
-
}
|
|
1055
|
-
if (adminResourcesConfig && adminResourcesConfig !== true && !adminResourcesConfig.resources && !persistence?.adminResources) {
|
|
1056
|
-
throw new Error("SaasPlatformModule.forRoot: adminResources is enabled, but `persistence.adminResources` is missing.");
|
|
1057
|
-
}
|
|
1058
|
-
if (promoCodesConfig && (!persistence?.promo || !adapters.transactionRunner)) {
|
|
1059
|
-
throw new Error("SaasPlatformModule.forRoot: promoCodes requires `persistence.promo` and a transactionRunner.");
|
|
1060
|
-
}
|
|
1061
|
-
if (setupConfig && !((setupConfig === true ? void 0 : setupConfig.provisioningPort) ?? persistence?.core.superAdminProvisioning)) {
|
|
1062
|
-
throw new Error("SaasPlatformModule.forRoot: setup is enabled, but no provisioningPort is available (set `setup.provisioningPort` or `persistence.core.superAdminProvisioning`).");
|
|
1063
|
-
}
|
|
1064
|
-
if (adminStatsConfig && !adminStatsConfig.auditStatsPort && !persistence?.core.auditStats) {
|
|
1065
|
-
throw new Error("SaasPlatformModule.forRoot: adminStats is enabled, but no auditStatsPort is available (set `adminStats.auditStatsPort` or `persistence.core.auditStats`).");
|
|
1066
|
-
}
|
|
1067
|
-
if (subscriptionContractConfig) {
|
|
1068
|
-
const explicitRepository = subscriptionContractConfig === true ? void 0 : subscriptionContractConfig.subscriptionContractRepository;
|
|
1069
|
-
if (!explicitRepository && !persistence?.entitlement?.subscriptionContractRepository) {
|
|
1070
|
-
throw new Error("SaasPlatformModule.forRoot: subscriptionContract is enabled, but no repository is available (set `subscriptionContract.subscriptionContractRepository` or use a compatible persistence bundle).");
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
if (promoCodesConfig && promoCodesConfig !== true && promoCodesConfig.includePublicController !== false && !promoCodesConfig.firstTimeCustomerCheck) {
|
|
1074
|
-
throw new Error("SaasPlatformModule.forRoot: public promo preview requires `firstTimeCustomerCheck`.");
|
|
1075
|
-
}
|
|
1076
|
-
if (adminResourcesConfig === true && !persistence?.adminResources) {
|
|
1077
|
-
throw new Error("SaasPlatformModule.forRoot: adminResources is enabled, but `persistence.adminResources` is missing.");
|
|
1078
|
-
}
|
|
1079
|
-
if (tenantBillingConfig && !persistence?.tenantBilling) {
|
|
1080
|
-
const missing = [
|
|
1081
|
-
!tenantBillingConfig.subscriptionUsagePort && "subscriptionUsagePort",
|
|
1082
|
-
!tenantBillingConfig.subscriptionWritePort && "subscriptionWritePort"
|
|
1083
|
-
].filter(Boolean);
|
|
1084
|
-
if (missing.length) {
|
|
1085
|
-
throw new Error(`SaasPlatformModule.forRoot: tenantBilling is enabled, but adapters are missing: ${missing.join(", ")}`);
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
if (subscriptionBundlesConfig && !tenantBillingConfig) {
|
|
1089
|
-
throw new Error("SaasPlatformModule.forRoot: subscriptionBundles requires tenantBilling so auth and subscription usage can be shared.");
|
|
1090
|
-
}
|
|
1091
|
-
if (subscriptionBundlesConfig) {
|
|
1092
|
-
const missing = [];
|
|
1093
|
-
if (!persistence?.entitlement?.subscriptionBundleRepository) {
|
|
1094
|
-
missing.push("subscriptionBundleRepository");
|
|
1095
|
-
}
|
|
1096
|
-
if (!persistence?.catalog?.bundleRepository) {
|
|
1097
|
-
missing.push("bundleRepository");
|
|
1098
|
-
}
|
|
1099
|
-
if (missing.length) {
|
|
1100
|
-
throw new Error(`SaasPlatformModule.forRoot: subscriptionBundles is enabled, but persistence adapters are missing: ${missing.join(", ")}`);
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
if (requiresFullEntitlement) {
|
|
1104
|
-
const missing = [];
|
|
1105
|
-
if (!adapters.subscriptionRepository) missing.push("subscriptionRepository");
|
|
1106
|
-
if (!adapters.planVersionRepository) missing.push("planVersionRepository");
|
|
1107
|
-
if (!adapters.transactionRunner) missing.push("transactionRunner");
|
|
1108
|
-
if (missing.length) {
|
|
1109
|
-
throw new Error(`SaasPlatformModule.forRoot: entitlement active or required by the standard stack, but adapters are missing: ${missing.join(", ")}`);
|
|
1110
|
-
}
|
|
1111
|
-
if (persistence) {
|
|
1112
|
-
assertPersistenceCapabilities(persistence.capabilities, {
|
|
1113
|
-
transactions: true,
|
|
1114
|
-
pessimisticLocking: true
|
|
1115
|
-
}, "SaasPlatformModule entitlement (transactional enforceLimit)");
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
const dbCatalog = options.dbCatalog;
|
|
1119
|
-
const planCatalogModule = options.planCatalog ? PlanCatalogModule.forRootWithCatalog(options.planCatalog, {
|
|
1120
|
-
global: true
|
|
1121
|
-
}) : PlanCatalogModule.forRoot({
|
|
1122
|
-
projectKey: dbCatalog.projectKey,
|
|
1123
|
-
app: dbCatalog.app,
|
|
1124
|
-
currency: dbCatalog.currency,
|
|
1125
|
-
vatRate: dbCatalog.vatRate,
|
|
1126
|
-
marketing: dbCatalog.marketing,
|
|
1127
|
-
sink: adapters.planCatalogReadSink,
|
|
1128
|
-
imports: options.imports
|
|
1129
|
-
});
|
|
1130
|
-
const appInfo = options.app ?? {
|
|
1131
|
-
key: options.planCatalog?.projectKey ?? options.dbCatalog?.projectKey ?? "app",
|
|
1132
|
-
version: options.planCatalog?.app?.version ?? options.dbCatalog?.app?.version ?? "0.0.0"
|
|
1133
|
-
};
|
|
1134
|
-
const imports = [
|
|
1135
|
-
// Make injected client/auth providers visible to the high-level
|
|
1136
|
-
// module's own quota providers and automatic plan resolver too.
|
|
1137
|
-
...options.imports ?? [],
|
|
1138
|
-
planCatalogModule,
|
|
1139
|
-
DiscoveryModule.forRoot({
|
|
1140
|
-
app: appInfo,
|
|
1141
|
-
controller: {
|
|
1142
|
-
guards: options.controller.guards
|
|
1143
|
-
},
|
|
1144
|
-
imports: options.imports,
|
|
1145
|
-
snapshotPath: options.discoverySnapshotPath === void 0 ? "var/discovery-snapshot.json" : options.discoverySnapshotPath
|
|
1146
|
-
}),
|
|
1147
|
-
AdminModule.forRoot({
|
|
1148
|
-
mfaPort,
|
|
1149
|
-
auditPort,
|
|
1150
|
-
rlsBypassPort,
|
|
1151
|
-
imports: options.imports,
|
|
1152
|
-
global: true
|
|
1153
|
-
}),
|
|
1154
|
-
AdminManifestModule.forRoot({
|
|
1155
|
-
config: options.adminManifestConfig ?? buildMinimalManifestConfig(),
|
|
1156
|
-
extraProviders: options.adminManifestExtraProviders,
|
|
1157
|
-
includeManifestController: options.includeManifestController,
|
|
1158
|
-
guards: options.controller.guards,
|
|
1159
|
-
reloadGuards: options.reloadGuards,
|
|
1160
|
-
imports: options.imports,
|
|
1161
|
-
// Global like AdminModule above: apps register their manifest
|
|
1162
|
-
// contribution by injecting AdminManifestService into one of
|
|
1163
|
-
// their own modules (handbook §6.6). Re-exporting the module
|
|
1164
|
-
// from here does not make that injection resolvable.
|
|
1165
|
-
global: true
|
|
1166
|
-
})
|
|
1167
|
-
];
|
|
1168
|
-
if (requiresFullEntitlement) {
|
|
1169
|
-
imports.push(EntitlementModule.forRoot({
|
|
1170
|
-
subscriptionRepository: adapters.subscriptionRepository,
|
|
1171
|
-
planVersionRepository: adapters.planVersionRepository,
|
|
1172
|
-
transactionRunner: adapters.transactionRunner,
|
|
1173
|
-
resolutionConfig: options.entitlement ? options.entitlement.resolutionConfig : void 0,
|
|
1174
|
-
subscriptionContractRepository: persistence?.entitlement?.subscriptionContractRepository,
|
|
1175
|
-
subscriptionBundleRepository: persistence?.entitlement?.subscriptionBundleRepository,
|
|
1176
|
-
bundleRepository: persistence?.entitlement?.bundleRepository,
|
|
1177
|
-
imports: options.imports,
|
|
1178
|
-
global: Boolean(tenantBillingConfig || subscriptionBundlesConfig)
|
|
1179
|
-
}));
|
|
1180
|
-
}
|
|
1181
|
-
if (catalogConfig) {
|
|
1182
|
-
const catalog = persistence?.catalog;
|
|
1183
|
-
imports.push(CatalogModule.forRoot({
|
|
1184
|
-
planRepository: catalog.planRepository,
|
|
1185
|
-
bundleRepository: catalog.bundleRepository,
|
|
1186
|
-
catalogEntryRepository: catalog.catalogEntryRepository,
|
|
1187
|
-
marketingProjectionRepository: catalog.marketingProjectionRepository,
|
|
1188
|
-
promotionRepository: catalog.promotionRepository,
|
|
1189
|
-
marketingSettingsRepository: catalog.marketingSettingsRepository,
|
|
1190
|
-
controller: catalogConfig.adminControllers === false ? void 0 : {
|
|
1191
|
-
guards: options.controller.guards
|
|
1192
|
-
},
|
|
1193
|
-
imports: catalogConfig.imports ?? options.imports,
|
|
1194
|
-
extraProviders: catalogConfig.extraProviders,
|
|
1195
|
-
strictModeCheckMode: catalogConfig.strictModeCheckMode,
|
|
1196
|
-
autoSyncDiscoveryAtBoot: catalogConfig.autoSyncDiscoveryAtBoot,
|
|
1197
|
-
marketedOnlyFeatures: catalogConfig.marketedOnlyFeatures,
|
|
1198
|
-
featureUiRegistry: catalogConfig.featureUiRegistry,
|
|
1199
|
-
publicMarketingCatalog: catalogConfig.publicMarketingCatalog
|
|
1200
|
-
}));
|
|
1201
|
-
if (catalogConfig.publicCatalog !== false) {
|
|
1202
|
-
imports.push(PublicCatalogModule.forRoot({
|
|
1203
|
-
featureUiRegistry: catalogConfig.featureUiRegistry,
|
|
1204
|
-
projectKey: appInfo.key,
|
|
1205
|
-
bundleRepository: catalog.bundleRepository,
|
|
1206
|
-
marketingRepository: catalog.marketingProjectionRepository,
|
|
1207
|
-
catalogEntryRepository: catalog.catalogEntryRepository,
|
|
1208
|
-
imports: catalogConfig.imports ?? options.imports
|
|
1209
|
-
}));
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
if (adminResourcesConfig) {
|
|
1213
|
-
const config = adminResourcesConfig === true ? {} : adminResourcesConfig;
|
|
1214
|
-
imports.push(AdminResourcesModule.forRoot({
|
|
1215
|
-
resources: config.resources ?? persistence?.adminResources?.resources,
|
|
1216
|
-
guards: config.guards ?? [
|
|
1217
|
-
...options.controller.guards,
|
|
1218
|
-
SuperAdminGuard
|
|
1219
|
-
],
|
|
1220
|
-
imports: config.imports ?? options.imports
|
|
1221
|
-
}));
|
|
1222
|
-
}
|
|
1223
|
-
if (promoCodesConfig) {
|
|
1224
|
-
const config = promoCodesConfig === true ? {} : promoCodesConfig;
|
|
1225
|
-
const promo = persistence?.promo;
|
|
1226
|
-
const { firstTimeCustomerCheck, adminGuards, imports: promoImports, includePublicController, adminController, ...promoOptions } = config;
|
|
1227
|
-
imports.push(PromoCodesModule.forRoot({
|
|
1228
|
-
...promoOptions,
|
|
1229
|
-
promoCodeRepository: promo.promoCodeRepository,
|
|
1230
|
-
redemptionRepository: promo.redemptionRepository,
|
|
1231
|
-
validationLogRepository: promo.validationLogRepository,
|
|
1232
|
-
subscriptionLookup: promo.subscriptionLookup,
|
|
1233
|
-
revenueAggregator: promo.revenueAggregator,
|
|
1234
|
-
transactionRunner: adapters.transactionRunner,
|
|
1235
|
-
firstTimeCustomerCheck: firstTimeCustomerCheck ?? {
|
|
1236
|
-
hasExistingCustomerForEmail: /* @__PURE__ */ __name(async () => false, "hasExistingCustomerForEmail")
|
|
1237
|
-
},
|
|
1238
|
-
includePublicController: includePublicController ?? false,
|
|
1239
|
-
adminController: adminController === false ? false : {
|
|
1240
|
-
guards: adminGuards ?? [
|
|
1241
|
-
...options.controller.guards,
|
|
1242
|
-
SuperAdminGuard
|
|
1243
|
-
]
|
|
1244
|
-
},
|
|
1245
|
-
imports: promoImports ?? options.imports
|
|
1246
|
-
}));
|
|
1247
|
-
}
|
|
1248
|
-
let sharedTenantAuthGuards;
|
|
1249
|
-
let sharedSubscriptionUsagePort;
|
|
1250
|
-
let quotaProvidersHostedByTenantBilling = false;
|
|
1251
|
-
if (tenantBillingConfig) {
|
|
1252
|
-
const tenantSlice = persistence?.tenantBilling;
|
|
1253
|
-
const { authGuards, subscriptionUsagePort, usageSnapshotPort, subscriptionWritePort, imports: tenantImports, extraProviders, extraExports, ...tenantOptions } = tenantBillingConfig;
|
|
1254
|
-
const quotaProviders = options.quotaProviders ?? [];
|
|
1255
|
-
quotaProvidersHostedByTenantBilling = quotaProviders.length > 0;
|
|
1256
|
-
sharedTenantAuthGuards = normalizeTenantAuthGuards(authGuards);
|
|
1257
|
-
sharedSubscriptionUsagePort = subscriptionUsagePort ?? tenantSlice?.subscriptionUsagePort;
|
|
1258
|
-
const resolvedUsageSnapshotPort = usageSnapshotPort ?? tenantSlice?.usageSnapshotPort ?? quotaUsageSnapshotProvider(options.quotaProviders ?? []);
|
|
1259
|
-
imports.push(TenantBillingModule.forRoot({
|
|
1260
|
-
...tenantOptions,
|
|
1261
|
-
authGuards: sharedTenantAuthGuards,
|
|
1262
|
-
subscriptionUsagePort: sharedSubscriptionUsagePort,
|
|
1263
|
-
usageSnapshotPort: resolvedUsageSnapshotPort,
|
|
1264
|
-
subscriptionWritePort: subscriptionWritePort ?? tenantSlice?.subscriptionWritePort,
|
|
1265
|
-
imports: tenantImports ?? options.imports,
|
|
1266
|
-
extraProviders: [
|
|
1267
|
-
...quotaProviders,
|
|
1268
|
-
...extraProviders ?? []
|
|
1269
|
-
],
|
|
1270
|
-
extraExports: [
|
|
1271
|
-
...quotaProviders,
|
|
1272
|
-
...extraExports ?? []
|
|
1273
|
-
]
|
|
1274
|
-
}));
|
|
1275
|
-
}
|
|
1276
|
-
if (subscriptionBundlesConfig) {
|
|
1277
|
-
const config = subscriptionBundlesConfig === true ? {} : subscriptionBundlesConfig;
|
|
1278
|
-
const { controller, imports: bundleImports, extraProviders, ...bundleOptions } = config;
|
|
1279
|
-
imports.push(SubscriptionBundleModule.forRoot({
|
|
1280
|
-
...bundleOptions,
|
|
1281
|
-
subscriptionBundleRepository: persistence?.entitlement?.subscriptionBundleRepository,
|
|
1282
|
-
bundleRepository: persistence?.catalog?.bundleRepository,
|
|
1283
|
-
controller: controller === false ? void 0 : {
|
|
1284
|
-
...controller ?? {},
|
|
1285
|
-
authGuards: sharedTenantAuthGuards,
|
|
1286
|
-
subscriptionUsagePort: sharedSubscriptionUsagePort
|
|
1287
|
-
},
|
|
1288
|
-
imports: bundleImports ?? tenantBillingConfig?.imports ?? options.imports,
|
|
1289
|
-
extraProviders
|
|
1290
|
-
}));
|
|
1291
|
-
}
|
|
1292
|
-
if (setupConfig) {
|
|
1293
|
-
const config = setupConfig === true ? {} : setupConfig;
|
|
1294
|
-
imports.push(SetupModule.forRoot({
|
|
1295
|
-
...config,
|
|
1296
|
-
provisioningPort: config.provisioningPort ?? persistence?.core.superAdminProvisioning,
|
|
1297
|
-
imports: config.imports ?? options.imports
|
|
1298
|
-
}));
|
|
1299
|
-
}
|
|
1300
|
-
if (adminStatsConfig) {
|
|
1301
|
-
imports.push(AdminStatsModule.forRoot({
|
|
1302
|
-
...adminStatsConfig,
|
|
1303
|
-
guards: adminStatsConfig.guards ?? [
|
|
1304
|
-
...options.controller.guards,
|
|
1305
|
-
SuperAdminGuard
|
|
1306
|
-
],
|
|
1307
|
-
auditStatsPort: adminStatsConfig.auditStatsPort ?? persistence?.core.auditStats,
|
|
1308
|
-
imports: adminStatsConfig.imports ?? options.imports
|
|
1309
|
-
}));
|
|
1310
|
-
}
|
|
1311
|
-
if (checkoutOfferConfig) {
|
|
1312
|
-
imports.push(CheckoutOfferModule.forRoot({
|
|
1313
|
-
...checkoutOfferConfig,
|
|
1314
|
-
bundleRepository: checkoutOfferConfig.bundleRepository ?? persistence?.catalog?.bundleRepository,
|
|
1315
|
-
planRepository: checkoutOfferConfig.planRepository ?? persistence?.catalog?.planRepository,
|
|
1316
|
-
catalogEntryRepository: checkoutOfferConfig.catalogEntryRepository ?? persistence?.catalog?.catalogEntryRepository,
|
|
1317
|
-
imports: checkoutOfferConfig.imports ?? options.imports
|
|
1318
|
-
}));
|
|
1319
|
-
}
|
|
1320
|
-
if (subscriptionContractConfig) {
|
|
1321
|
-
const config = subscriptionContractConfig === true ? {} : subscriptionContractConfig;
|
|
1322
|
-
imports.push(SubscriptionContractModule.forRoot({
|
|
1323
|
-
...config,
|
|
1324
|
-
subscriptionContractRepository: config.subscriptionContractRepository ?? persistence?.entitlement?.subscriptionContractRepository,
|
|
1325
|
-
imports: config.imports ?? options.imports
|
|
1326
|
-
}));
|
|
1327
|
-
}
|
|
1328
|
-
const lightweightProviders = [];
|
|
1329
|
-
const lightweightExports = [];
|
|
1330
|
-
if (options.autoManifest !== false) {
|
|
1331
|
-
const contribution = buildStandardManifestContribution(catalogConfig, adminResourcesConfig, promoCodesConfig);
|
|
1332
|
-
lightweightProviders.push({
|
|
1333
|
-
provide: STANDARD_MANIFEST_REGISTRATION_TOKEN,
|
|
1334
|
-
useFactory: /* @__PURE__ */ __name((manifest) => {
|
|
1335
|
-
manifest.register(contribution);
|
|
1336
|
-
return contribution;
|
|
1337
|
-
}, "useFactory"),
|
|
1338
|
-
inject: [
|
|
1339
|
-
AdminManifestService
|
|
1340
|
-
]
|
|
1341
|
-
});
|
|
1342
|
-
}
|
|
1343
|
-
const hasExplicitResolver = !!adapters.planResolver;
|
|
1344
|
-
const hasSubscriptionResolver = Boolean(tenantBillingConfig && adapters.subscriptionRepository);
|
|
1345
|
-
const hasResolver = hasExplicitResolver || hasSubscriptionResolver;
|
|
1346
|
-
const hasFallback = !!options.defaultPlanId;
|
|
1347
|
-
if (hasResolver || hasFallback) {
|
|
1348
|
-
if (hasSubscriptionResolver && !hasExplicitResolver) {
|
|
1349
|
-
lightweightProviders.push(asProvider(PLATFORM_SUBSCRIPTION_REPOSITORY_TOKEN, adapters.subscriptionRepository));
|
|
1350
|
-
}
|
|
1351
|
-
lightweightProviders.push(hasExplicitResolver ? asProvider(PLAN_RESOLVER_PORT_TOKEN, adapters.planResolver) : hasSubscriptionResolver ? {
|
|
1352
|
-
provide: PLAN_RESOLVER_PORT_TOKEN,
|
|
1353
|
-
useFactory: /* @__PURE__ */ __name((subscriptions) => new SubscriptionPlanResolver(subscriptions), "useFactory"),
|
|
1354
|
-
inject: [
|
|
1355
|
-
PLATFORM_SUBSCRIPTION_REPOSITORY_TOKEN
|
|
1356
|
-
]
|
|
1357
|
-
} : {
|
|
1358
|
-
provide: PLAN_RESOLVER_PORT_TOKEN,
|
|
1359
|
-
useValue: new StaticPlanResolver(options.defaultPlanId)
|
|
1360
|
-
}, StaticEntitlementService, StaticFeatureGuard, EnforceQuotaInterceptor, ...quotaProvidersHostedByTenantBilling ? [] : options.quotaProviders ?? [], {
|
|
1361
|
-
provide: QUOTA_PROVIDERS_TOKEN,
|
|
1362
|
-
useFactory: /* @__PURE__ */ __name((...providers) => providers, "useFactory"),
|
|
1363
|
-
inject: options.quotaProviders ?? []
|
|
1364
|
-
}, ...options.globalFeatureGuard === false ? [] : [
|
|
1365
|
-
{
|
|
1366
|
-
provide: APP_GUARD,
|
|
1367
|
-
useExisting: StaticFeatureGuard
|
|
1368
|
-
}
|
|
1369
|
-
], {
|
|
1370
|
-
provide: APP_INTERCEPTOR,
|
|
1371
|
-
useExisting: EnforceQuotaInterceptor
|
|
1372
|
-
});
|
|
1373
|
-
lightweightExports.push(PLAN_RESOLVER_PORT_TOKEN, StaticEntitlementService, StaticFeatureGuard, EnforceQuotaInterceptor, QUOTA_PROVIDERS_TOKEN);
|
|
1374
|
-
if (options.globalFeatureGuard === false) {
|
|
1375
|
-
lightweightProviders.push(FeatureGuardCoverageCheck);
|
|
1376
|
-
imports.push(NestDiscoveryModule);
|
|
1377
|
-
}
|
|
1378
|
-
} else {
|
|
1379
|
-
PLATFORM_LOGGER.warn("No plan resolver configured \u2014 @RequireFeature and @EnforceQuota are INERT. The platform registered neither StaticFeatureGuard nor EnforceQuotaInterceptor, so every annotated route serves unlicensed traffic and every quota is unlimited. Set one of: adapters.planResolver, defaultPlanId, or tenantBilling.");
|
|
1380
|
-
}
|
|
1381
|
-
const tenantControllers = [];
|
|
1382
|
-
if (options.tenantManifest) {
|
|
1383
|
-
if (!hasResolver && !hasFallback) {
|
|
1384
|
-
throw new Error("SaasPlatformModule.forRoot: tenantManifest requires defaultPlanId, adapters.planResolver or tenantBilling so it can resolve features.");
|
|
1385
|
-
}
|
|
1386
|
-
lightweightProviders.push(TenantManifestService);
|
|
1387
|
-
lightweightExports.push(TenantManifestService);
|
|
1388
|
-
tenantControllers.push(buildTenantManifestController(options.tenantManifest === true ? {
|
|
1389
|
-
guards: Array.isArray(tenantBillingConfig?.authGuards) ? tenantBillingConfig.authGuards : options.controller.guards
|
|
1390
|
-
} : options.tenantManifest));
|
|
1391
|
-
}
|
|
1392
|
-
return {
|
|
1393
|
-
module: _SaasPlatformModule,
|
|
1394
|
-
imports,
|
|
1395
|
-
providers: lightweightProviders,
|
|
1396
|
-
controllers: tenantControllers,
|
|
1397
|
-
exports: [
|
|
1398
|
-
PlanCatalogModule,
|
|
1399
|
-
DiscoveryModule,
|
|
1400
|
-
AdminModule,
|
|
1401
|
-
// ADMIN_MANIFEST_CONFIG travels transitively: re-exporting an
|
|
1402
|
-
// imported module's token directly is an UnknownExportException
|
|
1403
|
-
// at boot — the module export below already carries it.
|
|
1404
|
-
AdminManifestModule,
|
|
1405
|
-
...requiresFullEntitlement ? [
|
|
1406
|
-
EntitlementModule
|
|
1407
|
-
] : [],
|
|
1408
|
-
...catalogConfig ? [
|
|
1409
|
-
CatalogModule
|
|
1410
|
-
] : [],
|
|
1411
|
-
...tenantBillingConfig ? [
|
|
1412
|
-
TenantBillingModule
|
|
1413
|
-
] : [],
|
|
1414
|
-
...subscriptionBundlesConfig ? [
|
|
1415
|
-
SubscriptionBundleModule
|
|
1416
|
-
] : [],
|
|
1417
|
-
...adminResourcesConfig ? [
|
|
1418
|
-
AdminResourcesModule
|
|
1419
|
-
] : [],
|
|
1420
|
-
...promoCodesConfig ? [
|
|
1421
|
-
PromoCodesModule
|
|
1422
|
-
] : [],
|
|
1423
|
-
...setupConfig ? [
|
|
1424
|
-
SetupModule
|
|
1425
|
-
] : [],
|
|
1426
|
-
...adminStatsConfig ? [
|
|
1427
|
-
AdminStatsModule
|
|
1428
|
-
] : [],
|
|
1429
|
-
...checkoutOfferConfig ? [
|
|
1430
|
-
CheckoutOfferModule
|
|
1431
|
-
] : [],
|
|
1432
|
-
...subscriptionContractConfig ? [
|
|
1433
|
-
SubscriptionContractModule
|
|
1434
|
-
] : [],
|
|
1435
|
-
...lightweightExports
|
|
1436
|
-
],
|
|
1437
|
-
global: true
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1440
|
-
};
|
|
1441
|
-
SaasPlatformModule = _ts_decorate10([
|
|
1442
|
-
Module2({})
|
|
1443
|
-
], SaasPlatformModule);
|
|
1444
|
-
|
|
1445
|
-
export {
|
|
1446
|
-
SETUP_PROVISIONING_PORT_TOKEN,
|
|
1447
|
-
SETUP_CONFIG_TOKEN,
|
|
1448
|
-
SetupService,
|
|
1449
|
-
SetupController,
|
|
1450
|
-
SetupModule,
|
|
1451
|
-
PLAN_RESOLVER_PORT_TOKEN,
|
|
1452
|
-
StaticPlanResolver,
|
|
1453
|
-
StaticEntitlementService,
|
|
1454
|
-
FeatureGuardCoverageCheck,
|
|
1455
|
-
STATIC_FEATURE_GUARD_CONFIG_TOKEN,
|
|
1456
|
-
StaticFeatureGuard,
|
|
1457
|
-
QUOTA_PROVIDERS_TOKEN,
|
|
1458
|
-
EnforceQuotaInterceptor,
|
|
1459
|
-
QuotaProvidersUsageSnapshot,
|
|
1460
|
-
SubscriptionPlanResolver,
|
|
1461
|
-
TenantManifestService,
|
|
1462
|
-
buildTenantManifestController,
|
|
1463
|
-
SaasPlatformModule
|
|
1464
|
-
};
|