@saasicat/nest 1.0.0-rc.21 → 1.0.0-rc.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/_entries.cjs +4887 -3609
  3. package/dist/admin/index.js +7 -5
  4. package/dist/{aggregation-ChpZDh0g.d.ts → aggregation-6fPkeV8i.d.ts} +39 -4
  5. package/dist/{aggregation-OpnhwzF5.d.cts → aggregation-DjQUc7yd.d.cts} +39 -4
  6. package/dist/billing/index.d.cts +68 -9
  7. package/dist/billing/index.d.ts +68 -9
  8. package/dist/billing/index.js +16 -5
  9. package/dist/checkout-offer/index.d.cts +2 -2
  10. package/dist/checkout-offer/index.d.ts +2 -2
  11. package/dist/checkout-offer/index.js +4 -4
  12. package/dist/{checkout-offer.service-CCVxG9b2.d.cts → checkout-offer.service-DmVGrT4v.d.cts} +1 -1
  13. package/dist/{checkout-offer.service-BeHgYikI.d.ts → checkout-offer.service-Yi30L4ry.d.ts} +1 -1
  14. package/dist/{chunk-WHJSYKNC.js → chunk-3U4N5UYD.js} +1 -1
  15. package/dist/{chunk-M47BNEY2.js → chunk-3YYLOYUT.js} +1373 -266
  16. package/dist/{chunk-G6EZWECL.js → chunk-B4YP7REK.js} +94 -26
  17. package/dist/{chunk-QPVDCKYS.js → chunk-ESEWSAOV.js} +4 -3
  18. package/dist/{chunk-NDLC5GYK.js → chunk-EU4N5LET.js} +4 -3
  19. package/dist/{chunk-LLYVYRGJ.js → chunk-F2PF4IXB.js} +1 -275
  20. package/dist/{chunk-AOS2JPDD.js → chunk-FJIOHAO5.js} +77 -41
  21. package/dist/{chunk-TOEFN7DN.js → chunk-FPMBQDW7.js} +2 -2
  22. package/dist/chunk-OSOP4KWL.js +288 -0
  23. package/dist/{chunk-3RLWML2S.js → chunk-QWKBOLBH.js} +35 -0
  24. package/dist/{chunk-JBCC6C3M.js → chunk-R3I5X262.js} +5 -4
  25. package/dist/{chunk-4SDSYV4A.js → chunk-T6WXDGIU.js} +1 -1
  26. package/dist/{chunk-R5YCJBHY.js → chunk-U5UPEFWC.js} +2 -2
  27. package/dist/{chunk-XSSWYPP5.js → chunk-UMZCOCT5.js} +1 -1
  28. package/dist/{chunk-7NJKVC5X.js → chunk-WQNOCOI2.js} +53 -6
  29. package/dist/{chunk-55QEDAMX.js → chunk-WTAS2CLM.js} +4 -9
  30. package/dist/{enforce-quota.interceptor-BFyVdWe8.d.cts → enforce-quota.interceptor-B9UhCBXx.d.cts} +2 -2
  31. package/dist/{enforce-quota.interceptor-GaBXboGx.d.ts → enforce-quota.interceptor-CR2waXNA.d.ts} +2 -2
  32. package/dist/entitlement/index.d.cts +1 -1
  33. package/dist/entitlement/index.d.ts +1 -1
  34. package/dist/entitlement/index.js +4 -2
  35. package/dist/index.d.cts +11 -11
  36. package/dist/index.d.ts +11 -11
  37. package/dist/index.js +36 -20
  38. package/dist/{issuer-identity.check-CBO0vcsq.d.cts → issuer-identity.check-BntcNdld.d.cts} +1 -1
  39. package/dist/{issuer-identity.check-Cz9CEMkZ.d.ts → issuer-identity.check-DFmS8whs.d.ts} +1 -1
  40. package/dist/{module-options-qAOwinHR.d.cts → module-options-C4S_StYF.d.cts} +2 -2
  41. package/dist/{module-options-DmQ3G4sZ.d.ts → module-options-DxJI-1iH.d.ts} +2 -2
  42. package/dist/payments/index.js +2 -2
  43. package/dist/platform/index.d.cts +25 -16
  44. package/dist/platform/index.d.ts +25 -16
  45. package/dist/platform/index.js +16 -14
  46. package/dist/promo/index.d.cts +11 -4
  47. package/dist/promo/index.d.ts +11 -4
  48. package/dist/promo/index.js +5 -3
  49. package/dist/{promo.module-CKkECmU8.d.cts → promo.module-Ddx-swUV.d.cts} +1 -1
  50. package/dist/{promo.module-DuIJdK3U.d.ts → promo.module-PsIvDcUp.d.ts} +1 -1
  51. package/dist/{promo.service-BYBu6dy3.d.cts → promo.service-BextPvx5.d.cts} +23 -1
  52. package/dist/{promo.service-CFjfF0Xm.d.ts → promo.service-Dqqh0JXn.d.ts} +23 -1
  53. package/dist/registration/index.d.cts +2 -2
  54. package/dist/registration/index.d.ts +2 -2
  55. package/dist/registration/index.js +5 -5
  56. package/dist/subscription-contract/index.js +2 -2
  57. package/dist/{tenant-billing.controller-DKbAqTbM.d.cts → tenant-billing.controller-BC6-S5cT.d.cts} +91 -10
  58. package/dist/{tenant-billing.controller-BLqbsONe.d.ts → tenant-billing.controller-BuQDQ76i.d.ts} +91 -10
  59. package/dist/{tenant-billing.module-ClbjzocC.d.cts → tenant-billing.module-C6MFfCKq.d.cts} +24 -1
  60. package/dist/{tenant-billing.module-DohgJJ2m.d.ts → tenant-billing.module-CUCQL0-k.d.ts} +24 -1
  61. package/dist/testing/index.d.cts +6 -6
  62. package/dist/testing/index.d.ts +6 -6
  63. package/dist/testing/index.js +33 -31
  64. package/package.json +3 -3
@@ -1,27 +1,30 @@
1
1
  import {
2
2
  PromoCodesModule
3
- } from "./chunk-4SDSYV4A.js";
3
+ } from "./chunk-T6WXDGIU.js";
4
4
  import {
5
5
  SubscriptionContractModule
6
- } from "./chunk-XSSWYPP5.js";
6
+ } from "./chunk-UMZCOCT5.js";
7
7
  import {
8
8
  AdminManifestModule,
9
9
  AdminManifestService,
10
10
  AdminModule,
11
- AdminResourcesModule,
12
11
  AdminStatsModule,
13
12
  SuperAdminGuard
14
- } from "./chunk-LLYVYRGJ.js";
13
+ } from "./chunk-F2PF4IXB.js";
15
14
  import {
16
15
  FEATURE_GUARD_MARKER,
17
16
  PublicCatalogModule,
18
17
  REQUIRE_FEATURE_KEY,
18
+ SubscriberAccountModule,
19
19
  SubscriptionBundleModule,
20
20
  TenantBillingModule,
21
21
  catalogSource,
22
22
  isPlatformFeatureGuard,
23
23
  loadPlanCatalogFromFile
24
- } from "./chunk-M47BNEY2.js";
24
+ } from "./chunk-3YYLOYUT.js";
25
+ import {
26
+ AdminResourcesModule
27
+ } from "./chunk-OSOP4KWL.js";
25
28
  import {
26
29
  CatalogModule,
27
30
  WebAuditLogger,
@@ -33,17 +36,17 @@ import {
33
36
  } from "./chunk-34XVPR6P.js";
34
37
  import {
35
38
  CheckoutOfferModule
36
- } from "./chunk-TOEFN7DN.js";
39
+ } from "./chunk-FPMBQDW7.js";
37
40
  import {
38
41
  DiscoveryModule
39
42
  } from "./chunk-S33SO5XX.js";
40
43
  import {
41
44
  EntitlementModule
42
- } from "./chunk-WHJSYKNC.js";
45
+ } from "./chunk-3U4N5UYD.js";
43
46
  import {
44
47
  LimitExceededError,
45
48
  cancellationHasLanded
46
- } from "./chunk-G6EZWECL.js";
49
+ } from "./chunk-B4YP7REK.js";
47
50
  import {
48
51
  findPlan
49
52
  } from "./chunk-TBBZWZQT.js";
@@ -55,10 +58,10 @@ import {
55
58
  } from "./chunk-QUZU2M33.js";
56
59
  import {
57
60
  PaymentsModule
58
- } from "./chunk-QPVDCKYS.js";
61
+ } from "./chunk-ESEWSAOV.js";
59
62
  import {
60
63
  PaymentGatewayRegistry
61
- } from "./chunk-7NJKVC5X.js";
64
+ } from "./chunk-WQNOCOI2.js";
62
65
  import {
63
66
  RLS_BYPASS_PORT_TOKEN
64
67
  } from "./chunk-SZ7RFPXA.js";
@@ -1705,18 +1708,23 @@ function optionsOf2(slot) {
1705
1708
  __name(optionsOf2, "optionsOf");
1706
1709
 
1707
1710
  // src/platform/compose/admin-resources.ts
1708
- function composeAdminResources({ options, persistence }) {
1711
+ function composeAdminResources({ options, persistence, shared }) {
1709
1712
  if (!options.adminResources) return [];
1710
1713
  const config = optionsOf2(options.adminResources);
1714
+ shared.adminResourcesModule = AdminResourcesModule.forRoot({
1715
+ resources: config.resources ?? persistence?.adminResources?.resources,
1716
+ guards: adminResourceGuards(options),
1717
+ imports: config.imports ?? options.imports
1718
+ });
1711
1719
  return [
1712
- AdminResourcesModule.forRoot({
1713
- resources: config.resources ?? persistence?.adminResources?.resources,
1714
- guards: config.guards ?? operatorGuards(options),
1715
- imports: config.imports ?? options.imports
1716
- })
1720
+ shared.adminResourcesModule
1717
1721
  ];
1718
1722
  }
1719
1723
  __name(composeAdminResources, "composeAdminResources");
1724
+ function adminResourceGuards(options) {
1725
+ return optionsOf2(options.adminResources).guards ?? operatorGuards(options);
1726
+ }
1727
+ __name(adminResourceGuards, "adminResourceGuards");
1720
1728
 
1721
1729
  // src/platform/compose/catalog.ts
1722
1730
  function composeCatalog({ options, persistence }) {
@@ -1905,6 +1913,29 @@ function composePromoCodes({ options, adapters, persistence }) {
1905
1913
  }
1906
1914
  __name(composePromoCodes, "composePromoCodes");
1907
1915
 
1916
+ // src/platform/compose/subscriber-account.ts
1917
+ function servesSubscriberAccounts(options) {
1918
+ return Boolean(options.adminResources && optionsOf2(options.tenantBilling).chargeJournal);
1919
+ }
1920
+ __name(servesSubscriberAccounts, "servesSubscriberAccounts");
1921
+ function composeSubscriberAccount(ctx) {
1922
+ const { adminResourcesModule, tenantBillingModule } = ctx.shared;
1923
+ if (!servesSubscriberAccounts(ctx.options) || !adminResourcesModule || !tenantBillingModule) {
1924
+ return [];
1925
+ }
1926
+ return [
1927
+ SubscriberAccountModule.forRoot({
1928
+ guards: adminResourceGuards(ctx.options),
1929
+ imports: [
1930
+ adminResourcesModule,
1931
+ tenantBillingModule,
1932
+ ...optionsOf2(ctx.options.adminResources).imports ?? ctx.options.imports ?? []
1933
+ ]
1934
+ })
1935
+ ];
1936
+ }
1937
+ __name(composeSubscriberAccount, "composeSubscriberAccount");
1938
+
1908
1939
  // src/platform/compose/tenant-bindings.ts
1909
1940
  function normalizeTenantAuthGuards(guards) {
1910
1941
  if (!Array.isArray(guards)) return guards;
@@ -1934,29 +1965,30 @@ function composeTenantBilling(ctx) {
1934
1965
  ctx.shared.quotaProvidersHostedByTenantBilling = quotaProviders.length > 0;
1935
1966
  ctx.shared.authGuards = normalizeTenantAuthGuards(authGuards);
1936
1967
  ctx.shared.subscriptionUsagePort = subscriptionUsagePort ?? tenantSlice?.subscriptionUsagePort;
1968
+ ctx.shared.tenantBillingModule = TenantBillingModule.forRoot({
1969
+ ...tenantOptions,
1970
+ authGuards: ctx.shared.authGuards,
1971
+ // The same adapter `SubscriptionBundleModule` gets. That module
1972
+ // exports the token, but it is a sibling import here rather than an
1973
+ // ancestor, so its exports never reach this module's providers —
1974
+ // and the plan-change rule that reads bookings would resolve to
1975
+ // "none" and allow the move it exists to refuse.
1976
+ subscriptionBundleRepository: ctx.persistence?.entitlement?.subscriptionBundleRepository,
1977
+ subscriptionUsagePort: ctx.shared.subscriptionUsagePort,
1978
+ usageSnapshotPort: usageSnapshotPort ?? tenantSlice?.usageSnapshotPort ?? quotaUsageSnapshotProvider(quotaProviders),
1979
+ subscriptionWritePort: subscriptionWritePort ?? tenantSlice?.subscriptionWritePort,
1980
+ imports: tenantImports ?? ctx.options.imports,
1981
+ extraProviders: [
1982
+ ...quotaProviders,
1983
+ ...extraProviders ?? []
1984
+ ],
1985
+ extraExports: [
1986
+ ...quotaProviders,
1987
+ ...extraExports ?? []
1988
+ ]
1989
+ });
1937
1990
  return [
1938
- TenantBillingModule.forRoot({
1939
- ...tenantOptions,
1940
- authGuards: ctx.shared.authGuards,
1941
- // The same adapter `SubscriptionBundleModule` gets. That module
1942
- // exports the token, but it is a sibling import here rather than an
1943
- // ancestor, so its exports never reach this module's providers —
1944
- // and the plan-change rule that reads bookings would resolve to
1945
- // "none" and allow the move it exists to refuse.
1946
- subscriptionBundleRepository: ctx.persistence?.entitlement?.subscriptionBundleRepository,
1947
- subscriptionUsagePort: ctx.shared.subscriptionUsagePort,
1948
- usageSnapshotPort: usageSnapshotPort ?? tenantSlice?.usageSnapshotPort ?? quotaUsageSnapshotProvider(quotaProviders),
1949
- subscriptionWritePort: subscriptionWritePort ?? tenantSlice?.subscriptionWritePort,
1950
- imports: tenantImports ?? ctx.options.imports,
1951
- extraProviders: [
1952
- ...quotaProviders,
1953
- ...extraProviders ?? []
1954
- ],
1955
- extraExports: [
1956
- ...quotaProviders,
1957
- ...extraExports ?? []
1958
- ]
1959
- })
1991
+ ctx.shared.tenantBillingModule
1960
1992
  ];
1961
1993
  }
1962
1994
  __name(composeTenantBilling, "composeTenantBilling");
@@ -1998,7 +2030,9 @@ var FEATURE_COMPOSERS = [
1998
2030
  composeSetup,
1999
2031
  composeAdminStats,
2000
2032
  composeCheckoutOffer,
2001
- composeSubscriptionContract
2033
+ composeSubscriptionContract,
2034
+ // After the admin resources and tenant billing: it imports both.
2035
+ composeSubscriberAccount
2002
2036
  ];
2003
2037
  function composeFeatures(ctx) {
2004
2038
  return FEATURE_COMPOSERS.flatMap((compose) => compose(ctx));
@@ -2501,9 +2535,10 @@ import { DiscoveryModule as NestDiscoveryModule } from "@nestjs/core";
2501
2535
  import { planCatalogSettingsOf } from "@saasicat/core";
2502
2536
 
2503
2537
  // src/platform/compose/manifest.ts
2538
+ import { SUBSCRIBER_ACCOUNT_CAPABILITY } from "@saasicat/core";
2504
2539
  var PLATFORM_SUBSCRIPTION_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/PlatformSubscriptionRepository");
2505
2540
  var STANDARD_MANIFEST_REGISTRATION_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/StandardManifestRegistration");
2506
- function buildStandardManifestContribution(catalog, adminResources, promoCodes) {
2541
+ function buildStandardManifestContribution(catalog, adminResources, promoCodes, subscriberAccounts) {
2507
2542
  const capabilities = {
2508
2543
  "discovery.read": true,
2509
2544
  "settings.read": true
@@ -2536,6 +2571,7 @@ function buildStandardManifestContribution(catalog, adminResources, promoCodes)
2536
2571
  }
2537
2572
  };
2538
2573
  }
2574
+ if (subscriberAccounts) capabilities[SUBSCRIBER_ACCOUNT_CAPABILITY] = true;
2539
2575
  if (promoCodes) {
2540
2576
  Object.assign(capabilities, {
2541
2577
  "promoCodes.read": true,
@@ -2865,7 +2901,7 @@ var SaaSiCatModule = class _SaaSiCatModule {
2865
2901
  const lightweightProviders = [];
2866
2902
  const lightweightExports = [];
2867
2903
  if (options.autoManifest !== false) {
2868
- const contribution = buildStandardManifestContribution(catalogConfig, adminResourcesConfig, promoCodesConfig);
2904
+ const contribution = buildStandardManifestContribution(catalogConfig, adminResourcesConfig, promoCodesConfig, servesSubscriberAccounts(options));
2869
2905
  lightweightProviders.push({
2870
2906
  provide: STANDARD_MANIFEST_REGISTRATION_TOKEN,
2871
2907
  useFactory: /* @__PURE__ */ __name((manifest) => {
@@ -3,10 +3,10 @@ import {
3
3
  CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN,
4
4
  CheckoutOfferPricing,
5
5
  CheckoutOfferService
6
- } from "./chunk-55QEDAMX.js";
6
+ } from "./chunk-WTAS2CLM.js";
7
7
  import {
8
8
  SubscriptionContractService
9
- } from "./chunk-NDLC5GYK.js";
9
+ } from "./chunk-EU4N5LET.js";
10
10
  import {
11
11
  SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN
12
12
  } from "./chunk-VBRYPU7V.js";
@@ -0,0 +1,288 @@
1
+ import {
2
+ EnforceMfa
3
+ } from "./chunk-34XVPR6P.js";
4
+ import {
5
+ AdminAuditService
6
+ } from "./chunk-OOTEXP47.js";
7
+ import {
8
+ asProvider
9
+ } from "./chunk-J7NJRK3K.js";
10
+ import {
11
+ __name
12
+ } from "./chunk-SHUYVCID.js";
13
+
14
+ // src/admin/admin-resources.module.ts
15
+ import { Body, Controller, Get, Inject, Injectable, Module, NotFoundException, Param, Post, Query, Req, UseGuards } from "@nestjs/common";
16
+ import { IsOptional, IsString, MaxLength } from "class-validator";
17
+ import { BILLING_ERROR_CODES } from "@saasicat/core";
18
+ function _ts_decorate(decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ }
24
+ __name(_ts_decorate, "_ts_decorate");
25
+ function _ts_metadata(k, v) {
26
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
27
+ }
28
+ __name(_ts_metadata, "_ts_metadata");
29
+ function _ts_param(paramIndex, decorator) {
30
+ return function(target, key) {
31
+ decorator(target, key, paramIndex);
32
+ };
33
+ }
34
+ __name(_ts_param, "_ts_param");
35
+ var ADMIN_RESOURCES_PORT_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/AdminResourcesPort");
36
+ var SuspendTenantDto = class {
37
+ static {
38
+ __name(this, "SuspendTenantDto");
39
+ }
40
+ reason;
41
+ };
42
+ _ts_decorate([
43
+ IsOptional(),
44
+ IsString(),
45
+ MaxLength(500),
46
+ _ts_metadata("design:type", String)
47
+ ], SuspendTenantDto.prototype, "reason", void 0);
48
+ var AdminResourcesService = class {
49
+ static {
50
+ __name(this, "AdminResourcesService");
51
+ }
52
+ resources;
53
+ audit;
54
+ constructor(resources, audit) {
55
+ this.resources = resources;
56
+ this.audit = audit;
57
+ }
58
+ listTenants(filter) {
59
+ return this.resources.listTenants(filter);
60
+ }
61
+ async getTenantDetail(slug) {
62
+ const tenant = await this.resources.getTenantDetail(slug);
63
+ if (!tenant) {
64
+ throw new NotFoundException({
65
+ code: BILLING_ERROR_CODES.TENANT_NOT_FOUND,
66
+ message: `Tenant ${slug} not found`,
67
+ params: {
68
+ slug
69
+ }
70
+ });
71
+ }
72
+ return tenant;
73
+ }
74
+ listUsers(filter) {
75
+ return this.resources.listUsers(filter);
76
+ }
77
+ listAudit(filter) {
78
+ return this.resources.listAudit(filter);
79
+ }
80
+ listSubscriptions() {
81
+ return this.resources.listSubscriptions();
82
+ }
83
+ suspendTenant(slug, reason, actor) {
84
+ return this.setTenantActive(slug, false, "PAST_DUE", actor, {
85
+ action: "TENANT_SUSPEND",
86
+ reason: reason ?? ""
87
+ });
88
+ }
89
+ reactivateTenant(slug, actor) {
90
+ return this.setTenantActive(slug, true, "ACTIVE", actor, {
91
+ action: "TENANT_REACTIVATE",
92
+ reason: ""
93
+ });
94
+ }
95
+ async setTenantActive(slug, active, subscriptionStatus, actor, audit) {
96
+ const result = await this.resources.setTenantActive(slug, active, subscriptionStatus);
97
+ if (!result) {
98
+ throw new NotFoundException({
99
+ code: BILLING_ERROR_CODES.TENANT_NOT_FOUND,
100
+ message: `Tenant ${slug} not found`,
101
+ params: {
102
+ slug
103
+ }
104
+ });
105
+ }
106
+ await this.audit.log({
107
+ actor,
108
+ entity: "Tenant",
109
+ entityId: result.id,
110
+ action: audit.action,
111
+ changes: {
112
+ slug,
113
+ reason: audit.reason
114
+ }
115
+ });
116
+ return result;
117
+ }
118
+ };
119
+ AdminResourcesService = _ts_decorate([
120
+ Injectable(),
121
+ _ts_param(0, Inject(ADMIN_RESOURCES_PORT_TOKEN)),
122
+ _ts_param(1, Inject(AdminAuditService)),
123
+ _ts_metadata("design:type", Function),
124
+ _ts_metadata("design:paramtypes", [
125
+ typeof AdminResourcesPort === "undefined" ? Object : AdminResourcesPort,
126
+ typeof AdminAuditService === "undefined" ? Object : AdminAuditService
127
+ ])
128
+ ], AdminResourcesService);
129
+ function actorFromRequest(request) {
130
+ const userId = request.user?.id ?? request.user?.userId ?? "unknown";
131
+ return {
132
+ userId,
133
+ email: request.user?.email ?? `${userId}@unknown`,
134
+ source: "web",
135
+ context: request.user?.sessionId ?? "unknown"
136
+ };
137
+ }
138
+ __name(actorFromRequest, "actorFromRequest");
139
+ function buildAdminResourcesController(guards) {
140
+ let GeneratedAdminResourcesController = class GeneratedAdminResourcesController {
141
+ static {
142
+ __name(this, "GeneratedAdminResourcesController");
143
+ }
144
+ resources;
145
+ constructor(resources) {
146
+ this.resources = resources;
147
+ }
148
+ listTenants(query) {
149
+ return this.resources.listTenants(query);
150
+ }
151
+ getTenant(slug) {
152
+ return this.resources.getTenantDetail(slug);
153
+ }
154
+ suspendTenant(request, slug, dto) {
155
+ return this.resources.suspendTenant(slug, dto.reason, actorFromRequest(request));
156
+ }
157
+ reactivateTenant(request, slug) {
158
+ return this.resources.reactivateTenant(slug, actorFromRequest(request));
159
+ }
160
+ listUsers(query) {
161
+ return this.resources.listUsers(query);
162
+ }
163
+ listAudit(query) {
164
+ return this.resources.listAudit({
165
+ actor: query.actor,
166
+ action: query.action,
167
+ entity: query.entity,
168
+ since: query.since,
169
+ limit: query.limit ? Number.parseInt(query.limit, 10) : void 0
170
+ });
171
+ }
172
+ listSubscriptions() {
173
+ return this.resources.listSubscriptions();
174
+ }
175
+ };
176
+ _ts_decorate([
177
+ Get("tenants"),
178
+ _ts_param(0, Query()),
179
+ _ts_metadata("design:type", Function),
180
+ _ts_metadata("design:paramtypes", [
181
+ Object
182
+ ]),
183
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
184
+ ], GeneratedAdminResourcesController.prototype, "listTenants", null);
185
+ _ts_decorate([
186
+ Get("tenants/:slug"),
187
+ _ts_param(0, Param("slug")),
188
+ _ts_metadata("design:type", Function),
189
+ _ts_metadata("design:paramtypes", [
190
+ String
191
+ ]),
192
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
193
+ ], GeneratedAdminResourcesController.prototype, "getTenant", null);
194
+ _ts_decorate([
195
+ Post("tenants/:slug/suspend"),
196
+ EnforceMfa(),
197
+ _ts_param(0, Req()),
198
+ _ts_param(1, Param("slug")),
199
+ _ts_param(2, Body()),
200
+ _ts_metadata("design:type", Function),
201
+ _ts_metadata("design:paramtypes", [
202
+ typeof AdminRequest === "undefined" ? Object : AdminRequest,
203
+ String,
204
+ typeof SuspendTenantDto === "undefined" ? Object : SuspendTenantDto
205
+ ]),
206
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
207
+ ], GeneratedAdminResourcesController.prototype, "suspendTenant", null);
208
+ _ts_decorate([
209
+ Post("tenants/:slug/reactivate"),
210
+ EnforceMfa(),
211
+ _ts_param(0, Req()),
212
+ _ts_param(1, Param("slug")),
213
+ _ts_metadata("design:type", Function),
214
+ _ts_metadata("design:paramtypes", [
215
+ typeof AdminRequest === "undefined" ? Object : AdminRequest,
216
+ String
217
+ ]),
218
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
219
+ ], GeneratedAdminResourcesController.prototype, "reactivateTenant", null);
220
+ _ts_decorate([
221
+ Get("users"),
222
+ _ts_param(0, Query()),
223
+ _ts_metadata("design:type", Function),
224
+ _ts_metadata("design:paramtypes", [
225
+ Object
226
+ ]),
227
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
228
+ ], GeneratedAdminResourcesController.prototype, "listUsers", null);
229
+ _ts_decorate([
230
+ Get("audit"),
231
+ _ts_param(0, Query()),
232
+ _ts_metadata("design:type", Function),
233
+ _ts_metadata("design:paramtypes", [
234
+ Object
235
+ ]),
236
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
237
+ ], GeneratedAdminResourcesController.prototype, "listAudit", null);
238
+ _ts_decorate([
239
+ Get("subscriptions"),
240
+ _ts_metadata("design:type", Function),
241
+ _ts_metadata("design:paramtypes", []),
242
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
243
+ ], GeneratedAdminResourcesController.prototype, "listSubscriptions", null);
244
+ GeneratedAdminResourcesController = _ts_decorate([
245
+ Controller("admin"),
246
+ UseGuards(...guards),
247
+ _ts_param(0, Inject(AdminResourcesService)),
248
+ _ts_metadata("design:type", Function),
249
+ _ts_metadata("design:paramtypes", [
250
+ typeof AdminResourcesService === "undefined" ? Object : AdminResourcesService
251
+ ])
252
+ ], GeneratedAdminResourcesController);
253
+ return GeneratedAdminResourcesController;
254
+ }
255
+ __name(buildAdminResourcesController, "buildAdminResourcesController");
256
+ var AdminResourcesModule = class _AdminResourcesModule {
257
+ static {
258
+ __name(this, "AdminResourcesModule");
259
+ }
260
+ static forRoot(options) {
261
+ return {
262
+ module: _AdminResourcesModule,
263
+ global: options.global ?? false,
264
+ imports: options.imports ?? [],
265
+ controllers: [
266
+ buildAdminResourcesController(options.guards)
267
+ ],
268
+ providers: [
269
+ asProvider(ADMIN_RESOURCES_PORT_TOKEN, options.resources),
270
+ AdminResourcesService
271
+ ],
272
+ exports: [
273
+ ADMIN_RESOURCES_PORT_TOKEN,
274
+ AdminResourcesService
275
+ ]
276
+ };
277
+ }
278
+ };
279
+ AdminResourcesModule = _ts_decorate([
280
+ Module({})
281
+ ], AdminResourcesModule);
282
+
283
+ export {
284
+ ADMIN_RESOURCES_PORT_TOKEN,
285
+ SuspendTenantDto,
286
+ AdminResourcesService,
287
+ AdminResourcesModule
288
+ };
@@ -3,6 +3,7 @@ import {
3
3
  } from "./chunk-TBBZWZQT.js";
4
4
  import {
5
5
  computeIncludedVat,
6
+ grossFromNet,
6
7
  netFromGross,
7
8
  round2
8
9
  } from "./chunk-6PJE7EWO.js";
@@ -22,6 +23,14 @@ function computeDiscountGross(plan, code) {
22
23
  return round2(v);
23
24
  }
24
25
  __name(computeDiscountGross, "computeDiscountGross");
26
+ function promoCodeDiscountNet(planNet, vatRate, code) {
27
+ const planGross = grossFromNet(planNet, vatRate);
28
+ const discountGross = Math.min(computeDiscountGross({
29
+ gross: planGross
30
+ }, code), planGross);
31
+ return Math.min(planNet, netFromGross(discountGross, vatRate));
32
+ }
33
+ __name(promoCodeDiscountNet, "promoCodeDiscountNet");
25
34
  function computeDiscountedGross(planGross, discountGross) {
26
35
  return round2(planGross - discountGross);
27
36
  }
@@ -671,6 +680,31 @@ var PromoCodesService = class {
671
680
  endsAt
672
681
  }, tx);
673
682
  }
683
+ /**
684
+ * The code redeemed for a subscription, with the values it was redeemed
685
+ * at, unless the redemption was reversed — or null.
686
+ *
687
+ * An expired redemption still counts. Its term is counted from the
688
+ * subscription's start, which lies before a trial, while a contract counts
689
+ * a discount from the first period that is paid: a code for one month
690
+ * redeemed in a thirty-day trial has expired before the customer has paid
691
+ * for anything. A code deleted since still names what was agreed, so it is
692
+ * read without the refusal `findOne` gives.
693
+ */
694
+ async redeemedCodeFor(subscriptionId) {
695
+ const redemption = await this.redemptionRepo.findBySubscription(subscriptionId);
696
+ if (!redemption || redemption.status === "REVERSED") return null;
697
+ const promo = await this.promoRepo.findById(redemption.promoCodeId);
698
+ if (!promo) return null;
699
+ return {
700
+ code: promo.code,
701
+ valueType: redemption.appliedValueType,
702
+ value: redemption.appliedValue,
703
+ durationType: redemption.appliedDurationType,
704
+ durationValue: redemption.appliedDurationValue,
705
+ redeemedAt: redemption.redeemedAt
706
+ };
707
+ }
674
708
  async reverse(subscriptionId) {
675
709
  return this.transactionRunner.run(async (tx) => {
676
710
  const redemption = await this.redemptionRepo.findBySubscription(subscriptionId, tx);
@@ -876,6 +910,7 @@ __name(termsAfter, "termsAfter");
876
910
 
877
911
  export {
878
912
  computeDiscountGross,
913
+ promoCodeDiscountNet,
879
914
  computeDiscountedGross,
880
915
  computeRegularStartsAt,
881
916
  addCycles,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CheckoutOfferService
3
- } from "./chunk-55QEDAMX.js";
3
+ } from "./chunk-WTAS2CLM.js";
4
4
  import {
5
5
  grossFromNet,
6
6
  netFromGross
@@ -9,8 +9,9 @@ import {
9
9
  PaymentCallbackService,
10
10
  PaymentGatewayRegistry,
11
11
  SUBSCRIBER_PAYMENT_METHOD_REPOSITORY_TOKEN,
12
+ openGatewayForm,
12
13
  refuseForeignReturnUrls
13
- } from "./chunk-7NJKVC5X.js";
14
+ } from "./chunk-WQNOCOI2.js";
14
15
  import {
15
16
  INVOICE_ADDRESS_FIELDS,
16
17
  settleNewSubscriberDetails
@@ -242,7 +243,7 @@ var RegistrationPaymentService = class _RegistrationPaymentService {
242
243
  if (!account) {
243
244
  throw new ConflictException(codedError(PAYMENT_ERROR_CODES.PAYMENTS_NOT_CONFIGURED));
244
245
  }
245
- const session = await account.gateway.startPaymentMethodSetup({
246
+ const session = await openGatewayForm(account, {
246
247
  subject: {
247
248
  kind: "registration",
248
249
  pendingRegistrationId: pending.id
@@ -262,7 +263,7 @@ var RegistrationPaymentService = class _RegistrationPaymentService {
262
263
  methods: account.methods,
263
264
  successUrl: urls.successUrl,
264
265
  cancelUrl: urls.cancelUrl
265
- });
266
+ }, this.logger);
266
267
  const updated = await this.repo.update(pending.id, {
267
268
  ...billing,
268
269
  status: "CHECKOUT_STARTED",
@@ -12,7 +12,7 @@ import {
12
12
  PROMO_SUBSCRIPTION_LOOKUP_TOKEN,
13
13
  PROMO_TRANSACTION_RUNNER_TOKEN,
14
14
  PromoCodesService
15
- } from "./chunk-3RLWML2S.js";
15
+ } from "./chunk-QWKBOLBH.js";
16
16
  import {
17
17
  SaaSiCatPublicRoute
18
18
  } from "./chunk-YSC46BGM.js";
@@ -7,14 +7,14 @@ import {
7
7
  REQUIRE_FEATURE_KEY,
8
8
  loadPlanCatalogFromString,
9
9
  periodEndAfter
10
- } from "./chunk-M47BNEY2.js";
10
+ } from "./chunk-3YYLOYUT.js";
11
11
  import {
12
12
  EnforceMfa
13
13
  } from "./chunk-34XVPR6P.js";
14
14
  import {
15
15
  EntitlementService,
16
16
  isLimitExceededError
17
- } from "./chunk-G6EZWECL.js";
17
+ } from "./chunk-B4YP7REK.js";
18
18
  import {
19
19
  ENTITLEMENT_SERVICE_TOKEN
20
20
  } from "./chunk-OUDSQ3PU.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SubscriptionContractService
3
- } from "./chunk-NDLC5GYK.js";
3
+ } from "./chunk-EU4N5LET.js";
4
4
  import {
5
5
  SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN
6
6
  } from "./chunk-VBRYPU7V.js";