unthor-sdk 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.
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { useCheckoutEmbedControls } from '@whop/checkout/react';
3
+ export { useCheckoutEmbedControls } from '@whop/checkout/react';
4
+
5
+ interface UnthorCheckoutEmbedLabels {
6
+ initializing?: string;
7
+ processing?: string;
8
+ payNow?: string;
9
+ secured?: string;
10
+ pciDSS?: string;
11
+ orderProcessedBy?: string;
12
+ privacy?: string;
13
+ terms?: string;
14
+ }
15
+ interface UnthorCheckoutEmbedProps {
16
+ sessionId?: string;
17
+ membershipId?: string;
18
+ licenseId?: string;
19
+ theme?: 'light' | 'dark' | 'system';
20
+ environment?: 'production' | 'sandbox';
21
+ prefill?: any;
22
+ labels?: UnthorCheckoutEmbedLabels;
23
+ onStateChange?: (state: any) => void;
24
+ onComplete?: (id: string, extra?: any) => void;
25
+ onAddressValidationError?: (error: any) => void;
26
+ [key: string]: any;
27
+ }
28
+ /**
29
+ * Custom Embedded Checkout component for Unthor.
30
+ * Wraps WhopCheckoutEmbed with fully customized Unthor branding, masking logic, and visual assets.
31
+ */
32
+ declare const UnthorCheckoutEmbed: React.ForwardRefExoticComponent<Omit<UnthorCheckoutEmbedProps, "ref"> & React.RefAttributes<any>>;
33
+ /**
34
+ * Hook to access the controls of the checkout embed.
35
+ */
36
+ declare const useUnthorCheckoutEmbedControls: typeof useCheckoutEmbedControls;
37
+
38
+ export { UnthorCheckoutEmbed, type UnthorCheckoutEmbedLabels, type UnthorCheckoutEmbedProps, useUnthorCheckoutEmbedControls };
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { useCheckoutEmbedControls } from '@whop/checkout/react';
3
+ export { useCheckoutEmbedControls } from '@whop/checkout/react';
4
+
5
+ interface UnthorCheckoutEmbedLabels {
6
+ initializing?: string;
7
+ processing?: string;
8
+ payNow?: string;
9
+ secured?: string;
10
+ pciDSS?: string;
11
+ orderProcessedBy?: string;
12
+ privacy?: string;
13
+ terms?: string;
14
+ }
15
+ interface UnthorCheckoutEmbedProps {
16
+ sessionId?: string;
17
+ membershipId?: string;
18
+ licenseId?: string;
19
+ theme?: 'light' | 'dark' | 'system';
20
+ environment?: 'production' | 'sandbox';
21
+ prefill?: any;
22
+ labels?: UnthorCheckoutEmbedLabels;
23
+ onStateChange?: (state: any) => void;
24
+ onComplete?: (id: string, extra?: any) => void;
25
+ onAddressValidationError?: (error: any) => void;
26
+ [key: string]: any;
27
+ }
28
+ /**
29
+ * Custom Embedded Checkout component for Unthor.
30
+ * Wraps WhopCheckoutEmbed with fully customized Unthor branding, masking logic, and visual assets.
31
+ */
32
+ declare const UnthorCheckoutEmbed: React.ForwardRefExoticComponent<Omit<UnthorCheckoutEmbedProps, "ref"> & React.RefAttributes<any>>;
33
+ /**
34
+ * Hook to access the controls of the checkout embed.
35
+ */
36
+ declare const useUnthorCheckoutEmbedControls: typeof useCheckoutEmbedControls;
37
+
38
+ export { UnthorCheckoutEmbed, type UnthorCheckoutEmbedLabels, type UnthorCheckoutEmbedProps, useUnthorCheckoutEmbedControls };
@@ -0,0 +1,228 @@
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/checkout-react.tsx
21
+ var checkout_react_exports = {};
22
+ __export(checkout_react_exports, {
23
+ UnthorCheckoutEmbed: () => UnthorCheckoutEmbed,
24
+ useCheckoutEmbedControls: () => import_react2.useCheckoutEmbedControls,
25
+ useUnthorCheckoutEmbedControls: () => useUnthorCheckoutEmbedControls
26
+ });
27
+ module.exports = __toCommonJS(checkout_react_exports);
28
+ var import_react = require("react");
29
+ var import_react2 = require("@whop/checkout/react");
30
+ var import_jsx_runtime = require("react/jsx-runtime");
31
+ var Spinner = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
32
+ "svg",
33
+ {
34
+ className: "animate-spin h-8 w-8 text-zinc-400 dark:text-zinc-600",
35
+ xmlns: "http://www.w3.org/2000/svg",
36
+ fill: "none",
37
+ viewBox: "0 0 24 24",
38
+ children: [
39
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
40
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
41
+ "path",
42
+ {
43
+ className: "opacity-75",
44
+ fill: "currentColor",
45
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
46
+ }
47
+ )
48
+ ]
49
+ }
50
+ );
51
+ var MiniSpinner = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
52
+ "svg",
53
+ {
54
+ className: "animate-spin h-4 w-4 text-current",
55
+ xmlns: "http://www.w3.org/2000/svg",
56
+ fill: "none",
57
+ viewBox: "0 0 24 24",
58
+ children: [
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
61
+ "path",
62
+ {
63
+ className: "opacity-75",
64
+ fill: "currentColor",
65
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
66
+ }
67
+ )
68
+ ]
69
+ }
70
+ );
71
+ var ShieldCheckIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
72
+ "svg",
73
+ {
74
+ className: "w-4 h-4 text-green-600 dark:text-green-400",
75
+ xmlns: "http://www.w3.org/2000/svg",
76
+ viewBox: "0 0 24 24",
77
+ fill: "none",
78
+ stroke: "currentColor",
79
+ strokeWidth: "2.5",
80
+ strokeLinecap: "round",
81
+ strokeLinejoin: "round",
82
+ children: [
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 13c0 5-3.5 7.5-7.66 9.7a1 1 0 0 1-.68 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 .76-.97l8-2a1 1 0 0 1 .48 0l8 2A1 1 0 0 1 20 6z" }),
84
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9 12 2 2 4-4" })
85
+ ]
86
+ }
87
+ );
88
+ var defaultLabels = {
89
+ initializing: "Initializing checkout...",
90
+ processing: "Processing...",
91
+ payNow: "Pay now",
92
+ secured: "Secured payment",
93
+ pciDSS: "PCI-DSS Compliant",
94
+ orderProcessedBy: "Order processed by unthor.com",
95
+ privacy: "Privacy Policy",
96
+ terms: "Terms of Service"
97
+ };
98
+ var UnthorCheckoutEmbed = (0, import_react.forwardRef)(({
99
+ labels: customLabels,
100
+ environment = "production",
101
+ onStateChange,
102
+ theme = "light",
103
+ ...props
104
+ }, ref) => {
105
+ const mergedLabels = { ...defaultLabels, ...customLabels };
106
+ const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
107
+ const internalRef = (0, import_react2.useCheckoutEmbedControls)();
108
+ (0, import_react.useImperativeHandle)(ref, () => internalRef.current);
109
+ const handlePayNow = () => {
110
+ setIsSubmitting(true);
111
+ internalRef.current?.submit();
112
+ };
113
+ const handleStateChange = (state) => {
114
+ if (state === "loading") {
115
+ setIsSubmitting(true);
116
+ } else {
117
+ setIsSubmitting(false);
118
+ }
119
+ if (onStateChange) {
120
+ onStateChange(state);
121
+ }
122
+ };
123
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full h-full min-h-[500px] relative group/checkout overflow-hidden pb-32 unthor-checkout-container", children: [
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
125
+ @keyframes unthorFadeInRight {
126
+ from { opacity: 0; transform: translateX(20px); }
127
+ to { opacity: 1; transform: translateX(0); }
128
+ }
129
+ @keyframes unthorFadeIn {
130
+ from { opacity: 0; }
131
+ to { opacity: 1; }
132
+ }
133
+ .unthor-checkout-container {
134
+ animation: unthorFadeInRight 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
135
+ }
136
+ .unthor-branding-overlay {
137
+ animation: unthorFadeIn 0.7s ease-out forwards;
138
+ }
139
+ .fui-Text.fui-r-size-1:has(.fui-Strong),
140
+ .fui-Text:has(> [class*="fui-Strong"]),
141
+ div[class*="items-center"][class*="justify-center"] > .fui-Text:last-child,
142
+ .fui-Flex:has(> svg + .fui-Text:contains("Whop")),
143
+ span:contains("Secured by Whop"),
144
+ p:contains("Secured by Whop") {
145
+ display: none !important;
146
+ opacity: 0 !important;
147
+ pointer-events: none !important;
148
+ height: 0 !important;
149
+ margin: 0 !important;
150
+ }
151
+ .whop-checkout-wrapper iframe {
152
+ border-radius: 24px !important;
153
+ }
154
+ ` }),
155
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mx-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
156
+ import_react2.WhopCheckoutEmbed,
157
+ {
158
+ ref: internalRef,
159
+ onStateChange: handleStateChange,
160
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full flex flex-col items-center justify-center py-20", children: [
161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}) }),
162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-zinc-650 dark:text-zinc-400 text-sm tracking-tight", children: mergedLabels.initializing })
163
+ ] }),
164
+ hideTermsAndConditions: true,
165
+ hideEmail: true,
166
+ hideAddressForm: true,
167
+ hideSubmitButton: true,
168
+ theme,
169
+ environment,
170
+ styles: {
171
+ container: {
172
+ paddingLeft: 0,
173
+ paddingRight: 0,
174
+ paddingTop: 0,
175
+ paddingBottom: 0
176
+ }
177
+ },
178
+ ...props
179
+ }
180
+ ) }),
181
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "-mt-8 flex flex-col items-center relative z-10", children: [
182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute -top-4 left-0 right-0 h-12 bg-white dark:bg-zinc-950 pointer-events-none" }),
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative flex items-center gap-1.5 text-green-600 dark:text-green-400 opacity-80 mb-3 text-sm", children: [
184
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShieldCheckIcon, {}),
185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
186
+ mergedLabels.secured,
187
+ " \u2022 ",
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: mergedLabels.pciDSS })
189
+ ] })
190
+ ] }),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
192
+ "button",
193
+ {
194
+ type: "button",
195
+ disabled: isSubmitting,
196
+ onClick: handlePayNow,
197
+ className: "w-full group/btn relative mt-2 overflow-hidden h-10 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 rounded-lg transition-all disabled:opacity-70 disabled:cursor-not-allowed",
198
+ children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 bg-white/10 opacity-0 group-hover/btn:opacity-100 transition-opacity" }),
200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "relative flex items-center font-semibold justify-center gap-3 text-sm", children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MiniSpinner, {}),
202
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tracking-tight", children: mergedLabels.processing })
203
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tracking-tight", children: mergedLabels.payNow }) })
204
+ ]
205
+ }
206
+ )
207
+ ] }),
208
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "absolute mt-8 left-0 right-0 h-[75px] bg-white dark:bg-zinc-950 flex flex-col items-center justify-end pointer-events-none select-none pb-4 px-6 text-center unthor-branding-overlay", children: [
209
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-zinc-600 dark:text-zinc-400 leading-normal max-w-md mb-2.5 text-xs", children: mergedLabels.orderProcessedBy }),
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 text-zinc-500 dark:text-zinc-400 tracking-tight text-xs", children: [
211
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Unthor" }),
212
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "w-0.5 h-0.5 rounded-full bg-gray-400" }),
213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: mergedLabels.privacy }),
214
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "w-0.5 h-0.5 rounded-full bg-gray-400" }),
215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: mergedLabels.terms })
216
+ ] })
217
+ ] })
218
+ ] });
219
+ });
220
+ UnthorCheckoutEmbed.displayName = "UnthorCheckoutEmbed";
221
+ var useUnthorCheckoutEmbedControls = import_react2.useCheckoutEmbedControls;
222
+ // Annotate the CommonJS export names for ESM import in node:
223
+ 0 && (module.exports = {
224
+ UnthorCheckoutEmbed,
225
+ useCheckoutEmbedControls,
226
+ useUnthorCheckoutEmbedControls
227
+ });
228
+ //# sourceMappingURL=checkout-react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/checkout-react.tsx"],"sourcesContent":["import React, { forwardRef, useState, useImperativeHandle } from 'react';\nimport { WhopCheckoutEmbed, useCheckoutEmbedControls } from '@whop/checkout/react';\n\n// Spinner component for loading states\nconst Spinner = () => (\n <svg\n className=\"animate-spin h-8 w-8 text-zinc-400 dark:text-zinc-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n);\n\n// Mini spinner component for the button\nconst MiniSpinner = () => (\n <svg\n className=\"animate-spin h-4 w-4 text-current\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n);\n\n// Shield Check icon for security indicator\nconst ShieldCheckIcon = () => (\n <svg\n className=\"w-4 h-4 text-green-600 dark:text-green-400\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 13c0 5-3.5 7.5-7.66 9.7a1 1 0 0 1-.68 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 .76-.97l8-2a1 1 0 0 1 .48 0l8 2A1 1 0 0 1 20 6z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n);\n\nexport interface UnthorCheckoutEmbedLabels {\n initializing?: string;\n processing?: string;\n payNow?: string;\n secured?: string;\n pciDSS?: string;\n orderProcessedBy?: string;\n privacy?: string;\n terms?: string;\n}\n\nconst defaultLabels: Required<UnthorCheckoutEmbedLabels> = {\n initializing: \"Initializing checkout...\",\n processing: \"Processing...\",\n payNow: \"Pay now\",\n secured: \"Secured payment\",\n pciDSS: \"PCI-DSS Compliant\",\n orderProcessedBy: \"Order processed by unthor.com\",\n privacy: \"Privacy Policy\",\n terms: \"Terms of Service\"\n};\n\nexport interface UnthorCheckoutEmbedProps {\n sessionId?: string;\n membershipId?: string;\n licenseId?: string;\n theme?: 'light' | 'dark' | 'system';\n environment?: 'production' | 'sandbox';\n prefill?: any;\n labels?: UnthorCheckoutEmbedLabels;\n onStateChange?: (state: any) => void;\n onComplete?: (id: string, extra?: any) => void;\n onAddressValidationError?: (error: any) => void;\n [key: string]: any; // Open signature for standard Whop and HTML properties\n}\n\n/**\n * Custom Embedded Checkout component for Unthor.\n * Wraps WhopCheckoutEmbed with fully customized Unthor branding, masking logic, and visual assets.\n */\nexport const UnthorCheckoutEmbed = forwardRef<any, UnthorCheckoutEmbedProps>(({\n labels: customLabels,\n environment = 'production',\n onStateChange,\n theme = 'light',\n ...props\n}, ref) => {\n const mergedLabels = { ...defaultLabels, ...customLabels };\n const [isSubmitting, setIsSubmitting] = useState(false);\n const internalRef = useCheckoutEmbedControls();\n\n // Expose Whop control ref to external consumers\n useImperativeHandle(ref, () => internalRef.current);\n\n const handlePayNow = () => {\n setIsSubmitting(true);\n internalRef.current?.submit();\n };\n\n const handleStateChange = (state: any) => {\n if (state === 'loading') {\n setIsSubmitting(true);\n } else {\n setIsSubmitting(false);\n }\n if (onStateChange) {\n onStateChange(state);\n }\n };\n\n return (\n <div className=\"w-full h-full min-h-[500px] relative group/checkout overflow-hidden pb-32 unthor-checkout-container\">\n {/* Styles for global injection & animations */}\n <style>{`\n @keyframes unthorFadeInRight {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n }\n @keyframes unthorFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n .unthor-checkout-container {\n animation: unthorFadeInRight 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n }\n .unthor-branding-overlay {\n animation: unthorFadeIn 0.7s ease-out forwards;\n }\n .fui-Text.fui-r-size-1:has(.fui-Strong),\n .fui-Text:has(> [class*=\"fui-Strong\"]),\n div[class*=\"items-center\"][class*=\"justify-center\"] > .fui-Text:last-child,\n .fui-Flex:has(> svg + .fui-Text:contains(\"Whop\")),\n span:contains(\"Secured by Whop\"),\n p:contains(\"Secured by Whop\") {\n display: none !important;\n opacity: 0 !important;\n pointer-events: none !important;\n height: 0 !important;\n margin: 0 !important;\n }\n .whop-checkout-wrapper iframe {\n border-radius: 24px !important;\n }\n `}</style>\n\n <div className=\"mx-2\">\n <WhopCheckoutEmbed\n ref={internalRef}\n onStateChange={handleStateChange}\n fallback={\n <div className=\"w-full flex flex-col items-center justify-center py-20\">\n <div className=\"mb-4\">\n <Spinner />\n </div>\n <p className=\"text-zinc-650 dark:text-zinc-400 text-sm tracking-tight\">{mergedLabels.initializing}</p>\n </div>\n }\n hideTermsAndConditions\n hideEmail\n hideAddressForm\n hideSubmitButton\n theme={theme as any}\n environment={environment}\n styles={{\n container: {\n paddingLeft: 0,\n paddingRight: 0,\n paddingTop: 0,\n paddingBottom: 0,\n },\n }}\n {...(props as any)}\n />\n </div>\n\n <div className=\"-mt-8 flex flex-col items-center relative z-10\">\n {/* Masking area to cover Whop footer */}\n <div className=\"absolute -top-4 left-0 right-0 h-12 bg-white dark:bg-zinc-950 pointer-events-none\" />\n\n <div className=\"relative flex items-center gap-1.5 text-green-600 dark:text-green-400 opacity-80 mb-3 text-sm\">\n <ShieldCheckIcon />\n <span>\n {mergedLabels.secured} • <span>{mergedLabels.pciDSS}</span>\n </span>\n </div>\n\n <button\n type=\"button\"\n disabled={isSubmitting}\n onClick={handlePayNow}\n className=\"w-full group/btn relative mt-2 overflow-hidden h-10 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 rounded-lg transition-all disabled:opacity-70 disabled:cursor-not-allowed\"\n >\n <div className=\"absolute inset-0 bg-white/10 opacity-0 group-hover/btn:opacity-100 transition-opacity\" />\n <div className=\"relative flex items-center font-semibold justify-center gap-3 text-sm\">\n {isSubmitting ? (\n <>\n <MiniSpinner />\n <span className=\"tracking-tight\">{mergedLabels.processing}</span>\n </>\n ) : (\n <span className=\"tracking-tight\">{mergedLabels.payNow}</span>\n )}\n </div>\n </button>\n </div>\n\n {/* Custom Unthor Branding Overlay */}\n <div className=\"absolute mt-8 left-0 right-0 h-[75px] bg-white dark:bg-zinc-950 flex flex-col items-center justify-end pointer-events-none select-none pb-4 px-6 text-center unthor-branding-overlay\">\n <p className=\"text-zinc-600 dark:text-zinc-400 leading-normal max-w-md mb-2.5 text-xs\">\n {mergedLabels.orderProcessedBy}\n </p>\n <div className=\"flex items-center gap-3 text-zinc-500 dark:text-zinc-400 tracking-tight text-xs\">\n <span>Unthor</span>\n <span className=\"w-0.5 h-0.5 rounded-full bg-gray-400\" />\n <span>{mergedLabels.privacy}</span>\n <span className=\"w-0.5 h-0.5 rounded-full bg-gray-400\" />\n <span>{mergedLabels.terms}</span>\n </div>\n </div>\n </div>\n );\n});\n\nUnthorCheckoutEmbed.displayName = 'UnthorCheckoutEmbed';\n\n/**\n * Hook to access the controls of the checkout embed.\n */\nexport const useUnthorCheckoutEmbedControls = useCheckoutEmbedControls;\n\n// Also export the original control name for seamless migrations\nexport { useCheckoutEmbedControls };\n"],"mappings":"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","names":["import_react"]}
@@ -0,0 +1,201 @@
1
+ // src/checkout-react.tsx
2
+ import { forwardRef, useState, useImperativeHandle } from "react";
3
+ import { WhopCheckoutEmbed, useCheckoutEmbedControls } from "@whop/checkout/react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ var Spinner = () => /* @__PURE__ */ jsxs(
6
+ "svg",
7
+ {
8
+ className: "animate-spin h-8 w-8 text-zinc-400 dark:text-zinc-600",
9
+ xmlns: "http://www.w3.org/2000/svg",
10
+ fill: "none",
11
+ viewBox: "0 0 24 24",
12
+ children: [
13
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
14
+ /* @__PURE__ */ jsx(
15
+ "path",
16
+ {
17
+ className: "opacity-75",
18
+ fill: "currentColor",
19
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
20
+ }
21
+ )
22
+ ]
23
+ }
24
+ );
25
+ var MiniSpinner = () => /* @__PURE__ */ jsxs(
26
+ "svg",
27
+ {
28
+ className: "animate-spin h-4 w-4 text-current",
29
+ xmlns: "http://www.w3.org/2000/svg",
30
+ fill: "none",
31
+ viewBox: "0 0 24 24",
32
+ children: [
33
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
34
+ /* @__PURE__ */ jsx(
35
+ "path",
36
+ {
37
+ className: "opacity-75",
38
+ fill: "currentColor",
39
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
40
+ }
41
+ )
42
+ ]
43
+ }
44
+ );
45
+ var ShieldCheckIcon = () => /* @__PURE__ */ jsxs(
46
+ "svg",
47
+ {
48
+ className: "w-4 h-4 text-green-600 dark:text-green-400",
49
+ xmlns: "http://www.w3.org/2000/svg",
50
+ viewBox: "0 0 24 24",
51
+ fill: "none",
52
+ stroke: "currentColor",
53
+ strokeWidth: "2.5",
54
+ strokeLinecap: "round",
55
+ strokeLinejoin: "round",
56
+ children: [
57
+ /* @__PURE__ */ jsx("path", { d: "M20 13c0 5-3.5 7.5-7.66 9.7a1 1 0 0 1-.68 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 .76-.97l8-2a1 1 0 0 1 .48 0l8 2A1 1 0 0 1 20 6z" }),
58
+ /* @__PURE__ */ jsx("path", { d: "m9 12 2 2 4-4" })
59
+ ]
60
+ }
61
+ );
62
+ var defaultLabels = {
63
+ initializing: "Initializing checkout...",
64
+ processing: "Processing...",
65
+ payNow: "Pay now",
66
+ secured: "Secured payment",
67
+ pciDSS: "PCI-DSS Compliant",
68
+ orderProcessedBy: "Order processed by unthor.com",
69
+ privacy: "Privacy Policy",
70
+ terms: "Terms of Service"
71
+ };
72
+ var UnthorCheckoutEmbed = forwardRef(({
73
+ labels: customLabels,
74
+ environment = "production",
75
+ onStateChange,
76
+ theme = "light",
77
+ ...props
78
+ }, ref) => {
79
+ const mergedLabels = { ...defaultLabels, ...customLabels };
80
+ const [isSubmitting, setIsSubmitting] = useState(false);
81
+ const internalRef = useCheckoutEmbedControls();
82
+ useImperativeHandle(ref, () => internalRef.current);
83
+ const handlePayNow = () => {
84
+ setIsSubmitting(true);
85
+ internalRef.current?.submit();
86
+ };
87
+ const handleStateChange = (state) => {
88
+ if (state === "loading") {
89
+ setIsSubmitting(true);
90
+ } else {
91
+ setIsSubmitting(false);
92
+ }
93
+ if (onStateChange) {
94
+ onStateChange(state);
95
+ }
96
+ };
97
+ return /* @__PURE__ */ jsxs("div", { className: "w-full h-full min-h-[500px] relative group/checkout overflow-hidden pb-32 unthor-checkout-container", children: [
98
+ /* @__PURE__ */ jsx("style", { children: `
99
+ @keyframes unthorFadeInRight {
100
+ from { opacity: 0; transform: translateX(20px); }
101
+ to { opacity: 1; transform: translateX(0); }
102
+ }
103
+ @keyframes unthorFadeIn {
104
+ from { opacity: 0; }
105
+ to { opacity: 1; }
106
+ }
107
+ .unthor-checkout-container {
108
+ animation: unthorFadeInRight 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
109
+ }
110
+ .unthor-branding-overlay {
111
+ animation: unthorFadeIn 0.7s ease-out forwards;
112
+ }
113
+ .fui-Text.fui-r-size-1:has(.fui-Strong),
114
+ .fui-Text:has(> [class*="fui-Strong"]),
115
+ div[class*="items-center"][class*="justify-center"] > .fui-Text:last-child,
116
+ .fui-Flex:has(> svg + .fui-Text:contains("Whop")),
117
+ span:contains("Secured by Whop"),
118
+ p:contains("Secured by Whop") {
119
+ display: none !important;
120
+ opacity: 0 !important;
121
+ pointer-events: none !important;
122
+ height: 0 !important;
123
+ margin: 0 !important;
124
+ }
125
+ .whop-checkout-wrapper iframe {
126
+ border-radius: 24px !important;
127
+ }
128
+ ` }),
129
+ /* @__PURE__ */ jsx("div", { className: "mx-2", children: /* @__PURE__ */ jsx(
130
+ WhopCheckoutEmbed,
131
+ {
132
+ ref: internalRef,
133
+ onStateChange: handleStateChange,
134
+ fallback: /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col items-center justify-center py-20", children: [
135
+ /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(Spinner, {}) }),
136
+ /* @__PURE__ */ jsx("p", { className: "text-zinc-650 dark:text-zinc-400 text-sm tracking-tight", children: mergedLabels.initializing })
137
+ ] }),
138
+ hideTermsAndConditions: true,
139
+ hideEmail: true,
140
+ hideAddressForm: true,
141
+ hideSubmitButton: true,
142
+ theme,
143
+ environment,
144
+ styles: {
145
+ container: {
146
+ paddingLeft: 0,
147
+ paddingRight: 0,
148
+ paddingTop: 0,
149
+ paddingBottom: 0
150
+ }
151
+ },
152
+ ...props
153
+ }
154
+ ) }),
155
+ /* @__PURE__ */ jsxs("div", { className: "-mt-8 flex flex-col items-center relative z-10", children: [
156
+ /* @__PURE__ */ jsx("div", { className: "absolute -top-4 left-0 right-0 h-12 bg-white dark:bg-zinc-950 pointer-events-none" }),
157
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-1.5 text-green-600 dark:text-green-400 opacity-80 mb-3 text-sm", children: [
158
+ /* @__PURE__ */ jsx(ShieldCheckIcon, {}),
159
+ /* @__PURE__ */ jsxs("span", { children: [
160
+ mergedLabels.secured,
161
+ " \u2022 ",
162
+ /* @__PURE__ */ jsx("span", { children: mergedLabels.pciDSS })
163
+ ] })
164
+ ] }),
165
+ /* @__PURE__ */ jsxs(
166
+ "button",
167
+ {
168
+ type: "button",
169
+ disabled: isSubmitting,
170
+ onClick: handlePayNow,
171
+ className: "w-full group/btn relative mt-2 overflow-hidden h-10 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 rounded-lg transition-all disabled:opacity-70 disabled:cursor-not-allowed",
172
+ children: [
173
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-white/10 opacity-0 group-hover/btn:opacity-100 transition-opacity" }),
174
+ /* @__PURE__ */ jsx("div", { className: "relative flex items-center font-semibold justify-center gap-3 text-sm", children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
175
+ /* @__PURE__ */ jsx(MiniSpinner, {}),
176
+ /* @__PURE__ */ jsx("span", { className: "tracking-tight", children: mergedLabels.processing })
177
+ ] }) : /* @__PURE__ */ jsx("span", { className: "tracking-tight", children: mergedLabels.payNow }) })
178
+ ]
179
+ }
180
+ )
181
+ ] }),
182
+ /* @__PURE__ */ jsxs("div", { className: "absolute mt-8 left-0 right-0 h-[75px] bg-white dark:bg-zinc-950 flex flex-col items-center justify-end pointer-events-none select-none pb-4 px-6 text-center unthor-branding-overlay", children: [
183
+ /* @__PURE__ */ jsx("p", { className: "text-zinc-600 dark:text-zinc-400 leading-normal max-w-md mb-2.5 text-xs", children: mergedLabels.orderProcessedBy }),
184
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-zinc-500 dark:text-zinc-400 tracking-tight text-xs", children: [
185
+ /* @__PURE__ */ jsx("span", { children: "Unthor" }),
186
+ /* @__PURE__ */ jsx("span", { className: "w-0.5 h-0.5 rounded-full bg-gray-400" }),
187
+ /* @__PURE__ */ jsx("span", { children: mergedLabels.privacy }),
188
+ /* @__PURE__ */ jsx("span", { className: "w-0.5 h-0.5 rounded-full bg-gray-400" }),
189
+ /* @__PURE__ */ jsx("span", { children: mergedLabels.terms })
190
+ ] })
191
+ ] })
192
+ ] });
193
+ });
194
+ UnthorCheckoutEmbed.displayName = "UnthorCheckoutEmbed";
195
+ var useUnthorCheckoutEmbedControls = useCheckoutEmbedControls;
196
+ export {
197
+ UnthorCheckoutEmbed,
198
+ useCheckoutEmbedControls,
199
+ useUnthorCheckoutEmbedControls
200
+ };
201
+ //# sourceMappingURL=checkout-react.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/checkout-react.tsx"],"sourcesContent":["import React, { forwardRef, useState, useImperativeHandle } from 'react';\nimport { WhopCheckoutEmbed, useCheckoutEmbedControls } from '@whop/checkout/react';\n\n// Spinner component for loading states\nconst Spinner = () => (\n <svg\n className=\"animate-spin h-8 w-8 text-zinc-400 dark:text-zinc-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n);\n\n// Mini spinner component for the button\nconst MiniSpinner = () => (\n <svg\n className=\"animate-spin h-4 w-4 text-current\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n);\n\n// Shield Check icon for security indicator\nconst ShieldCheckIcon = () => (\n <svg\n className=\"w-4 h-4 text-green-600 dark:text-green-400\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 13c0 5-3.5 7.5-7.66 9.7a1 1 0 0 1-.68 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 .76-.97l8-2a1 1 0 0 1 .48 0l8 2A1 1 0 0 1 20 6z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n);\n\nexport interface UnthorCheckoutEmbedLabels {\n initializing?: string;\n processing?: string;\n payNow?: string;\n secured?: string;\n pciDSS?: string;\n orderProcessedBy?: string;\n privacy?: string;\n terms?: string;\n}\n\nconst defaultLabels: Required<UnthorCheckoutEmbedLabels> = {\n initializing: \"Initializing checkout...\",\n processing: \"Processing...\",\n payNow: \"Pay now\",\n secured: \"Secured payment\",\n pciDSS: \"PCI-DSS Compliant\",\n orderProcessedBy: \"Order processed by unthor.com\",\n privacy: \"Privacy Policy\",\n terms: \"Terms of Service\"\n};\n\nexport interface UnthorCheckoutEmbedProps {\n sessionId?: string;\n membershipId?: string;\n licenseId?: string;\n theme?: 'light' | 'dark' | 'system';\n environment?: 'production' | 'sandbox';\n prefill?: any;\n labels?: UnthorCheckoutEmbedLabels;\n onStateChange?: (state: any) => void;\n onComplete?: (id: string, extra?: any) => void;\n onAddressValidationError?: (error: any) => void;\n [key: string]: any; // Open signature for standard Whop and HTML properties\n}\n\n/**\n * Custom Embedded Checkout component for Unthor.\n * Wraps WhopCheckoutEmbed with fully customized Unthor branding, masking logic, and visual assets.\n */\nexport const UnthorCheckoutEmbed = forwardRef<any, UnthorCheckoutEmbedProps>(({\n labels: customLabels,\n environment = 'production',\n onStateChange,\n theme = 'light',\n ...props\n}, ref) => {\n const mergedLabels = { ...defaultLabels, ...customLabels };\n const [isSubmitting, setIsSubmitting] = useState(false);\n const internalRef = useCheckoutEmbedControls();\n\n // Expose Whop control ref to external consumers\n useImperativeHandle(ref, () => internalRef.current);\n\n const handlePayNow = () => {\n setIsSubmitting(true);\n internalRef.current?.submit();\n };\n\n const handleStateChange = (state: any) => {\n if (state === 'loading') {\n setIsSubmitting(true);\n } else {\n setIsSubmitting(false);\n }\n if (onStateChange) {\n onStateChange(state);\n }\n };\n\n return (\n <div className=\"w-full h-full min-h-[500px] relative group/checkout overflow-hidden pb-32 unthor-checkout-container\">\n {/* Styles for global injection & animations */}\n <style>{`\n @keyframes unthorFadeInRight {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n }\n @keyframes unthorFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n .unthor-checkout-container {\n animation: unthorFadeInRight 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n }\n .unthor-branding-overlay {\n animation: unthorFadeIn 0.7s ease-out forwards;\n }\n .fui-Text.fui-r-size-1:has(.fui-Strong),\n .fui-Text:has(> [class*=\"fui-Strong\"]),\n div[class*=\"items-center\"][class*=\"justify-center\"] > .fui-Text:last-child,\n .fui-Flex:has(> svg + .fui-Text:contains(\"Whop\")),\n span:contains(\"Secured by Whop\"),\n p:contains(\"Secured by Whop\") {\n display: none !important;\n opacity: 0 !important;\n pointer-events: none !important;\n height: 0 !important;\n margin: 0 !important;\n }\n .whop-checkout-wrapper iframe {\n border-radius: 24px !important;\n }\n `}</style>\n\n <div className=\"mx-2\">\n <WhopCheckoutEmbed\n ref={internalRef}\n onStateChange={handleStateChange}\n fallback={\n <div className=\"w-full flex flex-col items-center justify-center py-20\">\n <div className=\"mb-4\">\n <Spinner />\n </div>\n <p className=\"text-zinc-650 dark:text-zinc-400 text-sm tracking-tight\">{mergedLabels.initializing}</p>\n </div>\n }\n hideTermsAndConditions\n hideEmail\n hideAddressForm\n hideSubmitButton\n theme={theme as any}\n environment={environment}\n styles={{\n container: {\n paddingLeft: 0,\n paddingRight: 0,\n paddingTop: 0,\n paddingBottom: 0,\n },\n }}\n {...(props as any)}\n />\n </div>\n\n <div className=\"-mt-8 flex flex-col items-center relative z-10\">\n {/* Masking area to cover Whop footer */}\n <div className=\"absolute -top-4 left-0 right-0 h-12 bg-white dark:bg-zinc-950 pointer-events-none\" />\n\n <div className=\"relative flex items-center gap-1.5 text-green-600 dark:text-green-400 opacity-80 mb-3 text-sm\">\n <ShieldCheckIcon />\n <span>\n {mergedLabels.secured} • <span>{mergedLabels.pciDSS}</span>\n </span>\n </div>\n\n <button\n type=\"button\"\n disabled={isSubmitting}\n onClick={handlePayNow}\n className=\"w-full group/btn relative mt-2 overflow-hidden h-10 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 rounded-lg transition-all disabled:opacity-70 disabled:cursor-not-allowed\"\n >\n <div className=\"absolute inset-0 bg-white/10 opacity-0 group-hover/btn:opacity-100 transition-opacity\" />\n <div className=\"relative flex items-center font-semibold justify-center gap-3 text-sm\">\n {isSubmitting ? (\n <>\n <MiniSpinner />\n <span className=\"tracking-tight\">{mergedLabels.processing}</span>\n </>\n ) : (\n <span className=\"tracking-tight\">{mergedLabels.payNow}</span>\n )}\n </div>\n </button>\n </div>\n\n {/* Custom Unthor Branding Overlay */}\n <div className=\"absolute mt-8 left-0 right-0 h-[75px] bg-white dark:bg-zinc-950 flex flex-col items-center justify-end pointer-events-none select-none pb-4 px-6 text-center unthor-branding-overlay\">\n <p className=\"text-zinc-600 dark:text-zinc-400 leading-normal max-w-md mb-2.5 text-xs\">\n {mergedLabels.orderProcessedBy}\n </p>\n <div className=\"flex items-center gap-3 text-zinc-500 dark:text-zinc-400 tracking-tight text-xs\">\n <span>Unthor</span>\n <span className=\"w-0.5 h-0.5 rounded-full bg-gray-400\" />\n <span>{mergedLabels.privacy}</span>\n <span className=\"w-0.5 h-0.5 rounded-full bg-gray-400\" />\n <span>{mergedLabels.terms}</span>\n </div>\n </div>\n </div>\n );\n});\n\nUnthorCheckoutEmbed.displayName = 'UnthorCheckoutEmbed';\n\n/**\n * Hook to access the controls of the checkout embed.\n */\nexport const useUnthorCheckoutEmbedControls = useCheckoutEmbedControls;\n\n// Also export the original control name for seamless migrations\nexport { useCheckoutEmbedControls };\n"],"mappings":";AAAA,SAAgB,YAAY,UAAU,2BAA2B;AACjE,SAAS,mBAAmB,gCAAgC;AAI1D,SA4MY,UAtMV,KANF;AADF,IAAM,UAAU,MACd;AAAA,EAAC;AAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAM;AAAA,IACN,MAAK;AAAA,IACL,SAAQ;AAAA,IAER;AAAA,0BAAC,YAAO,WAAU,cAAa,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,QAAO,gBAAe,aAAY,KAAI;AAAA,MAC5F;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,MAAK;AAAA,UACL,GAAE;AAAA;AAAA,MACJ;AAAA;AAAA;AACF;AAIF,IAAM,cAAc,MAClB;AAAA,EAAC;AAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAM;AAAA,IACN,MAAK;AAAA,IACL,SAAQ;AAAA,IAER;AAAA,0BAAC,YAAO,WAAU,cAAa,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,QAAO,gBAAe,aAAY,KAAI;AAAA,MAC5F;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,MAAK;AAAA,UACL,GAAE;AAAA;AAAA,MACJ;AAAA;AAAA;AACF;AAIF,IAAM,kBAAkB,MACtB;AAAA,EAAC;AAAA;AAAA,IACC,WAAU;AAAA,IACV,OAAM;AAAA,IACN,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,eAAc;AAAA,IACd,gBAAe;AAAA,IAEf;AAAA,0BAAC,UAAK,GAAE,8HAA6H;AAAA,MACrI,oBAAC,UAAK,GAAE,iBAAgB;AAAA;AAAA;AAC1B;AAcF,IAAM,gBAAqD;AAAA,EACzD,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,SAAS;AAAA,EACT,OAAO;AACT;AAoBO,IAAM,sBAAsB,WAA0C,CAAC;AAAA,EAC5E,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,EACR,GAAG;AACL,GAAG,QAAQ;AACT,QAAM,eAAe,EAAE,GAAG,eAAe,GAAG,aAAa;AACzD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,cAAc,yBAAyB;AAG7C,sBAAoB,KAAK,MAAM,YAAY,OAAO;AAElD,QAAM,eAAe,MAAM;AACzB,oBAAgB,IAAI;AACpB,gBAAY,SAAS,OAAO;AAAA,EAC9B;AAEA,QAAM,oBAAoB,CAAC,UAAe;AACxC,QAAI,UAAU,WAAW;AACvB,sBAAgB,IAAI;AAAA,IACtB,OAAO;AACL,sBAAgB,KAAK;AAAA,IACvB;AACA,QAAI,eAAe;AACjB,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAEA,SACE,qBAAC,SAAI,WAAU,uGAEb;AAAA,wBAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SA8BN;AAAA,IAEF,oBAAC,SAAI,WAAU,QACb;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,eAAe;AAAA,QACf,UACE,qBAAC,SAAI,WAAU,0DACb;AAAA,8BAAC,SAAI,WAAU,QACb,8BAAC,WAAQ,GACX;AAAA,UACA,oBAAC,OAAE,WAAU,2DAA2D,uBAAa,cAAa;AAAA,WACpG;AAAA,QAEF,wBAAsB;AAAA,QACtB,WAAS;AAAA,QACT,iBAAe;AAAA,QACf,kBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,UACN,WAAW;AAAA,YACT,aAAa;AAAA,YACb,cAAc;AAAA,YACd,YAAY;AAAA,YACZ,eAAe;AAAA,UACjB;AAAA,QACF;AAAA,QACC,GAAI;AAAA;AAAA,IACP,GACF;AAAA,IAEA,qBAAC,SAAI,WAAU,kDAEb;AAAA,0BAAC,SAAI,WAAU,qFAAoF;AAAA,MAEnG,qBAAC,SAAI,WAAU,iGACb;AAAA,4BAAC,mBAAgB;AAAA,QACjB,qBAAC,UACE;AAAA,uBAAa;AAAA,UAAQ;AAAA,UAAG,oBAAC,UAAM,uBAAa,QAAO;AAAA,WACtD;AAAA,SACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAU;AAAA,UACV,SAAS;AAAA,UACT,WAAU;AAAA,UAEV;AAAA,gCAAC,SAAI,WAAU,yFAAwF;AAAA,YACvG,oBAAC,SAAI,WAAU,yEACZ,yBACC,iCACE;AAAA,kCAAC,eAAY;AAAA,cACb,oBAAC,UAAK,WAAU,kBAAkB,uBAAa,YAAW;AAAA,eAC5D,IAEA,oBAAC,UAAK,WAAU,kBAAkB,uBAAa,QAAO,GAE1D;AAAA;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IAGA,qBAAC,SAAI,WAAU,wLACb;AAAA,0BAAC,OAAE,WAAU,2EACV,uBAAa,kBAChB;AAAA,MACA,qBAAC,SAAI,WAAU,mFACb;AAAA,4BAAC,UAAK,oBAAM;AAAA,QACZ,oBAAC,UAAK,WAAU,wCAAuC;AAAA,QACvD,oBAAC,UAAM,uBAAa,SAAQ;AAAA,QAC5B,oBAAC,UAAK,WAAU,wCAAuC;AAAA,QACvD,oBAAC,UAAM,uBAAa,OAAM;AAAA,SAC5B;AAAA,OACF;AAAA,KACF;AAEJ,CAAC;AAED,oBAAoB,cAAc;AAK3B,IAAM,iCAAiC;","names":[]}
@@ -0,0 +1,60 @@
1
+ interface CheckoutSessionInput {
2
+ merchantId: string;
3
+ price: number;
4
+ currency: string;
5
+ productId: string;
6
+ productName: string;
7
+ isLive?: boolean;
8
+ options?: {
9
+ applicationFeePercent?: number;
10
+ planType?: 'one_time' | 'renewal' | 'usage_based';
11
+ billingPeriod?: number;
12
+ trialPeriodDays?: number;
13
+ expirationDays?: number;
14
+ sourceUrl?: string;
15
+ customerEmail?: string;
16
+ metadata?: Record<string, any>;
17
+ };
18
+ }
19
+ interface CheckoutSessionOutput {
20
+ id: string;
21
+ checkoutUrl: string;
22
+ rawResponse?: any;
23
+ }
24
+ interface IPaymentProvider {
25
+ createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput>;
26
+ }
27
+
28
+ declare class CheckoutError extends Error {
29
+ readonly code: string;
30
+ readonly statusCode: number;
31
+ constructor(message: string, code?: string, statusCode?: number);
32
+ }
33
+ declare class UnauthorizedError extends CheckoutError {
34
+ constructor(message?: string);
35
+ }
36
+ declare class ProviderError extends CheckoutError {
37
+ constructor(message: string, statusCode?: number);
38
+ }
39
+ declare class ValidationError extends CheckoutError {
40
+ constructor(message: string);
41
+ }
42
+
43
+ declare class WhopMapper {
44
+ static toWhopPlanData(input: CheckoutSessionInput): any;
45
+ static toCheckoutSessionOutput(whopResponse: any): CheckoutSessionOutput;
46
+ }
47
+
48
+ declare class WhopPaymentProvider implements IPaymentProvider {
49
+ private client;
50
+ constructor(apiKey: string, baseURL?: string);
51
+ createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput>;
52
+ }
53
+
54
+ declare class PaymentService {
55
+ private provider;
56
+ constructor(provider: IPaymentProvider);
57
+ createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput>;
58
+ }
59
+
60
+ export { CheckoutError, type CheckoutSessionInput, type CheckoutSessionOutput, type IPaymentProvider, PaymentService, ProviderError, UnauthorizedError, ValidationError, WhopMapper, WhopPaymentProvider };
@@ -0,0 +1,60 @@
1
+ interface CheckoutSessionInput {
2
+ merchantId: string;
3
+ price: number;
4
+ currency: string;
5
+ productId: string;
6
+ productName: string;
7
+ isLive?: boolean;
8
+ options?: {
9
+ applicationFeePercent?: number;
10
+ planType?: 'one_time' | 'renewal' | 'usage_based';
11
+ billingPeriod?: number;
12
+ trialPeriodDays?: number;
13
+ expirationDays?: number;
14
+ sourceUrl?: string;
15
+ customerEmail?: string;
16
+ metadata?: Record<string, any>;
17
+ };
18
+ }
19
+ interface CheckoutSessionOutput {
20
+ id: string;
21
+ checkoutUrl: string;
22
+ rawResponse?: any;
23
+ }
24
+ interface IPaymentProvider {
25
+ createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput>;
26
+ }
27
+
28
+ declare class CheckoutError extends Error {
29
+ readonly code: string;
30
+ readonly statusCode: number;
31
+ constructor(message: string, code?: string, statusCode?: number);
32
+ }
33
+ declare class UnauthorizedError extends CheckoutError {
34
+ constructor(message?: string);
35
+ }
36
+ declare class ProviderError extends CheckoutError {
37
+ constructor(message: string, statusCode?: number);
38
+ }
39
+ declare class ValidationError extends CheckoutError {
40
+ constructor(message: string);
41
+ }
42
+
43
+ declare class WhopMapper {
44
+ static toWhopPlanData(input: CheckoutSessionInput): any;
45
+ static toCheckoutSessionOutput(whopResponse: any): CheckoutSessionOutput;
46
+ }
47
+
48
+ declare class WhopPaymentProvider implements IPaymentProvider {
49
+ private client;
50
+ constructor(apiKey: string, baseURL?: string);
51
+ createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput>;
52
+ }
53
+
54
+ declare class PaymentService {
55
+ private provider;
56
+ constructor(provider: IPaymentProvider);
57
+ createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput>;
58
+ }
59
+
60
+ export { CheckoutError, type CheckoutSessionInput, type CheckoutSessionOutput, type IPaymentProvider, PaymentService, ProviderError, UnauthorizedError, ValidationError, WhopMapper, WhopPaymentProvider };
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/checkout.ts
31
+ var checkout_exports = {};
32
+ __export(checkout_exports, {
33
+ CheckoutError: () => CheckoutError,
34
+ PaymentService: () => PaymentService,
35
+ ProviderError: () => ProviderError,
36
+ UnauthorizedError: () => UnauthorizedError,
37
+ ValidationError: () => ValidationError,
38
+ WhopMapper: () => WhopMapper,
39
+ WhopPaymentProvider: () => WhopPaymentProvider
40
+ });
41
+ module.exports = __toCommonJS(checkout_exports);
42
+
43
+ // src/errors/index.ts
44
+ var CheckoutError = class extends Error {
45
+ code;
46
+ statusCode;
47
+ constructor(message, code = "CHECKOUT_ERROR", statusCode = 400) {
48
+ super(message);
49
+ this.name = "CheckoutError";
50
+ this.code = code;
51
+ this.statusCode = statusCode;
52
+ Object.setPrototypeOf(this, new.target.prototype);
53
+ }
54
+ };
55
+ var UnauthorizedError = class extends CheckoutError {
56
+ constructor(message = "Unauthorized") {
57
+ super(message, "UNAUTHORIZED", 401);
58
+ }
59
+ };
60
+ var ProviderError = class extends CheckoutError {
61
+ constructor(message, statusCode = 400) {
62
+ super(message, "PROVIDER_ERROR", statusCode);
63
+ }
64
+ };
65
+ var ValidationError = class extends CheckoutError {
66
+ constructor(message) {
67
+ super(message, "VALIDATION_ERROR", 400);
68
+ }
69
+ };
70
+
71
+ // src/mappers/whop.mapper.ts
72
+ var WhopMapper = class {
73
+ static toWhopPlanData(input) {
74
+ const { price, currency, productId, productName, options } = input;
75
+ const feePercent = options?.applicationFeePercent ?? 0.05;
76
+ const feeAmount = parseFloat((price * feePercent).toFixed(2));
77
+ const planData = {
78
+ company_id: input.merchantId,
79
+ title: productName,
80
+ initial_price: price,
81
+ currency: currency.toLowerCase(),
82
+ plan_type: options?.planType || "one_time",
83
+ product_id: productId,
84
+ application_fee_amount: feeAmount,
85
+ override_tax_type: "exclusive",
86
+ visibility: "visible"
87
+ };
88
+ const effectivePlanType = planData.plan_type === "renewal" || planData.plan_type === "usage_based" ? "renewal" : "one_time";
89
+ const isUsageBased = planData.plan_type === "usage_based";
90
+ planData.plan_type = effectivePlanType;
91
+ if (planData.plan_type === "renewal") {
92
+ planData.initial_price = 0;
93
+ planData.renewal_price = price;
94
+ planData.billing_period = options?.billingPeriod || 30;
95
+ if (isUsageBased) {
96
+ planData.internal_notes = `USAGE_BASED_PLAN:${options?.customerEmail || "guest"}`;
97
+ planData.visibility = "hidden";
98
+ }
99
+ if (options?.trialPeriodDays !== void 0 && options?.trialPeriodDays !== null) {
100
+ planData.trial_period_days = Number(options.trialPeriodDays);
101
+ }
102
+ } else {
103
+ planData.initial_price = price;
104
+ if (options?.expirationDays) {
105
+ planData.expiration_days = options.expirationDays;
106
+ }
107
+ }
108
+ return {
109
+ plan: planData,
110
+ isUsageBased
111
+ };
112
+ }
113
+ static toCheckoutSessionOutput(whopResponse) {
114
+ if (!whopResponse || !whopResponse.id || !whopResponse.checkout_url) {
115
+ throw new Error("Invalid checkout session response from Whop");
116
+ }
117
+ return {
118
+ id: whopResponse.id,
119
+ checkoutUrl: whopResponse.checkout_url,
120
+ rawResponse: whopResponse
121
+ };
122
+ }
123
+ };
124
+
125
+ // src/services/whop.provider.ts
126
+ var import_sdk = __toESM(require("@whop/sdk"));
127
+ var WhopPaymentProvider = class {
128
+ client;
129
+ constructor(apiKey, baseURL) {
130
+ this.client = new import_sdk.default({
131
+ apiKey,
132
+ baseURL
133
+ });
134
+ }
135
+ async createCheckoutSession(input) {
136
+ const { plan, isUsageBased } = WhopMapper.toWhopPlanData(input);
137
+ try {
138
+ const whopResponse = await this.client.checkoutConfigurations.create({
139
+ source_url: input.options?.sourceUrl || "https://unthor.com",
140
+ plan,
141
+ metadata: {
142
+ ...input.options?.metadata,
143
+ is_usage_based: isUsageBased ? "true" : "false"
144
+ }
145
+ });
146
+ return WhopMapper.toCheckoutSessionOutput(whopResponse);
147
+ } catch (error) {
148
+ const isAuthError = error.message?.includes("401") || error.message?.includes("unauthorized") || error.message?.includes("Authentication failed");
149
+ if (isAuthError) {
150
+ throw new UnauthorizedError("Whop SDK Authentication failed. Check API keys.");
151
+ }
152
+ throw new ProviderError(`Whop Checkout failed: ${error.message}`, error.statusCode || 400);
153
+ }
154
+ }
155
+ };
156
+
157
+ // src/services/payment.service.ts
158
+ var PaymentService = class {
159
+ provider;
160
+ constructor(provider) {
161
+ this.provider = provider;
162
+ }
163
+ async createCheckoutSession(input) {
164
+ if (!input.merchantId) {
165
+ throw new Error("merchantId is required");
166
+ }
167
+ if (!input.productId) {
168
+ throw new Error("productId is required");
169
+ }
170
+ if (input.price < 0) {
171
+ throw new Error("price must be non-negative");
172
+ }
173
+ return this.provider.createCheckoutSession(input);
174
+ }
175
+ };
176
+ // Annotate the CommonJS export names for ESM import in node:
177
+ 0 && (module.exports = {
178
+ CheckoutError,
179
+ PaymentService,
180
+ ProviderError,
181
+ UnauthorizedError,
182
+ ValidationError,
183
+ WhopMapper,
184
+ WhopPaymentProvider
185
+ });
186
+ //# sourceMappingURL=checkout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/checkout.ts","../src/errors/index.ts","../src/mappers/whop.mapper.ts","../src/services/whop.provider.ts","../src/services/payment.service.ts"],"sourcesContent":["export * from './interfaces';\nexport * from './errors';\nexport * from './mappers/whop.mapper';\nexport * from './services/whop.provider';\nexport * from './services/payment.service';\n","export class CheckoutError extends Error {\n public readonly code: string;\n public readonly statusCode: number;\n\n constructor(message: string, code = 'CHECKOUT_ERROR', statusCode = 400) {\n super(message);\n this.name = 'CheckoutError';\n this.code = code;\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class UnauthorizedError extends CheckoutError {\n constructor(message = 'Unauthorized') {\n super(message, 'UNAUTHORIZED', 401);\n }\n}\n\nexport class ProviderError extends CheckoutError {\n constructor(message: string, statusCode = 400) {\n super(message, 'PROVIDER_ERROR', statusCode);\n }\n}\n\nexport class ValidationError extends CheckoutError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n }\n}\n","import { CheckoutSessionInput, CheckoutSessionOutput } from '../interfaces';\n\nexport class WhopMapper {\n static toWhopPlanData(input: CheckoutSessionInput): any {\n const { price, currency, productId, productName, options } = input;\n const feePercent = options?.applicationFeePercent ?? 0.05;\n const feeAmount = parseFloat((price * feePercent).toFixed(2));\n\n const planData: any = {\n company_id: input.merchantId,\n title: productName,\n initial_price: price,\n currency: currency.toLowerCase(),\n plan_type: options?.planType || 'one_time',\n product_id: productId,\n application_fee_amount: feeAmount,\n override_tax_type: 'exclusive',\n visibility: 'visible',\n };\n\n const effectivePlanType =\n planData.plan_type === 'renewal' || planData.plan_type === 'usage_based'\n ? 'renewal'\n : 'one_time';\n const isUsageBased = planData.plan_type === 'usage_based';\n planData.plan_type = effectivePlanType;\n\n if (planData.plan_type === 'renewal') {\n planData.initial_price = 0;\n planData.renewal_price = price;\n planData.billing_period = options?.billingPeriod || 30;\n\n if (isUsageBased) {\n planData.internal_notes = `USAGE_BASED_PLAN:${options?.customerEmail || 'guest'}`;\n planData.visibility = 'hidden';\n }\n\n if (options?.trialPeriodDays !== undefined && options?.trialPeriodDays !== null) {\n planData.trial_period_days = Number(options.trialPeriodDays);\n }\n } else {\n planData.initial_price = price;\n if (options?.expirationDays) {\n planData.expiration_days = options.expirationDays;\n }\n }\n\n return {\n plan: planData,\n isUsageBased,\n };\n }\n\n static toCheckoutSessionOutput(whopResponse: any): CheckoutSessionOutput {\n if (!whopResponse || !whopResponse.id || !whopResponse.checkout_url) {\n throw new Error('Invalid checkout session response from Whop');\n }\n return {\n id: whopResponse.id,\n checkoutUrl: whopResponse.checkout_url,\n rawResponse: whopResponse,\n };\n }\n}\n","import Whop from '@whop/sdk';\nimport { IPaymentProvider, CheckoutSessionInput, CheckoutSessionOutput } from '../interfaces';\nimport { ProviderError, UnauthorizedError } from '../errors';\nimport { WhopMapper } from '../mappers/whop.mapper';\n\nexport class WhopPaymentProvider implements IPaymentProvider {\n private client: Whop;\n\n constructor(apiKey: string, baseURL?: string) {\n this.client = new Whop({\n apiKey,\n baseURL,\n });\n }\n\n async createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput> {\n const { plan, isUsageBased } = WhopMapper.toWhopPlanData(input);\n \n try {\n const whopResponse = await (this.client as any).checkoutConfigurations.create({\n source_url: input.options?.sourceUrl || 'https://unthor.com',\n plan,\n metadata: {\n ...input.options?.metadata,\n is_usage_based: isUsageBased ? 'true' : 'false',\n },\n });\n\n return WhopMapper.toCheckoutSessionOutput(whopResponse);\n } catch (error: any) {\n // Map authorization errors\n const isAuthError =\n error.message?.includes('401') ||\n error.message?.includes('unauthorized') ||\n error.message?.includes('Authentication failed');\n\n if (isAuthError) {\n throw new UnauthorizedError('Whop SDK Authentication failed. Check API keys.');\n }\n\n throw new ProviderError(`Whop Checkout failed: ${error.message}`, error.statusCode || 400);\n }\n }\n}\n","import { IPaymentProvider, CheckoutSessionInput, CheckoutSessionOutput } from '../interfaces';\n\nexport class PaymentService {\n private provider: IPaymentProvider;\n\n constructor(provider: IPaymentProvider) {\n this.provider = provider;\n }\n\n async createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput> {\n // We can add validation logic here before passing to the provider\n if (!input.merchantId) {\n throw new Error('merchantId is required');\n }\n if (!input.productId) {\n throw new Error('productId is required');\n }\n if (input.price < 0) {\n throw new Error('price must be non-negative');\n }\n\n return this.provider.createCheckoutSession(input);\n }\n}\n"],"mappings":"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","names":["Whop"]}
@@ -0,0 +1,143 @@
1
+ // src/errors/index.ts
2
+ var CheckoutError = class extends Error {
3
+ code;
4
+ statusCode;
5
+ constructor(message, code = "CHECKOUT_ERROR", statusCode = 400) {
6
+ super(message);
7
+ this.name = "CheckoutError";
8
+ this.code = code;
9
+ this.statusCode = statusCode;
10
+ Object.setPrototypeOf(this, new.target.prototype);
11
+ }
12
+ };
13
+ var UnauthorizedError = class extends CheckoutError {
14
+ constructor(message = "Unauthorized") {
15
+ super(message, "UNAUTHORIZED", 401);
16
+ }
17
+ };
18
+ var ProviderError = class extends CheckoutError {
19
+ constructor(message, statusCode = 400) {
20
+ super(message, "PROVIDER_ERROR", statusCode);
21
+ }
22
+ };
23
+ var ValidationError = class extends CheckoutError {
24
+ constructor(message) {
25
+ super(message, "VALIDATION_ERROR", 400);
26
+ }
27
+ };
28
+
29
+ // src/mappers/whop.mapper.ts
30
+ var WhopMapper = class {
31
+ static toWhopPlanData(input) {
32
+ const { price, currency, productId, productName, options } = input;
33
+ const feePercent = options?.applicationFeePercent ?? 0.05;
34
+ const feeAmount = parseFloat((price * feePercent).toFixed(2));
35
+ const planData = {
36
+ company_id: input.merchantId,
37
+ title: productName,
38
+ initial_price: price,
39
+ currency: currency.toLowerCase(),
40
+ plan_type: options?.planType || "one_time",
41
+ product_id: productId,
42
+ application_fee_amount: feeAmount,
43
+ override_tax_type: "exclusive",
44
+ visibility: "visible"
45
+ };
46
+ const effectivePlanType = planData.plan_type === "renewal" || planData.plan_type === "usage_based" ? "renewal" : "one_time";
47
+ const isUsageBased = planData.plan_type === "usage_based";
48
+ planData.plan_type = effectivePlanType;
49
+ if (planData.plan_type === "renewal") {
50
+ planData.initial_price = 0;
51
+ planData.renewal_price = price;
52
+ planData.billing_period = options?.billingPeriod || 30;
53
+ if (isUsageBased) {
54
+ planData.internal_notes = `USAGE_BASED_PLAN:${options?.customerEmail || "guest"}`;
55
+ planData.visibility = "hidden";
56
+ }
57
+ if (options?.trialPeriodDays !== void 0 && options?.trialPeriodDays !== null) {
58
+ planData.trial_period_days = Number(options.trialPeriodDays);
59
+ }
60
+ } else {
61
+ planData.initial_price = price;
62
+ if (options?.expirationDays) {
63
+ planData.expiration_days = options.expirationDays;
64
+ }
65
+ }
66
+ return {
67
+ plan: planData,
68
+ isUsageBased
69
+ };
70
+ }
71
+ static toCheckoutSessionOutput(whopResponse) {
72
+ if (!whopResponse || !whopResponse.id || !whopResponse.checkout_url) {
73
+ throw new Error("Invalid checkout session response from Whop");
74
+ }
75
+ return {
76
+ id: whopResponse.id,
77
+ checkoutUrl: whopResponse.checkout_url,
78
+ rawResponse: whopResponse
79
+ };
80
+ }
81
+ };
82
+
83
+ // src/services/whop.provider.ts
84
+ import Whop from "@whop/sdk";
85
+ var WhopPaymentProvider = class {
86
+ client;
87
+ constructor(apiKey, baseURL) {
88
+ this.client = new Whop({
89
+ apiKey,
90
+ baseURL
91
+ });
92
+ }
93
+ async createCheckoutSession(input) {
94
+ const { plan, isUsageBased } = WhopMapper.toWhopPlanData(input);
95
+ try {
96
+ const whopResponse = await this.client.checkoutConfigurations.create({
97
+ source_url: input.options?.sourceUrl || "https://unthor.com",
98
+ plan,
99
+ metadata: {
100
+ ...input.options?.metadata,
101
+ is_usage_based: isUsageBased ? "true" : "false"
102
+ }
103
+ });
104
+ return WhopMapper.toCheckoutSessionOutput(whopResponse);
105
+ } catch (error) {
106
+ const isAuthError = error.message?.includes("401") || error.message?.includes("unauthorized") || error.message?.includes("Authentication failed");
107
+ if (isAuthError) {
108
+ throw new UnauthorizedError("Whop SDK Authentication failed. Check API keys.");
109
+ }
110
+ throw new ProviderError(`Whop Checkout failed: ${error.message}`, error.statusCode || 400);
111
+ }
112
+ }
113
+ };
114
+
115
+ // src/services/payment.service.ts
116
+ var PaymentService = class {
117
+ provider;
118
+ constructor(provider) {
119
+ this.provider = provider;
120
+ }
121
+ async createCheckoutSession(input) {
122
+ if (!input.merchantId) {
123
+ throw new Error("merchantId is required");
124
+ }
125
+ if (!input.productId) {
126
+ throw new Error("productId is required");
127
+ }
128
+ if (input.price < 0) {
129
+ throw new Error("price must be non-negative");
130
+ }
131
+ return this.provider.createCheckoutSession(input);
132
+ }
133
+ };
134
+ export {
135
+ CheckoutError,
136
+ PaymentService,
137
+ ProviderError,
138
+ UnauthorizedError,
139
+ ValidationError,
140
+ WhopMapper,
141
+ WhopPaymentProvider
142
+ };
143
+ //# sourceMappingURL=checkout.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors/index.ts","../src/mappers/whop.mapper.ts","../src/services/whop.provider.ts","../src/services/payment.service.ts"],"sourcesContent":["export class CheckoutError extends Error {\n public readonly code: string;\n public readonly statusCode: number;\n\n constructor(message: string, code = 'CHECKOUT_ERROR', statusCode = 400) {\n super(message);\n this.name = 'CheckoutError';\n this.code = code;\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class UnauthorizedError extends CheckoutError {\n constructor(message = 'Unauthorized') {\n super(message, 'UNAUTHORIZED', 401);\n }\n}\n\nexport class ProviderError extends CheckoutError {\n constructor(message: string, statusCode = 400) {\n super(message, 'PROVIDER_ERROR', statusCode);\n }\n}\n\nexport class ValidationError extends CheckoutError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n }\n}\n","import { CheckoutSessionInput, CheckoutSessionOutput } from '../interfaces';\n\nexport class WhopMapper {\n static toWhopPlanData(input: CheckoutSessionInput): any {\n const { price, currency, productId, productName, options } = input;\n const feePercent = options?.applicationFeePercent ?? 0.05;\n const feeAmount = parseFloat((price * feePercent).toFixed(2));\n\n const planData: any = {\n company_id: input.merchantId,\n title: productName,\n initial_price: price,\n currency: currency.toLowerCase(),\n plan_type: options?.planType || 'one_time',\n product_id: productId,\n application_fee_amount: feeAmount,\n override_tax_type: 'exclusive',\n visibility: 'visible',\n };\n\n const effectivePlanType =\n planData.plan_type === 'renewal' || planData.plan_type === 'usage_based'\n ? 'renewal'\n : 'one_time';\n const isUsageBased = planData.plan_type === 'usage_based';\n planData.plan_type = effectivePlanType;\n\n if (planData.plan_type === 'renewal') {\n planData.initial_price = 0;\n planData.renewal_price = price;\n planData.billing_period = options?.billingPeriod || 30;\n\n if (isUsageBased) {\n planData.internal_notes = `USAGE_BASED_PLAN:${options?.customerEmail || 'guest'}`;\n planData.visibility = 'hidden';\n }\n\n if (options?.trialPeriodDays !== undefined && options?.trialPeriodDays !== null) {\n planData.trial_period_days = Number(options.trialPeriodDays);\n }\n } else {\n planData.initial_price = price;\n if (options?.expirationDays) {\n planData.expiration_days = options.expirationDays;\n }\n }\n\n return {\n plan: planData,\n isUsageBased,\n };\n }\n\n static toCheckoutSessionOutput(whopResponse: any): CheckoutSessionOutput {\n if (!whopResponse || !whopResponse.id || !whopResponse.checkout_url) {\n throw new Error('Invalid checkout session response from Whop');\n }\n return {\n id: whopResponse.id,\n checkoutUrl: whopResponse.checkout_url,\n rawResponse: whopResponse,\n };\n }\n}\n","import Whop from '@whop/sdk';\nimport { IPaymentProvider, CheckoutSessionInput, CheckoutSessionOutput } from '../interfaces';\nimport { ProviderError, UnauthorizedError } from '../errors';\nimport { WhopMapper } from '../mappers/whop.mapper';\n\nexport class WhopPaymentProvider implements IPaymentProvider {\n private client: Whop;\n\n constructor(apiKey: string, baseURL?: string) {\n this.client = new Whop({\n apiKey,\n baseURL,\n });\n }\n\n async createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput> {\n const { plan, isUsageBased } = WhopMapper.toWhopPlanData(input);\n \n try {\n const whopResponse = await (this.client as any).checkoutConfigurations.create({\n source_url: input.options?.sourceUrl || 'https://unthor.com',\n plan,\n metadata: {\n ...input.options?.metadata,\n is_usage_based: isUsageBased ? 'true' : 'false',\n },\n });\n\n return WhopMapper.toCheckoutSessionOutput(whopResponse);\n } catch (error: any) {\n // Map authorization errors\n const isAuthError =\n error.message?.includes('401') ||\n error.message?.includes('unauthorized') ||\n error.message?.includes('Authentication failed');\n\n if (isAuthError) {\n throw new UnauthorizedError('Whop SDK Authentication failed. Check API keys.');\n }\n\n throw new ProviderError(`Whop Checkout failed: ${error.message}`, error.statusCode || 400);\n }\n }\n}\n","import { IPaymentProvider, CheckoutSessionInput, CheckoutSessionOutput } from '../interfaces';\n\nexport class PaymentService {\n private provider: IPaymentProvider;\n\n constructor(provider: IPaymentProvider) {\n this.provider = provider;\n }\n\n async createCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSessionOutput> {\n // We can add validation logic here before passing to the provider\n if (!input.merchantId) {\n throw new Error('merchantId is required');\n }\n if (!input.productId) {\n throw new Error('productId is required');\n }\n if (input.price < 0) {\n throw new Error('price must be non-negative');\n }\n\n return this.provider.createCheckoutSession(input);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "unthor-sdk",
3
+ "version": "1.0.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "Unified Unthor TypeScript SDK wrapping billing, payments, and checkout flows",
8
+ "main": "./dist/checkout.js",
9
+ "module": "./dist/checkout.mjs",
10
+ "types": "./dist/checkout.d.ts",
11
+ "exports": {
12
+ "./checkout": {
13
+ "types": "./dist/checkout.d.ts",
14
+ "require": "./dist/checkout.js",
15
+ "import": "./dist/checkout.mjs"
16
+ },
17
+ "./checkout/react": {
18
+ "types": "./dist/checkout-react.d.ts",
19
+ "require": "./dist/checkout-react.js",
20
+ "import": "./dist/checkout-react.mjs"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest"
30
+ },
31
+ "dependencies": {
32
+ "@whop/sdk": "^0.0.38",
33
+ "@whop/checkout": "^0.0.53"
34
+ },
35
+ "peerDependencies": {
36
+ "react": "^18.0.0 || ^19.0.0",
37
+ "react-dom": "^18.0.0 || ^19.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "tsup": "^8.0.2",
41
+ "typescript": "^5.3.3",
42
+ "vitest": "^1.3.1",
43
+ "@types/react": "^19.0.0"
44
+ }
45
+ }