@umituz/web-payment 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +349 -2
  3. package/dist/billing-adapter.interface-CDkeeowZ.d.mts +94 -0
  4. package/dist/billing-adapter.interface-m7yE50I0.d.ts +94 -0
  5. package/dist/billing-cycle.enum--hJRYlgP.d.mts +10 -0
  6. package/dist/billing-cycle.enum--hJRYlgP.d.ts +10 -0
  7. package/dist/billing-env-D4YjvA3M.d.mts +8 -0
  8. package/dist/billing-env-D4YjvA3M.d.ts +8 -0
  9. package/dist/checkout-metadata-D7Wp_DAD.d.mts +27 -0
  10. package/dist/checkout-metadata-D7Wp_DAD.d.ts +27 -0
  11. package/dist/chunk-2KV7JFYF.mjs +61 -0
  12. package/dist/chunk-2NH5DOLT.mjs +101 -0
  13. package/dist/chunk-3AXPZOCV.mjs +106 -0
  14. package/dist/chunk-4N3BASZ6.mjs +51 -0
  15. package/dist/chunk-NHKK3ENU.mjs +1128 -0
  16. package/dist/chunk-PIWNUAKW.mjs +30 -0
  17. package/dist/chunk-QFB7AOSQ.mjs +33 -0
  18. package/dist/chunk-RQTMBR74.mjs +30 -0
  19. package/dist/chunk-U45FS4FF.mjs +110 -0
  20. package/dist/chunk-X6R76FZT.mjs +0 -0
  21. package/dist/chunk-XQ2HJTTA.mjs +252 -0
  22. package/dist/core.d.mts +17 -0
  23. package/dist/core.d.ts +17 -0
  24. package/dist/core.js +425 -0
  25. package/dist/core.mjs +66 -0
  26. package/dist/http.d.mts +12 -0
  27. package/dist/http.d.ts +12 -0
  28. package/dist/http.js +115 -0
  29. package/dist/http.mjs +88 -0
  30. package/dist/index.d.mts +17 -0
  31. package/dist/index.d.ts +17 -0
  32. package/dist/index.js +1929 -0
  33. package/dist/index.mjs +153 -0
  34. package/dist/memory.d.mts +14 -0
  35. package/dist/memory.d.ts +14 -0
  36. package/dist/memory.js +130 -0
  37. package/dist/memory.mjs +6 -0
  38. package/dist/portal.d.mts +445 -0
  39. package/dist/portal.d.ts +445 -0
  40. package/dist/portal.js +2927 -0
  41. package/dist/portal.mjs +2737 -0
  42. package/dist/product.mapper-CnY1ISOp.d.ts +97 -0
  43. package/dist/product.mapper-noVl-sel.d.mts +97 -0
  44. package/dist/products.d.mts +64 -0
  45. package/dist/products.d.ts +64 -0
  46. package/dist/products.js +370 -0
  47. package/dist/products.mjs +21 -0
  48. package/dist/react.d.mts +182 -0
  49. package/dist/react.d.ts +182 -0
  50. package/dist/react.js +1874 -0
  51. package/dist/react.mjs +105 -0
  52. package/dist/server.d.mts +177 -0
  53. package/dist/server.d.ts +177 -0
  54. package/dist/server.js +622 -0
  55. package/dist/server.mjs +417 -0
  56. package/dist/visual-tokens-BCLVR85G.d.mts +94 -0
  57. package/dist/visual-tokens-BCLVR85G.d.ts +94 -0
  58. package/package.json +122 -4
  59. package/src/core.ts +81 -0
  60. package/src/domain/entities/cancellation.entity.ts +28 -0
  61. package/src/domain/entities/checkout.entity.ts +21 -0
  62. package/src/domain/entities/index.ts +10 -0
  63. package/src/domain/entities/order.entity.ts +15 -0
  64. package/src/domain/entities/product.entity.ts +16 -0
  65. package/src/domain/entities/subscription.entity.ts +24 -0
  66. package/src/domain/entities/sync.entity.ts +4 -0
  67. package/src/domain/enums/amount-type.enum.ts +10 -0
  68. package/src/domain/enums/billing-cycle.enum.ts +30 -0
  69. package/src/domain/enums/index.ts +5 -0
  70. package/src/domain/enums/payment-provider.enum.ts +14 -0
  71. package/src/domain/enums/subscription-status.enum.ts +32 -0
  72. package/src/domain/index.ts +5 -0
  73. package/src/domain/interfaces/billing-adapter.interface.ts +18 -0
  74. package/src/domain/interfaces/index.ts +1 -0
  75. package/src/domain/mappers/product.mapper.ts +176 -0
  76. package/src/domain/utils/minor-units.ts +20 -0
  77. package/src/domain/utils/percent-discount.ts +17 -0
  78. package/src/http.ts +3 -0
  79. package/src/index.ts +12 -0
  80. package/src/infrastructure/browser/hosted-checkout.ts +26 -0
  81. package/src/infrastructure/config/billing-env.ts +31 -0
  82. package/src/infrastructure/constants/billing.constants.ts +10 -0
  83. package/src/infrastructure/http/http-client.ts +83 -0
  84. package/src/infrastructure/pagination/page-iterator.ts +43 -0
  85. package/src/infrastructure/query/query-builder.ts +26 -0
  86. package/src/infrastructure/services/billing.client.ts +300 -0
  87. package/src/infrastructure/services/create-billing-client.ts +23 -0
  88. package/src/infrastructure/services/http/create-http-adapter.ts +123 -0
  89. package/src/infrastructure/services/memory/create-memory-adapter.ts +126 -0
  90. package/src/infrastructure/services/product.repository.ts +198 -0
  91. package/src/infrastructure/utils/checkout-metadata.ts +55 -0
  92. package/src/infrastructure/utils/date-renderer.ts +53 -0
  93. package/src/infrastructure/utils/money-formatter.ts +39 -0
  94. package/src/infrastructure/utils/normalization.util.ts +22 -0
  95. package/src/infrastructure/utils/pagination-clamp.ts +11 -0
  96. package/src/infrastructure/utils/receipt.util.ts +6 -0
  97. package/src/infrastructure/utils/security.util.ts +23 -0
  98. package/src/infrastructure/utils/type-guards.util.ts +23 -0
  99. package/src/infrastructure/utils/validation.util.ts +10 -0
  100. package/src/infrastructure/webhook/parse-event.ts +135 -0
  101. package/src/infrastructure/webhook/verify-webhook.ts +124 -0
  102. package/src/memory.ts +3 -0
  103. package/src/portal.ts +2 -0
  104. package/src/presentation/components/BillingHistoryList.tsx +172 -0
  105. package/src/presentation/components/BillingProvider.tsx +179 -0
  106. package/src/presentation/components/CancelSubscriptionButton.tsx +155 -0
  107. package/src/presentation/components/CheckoutButton.tsx +76 -0
  108. package/src/presentation/components/CustomerPortalLink.tsx +71 -0
  109. package/src/presentation/components/PricingTable.tsx +225 -0
  110. package/src/presentation/components/SubscriptionStatusBadge.tsx +102 -0
  111. package/src/presentation/context/billing-context.ts +30 -0
  112. package/src/presentation/hooks/useBilling.ts +3 -0
  113. package/src/presentation/hooks/useCancelSubscription.ts +47 -0
  114. package/src/presentation/hooks/useCheckoutButton.ts +49 -0
  115. package/src/presentation/hooks/useProducts.ts +76 -0
  116. package/src/presentation/navigation/navigation.strategy.ts +16 -0
  117. package/src/presentation/portal/TurnkeyBillingPage.tsx +144 -0
  118. package/src/presentation/portal/components/BillingLayout.tsx +163 -0
  119. package/src/presentation/portal/components/BillingPage.tsx +22 -0
  120. package/src/presentation/portal/components/BillingPortal.tsx +248 -0
  121. package/src/presentation/portal/components/InvoiceCard.tsx +275 -0
  122. package/src/presentation/portal/components/OverviewTab.tsx +137 -0
  123. package/src/presentation/portal/components/PaymentMethodsList.tsx +268 -0
  124. package/src/presentation/portal/components/PlanComparison.tsx +405 -0
  125. package/src/presentation/portal/components/PlanTab.tsx +197 -0
  126. package/src/presentation/portal/components/PortalButton.tsx +89 -0
  127. package/src/presentation/portal/components/PortalSpinner.tsx +30 -0
  128. package/src/presentation/portal/components/UsageCard.tsx +158 -0
  129. package/src/presentation/portal/components/index.ts +11 -0
  130. package/src/presentation/portal/constants.ts +44 -0
  131. package/src/presentation/portal/create-portal-client.ts +202 -0
  132. package/src/presentation/portal/hooks/index.ts +3 -0
  133. package/src/presentation/portal/hooks/useBilling.ts +240 -0
  134. package/src/presentation/portal/index.ts +97 -0
  135. package/src/presentation/portal/labels.tsx +218 -0
  136. package/src/presentation/portal/styles.ts +70 -0
  137. package/src/presentation/portal/types.ts +213 -0
  138. package/src/presentation/portal/utils/billing.ts +193 -0
  139. package/src/presentation/portal/utils/index.ts +27 -0
  140. package/src/presentation/portal/utils/plans.ts +71 -0
  141. package/src/presentation/theme/visual-tokens.ts +103 -0
  142. package/src/presentation/utils/cancellation-reason-catalog.ts +18 -0
  143. package/src/presentation/utils/checkout-button-visual.ts +50 -0
  144. package/src/presentation/utils/inline-error-visual.ts +21 -0
  145. package/src/presentation/utils/product-pricing.ts +33 -0
  146. package/src/presentation/utils/status-label.ts +23 -0
  147. package/src/presentation/utils/status-tone.ts +25 -0
  148. package/src/products.ts +20 -0
  149. package/src/react.tsx +63 -0
  150. package/src/server.ts +79 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,153 @@
1
+ import "./chunk-X6R76FZT.mjs";
2
+ import {
3
+ BillingContext,
4
+ BillingHistoryList,
5
+ BillingProvider,
6
+ CANCELLATION_REASON_CATALOG,
7
+ CancelSubscriptionButton,
8
+ CheckoutButton,
9
+ CustomerPortalLink,
10
+ PricingTable,
11
+ SubscriptionStatusBadge,
12
+ isInsecureUrl,
13
+ isLoopbackHost,
14
+ useBilling,
15
+ useCancelSubscription,
16
+ useCheckoutButton,
17
+ useProducts
18
+ } from "./chunk-NHKK3ENU.mjs";
19
+ import {
20
+ CANCELLATION_REASON,
21
+ CANCELLATION_REASON_VALUES,
22
+ POLAR_AMOUNT_TYPE,
23
+ applyPercentDiscount,
24
+ normalizeCouponCode
25
+ } from "./chunk-4N3BASZ6.mjs";
26
+ import {
27
+ FREE_SUBSCRIPTION_STATUS,
28
+ createMemoryBillingAdapter,
29
+ isActiveSubscription
30
+ } from "./chunk-3AXPZOCV.mjs";
31
+ import {
32
+ NoopNavigationStrategy,
33
+ TONE_PAIRS,
34
+ VisualTokens,
35
+ WindowNavigationStrategy
36
+ } from "./chunk-2NH5DOLT.mjs";
37
+ import {
38
+ CHECKOUT_ID_PARAM
39
+ } from "./chunk-QFB7AOSQ.mjs";
40
+ import {
41
+ PAYMENT_PROVIDER,
42
+ PAYMENT_PROVIDER_VALUES,
43
+ buildCheckoutMetadata,
44
+ formatReceiptNumber,
45
+ isKnownPaymentProvider,
46
+ readCheckoutMetadata
47
+ } from "./chunk-2KV7JFYF.mjs";
48
+ import {
49
+ minorUnitDivisor,
50
+ toMajorUnits,
51
+ toMinorUnits
52
+ } from "./chunk-PIWNUAKW.mjs";
53
+ import {
54
+ BillingApiError,
55
+ FetchHttpClient,
56
+ ProductRepository,
57
+ getAllProducts,
58
+ getProductById,
59
+ getProducts,
60
+ isBillingApiError
61
+ } from "./chunk-XQ2HJTTA.mjs";
62
+ import {
63
+ SUBSCRIPTION_STATUS,
64
+ SUBSCRIPTION_STATUS_VALUES,
65
+ isKnownSubscriptionStatus,
66
+ mapProduct,
67
+ mapProductList
68
+ } from "./chunk-U45FS4FF.mjs";
69
+ import {
70
+ BILLING_CYCLE,
71
+ BILLING_CYCLE_VALUES,
72
+ isKnownBillingCycle,
73
+ parseBillingCycle
74
+ } from "./chunk-RQTMBR74.mjs";
75
+
76
+ // src/infrastructure/browser/hosted-checkout.ts
77
+ function isSafeCheckoutUrl(url) {
78
+ if (typeof url !== "string" || url.length === 0) return false;
79
+ if (url.startsWith("https://")) return true;
80
+ return isInsecureUrl(url) && isLoopbackHost(url);
81
+ }
82
+ function redirectToHostedCheckout(url) {
83
+ if (!isSafeCheckoutUrl(url)) throw new Error("invalid_checkout_url");
84
+ window.location.assign(url);
85
+ }
86
+ function checkoutIdFromLocationSearch(search) {
87
+ const withoutLeading = search.startsWith("?") ? search.slice(1) : search;
88
+ for (const pair of withoutLeading.split("&")) {
89
+ const separator = pair.indexOf("=");
90
+ if (separator === -1) continue;
91
+ if (pair.slice(0, separator) !== CHECKOUT_ID_PARAM) continue;
92
+ const value = pair.slice(separator + 1);
93
+ if (value.length === 0) return null;
94
+ return decodeURIComponent(value);
95
+ }
96
+ return null;
97
+ }
98
+ export {
99
+ BILLING_CYCLE,
100
+ BILLING_CYCLE_VALUES,
101
+ BillingApiError,
102
+ BillingContext,
103
+ BillingHistoryList,
104
+ BillingProvider,
105
+ CANCELLATION_REASON,
106
+ CANCELLATION_REASON_CATALOG,
107
+ CANCELLATION_REASON_VALUES,
108
+ CHECKOUT_ID_PARAM,
109
+ CancelSubscriptionButton,
110
+ CheckoutButton,
111
+ CustomerPortalLink,
112
+ FREE_SUBSCRIPTION_STATUS,
113
+ FetchHttpClient,
114
+ NoopNavigationStrategy,
115
+ PAYMENT_PROVIDER,
116
+ PAYMENT_PROVIDER_VALUES,
117
+ POLAR_AMOUNT_TYPE,
118
+ PricingTable,
119
+ ProductRepository,
120
+ SUBSCRIPTION_STATUS,
121
+ SUBSCRIPTION_STATUS_VALUES,
122
+ SubscriptionStatusBadge,
123
+ TONE_PAIRS,
124
+ VisualTokens,
125
+ WindowNavigationStrategy,
126
+ applyPercentDiscount,
127
+ buildCheckoutMetadata,
128
+ checkoutIdFromLocationSearch,
129
+ createMemoryBillingAdapter,
130
+ formatReceiptNumber,
131
+ getAllProducts,
132
+ getProductById,
133
+ getProducts,
134
+ isActiveSubscription,
135
+ isBillingApiError,
136
+ isKnownBillingCycle,
137
+ isKnownPaymentProvider,
138
+ isKnownSubscriptionStatus,
139
+ isSafeCheckoutUrl,
140
+ mapProduct,
141
+ mapProductList,
142
+ minorUnitDivisor,
143
+ normalizeCouponCode,
144
+ parseBillingCycle,
145
+ readCheckoutMetadata,
146
+ redirectToHostedCheckout,
147
+ toMajorUnits,
148
+ toMinorUnits,
149
+ useBilling,
150
+ useCancelSubscription,
151
+ useCheckoutButton,
152
+ useProducts
153
+ };
@@ -0,0 +1,14 @@
1
+ import { g as SubscriptionStatus, O as OrderItem, d as CheckoutParams, c as CancellationReason, B as BillingAdapter } from './billing-adapter.interface-CDkeeowZ.mjs';
2
+ import './billing-cycle.enum--hJRYlgP.mjs';
3
+
4
+ interface MemoryAdapterConfig {
5
+ initialStatus?: Partial<SubscriptionStatus>;
6
+ initialHistory?: OrderItem[];
7
+ checkoutUrlBase?: string;
8
+ portalUrl?: string;
9
+ onCheckout?: (params: CheckoutParams) => void;
10
+ onCancel?: (reason?: CancellationReason) => void;
11
+ }
12
+ declare function createMemoryBillingAdapter(config?: MemoryAdapterConfig): BillingAdapter;
13
+
14
+ export { type MemoryAdapterConfig, createMemoryBillingAdapter };
@@ -0,0 +1,14 @@
1
+ import { g as SubscriptionStatus, O as OrderItem, d as CheckoutParams, c as CancellationReason, B as BillingAdapter } from './billing-adapter.interface-m7yE50I0.js';
2
+ import './billing-cycle.enum--hJRYlgP.js';
3
+
4
+ interface MemoryAdapterConfig {
5
+ initialStatus?: Partial<SubscriptionStatus>;
6
+ initialHistory?: OrderItem[];
7
+ checkoutUrlBase?: string;
8
+ portalUrl?: string;
9
+ onCheckout?: (params: CheckoutParams) => void;
10
+ onCancel?: (reason?: CancellationReason) => void;
11
+ }
12
+ declare function createMemoryBillingAdapter(config?: MemoryAdapterConfig): BillingAdapter;
13
+
14
+ export { type MemoryAdapterConfig, createMemoryBillingAdapter };
package/dist/memory.js ADDED
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/memory.ts
21
+ var memory_exports = {};
22
+ __export(memory_exports, {
23
+ createMemoryBillingAdapter: () => createMemoryBillingAdapter
24
+ });
25
+ module.exports = __toCommonJS(memory_exports);
26
+
27
+ // src/domain/entities/subscription.entity.ts
28
+ var FREE_SUBSCRIPTION_STATUS = Object.freeze({
29
+ plan: "free",
30
+ subscriptionStatus: "none"
31
+ });
32
+ function isActiveSubscription(status) {
33
+ return status.subscriptionStatus === "active" || status.subscriptionStatus === "trialing";
34
+ }
35
+
36
+ // src/infrastructure/services/memory/create-memory-adapter.ts
37
+ function createMemoryBillingAdapter(config = {}) {
38
+ let status = {
39
+ plan: "free",
40
+ subscriptionStatus: "none",
41
+ billingCycle: "monthly",
42
+ cancelAtPeriodEnd: false,
43
+ ...config.initialStatus
44
+ };
45
+ const history = config.initialHistory ? [...config.initialHistory] : [];
46
+ const pending = /* @__PURE__ */ new Map();
47
+ let sequence = 0;
48
+ function checkoutUrl(checkout) {
49
+ if (checkout.params.successUrl) {
50
+ return checkout.params.successUrl.replace("{CHECKOUT_ID}", checkout.id);
51
+ }
52
+ const base = config.checkoutUrlBase ?? "https://checkout.example";
53
+ return `${base.replace(/\/$/, "")}/${checkout.id}`;
54
+ }
55
+ function fulfill(checkout) {
56
+ const planName = checkout.params.planKey ?? checkout.params.productId ?? checkout.params.productKey ?? "default";
57
+ return {
58
+ ...status,
59
+ plan: planName,
60
+ subscriptionStatus: "active",
61
+ subscriptionId: `sub_${checkout.id.slice(4)}`,
62
+ billingCycle: checkout.params.billingCycle ?? status.billingCycle,
63
+ cancelAtPeriodEnd: false,
64
+ currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3).toISOString()
65
+ };
66
+ }
67
+ return {
68
+ async getStatus(_userId) {
69
+ return { ...status };
70
+ },
71
+ async createCheckout(params) {
72
+ config.onCheckout?.(params);
73
+ sequence += 1;
74
+ const checkout = {
75
+ id: `chk_${Date.now()}_${sequence}`,
76
+ params
77
+ };
78
+ pending.set(checkout.id, checkout);
79
+ return {
80
+ id: checkout.id,
81
+ url: checkoutUrl(checkout)
82
+ };
83
+ },
84
+ async syncSubscription(_userId, checkoutId) {
85
+ const checkout = checkoutId ? pending.get(checkoutId) : void 0;
86
+ const last = checkout ? void 0 : [...pending.values()].pop();
87
+ const target = checkout ?? last;
88
+ if (!target) {
89
+ return { synced: false, plan: status.plan };
90
+ }
91
+ status = fulfill(target);
92
+ pending.delete(target.id);
93
+ history.unshift({
94
+ id: `ord_${target.id}`,
95
+ amount: 0,
96
+ currency: "usd",
97
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
98
+ productName: target.params.planKey ?? target.params.productId,
99
+ status: "paid",
100
+ paid: true
101
+ });
102
+ return { synced: true, plan: status.plan };
103
+ },
104
+ async getBillingHistory(_userId) {
105
+ return [...history];
106
+ },
107
+ async cancelSubscription(reason) {
108
+ config.onCancel?.(reason);
109
+ if (!isActiveSubscription(status)) {
110
+ return { success: false };
111
+ }
112
+ status = {
113
+ ...status,
114
+ subscriptionStatus: "canceled",
115
+ cancelAtPeriodEnd: true
116
+ };
117
+ return {
118
+ success: true,
119
+ endsAt: status.currentPeriodEnd ?? (/* @__PURE__ */ new Date()).toISOString()
120
+ };
121
+ },
122
+ async getPortalUrl(_userId) {
123
+ return config.portalUrl ?? "https://portal.example/billing";
124
+ }
125
+ };
126
+ }
127
+ // Annotate the CommonJS export names for ESM import in node:
128
+ 0 && (module.exports = {
129
+ createMemoryBillingAdapter
130
+ });
@@ -0,0 +1,6 @@
1
+ import {
2
+ createMemoryBillingAdapter
3
+ } from "./chunk-3AXPZOCV.mjs";
4
+ export {
5
+ createMemoryBillingAdapter
6
+ };