@saasicat/nest 1.0.0-rc.8 → 1.0.0-rc.9
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/dist/.build-stamp +1 -1
- package/dist/_entries.cjs +56 -17
- package/dist/billing/index.d.cts +20 -5
- package/dist/billing/index.d.ts +20 -5
- package/dist/billing/index.js +7 -5
- package/dist/{chunk-IW5XGOEU.js → chunk-5LE5AZUP.js} +1 -1
- package/dist/{chunk-7JEXCHMU.js → chunk-6FQ3G4IF.js} +1 -1
- package/dist/{chunk-GHIECNF3.js → chunk-FVD4TGER.js} +10 -3
- package/dist/{chunk-UUFUSKX2.js → chunk-H7SF4EUR.js} +2 -0
- package/dist/{chunk-JNONSUP3.js → chunk-HFQNSOIU.js} +1 -1
- package/dist/{chunk-DQW3DHSD.js → chunk-KBRELZT4.js} +1 -1
- package/dist/{chunk-2BNZK22P.js → chunk-OI7P6ZED.js} +7 -6
- package/dist/{chunk-TJ5E42WX.js → chunk-W67WBRW5.js} +46 -18
- package/dist/{define-saasicat-DVKyc8oT.d.ts → define-saasicat-DKyoOmEC.d.ts} +1 -1
- package/dist/{define-saasicat-BrlUxP9g.d.cts → define-saasicat-j-CoHjoG.d.cts} +1 -1
- package/dist/{enforce-quota.interceptor-DEAyTI-x.d.ts → enforce-quota.interceptor-CLPZKiJC.d.ts} +2 -2
- package/dist/{enforce-quota.interceptor-DvuVXX_y.d.cts → enforce-quota.interceptor-CLS6xJ-E.d.cts} +2 -2
- package/dist/entitlement/index.js +3 -3
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +11 -9
- package/dist/{module-options-5-kVLwuv.d.cts → module-options-BDb8Tam7.d.cts} +8 -1
- package/dist/{module-options-DVmppjem.d.ts → module-options-DF3H6q3A.d.ts} +8 -1
- package/dist/platform/index.d.cts +7 -7
- package/dist/platform/index.d.ts +7 -7
- package/dist/platform/index.js +7 -7
- package/dist/promo/index.js +3 -3
- package/dist/{tenant-billing.controller-DElYt3Aa.d.cts → tenant-billing.controller-BqYJjjRi.d.cts} +105 -3
- package/dist/{tenant-billing.controller-CVDMTGx6.d.ts → tenant-billing.controller-DhNqJDoU.d.ts} +105 -3
- package/dist/{tenant-billing.module-BVXDucZj.d.cts → tenant-billing.module-D96e9tYP.d.cts} +2 -137
- package/dist/{tenant-billing.module-C7rgy1jA.d.ts → tenant-billing.module-ZBfERe3L.d.ts} +2 -137
- package/dist/testing/index.d.cts +4 -4
- package/dist/testing/index.d.ts +4 -4
- package/dist/testing/index.js +7 -7
- package/package.json +3 -3
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
aec99b9d672b86bd7310c62f4ec0587e8708c675222a1792a640af85a8cdd6b2
|
package/dist/_entries.cjs
CHANGED
|
@@ -1639,6 +1639,7 @@ __export(billing_exports, {
|
|
|
1639
1639
|
FEATURE_GUARD_MARKER: () => FEATURE_GUARD_MARKER,
|
|
1640
1640
|
FeatureGuard: () => FeatureGuard,
|
|
1641
1641
|
LimitExceededFilter: () => LimitExceededFilter,
|
|
1642
|
+
NO_NOTICE_PERIOD: () => NO_NOTICE_PERIOD,
|
|
1642
1643
|
PENDING_PLAN_QUERY_PORT_TOKEN: () => PENDING_PLAN_QUERY_PORT_TOKEN,
|
|
1643
1644
|
PLAN_CATALOG_IMPORT_SINK_TOKEN: () => PLAN_CATALOG_IMPORT_SINK_TOKEN,
|
|
1644
1645
|
PLAN_CATALOG_READ_SINK_TOKEN: () => PLAN_CATALOG_READ_SINK_TOKEN,
|
|
@@ -1954,9 +1955,12 @@ function decideCancellation(input) {
|
|
|
1954
1955
|
};
|
|
1955
1956
|
}
|
|
1956
1957
|
__name(decideCancellation, "decideCancellation");
|
|
1958
|
+
var NO_NOTICE_PERIOD = {
|
|
1959
|
+
monthly: 0,
|
|
1960
|
+
yearly: 0
|
|
1961
|
+
};
|
|
1957
1962
|
function noticeDaysFor(periods, billingCycle) {
|
|
1958
|
-
|
|
1959
|
-
return (billingCycle === "YEARLY" ? periods.yearly : periods.monthly) ?? 0;
|
|
1963
|
+
return billingCycle === "YEARLY" ? periods.yearly : periods.monthly;
|
|
1960
1964
|
}
|
|
1961
1965
|
__name(noticeDaysFor, "noticeDaysFor");
|
|
1962
1966
|
function decideCancellationFor(sub, now, noticePeriodDays) {
|
|
@@ -2144,6 +2148,7 @@ function buildPlanCatalogFromSnapshot(settings, snapshot) {
|
|
|
2144
2148
|
app: settings.app,
|
|
2145
2149
|
currency: settings.currency,
|
|
2146
2150
|
vatRate: settings.vatRate,
|
|
2151
|
+
tenantBilling: settings.tenantBilling,
|
|
2147
2152
|
...settings.marketing ? {
|
|
2148
2153
|
marketing: settings.marketing
|
|
2149
2154
|
} : {},
|
|
@@ -2183,6 +2188,7 @@ var PlanCatalogModule = class _PlanCatalogModule {
|
|
|
2183
2188
|
app: options.app,
|
|
2184
2189
|
currency: options.currency,
|
|
2185
2190
|
vatRate: options.vatRate,
|
|
2191
|
+
tenantBilling: options.tenantBilling,
|
|
2186
2192
|
marketing: options.marketing
|
|
2187
2193
|
}, snapshot);
|
|
2188
2194
|
}, "useFactory"),
|
|
@@ -3174,6 +3180,13 @@ var import_js_yaml = __toESM(require("js-yaml"), 1);
|
|
|
3174
3180
|
var import__ = __toESM(require("ajv/dist/2020.js"), 1);
|
|
3175
3181
|
var import_ajv_formats = __toESM(require("ajv-formats"), 1);
|
|
3176
3182
|
var import_spec = require("@saasicat/spec");
|
|
3183
|
+
function locate(error) {
|
|
3184
|
+
const segments = (error.instancePath ?? "").split("/").filter(Boolean);
|
|
3185
|
+
const missing = error.params?.missingProperty;
|
|
3186
|
+
if (missing) segments.push(missing);
|
|
3187
|
+
return segments.length > 0 ? segments.join(".") : "(document root)";
|
|
3188
|
+
}
|
|
3189
|
+
__name(locate, "locate");
|
|
3177
3190
|
var PLAN_CATALOG_UNREADABLE_ERROR = "PlanCatalogUnreadableError";
|
|
3178
3191
|
var PlanCatalogValidationError = class extends Error {
|
|
3179
3192
|
static {
|
|
@@ -3182,7 +3195,7 @@ var PlanCatalogValidationError = class extends Error {
|
|
|
3182
3195
|
source;
|
|
3183
3196
|
errors;
|
|
3184
3197
|
constructor(source, errors) {
|
|
3185
|
-
const messages = errors.map((e) => `${e
|
|
3198
|
+
const messages = errors.map((e) => `${locate(e)}: ${e.message ?? "unknown"}`).join("\n ");
|
|
3186
3199
|
super(`Plan catalog validation failed for ${source}:
|
|
3187
3200
|
${messages}`), this.source = source, this.errors = errors;
|
|
3188
3201
|
this.name = "PlanCatalogValidationError";
|
|
@@ -6128,7 +6141,7 @@ var TenantBillingController = class _TenantBillingController {
|
|
|
6128
6141
|
contractFreeze;
|
|
6129
6142
|
trialProjection;
|
|
6130
6143
|
cancellationNoticeDays;
|
|
6131
|
-
constructor(entitlements, planPreview, subscriptionUsage, usageSnapshot, subscriptionWrite, tenantIdResolver = null, userIdResolver = null, blockedPlans = null, promoCodes = null, auditService = null, userEmailResolver = null, auditContextResolver = null, subscriptionBundles = null, contractFreeze = null, trialProjection = null, cancellationNoticeDays =
|
|
6144
|
+
constructor(entitlements, planPreview, subscriptionUsage, usageSnapshot, subscriptionWrite, tenantIdResolver = null, userIdResolver = null, blockedPlans = null, promoCodes = null, auditService = null, userEmailResolver = null, auditContextResolver = null, subscriptionBundles = null, contractFreeze = null, trialProjection = null, cancellationNoticeDays = NO_NOTICE_PERIOD) {
|
|
6132
6145
|
this.entitlements = entitlements;
|
|
6133
6146
|
this.planPreview = planPreview;
|
|
6134
6147
|
this.subscriptionUsage = subscriptionUsage;
|
|
@@ -6951,6 +6964,7 @@ TenantBillingController = _ts_decorate35([
|
|
|
6951
6964
|
|
|
6952
6965
|
// src/billing/tenant-billing.module.ts
|
|
6953
6966
|
var import_common35 = require("@nestjs/common");
|
|
6967
|
+
var import_spec2 = require("@saasicat/spec");
|
|
6954
6968
|
function _ts_decorate36(decorators, target, key, desc) {
|
|
6955
6969
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
6956
6970
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -6958,6 +6972,27 @@ function _ts_decorate36(decorators, target, key, desc) {
|
|
|
6958
6972
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6959
6973
|
}
|
|
6960
6974
|
__name(_ts_decorate36, "_ts_decorate");
|
|
6975
|
+
function settingFromCatalog(catalog, key) {
|
|
6976
|
+
const settings = catalog.tenantBilling;
|
|
6977
|
+
const value = settings?.[key];
|
|
6978
|
+
if (value === void 0) {
|
|
6979
|
+
throw new Error(`The plan catalogue carries no tenantBilling.${key}. It is a required section of config/saas.yaml and the loader refuses a file without it, so a catalogue that reaches here without one was built in code: check the \`dbCatalog\` block, which forwards \`tenantBilling\` from that same file, or the object passed to \`planCatalog\`.`);
|
|
6980
|
+
}
|
|
6981
|
+
return value;
|
|
6982
|
+
}
|
|
6983
|
+
__name(settingFromCatalog, "settingFromCatalog");
|
|
6984
|
+
var MOVED_TO_THE_FILE = Object.keys(import_spec2.planCatalogSchema.properties?.tenantBilling?.properties ?? // Refuses to guess rather than falling back to an empty list: an empty
|
|
6985
|
+
// one would turn this guard off without saying so.
|
|
6986
|
+
(() => {
|
|
6987
|
+
throw new Error("plan-catalog.schema.json declares no tenantBilling properties \u2014 @saasicat/spec and @saasicat/nest are out of step.");
|
|
6988
|
+
})());
|
|
6989
|
+
function assertNoMovedOptions(options) {
|
|
6990
|
+
const given = options;
|
|
6991
|
+
const passed = MOVED_TO_THE_FILE.filter((key) => given[key] !== void 0);
|
|
6992
|
+
if (passed.length === 0) return;
|
|
6993
|
+
throw new Error(`TenantBillingModule.forRoot() no longer accepts ${passed.join(" and ")} \u2014 this moved to config/saas.yaml under \`tenantBilling:\`. Move the value there (both members of each setting are required) and delete it here. The file is the one place these live, so a fallback here would be the second home that change exists to close. See docs/guides/upgrade-to-1.0.md.`);
|
|
6994
|
+
}
|
|
6995
|
+
__name(assertNoMovedOptions, "assertNoMovedOptions");
|
|
6961
6996
|
var TenantBillingModule = class _TenantBillingModule {
|
|
6962
6997
|
static {
|
|
6963
6998
|
__name(this, "TenantBillingModule");
|
|
@@ -6972,18 +7007,20 @@ var TenantBillingModule = class _TenantBillingModule {
|
|
|
6972
7007
|
TenantAdminGuard,
|
|
6973
7008
|
PlanChangePreviewService
|
|
6974
7009
|
];
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
7010
|
+
assertNoMovedOptions(options);
|
|
7011
|
+
providers.push({
|
|
7012
|
+
provide: CANCELLATION_NOTICE_DAYS_TOKEN,
|
|
7013
|
+
useFactory: /* @__PURE__ */ __name((catalog) => settingFromCatalog(catalog, "cancellationNoticeDays"), "useFactory"),
|
|
7014
|
+
inject: [
|
|
7015
|
+
PLAN_CATALOG_TOKEN
|
|
7016
|
+
]
|
|
7017
|
+
}, {
|
|
7018
|
+
provide: SELF_SERVICE_BLOCKED_PLANS_TOKEN,
|
|
7019
|
+
useFactory: /* @__PURE__ */ __name((catalog) => settingFromCatalog(catalog, "selfServiceBlockedPlans"), "useFactory"),
|
|
7020
|
+
inject: [
|
|
7021
|
+
PLAN_CATALOG_TOKEN
|
|
7022
|
+
]
|
|
7023
|
+
});
|
|
6987
7024
|
if (options.subscriptionBundleRepository) {
|
|
6988
7025
|
providers.push(asProvider(SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN, options.subscriptionBundleRepository));
|
|
6989
7026
|
}
|
|
@@ -14569,7 +14606,7 @@ var RULE_SPECS = [
|
|
|
14569
14606
|
id: "catalog.identity-or-sink",
|
|
14570
14607
|
when: /* @__PURE__ */ __name((c) => !c.options.planCatalog, "when"),
|
|
14571
14608
|
assert: /* @__PURE__ */ __name((c) => Boolean(c.adapters.planCatalogReadSink && c.options.dbCatalog), "assert"),
|
|
14572
|
-
message: "no plan catalogue is reachable. Either set `planCatalog` (the quickstart YAML path) or, for DB hydration, BOTH a `planCatalogReadSink` (via `adapters` or `persistence`) AND `dbCatalog` ({ app, currency, vatRate }). Without the identity the app boots with a silently empty catalogue."
|
|
14609
|
+
message: "no plan catalogue is reachable. Either set `planCatalog` (the quickstart YAML path) or, for DB hydration, BOTH a `planCatalogReadSink` (via `adapters` or `persistence`) AND `dbCatalog` ({ app, currency, vatRate, tenantBilling }). Without the identity the app boots with a silently empty catalogue."
|
|
14573
14610
|
},
|
|
14574
14611
|
{
|
|
14575
14612
|
id: "catalog.app-is-named",
|
|
@@ -16220,6 +16257,7 @@ function composePlanCatalog(options, sink) {
|
|
|
16220
16257
|
app: dbCatalog.app,
|
|
16221
16258
|
currency: dbCatalog.currency,
|
|
16222
16259
|
vatRate: dbCatalog.vatRate,
|
|
16260
|
+
tenantBilling: dbCatalog.tenantBilling,
|
|
16223
16261
|
marketing: dbCatalog.marketing,
|
|
16224
16262
|
sink,
|
|
16225
16263
|
imports: options.imports
|
|
@@ -18659,6 +18697,7 @@ __export(src_exports, {
|
|
|
18659
18697
|
MarketingSettingsService: () => MarketingSettingsService,
|
|
18660
18698
|
MfaGuard: () => MfaGuard,
|
|
18661
18699
|
MfaService: () => MfaService,
|
|
18700
|
+
NO_NOTICE_PERIOD: () => NO_NOTICE_PERIOD,
|
|
18662
18701
|
PASSWORD_HASHER_TOKEN: () => PASSWORD_HASHER_TOKEN,
|
|
18663
18702
|
PAYMENT_EVENT_LOG_TOKEN: () => PAYMENT_EVENT_LOG_TOKEN,
|
|
18664
18703
|
PAYMENT_PROVIDER_TOKEN: () => PAYMENT_PROVIDER_TOKEN,
|
package/dist/billing/index.d.cts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { BillingCycle, BundleVersionRow, FeatureKey, UpsellOfferResolver, BundleRepository, CatalogEntryRepository, UpsellOffer, PlanCatalog, PlanCatalogReadSink, PlanCatalogReadSnapshot, PlanCatalogImportSink, PlanCatalogImportReport, PlanId, PlanDef, QuotaKey, MarketingTopFeature, FeatureUiRegistry, MarketingProjectionRepository, ConfiguratorSourcesLookup, ConfiguratorMarketingProvider, ConfiguratorCatalog } from '@saasicat/core';
|
|
2
|
-
export { BundleVersionFields, ChangeDirection, DiffResult, PlanVersionFields, VersionChange, VersionChangeDirection, classifyBundleVersionDiff, classifyPlanDiff } from '@saasicat/core';
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
export { BundleVersionFields, CancellationNoticePeriods, ChangeDirection, DiffResult, PlanVersionFields, SelfServiceBlockedPlans, VersionChange, VersionChangeDirection, classifyBundleVersionDiff, classifyPlanDiff } from '@saasicat/core';
|
|
3
|
+
export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as CancellableSubscription, c as CancellationDecision, d as CancellationInput, e as ChangePlanDto, f as CompleteOnboardingSubscriptionDto, g as ComposedTenantAuthGuard, h as CycleDirection, L as LimitsCheckRow, N as NO_NOTICE_PERIOD, P as PendingPlanMaterializationService, i as PlanChangeContext, j as PlanChangePreviewDto, k as PlanChangePreviewIssue, l as PlanChangePreviewService, m as PlanChangeType, n as PlanDirection, o as PlanSnapshotDto, p as PreviewPlanChangeDto, q as ProrationDto, r as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, s as SubscriptionBundleCancelPreviewDto, t as SubscriptionBundleConfig, u as SubscriptionBundlePreviewContext, v as SubscriptionBundlePreviewIssue, w as SubscriptionBundlePreviewService, x as SubscriptionBundlesService, T as TenantAdminGuard, y as TenantBillingController, U as UsageResponse, z as addMonths, D as clampToParent, E as computeProration, F as decideCancellation, G as decideCancellationFor, H as noticeDaysFor, I as resolveBundleCancelEffectiveAt } from '../tenant-billing.controller-BqYJjjRi.cjs';
|
|
4
|
+
import { F as FEATURE_GUARD_MARKER, f as ContractFreezePort, g as ContractFreezeSourcePort } from '../tenant-billing.module-D96e9tYP.cjs';
|
|
5
|
+
export { A as AUDIT_CONTEXT_RESOLVER_TOKEN, a as AuditContextResolver, b as AuthGuardList, C as CANCELLATION_NOTICE_DAYS_TOKEN, c as CONTRACT_FREEZE_PORT_TOKEN, d as CONTRACT_FREEZE_SOURCE_PORT_TOKEN, e as ContractFreezeBundleSnapshot, D as DuePendingPlanChange, M as MarkedFeatureGuard, P as PENDING_PLAN_QUERY_PORT_TOKEN, h as PendingPlanQueryPort, S as SELF_SERVICE_BLOCKED_BUNDLES_TOKEN, i as SELF_SERVICE_BLOCKED_PLANS_TOKEN, j as SUBSCRIPTION_USAGE_PORT_TOKEN, k as SUBSCRIPTION_WRITE_PORT_TOKEN, l as SelfServiceBlockedBundles, m as SubscriptionBundleControllerOptions, n as SubscriptionBundleModule, o as SubscriptionBundleModuleOptions, T as TENANT_AUTH_GUARDS_TOKEN, p as TENANT_ID_RESOLVER_TOKEN, q as TRIAL_PROJECTION_PORT_TOKEN, r as TenantBillingModule, s as TenantBillingModuleOptions, t as TenantIdResolver, u as TrialProjectionInput, v as TrialProjectionPort, U as USAGE_SNAPSHOT_PORT_TOKEN, w as USER_EMAIL_RESOLVER_TOKEN, x as USER_ID_RESOLVER_TOKEN, y as UserEmailResolver, z as UserIdResolver, B as isPlatformFeatureGuard } from '../tenant-billing.module-D96e9tYP.cjs';
|
|
5
6
|
import * as _nestjs_common from '@nestjs/common';
|
|
6
7
|
import { CanActivate, ExecutionContext, ArgumentsHost, Type, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
|
|
7
8
|
export { Type as NestType } from '@nestjs/common';
|
|
8
9
|
import { Reflector, BaseExceptionFilter } from '@nestjs/core';
|
|
9
10
|
import { c as EntitlementService } from '../aggregation-Bsg1g9Q0.cjs';
|
|
10
11
|
import { P as ProviderSpec } from '../di-CcNeq9v-.cjs';
|
|
11
|
-
export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, e as CycleDirection, L as LimitsCheckRow, P as PendingPlanMaterializationService, f as PlanChangeContext, g as PlanChangePreviewDto, h as PlanChangePreviewIssue, i as PlanChangePreviewService, j as PlanChangeType, k as PlanDirection, l as PlanSnapshotDto, m as PreviewPlanChangeDto, n as ProrationDto, o as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, p as SubscriptionBundleCancelPreviewDto, q as SubscriptionBundleConfig, r as SubscriptionBundlePreviewContext, s as SubscriptionBundlePreviewIssue, t as SubscriptionBundlePreviewService, u as SubscriptionBundlesService, T as TenantAdminGuard, v as TenantBillingController, U as UsageResponse, w as addMonths, x as clampToParent, y as computeProration, z as resolveBundleCancelEffectiveAt } from '../tenant-billing.controller-DElYt3Aa.cjs';
|
|
12
12
|
import { S as SubscriptionContractService } from '../subscription-contract.service-hD87MKyg.cjs';
|
|
13
|
-
import '../plan-resolution-CwUy_OqC.cjs';
|
|
14
13
|
import '../promo.service-BJbKAmw3.cjs';
|
|
15
14
|
import '../admin-audit.service-4P3Djdxk.cjs';
|
|
15
|
+
import '../plan-resolution-CwUy_OqC.cjs';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* One period onwards, on `anchorDay` where the month has one.
|
|
@@ -550,6 +550,9 @@ interface AjvErrorLike {
|
|
|
550
550
|
instancePath?: string;
|
|
551
551
|
message?: string;
|
|
552
552
|
schemaPath?: string;
|
|
553
|
+
params?: {
|
|
554
|
+
missingProperty?: string;
|
|
555
|
+
};
|
|
553
556
|
}
|
|
554
557
|
/**
|
|
555
558
|
* `Error.name` for a document that could not be read as a catalog at all.
|
|
@@ -603,6 +606,12 @@ interface PlanCatalogModuleOptions {
|
|
|
603
606
|
app: PlanCatalog['app'];
|
|
604
607
|
currency: string;
|
|
605
608
|
vatRate: number;
|
|
609
|
+
/**
|
|
610
|
+
* Commercial self-service settings from `config/saas.yaml#tenantBilling`.
|
|
611
|
+
* The read sink loads plans and features; settings are never in the
|
|
612
|
+
* database, so they can only come from the file.
|
|
613
|
+
*/
|
|
614
|
+
tenantBilling: PlanCatalog['tenantBilling'];
|
|
606
615
|
/**
|
|
607
616
|
* App-wide marketing configuration — including the
|
|
608
617
|
* `availableLocales` pool. Flows into `PLAN_CATALOG_TOKEN.marketing`
|
|
@@ -633,6 +642,12 @@ interface PlanCatalogBuildSettings {
|
|
|
633
642
|
app: PlanCatalog['app'];
|
|
634
643
|
currency: string;
|
|
635
644
|
vatRate: number;
|
|
645
|
+
/**
|
|
646
|
+
* Commercial self-service settings from `config/saas.yaml#tenantBilling`.
|
|
647
|
+
* Required, like the two above: the database carries plans and features,
|
|
648
|
+
* never the settings, so this can only come from the file.
|
|
649
|
+
*/
|
|
650
|
+
tenantBilling: PlanCatalog['tenantBilling'];
|
|
636
651
|
/** App-wide marketing configuration. Optional. */
|
|
637
652
|
marketing?: PlanCatalog['marketing'];
|
|
638
653
|
}
|
package/dist/billing/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { BillingCycle, BundleVersionRow, FeatureKey, UpsellOfferResolver, BundleRepository, CatalogEntryRepository, UpsellOffer, PlanCatalog, PlanCatalogReadSink, PlanCatalogReadSnapshot, PlanCatalogImportSink, PlanCatalogImportReport, PlanId, PlanDef, QuotaKey, MarketingTopFeature, FeatureUiRegistry, MarketingProjectionRepository, ConfiguratorSourcesLookup, ConfiguratorMarketingProvider, ConfiguratorCatalog } from '@saasicat/core';
|
|
2
|
-
export { BundleVersionFields, ChangeDirection, DiffResult, PlanVersionFields, VersionChange, VersionChangeDirection, classifyBundleVersionDiff, classifyPlanDiff } from '@saasicat/core';
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
export { BundleVersionFields, CancellationNoticePeriods, ChangeDirection, DiffResult, PlanVersionFields, SelfServiceBlockedPlans, VersionChange, VersionChangeDirection, classifyBundleVersionDiff, classifyPlanDiff } from '@saasicat/core';
|
|
3
|
+
export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as CancellableSubscription, c as CancellationDecision, d as CancellationInput, e as ChangePlanDto, f as CompleteOnboardingSubscriptionDto, g as ComposedTenantAuthGuard, h as CycleDirection, L as LimitsCheckRow, N as NO_NOTICE_PERIOD, P as PendingPlanMaterializationService, i as PlanChangeContext, j as PlanChangePreviewDto, k as PlanChangePreviewIssue, l as PlanChangePreviewService, m as PlanChangeType, n as PlanDirection, o as PlanSnapshotDto, p as PreviewPlanChangeDto, q as ProrationDto, r as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, s as SubscriptionBundleCancelPreviewDto, t as SubscriptionBundleConfig, u as SubscriptionBundlePreviewContext, v as SubscriptionBundlePreviewIssue, w as SubscriptionBundlePreviewService, x as SubscriptionBundlesService, T as TenantAdminGuard, y as TenantBillingController, U as UsageResponse, z as addMonths, D as clampToParent, E as computeProration, F as decideCancellation, G as decideCancellationFor, H as noticeDaysFor, I as resolveBundleCancelEffectiveAt } from '../tenant-billing.controller-DhNqJDoU.js';
|
|
4
|
+
import { F as FEATURE_GUARD_MARKER, f as ContractFreezePort, g as ContractFreezeSourcePort } from '../tenant-billing.module-ZBfERe3L.js';
|
|
5
|
+
export { A as AUDIT_CONTEXT_RESOLVER_TOKEN, a as AuditContextResolver, b as AuthGuardList, C as CANCELLATION_NOTICE_DAYS_TOKEN, c as CONTRACT_FREEZE_PORT_TOKEN, d as CONTRACT_FREEZE_SOURCE_PORT_TOKEN, e as ContractFreezeBundleSnapshot, D as DuePendingPlanChange, M as MarkedFeatureGuard, P as PENDING_PLAN_QUERY_PORT_TOKEN, h as PendingPlanQueryPort, S as SELF_SERVICE_BLOCKED_BUNDLES_TOKEN, i as SELF_SERVICE_BLOCKED_PLANS_TOKEN, j as SUBSCRIPTION_USAGE_PORT_TOKEN, k as SUBSCRIPTION_WRITE_PORT_TOKEN, l as SelfServiceBlockedBundles, m as SubscriptionBundleControllerOptions, n as SubscriptionBundleModule, o as SubscriptionBundleModuleOptions, T as TENANT_AUTH_GUARDS_TOKEN, p as TENANT_ID_RESOLVER_TOKEN, q as TRIAL_PROJECTION_PORT_TOKEN, r as TenantBillingModule, s as TenantBillingModuleOptions, t as TenantIdResolver, u as TrialProjectionInput, v as TrialProjectionPort, U as USAGE_SNAPSHOT_PORT_TOKEN, w as USER_EMAIL_RESOLVER_TOKEN, x as USER_ID_RESOLVER_TOKEN, y as UserEmailResolver, z as UserIdResolver, B as isPlatformFeatureGuard } from '../tenant-billing.module-ZBfERe3L.js';
|
|
5
6
|
import * as _nestjs_common from '@nestjs/common';
|
|
6
7
|
import { CanActivate, ExecutionContext, ArgumentsHost, Type, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
|
|
7
8
|
export { Type as NestType } from '@nestjs/common';
|
|
8
9
|
import { Reflector, BaseExceptionFilter } from '@nestjs/core';
|
|
9
10
|
import { c as EntitlementService } from '../aggregation-53yv4-rr.js';
|
|
10
11
|
import { P as ProviderSpec } from '../di-CcNeq9v-.js';
|
|
11
|
-
export { A as AddBundleToSubscriptionInput, B as BundlePreviewSnapshot, C as CancelBundleFromSubscriptionInput, a as CancelSubscriptionDto, b as ChangePlanDto, c as CompleteOnboardingSubscriptionDto, d as ComposedTenantAuthGuard, e as CycleDirection, L as LimitsCheckRow, P as PendingPlanMaterializationService, f as PlanChangeContext, g as PlanChangePreviewDto, h as PlanChangePreviewIssue, i as PlanChangePreviewService, j as PlanChangeType, k as PlanDirection, l as PlanSnapshotDto, m as PreviewPlanChangeDto, n as ProrationDto, o as ProrationInput, R as RedundantFeatureHint, S as SubscriptionBundleAddPreviewDto, p as SubscriptionBundleCancelPreviewDto, q as SubscriptionBundleConfig, r as SubscriptionBundlePreviewContext, s as SubscriptionBundlePreviewIssue, t as SubscriptionBundlePreviewService, u as SubscriptionBundlesService, T as TenantAdminGuard, v as TenantBillingController, U as UsageResponse, w as addMonths, x as clampToParent, y as computeProration, z as resolveBundleCancelEffectiveAt } from '../tenant-billing.controller-CVDMTGx6.js';
|
|
12
12
|
import { S as SubscriptionContractService } from '../subscription-contract.service-hD87MKyg.js';
|
|
13
|
-
import '../plan-resolution-CwUy_OqC.js';
|
|
14
13
|
import '../promo.service-BJbKAmw3.js';
|
|
15
14
|
import '../admin-audit.service-4P3Djdxk.js';
|
|
15
|
+
import '../plan-resolution-CwUy_OqC.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* One period onwards, on `anchorDay` where the month has one.
|
|
@@ -550,6 +550,9 @@ interface AjvErrorLike {
|
|
|
550
550
|
instancePath?: string;
|
|
551
551
|
message?: string;
|
|
552
552
|
schemaPath?: string;
|
|
553
|
+
params?: {
|
|
554
|
+
missingProperty?: string;
|
|
555
|
+
};
|
|
553
556
|
}
|
|
554
557
|
/**
|
|
555
558
|
* `Error.name` for a document that could not be read as a catalog at all.
|
|
@@ -603,6 +606,12 @@ interface PlanCatalogModuleOptions {
|
|
|
603
606
|
app: PlanCatalog['app'];
|
|
604
607
|
currency: string;
|
|
605
608
|
vatRate: number;
|
|
609
|
+
/**
|
|
610
|
+
* Commercial self-service settings from `config/saas.yaml#tenantBilling`.
|
|
611
|
+
* The read sink loads plans and features; settings are never in the
|
|
612
|
+
* database, so they can only come from the file.
|
|
613
|
+
*/
|
|
614
|
+
tenantBilling: PlanCatalog['tenantBilling'];
|
|
606
615
|
/**
|
|
607
616
|
* App-wide marketing configuration — including the
|
|
608
617
|
* `availableLocales` pool. Flows into `PLAN_CATALOG_TOKEN.marketing`
|
|
@@ -633,6 +642,12 @@ interface PlanCatalogBuildSettings {
|
|
|
633
642
|
app: PlanCatalog['app'];
|
|
634
643
|
currency: string;
|
|
635
644
|
vatRate: number;
|
|
645
|
+
/**
|
|
646
|
+
* Commercial self-service settings from `config/saas.yaml#tenantBilling`.
|
|
647
|
+
* Required, like the two above: the database carries plans and features,
|
|
648
|
+
* never the settings, so this can only come from the file.
|
|
649
|
+
*/
|
|
650
|
+
tenantBilling: PlanCatalog['tenantBilling'];
|
|
636
651
|
/** App-wide marketing configuration. Optional. */
|
|
637
652
|
marketing?: PlanCatalog['marketing'];
|
|
638
653
|
}
|
package/dist/billing/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
decideRenewal,
|
|
25
25
|
loadPlanCatalogFromFile,
|
|
26
26
|
loadPlanCatalogFromString
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-FVD4TGER.js";
|
|
28
28
|
import {
|
|
29
29
|
AddSubscriptionBundleDto,
|
|
30
30
|
BILLING_FEATURE_UI_REGISTRY_TOKEN,
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
ComposedTenantAuthGuard,
|
|
39
39
|
DEFAULT_BUNDLE_MINIMUM_TERM_MONTHS,
|
|
40
40
|
FEATURE_GUARD_MARKER,
|
|
41
|
+
NO_NOTICE_PERIOD,
|
|
41
42
|
PUBLIC_CATALOG_BUNDLE_REPOSITORY_TOKEN,
|
|
42
43
|
PUBLIC_CATALOG_MARKETING_REPOSITORY_TOKEN,
|
|
43
44
|
PendingPlanMaterializationService,
|
|
@@ -78,8 +79,8 @@ import {
|
|
|
78
79
|
resolveBundleCancelEffectiveAt,
|
|
79
80
|
resolvePlanAnchorDay,
|
|
80
81
|
retreatOneCycle
|
|
81
|
-
} from "../chunk-
|
|
82
|
-
import "../chunk-
|
|
82
|
+
} from "../chunk-W67WBRW5.js";
|
|
83
|
+
import "../chunk-6FQ3G4IF.js";
|
|
83
84
|
import "../chunk-F7P2X2DR.js";
|
|
84
85
|
import {
|
|
85
86
|
AUDIT_CONTEXT_RESOLVER_TOKEN,
|
|
@@ -104,7 +105,7 @@ import "../chunk-YSC46BGM.js";
|
|
|
104
105
|
import {
|
|
105
106
|
SUBSCRIPTION_BUNDLE_CONFIG_TOKEN,
|
|
106
107
|
SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN
|
|
107
|
-
} from "../chunk-
|
|
108
|
+
} from "../chunk-5LE5AZUP.js";
|
|
108
109
|
import {
|
|
109
110
|
PLAN_CATALOG_READ_SINK_TOKEN,
|
|
110
111
|
PLAN_CATALOG_TOKEN,
|
|
@@ -119,7 +120,7 @@ import {
|
|
|
119
120
|
getPlanQuota,
|
|
120
121
|
isFeatureInPlan,
|
|
121
122
|
isFeaturePlannedOnly
|
|
122
|
-
} from "../chunk-
|
|
123
|
+
} from "../chunk-H7SF4EUR.js";
|
|
123
124
|
import "../chunk-VBRYPU7V.js";
|
|
124
125
|
import "../chunk-57V6ZTI6.js";
|
|
125
126
|
import "../chunk-OUDSQ3PU.js";
|
|
@@ -147,6 +148,7 @@ export {
|
|
|
147
148
|
FEATURE_GUARD_MARKER,
|
|
148
149
|
FeatureGuard,
|
|
149
150
|
LimitExceededFilter,
|
|
151
|
+
NO_NOTICE_PERIOD,
|
|
150
152
|
PENDING_PLAN_QUERY_PORT_TOKEN,
|
|
151
153
|
PLAN_CATALOG_IMPORT_SINK_TOKEN,
|
|
152
154
|
PLAN_CATALOG_READ_SINK_TOKEN,
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
PUBLIC_CATALOG_CATALOG_ENTRY_REPOSITORY_TOKEN,
|
|
5
5
|
REQUIRE_FEATURE_KEY,
|
|
6
6
|
periodEndAfter
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-W67WBRW5.js";
|
|
8
8
|
import {
|
|
9
9
|
EntitlementService,
|
|
10
10
|
isLimitExceededError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5LE5AZUP.js";
|
|
12
12
|
import {
|
|
13
13
|
ENTITLEMENT_SERVICE_TOKEN
|
|
14
14
|
} from "./chunk-OUDSQ3PU.js";
|
|
@@ -401,6 +401,13 @@ import yaml from "js-yaml";
|
|
|
401
401
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
402
402
|
import addFormats from "ajv-formats";
|
|
403
403
|
import { planCatalogSchema } from "@saasicat/spec";
|
|
404
|
+
function locate(error) {
|
|
405
|
+
const segments = (error.instancePath ?? "").split("/").filter(Boolean);
|
|
406
|
+
const missing = error.params?.missingProperty;
|
|
407
|
+
if (missing) segments.push(missing);
|
|
408
|
+
return segments.length > 0 ? segments.join(".") : "(document root)";
|
|
409
|
+
}
|
|
410
|
+
__name(locate, "locate");
|
|
404
411
|
var PLAN_CATALOG_UNREADABLE_ERROR = "PlanCatalogUnreadableError";
|
|
405
412
|
var PlanCatalogValidationError = class extends Error {
|
|
406
413
|
static {
|
|
@@ -409,7 +416,7 @@ var PlanCatalogValidationError = class extends Error {
|
|
|
409
416
|
source;
|
|
410
417
|
errors;
|
|
411
418
|
constructor(source, errors) {
|
|
412
|
-
const messages = errors.map((e) => `${e
|
|
419
|
+
const messages = errors.map((e) => `${locate(e)}: ${e.message ?? "unknown"}`).join("\n ");
|
|
413
420
|
super(`Plan catalog validation failed for ${source}:
|
|
414
421
|
${messages}`), this.source = source, this.errors = errors;
|
|
415
422
|
this.name = "PlanCatalogValidationError";
|
|
@@ -62,6 +62,7 @@ function buildPlanCatalogFromSnapshot(settings, snapshot) {
|
|
|
62
62
|
app: settings.app,
|
|
63
63
|
currency: settings.currency,
|
|
64
64
|
vatRate: settings.vatRate,
|
|
65
|
+
tenantBilling: settings.tenantBilling,
|
|
65
66
|
...settings.marketing ? {
|
|
66
67
|
marketing: settings.marketing
|
|
67
68
|
} : {},
|
|
@@ -102,6 +103,7 @@ var PlanCatalogModule = class _PlanCatalogModule {
|
|
|
102
103
|
app: options.app,
|
|
103
104
|
currency: options.currency,
|
|
104
105
|
vatRate: options.vatRate,
|
|
106
|
+
tenantBilling: options.tenantBilling,
|
|
105
107
|
marketing: options.marketing
|
|
106
108
|
}, snapshot);
|
|
107
109
|
}, "useFactory"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PromoCodesModule
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HFQNSOIU.js";
|
|
4
4
|
import {
|
|
5
5
|
SubscriptionContractModule
|
|
6
6
|
} from "./chunk-L4VVZ4O5.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
SubscriptionBundleModule,
|
|
21
21
|
TenantBillingModule,
|
|
22
22
|
isPlatformFeatureGuard
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-W67WBRW5.js";
|
|
24
24
|
import {
|
|
25
25
|
CatalogModule
|
|
26
26
|
} from "./chunk-DFQETRBL.js";
|
|
@@ -35,15 +35,15 @@ import {
|
|
|
35
35
|
} from "./chunk-XBYAFEOR.js";
|
|
36
36
|
import {
|
|
37
37
|
EntitlementModule
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-KBRELZT4.js";
|
|
39
39
|
import {
|
|
40
40
|
LimitExceededError,
|
|
41
41
|
cancellationHasLanded
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-5LE5AZUP.js";
|
|
43
43
|
import {
|
|
44
44
|
PLAN_CATALOG_TOKEN,
|
|
45
45
|
PlanCatalogModule
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-H7SF4EUR.js";
|
|
47
47
|
import {
|
|
48
48
|
codedError
|
|
49
49
|
} from "./chunk-57V6ZTI6.js";
|
|
@@ -541,7 +541,7 @@ var RULE_SPECS = [
|
|
|
541
541
|
id: "catalog.identity-or-sink",
|
|
542
542
|
when: /* @__PURE__ */ __name((c) => !c.options.planCatalog, "when"),
|
|
543
543
|
assert: /* @__PURE__ */ __name((c) => Boolean(c.adapters.planCatalogReadSink && c.options.dbCatalog), "assert"),
|
|
544
|
-
message: "no plan catalogue is reachable. Either set `planCatalog` (the quickstart YAML path) or, for DB hydration, BOTH a `planCatalogReadSink` (via `adapters` or `persistence`) AND `dbCatalog` ({ app, currency, vatRate }). Without the identity the app boots with a silently empty catalogue."
|
|
544
|
+
message: "no plan catalogue is reachable. Either set `planCatalog` (the quickstart YAML path) or, for DB hydration, BOTH a `planCatalogReadSink` (via `adapters` or `persistence`) AND `dbCatalog` ({ app, currency, vatRate, tenantBilling }). Without the identity the app boots with a silently empty catalogue."
|
|
545
545
|
},
|
|
546
546
|
{
|
|
547
547
|
id: "catalog.app-is-named",
|
|
@@ -1615,6 +1615,7 @@ function composePlanCatalog(options, sink) {
|
|
|
1615
1615
|
app: dbCatalog.app,
|
|
1616
1616
|
currency: dbCatalog.currency,
|
|
1617
1617
|
vatRate: dbCatalog.vatRate,
|
|
1618
|
+
tenantBilling: dbCatalog.tenantBilling,
|
|
1618
1619
|
marketing: dbCatalog.marketing,
|
|
1619
1620
|
sink,
|
|
1620
1621
|
imports: options.imports
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PromoCodesService
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6FQ3G4IF.js";
|
|
4
4
|
import {
|
|
5
5
|
SubscriptionContractService
|
|
6
6
|
} from "./chunk-F7P2X2DR.js";
|
|
@@ -30,13 +30,13 @@ import {
|
|
|
30
30
|
SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN,
|
|
31
31
|
cancellationHasLanded,
|
|
32
32
|
toEffectiveLimitsSnapshot
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-5LE5AZUP.js";
|
|
34
34
|
import {
|
|
35
35
|
PLAN_CATALOG_TOKEN,
|
|
36
36
|
findPlan,
|
|
37
37
|
getMarketedPlans,
|
|
38
38
|
getPlanPriceNet
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-H7SF4EUR.js";
|
|
40
40
|
import {
|
|
41
41
|
SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN
|
|
42
42
|
} from "./chunk-VBRYPU7V.js";
|
|
@@ -265,9 +265,12 @@ function decideCancellation(input) {
|
|
|
265
265
|
};
|
|
266
266
|
}
|
|
267
267
|
__name(decideCancellation, "decideCancellation");
|
|
268
|
+
var NO_NOTICE_PERIOD = {
|
|
269
|
+
monthly: 0,
|
|
270
|
+
yearly: 0
|
|
271
|
+
};
|
|
268
272
|
function noticeDaysFor(periods, billingCycle) {
|
|
269
|
-
|
|
270
|
-
return (billingCycle === "YEARLY" ? periods.yearly : periods.monthly) ?? 0;
|
|
273
|
+
return billingCycle === "YEARLY" ? periods.yearly : periods.monthly;
|
|
271
274
|
}
|
|
272
275
|
__name(noticeDaysFor, "noticeDaysFor");
|
|
273
276
|
function decideCancellationFor(sub, now, noticePeriodDays) {
|
|
@@ -1889,7 +1892,7 @@ var TenantBillingController = class _TenantBillingController {
|
|
|
1889
1892
|
contractFreeze;
|
|
1890
1893
|
trialProjection;
|
|
1891
1894
|
cancellationNoticeDays;
|
|
1892
|
-
constructor(entitlements, planPreview, subscriptionUsage, usageSnapshot, subscriptionWrite, tenantIdResolver = null, userIdResolver = null, blockedPlans = null, promoCodes = null, auditService = null, userEmailResolver = null, auditContextResolver = null, subscriptionBundles = null, contractFreeze = null, trialProjection = null, cancellationNoticeDays =
|
|
1895
|
+
constructor(entitlements, planPreview, subscriptionUsage, usageSnapshot, subscriptionWrite, tenantIdResolver = null, userIdResolver = null, blockedPlans = null, promoCodes = null, auditService = null, userEmailResolver = null, auditContextResolver = null, subscriptionBundles = null, contractFreeze = null, trialProjection = null, cancellationNoticeDays = NO_NOTICE_PERIOD) {
|
|
1893
1896
|
this.entitlements = entitlements;
|
|
1894
1897
|
this.planPreview = planPreview;
|
|
1895
1898
|
this.subscriptionUsage = subscriptionUsage;
|
|
@@ -2712,6 +2715,7 @@ TenantBillingController = _ts_decorate12([
|
|
|
2712
2715
|
|
|
2713
2716
|
// src/billing/tenant-billing.module.ts
|
|
2714
2717
|
import { Module as Module2 } from "@nestjs/common";
|
|
2718
|
+
import { planCatalogSchema } from "@saasicat/spec";
|
|
2715
2719
|
function _ts_decorate13(decorators, target, key, desc) {
|
|
2716
2720
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2717
2721
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2719,6 +2723,27 @@ function _ts_decorate13(decorators, target, key, desc) {
|
|
|
2719
2723
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2720
2724
|
}
|
|
2721
2725
|
__name(_ts_decorate13, "_ts_decorate");
|
|
2726
|
+
function settingFromCatalog(catalog, key) {
|
|
2727
|
+
const settings = catalog.tenantBilling;
|
|
2728
|
+
const value = settings?.[key];
|
|
2729
|
+
if (value === void 0) {
|
|
2730
|
+
throw new Error(`The plan catalogue carries no tenantBilling.${key}. It is a required section of config/saas.yaml and the loader refuses a file without it, so a catalogue that reaches here without one was built in code: check the \`dbCatalog\` block, which forwards \`tenantBilling\` from that same file, or the object passed to \`planCatalog\`.`);
|
|
2731
|
+
}
|
|
2732
|
+
return value;
|
|
2733
|
+
}
|
|
2734
|
+
__name(settingFromCatalog, "settingFromCatalog");
|
|
2735
|
+
var MOVED_TO_THE_FILE = Object.keys(planCatalogSchema.properties?.tenantBilling?.properties ?? // Refuses to guess rather than falling back to an empty list: an empty
|
|
2736
|
+
// one would turn this guard off without saying so.
|
|
2737
|
+
(() => {
|
|
2738
|
+
throw new Error("plan-catalog.schema.json declares no tenantBilling properties \u2014 @saasicat/spec and @saasicat/nest are out of step.");
|
|
2739
|
+
})());
|
|
2740
|
+
function assertNoMovedOptions(options) {
|
|
2741
|
+
const given = options;
|
|
2742
|
+
const passed = MOVED_TO_THE_FILE.filter((key) => given[key] !== void 0);
|
|
2743
|
+
if (passed.length === 0) return;
|
|
2744
|
+
throw new Error(`TenantBillingModule.forRoot() no longer accepts ${passed.join(" and ")} \u2014 this moved to config/saas.yaml under \`tenantBilling:\`. Move the value there (both members of each setting are required) and delete it here. The file is the one place these live, so a fallback here would be the second home that change exists to close. See docs/guides/upgrade-to-1.0.md.`);
|
|
2745
|
+
}
|
|
2746
|
+
__name(assertNoMovedOptions, "assertNoMovedOptions");
|
|
2722
2747
|
var TenantBillingModule = class _TenantBillingModule {
|
|
2723
2748
|
static {
|
|
2724
2749
|
__name(this, "TenantBillingModule");
|
|
@@ -2733,18 +2758,20 @@ var TenantBillingModule = class _TenantBillingModule {
|
|
|
2733
2758
|
TenantAdminGuard,
|
|
2734
2759
|
PlanChangePreviewService
|
|
2735
2760
|
];
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2761
|
+
assertNoMovedOptions(options);
|
|
2762
|
+
providers.push({
|
|
2763
|
+
provide: CANCELLATION_NOTICE_DAYS_TOKEN,
|
|
2764
|
+
useFactory: /* @__PURE__ */ __name((catalog) => settingFromCatalog(catalog, "cancellationNoticeDays"), "useFactory"),
|
|
2765
|
+
inject: [
|
|
2766
|
+
PLAN_CATALOG_TOKEN
|
|
2767
|
+
]
|
|
2768
|
+
}, {
|
|
2769
|
+
provide: SELF_SERVICE_BLOCKED_PLANS_TOKEN,
|
|
2770
|
+
useFactory: /* @__PURE__ */ __name((catalog) => settingFromCatalog(catalog, "selfServiceBlockedPlans"), "useFactory"),
|
|
2771
|
+
inject: [
|
|
2772
|
+
PLAN_CATALOG_TOKEN
|
|
2773
|
+
]
|
|
2774
|
+
});
|
|
2748
2775
|
if (options.subscriptionBundleRepository) {
|
|
2749
2776
|
providers.push(asProvider(SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN, options.subscriptionBundleRepository));
|
|
2750
2777
|
}
|
|
@@ -3514,6 +3541,7 @@ export {
|
|
|
3514
3541
|
bundleCycleFitsPlan,
|
|
3515
3542
|
computeNextBundlePeriod,
|
|
3516
3543
|
decideCancellation,
|
|
3544
|
+
NO_NOTICE_PERIOD,
|
|
3517
3545
|
noticeDaysFor,
|
|
3518
3546
|
decideCancellationFor,
|
|
3519
3547
|
FEATURE_GUARD_MARKER,
|
|
@@ -3,7 +3,7 @@ import { ExecutionContext, DynamicModule } from '@nestjs/common';
|
|
|
3
3
|
import { Reflector } from '@nestjs/core';
|
|
4
4
|
import { SuperAdminProvisioningPort, SetupStatusResponse, SetupRequest, SetupResult, SetupConfirmMfaRequest, SetupConfirmMfaResponse } from '@saasicat/core';
|
|
5
5
|
import { h as MfaService } from './admin-stats.service-TYiSUwIR.js';
|
|
6
|
-
import { e as SaaSiCatModuleOptions } from './module-options-
|
|
6
|
+
import { e as SaaSiCatModuleOptions } from './module-options-DF3H6q3A.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Shared metadata key for endpoints that intentionally run without application
|
|
@@ -3,7 +3,7 @@ import { ExecutionContext, DynamicModule } from '@nestjs/common';
|
|
|
3
3
|
import { Reflector } from '@nestjs/core';
|
|
4
4
|
import { SuperAdminProvisioningPort, SetupStatusResponse, SetupRequest, SetupResult, SetupConfirmMfaRequest, SetupConfirmMfaResponse } from '@saasicat/core';
|
|
5
5
|
import { h as MfaService } from './admin-stats.service-DfKupywR.cjs';
|
|
6
|
-
import { e as SaaSiCatModuleOptions } from './module-options-
|
|
6
|
+
import { e as SaaSiCatModuleOptions } from './module-options-BDb8Tam7.cjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Shared metadata key for endpoints that intentionally run without application
|