@antelopejs/dms-saas 0.2.0 → 0.2.1

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 (177) hide show
  1. package/README.md +257 -10
  2. package/dist/billing-state/index.d.ts +1 -0
  3. package/dist/billing-state/index.js +1 -0
  4. package/dist/billing-state/index.js.map +1 -1
  5. package/dist/billing-state/past-due-banner.d.ts +4 -0
  6. package/dist/billing-state/past-due-banner.js +25 -0
  7. package/dist/billing-state/past-due-banner.js.map +1 -0
  8. package/dist/config/runtime.d.ts +6 -1
  9. package/dist/config/runtime.js +50 -1
  10. package/dist/config/runtime.js.map +1 -1
  11. package/dist/crons/recompute-billing-state.js +4 -1
  12. package/dist/crons/recompute-billing-state.js.map +1 -1
  13. package/dist/data-api/platformOwner/index.d.ts +1 -0
  14. package/dist/data-api/platformOwner/index.js +1 -0
  15. package/dist/data-api/platformOwner/index.js.map +1 -1
  16. package/dist/data-api/platformOwner/invitations.d.ts +22 -0
  17. package/dist/data-api/platformOwner/invitations.js +121 -0
  18. package/dist/data-api/platformOwner/invitations.js.map +1 -0
  19. package/dist/data-api/platformOwner/workspaces.d.ts +3 -0
  20. package/dist/data-api/platformOwner/workspaces.js +64 -12
  21. package/dist/data-api/platformOwner/workspaces.js.map +1 -1
  22. package/dist/data-api/tenant/tenant-invoices.js +2 -10
  23. package/dist/data-api/tenant/tenant-invoices.js.map +1 -1
  24. package/dist/hooks/register.js +2 -1
  25. package/dist/hooks/register.js.map +1 -1
  26. package/dist/implementations/dms-saas/billing.d.ts +2 -1
  27. package/dist/implementations/dms-saas/billing.js +6 -0
  28. package/dist/implementations/dms-saas/billing.js.map +1 -1
  29. package/dist/index.js +5 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/invoice-line-items/injection.d.ts +10 -0
  32. package/dist/invoice-line-items/injection.js +7 -3
  33. package/dist/invoice-line-items/injection.js.map +1 -1
  34. package/dist/operator-actions/index.d.ts +1 -0
  35. package/dist/operator-actions/index.js +1 -0
  36. package/dist/operator-actions/index.js.map +1 -1
  37. package/dist/operator-actions/invitation-commands.d.ts +12 -0
  38. package/dist/operator-actions/invitation-commands.js +46 -0
  39. package/dist/operator-actions/invitation-commands.js.map +1 -0
  40. package/dist/operator-actions/types.d.ts +1 -1
  41. package/dist/pages/platform/dashboard.js +2 -4
  42. package/dist/pages/platform/dashboard.js.map +1 -1
  43. package/dist/pages/platform/workspaces/detail.js +40 -1
  44. package/dist/pages/platform/workspaces/detail.js.map +1 -1
  45. package/dist/pages/platform/workspaces/index.d.ts +2 -8
  46. package/dist/pages/platform/workspaces/index.js +27 -111
  47. package/dist/pages/platform/workspaces/index.js.map +1 -1
  48. package/dist/pages/public/legal/privacy-policy.js +2 -1
  49. package/dist/pages/public/legal/privacy-policy.js.map +1 -1
  50. package/dist/pages/public/legal/terms-and-conditions.js +2 -1
  51. package/dist/pages/public/legal/terms-and-conditions.js.map +1 -1
  52. package/dist/pages/public/legal/terms-of-use.js +2 -1
  53. package/dist/pages/public/legal/terms-of-use.js.map +1 -1
  54. package/dist/plans/index.d.ts +1 -0
  55. package/dist/plans/index.js +1 -0
  56. package/dist/plans/index.js.map +1 -1
  57. package/dist/plans/platform-support.d.ts +2 -0
  58. package/dist/plans/platform-support.js +19 -0
  59. package/dist/plans/platform-support.js.map +1 -0
  60. package/dist/plans/seat-capacity.d.ts +9 -2
  61. package/dist/plans/seat-capacity.js +59 -12
  62. package/dist/plans/seat-capacity.js.map +1 -1
  63. package/dist/plans/seat-hooks.js +34 -13
  64. package/dist/plans/seat-hooks.js.map +1 -1
  65. package/dist/routes/platformOwner/dashboard.d.ts +8 -6
  66. package/dist/routes/platformOwner/dashboard.js +31 -17
  67. package/dist/routes/platformOwner/dashboard.js.map +1 -1
  68. package/dist/routes/platformOwner/index.d.ts +1 -0
  69. package/dist/routes/platformOwner/index.js +1 -0
  70. package/dist/routes/platformOwner/index.js.map +1 -1
  71. package/dist/routes/platformOwner/workspace-invitations.d.ts +13 -0
  72. package/dist/routes/platformOwner/workspace-invitations.js +73 -0
  73. package/dist/routes/platformOwner/workspace-invitations.js.map +1 -0
  74. package/dist/routes/public/register.d.ts +7 -3
  75. package/dist/routes/public/register.js +42 -27
  76. package/dist/routes/public/register.js.map +1 -1
  77. package/dist/routes/tenant/tenant-billing.d.ts +7 -11
  78. package/dist/routes/tenant/tenant-billing.js +34 -26
  79. package/dist/routes/tenant/tenant-billing.js.map +1 -1
  80. package/dist/routes/tenant/tenant-plan.d.ts +1 -0
  81. package/dist/routes/tenant/tenant-plan.js +27 -2
  82. package/dist/routes/tenant/tenant-plan.js.map +1 -1
  83. package/dist/routes/tenant/tenant-seats.d.ts +2 -4
  84. package/dist/routes/tenant/tenant-seats.js.map +1 -1
  85. package/dist/routes/tenant/workspaces.d.ts +2 -0
  86. package/dist/routes/tenant/workspaces.js +10 -4
  87. package/dist/routes/tenant/workspaces.js.map +1 -1
  88. package/dist/stripe/upcoming-invoice.d.ts +21 -0
  89. package/dist/stripe/upcoming-invoice.js +42 -0
  90. package/dist/stripe/upcoming-invoice.js.map +1 -0
  91. package/dist/stripe/webhook-dispatch.js +2 -0
  92. package/dist/stripe/webhook-dispatch.js.map +1 -1
  93. package/dist/types/config.d.ts +9 -0
  94. package/dist/types/config.js +7 -0
  95. package/dist/types/config.js.map +1 -1
  96. package/dist/upcoming-invoice/db/preview-cache.model.d.ts +38 -0
  97. package/dist/upcoming-invoice/db/preview-cache.model.js +57 -0
  98. package/dist/upcoming-invoice/db/preview-cache.model.js.map +1 -0
  99. package/dist/upcoming-invoice/db/preview-cache.table.d.ts +10 -0
  100. package/dist/upcoming-invoice/db/preview-cache.table.js +42 -0
  101. package/dist/upcoming-invoice/db/preview-cache.table.js.map +1 -0
  102. package/dist/upcoming-invoice/eligibility.d.ts +17 -0
  103. package/dist/upcoming-invoice/eligibility.js +52 -0
  104. package/dist/upcoming-invoice/eligibility.js.map +1 -0
  105. package/dist/upcoming-invoice/invalidation.d.ts +2 -0
  106. package/dist/upcoming-invoice/invalidation.js +39 -0
  107. package/dist/upcoming-invoice/invalidation.js.map +1 -0
  108. package/dist/upcoming-invoice/mapping.d.ts +8 -0
  109. package/dist/upcoming-invoice/mapping.js +82 -0
  110. package/dist/upcoming-invoice/mapping.js.map +1 -0
  111. package/dist/upcoming-invoice/outcomes.d.ts +13 -0
  112. package/dist/upcoming-invoice/outcomes.js +15 -0
  113. package/dist/upcoming-invoice/outcomes.js.map +1 -0
  114. package/dist/upcoming-invoice/preview.d.ts +3 -0
  115. package/dist/upcoming-invoice/preview.js +80 -0
  116. package/dist/upcoming-invoice/preview.js.map +1 -0
  117. package/dist/upcoming-invoice/pricing.d.ts +3 -0
  118. package/dist/upcoming-invoice/pricing.js +84 -0
  119. package/dist/upcoming-invoice/pricing.js.map +1 -0
  120. package/dist/upcoming-invoice/usage.d.ts +14 -0
  121. package/dist/upcoming-invoice/usage.js +53 -0
  122. package/dist/upcoming-invoice/usage.js.map +1 -0
  123. package/dist/workspaces/billing-identity.d.ts +19 -0
  124. package/dist/workspaces/billing-identity.js +51 -0
  125. package/dist/workspaces/billing-identity.js.map +1 -0
  126. package/dist/workspaces/default-plan.d.ts +5 -0
  127. package/dist/workspaces/default-plan.js +109 -0
  128. package/dist/workspaces/default-plan.js.map +1 -0
  129. package/dist/workspaces/index.d.ts +2 -0
  130. package/dist/workspaces/index.js +2 -0
  131. package/dist/workspaces/index.js.map +1 -1
  132. package/dist/workspaces/invitations.d.ts +26 -0
  133. package/dist/workspaces/invitations.js +112 -0
  134. package/dist/workspaces/invitations.js.map +1 -0
  135. package/dist/workspaces/provisioning.d.ts +3 -3
  136. package/dist/workspaces/provisioning.js +39 -11
  137. package/dist/workspaces/provisioning.js.map +1 -1
  138. package/frontend-vue/app/components/BillingIdentityFields.vue +179 -0
  139. package/frontend-vue/app/components/PastDueBanner.vue +81 -0
  140. package/frontend-vue/app/components/PaymentMethodCard.vue +94 -38
  141. package/frontend-vue/app/components/PlanComparisonModal.vue +62 -26
  142. package/frontend-vue/app/components/PlanUpgradeModal.vue +181 -0
  143. package/frontend-vue/app/components/PlatformNotes.vue +4 -0
  144. package/frontend-vue/app/components/RefundButton.vue +10 -1
  145. package/frontend-vue/app/components/Register.vue +49 -92
  146. package/frontend-vue/app/components/SeatQuotaBanner.vue +28 -0
  147. package/frontend-vue/app/components/TenantBillingForm.vue +52 -128
  148. package/frontend-vue/app/components/TenantPlanCard.vue +68 -10
  149. package/frontend-vue/app/components/UserSummaryCard.vue +12 -10
  150. package/frontend-vue/app/components/WorkspaceAdminCreateModal.vue +202 -0
  151. package/frontend-vue/app/components/WorkspaceCreateModal.vue +46 -9
  152. package/frontend-vue/app/components/WorkspaceInvitationLink.vue +106 -0
  153. package/frontend-vue/app/components/WorkspaceSummaryCard.vue +39 -15
  154. package/frontend-vue/app/components/WorkspaceSuspended.vue +3 -5
  155. package/frontend-vue/app/components/WorkspaceSwitcherWidget.vue +8 -5
  156. package/frontend-vue/app/composables/useBillingCountries.ts +25 -5
  157. package/frontend-vue/app/composables/useBillingIdentity.ts +141 -0
  158. package/frontend-vue/app/composables/useInvitationLink.ts +69 -0
  159. package/frontend-vue/app/composables/usePastDueBannerAction.ts +20 -0
  160. package/frontend-vue/app/composables/usePlanComparison.ts +15 -0
  161. package/frontend-vue/app/composables/usePlanFeatureFormat.ts +312 -20
  162. package/frontend-vue/app/composables/usePlanFeatureLabel.ts +24 -0
  163. package/frontend-vue/app/composables/useSaasRegistration.ts +110 -223
  164. package/frontend-vue/app/composables/useSeatQuota.ts +8 -0
  165. package/frontend-vue/app/composables/useStripePaymentElement.ts +3 -3
  166. package/frontend-vue/app/composables/useWorkspaceAccessCache.ts +29 -2
  167. package/frontend-vue/app/composables/useWorkspaceFinalization.ts +7 -32
  168. package/frontend-vue/app/custom-pages/auth/no-workspace.vue +49 -194
  169. package/frontend-vue/app/plugins/auth-links.ts +0 -4
  170. package/frontend-vue/app/types/runtime-config.ts +13 -0
  171. package/frontend-vue/dms.frontend.ts +10 -4
  172. package/frontend-vue/i18n/locales/saas-en-GB.json +161 -36
  173. package/frontend-vue/i18n/locales/saas-fr-FR.json +162 -37
  174. package/frontend-vue/package.json +0 -1
  175. package/frontend-vue/pnpm-lock.yaml +1 -125
  176. package/package.json +5 -5
  177. package/frontend-vue/app/middleware/workspace-suspended.global.ts +0 -59
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.priceUpcomingInvoice = priceUpcomingInvoice;
4
+ const logging_1 = require("@antelopejs/interface-core/logging");
5
+ const upcoming_invoice_1 = require("../stripe/upcoming-invoice");
6
+ const mapping_1 = require("./mapping");
7
+ const outcomes_1 = require("./outcomes");
8
+ const usage_1 = require("./usage");
9
+ const LOG_PREFIX = "[dms-saas:upcoming-invoice]";
10
+ const COMPLETE_TAX_STATUS = "complete";
11
+ const STRIPE_ERROR_OUTCOMES = new Map([
12
+ ["invoice_upcoming_none", (0, outcomes_1.absent)("no_upcoming_invoice")],
13
+ ["stripe_tax_inactive", (0, outcomes_1.unavailable)("tax_not_configured")],
14
+ ["customer_tax_location_invalid", (0, outcomes_1.unavailable)("tax_location_invalid")],
15
+ ["invalid_tax_location", (0, outcomes_1.unavailable)("tax_location_invalid")],
16
+ ["taxes_calculation_failed", (0, outcomes_1.unavailable)("tax_calculation_failed")],
17
+ ]);
18
+ const AUTOMATIC_TAX_STATUS_REASONS = {
19
+ requires_location_inputs: "tax_location_required",
20
+ failed: "tax_calculation_failed",
21
+ };
22
+ const PROVIDER_ERROR = (0, outcomes_1.unavailable)("provider_error");
23
+ function stripeErrorCode(error) {
24
+ if (typeof error !== "object" || error === null)
25
+ return null;
26
+ const { code } = error;
27
+ return typeof code === "string" ? code : null;
28
+ }
29
+ function classifyStripeError(error) {
30
+ const code = stripeErrorCode(error);
31
+ return (code && STRIPE_ERROR_OUTCOMES.get(code)) || PROVIDER_ERROR;
32
+ }
33
+ function incompleteTaxReason(invoice) {
34
+ const { enabled, status } = invoice.automatic_tax;
35
+ if (!enabled || status === COMPLETE_TAX_STATUS)
36
+ return null;
37
+ return ((status && AUTOMATIC_TAX_STATUS_REASONS[status]) || "tax_calculation_failed");
38
+ }
39
+ function reportUnavailable(tenantId, reason, cause) {
40
+ logging_1.Logging.Error(`${LOG_PREFIX} no upcoming invoice preview for tenant ${tenantId} (${reason})`, cause);
41
+ }
42
+ async function priceWithStripe(tenantId, target, computedAt) {
43
+ const cycle = await (0, upcoming_invoice_1.retrieveStripeSubscriptionCycle)(target.subscriptionId);
44
+ const usage = await (0, usage_1.quoteRunningCycleUsage)({
45
+ tenantId,
46
+ subscription: target.subscription,
47
+ stripeSubscriptionId: target.subscriptionId,
48
+ cycle,
49
+ now: computedAt,
50
+ });
51
+ if (!usage) {
52
+ reportUnavailable(tenantId, "usage_unavailable");
53
+ return (0, outcomes_1.stampOutcome)((0, outcomes_1.unavailable)("usage_unavailable"), computedAt);
54
+ }
55
+ const invoice = await (0, upcoming_invoice_1.previewStripeUpcomingInvoice)({
56
+ customerId: target.customerId,
57
+ subscriptionId: target.subscriptionId,
58
+ currency: cycle.currency,
59
+ quotedItems: usage.items,
60
+ });
61
+ const taxReason = incompleteTaxReason(invoice);
62
+ if (taxReason) {
63
+ reportUnavailable(tenantId, taxReason);
64
+ return (0, outcomes_1.stampOutcome)((0, outcomes_1.unavailable)(taxReason), computedAt);
65
+ }
66
+ return (0, mapping_1.toAvailablePreview)(invoice, {
67
+ billingDate: cycle.currentPeriodEnd,
68
+ usageThrough: usage.usageThrough,
69
+ computedAt,
70
+ });
71
+ }
72
+ async function priceUpcomingInvoice(tenantId, target, computedAt) {
73
+ try {
74
+ return await priceWithStripe(tenantId, target, computedAt);
75
+ }
76
+ catch (error) {
77
+ const outcome = classifyStripeError(error);
78
+ if (outcome.status === "unavailable") {
79
+ reportUnavailable(tenantId, outcome.reason, error);
80
+ }
81
+ return (0, outcomes_1.stampOutcome)(outcome, computedAt);
82
+ }
83
+ }
84
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/upcoming-invoice/pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { TenantSubscription } from "../db";
2
+ import type { QuotedInvoiceItem, StripeSubscriptionCycle } from "../stripe/upcoming-invoice";
3
+ export interface QuotedUsage {
4
+ items: QuotedInvoiceItem[];
5
+ usageThrough: Date | null;
6
+ }
7
+ export interface UsageQuoteRequest {
8
+ tenantId: string;
9
+ subscription: TenantSubscription;
10
+ stripeSubscriptionId: string;
11
+ cycle: StripeSubscriptionCycle;
12
+ now: Date;
13
+ }
14
+ export declare function quoteRunningCycleUsage(request: UsageQuoteRequest): Promise<QuotedUsage | null>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.quoteRunningCycleUsage = quoteRunningCycleUsage;
4
+ const invoice_line_items_1 = require("@antelopejs/interface-dms-saas/invoice-line-items");
5
+ const invoice_line_items_2 = require("../implementations/dms-saas/invoice-line-items");
6
+ const invoice_line_items_3 = require("../invoice-line-items");
7
+ const billing_window_1 = require("../invoice-line-items/billing-window");
8
+ const PREVIEW_INVOICE_ID_PREFIX = "upcoming_";
9
+ const NO_USAGE = { items: [], usageThrough: null };
10
+ function buildPreviewContext(request) {
11
+ if (request.now <= request.cycle.currentPeriodStart)
12
+ return null;
13
+ return (0, billing_window_1.clipInvoiceUsageWindow)({
14
+ tenantId: request.tenantId,
15
+ invoiceId: `${PREVIEW_INVOICE_ID_PREFIX}${request.stripeSubscriptionId}`,
16
+ currency: request.cycle.currency,
17
+ periodStart: request.cycle.currentPeriodStart,
18
+ periodEnd: request.now,
19
+ isPreview: true,
20
+ }, request.subscription, request.stripeSubscriptionId);
21
+ }
22
+ async function quoteProviderLines(provider, context) {
23
+ const resolution = await (0, invoice_line_items_3.resolveProviderLineItems)(provider, context);
24
+ if (resolution.failures > 0)
25
+ return null;
26
+ const selection = (0, invoice_line_items_1.selectInvoiceLineItemsToCreate)(provider.id, resolution.lineItems, new Set());
27
+ (0, invoice_line_items_3.reportSkippedLineItems)(provider.id, context.invoiceId, selection.skipped);
28
+ if (selection.skipped.some((line) => line.reason === "invalid"))
29
+ return null;
30
+ return selection.accepted.map((prepared) => ({
31
+ amountMinorUnits: prepared.item.amountCents,
32
+ description: prepared.item.description,
33
+ periodStart: context.periodStart,
34
+ periodEnd: context.periodEnd,
35
+ metadata: (0, invoice_line_items_3.buildLineItemMetadata)(provider.id, prepared),
36
+ }));
37
+ }
38
+ async function quoteRunningCycleUsage(request) {
39
+ const providers = (0, invoice_line_items_2.getInvoiceLineItemsProviders)();
40
+ if (providers.length === 0)
41
+ return NO_USAGE;
42
+ const context = buildPreviewContext(request);
43
+ if (!context)
44
+ return NO_USAGE;
45
+ const quotes = await Promise.all(providers.map((provider) => quoteProviderLines(provider, context)));
46
+ if (quotes.some((quote) => quote === null))
47
+ return null;
48
+ return {
49
+ items: quotes.flatMap((quote) => quote ?? []),
50
+ usageThrough: context.periodEnd,
51
+ };
52
+ }
53
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/upcoming-invoice/usage.ts"],"names":[],"mappings":";;AAmFA,wDAeC;AA9FD,0FAAmG;AAEnG,uFAA8F;AAC9F,8DAI+B;AAC/B,yEAA8E;AAM9E,MAAM,yBAAyB,GAAG,WAAW,CAAC;AAiB9C,MAAM,QAAQ,GAAgB,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;AAEhE,SAAS,mBAAmB,CAC1B,OAA0B;IAE1B,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,IAAA,uCAAsB,EAC3B;QACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,GAAG,yBAAyB,GAAG,OAAO,CAAC,oBAAoB,EAAE;QACxE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ;QAChC,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,kBAAkB;QAC7C,SAAS,EAAE,OAAO,CAAC,GAAG;QACtB,SAAS,EAAE,IAAI;KAChB,EACD,OAAO,CAAC,YAAY,EACpB,OAAO,CAAC,oBAAoB,CAC7B,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,QAAkC,EAClC,OAAgC;IAEhC,MAAM,UAAU,GAAG,MAAM,IAAA,6CAAwB,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,QAAQ,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,SAAS,GAAG,IAAA,mDAA8B,EAC9C,QAAQ,CAAC,EAAE,EACX,UAAU,CAAC,SAAS,EACpB,IAAI,GAAG,EAAE,CACV,CAAC;IACF,IAAA,2CAAsB,EAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1E,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7E,OAAO,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3C,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW;QAC3C,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW;QACtC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,IAAA,0CAAqB,EAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;KACvD,CAAC,CAAC,CAAC;AACN,CAAC;AAQM,KAAK,UAAU,sBAAsB,CAC1C,OAA0B;IAE1B,MAAM,SAAS,GAAG,IAAA,iDAA4B,GAAE,CAAC;IACjD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CACnE,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,YAAY,EAAE,OAAO,CAAC,SAAS;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { TenantCustomerType } from "../db";
2
+ import type { CustomerBillingAddress } from "../stripe";
3
+ export interface BillingIdentityInput {
4
+ customerType?: string | null;
5
+ companyName?: string | null;
6
+ vatNumber?: string | null;
7
+ billingEmail?: string | null;
8
+ address?: CustomerBillingAddress;
9
+ }
10
+ export interface BillingIdentity {
11
+ customerType: TenantCustomerType;
12
+ companyName: string | null;
13
+ vatNumber: string | null;
14
+ billingEmail: string;
15
+ address: CustomerBillingAddress;
16
+ }
17
+ export type BillingIdentityField = "customerType" | "companyName" | "country" | "line1" | "postalCode" | "city" | "billingEmail";
18
+ export declare function findMissingBillingIdentityFields(identity: BillingIdentityInput): BillingIdentityField[];
19
+ export declare function parseBillingIdentity(identity: BillingIdentityInput): BillingIdentity;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findMissingBillingIdentityFields = findMissingBillingIdentityFields;
4
+ exports.parseBillingIdentity = parseBillingIdentity;
5
+ const interface_api_util_1 = require("@antelopejs/interface-api-util");
6
+ const HTTP_BAD_REQUEST = 400;
7
+ const BUSINESS_CUSTOMER_TYPE = "business";
8
+ const CUSTOMER_TYPES = new Set(["individual", "business"]);
9
+ const COUNTRY_CODE_PATTERN = /^[A-Z]{2}$/;
10
+ const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11
+ function trimmed(value) {
12
+ const result = value?.trim();
13
+ return result ? result : null;
14
+ }
15
+ function isBusiness(identity) {
16
+ return identity.customerType === BUSINESS_CUSTOMER_TYPE;
17
+ }
18
+ const FIELD_CHECKS = {
19
+ customerType: (identity) => CUSTOMER_TYPES.has(identity.customerType ?? ""),
20
+ companyName: (identity) => !isBusiness(identity) || !!trimmed(identity.companyName),
21
+ country: (identity) => COUNTRY_CODE_PATTERN.test(trimmed(identity.address?.country) ?? ""),
22
+ line1: (identity) => !!trimmed(identity.address?.line1),
23
+ postalCode: (identity) => !!trimmed(identity.address?.postalCode),
24
+ city: (identity) => !!trimmed(identity.address?.city),
25
+ billingEmail: (identity) => EMAIL_PATTERN.test(trimmed(identity.billingEmail) ?? ""),
26
+ };
27
+ function findMissingBillingIdentityFields(identity) {
28
+ return Object.keys(FIELD_CHECKS).filter((field) => !FIELD_CHECKS[field](identity));
29
+ }
30
+ function normalizeAddress(address) {
31
+ return {
32
+ line1: trimmed(address?.line1),
33
+ line2: trimmed(address?.line2),
34
+ postalCode: trimmed(address?.postalCode),
35
+ city: trimmed(address?.city),
36
+ state: trimmed(address?.state),
37
+ country: trimmed(address?.country),
38
+ };
39
+ }
40
+ function parseBillingIdentity(identity) {
41
+ (0, interface_api_util_1.assert)(findMissingBillingIdentityFields(identity).length === 0, HTTP_BAD_REQUEST, "saas.errors.billing.identity_incomplete");
42
+ const business = isBusiness(identity);
43
+ return {
44
+ customerType: identity.customerType,
45
+ companyName: business ? trimmed(identity.companyName) : null,
46
+ vatNumber: business ? trimmed(identity.vatNumber) : null,
47
+ billingEmail: trimmed(identity.billingEmail) ?? "",
48
+ address: normalizeAddress(identity.address),
49
+ };
50
+ }
51
+ //# sourceMappingURL=billing-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-identity.js","sourceRoot":"","sources":["../../src/workspaces/billing-identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type Plan } from "../db";
2
+ export declare function selectDefaultPlan(plans: Plan[], configuredSlug?: string): Plan | null;
3
+ export declare function resolveDefaultPlan(): Promise<Plan | null>;
4
+ export declare function ensureDefaultSubscription(tenantId: string, plan?: Plan | null): Promise<boolean>;
5
+ export declare function backfillDefaultSubscriptions(): Promise<number>;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectDefaultPlan = selectDefaultPlan;
4
+ exports.resolveDefaultPlan = resolveDefaultPlan;
5
+ exports.ensureDefaultSubscription = ensureDefaultSubscription;
6
+ exports.backfillDefaultSubscriptions = backfillDefaultSubscriptions;
7
+ const logging_1 = require("@antelopejs/interface-core/logging");
8
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
9
+ const db_1 = require("@antelopejs/interface-dms/db");
10
+ const tenant_lifecycle_1 = require("@antelopejs/interface-dms/tenant-lifecycle");
11
+ const billing_state_1 = require("../billing-state");
12
+ const config_1 = require("../config");
13
+ const db_2 = require("../db");
14
+ const free_workspace_guard_1 = require("./free-workspace-guard");
15
+ const LOG_PREFIX = "[dms-saas:default-plan]";
16
+ const ACTIVE_STATUS = "active";
17
+ const DEFAULT_PLAN_AUDIENCES = new Set(["any", "individual"]);
18
+ function isDefaultPlanCandidate(plan) {
19
+ return (plan.isActive &&
20
+ !plan.isDeleted &&
21
+ (0, free_workspace_guard_1.isFreePlan)(plan) &&
22
+ DEFAULT_PLAN_AUDIENCES.has(plan.audience));
23
+ }
24
+ function selectDefaultPlan(plans, configuredSlug) {
25
+ const candidates = plans
26
+ .filter(isDefaultPlanCandidate)
27
+ .sort((left, right) => left.order - right.order);
28
+ if (!configuredSlug)
29
+ return candidates[0] ?? null;
30
+ const configured = candidates.find((plan) => plan.slug === configuredSlug);
31
+ if (!configured) {
32
+ logging_1.Logging.Warn(`${LOG_PREFIX} defaultPlanSlug "${configuredSlug}" names no active free plan; falling back to the lowest-ordered one`);
33
+ }
34
+ return configured ?? candidates[0] ?? null;
35
+ }
36
+ let hasWarnedMissingPlan = false;
37
+ async function resolveDefaultPlan() {
38
+ const plans = await (0, interface_database_decorators_1.GetModel)(db_2.PlanModel).findActiveNotDeleted();
39
+ const plan = selectDefaultPlan(plans, (0, config_1.getDefaultPlanSlug)());
40
+ if (plan)
41
+ hasWarnedMissingPlan = false;
42
+ return plan;
43
+ }
44
+ function logMissingDefaultPlan() {
45
+ if (hasWarnedMissingPlan)
46
+ return;
47
+ hasWarnedMissingPlan = true;
48
+ logging_1.Logging.Warn(`${LOG_PREFIX} the catalogue has no active free plan: workspaces without a subscription stay plan-less until one is published`);
49
+ }
50
+ async function insertDefaultSubscription(tenantId, plan) {
51
+ const model = (0, interface_database_decorators_1.GetModel)(db_2.TenantSubscriptionModel, tenantId);
52
+ if (await model.findOne())
53
+ return false;
54
+ const now = new Date();
55
+ await model.insert([
56
+ {
57
+ _id: tenantId,
58
+ planId: plan._id,
59
+ status: ACTIVE_STATUS,
60
+ isComplimentary: false,
61
+ stripeCustomerId: null,
62
+ stripeSubscriptionId: null,
63
+ stripeCheckoutSessionId: null,
64
+ createdBy: null,
65
+ createdAt: now,
66
+ updatedAt: now,
67
+ },
68
+ ]);
69
+ return true;
70
+ }
71
+ async function ensureDefaultSubscription(tenantId, plan) {
72
+ const defaultPlan = plan === undefined ? await resolveDefaultPlan() : plan;
73
+ if (!defaultPlan) {
74
+ logMissingDefaultPlan();
75
+ return false;
76
+ }
77
+ const isAttached = await (0, tenant_lifecycle_1.runTenantLifecycleOperation)(tenantId, () => insertDefaultSubscription(tenantId, defaultPlan));
78
+ if (isAttached)
79
+ await (0, billing_state_1.recomputeTenantBillingState)(tenantId);
80
+ return isAttached;
81
+ }
82
+ async function attachToTenant(tenantId, plan) {
83
+ try {
84
+ return await ensureDefaultSubscription(tenantId, plan);
85
+ }
86
+ catch (error) {
87
+ logging_1.Logging.Error(`${LOG_PREFIX} could not cover workspace ${tenantId}`, error);
88
+ return false;
89
+ }
90
+ }
91
+ async function backfillDefaultSubscriptions() {
92
+ const plan = await resolveDefaultPlan();
93
+ if (!plan) {
94
+ logMissingDefaultPlan();
95
+ return 0;
96
+ }
97
+ const tenants = await (0, interface_database_decorators_1.GetModel)(db_1.TenantModel).table.pluck("_id").run();
98
+ let attachedCount = 0;
99
+ for (const tenant of tenants) {
100
+ if (tenant._id && (await attachToTenant(tenant._id, plan))) {
101
+ attachedCount++;
102
+ }
103
+ }
104
+ if (attachedCount > 0) {
105
+ logging_1.Logging.Info(`${LOG_PREFIX} attached plan "${plan.slug}" to ${attachedCount} workspace(s)`);
106
+ }
107
+ return attachedCount;
108
+ }
109
+ //# sourceMappingURL=default-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-plan.js","sourceRoot":"","sources":["../../src/workspaces/default-plan.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  export * from "./billing-profile";
2
+ export * from "./default-plan";
2
3
  export * from "./deletion";
3
4
  export * from "./free-workspace-guard";
5
+ export * from "./invitations";
4
6
  export * from "./provisioning";
5
7
  export * from "./registration-extras";
6
8
  export * from "./suspension";
@@ -15,8 +15,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./billing-profile"), exports);
18
+ __exportStar(require("./default-plan"), exports);
18
19
  __exportStar(require("./deletion"), exports);
19
20
  __exportStar(require("./free-workspace-guard"), exports);
21
+ __exportStar(require("./invitations"), exports);
20
22
  __exportStar(require("./provisioning"), exports);
21
23
  __exportStar(require("./registration-extras"), exports);
22
24
  __exportStar(require("./suspension"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workspaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,6CAA2B;AAC3B,yDAAuC;AACvC,iDAA+B;AAC/B,wDAAsC;AACtC,+CAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workspaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,iDAA+B;AAC/B,6CAA2B;AAC3B,yDAAuC;AACvC,gDAA8B;AAC9B,iDAA+B;AAC/B,wDAAsC;AACtC,+CAA6B"}
@@ -0,0 +1,26 @@
1
+ import type { User } from "@antelopejs/interface-dms/auth/db";
2
+ import { type UserInvite } from "@antelopejs/interface-dms/db";
3
+ export type InvitationEmailDelivery = "sent" | "failed";
4
+ export type InvitationStatus = "pending" | "expired";
5
+ export interface InvitationLink {
6
+ link: string;
7
+ expiresAt: Date;
8
+ }
9
+ interface InvitationSender {
10
+ workspaceName?: string;
11
+ inviterName?: string;
12
+ }
13
+ type DeliverableInvitation = Pick<UserInvite, "email" | "token" | "firstname" | "lastname" | "language">;
14
+ export interface ReissuedInvitation {
15
+ invite: UserInvite;
16
+ emailDelivery: InvitationEmailDelivery;
17
+ }
18
+ export declare function invitationStatusOf(invite: Pick<UserInvite, "expiresAt">, now?: Date): InvitationStatus;
19
+ export declare function buildInvitationLink(invite: Pick<UserInvite, "email" | "token" | "firstname" | "lastname">): Promise<string>;
20
+ export declare function inviterNameOf(user: Pick<User, "name">): string | undefined;
21
+ export declare function deliverInvitationEmail(invite: DeliverableInvitation, sender?: InvitationSender): Promise<InvitationEmailDelivery>;
22
+ export declare function countPendingInvitations(tenantId: string, now?: Date): Promise<number>;
23
+ export declare function findPendingOwnerInvite(tenantId: string): Promise<UserInvite | undefined>;
24
+ export declare function resendInvitation(tenantId: string, inviteId: string, inviterName?: string): Promise<ReissuedInvitation>;
25
+ export declare function resolveInvitationLink(tenantId: string, inviteId: string): Promise<InvitationLink>;
26
+ export {};
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invitationStatusOf = invitationStatusOf;
4
+ exports.buildInvitationLink = buildInvitationLink;
5
+ exports.inviterNameOf = inviterNameOf;
6
+ exports.deliverInvitationEmail = deliverInvitationEmail;
7
+ exports.countPendingInvitations = countPendingInvitations;
8
+ exports.findPendingOwnerInvite = findPendingOwnerInvite;
9
+ exports.resendInvitation = resendInvitation;
10
+ exports.resolveInvitationLink = resolveInvitationLink;
11
+ const interface_api_util_1 = require("@antelopejs/interface-api-util");
12
+ const logging_1 = require("@antelopejs/interface-core/logging");
13
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
14
+ const auth_1 = require("@antelopejs/interface-dms/auth");
15
+ const client_base_url_1 = require("@antelopejs/interface-dms/client-base-url");
16
+ const db_1 = require("@antelopejs/interface-dms/db");
17
+ const invite_resolution_1 = require("@antelopejs/interface-dms/invite-resolution");
18
+ const invites_1 = require("@antelopejs/interface-dms/invites");
19
+ const HTTP_NOT_FOUND = 404;
20
+ const SIGNUP_PATH = "/auth/signup";
21
+ function invitationStatusOf(invite, now = new Date()) {
22
+ return invite.expiresAt.getTime() > now.getTime() ? "pending" : "expired";
23
+ }
24
+ async function buildInvitationLink(invite) {
25
+ const params = new URLSearchParams({
26
+ token: invite.token,
27
+ email: invite.email,
28
+ });
29
+ const name = (0, invites_1.inviteeDisplayName)(invite.firstname, invite.lastname);
30
+ if (name)
31
+ params.set("name", name);
32
+ const baseUrl = (await (0, client_base_url_1.GetClientBaseUrl)()) ?? "";
33
+ return `${baseUrl}${SIGNUP_PATH}?${params.toString()}`;
34
+ }
35
+ function inviterNameOf(user) {
36
+ return user.name?.trim() || undefined;
37
+ }
38
+ function invitationEmailContext(invite, sender) {
39
+ return {
40
+ workspaceName: sender.workspaceName,
41
+ inviterName: sender.inviterName,
42
+ language: invite.language,
43
+ };
44
+ }
45
+ async function deliverInvitationEmail(invite, sender = {}) {
46
+ try {
47
+ await (0, auth_1.sendAdminInviteEmail)(invite.email, invite.token, (0, invites_1.inviteeDisplayName)(invite.firstname, invite.lastname), invitationEmailContext(invite, sender));
48
+ return "sent";
49
+ }
50
+ catch (error) {
51
+ logging_1.Logging.Error(`[dms-saas] invitation email to "${invite.email}" could not be sent:`, error);
52
+ return "failed";
53
+ }
54
+ }
55
+ async function countPendingInvitations(tenantId, now = new Date()) {
56
+ const invites = await (0, interface_database_decorators_1.GetModel)(db_1.UserInviteModel, tenantId).getAll();
57
+ return invites.filter((invite) => invitationStatusOf(invite, now) === "pending").length;
58
+ }
59
+ async function findPendingOwnerInvite(tenantId) {
60
+ const invites = await (0, interface_database_decorators_1.GetModel)(db_1.UserInviteModel, tenantId).getAll();
61
+ return invites
62
+ .filter((invite) => invite.asTenantOwner)
63
+ .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())[0];
64
+ }
65
+ async function loadActionableInvite(tenantId, inviteId) {
66
+ const invite = await (0, invite_resolution_1.loadInviteForAction)(tenantId, inviteId);
67
+ (0, interface_api_util_1.assert)(invite, HTTP_NOT_FOUND, "saas.errors.invitations.not_found");
68
+ await (0, invite_resolution_1.assertInviteReady)(tenantId, invite);
69
+ return invite;
70
+ }
71
+ async function renewInvite(tenantId, invite) {
72
+ const { inviteId } = await (0, invites_1.createUserInviteToken)({
73
+ tenantId,
74
+ replacesInvite: invite,
75
+ email: invite.email,
76
+ firstname: invite.firstname,
77
+ lastname: invite.lastname,
78
+ language: invite.language,
79
+ roleIds: invite.roles_ids,
80
+ asTenantOwner: invite.asTenantOwner,
81
+ skipEmailValidation: invite.skipEmailValidation,
82
+ extensions: invite.extensions ?? undefined,
83
+ replacementReason: "resent",
84
+ });
85
+ const renewed = await (0, interface_database_decorators_1.GetModel)(db_1.UserInviteModel, tenantId).get(inviteId);
86
+ if (!renewed)
87
+ throw new Error("Renewed invitation was not persisted");
88
+ return renewed;
89
+ }
90
+ async function workspaceNameOf(tenantId) {
91
+ const tenant = await (0, interface_database_decorators_1.GetModel)(db_1.TenantModel).get(tenantId);
92
+ return tenant?.name || undefined;
93
+ }
94
+ async function resendInvitation(tenantId, inviteId, inviterName) {
95
+ const invite = await renewInvite(tenantId, await loadActionableInvite(tenantId, inviteId));
96
+ const emailDelivery = await deliverInvitationEmail(invite, {
97
+ workspaceName: await workspaceNameOf(tenantId),
98
+ inviterName,
99
+ });
100
+ return { invite, emailDelivery };
101
+ }
102
+ async function resolveInvitationLink(tenantId, inviteId) {
103
+ const stored = await loadActionableInvite(tenantId, inviteId);
104
+ const invite = invitationStatusOf(stored) === "pending"
105
+ ? stored
106
+ : await renewInvite(tenantId, stored);
107
+ return {
108
+ link: await buildInvitationLink(invite),
109
+ expiresAt: invite.expiresAt,
110
+ };
111
+ }
112
+ //# sourceMappingURL=invitations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invitations.js","sourceRoot":"","sources":["../../src/workspaces/invitations.ts"],"names":[],"mappings":"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"}
@@ -11,13 +11,12 @@ export interface WorkspaceBillingProfile {
11
11
  export interface WorkspaceProvisioningPayload extends WorkspaceBillingProfile {
12
12
  workspaceName: string;
13
13
  planId: string;
14
- paymentMethodId: string;
14
+ paymentMethodId?: string;
15
15
  extras?: Record<string, unknown>;
16
16
  }
17
17
  export interface StripeCustomerProfile extends WorkspaceBillingProfile {
18
18
  email: string;
19
19
  fallbackName: string;
20
- paymentMethodId: string;
21
20
  }
22
21
  export interface WorkspaceProvisioningHandles {
23
22
  mustPreserveWorkspace?: boolean;
@@ -45,5 +44,6 @@ export interface ProvisionedWorkspace {
45
44
  }
46
45
  export declare function assertBillingCountry(address: WorkspaceAddressInput | undefined): void;
47
46
  export declare function ensurePlanIsAvailableForCustomer(planId: string, customerType: WorkspaceCustomerType): Promise<Plan>;
48
- export declare function resolveCardDetails(paymentMethodId: string): Promise<CardDetails>;
47
+ export declare function resolveCardDetails(paymentMethodId: string | undefined): Promise<CardDetails>;
48
+ export declare function resolveRegistrationPlan(): Promise<Plan>;
49
49
  export declare function provisionWorkspace(input: WorkspaceProvisioningInput): Promise<ProvisionedWorkspace>;