@usethrottle/checkout-sdk 1.4.0 → 1.6.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.
- package/CHANGELOG.md +18 -0
- package/README.md +2 -0
- package/dist/index.cjs +11 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +17 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +37 -6
- package/dist/server.d.ts +37 -6
- package/dist/server.js +17 -1
- package/dist/server.js.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @usethrottle/checkout-sdk
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 03e4050: Analytics & attribution: `onSucceeded` (and the underlying
|
|
8
|
+
`throttle.completed` postMessage, protocol v1.4 additive) now carries
|
|
9
|
+
`total` (minor units), `currency`, and `lineItems[]` (`sku` = merchant
|
|
10
|
+
catalog id) so merchant pages can fire GA4/Meta purchase events without an
|
|
11
|
+
extra fetch. checkout-sdk also forwards `subscriptionId` and enriches
|
|
12
|
+
`succeeded` telemetry with `total`/`currency`. api-client picks up
|
|
13
|
+
`clientContext` on checkout session create/complete + order responses and
|
|
14
|
+
the new `/api/v1/tracking-settings` endpoints.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [03e4050]
|
|
19
|
+
- @usethrottle/checkout-react@1.3.0
|
|
20
|
+
|
|
3
21
|
## 1.4.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -85,6 +85,8 @@ const nextCursor = ordersPage.pagination?.cursor;
|
|
|
85
85
|
| ----------------------------- | --------------------------------------------- | --------------------------------------------------------- |
|
|
86
86
|
| `createSession(input)` | `POST /api/v1/checkout/sessions` | Creates a cart-backed hosted/embed checkout session. |
|
|
87
87
|
| `completeSession(id, input)` | `POST /api/v1/checkout/sessions/:id/complete` | Completes a checkout session from server-side proxy mode. |
|
|
88
|
+
| `getSession(id)` | `GET /api/v1/checkout/sessions/:id` | Reads a session back, including its current `status`. |
|
|
89
|
+
| `cancelSession(id)` | `DELETE /api/v1/checkout/sessions/:id` | Cancels an in-flight session. Idempotent. |
|
|
88
90
|
| `createEmbedToken(input)` | `POST /api/v1/checkout-sessions/embed-token` | Mints an embed token for proxy-mode card capture. |
|
|
89
91
|
| `getOrder(id)` | `GET /api/v1/orders/:id` | Reads public-safe order totals/status. |
|
|
90
92
|
| `listOrders(options)` | `GET /api/v1/orders` | Lists public-safe orders with optional filters. |
|
package/dist/index.cjs
CHANGED
|
@@ -57,11 +57,19 @@ function ThrottleCheckout({
|
|
|
57
57
|
emit({ type: "processing", sessionId, timestamp: Date.now() });
|
|
58
58
|
}, [emit, sessionId]);
|
|
59
59
|
const handleSucceeded = (0, import_react.useCallback)(
|
|
60
|
-
(
|
|
60
|
+
(evt) => {
|
|
61
61
|
if (settledRef.current) return;
|
|
62
62
|
settledRef.current = true;
|
|
63
|
-
emit({
|
|
64
|
-
|
|
63
|
+
emit({
|
|
64
|
+
type: "succeeded",
|
|
65
|
+
sessionId,
|
|
66
|
+
orderId: evt.orderId,
|
|
67
|
+
paymentId: evt.paymentId,
|
|
68
|
+
timestamp: Date.now(),
|
|
69
|
+
...evt.total !== void 0 ? { total: evt.total } : {},
|
|
70
|
+
...evt.currency !== void 0 ? { currency: evt.currency } : {}
|
|
71
|
+
});
|
|
72
|
+
onSucceeded?.(evt);
|
|
65
73
|
},
|
|
66
74
|
[emit, sessionId, onSucceeded]
|
|
67
75
|
);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/ThrottleCheckout.tsx"],"sourcesContent":["export { ThrottleCheckout } from './ThrottleCheckout.js';\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\nexport type {
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ThrottleCheckout.tsx"],"sourcesContent":["export { ThrottleCheckout } from './ThrottleCheckout.js';\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\nexport type {\n BrandTheme,\n TelemetryEvent,\n ThrottleCheckoutProps,\n SucceededLineItem,\n} from './types.js';\n","import { useCallback, useEffect, useRef } from 'react';\nimport { PaymentEmbed } from '@usethrottle/checkout-react';\nimport type { ThrottleCheckoutProps, TelemetryEvent } from './types.js';\n\n/**\n * ThrottleCheckout — Phase 1 platform SDK wrapper.\n *\n * Wraps `<PaymentEmbed>` from `@usethrottle/checkout-react` and adds:\n * 1. Idempotency — settledRef ensures `onSucceeded` / `onFailed` fire at most once\n * per component lifetime, even if the iframe sends duplicate events.\n * 2. Telemetry — `onTelemetry` callback receives every lifecycle event with a\n * typed payload so workspaces can pipe to Datadog / Segment / etc.\n * 3. Brand theming — `theme.primary` + `theme.logo` are forwarded to the underlying\n * `<PaymentEmbed>` which appends them as URL query params on the\n * hosted checkout iframe src.\n */\nexport function ThrottleCheckout({\n sessionId,\n parentOrigin = '',\n baseUrl,\n theme,\n onSucceeded,\n onFailed,\n onCancelled,\n onTelemetry,\n}: ThrottleCheckoutProps): JSX.Element {\n // Idempotency guard — once a terminal event (success or failure) fires,\n // all subsequent duplicate events from the iframe are silently dropped.\n const settledRef = useRef(false);\n\n const emit = useCallback(\n (event: TelemetryEvent) => {\n onTelemetry?.(event);\n },\n [onTelemetry],\n );\n\n // Fire \"mounted\" telemetry once on initial render.\n useEffect(() => {\n emit({ type: 'mounted', sessionId, timestamp: Date.now() });\n // intentionally only on mount — sessionId identity change re-mounts anyway\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleReady = useCallback(() => {\n emit({ type: 'ready', sessionId, timestamp: Date.now() });\n }, [emit, sessionId]);\n\n const handleProcessing = useCallback(() => {\n emit({ type: 'processing', sessionId, timestamp: Date.now() });\n }, [emit, sessionId]);\n\n const handleSucceeded = useCallback(\n (evt: {\n orderId: string;\n paymentId: string;\n subscriptionId?: string;\n total?: number;\n currency?: string;\n lineItems?: import('./types.js').SucceededLineItem[];\n }) => {\n if (settledRef.current) return;\n settledRef.current = true;\n emit({\n type: 'succeeded',\n sessionId,\n orderId: evt.orderId,\n paymentId: evt.paymentId,\n timestamp: Date.now(),\n ...(evt.total !== undefined ? { total: evt.total } : {}),\n ...(evt.currency !== undefined ? { currency: evt.currency } : {}),\n });\n onSucceeded?.(evt);\n },\n [emit, sessionId, onSucceeded],\n );\n\n const handleFailed = useCallback(\n ({ code, message }: { code: string; message: string }) => {\n if (settledRef.current) return;\n settledRef.current = true;\n emit({ type: 'failed', sessionId, code, message, timestamp: Date.now() });\n onFailed?.({ code, message });\n },\n [emit, sessionId, onFailed],\n );\n\n const handleCanceled = useCallback(() => {\n emit({ type: 'cancelled', sessionId, timestamp: Date.now() });\n onCancelled?.();\n }, [emit, sessionId, onCancelled]);\n\n return (\n <PaymentEmbed\n sessionId={sessionId}\n parentOrigin={parentOrigin}\n {...(baseUrl !== undefined ? { baseUrl } : {})}\n primary={theme?.primary}\n logo={theme?.logo}\n onReady={handleReady}\n onProcessing={handleProcessing}\n onSucceeded={handleSucceeded}\n onFailed={handleFailed}\n onCanceled={handleCanceled}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAA+C;AAC/C,4BAA6B;AA4FzB;AA7EG,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AAGrC,QAAM,iBAAa,qBAAO,KAAK;AAE/B,QAAM,WAAO;AAAA,IACX,CAAC,UAA0B;AACzB,oBAAc,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAGA,8BAAU,MAAM;AACd,SAAK,EAAE,MAAM,WAAW,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EAG5D,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAc,0BAAY,MAAM;AACpC,SAAK,EAAE,MAAM,SAAS,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EAC1D,GAAG,CAAC,MAAM,SAAS,CAAC;AAEpB,QAAM,uBAAmB,0BAAY,MAAM;AACzC,SAAK,EAAE,MAAM,cAAc,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EAC/D,GAAG,CAAC,MAAM,SAAS,CAAC;AAEpB,QAAM,sBAAkB;AAAA,IACtB,CAAC,QAOK;AACJ,UAAI,WAAW,QAAS;AACxB,iBAAW,UAAU;AACrB,WAAK;AAAA,QACH,MAAM;AAAA,QACN;AAAA,QACA,SAAS,IAAI;AAAA,QACb,WAAW,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,GAAI,IAAI,UAAU,SAAY,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC;AAAA,QACtD,GAAI,IAAI,aAAa,SAAY,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC;AAAA,MACjE,CAAC;AACD,oBAAc,GAAG;AAAA,IACnB;AAAA,IACA,CAAC,MAAM,WAAW,WAAW;AAAA,EAC/B;AAEA,QAAM,mBAAe;AAAA,IACnB,CAAC,EAAE,MAAM,QAAQ,MAAyC;AACxD,UAAI,WAAW,QAAS;AACxB,iBAAW,UAAU;AACrB,WAAK,EAAE,MAAM,UAAU,WAAW,MAAM,SAAS,WAAW,KAAK,IAAI,EAAE,CAAC;AACxE,iBAAW,EAAE,MAAM,QAAQ,CAAC;AAAA,IAC9B;AAAA,IACA,CAAC,MAAM,WAAW,QAAQ;AAAA,EAC5B;AAEA,QAAM,qBAAiB,0BAAY,MAAM;AACvC,SAAK,EAAE,MAAM,aAAa,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAC5D,kBAAc;AAAA,EAChB,GAAG,CAAC,MAAM,WAAW,WAAW,CAAC;AAEjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACC,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC5C,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,SAAS;AAAA,MACT,cAAc;AAAA,MACd,aAAa;AAAA,MACb,UAAU;AAAA,MACV,YAAY;AAAA;AAAA,EACd;AAEJ;;;ADzGA,oBAA+C;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,16 @@ interface BrandTheme {
|
|
|
9
9
|
/** Absolute URL of merchant logo image. */
|
|
10
10
|
logo?: string;
|
|
11
11
|
}
|
|
12
|
+
/** Line item snapshot on succeeded events — minor-unit prices; `sku` is the
|
|
13
|
+
* merchant catalog id (analytics content_ids join key). */
|
|
14
|
+
interface SucceededLineItem {
|
|
15
|
+
id?: string;
|
|
16
|
+
name: string;
|
|
17
|
+
sku?: string;
|
|
18
|
+
quantity: number;
|
|
19
|
+
unitPrice: number;
|
|
20
|
+
total: number;
|
|
21
|
+
}
|
|
12
22
|
type TelemetryEvent = {
|
|
13
23
|
type: 'mounted';
|
|
14
24
|
sessionId: string;
|
|
@@ -27,6 +37,9 @@ type TelemetryEvent = {
|
|
|
27
37
|
orderId: string;
|
|
28
38
|
paymentId: string;
|
|
29
39
|
timestamp: number;
|
|
40
|
+
/** Order total in minor units (when the checkout page supplied it). */
|
|
41
|
+
total?: number;
|
|
42
|
+
currency?: string;
|
|
30
43
|
} | {
|
|
31
44
|
type: 'failed';
|
|
32
45
|
sessionId: string;
|
|
@@ -55,10 +68,17 @@ interface ThrottleCheckoutProps {
|
|
|
55
68
|
baseUrl?: string;
|
|
56
69
|
/** Optional brand theming forwarded to the hosted checkout page. */
|
|
57
70
|
theme?: BrandTheme;
|
|
58
|
-
/** Fired once when payment completes successfully.
|
|
71
|
+
/** Fired once when payment completes successfully. Analytics fields
|
|
72
|
+
* (`total`/`currency`/`lineItems`, minor units) are present when the
|
|
73
|
+
* checkout page supplied them — fire `gtag`/`fbq` purchase events with
|
|
74
|
+
* value = total / 100. */
|
|
59
75
|
onSucceeded?: (args: {
|
|
60
76
|
orderId: string;
|
|
61
77
|
paymentId: string;
|
|
78
|
+
subscriptionId?: string;
|
|
79
|
+
total?: number;
|
|
80
|
+
currency?: string;
|
|
81
|
+
lineItems?: SucceededLineItem[];
|
|
62
82
|
}) => void;
|
|
63
83
|
/** Fired once when payment fails terminally. */
|
|
64
84
|
onFailed?: (args: {
|
|
@@ -85,4 +105,4 @@ interface ThrottleCheckoutProps {
|
|
|
85
105
|
*/
|
|
86
106
|
declare function ThrottleCheckout({ sessionId, parentOrigin, baseUrl, theme, onSucceeded, onFailed, onCancelled, onTelemetry, }: ThrottleCheckoutProps): JSX.Element;
|
|
87
107
|
|
|
88
|
-
export { type BrandTheme, type TelemetryEvent, ThrottleCheckout, type ThrottleCheckoutProps };
|
|
108
|
+
export { type BrandTheme, type SucceededLineItem, type TelemetryEvent, ThrottleCheckout, type ThrottleCheckoutProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,16 @@ interface BrandTheme {
|
|
|
9
9
|
/** Absolute URL of merchant logo image. */
|
|
10
10
|
logo?: string;
|
|
11
11
|
}
|
|
12
|
+
/** Line item snapshot on succeeded events — minor-unit prices; `sku` is the
|
|
13
|
+
* merchant catalog id (analytics content_ids join key). */
|
|
14
|
+
interface SucceededLineItem {
|
|
15
|
+
id?: string;
|
|
16
|
+
name: string;
|
|
17
|
+
sku?: string;
|
|
18
|
+
quantity: number;
|
|
19
|
+
unitPrice: number;
|
|
20
|
+
total: number;
|
|
21
|
+
}
|
|
12
22
|
type TelemetryEvent = {
|
|
13
23
|
type: 'mounted';
|
|
14
24
|
sessionId: string;
|
|
@@ -27,6 +37,9 @@ type TelemetryEvent = {
|
|
|
27
37
|
orderId: string;
|
|
28
38
|
paymentId: string;
|
|
29
39
|
timestamp: number;
|
|
40
|
+
/** Order total in minor units (when the checkout page supplied it). */
|
|
41
|
+
total?: number;
|
|
42
|
+
currency?: string;
|
|
30
43
|
} | {
|
|
31
44
|
type: 'failed';
|
|
32
45
|
sessionId: string;
|
|
@@ -55,10 +68,17 @@ interface ThrottleCheckoutProps {
|
|
|
55
68
|
baseUrl?: string;
|
|
56
69
|
/** Optional brand theming forwarded to the hosted checkout page. */
|
|
57
70
|
theme?: BrandTheme;
|
|
58
|
-
/** Fired once when payment completes successfully.
|
|
71
|
+
/** Fired once when payment completes successfully. Analytics fields
|
|
72
|
+
* (`total`/`currency`/`lineItems`, minor units) are present when the
|
|
73
|
+
* checkout page supplied them — fire `gtag`/`fbq` purchase events with
|
|
74
|
+
* value = total / 100. */
|
|
59
75
|
onSucceeded?: (args: {
|
|
60
76
|
orderId: string;
|
|
61
77
|
paymentId: string;
|
|
78
|
+
subscriptionId?: string;
|
|
79
|
+
total?: number;
|
|
80
|
+
currency?: string;
|
|
81
|
+
lineItems?: SucceededLineItem[];
|
|
62
82
|
}) => void;
|
|
63
83
|
/** Fired once when payment fails terminally. */
|
|
64
84
|
onFailed?: (args: {
|
|
@@ -85,4 +105,4 @@ interface ThrottleCheckoutProps {
|
|
|
85
105
|
*/
|
|
86
106
|
declare function ThrottleCheckout({ sessionId, parentOrigin, baseUrl, theme, onSucceeded, onFailed, onCancelled, onTelemetry, }: ThrottleCheckoutProps): JSX.Element;
|
|
87
107
|
|
|
88
|
-
export { type BrandTheme, type TelemetryEvent, ThrottleCheckout, type ThrottleCheckoutProps };
|
|
108
|
+
export { type BrandTheme, type SucceededLineItem, type TelemetryEvent, ThrottleCheckout, type ThrottleCheckoutProps };
|
package/dist/index.js
CHANGED
|
@@ -29,11 +29,19 @@ function ThrottleCheckout({
|
|
|
29
29
|
emit({ type: "processing", sessionId, timestamp: Date.now() });
|
|
30
30
|
}, [emit, sessionId]);
|
|
31
31
|
const handleSucceeded = useCallback(
|
|
32
|
-
(
|
|
32
|
+
(evt) => {
|
|
33
33
|
if (settledRef.current) return;
|
|
34
34
|
settledRef.current = true;
|
|
35
|
-
emit({
|
|
36
|
-
|
|
35
|
+
emit({
|
|
36
|
+
type: "succeeded",
|
|
37
|
+
sessionId,
|
|
38
|
+
orderId: evt.orderId,
|
|
39
|
+
paymentId: evt.paymentId,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
...evt.total !== void 0 ? { total: evt.total } : {},
|
|
42
|
+
...evt.currency !== void 0 ? { currency: evt.currency } : {}
|
|
43
|
+
});
|
|
44
|
+
onSucceeded?.(evt);
|
|
37
45
|
},
|
|
38
46
|
[emit, sessionId, onSucceeded]
|
|
39
47
|
);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ThrottleCheckout.tsx","../src/index.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { PaymentEmbed } from '@usethrottle/checkout-react';\nimport type { ThrottleCheckoutProps, TelemetryEvent } from './types.js';\n\n/**\n * ThrottleCheckout — Phase 1 platform SDK wrapper.\n *\n * Wraps `<PaymentEmbed>` from `@usethrottle/checkout-react` and adds:\n * 1. Idempotency — settledRef ensures `onSucceeded` / `onFailed` fire at most once\n * per component lifetime, even if the iframe sends duplicate events.\n * 2. Telemetry — `onTelemetry` callback receives every lifecycle event with a\n * typed payload so workspaces can pipe to Datadog / Segment / etc.\n * 3. Brand theming — `theme.primary` + `theme.logo` are forwarded to the underlying\n * `<PaymentEmbed>` which appends them as URL query params on the\n * hosted checkout iframe src.\n */\nexport function ThrottleCheckout({\n sessionId,\n parentOrigin = '',\n baseUrl,\n theme,\n onSucceeded,\n onFailed,\n onCancelled,\n onTelemetry,\n}: ThrottleCheckoutProps): JSX.Element {\n // Idempotency guard — once a terminal event (success or failure) fires,\n // all subsequent duplicate events from the iframe are silently dropped.\n const settledRef = useRef(false);\n\n const emit = useCallback(\n (event: TelemetryEvent) => {\n onTelemetry?.(event);\n },\n [onTelemetry],\n );\n\n // Fire \"mounted\" telemetry once on initial render.\n useEffect(() => {\n emit({ type: 'mounted', sessionId, timestamp: Date.now() });\n // intentionally only on mount — sessionId identity change re-mounts anyway\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleReady = useCallback(() => {\n emit({ type: 'ready', sessionId, timestamp: Date.now() });\n }, [emit, sessionId]);\n\n const handleProcessing = useCallback(() => {\n emit({ type: 'processing', sessionId, timestamp: Date.now() });\n }, [emit, sessionId]);\n\n const handleSucceeded = useCallback(\n (
|
|
1
|
+
{"version":3,"sources":["../src/ThrottleCheckout.tsx","../src/index.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { PaymentEmbed } from '@usethrottle/checkout-react';\nimport type { ThrottleCheckoutProps, TelemetryEvent } from './types.js';\n\n/**\n * ThrottleCheckout — Phase 1 platform SDK wrapper.\n *\n * Wraps `<PaymentEmbed>` from `@usethrottle/checkout-react` and adds:\n * 1. Idempotency — settledRef ensures `onSucceeded` / `onFailed` fire at most once\n * per component lifetime, even if the iframe sends duplicate events.\n * 2. Telemetry — `onTelemetry` callback receives every lifecycle event with a\n * typed payload so workspaces can pipe to Datadog / Segment / etc.\n * 3. Brand theming — `theme.primary` + `theme.logo` are forwarded to the underlying\n * `<PaymentEmbed>` which appends them as URL query params on the\n * hosted checkout iframe src.\n */\nexport function ThrottleCheckout({\n sessionId,\n parentOrigin = '',\n baseUrl,\n theme,\n onSucceeded,\n onFailed,\n onCancelled,\n onTelemetry,\n}: ThrottleCheckoutProps): JSX.Element {\n // Idempotency guard — once a terminal event (success or failure) fires,\n // all subsequent duplicate events from the iframe are silently dropped.\n const settledRef = useRef(false);\n\n const emit = useCallback(\n (event: TelemetryEvent) => {\n onTelemetry?.(event);\n },\n [onTelemetry],\n );\n\n // Fire \"mounted\" telemetry once on initial render.\n useEffect(() => {\n emit({ type: 'mounted', sessionId, timestamp: Date.now() });\n // intentionally only on mount — sessionId identity change re-mounts anyway\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleReady = useCallback(() => {\n emit({ type: 'ready', sessionId, timestamp: Date.now() });\n }, [emit, sessionId]);\n\n const handleProcessing = useCallback(() => {\n emit({ type: 'processing', sessionId, timestamp: Date.now() });\n }, [emit, sessionId]);\n\n const handleSucceeded = useCallback(\n (evt: {\n orderId: string;\n paymentId: string;\n subscriptionId?: string;\n total?: number;\n currency?: string;\n lineItems?: import('./types.js').SucceededLineItem[];\n }) => {\n if (settledRef.current) return;\n settledRef.current = true;\n emit({\n type: 'succeeded',\n sessionId,\n orderId: evt.orderId,\n paymentId: evt.paymentId,\n timestamp: Date.now(),\n ...(evt.total !== undefined ? { total: evt.total } : {}),\n ...(evt.currency !== undefined ? { currency: evt.currency } : {}),\n });\n onSucceeded?.(evt);\n },\n [emit, sessionId, onSucceeded],\n );\n\n const handleFailed = useCallback(\n ({ code, message }: { code: string; message: string }) => {\n if (settledRef.current) return;\n settledRef.current = true;\n emit({ type: 'failed', sessionId, code, message, timestamp: Date.now() });\n onFailed?.({ code, message });\n },\n [emit, sessionId, onFailed],\n );\n\n const handleCanceled = useCallback(() => {\n emit({ type: 'cancelled', sessionId, timestamp: Date.now() });\n onCancelled?.();\n }, [emit, sessionId, onCancelled]);\n\n return (\n <PaymentEmbed\n sessionId={sessionId}\n parentOrigin={parentOrigin}\n {...(baseUrl !== undefined ? { baseUrl } : {})}\n primary={theme?.primary}\n logo={theme?.logo}\n onReady={handleReady}\n onProcessing={handleProcessing}\n onSucceeded={handleSucceeded}\n onFailed={handleFailed}\n onCanceled={handleCanceled}\n />\n );\n}\n","export { ThrottleCheckout } from './ThrottleCheckout.js';\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\nexport type {\n BrandTheme,\n TelemetryEvent,\n ThrottleCheckoutProps,\n SucceededLineItem,\n} from './types.js';\n"],"mappings":";AAAA,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,oBAAoB;AA4FzB;AA7EG,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AAGrC,QAAM,aAAa,OAAO,KAAK;AAE/B,QAAM,OAAO;AAAA,IACX,CAAC,UAA0B;AACzB,oBAAc,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAGA,YAAU,MAAM;AACd,SAAK,EAAE,MAAM,WAAW,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EAG5D,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,YAAY,MAAM;AACpC,SAAK,EAAE,MAAM,SAAS,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EAC1D,GAAG,CAAC,MAAM,SAAS,CAAC;AAEpB,QAAM,mBAAmB,YAAY,MAAM;AACzC,SAAK,EAAE,MAAM,cAAc,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EAC/D,GAAG,CAAC,MAAM,SAAS,CAAC;AAEpB,QAAM,kBAAkB;AAAA,IACtB,CAAC,QAOK;AACJ,UAAI,WAAW,QAAS;AACxB,iBAAW,UAAU;AACrB,WAAK;AAAA,QACH,MAAM;AAAA,QACN;AAAA,QACA,SAAS,IAAI;AAAA,QACb,WAAW,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,GAAI,IAAI,UAAU,SAAY,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC;AAAA,QACtD,GAAI,IAAI,aAAa,SAAY,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC;AAAA,MACjE,CAAC;AACD,oBAAc,GAAG;AAAA,IACnB;AAAA,IACA,CAAC,MAAM,WAAW,WAAW;AAAA,EAC/B;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,EAAE,MAAM,QAAQ,MAAyC;AACxD,UAAI,WAAW,QAAS;AACxB,iBAAW,UAAU;AACrB,WAAK,EAAE,MAAM,UAAU,WAAW,MAAM,SAAS,WAAW,KAAK,IAAI,EAAE,CAAC;AACxE,iBAAW,EAAE,MAAM,QAAQ,CAAC;AAAA,IAC9B;AAAA,IACA,CAAC,MAAM,WAAW,QAAQ;AAAA,EAC5B;AAEA,QAAM,iBAAiB,YAAY,MAAM;AACvC,SAAK,EAAE,MAAM,aAAa,WAAW,WAAW,KAAK,IAAI,EAAE,CAAC;AAC5D,kBAAc;AAAA,EAChB,GAAG,CAAC,MAAM,WAAW,WAAW,CAAC;AAEjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACC,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC5C,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,SAAS;AAAA,MACT,cAAc;AAAA,MACd,aAAa;AAAA,MACb,UAAU;AAAA,MACV,YAAY;AAAA;AAAA,EACd;AAEJ;;;ACzGA,SAAS,eAAe,uBAAuB;","names":[]}
|
package/dist/server.cjs
CHANGED
|
@@ -95,6 +95,22 @@ var CheckoutClient = class {
|
|
|
95
95
|
);
|
|
96
96
|
return normalizeCompleteResult(data);
|
|
97
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Read a checkout session's current state — `status` tells you whether the
|
|
100
|
+
* buyer is still in it (`open`, `processing`) or it has settled (`completed`,
|
|
101
|
+
* `cancelled`, `expired`). Use it to decide whether a session can be resumed
|
|
102
|
+
* or cancelled instead of tracking that yourself.
|
|
103
|
+
*/
|
|
104
|
+
async getSession(sessionId) {
|
|
105
|
+
const data = await this.request(
|
|
106
|
+
"GET",
|
|
107
|
+
`/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`
|
|
108
|
+
);
|
|
109
|
+
return {
|
|
110
|
+
...normalizeCheckoutSession(data),
|
|
111
|
+
status: requiredString(data?.status, "checkoutSession.status")
|
|
112
|
+
};
|
|
113
|
+
}
|
|
98
114
|
/**
|
|
99
115
|
* Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).
|
|
100
116
|
* Idempotent — cancelling an already-cancelled session is a no-op; a completed
|
|
@@ -221,7 +237,7 @@ function normalizeEmbedToken(raw) {
|
|
|
221
237
|
currency: optionalString(raw?.currency) ?? "USD",
|
|
222
238
|
hostedUrl: optionalString(raw?.hostedUrl) ?? void 0,
|
|
223
239
|
embedUrl: optionalString(raw?.embedUrl) ?? void 0,
|
|
224
|
-
|
|
240
|
+
processorInstanceId: optionalString(raw?.processorInstanceId) ?? void 0,
|
|
225
241
|
merchantAccountId: optionalString(raw?.merchantAccountId) ?? void 0
|
|
226
242
|
};
|
|
227
243
|
}
|
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { ThrottleError } from '@usethrottle/errors';\n\nexport type PaymentMethod = 'net30' | 'card' | 'gr4vy';\nexport type SubscriptionInterval = 'weekly' | 'monthly' | 'quarterly' | 'yearly';\nexport type CheckoutEmbedMode = 'checkout-full' | 'payment-only';\nexport type CheckoutEmbedRoute = 'c' | 's';\n\nexport interface CheckoutClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n}\n\nexport interface CheckoutAddress {\n firstName: string;\n lastName: string;\n company?: string;\n addressLine1: string;\n addressLine2?: string;\n city: string;\n stateProvince: string;\n postalCode: string;\n countryCode: string;\n phone?: string;\n}\n\nexport interface CheckoutCustomerAddressInput {\n firstName?: string;\n lastName?: string;\n phone?: string;\n addressLine1?: string;\n addressLine2?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n country?: string;\n}\n\nexport interface CheckoutCustomerInput {\n customerId?: string;\n externalCustomerId?: string;\n email?: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n shippingAddress?: CheckoutCustomerAddressInput;\n billingAddress?: CheckoutCustomerAddressInput;\n metadata?: Record<string, unknown>;\n}\n\nexport interface RecurringIntentInput {\n plan: string;\n interval: SubscriptionInterval;\n amount?: number;\n trialDays?: number;\n planName?: string;\n create?: 'auto' | 'manual';\n}\n\nexport interface CheckoutCollectInput {\n shippingAddress?: boolean;\n billingAddress?: boolean;\n}\n\nexport interface CheckoutPaymentTermsInput {\n netN?: number | null;\n}\n\nexport interface CreateCheckoutSessionInput {\n applicationId: string;\n cartId?: string;\n externalCartId?: string;\n customerEmail?: string;\n customer?: CheckoutCustomerInput;\n returnUrl: string;\n cancelUrl: string;\n allowedMethods?: string[];\n paymentTerms?: CheckoutPaymentTermsInput;\n recurring?: RecurringIntentInput;\n collect?: CheckoutCollectInput;\n metadata?: Record<string, unknown>;\n discountCode?: string;\n}\n\nexport interface CheckoutSession {\n sessionId: string;\n id?: string;\n checkoutUrl?: string;\n hostedUrl?: string;\n embedUrl?: string;\n embedToken?: string;\n expiresAt?: string;\n [key: string]: unknown;\n}\n\nexport interface Net30Acceptance {\n termsHash: string;\n acceptedAt: string;\n companyName: string;\n billingEmail: string;\n}\n\nexport interface CompleteCheckoutSessionInput {\n email?: string;\n shippingAddress?: CheckoutAddress;\n billingAddress?: CheckoutAddress;\n billingSameAsShipping?: boolean;\n paymentMethod: PaymentMethod;\n netDays?: number;\n termsAccepted?: boolean;\n termsSnapshot?: string;\n invoiceNumber?: string;\n net30Acceptance?: Net30Acceptance;\n paymentToken?: string;\n gr4vyCheckoutSessionId?: string;\n gr4vyTransactionId?: string;\n}\n\nexport interface CompleteCheckoutSessionResult {\n orderId: string;\n orderNumber?: string;\n paymentId?: string;\n total?: number;\n currency?: string;\n status?: string;\n paymentStatus?: string;\n [key: string]: unknown;\n}\n\nexport interface CreateEmbedTokenInput {\n externalCartId?: string;\n amount: number;\n currency: string;\n country?: string;\n // NOTE: `allowedMethods` is intentionally NOT accepted here. A payment-only\n // Gr4vy embed cannot restrict payment methods (the Gr4vy widget renders the\n // methods configured on your Gr4vy connection). The server rejects it with\n // `allowed_methods_unsupported`. To restrict methods, configure the connection\n // or use the full hosted checkout, where allowedMethods filters the selection.\n}\n\nexport interface CreateEmbedTokenResult {\n embedToken: string;\n checkoutSessionId: string;\n amount: number;\n currency: string;\n hostedUrl?: string;\n embedUrl?: string;\n gr4vyId?: string;\n merchantAccountId?: string;\n [key: string]: unknown;\n}\n\nexport interface CheckoutOrder {\n id: string;\n orderNumber?: string;\n status: string;\n paymentStatus: string | null;\n currency: string;\n subtotal: number;\n taxTotal: number;\n shippingTotal: number;\n total: number;\n metadata?: Record<string, unknown>;\n payments?: CheckoutPayment[];\n [key: string]: unknown;\n}\n\nexport interface ListOrdersOptions {\n customerId?: string;\n cursor?: string;\n limit?: number;\n status?: string;\n paymentStatus?: string;\n}\n\nexport interface PaginatedOrders {\n data: CheckoutOrder[];\n pagination?: {\n cursor: string | null;\n hasMore: boolean;\n };\n}\n\nexport interface CheckoutPayment {\n id: string;\n orderId?: string;\n processor?: string;\n processorTransactionId?: string | null;\n amount?: number;\n currency?: string;\n status?: string;\n method?: string;\n createdAt?: string;\n transactions?: CheckoutPaymentTransaction[];\n [key: string]: unknown;\n}\n\nexport interface CheckoutPaymentTransaction {\n id: string;\n paymentId?: string;\n type?: string;\n amount?: number;\n currency?: string;\n status?: string;\n createdAt?: string;\n [key: string]: unknown;\n}\n\nexport interface BuildCheckoutUrlOptions {\n checkoutOrigin?: string;\n sessionId: string;\n parentOrigin?: string;\n mode?: CheckoutEmbedMode;\n route?: CheckoutEmbedRoute;\n primary?: string;\n logo?: string;\n}\n\nexport interface ThrottleEnvelope<T> {\n data?: T;\n meta?: Record<string, unknown>;\n error?: {\n code?: string;\n message?: string;\n details?: unknown;\n };\n}\n\n/**\n * Thrown on a non-2xx response from the Throttle Checkout API.\n *\n * Extends the shared {@link ThrottleError} so a single\n * `catch (e) { if (e instanceof ThrottleError) … }` covers errors from every\n * Throttle SDK. `instanceof ThrottleCheckoutError` keeps working for existing\n * code.\n */\nexport class ThrottleCheckoutError extends ThrottleError {\n constructor(args: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n body?: unknown;\n }) {\n super(args);\n this.name = 'ThrottleCheckoutError';\n }\n}\n\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n\nexport class CheckoutClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly timeoutMs: number;\n\n constructor(opts: CheckoutClientOptions) {\n if (!opts.apiKey) throw new Error('CheckoutClient: apiKey is required');\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('CheckoutClient: fetch is required');\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const envelope = await this.requestEnvelope<T>(method, path, body);\n if (Object.prototype.hasOwnProperty.call(envelope, 'data')) {\n return envelope.data as T;\n }\n return envelope as T;\n }\n\n async requestEnvelope<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n\n try {\n const res = await this.fetchImpl(toAbsoluteUrl(this.baseUrl, path), {\n method,\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: ctrl.signal,\n });\n\n if (res.status === 204) return { data: undefined as T };\n\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) {\n throw new ThrottleCheckoutError({\n code: json.error?.code ?? 'unknown_error',\n message: json.error?.message ?? `HTTP ${res.status}`,\n statusCode: res.status,\n details: json.error?.details,\n body: json,\n });\n }\n return json;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async createSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout/sessions', input);\n return normalizeCheckoutSession(data);\n }\n\n async completeSession(\n sessionId: string,\n input: CompleteCheckoutSessionInput,\n ): Promise<CompleteCheckoutSessionResult> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}/complete`,\n input,\n );\n return normalizeCompleteResult(data);\n }\n\n /**\n * Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).\n * Idempotent — cancelling an already-cancelled session is a no-op; a completed\n * session cannot be cancelled (the API returns 422 `already_completed`).\n */\n async cancelSession(sessionId: string): Promise<void> {\n await this.request<unknown>(\n 'DELETE',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`,\n );\n }\n\n async createEmbedToken(input: CreateEmbedTokenInput): Promise<CreateEmbedTokenResult> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout-sessions/embed-token', input);\n return normalizeEmbedToken(data);\n }\n\n async getOrder(orderId: string): Promise<CheckoutOrder> {\n const data = await this.request<unknown>('GET', `/api/v1/orders/${encodeURIComponent(orderId)}`);\n return normalizeOrder(data);\n }\n\n async listOrders(options: ListOrdersOptions = {}): Promise<PaginatedOrders> {\n const params = new URLSearchParams();\n if (options.customerId) params.set('customerId', options.customerId);\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.status) params.set('status', options.status);\n if (options.paymentStatus) params.set('paymentStatus', options.paymentStatus);\n\n const query = params.toString();\n const envelope = await this.requestEnvelope<unknown[]>(\n 'GET',\n `/api/v1/orders${query ? `?${query}` : ''}`,\n );\n return {\n data: (envelope.data ?? []).map(normalizeOrder),\n pagination: envelope.meta?.pagination as PaginatedOrders['pagination'],\n };\n }\n\n async listOrderPayments(orderId: string): Promise<CheckoutPayment[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/orders/${encodeURIComponent(orderId)}/payments`,\n );\n return (data ?? []).map(normalizePayment);\n }\n\n async listPaymentTransactions(paymentId: string): Promise<CheckoutPaymentTransaction[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/payments/${encodeURIComponent(paymentId)}/transactions`,\n );\n return (data ?? []).map(normalizeTransaction);\n }\n\n async getOrderWithPayments(orderId: string): Promise<CheckoutOrder> {\n const order = await this.getOrder(orderId);\n const payments = await this.listOrderPayments(orderId);\n return {\n ...order,\n payments: await Promise.all(\n payments.map(async (payment) => ({\n ...payment,\n transactions: payment.id ? await this.listPaymentTransactions(payment.id) : [],\n })),\n ),\n };\n }\n}\n\nexport function createCheckoutClient(opts: CheckoutClientOptions): CheckoutClient {\n return new CheckoutClient(opts);\n}\n\nexport function buildCheckoutHostedUrl(options: BuildCheckoutUrlOptions): string {\n const route = options.route ?? 's';\n const base = (options.checkoutOrigin ?? 'https://checkout.usethrottle.dev').replace(/\\/+$/, '');\n return `${base}/${route}/${encodeURIComponent(options.sessionId)}`;\n}\n\nexport function buildCheckoutEmbedUrl(options: BuildCheckoutUrlOptions): string {\n const baseUrl = buildCheckoutHostedUrl({\n checkoutOrigin: options.checkoutOrigin,\n sessionId: options.sessionId,\n route: options.route ?? 'c',\n });\n const params = new URLSearchParams({\n embed: '1',\n mode: options.mode ?? 'payment-only',\n ...(options.parentOrigin ? { parentOrigin: options.parentOrigin.replace(/\\/+$/, '') } : {}),\n });\n if (options.primary) params.set('primary', options.primary);\n if (options.logo) params.set('logo', options.logo);\n return `${baseUrl}?${params.toString()}`;\n}\n\nfunction toAbsoluteUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//i.test(path)) return path;\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n}\n\nfunction normalizeCheckoutSession(raw: any): CheckoutSession {\n const sessionId = raw?.sessionId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n id: optionalString(raw?.id) ?? undefined,\n sessionId: requiredString(sessionId, 'checkoutSession.sessionId'),\n checkoutUrl: optionalString(raw?.checkoutUrl) ?? undefined,\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n embedToken: optionalString(raw?.embedToken) ?? undefined,\n expiresAt: optionalString(raw?.expiresAt) ?? undefined,\n };\n}\n\nfunction normalizeCompleteResult(raw: any): CompleteCheckoutSessionResult {\n const orderId = raw?.orderId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n orderId: requiredString(orderId, 'checkoutComplete.orderId'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n total: optionalNumber(raw?.total),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n paymentStatus: optionalString(raw?.paymentStatus) ?? undefined,\n };\n}\n\nfunction normalizeEmbedToken(raw: any): CreateEmbedTokenResult {\n return {\n ...withoutSnakeKeys(raw),\n embedToken: requiredString(raw?.embedToken, 'embedToken.embedToken'),\n checkoutSessionId: requiredString(raw?.checkoutSessionId, 'embedToken.checkoutSessionId'),\n amount: Number(raw?.amount ?? 0),\n currency: optionalString(raw?.currency) ?? 'USD',\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n gr4vyId: optionalString(raw?.gr4vyId) ?? undefined,\n merchantAccountId: optionalString(raw?.merchantAccountId) ?? undefined,\n };\n}\n\nfunction normalizeOrder(raw: any): CheckoutOrder {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'order.id'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n status: optionalString(raw?.status) ?? 'processing',\n paymentStatus: optionalString(raw?.paymentStatus),\n currency: optionalString(raw?.currency) ?? 'USD',\n subtotal: Number(raw?.subtotal ?? 0),\n taxTotal: Number(raw?.taxTotal ?? 0),\n shippingTotal: Number(raw?.shippingTotal ?? 0),\n total: Number(raw?.total ?? 0),\n metadata: objectOrUndefined(raw?.metadata),\n payments: Array.isArray(raw?.payments) ? raw.payments.map(normalizePayment) : undefined,\n };\n}\n\nfunction normalizePayment(raw: any): CheckoutPayment {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'payment.id'),\n orderId: optionalString(raw?.orderId) ?? undefined,\n processor: optionalString(raw?.processor) ?? undefined,\n processorTransactionId:\n optionalString(raw?.processorTransactionId) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n method: optionalString(raw?.method) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n transactions: Array.isArray(raw?.transactions)\n ? raw.transactions.map(normalizeTransaction)\n : undefined,\n };\n}\n\nfunction normalizeTransaction(raw: any): CheckoutPaymentTransaction {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'transaction.id'),\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n type: optionalString(raw?.type) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n };\n}\n\nfunction withoutSnakeKeys(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).filter(([key]) => !key.includes('_')),\n );\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction optionalNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction objectOrUndefined(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"],"mappings":"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","names":["import_errors"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { ThrottleError } from '@usethrottle/errors';\n\n/**\n * `'embedded'` completes a card payment taken by the payment embed; `'net30'`\n * issues an invoice on terms. `'card'` names the card category in\n * `allowedMethods` — `completeSession` rejects it with 422\n * `payment_method_not_supported`. Use `'embedded'`.\n */\nexport type PaymentMethod = 'net30' | 'card' | 'embedded';\nexport type SubscriptionInterval = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';\nexport type CheckoutEmbedMode = 'checkout-full' | 'payment-only';\nexport type CheckoutEmbedRoute = 'c' | 's';\n\nexport interface CheckoutClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n}\n\nexport interface CheckoutAddress {\n firstName: string;\n lastName: string;\n company?: string;\n addressLine1: string;\n addressLine2?: string;\n city: string;\n stateProvince: string;\n postalCode: string;\n countryCode: string;\n phone?: string;\n}\n\nexport interface CheckoutCustomerAddressInput {\n firstName?: string;\n lastName?: string;\n phone?: string;\n addressLine1?: string;\n addressLine2?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n country?: string;\n}\n\nexport interface CheckoutCustomerInput {\n customerId?: string;\n externalCustomerId?: string;\n email?: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n shippingAddress?: CheckoutCustomerAddressInput;\n billingAddress?: CheckoutCustomerAddressInput;\n metadata?: Record<string, unknown>;\n}\n\nexport interface RecurringIntentInput {\n plan: string;\n interval: SubscriptionInterval;\n amount?: number;\n trialDays?: number;\n planName?: string;\n create?: 'auto' | 'manual';\n}\n\nexport interface CheckoutCollectInput {\n shippingAddress?: boolean;\n billingAddress?: boolean;\n}\n\nexport interface CheckoutPaymentTermsInput {\n netN?: number | null;\n}\n\nexport interface CreateCheckoutSessionInput {\n applicationId: string;\n cartId?: string;\n externalCartId?: string;\n customerEmail?: string;\n customer?: CheckoutCustomerInput;\n returnUrl: string;\n cancelUrl: string;\n allowedMethods?: string[];\n paymentTerms?: CheckoutPaymentTermsInput;\n recurring?: RecurringIntentInput;\n collect?: CheckoutCollectInput;\n metadata?: Record<string, unknown>;\n discountCode?: string;\n}\n\nexport interface CheckoutSession {\n sessionId: string;\n id?: string;\n checkoutUrl?: string;\n hostedUrl?: string;\n embedUrl?: string;\n embedToken?: string;\n expiresAt?: string;\n [key: string]: unknown;\n}\n\nexport type CheckoutSessionStatus =\n | 'open'\n | 'customer_set'\n | 'address_set'\n | 'processing'\n | 'completed'\n | 'expired'\n | 'cancelled';\n\n/** A session as read back by `getSession` — the create response plus its current state. */\nexport interface CheckoutSessionDetails extends CheckoutSession {\n status: CheckoutSessionStatus;\n cartId?: string | null;\n customerId?: string | null;\n customerEmail?: string | null;\n shippingAddress?: CheckoutAddress | null;\n billingAddress?: CheckoutAddress | null;\n returnUrl?: string;\n cancelUrl?: string;\n completedAt?: string | null;\n allowedMethods?: string[] | null;\n collectShipping?: boolean;\n collectBilling?: boolean;\n discountCode?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Net30Acceptance {\n termsHash: string;\n acceptedAt: string;\n companyName: string;\n billingEmail: string;\n}\n\nexport interface CompleteCheckoutSessionInput {\n email?: string;\n shippingAddress?: CheckoutAddress;\n billingAddress?: CheckoutAddress;\n billingSameAsShipping?: boolean;\n paymentMethod: PaymentMethod;\n netDays?: number;\n termsAccepted?: boolean;\n termsSnapshot?: string;\n invoiceNumber?: string;\n net30Acceptance?: Net30Acceptance;\n paymentToken?: string;\n processorCheckoutSessionId?: string;\n processorTransactionId?: string;\n}\n\nexport interface CompleteCheckoutSessionResult {\n orderId: string;\n orderNumber?: string;\n paymentId?: string;\n total?: number;\n currency?: string;\n status?: string;\n paymentStatus?: string;\n [key: string]: unknown;\n}\n\nexport interface CreateEmbedTokenInput {\n externalCartId?: string;\n amount: number;\n currency: string;\n country?: string;\n // NOTE: `allowedMethods` is intentionally NOT accepted here. A payment-only\n // Gr4vy embed cannot restrict payment methods (the Gr4vy widget renders the\n // methods configured on your Gr4vy connection). The server rejects it with\n // `allowed_methods_unsupported`. To restrict methods, configure the connection\n // or use the full hosted checkout, where allowedMethods filters the selection.\n}\n\nexport interface CreateEmbedTokenResult {\n embedToken: string;\n checkoutSessionId: string;\n amount: number;\n currency: string;\n hostedUrl?: string;\n embedUrl?: string;\n processorInstanceId?: string;\n merchantAccountId?: string;\n [key: string]: unknown;\n}\n\nexport interface CheckoutOrder {\n id: string;\n orderNumber?: string;\n status: string;\n paymentStatus: string | null;\n currency: string;\n subtotal: number;\n taxTotal: number;\n shippingTotal: number;\n total: number;\n metadata?: Record<string, unknown>;\n payments?: CheckoutPayment[];\n [key: string]: unknown;\n}\n\nexport interface ListOrdersOptions {\n customerId?: string;\n cursor?: string;\n limit?: number;\n status?: string;\n paymentStatus?: string;\n}\n\nexport interface PaginatedOrders {\n data: CheckoutOrder[];\n pagination?: {\n cursor: string | null;\n hasMore: boolean;\n };\n}\n\nexport interface CheckoutPayment {\n id: string;\n orderId?: string;\n processor?: string;\n processorTransactionId?: string | null;\n amount?: number;\n currency?: string;\n status?: string;\n method?: string;\n createdAt?: string;\n transactions?: CheckoutPaymentTransaction[];\n [key: string]: unknown;\n}\n\nexport interface CheckoutPaymentTransaction {\n id: string;\n paymentId?: string;\n type?: string;\n amount?: number;\n currency?: string;\n status?: string;\n createdAt?: string;\n [key: string]: unknown;\n}\n\nexport interface BuildCheckoutUrlOptions {\n checkoutOrigin?: string;\n sessionId: string;\n parentOrigin?: string;\n mode?: CheckoutEmbedMode;\n route?: CheckoutEmbedRoute;\n primary?: string;\n logo?: string;\n}\n\nexport interface ThrottleEnvelope<T> {\n data?: T;\n meta?: Record<string, unknown>;\n error?: {\n code?: string;\n message?: string;\n details?: unknown;\n };\n}\n\n/**\n * Thrown on a non-2xx response from the Throttle Checkout API.\n *\n * Extends the shared {@link ThrottleError} so a single\n * `catch (e) { if (e instanceof ThrottleError) … }` covers errors from every\n * Throttle SDK. `instanceof ThrottleCheckoutError` keeps working for existing\n * code.\n */\nexport class ThrottleCheckoutError extends ThrottleError {\n constructor(args: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n body?: unknown;\n }) {\n super(args);\n this.name = 'ThrottleCheckoutError';\n }\n}\n\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n\nexport class CheckoutClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly timeoutMs: number;\n\n constructor(opts: CheckoutClientOptions) {\n if (!opts.apiKey) throw new Error('CheckoutClient: apiKey is required');\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('CheckoutClient: fetch is required');\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const envelope = await this.requestEnvelope<T>(method, path, body);\n if (Object.prototype.hasOwnProperty.call(envelope, 'data')) {\n return envelope.data as T;\n }\n return envelope as T;\n }\n\n async requestEnvelope<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n\n try {\n const res = await this.fetchImpl(toAbsoluteUrl(this.baseUrl, path), {\n method,\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: ctrl.signal,\n });\n\n if (res.status === 204) return { data: undefined as T };\n\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) {\n throw new ThrottleCheckoutError({\n code: json.error?.code ?? 'unknown_error',\n message: json.error?.message ?? `HTTP ${res.status}`,\n statusCode: res.status,\n details: json.error?.details,\n body: json,\n });\n }\n return json;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async createSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout/sessions', input);\n return normalizeCheckoutSession(data);\n }\n\n async completeSession(\n sessionId: string,\n input: CompleteCheckoutSessionInput,\n ): Promise<CompleteCheckoutSessionResult> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}/complete`,\n input,\n );\n return normalizeCompleteResult(data);\n }\n\n /**\n * Read a checkout session's current state — `status` tells you whether the\n * buyer is still in it (`open`, `processing`) or it has settled (`completed`,\n * `cancelled`, `expired`). Use it to decide whether a session can be resumed\n * or cancelled instead of tracking that yourself.\n */\n async getSession(sessionId: string): Promise<CheckoutSessionDetails> {\n const data = await this.request<any>(\n 'GET',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`,\n );\n return {\n ...normalizeCheckoutSession(data),\n status: requiredString(data?.status, 'checkoutSession.status') as CheckoutSessionStatus,\n };\n }\n\n /**\n * Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).\n * Idempotent — cancelling an already-cancelled session is a no-op; a completed\n * session cannot be cancelled (the API returns 422 `already_completed`).\n */\n async cancelSession(sessionId: string): Promise<void> {\n await this.request<unknown>(\n 'DELETE',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`,\n );\n }\n\n async createEmbedToken(input: CreateEmbedTokenInput): Promise<CreateEmbedTokenResult> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout-sessions/embed-token', input);\n return normalizeEmbedToken(data);\n }\n\n async getOrder(orderId: string): Promise<CheckoutOrder> {\n const data = await this.request<unknown>('GET', `/api/v1/orders/${encodeURIComponent(orderId)}`);\n return normalizeOrder(data);\n }\n\n async listOrders(options: ListOrdersOptions = {}): Promise<PaginatedOrders> {\n const params = new URLSearchParams();\n if (options.customerId) params.set('customerId', options.customerId);\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.status) params.set('status', options.status);\n if (options.paymentStatus) params.set('paymentStatus', options.paymentStatus);\n\n const query = params.toString();\n const envelope = await this.requestEnvelope<unknown[]>(\n 'GET',\n `/api/v1/orders${query ? `?${query}` : ''}`,\n );\n return {\n data: (envelope.data ?? []).map(normalizeOrder),\n pagination: envelope.meta?.pagination as PaginatedOrders['pagination'],\n };\n }\n\n async listOrderPayments(orderId: string): Promise<CheckoutPayment[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/orders/${encodeURIComponent(orderId)}/payments`,\n );\n return (data ?? []).map(normalizePayment);\n }\n\n async listPaymentTransactions(paymentId: string): Promise<CheckoutPaymentTransaction[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/payments/${encodeURIComponent(paymentId)}/transactions`,\n );\n return (data ?? []).map(normalizeTransaction);\n }\n\n async getOrderWithPayments(orderId: string): Promise<CheckoutOrder> {\n const order = await this.getOrder(orderId);\n const payments = await this.listOrderPayments(orderId);\n return {\n ...order,\n payments: await Promise.all(\n payments.map(async (payment) => ({\n ...payment,\n transactions: payment.id ? await this.listPaymentTransactions(payment.id) : [],\n })),\n ),\n };\n }\n}\n\nexport function createCheckoutClient(opts: CheckoutClientOptions): CheckoutClient {\n return new CheckoutClient(opts);\n}\n\nexport function buildCheckoutHostedUrl(options: BuildCheckoutUrlOptions): string {\n const route = options.route ?? 's';\n const base = (options.checkoutOrigin ?? 'https://checkout.usethrottle.dev').replace(/\\/+$/, '');\n return `${base}/${route}/${encodeURIComponent(options.sessionId)}`;\n}\n\nexport function buildCheckoutEmbedUrl(options: BuildCheckoutUrlOptions): string {\n const baseUrl = buildCheckoutHostedUrl({\n checkoutOrigin: options.checkoutOrigin,\n sessionId: options.sessionId,\n route: options.route ?? 'c',\n });\n const params = new URLSearchParams({\n embed: '1',\n mode: options.mode ?? 'payment-only',\n ...(options.parentOrigin ? { parentOrigin: options.parentOrigin.replace(/\\/+$/, '') } : {}),\n });\n if (options.primary) params.set('primary', options.primary);\n if (options.logo) params.set('logo', options.logo);\n return `${baseUrl}?${params.toString()}`;\n}\n\nfunction toAbsoluteUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//i.test(path)) return path;\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n}\n\nfunction normalizeCheckoutSession(raw: any): CheckoutSession {\n const sessionId = raw?.sessionId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n id: optionalString(raw?.id) ?? undefined,\n sessionId: requiredString(sessionId, 'checkoutSession.sessionId'),\n checkoutUrl: optionalString(raw?.checkoutUrl) ?? undefined,\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n embedToken: optionalString(raw?.embedToken) ?? undefined,\n expiresAt: optionalString(raw?.expiresAt) ?? undefined,\n };\n}\n\nfunction normalizeCompleteResult(raw: any): CompleteCheckoutSessionResult {\n const orderId = raw?.orderId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n orderId: requiredString(orderId, 'checkoutComplete.orderId'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n total: optionalNumber(raw?.total),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n paymentStatus: optionalString(raw?.paymentStatus) ?? undefined,\n };\n}\n\nfunction normalizeEmbedToken(raw: any): CreateEmbedTokenResult {\n return {\n ...withoutSnakeKeys(raw),\n embedToken: requiredString(raw?.embedToken, 'embedToken.embedToken'),\n checkoutSessionId: requiredString(raw?.checkoutSessionId, 'embedToken.checkoutSessionId'),\n amount: Number(raw?.amount ?? 0),\n currency: optionalString(raw?.currency) ?? 'USD',\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n processorInstanceId: optionalString(raw?.processorInstanceId) ?? undefined,\n merchantAccountId: optionalString(raw?.merchantAccountId) ?? undefined,\n };\n}\n\nfunction normalizeOrder(raw: any): CheckoutOrder {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'order.id'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n status: optionalString(raw?.status) ?? 'processing',\n paymentStatus: optionalString(raw?.paymentStatus),\n currency: optionalString(raw?.currency) ?? 'USD',\n subtotal: Number(raw?.subtotal ?? 0),\n taxTotal: Number(raw?.taxTotal ?? 0),\n shippingTotal: Number(raw?.shippingTotal ?? 0),\n total: Number(raw?.total ?? 0),\n metadata: objectOrUndefined(raw?.metadata),\n payments: Array.isArray(raw?.payments) ? raw.payments.map(normalizePayment) : undefined,\n };\n}\n\nfunction normalizePayment(raw: any): CheckoutPayment {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'payment.id'),\n orderId: optionalString(raw?.orderId) ?? undefined,\n processor: optionalString(raw?.processor) ?? undefined,\n processorTransactionId:\n optionalString(raw?.processorTransactionId) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n method: optionalString(raw?.method) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n transactions: Array.isArray(raw?.transactions)\n ? raw.transactions.map(normalizeTransaction)\n : undefined,\n };\n}\n\nfunction normalizeTransaction(raw: any): CheckoutPaymentTransaction {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'transaction.id'),\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n type: optionalString(raw?.type) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n };\n}\n\nfunction withoutSnakeKeys(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).filter(([key]) => !key.includes('_')),\n );\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction optionalNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction objectOrUndefined(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA8B;AA4R9B,IAAAA,iBAA+C;AAbxC,IAAM,wBAAN,cAAoC,4BAAc;AAAA,EACvD,YAAY,MAMT;AACD,UAAM,IAAI;AACV,SAAK,OAAO;AAAA,EACd;AACF;AAIO,IAAM,iBAAN,MAAqB;AAAA,EAM1B,YAAY,MAA6B;AACvC,QAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,oCAAoC;AACtE,UAAM,YAAY,KAAK,SAAS,WAAW;AAC3C,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,mCAAmC;AACnE,SAAK,SAAS,KAAK;AACnB,SAAK,WAAW,KAAK,WAAW,+BAA+B,QAAQ,QAAQ,EAAE;AACjF,SAAK,YAAY;AACjB,SAAK,YAAY,KAAK,aAAa;AAAA,EACrC;AAAA,EAEA,MAAM,QAAqB,QAAgB,MAAc,MAA4B;AACnF,UAAM,WAAW,MAAM,KAAK,gBAAmB,QAAQ,MAAM,IAAI;AACjE,QAAI,OAAO,UAAU,eAAe,KAAK,UAAU,MAAM,GAAG;AAC1D,aAAO,SAAS;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBACJ,QACA,MACA,MAC8B;AAC9B,UAAM,OAAO,IAAI,gBAAgB;AACjC,UAAM,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,SAAS;AAE3D,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,UAAU,cAAc,KAAK,SAAS,IAAI,GAAG;AAAA,QAClE;AAAA,QACA,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,aAAa,KAAK;AAAA,QACpB;AAAA,QACA,MAAM,SAAS,SAAY,KAAK,UAAU,IAAI,IAAI;AAAA,QAClD,QAAQ,KAAK;AAAA,MACf,CAAC;AAED,UAAI,IAAI,WAAW,IAAK,QAAO,EAAE,MAAM,OAAe;AAEtD,YAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,sBAAsB;AAAA,UAC9B,MAAM,KAAK,OAAO,QAAQ;AAAA,UAC1B,SAAS,KAAK,OAAO,WAAW,QAAQ,IAAI,MAAM;AAAA,UAClD,YAAY,IAAI;AAAA,UAChB,SAAS,KAAK,OAAO;AAAA,UACrB,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,OAA6D;AAC/E,UAAM,OAAO,MAAM,KAAK,QAAiB,QAAQ,6BAA6B,KAAK;AACnF,WAAO,yBAAyB,IAAI;AAAA,EACtC;AAAA,EAEA,MAAM,gBACJ,WACA,OACwC;AACxC,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,6BAA6B,mBAAmB,SAAS,CAAC;AAAA,MAC1D;AAAA,IACF;AACA,WAAO,wBAAwB,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,WAAoD;AACnE,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,6BAA6B,mBAAmB,SAAS,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,MACL,GAAG,yBAAyB,IAAI;AAAA,MAChC,QAAQ,eAAe,MAAM,QAAQ,wBAAwB;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,WAAkC;AACpD,UAAM,KAAK;AAAA,MACT;AAAA,MACA,6BAA6B,mBAAmB,SAAS,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,OAA+D;AACpF,UAAM,OAAO,MAAM,KAAK,QAAiB,QAAQ,yCAAyC,KAAK;AAC/F,WAAO,oBAAoB,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,SAAS,SAAyC;AACtD,UAAM,OAAO,MAAM,KAAK,QAAiB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,EAAE;AAC/F,WAAO,eAAe,IAAI;AAAA,EAC5B;AAAA,EAEA,MAAM,WAAW,UAA6B,CAAC,GAA6B;AAC1E,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,QAAQ,WAAY,QAAO,IAAI,cAAc,QAAQ,UAAU;AACnE,QAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AACvD,QAAI,QAAQ,UAAU,OAAW,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAC1E,QAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AACvD,QAAI,QAAQ,cAAe,QAAO,IAAI,iBAAiB,QAAQ,aAAa;AAE5E,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA,iBAAiB,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,IAC3C;AACA,WAAO;AAAA,MACL,OAAO,SAAS,QAAQ,CAAC,GAAG,IAAI,cAAc;AAAA,MAC9C,YAAY,SAAS,MAAM;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,SAA6C;AACnE,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,kBAAkB,mBAAmB,OAAO,CAAC;AAAA,IAC/C;AACA,YAAQ,QAAQ,CAAC,GAAG,IAAI,gBAAgB;AAAA,EAC1C;AAAA,EAEA,MAAM,wBAAwB,WAA0D;AACtF,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,oBAAoB,mBAAmB,SAAS,CAAC;AAAA,IACnD;AACA,YAAQ,QAAQ,CAAC,GAAG,IAAI,oBAAoB;AAAA,EAC9C;AAAA,EAEA,MAAM,qBAAqB,SAAyC;AAClE,UAAM,QAAQ,MAAM,KAAK,SAAS,OAAO;AACzC,UAAM,WAAW,MAAM,KAAK,kBAAkB,OAAO;AACrD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,MAAM,QAAQ;AAAA,QACtB,SAAS,IAAI,OAAO,aAAa;AAAA,UAC/B,GAAG;AAAA,UACH,cAAc,QAAQ,KAAK,MAAM,KAAK,wBAAwB,QAAQ,EAAE,IAAI,CAAC;AAAA,QAC/E,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,MAA6C;AAChF,SAAO,IAAI,eAAe,IAAI;AAChC;AAEO,SAAS,uBAAuB,SAA0C;AAC/E,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,QAAQ,QAAQ,kBAAkB,oCAAoC,QAAQ,QAAQ,EAAE;AAC9F,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,mBAAmB,QAAQ,SAAS,CAAC;AAClE;AAEO,SAAS,sBAAsB,SAA0C;AAC9E,QAAM,UAAU,uBAAuB;AAAA,IACrC,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,OAAO,QAAQ,SAAS;AAAA,EAC1B,CAAC;AACD,QAAM,SAAS,IAAI,gBAAgB;AAAA,IACjC,OAAO;AAAA,IACP,MAAM,QAAQ,QAAQ;AAAA,IACtB,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,QAAQ,QAAQ,EAAE,EAAE,IAAI,CAAC;AAAA,EAC3F,CAAC;AACD,MAAI,QAAQ,QAAS,QAAO,IAAI,WAAW,QAAQ,OAAO;AAC1D,MAAI,QAAQ,KAAM,QAAO,IAAI,QAAQ,QAAQ,IAAI;AACjD,SAAO,GAAG,OAAO,IAAI,OAAO,SAAS,CAAC;AACxC;AAEA,SAAS,cAAc,SAAiB,MAAsB;AAC5D,MAAI,gBAAgB,KAAK,IAAI,EAAG,QAAO;AACvC,SAAO,GAAG,OAAO,GAAG,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,EAAE;AAC9D;AAEA,SAAS,yBAAyB,KAA2B;AAC3D,QAAM,YAAY,KAAK,aAAa,KAAK;AACzC,SAAO;AAAA,IACL,GAAG,iBAAiB,GAAG;AAAA,IACvB,IAAI,eAAe,KAAK,EAAE,KAAK;AAAA,IAC/B,WAAW,eAAe,WAAW,2BAA2B;AAAA,IAChE,aAAa,eAAe,KAAK,WAAW,KAAK;AAAA,IACjD,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,IAC7C,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,YAAY,eAAe,KAAK,UAAU,KAAK;AAAA,IAC/C,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,EAC/C;AACF;AAEA,SAAS,wBAAwB,KAAyC;AACxE,QAAM,UAAU,KAAK,WAAW,KAAK;AACrC,SAAO;AAAA,IACL,GAAG,iBAAiB,GAAG;AAAA,IACvB,SAAS,eAAe,SAAS,0BAA0B;AAAA,IAC3D,aAAa,eAAe,KAAK,WAAW,KAAK;AAAA,IACjD,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,IAC7C,OAAO,eAAe,KAAK,KAAK;AAAA,IAChC,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,QAAQ,eAAe,KAAK,MAAM,KAAK;AAAA,IACvC,eAAe,eAAe,KAAK,aAAa,KAAK;AAAA,EACvD;AACF;AAEA,SAAS,oBAAoB,KAAkC;AAC7D,SAAO;AAAA,IACL,GAAG,iBAAiB,GAAG;AAAA,IACvB,YAAY,eAAe,KAAK,YAAY,uBAAuB;AAAA,IACnE,mBAAmB,eAAe,KAAK,mBAAmB,8BAA8B;AAAA,IACxF,QAAQ,OAAO,KAAK,UAAU,CAAC;AAAA,IAC/B,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,IAC7C,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,qBAAqB,eAAe,KAAK,mBAAmB,KAAK;AAAA,IACjE,mBAAmB,eAAe,KAAK,iBAAiB,KAAK;AAAA,EAC/D;AACF;AAEA,SAAS,eAAe,KAAyB;AAC/C,SAAO;AAAA,IACL,GAAG,iBAAiB,GAAG;AAAA,IACvB,IAAI,eAAe,KAAK,IAAI,UAAU;AAAA,IACtC,aAAa,eAAe,KAAK,WAAW,KAAK;AAAA,IACjD,QAAQ,eAAe,KAAK,MAAM,KAAK;AAAA,IACvC,eAAe,eAAe,KAAK,aAAa;AAAA,IAChD,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,UAAU,OAAO,KAAK,YAAY,CAAC;AAAA,IACnC,UAAU,OAAO,KAAK,YAAY,CAAC;AAAA,IACnC,eAAe,OAAO,KAAK,iBAAiB,CAAC;AAAA,IAC7C,OAAO,OAAO,KAAK,SAAS,CAAC;AAAA,IAC7B,UAAU,kBAAkB,KAAK,QAAQ;AAAA,IACzC,UAAU,MAAM,QAAQ,KAAK,QAAQ,IAAI,IAAI,SAAS,IAAI,gBAAgB,IAAI;AAAA,EAChF;AACF;AAEA,SAAS,iBAAiB,KAA2B;AACnD,SAAO;AAAA,IACL,GAAG,iBAAiB,GAAG;AAAA,IACvB,IAAI,eAAe,KAAK,IAAI,YAAY;AAAA,IACxC,SAAS,eAAe,KAAK,OAAO,KAAK;AAAA,IACzC,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,IAC7C,wBACE,eAAe,KAAK,sBAAsB,KAAK;AAAA,IACjD,QAAQ,eAAe,KAAK,MAAM;AAAA,IAClC,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,QAAQ,eAAe,KAAK,MAAM,KAAK;AAAA,IACvC,QAAQ,eAAe,KAAK,MAAM,KAAK;AAAA,IACvC,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,IAC7C,cAAc,MAAM,QAAQ,KAAK,YAAY,IACzC,IAAI,aAAa,IAAI,oBAAoB,IACzC;AAAA,EACN;AACF;AAEA,SAAS,qBAAqB,KAAsC;AAClE,SAAO;AAAA,IACL,GAAG,iBAAiB,GAAG;AAAA,IACvB,IAAI,eAAe,KAAK,IAAI,gBAAgB;AAAA,IAC5C,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,IAC7C,MAAM,eAAe,KAAK,IAAI,KAAK;AAAA,IACnC,QAAQ,eAAe,KAAK,MAAM;AAAA,IAClC,UAAU,eAAe,KAAK,QAAQ,KAAK;AAAA,IAC3C,QAAQ,eAAe,KAAK,MAAM,KAAK;AAAA,IACvC,WAAW,eAAe,KAAK,SAAS,KAAK;AAAA,EAC/C;AACF;AAEA,SAAS,iBAAiB,OAAyC;AACjE,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACzE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAgC,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,SAAS,GAAG,CAAC;AAAA,EACvF;AACF;AAEA,SAAS,eAAe,OAAgB,OAAuB;AAC7D,MAAI,OAAO,UAAU,YAAY,MAAM,SAAS,EAAG,QAAO;AAC1D,QAAM,IAAI,MAAM,sCAAsC,KAAK,EAAE;AAC/D;AAEA,SAAS,eAAe,OAA+B;AACrD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,eAAe,OAAoC;AAC1D,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAEA,SAAS,kBAAkB,OAAqD;AAC9E,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC5D,QACD;AACN;","names":["import_errors"]}
|
package/dist/server.d.cts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { ThrottleError } from '@usethrottle/errors';
|
|
2
2
|
export { ThrottleError, isThrottleError } from '@usethrottle/errors';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* `'embedded'` completes a card payment taken by the payment embed; `'net30'`
|
|
6
|
+
* issues an invoice on terms. `'card'` names the card category in
|
|
7
|
+
* `allowedMethods` — `completeSession` rejects it with 422
|
|
8
|
+
* `payment_method_not_supported`. Use `'embedded'`.
|
|
9
|
+
*/
|
|
10
|
+
type PaymentMethod = 'net30' | 'card' | 'embedded';
|
|
11
|
+
type SubscriptionInterval = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';
|
|
6
12
|
type CheckoutEmbedMode = 'checkout-full' | 'payment-only';
|
|
7
13
|
type CheckoutEmbedRoute = 'c' | 's';
|
|
8
14
|
interface CheckoutClientOptions {
|
|
@@ -85,6 +91,24 @@ interface CheckoutSession {
|
|
|
85
91
|
expiresAt?: string;
|
|
86
92
|
[key: string]: unknown;
|
|
87
93
|
}
|
|
94
|
+
type CheckoutSessionStatus = 'open' | 'customer_set' | 'address_set' | 'processing' | 'completed' | 'expired' | 'cancelled';
|
|
95
|
+
/** A session as read back by `getSession` — the create response plus its current state. */
|
|
96
|
+
interface CheckoutSessionDetails extends CheckoutSession {
|
|
97
|
+
status: CheckoutSessionStatus;
|
|
98
|
+
cartId?: string | null;
|
|
99
|
+
customerId?: string | null;
|
|
100
|
+
customerEmail?: string | null;
|
|
101
|
+
shippingAddress?: CheckoutAddress | null;
|
|
102
|
+
billingAddress?: CheckoutAddress | null;
|
|
103
|
+
returnUrl?: string;
|
|
104
|
+
cancelUrl?: string;
|
|
105
|
+
completedAt?: string | null;
|
|
106
|
+
allowedMethods?: string[] | null;
|
|
107
|
+
collectShipping?: boolean;
|
|
108
|
+
collectBilling?: boolean;
|
|
109
|
+
discountCode?: string | null;
|
|
110
|
+
metadata?: Record<string, unknown>;
|
|
111
|
+
}
|
|
88
112
|
interface Net30Acceptance {
|
|
89
113
|
termsHash: string;
|
|
90
114
|
acceptedAt: string;
|
|
@@ -103,8 +127,8 @@ interface CompleteCheckoutSessionInput {
|
|
|
103
127
|
invoiceNumber?: string;
|
|
104
128
|
net30Acceptance?: Net30Acceptance;
|
|
105
129
|
paymentToken?: string;
|
|
106
|
-
|
|
107
|
-
|
|
130
|
+
processorCheckoutSessionId?: string;
|
|
131
|
+
processorTransactionId?: string;
|
|
108
132
|
}
|
|
109
133
|
interface CompleteCheckoutSessionResult {
|
|
110
134
|
orderId: string;
|
|
@@ -129,7 +153,7 @@ interface CreateEmbedTokenResult {
|
|
|
129
153
|
currency: string;
|
|
130
154
|
hostedUrl?: string;
|
|
131
155
|
embedUrl?: string;
|
|
132
|
-
|
|
156
|
+
processorInstanceId?: string;
|
|
133
157
|
merchantAccountId?: string;
|
|
134
158
|
[key: string]: unknown;
|
|
135
159
|
}
|
|
@@ -230,6 +254,13 @@ declare class CheckoutClient {
|
|
|
230
254
|
requestEnvelope<T = unknown>(method: string, path: string, body?: unknown): Promise<ThrottleEnvelope<T>>;
|
|
231
255
|
createSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession>;
|
|
232
256
|
completeSession(sessionId: string, input: CompleteCheckoutSessionInput): Promise<CompleteCheckoutSessionResult>;
|
|
257
|
+
/**
|
|
258
|
+
* Read a checkout session's current state — `status` tells you whether the
|
|
259
|
+
* buyer is still in it (`open`, `processing`) or it has settled (`completed`,
|
|
260
|
+
* `cancelled`, `expired`). Use it to decide whether a session can be resumed
|
|
261
|
+
* or cancelled instead of tracking that yourself.
|
|
262
|
+
*/
|
|
263
|
+
getSession(sessionId: string): Promise<CheckoutSessionDetails>;
|
|
233
264
|
/**
|
|
234
265
|
* Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).
|
|
235
266
|
* Idempotent — cancelling an already-cancelled session is a no-op; a completed
|
|
@@ -247,4 +278,4 @@ declare function createCheckoutClient(opts: CheckoutClientOptions): CheckoutClie
|
|
|
247
278
|
declare function buildCheckoutHostedUrl(options: BuildCheckoutUrlOptions): string;
|
|
248
279
|
declare function buildCheckoutEmbedUrl(options: BuildCheckoutUrlOptions): string;
|
|
249
280
|
|
|
250
|
-
export { type BuildCheckoutUrlOptions, type CheckoutAddress, CheckoutClient, type CheckoutClientOptions, type CheckoutCollectInput, type CheckoutCustomerAddressInput, type CheckoutCustomerInput, type CheckoutEmbedMode, type CheckoutEmbedRoute, type CheckoutOrder, type CheckoutPayment, type CheckoutPaymentTermsInput, type CheckoutPaymentTransaction, type CheckoutSession, type CompleteCheckoutSessionInput, type CompleteCheckoutSessionResult, type CreateCheckoutSessionInput, type CreateEmbedTokenInput, type CreateEmbedTokenResult, type ListOrdersOptions, type Net30Acceptance, type PaginatedOrders, type PaymentMethod, type RecurringIntentInput, type SubscriptionInterval, ThrottleCheckoutError, type ThrottleEnvelope, buildCheckoutEmbedUrl, buildCheckoutHostedUrl, createCheckoutClient };
|
|
281
|
+
export { type BuildCheckoutUrlOptions, type CheckoutAddress, CheckoutClient, type CheckoutClientOptions, type CheckoutCollectInput, type CheckoutCustomerAddressInput, type CheckoutCustomerInput, type CheckoutEmbedMode, type CheckoutEmbedRoute, type CheckoutOrder, type CheckoutPayment, type CheckoutPaymentTermsInput, type CheckoutPaymentTransaction, type CheckoutSession, type CheckoutSessionDetails, type CheckoutSessionStatus, type CompleteCheckoutSessionInput, type CompleteCheckoutSessionResult, type CreateCheckoutSessionInput, type CreateEmbedTokenInput, type CreateEmbedTokenResult, type ListOrdersOptions, type Net30Acceptance, type PaginatedOrders, type PaymentMethod, type RecurringIntentInput, type SubscriptionInterval, ThrottleCheckoutError, type ThrottleEnvelope, buildCheckoutEmbedUrl, buildCheckoutHostedUrl, createCheckoutClient };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { ThrottleError } from '@usethrottle/errors';
|
|
2
2
|
export { ThrottleError, isThrottleError } from '@usethrottle/errors';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* `'embedded'` completes a card payment taken by the payment embed; `'net30'`
|
|
6
|
+
* issues an invoice on terms. `'card'` names the card category in
|
|
7
|
+
* `allowedMethods` — `completeSession` rejects it with 422
|
|
8
|
+
* `payment_method_not_supported`. Use `'embedded'`.
|
|
9
|
+
*/
|
|
10
|
+
type PaymentMethod = 'net30' | 'card' | 'embedded';
|
|
11
|
+
type SubscriptionInterval = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';
|
|
6
12
|
type CheckoutEmbedMode = 'checkout-full' | 'payment-only';
|
|
7
13
|
type CheckoutEmbedRoute = 'c' | 's';
|
|
8
14
|
interface CheckoutClientOptions {
|
|
@@ -85,6 +91,24 @@ interface CheckoutSession {
|
|
|
85
91
|
expiresAt?: string;
|
|
86
92
|
[key: string]: unknown;
|
|
87
93
|
}
|
|
94
|
+
type CheckoutSessionStatus = 'open' | 'customer_set' | 'address_set' | 'processing' | 'completed' | 'expired' | 'cancelled';
|
|
95
|
+
/** A session as read back by `getSession` — the create response plus its current state. */
|
|
96
|
+
interface CheckoutSessionDetails extends CheckoutSession {
|
|
97
|
+
status: CheckoutSessionStatus;
|
|
98
|
+
cartId?: string | null;
|
|
99
|
+
customerId?: string | null;
|
|
100
|
+
customerEmail?: string | null;
|
|
101
|
+
shippingAddress?: CheckoutAddress | null;
|
|
102
|
+
billingAddress?: CheckoutAddress | null;
|
|
103
|
+
returnUrl?: string;
|
|
104
|
+
cancelUrl?: string;
|
|
105
|
+
completedAt?: string | null;
|
|
106
|
+
allowedMethods?: string[] | null;
|
|
107
|
+
collectShipping?: boolean;
|
|
108
|
+
collectBilling?: boolean;
|
|
109
|
+
discountCode?: string | null;
|
|
110
|
+
metadata?: Record<string, unknown>;
|
|
111
|
+
}
|
|
88
112
|
interface Net30Acceptance {
|
|
89
113
|
termsHash: string;
|
|
90
114
|
acceptedAt: string;
|
|
@@ -103,8 +127,8 @@ interface CompleteCheckoutSessionInput {
|
|
|
103
127
|
invoiceNumber?: string;
|
|
104
128
|
net30Acceptance?: Net30Acceptance;
|
|
105
129
|
paymentToken?: string;
|
|
106
|
-
|
|
107
|
-
|
|
130
|
+
processorCheckoutSessionId?: string;
|
|
131
|
+
processorTransactionId?: string;
|
|
108
132
|
}
|
|
109
133
|
interface CompleteCheckoutSessionResult {
|
|
110
134
|
orderId: string;
|
|
@@ -129,7 +153,7 @@ interface CreateEmbedTokenResult {
|
|
|
129
153
|
currency: string;
|
|
130
154
|
hostedUrl?: string;
|
|
131
155
|
embedUrl?: string;
|
|
132
|
-
|
|
156
|
+
processorInstanceId?: string;
|
|
133
157
|
merchantAccountId?: string;
|
|
134
158
|
[key: string]: unknown;
|
|
135
159
|
}
|
|
@@ -230,6 +254,13 @@ declare class CheckoutClient {
|
|
|
230
254
|
requestEnvelope<T = unknown>(method: string, path: string, body?: unknown): Promise<ThrottleEnvelope<T>>;
|
|
231
255
|
createSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession>;
|
|
232
256
|
completeSession(sessionId: string, input: CompleteCheckoutSessionInput): Promise<CompleteCheckoutSessionResult>;
|
|
257
|
+
/**
|
|
258
|
+
* Read a checkout session's current state — `status` tells you whether the
|
|
259
|
+
* buyer is still in it (`open`, `processing`) or it has settled (`completed`,
|
|
260
|
+
* `cancelled`, `expired`). Use it to decide whether a session can be resumed
|
|
261
|
+
* or cancelled instead of tracking that yourself.
|
|
262
|
+
*/
|
|
263
|
+
getSession(sessionId: string): Promise<CheckoutSessionDetails>;
|
|
233
264
|
/**
|
|
234
265
|
* Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).
|
|
235
266
|
* Idempotent — cancelling an already-cancelled session is a no-op; a completed
|
|
@@ -247,4 +278,4 @@ declare function createCheckoutClient(opts: CheckoutClientOptions): CheckoutClie
|
|
|
247
278
|
declare function buildCheckoutHostedUrl(options: BuildCheckoutUrlOptions): string;
|
|
248
279
|
declare function buildCheckoutEmbedUrl(options: BuildCheckoutUrlOptions): string;
|
|
249
280
|
|
|
250
|
-
export { type BuildCheckoutUrlOptions, type CheckoutAddress, CheckoutClient, type CheckoutClientOptions, type CheckoutCollectInput, type CheckoutCustomerAddressInput, type CheckoutCustomerInput, type CheckoutEmbedMode, type CheckoutEmbedRoute, type CheckoutOrder, type CheckoutPayment, type CheckoutPaymentTermsInput, type CheckoutPaymentTransaction, type CheckoutSession, type CompleteCheckoutSessionInput, type CompleteCheckoutSessionResult, type CreateCheckoutSessionInput, type CreateEmbedTokenInput, type CreateEmbedTokenResult, type ListOrdersOptions, type Net30Acceptance, type PaginatedOrders, type PaymentMethod, type RecurringIntentInput, type SubscriptionInterval, ThrottleCheckoutError, type ThrottleEnvelope, buildCheckoutEmbedUrl, buildCheckoutHostedUrl, createCheckoutClient };
|
|
281
|
+
export { type BuildCheckoutUrlOptions, type CheckoutAddress, CheckoutClient, type CheckoutClientOptions, type CheckoutCollectInput, type CheckoutCustomerAddressInput, type CheckoutCustomerInput, type CheckoutEmbedMode, type CheckoutEmbedRoute, type CheckoutOrder, type CheckoutPayment, type CheckoutPaymentTermsInput, type CheckoutPaymentTransaction, type CheckoutSession, type CheckoutSessionDetails, type CheckoutSessionStatus, type CompleteCheckoutSessionInput, type CompleteCheckoutSessionResult, type CreateCheckoutSessionInput, type CreateEmbedTokenInput, type CreateEmbedTokenResult, type ListOrdersOptions, type Net30Acceptance, type PaginatedOrders, type PaymentMethod, type RecurringIntentInput, type SubscriptionInterval, ThrottleCheckoutError, type ThrottleEnvelope, buildCheckoutEmbedUrl, buildCheckoutHostedUrl, createCheckoutClient };
|
package/dist/server.js
CHANGED
|
@@ -65,6 +65,22 @@ var CheckoutClient = class {
|
|
|
65
65
|
);
|
|
66
66
|
return normalizeCompleteResult(data);
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Read a checkout session's current state — `status` tells you whether the
|
|
70
|
+
* buyer is still in it (`open`, `processing`) or it has settled (`completed`,
|
|
71
|
+
* `cancelled`, `expired`). Use it to decide whether a session can be resumed
|
|
72
|
+
* or cancelled instead of tracking that yourself.
|
|
73
|
+
*/
|
|
74
|
+
async getSession(sessionId) {
|
|
75
|
+
const data = await this.request(
|
|
76
|
+
"GET",
|
|
77
|
+
`/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`
|
|
78
|
+
);
|
|
79
|
+
return {
|
|
80
|
+
...normalizeCheckoutSession(data),
|
|
81
|
+
status: requiredString(data?.status, "checkoutSession.status")
|
|
82
|
+
};
|
|
83
|
+
}
|
|
68
84
|
/**
|
|
69
85
|
* Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).
|
|
70
86
|
* Idempotent — cancelling an already-cancelled session is a no-op; a completed
|
|
@@ -191,7 +207,7 @@ function normalizeEmbedToken(raw) {
|
|
|
191
207
|
currency: optionalString(raw?.currency) ?? "USD",
|
|
192
208
|
hostedUrl: optionalString(raw?.hostedUrl) ?? void 0,
|
|
193
209
|
embedUrl: optionalString(raw?.embedUrl) ?? void 0,
|
|
194
|
-
|
|
210
|
+
processorInstanceId: optionalString(raw?.processorInstanceId) ?? void 0,
|
|
195
211
|
merchantAccountId: optionalString(raw?.merchantAccountId) ?? void 0
|
|
196
212
|
};
|
|
197
213
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { ThrottleError } from '@usethrottle/errors';\n\nexport type PaymentMethod = 'net30' | 'card' | 'gr4vy';\nexport type SubscriptionInterval = 'weekly' | 'monthly' | 'quarterly' | 'yearly';\nexport type CheckoutEmbedMode = 'checkout-full' | 'payment-only';\nexport type CheckoutEmbedRoute = 'c' | 's';\n\nexport interface CheckoutClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n}\n\nexport interface CheckoutAddress {\n firstName: string;\n lastName: string;\n company?: string;\n addressLine1: string;\n addressLine2?: string;\n city: string;\n stateProvince: string;\n postalCode: string;\n countryCode: string;\n phone?: string;\n}\n\nexport interface CheckoutCustomerAddressInput {\n firstName?: string;\n lastName?: string;\n phone?: string;\n addressLine1?: string;\n addressLine2?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n country?: string;\n}\n\nexport interface CheckoutCustomerInput {\n customerId?: string;\n externalCustomerId?: string;\n email?: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n shippingAddress?: CheckoutCustomerAddressInput;\n billingAddress?: CheckoutCustomerAddressInput;\n metadata?: Record<string, unknown>;\n}\n\nexport interface RecurringIntentInput {\n plan: string;\n interval: SubscriptionInterval;\n amount?: number;\n trialDays?: number;\n planName?: string;\n create?: 'auto' | 'manual';\n}\n\nexport interface CheckoutCollectInput {\n shippingAddress?: boolean;\n billingAddress?: boolean;\n}\n\nexport interface CheckoutPaymentTermsInput {\n netN?: number | null;\n}\n\nexport interface CreateCheckoutSessionInput {\n applicationId: string;\n cartId?: string;\n externalCartId?: string;\n customerEmail?: string;\n customer?: CheckoutCustomerInput;\n returnUrl: string;\n cancelUrl: string;\n allowedMethods?: string[];\n paymentTerms?: CheckoutPaymentTermsInput;\n recurring?: RecurringIntentInput;\n collect?: CheckoutCollectInput;\n metadata?: Record<string, unknown>;\n discountCode?: string;\n}\n\nexport interface CheckoutSession {\n sessionId: string;\n id?: string;\n checkoutUrl?: string;\n hostedUrl?: string;\n embedUrl?: string;\n embedToken?: string;\n expiresAt?: string;\n [key: string]: unknown;\n}\n\nexport interface Net30Acceptance {\n termsHash: string;\n acceptedAt: string;\n companyName: string;\n billingEmail: string;\n}\n\nexport interface CompleteCheckoutSessionInput {\n email?: string;\n shippingAddress?: CheckoutAddress;\n billingAddress?: CheckoutAddress;\n billingSameAsShipping?: boolean;\n paymentMethod: PaymentMethod;\n netDays?: number;\n termsAccepted?: boolean;\n termsSnapshot?: string;\n invoiceNumber?: string;\n net30Acceptance?: Net30Acceptance;\n paymentToken?: string;\n gr4vyCheckoutSessionId?: string;\n gr4vyTransactionId?: string;\n}\n\nexport interface CompleteCheckoutSessionResult {\n orderId: string;\n orderNumber?: string;\n paymentId?: string;\n total?: number;\n currency?: string;\n status?: string;\n paymentStatus?: string;\n [key: string]: unknown;\n}\n\nexport interface CreateEmbedTokenInput {\n externalCartId?: string;\n amount: number;\n currency: string;\n country?: string;\n // NOTE: `allowedMethods` is intentionally NOT accepted here. A payment-only\n // Gr4vy embed cannot restrict payment methods (the Gr4vy widget renders the\n // methods configured on your Gr4vy connection). The server rejects it with\n // `allowed_methods_unsupported`. To restrict methods, configure the connection\n // or use the full hosted checkout, where allowedMethods filters the selection.\n}\n\nexport interface CreateEmbedTokenResult {\n embedToken: string;\n checkoutSessionId: string;\n amount: number;\n currency: string;\n hostedUrl?: string;\n embedUrl?: string;\n gr4vyId?: string;\n merchantAccountId?: string;\n [key: string]: unknown;\n}\n\nexport interface CheckoutOrder {\n id: string;\n orderNumber?: string;\n status: string;\n paymentStatus: string | null;\n currency: string;\n subtotal: number;\n taxTotal: number;\n shippingTotal: number;\n total: number;\n metadata?: Record<string, unknown>;\n payments?: CheckoutPayment[];\n [key: string]: unknown;\n}\n\nexport interface ListOrdersOptions {\n customerId?: string;\n cursor?: string;\n limit?: number;\n status?: string;\n paymentStatus?: string;\n}\n\nexport interface PaginatedOrders {\n data: CheckoutOrder[];\n pagination?: {\n cursor: string | null;\n hasMore: boolean;\n };\n}\n\nexport interface CheckoutPayment {\n id: string;\n orderId?: string;\n processor?: string;\n processorTransactionId?: string | null;\n amount?: number;\n currency?: string;\n status?: string;\n method?: string;\n createdAt?: string;\n transactions?: CheckoutPaymentTransaction[];\n [key: string]: unknown;\n}\n\nexport interface CheckoutPaymentTransaction {\n id: string;\n paymentId?: string;\n type?: string;\n amount?: number;\n currency?: string;\n status?: string;\n createdAt?: string;\n [key: string]: unknown;\n}\n\nexport interface BuildCheckoutUrlOptions {\n checkoutOrigin?: string;\n sessionId: string;\n parentOrigin?: string;\n mode?: CheckoutEmbedMode;\n route?: CheckoutEmbedRoute;\n primary?: string;\n logo?: string;\n}\n\nexport interface ThrottleEnvelope<T> {\n data?: T;\n meta?: Record<string, unknown>;\n error?: {\n code?: string;\n message?: string;\n details?: unknown;\n };\n}\n\n/**\n * Thrown on a non-2xx response from the Throttle Checkout API.\n *\n * Extends the shared {@link ThrottleError} so a single\n * `catch (e) { if (e instanceof ThrottleError) … }` covers errors from every\n * Throttle SDK. `instanceof ThrottleCheckoutError` keeps working for existing\n * code.\n */\nexport class ThrottleCheckoutError extends ThrottleError {\n constructor(args: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n body?: unknown;\n }) {\n super(args);\n this.name = 'ThrottleCheckoutError';\n }\n}\n\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n\nexport class CheckoutClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly timeoutMs: number;\n\n constructor(opts: CheckoutClientOptions) {\n if (!opts.apiKey) throw new Error('CheckoutClient: apiKey is required');\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('CheckoutClient: fetch is required');\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const envelope = await this.requestEnvelope<T>(method, path, body);\n if (Object.prototype.hasOwnProperty.call(envelope, 'data')) {\n return envelope.data as T;\n }\n return envelope as T;\n }\n\n async requestEnvelope<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n\n try {\n const res = await this.fetchImpl(toAbsoluteUrl(this.baseUrl, path), {\n method,\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: ctrl.signal,\n });\n\n if (res.status === 204) return { data: undefined as T };\n\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) {\n throw new ThrottleCheckoutError({\n code: json.error?.code ?? 'unknown_error',\n message: json.error?.message ?? `HTTP ${res.status}`,\n statusCode: res.status,\n details: json.error?.details,\n body: json,\n });\n }\n return json;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async createSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout/sessions', input);\n return normalizeCheckoutSession(data);\n }\n\n async completeSession(\n sessionId: string,\n input: CompleteCheckoutSessionInput,\n ): Promise<CompleteCheckoutSessionResult> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}/complete`,\n input,\n );\n return normalizeCompleteResult(data);\n }\n\n /**\n * Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).\n * Idempotent — cancelling an already-cancelled session is a no-op; a completed\n * session cannot be cancelled (the API returns 422 `already_completed`).\n */\n async cancelSession(sessionId: string): Promise<void> {\n await this.request<unknown>(\n 'DELETE',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`,\n );\n }\n\n async createEmbedToken(input: CreateEmbedTokenInput): Promise<CreateEmbedTokenResult> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout-sessions/embed-token', input);\n return normalizeEmbedToken(data);\n }\n\n async getOrder(orderId: string): Promise<CheckoutOrder> {\n const data = await this.request<unknown>('GET', `/api/v1/orders/${encodeURIComponent(orderId)}`);\n return normalizeOrder(data);\n }\n\n async listOrders(options: ListOrdersOptions = {}): Promise<PaginatedOrders> {\n const params = new URLSearchParams();\n if (options.customerId) params.set('customerId', options.customerId);\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.status) params.set('status', options.status);\n if (options.paymentStatus) params.set('paymentStatus', options.paymentStatus);\n\n const query = params.toString();\n const envelope = await this.requestEnvelope<unknown[]>(\n 'GET',\n `/api/v1/orders${query ? `?${query}` : ''}`,\n );\n return {\n data: (envelope.data ?? []).map(normalizeOrder),\n pagination: envelope.meta?.pagination as PaginatedOrders['pagination'],\n };\n }\n\n async listOrderPayments(orderId: string): Promise<CheckoutPayment[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/orders/${encodeURIComponent(orderId)}/payments`,\n );\n return (data ?? []).map(normalizePayment);\n }\n\n async listPaymentTransactions(paymentId: string): Promise<CheckoutPaymentTransaction[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/payments/${encodeURIComponent(paymentId)}/transactions`,\n );\n return (data ?? []).map(normalizeTransaction);\n }\n\n async getOrderWithPayments(orderId: string): Promise<CheckoutOrder> {\n const order = await this.getOrder(orderId);\n const payments = await this.listOrderPayments(orderId);\n return {\n ...order,\n payments: await Promise.all(\n payments.map(async (payment) => ({\n ...payment,\n transactions: payment.id ? await this.listPaymentTransactions(payment.id) : [],\n })),\n ),\n };\n }\n}\n\nexport function createCheckoutClient(opts: CheckoutClientOptions): CheckoutClient {\n return new CheckoutClient(opts);\n}\n\nexport function buildCheckoutHostedUrl(options: BuildCheckoutUrlOptions): string {\n const route = options.route ?? 's';\n const base = (options.checkoutOrigin ?? 'https://checkout.usethrottle.dev').replace(/\\/+$/, '');\n return `${base}/${route}/${encodeURIComponent(options.sessionId)}`;\n}\n\nexport function buildCheckoutEmbedUrl(options: BuildCheckoutUrlOptions): string {\n const baseUrl = buildCheckoutHostedUrl({\n checkoutOrigin: options.checkoutOrigin,\n sessionId: options.sessionId,\n route: options.route ?? 'c',\n });\n const params = new URLSearchParams({\n embed: '1',\n mode: options.mode ?? 'payment-only',\n ...(options.parentOrigin ? { parentOrigin: options.parentOrigin.replace(/\\/+$/, '') } : {}),\n });\n if (options.primary) params.set('primary', options.primary);\n if (options.logo) params.set('logo', options.logo);\n return `${baseUrl}?${params.toString()}`;\n}\n\nfunction toAbsoluteUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//i.test(path)) return path;\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n}\n\nfunction normalizeCheckoutSession(raw: any): CheckoutSession {\n const sessionId = raw?.sessionId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n id: optionalString(raw?.id) ?? undefined,\n sessionId: requiredString(sessionId, 'checkoutSession.sessionId'),\n checkoutUrl: optionalString(raw?.checkoutUrl) ?? undefined,\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n embedToken: optionalString(raw?.embedToken) ?? undefined,\n expiresAt: optionalString(raw?.expiresAt) ?? undefined,\n };\n}\n\nfunction normalizeCompleteResult(raw: any): CompleteCheckoutSessionResult {\n const orderId = raw?.orderId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n orderId: requiredString(orderId, 'checkoutComplete.orderId'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n total: optionalNumber(raw?.total),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n paymentStatus: optionalString(raw?.paymentStatus) ?? undefined,\n };\n}\n\nfunction normalizeEmbedToken(raw: any): CreateEmbedTokenResult {\n return {\n ...withoutSnakeKeys(raw),\n embedToken: requiredString(raw?.embedToken, 'embedToken.embedToken'),\n checkoutSessionId: requiredString(raw?.checkoutSessionId, 'embedToken.checkoutSessionId'),\n amount: Number(raw?.amount ?? 0),\n currency: optionalString(raw?.currency) ?? 'USD',\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n gr4vyId: optionalString(raw?.gr4vyId) ?? undefined,\n merchantAccountId: optionalString(raw?.merchantAccountId) ?? undefined,\n };\n}\n\nfunction normalizeOrder(raw: any): CheckoutOrder {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'order.id'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n status: optionalString(raw?.status) ?? 'processing',\n paymentStatus: optionalString(raw?.paymentStatus),\n currency: optionalString(raw?.currency) ?? 'USD',\n subtotal: Number(raw?.subtotal ?? 0),\n taxTotal: Number(raw?.taxTotal ?? 0),\n shippingTotal: Number(raw?.shippingTotal ?? 0),\n total: Number(raw?.total ?? 0),\n metadata: objectOrUndefined(raw?.metadata),\n payments: Array.isArray(raw?.payments) ? raw.payments.map(normalizePayment) : undefined,\n };\n}\n\nfunction normalizePayment(raw: any): CheckoutPayment {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'payment.id'),\n orderId: optionalString(raw?.orderId) ?? undefined,\n processor: optionalString(raw?.processor) ?? undefined,\n processorTransactionId:\n optionalString(raw?.processorTransactionId) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n method: optionalString(raw?.method) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n transactions: Array.isArray(raw?.transactions)\n ? raw.transactions.map(normalizeTransaction)\n : undefined,\n };\n}\n\nfunction normalizeTransaction(raw: any): CheckoutPaymentTransaction {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'transaction.id'),\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n type: optionalString(raw?.type) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n };\n}\n\nfunction withoutSnakeKeys(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).filter(([key]) => !key.includes('_')),\n );\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction optionalNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction objectOrUndefined(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"],"mappings":"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","names":["ThrottleError"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { ThrottleError } from '@usethrottle/errors';\n\n/**\n * `'embedded'` completes a card payment taken by the payment embed; `'net30'`\n * issues an invoice on terms. `'card'` names the card category in\n * `allowedMethods` — `completeSession` rejects it with 422\n * `payment_method_not_supported`. Use `'embedded'`.\n */\nexport type PaymentMethod = 'net30' | 'card' | 'embedded';\nexport type SubscriptionInterval = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';\nexport type CheckoutEmbedMode = 'checkout-full' | 'payment-only';\nexport type CheckoutEmbedRoute = 'c' | 's';\n\nexport interface CheckoutClientOptions {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n}\n\nexport interface CheckoutAddress {\n firstName: string;\n lastName: string;\n company?: string;\n addressLine1: string;\n addressLine2?: string;\n city: string;\n stateProvince: string;\n postalCode: string;\n countryCode: string;\n phone?: string;\n}\n\nexport interface CheckoutCustomerAddressInput {\n firstName?: string;\n lastName?: string;\n phone?: string;\n addressLine1?: string;\n addressLine2?: string;\n city?: string;\n state?: string;\n postalCode?: string;\n country?: string;\n}\n\nexport interface CheckoutCustomerInput {\n customerId?: string;\n externalCustomerId?: string;\n email?: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n shippingAddress?: CheckoutCustomerAddressInput;\n billingAddress?: CheckoutCustomerAddressInput;\n metadata?: Record<string, unknown>;\n}\n\nexport interface RecurringIntentInput {\n plan: string;\n interval: SubscriptionInterval;\n amount?: number;\n trialDays?: number;\n planName?: string;\n create?: 'auto' | 'manual';\n}\n\nexport interface CheckoutCollectInput {\n shippingAddress?: boolean;\n billingAddress?: boolean;\n}\n\nexport interface CheckoutPaymentTermsInput {\n netN?: number | null;\n}\n\nexport interface CreateCheckoutSessionInput {\n applicationId: string;\n cartId?: string;\n externalCartId?: string;\n customerEmail?: string;\n customer?: CheckoutCustomerInput;\n returnUrl: string;\n cancelUrl: string;\n allowedMethods?: string[];\n paymentTerms?: CheckoutPaymentTermsInput;\n recurring?: RecurringIntentInput;\n collect?: CheckoutCollectInput;\n metadata?: Record<string, unknown>;\n discountCode?: string;\n}\n\nexport interface CheckoutSession {\n sessionId: string;\n id?: string;\n checkoutUrl?: string;\n hostedUrl?: string;\n embedUrl?: string;\n embedToken?: string;\n expiresAt?: string;\n [key: string]: unknown;\n}\n\nexport type CheckoutSessionStatus =\n | 'open'\n | 'customer_set'\n | 'address_set'\n | 'processing'\n | 'completed'\n | 'expired'\n | 'cancelled';\n\n/** A session as read back by `getSession` — the create response plus its current state. */\nexport interface CheckoutSessionDetails extends CheckoutSession {\n status: CheckoutSessionStatus;\n cartId?: string | null;\n customerId?: string | null;\n customerEmail?: string | null;\n shippingAddress?: CheckoutAddress | null;\n billingAddress?: CheckoutAddress | null;\n returnUrl?: string;\n cancelUrl?: string;\n completedAt?: string | null;\n allowedMethods?: string[] | null;\n collectShipping?: boolean;\n collectBilling?: boolean;\n discountCode?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Net30Acceptance {\n termsHash: string;\n acceptedAt: string;\n companyName: string;\n billingEmail: string;\n}\n\nexport interface CompleteCheckoutSessionInput {\n email?: string;\n shippingAddress?: CheckoutAddress;\n billingAddress?: CheckoutAddress;\n billingSameAsShipping?: boolean;\n paymentMethod: PaymentMethod;\n netDays?: number;\n termsAccepted?: boolean;\n termsSnapshot?: string;\n invoiceNumber?: string;\n net30Acceptance?: Net30Acceptance;\n paymentToken?: string;\n processorCheckoutSessionId?: string;\n processorTransactionId?: string;\n}\n\nexport interface CompleteCheckoutSessionResult {\n orderId: string;\n orderNumber?: string;\n paymentId?: string;\n total?: number;\n currency?: string;\n status?: string;\n paymentStatus?: string;\n [key: string]: unknown;\n}\n\nexport interface CreateEmbedTokenInput {\n externalCartId?: string;\n amount: number;\n currency: string;\n country?: string;\n // NOTE: `allowedMethods` is intentionally NOT accepted here. A payment-only\n // Gr4vy embed cannot restrict payment methods (the Gr4vy widget renders the\n // methods configured on your Gr4vy connection). The server rejects it with\n // `allowed_methods_unsupported`. To restrict methods, configure the connection\n // or use the full hosted checkout, where allowedMethods filters the selection.\n}\n\nexport interface CreateEmbedTokenResult {\n embedToken: string;\n checkoutSessionId: string;\n amount: number;\n currency: string;\n hostedUrl?: string;\n embedUrl?: string;\n processorInstanceId?: string;\n merchantAccountId?: string;\n [key: string]: unknown;\n}\n\nexport interface CheckoutOrder {\n id: string;\n orderNumber?: string;\n status: string;\n paymentStatus: string | null;\n currency: string;\n subtotal: number;\n taxTotal: number;\n shippingTotal: number;\n total: number;\n metadata?: Record<string, unknown>;\n payments?: CheckoutPayment[];\n [key: string]: unknown;\n}\n\nexport interface ListOrdersOptions {\n customerId?: string;\n cursor?: string;\n limit?: number;\n status?: string;\n paymentStatus?: string;\n}\n\nexport interface PaginatedOrders {\n data: CheckoutOrder[];\n pagination?: {\n cursor: string | null;\n hasMore: boolean;\n };\n}\n\nexport interface CheckoutPayment {\n id: string;\n orderId?: string;\n processor?: string;\n processorTransactionId?: string | null;\n amount?: number;\n currency?: string;\n status?: string;\n method?: string;\n createdAt?: string;\n transactions?: CheckoutPaymentTransaction[];\n [key: string]: unknown;\n}\n\nexport interface CheckoutPaymentTransaction {\n id: string;\n paymentId?: string;\n type?: string;\n amount?: number;\n currency?: string;\n status?: string;\n createdAt?: string;\n [key: string]: unknown;\n}\n\nexport interface BuildCheckoutUrlOptions {\n checkoutOrigin?: string;\n sessionId: string;\n parentOrigin?: string;\n mode?: CheckoutEmbedMode;\n route?: CheckoutEmbedRoute;\n primary?: string;\n logo?: string;\n}\n\nexport interface ThrottleEnvelope<T> {\n data?: T;\n meta?: Record<string, unknown>;\n error?: {\n code?: string;\n message?: string;\n details?: unknown;\n };\n}\n\n/**\n * Thrown on a non-2xx response from the Throttle Checkout API.\n *\n * Extends the shared {@link ThrottleError} so a single\n * `catch (e) { if (e instanceof ThrottleError) … }` covers errors from every\n * Throttle SDK. `instanceof ThrottleCheckoutError` keeps working for existing\n * code.\n */\nexport class ThrottleCheckoutError extends ThrottleError {\n constructor(args: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n body?: unknown;\n }) {\n super(args);\n this.name = 'ThrottleCheckoutError';\n }\n}\n\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n\nexport class CheckoutClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly timeoutMs: number;\n\n constructor(opts: CheckoutClientOptions) {\n if (!opts.apiKey) throw new Error('CheckoutClient: apiKey is required');\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('CheckoutClient: fetch is required');\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const envelope = await this.requestEnvelope<T>(method, path, body);\n if (Object.prototype.hasOwnProperty.call(envelope, 'data')) {\n return envelope.data as T;\n }\n return envelope as T;\n }\n\n async requestEnvelope<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n\n try {\n const res = await this.fetchImpl(toAbsoluteUrl(this.baseUrl, path), {\n method,\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': this.apiKey,\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: ctrl.signal,\n });\n\n if (res.status === 204) return { data: undefined as T };\n\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) {\n throw new ThrottleCheckoutError({\n code: json.error?.code ?? 'unknown_error',\n message: json.error?.message ?? `HTTP ${res.status}`,\n statusCode: res.status,\n details: json.error?.details,\n body: json,\n });\n }\n return json;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async createSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout/sessions', input);\n return normalizeCheckoutSession(data);\n }\n\n async completeSession(\n sessionId: string,\n input: CompleteCheckoutSessionInput,\n ): Promise<CompleteCheckoutSessionResult> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}/complete`,\n input,\n );\n return normalizeCompleteResult(data);\n }\n\n /**\n * Read a checkout session's current state — `status` tells you whether the\n * buyer is still in it (`open`, `processing`) or it has settled (`completed`,\n * `cancelled`, `expired`). Use it to decide whether a session can be resumed\n * or cancelled instead of tracking that yourself.\n */\n async getSession(sessionId: string): Promise<CheckoutSessionDetails> {\n const data = await this.request<any>(\n 'GET',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`,\n );\n return {\n ...normalizeCheckoutSession(data),\n status: requiredString(data?.status, 'checkoutSession.status') as CheckoutSessionStatus,\n };\n }\n\n /**\n * Cancel an in-flight checkout session (e.g. the buyer abandoned the embed).\n * Idempotent — cancelling an already-cancelled session is a no-op; a completed\n * session cannot be cancelled (the API returns 422 `already_completed`).\n */\n async cancelSession(sessionId: string): Promise<void> {\n await this.request<unknown>(\n 'DELETE',\n `/api/v1/checkout/sessions/${encodeURIComponent(sessionId)}`,\n );\n }\n\n async createEmbedToken(input: CreateEmbedTokenInput): Promise<CreateEmbedTokenResult> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout-sessions/embed-token', input);\n return normalizeEmbedToken(data);\n }\n\n async getOrder(orderId: string): Promise<CheckoutOrder> {\n const data = await this.request<unknown>('GET', `/api/v1/orders/${encodeURIComponent(orderId)}`);\n return normalizeOrder(data);\n }\n\n async listOrders(options: ListOrdersOptions = {}): Promise<PaginatedOrders> {\n const params = new URLSearchParams();\n if (options.customerId) params.set('customerId', options.customerId);\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.status) params.set('status', options.status);\n if (options.paymentStatus) params.set('paymentStatus', options.paymentStatus);\n\n const query = params.toString();\n const envelope = await this.requestEnvelope<unknown[]>(\n 'GET',\n `/api/v1/orders${query ? `?${query}` : ''}`,\n );\n return {\n data: (envelope.data ?? []).map(normalizeOrder),\n pagination: envelope.meta?.pagination as PaginatedOrders['pagination'],\n };\n }\n\n async listOrderPayments(orderId: string): Promise<CheckoutPayment[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/orders/${encodeURIComponent(orderId)}/payments`,\n );\n return (data ?? []).map(normalizePayment);\n }\n\n async listPaymentTransactions(paymentId: string): Promise<CheckoutPaymentTransaction[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/payments/${encodeURIComponent(paymentId)}/transactions`,\n );\n return (data ?? []).map(normalizeTransaction);\n }\n\n async getOrderWithPayments(orderId: string): Promise<CheckoutOrder> {\n const order = await this.getOrder(orderId);\n const payments = await this.listOrderPayments(orderId);\n return {\n ...order,\n payments: await Promise.all(\n payments.map(async (payment) => ({\n ...payment,\n transactions: payment.id ? await this.listPaymentTransactions(payment.id) : [],\n })),\n ),\n };\n }\n}\n\nexport function createCheckoutClient(opts: CheckoutClientOptions): CheckoutClient {\n return new CheckoutClient(opts);\n}\n\nexport function buildCheckoutHostedUrl(options: BuildCheckoutUrlOptions): string {\n const route = options.route ?? 's';\n const base = (options.checkoutOrigin ?? 'https://checkout.usethrottle.dev').replace(/\\/+$/, '');\n return `${base}/${route}/${encodeURIComponent(options.sessionId)}`;\n}\n\nexport function buildCheckoutEmbedUrl(options: BuildCheckoutUrlOptions): string {\n const baseUrl = buildCheckoutHostedUrl({\n checkoutOrigin: options.checkoutOrigin,\n sessionId: options.sessionId,\n route: options.route ?? 'c',\n });\n const params = new URLSearchParams({\n embed: '1',\n mode: options.mode ?? 'payment-only',\n ...(options.parentOrigin ? { parentOrigin: options.parentOrigin.replace(/\\/+$/, '') } : {}),\n });\n if (options.primary) params.set('primary', options.primary);\n if (options.logo) params.set('logo', options.logo);\n return `${baseUrl}?${params.toString()}`;\n}\n\nfunction toAbsoluteUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//i.test(path)) return path;\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n}\n\nfunction normalizeCheckoutSession(raw: any): CheckoutSession {\n const sessionId = raw?.sessionId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n id: optionalString(raw?.id) ?? undefined,\n sessionId: requiredString(sessionId, 'checkoutSession.sessionId'),\n checkoutUrl: optionalString(raw?.checkoutUrl) ?? undefined,\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n embedToken: optionalString(raw?.embedToken) ?? undefined,\n expiresAt: optionalString(raw?.expiresAt) ?? undefined,\n };\n}\n\nfunction normalizeCompleteResult(raw: any): CompleteCheckoutSessionResult {\n const orderId = raw?.orderId ?? raw?.id;\n return {\n ...withoutSnakeKeys(raw),\n orderId: requiredString(orderId, 'checkoutComplete.orderId'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n total: optionalNumber(raw?.total),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n paymentStatus: optionalString(raw?.paymentStatus) ?? undefined,\n };\n}\n\nfunction normalizeEmbedToken(raw: any): CreateEmbedTokenResult {\n return {\n ...withoutSnakeKeys(raw),\n embedToken: requiredString(raw?.embedToken, 'embedToken.embedToken'),\n checkoutSessionId: requiredString(raw?.checkoutSessionId, 'embedToken.checkoutSessionId'),\n amount: Number(raw?.amount ?? 0),\n currency: optionalString(raw?.currency) ?? 'USD',\n hostedUrl: optionalString(raw?.hostedUrl) ?? undefined,\n embedUrl: optionalString(raw?.embedUrl) ?? undefined,\n processorInstanceId: optionalString(raw?.processorInstanceId) ?? undefined,\n merchantAccountId: optionalString(raw?.merchantAccountId) ?? undefined,\n };\n}\n\nfunction normalizeOrder(raw: any): CheckoutOrder {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'order.id'),\n orderNumber: optionalString(raw?.orderNumber) ?? undefined,\n status: optionalString(raw?.status) ?? 'processing',\n paymentStatus: optionalString(raw?.paymentStatus),\n currency: optionalString(raw?.currency) ?? 'USD',\n subtotal: Number(raw?.subtotal ?? 0),\n taxTotal: Number(raw?.taxTotal ?? 0),\n shippingTotal: Number(raw?.shippingTotal ?? 0),\n total: Number(raw?.total ?? 0),\n metadata: objectOrUndefined(raw?.metadata),\n payments: Array.isArray(raw?.payments) ? raw.payments.map(normalizePayment) : undefined,\n };\n}\n\nfunction normalizePayment(raw: any): CheckoutPayment {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'payment.id'),\n orderId: optionalString(raw?.orderId) ?? undefined,\n processor: optionalString(raw?.processor) ?? undefined,\n processorTransactionId:\n optionalString(raw?.processorTransactionId) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n method: optionalString(raw?.method) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n transactions: Array.isArray(raw?.transactions)\n ? raw.transactions.map(normalizeTransaction)\n : undefined,\n };\n}\n\nfunction normalizeTransaction(raw: any): CheckoutPaymentTransaction {\n return {\n ...withoutSnakeKeys(raw),\n id: requiredString(raw?.id, 'transaction.id'),\n paymentId: optionalString(raw?.paymentId) ?? undefined,\n type: optionalString(raw?.type) ?? undefined,\n amount: optionalNumber(raw?.amount),\n currency: optionalString(raw?.currency) ?? undefined,\n status: optionalString(raw?.status) ?? undefined,\n createdAt: optionalString(raw?.createdAt) ?? undefined,\n };\n}\n\nfunction withoutSnakeKeys(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).filter(([key]) => !key.includes('_')),\n );\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction optionalNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction objectOrUndefined(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"],"mappings":"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","names":["ThrottleError"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usethrottle/checkout-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -22,13 +22,18 @@
|
|
|
22
22
|
"README.md",
|
|
23
23
|
"CHANGELOG.md"
|
|
24
24
|
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
25
30
|
"peerDependencies": {
|
|
26
31
|
"react": ">=18 <20",
|
|
27
32
|
"react-dom": ">=18 <20"
|
|
28
33
|
},
|
|
29
34
|
"dependencies": {
|
|
30
|
-
"@usethrottle/checkout-react": "
|
|
31
|
-
"@usethrottle/errors": "
|
|
35
|
+
"@usethrottle/checkout-react": "workspace:*",
|
|
36
|
+
"@usethrottle/errors": "workspace:^"
|
|
32
37
|
},
|
|
33
38
|
"devDependencies": {
|
|
34
39
|
"@testing-library/react": "^16.0.0",
|
|
@@ -44,10 +49,5 @@
|
|
|
44
49
|
},
|
|
45
50
|
"publishConfig": {
|
|
46
51
|
"access": "public"
|
|
47
|
-
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"build": "tsup",
|
|
50
|
-
"test": "vitest run",
|
|
51
|
-
"typecheck": "tsc --noEmit"
|
|
52
52
|
}
|
|
53
|
-
}
|
|
53
|
+
}
|