@waffo/pancake-nextjs 0.1.9 → 0.3.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 +24 -0
- package/README.md +61 -54
- package/dist/index.cjs +62 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -64
- package/dist/index.d.ts +93 -64
- package/dist/index.js +58 -48
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +16 -10
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +25 -15
- package/dist/server.d.ts +25 -15
- package/dist/server.js +14 -10
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ All notable changes to `@waffo/pancake-nextjs` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.3.0] - 2026-07-17
|
|
8
|
+
|
|
9
|
+
Adds cashier language selection to checkout.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`CashierLanguage`** — re-exported from `@waffo/pancake-ts`; the union of supported checkout cashier languages (IETF BCP 47, e.g. `"en"`, `"pt-BR"`).
|
|
14
|
+
- **`language` on checkout** — anonymous/authenticated checkout props and `<CheckoutButton>` now accept an optional `language` (typed `CashierLanguage`), forwarded to the checkout session as the hosted page's default language. Inherited from `@waffo/pancake-ts` checkout params; requires `@waffo/pancake-ts` >= 0.13.0.
|
|
15
|
+
|
|
16
|
+
## [0.2.0] - 2026-07-14
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Public API renamed from "buyer" to "customer"** — the merchant's end consumer is called a customer across the SDK (matching the session-token JWT role). New primary names:
|
|
21
|
+
- Hooks: `useBuyer` → `useCustomer` · `useBuyerOrders` → `useCustomerOrders` · `useBuyerPayments` → `useCustomerPayments` · `useBuyerRefundTickets` → `useCustomerRefundTickets`
|
|
22
|
+
- Server action factories (`@waffo/pancake-nextjs/server`): `createBuyerTokenAction` → `createCustomerTokenAction` · `createBuyerSessionAction` → `createCustomerSessionAction`
|
|
23
|
+
- Types: `BuyerConfig` → `CustomerConfig` · `BuyerActionState` → `CustomerActionState` · `UseBuyerReturn` → `UseCustomerReturn` · `BuyerOnetimeOrder` → `CustomerOnetimeOrder` · `BuyerSubscriptionOrder` → `CustomerSubscriptionOrder` · `BuyerPayment` → `CustomerPayment` · `BuyerRefundTicket` → `CustomerRefundTicket` · `BuyerTokenAction` → `CustomerTokenAction` · `BuyerSessionAction` → `CustomerSessionAction` · `BuyerSessionActionType` → `CustomerSessionActionType`
|
|
24
|
+
- `<WaffoPancakeProvider>`: the config prop is now `customer` (the `buyer` prop is still accepted; `customer` wins when both are set)
|
|
25
|
+
- **Wire contract unchanged** — request/payload field names stay as-is: `buyerIdentity` (checkout params, `issueSessionToken` params), `buyerEmail` (webhook event data, GraphQL fields), HTTP paths, and header names. No server-side changes required.
|
|
26
|
+
|
|
27
|
+
### Deprecated
|
|
28
|
+
|
|
29
|
+
- All previous "buyer" names remain exported as working aliases of the new "customer" names (marked `@deprecated`) and will be removed in the next release: `useBuyer`, `useBuyerOrders`, `useBuyerPayments`, `useBuyerRefundTickets`, `createBuyerTokenAction`, `createBuyerSessionAction`, the `Buyer*` types listed above, and the `buyer` prop on `<WaffoPancakeProvider>`.
|
|
30
|
+
|
|
7
31
|
## [0.1.9] - 2026-06-05
|
|
8
32
|
|
|
9
33
|
### Changed
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Next.js SDK for the [Waffo Pancake](https://waffo.ai) Merchant of Record (MoR) p
|
|
|
5
5
|
- Three checkout modes: link (instant redirect), anonymous (API), authenticated (API + token)
|
|
6
6
|
- Popup blocker avoidance — synchronous `window.open` in click handler
|
|
7
7
|
- Webhook route handler with automatic signature verification and event dispatch
|
|
8
|
-
-
|
|
8
|
+
- Customer self-service hooks with automatic token lifecycle management
|
|
9
9
|
- Server action architecture — private keys never leave the server
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
@@ -16,7 +16,7 @@ npm install @waffo/pancake-nextjs
|
|
|
16
16
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
19
|
-
> Most merchants create stores and products in the [Dashboard](https://pancake.waffo.ai/dashboard). This SDK is primarily used for **embedding checkout, webhooks, and
|
|
19
|
+
> Most merchants create stores and products in the [Dashboard](https://pancake.waffo.ai/dashboard). This SDK is primarily used for **embedding checkout, webhooks, and customer self-service** into your Next.js app.
|
|
20
20
|
|
|
21
21
|
The fastest integration — a link checkout button, no API keys needed:
|
|
22
22
|
|
|
@@ -29,15 +29,15 @@ import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
|
29
29
|
</CheckoutButton>;
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
For API-level control (dynamic pricing,
|
|
32
|
+
For API-level control (dynamic pricing, customer identity, trial overrides), set up server actions first:
|
|
33
33
|
|
|
34
34
|
```ts
|
|
35
35
|
// app/lib/waffo.ts — define once, import everywhere
|
|
36
36
|
"use server";
|
|
37
37
|
import {
|
|
38
38
|
createCheckoutAction,
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
createCustomerTokenAction,
|
|
40
|
+
createCustomerSessionAction,
|
|
41
41
|
createMerchantQueryAction,
|
|
42
42
|
} from "@waffo/pancake-nextjs/server";
|
|
43
43
|
|
|
@@ -48,8 +48,8 @@ const config = {
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
export const checkout = createCheckoutAction(config);
|
|
51
|
-
export const
|
|
52
|
-
export const
|
|
51
|
+
export const issueCustomerToken = createCustomerTokenAction(config);
|
|
52
|
+
export const customerAction = createCustomerSessionAction(config);
|
|
53
53
|
export const merchantQuery = createMerchantQueryAction(config);
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -59,13 +59,13 @@ Private keys are captured in server action closures — they never reach the bro
|
|
|
59
59
|
|
|
60
60
|
Waffo supports three checkout modes based on how much control the merchant needs:
|
|
61
61
|
|
|
62
|
-
| Mode | `type` | Needs Server Action? | Use Case
|
|
63
|
-
| ----------------- | ----------------- | :------------------: |
|
|
64
|
-
| **Link** | `"link"` | No | Landing pages, email campaigns. Redirects to product page which auto-creates a session.
|
|
65
|
-
| **Anonymous** | omit | Yes | API-level control without
|
|
66
|
-
| **Authenticated** | `"authenticated"` | Yes | Merchant provides
|
|
62
|
+
| Mode | `type` | Needs Server Action? | Use Case |
|
|
63
|
+
| ----------------- | ----------------- | :------------------: | ---------------------------------------------------------------------------------------- |
|
|
64
|
+
| **Link** | `"link"` | No | Landing pages, email campaigns. Redirects to product page which auto-creates a session. |
|
|
65
|
+
| **Anonymous** | omit | Yes | API-level control without customer identity. Customer fills in details on checkout page. |
|
|
66
|
+
| **Authenticated** | `"authenticated"` | Yes | Merchant provides customer identity. Form pre-filled. Enables customer self-service. |
|
|
67
67
|
|
|
68
|
-
> **We recommend authenticated checkout whenever possible.** It binds orders to a stable merchant-controlled identifier. In anonymous mode, the
|
|
68
|
+
> **We recommend authenticated checkout whenever possible.** It binds orders to a stable merchant-controlled identifier. In anonymous mode, the customer self-reports their email — if they enter a different address, previous orders become unlinked and subscription trial periods can be exploited.
|
|
69
69
|
|
|
70
70
|
### Link Checkout
|
|
71
71
|
|
|
@@ -85,7 +85,7 @@ import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
|
85
85
|
storeSlug="my-store"
|
|
86
86
|
productId="PROD_xxx"
|
|
87
87
|
currency="USD"
|
|
88
|
-
email="
|
|
88
|
+
email="customer@example.com"
|
|
89
89
|
successUrl="https://example.com/thank-you"
|
|
90
90
|
country="US"
|
|
91
91
|
test={false}
|
|
@@ -116,19 +116,24 @@ import { checkout } from "./lib/waffo";
|
|
|
116
116
|
<CheckoutButton action={checkout} productId="PROD_xxx" currency="USD" withTrial={true} billingDetail={{ country: "JP", isBusiness: false }}>
|
|
117
117
|
Start Free Trial
|
|
118
118
|
</CheckoutButton>
|
|
119
|
+
|
|
120
|
+
// Set the default checkout language (IETF BCP 47) — the customer can still switch on the page
|
|
121
|
+
<CheckoutButton action={checkout} productId="PROD_xxx" currency="USD" language="pt-BR">
|
|
122
|
+
Comprar agora
|
|
123
|
+
</CheckoutButton>
|
|
119
124
|
```
|
|
120
125
|
|
|
121
126
|
Pass an optional `orderMerchantExternalId` to attach your internal order reference — see [Business-Side Identifiers](#business-side-identifiers).
|
|
122
127
|
|
|
123
128
|
### Authenticated Checkout (Recommended)
|
|
124
129
|
|
|
125
|
-
Creates a session **and** a token bound to the
|
|
130
|
+
Creates a session **and** a token bound to the customer you provide. `buyerIdentity` is for order attribution and trial tracking — it is not rendered on the checkout page. To pre-fill the email field on the checkout form, pass `buyerEmail` explicitly.
|
|
126
131
|
|
|
127
132
|
```tsx
|
|
128
133
|
import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
129
134
|
import { checkout } from "./lib/waffo";
|
|
130
135
|
|
|
131
|
-
// Basic —
|
|
136
|
+
// Basic — customer identity only (checkout page email field stays empty)
|
|
132
137
|
<CheckoutButton type="authenticated" action={checkout} productId="PROD_xxx" currency="USD" buyerIdentity={user.id}>
|
|
133
138
|
Upgrade to Pro
|
|
134
139
|
</CheckoutButton>
|
|
@@ -191,12 +196,12 @@ const { checkout, isLoading, error } = useCheckout({
|
|
|
191
196
|
|
|
192
197
|
Both `CheckoutButton` and `useCheckout` support two navigation modes via the `mode` prop:
|
|
193
198
|
|
|
194
|
-
- `"redirect"` (default) — navigates the current page.
|
|
199
|
+
- `"redirect"` (default) — navigates the current page. Customer returns via `successUrl`.
|
|
195
200
|
- `"popup"` — opens a new tab. Link mode opens the URL directly; API modes show a loading page first, then redirect once the session is ready.
|
|
196
201
|
|
|
197
202
|
## Webhook Verification
|
|
198
203
|
|
|
199
|
-
After a
|
|
204
|
+
After a customer completes payment, Waffo sends webhook events to your server. The `Webhook` factory creates a Next.js route handler that verifies signatures and dispatches events:
|
|
200
205
|
|
|
201
206
|
```ts
|
|
202
207
|
// app/api/webhooks/waffo/route.ts
|
|
@@ -237,18 +242,20 @@ export const POST = Webhook({
|
|
|
237
242
|
|
|
238
243
|
Returns `200` on success, `401` on invalid signature, `500` if a handler throws. Full event list: `onOrderCompleted`, `onSubscriptionActivated`, `onSubscriptionPaymentSucceeded`, `onSubscriptionCanceling`, `onSubscriptionUncanceled`, `onSubscriptionUpdated`, `onSubscriptionCanceled`, `onSubscriptionPastDue`, `onRefundSucceeded`, `onRefundFailed`.
|
|
239
244
|
|
|
240
|
-
##
|
|
245
|
+
## Customer Self-Service
|
|
241
246
|
|
|
242
|
-
Beyond checkout, you can let
|
|
247
|
+
Beyond checkout, you can let customers manage their own orders and subscriptions. Wrap with `WaffoPancakeProvider` — it auto-issues tokens and refreshes them before expiry:
|
|
243
248
|
|
|
244
249
|
```tsx
|
|
245
|
-
import { WaffoPancakeProvider,
|
|
246
|
-
import {
|
|
250
|
+
import { WaffoPancakeProvider, useCustomer, useCustomerOrders, useCustomerPayments, useCustomerRefundTickets } from "@waffo/pancake-nextjs";
|
|
251
|
+
import { issueCustomerToken, customerAction } from "./lib/waffo";
|
|
247
252
|
|
|
248
253
|
// Wrap once — provider manages token lifecycle
|
|
249
254
|
export default function AccountLayout({ user }: { user: { email: string } }) {
|
|
250
255
|
return (
|
|
251
|
-
<WaffoPancakeProvider
|
|
256
|
+
<WaffoPancakeProvider
|
|
257
|
+
customer={{ identity: user.email, storeId: "STO_xxx", issueToken: issueCustomerToken, sessionAction: customerAction }}
|
|
258
|
+
>
|
|
252
259
|
<AccountPage />
|
|
253
260
|
</WaffoPancakeProvider>
|
|
254
261
|
);
|
|
@@ -256,10 +263,10 @@ export default function AccountLayout({ user }: { user: { email: string } }) {
|
|
|
256
263
|
|
|
257
264
|
// All hooks work without passing token or client
|
|
258
265
|
function AccountPage() {
|
|
259
|
-
const { data: orders, isLoading, refetch } =
|
|
260
|
-
const { data: payments } =
|
|
261
|
-
const { data: tickets } =
|
|
262
|
-
const
|
|
266
|
+
const { data: orders, isLoading, refetch } = useCustomerOrders();
|
|
267
|
+
const { data: payments } = useCustomerPayments();
|
|
268
|
+
const { data: tickets } = useCustomerRefundTickets();
|
|
269
|
+
const customer = useCustomer();
|
|
263
270
|
|
|
264
271
|
if (isLoading) return <p>Loading...</p>;
|
|
265
272
|
|
|
@@ -271,9 +278,9 @@ function AccountPage() {
|
|
|
271
278
|
<p>
|
|
272
279
|
{sub.product?.name} — {sub.status}
|
|
273
280
|
</p>
|
|
274
|
-
{sub.status === "active" && <button onClick={() =>
|
|
281
|
+
{sub.status === "active" && <button onClick={() => customer.cancelSubscription.execute({ orderId: sub.id })}>Cancel</button>}
|
|
275
282
|
{sub.status === "canceling" && (
|
|
276
|
-
<button onClick={() =>
|
|
283
|
+
<button onClick={() => customer.reactivateSubscription.execute({ orderId: sub.id })}>Undo Cancellation</button>
|
|
277
284
|
)}
|
|
278
285
|
</div>
|
|
279
286
|
))}
|
|
@@ -287,7 +294,7 @@ function AccountPage() {
|
|
|
287
294
|
|
|
288
295
|
<button
|
|
289
296
|
onClick={() =>
|
|
290
|
-
|
|
297
|
+
customer.createRefundTicket.execute({
|
|
291
298
|
paymentId: "PAY_xxx",
|
|
292
299
|
reason: "Product not as described",
|
|
293
300
|
requestedAmount: { amount: "29.00", currency: "USD" },
|
|
@@ -302,14 +309,14 @@ function AccountPage() {
|
|
|
302
309
|
}
|
|
303
310
|
```
|
|
304
311
|
|
|
305
|
-
###
|
|
312
|
+
### Customer Hooks
|
|
306
313
|
|
|
307
|
-
| Hook
|
|
308
|
-
|
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
314
|
+
| Hook | Returns | Auto-fetches? |
|
|
315
|
+
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- | :--------------------: |
|
|
316
|
+
| `useCustomer()` | `cancelSubscription`, `cancelOnetimeOrder`, `reactivateSubscription`, `createRefundTicket`, `resubmitRefundTicket`, `query` | No — call `.execute()` |
|
|
317
|
+
| `useCustomerOrders()` | `{ onetimeOrders, subscriptionOrders }` with product, payments, billing cycle | Yes |
|
|
318
|
+
| `useCustomerPayments()` | Payment records — amount, status, failure reason | Yes |
|
|
319
|
+
| `useCustomerRefundTickets()` | Refund tickets — status, reason, amount | Yes |
|
|
313
320
|
|
|
314
321
|
Action hooks return `{ execute, isLoading, error, data }`. Data hooks return `{ data, isLoading, error, refetch }`.
|
|
315
322
|
|
|
@@ -317,10 +324,10 @@ Action hooks return `{ execute, isLoading, error, data }`. Data hooks return `{
|
|
|
317
324
|
|
|
318
325
|
Attach your own internal references to a checkout or a refund ticket so cross-system reconciliation does not require Waffo IDs. Two flat keys, both optional (max 128 chars):
|
|
319
326
|
|
|
320
|
-
| Field | Attach via
|
|
321
|
-
| -------------------------------- |
|
|
322
|
-
| `orderMerchantExternalId` | `CheckoutButton` / `useCheckout`
|
|
323
|
-
| `refundTicketMerchantExternalId` | `
|
|
327
|
+
| Field | Attach via | Inherited by |
|
|
328
|
+
| -------------------------------- | ---------------------------------- | --------------------------------------------- |
|
|
329
|
+
| `orderMerchantExternalId` | `CheckoutButton` / `useCheckout` | `Order`, `Payment` (incl. renewals), `Refund` |
|
|
330
|
+
| `refundTicketMerchantExternalId` | `useCustomer().createRefundTicket` | `RefundTicket`, `Refund` |
|
|
324
331
|
|
|
325
332
|
The same field name appears at every layer: prop / hook param, webhook payload (`event.data.orderMerchantExternalId` / `event.data.refundTicketMerchantExternalId`), and GraphQL types. A `refund.*` webhook event carries **both** keys (order key inherited from the originating order).
|
|
326
333
|
|
|
@@ -333,8 +340,8 @@ The same field name appears at every layer: prop / hook param, webhook payload (
|
|
|
333
340
|
|
|
334
341
|
// 2. Attach at refund-ticket creation — value is bound to the ticket and the
|
|
335
342
|
// refund record once the PSP confirms.
|
|
336
|
-
const
|
|
337
|
-
await
|
|
343
|
+
const customer = useCustomer();
|
|
344
|
+
await customer.createRefundTicket.execute({
|
|
338
345
|
paymentId: "PAY_xxx",
|
|
339
346
|
reason: "Product not as described",
|
|
340
347
|
requestedAmount: { amount: "29.00", currency: "USD" },
|
|
@@ -351,8 +358,8 @@ export const POST = Webhook({
|
|
|
351
358
|
},
|
|
352
359
|
});
|
|
353
360
|
|
|
354
|
-
// 4. Query by reference via the
|
|
355
|
-
const result = await
|
|
361
|
+
// 4. Query by reference via the customer's GraphQL surface — same field name on every type.
|
|
362
|
+
const result = await customer.query({
|
|
356
363
|
query: `query ($ref: String!) {
|
|
357
364
|
onetimeOrders(filter: { orderMerchantExternalId: { eq: $ref } }) {
|
|
358
365
|
id status orderMerchantExternalId
|
|
@@ -386,12 +393,12 @@ All merchant hooks return `{ data, isLoading, error, refetch }`.
|
|
|
386
393
|
|
|
387
394
|
## Server Actions
|
|
388
395
|
|
|
389
|
-
| Factory
|
|
390
|
-
|
|
|
391
|
-
| `createCheckoutAction(config)`
|
|
392
|
-
| `
|
|
393
|
-
| `
|
|
394
|
-
| `createMerchantQueryAction(config)`
|
|
396
|
+
| Factory | Returns | Description |
|
|
397
|
+
| ------------------------------------- | ----------------------- | ----------------------------------------------------- |
|
|
398
|
+
| `createCheckoutAction(config)` | `CheckoutAction` | Checkout session creation (anonymous + authenticated) |
|
|
399
|
+
| `createCustomerTokenAction(config)` | `CustomerTokenAction` | Customer session token issuance |
|
|
400
|
+
| `createCustomerSessionAction(config)` | `CustomerSessionAction` | Customer self-service operations |
|
|
401
|
+
| `createMerchantQueryAction(config)` | `MerchantQueryAction` | Merchant GraphQL queries |
|
|
395
402
|
|
|
396
403
|
Import from `@waffo/pancake-nextjs/server`. Config requires `merchantId` and `privateKey`.
|
|
397
404
|
|
|
@@ -407,7 +414,7 @@ Import from `@waffo/pancake-nextjs/server`. Config requires `merchantId` and `pr
|
|
|
407
414
|
|
|
408
415
|
### Types
|
|
409
416
|
|
|
410
|
-
Key types: `PriceInfo`, `BillingDetail`, `WebhookEvent`, `CheckoutAction`, `
|
|
417
|
+
Key types: `PriceInfo`, `BillingDetail`, `WebhookEvent`, `CheckoutAction`, `CustomerTokenAction`, `CustomerSessionAction`, `MerchantQueryAction`, `CustomerConfig`, `CheckoutButtonProps`, `CheckoutMode`, `CashierLanguage`, `UseCheckoutReturn`, `UseCustomerReturn`, `CustomerActionState<T>`, `QueryState<T>`, `SalesOverview`, `SubscriptionOverview`, `WebhookConfig`.
|
|
411
418
|
|
|
412
419
|
## Development
|
|
413
420
|
|
|
@@ -429,8 +436,8 @@ src/
|
|
|
429
436
|
├── provider.tsx # <WaffoPancakeProvider> — token lifecycle
|
|
430
437
|
├── checkout-button.tsx # <CheckoutButton> component
|
|
431
438
|
├── use-checkout.ts # useCheckout() — link + anonymous + authenticated
|
|
432
|
-
├── use-
|
|
433
|
-
├── use-
|
|
439
|
+
├── use-customer.ts # useCustomer() — customer actions
|
|
440
|
+
├── use-customer-data.ts # useCustomerOrders / useCustomerPayments / useCustomerRefundTickets
|
|
434
441
|
├── use-merchant-data.ts # useMerchantOrders / useMerchantSales / useMerchantSubscriptions
|
|
435
442
|
├── use-query.ts # Shared useQuery helper
|
|
436
443
|
├── webhook.ts # Webhook() route handler factory
|
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,10 @@ __export(src_exports, {
|
|
|
32
32
|
useBuyerPayments: () => useBuyerPayments,
|
|
33
33
|
useBuyerRefundTickets: () => useBuyerRefundTickets,
|
|
34
34
|
useCheckout: () => useCheckout,
|
|
35
|
+
useCustomer: () => useCustomer,
|
|
36
|
+
useCustomerOrders: () => useCustomerOrders,
|
|
37
|
+
useCustomerPayments: () => useCustomerPayments,
|
|
38
|
+
useCustomerRefundTickets: () => useCustomerRefundTickets,
|
|
35
39
|
useMerchantOrders: () => useMerchantOrders,
|
|
36
40
|
useMerchantSales: () => useMerchantSales,
|
|
37
41
|
useMerchantSubscriptions: () => useMerchantSubscriptions
|
|
@@ -43,23 +47,25 @@ var import_react = require("react");
|
|
|
43
47
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
44
48
|
var PancakeContext = (0, import_react.createContext)(null);
|
|
45
49
|
var REFRESH_BUFFER_MS = 3e4;
|
|
46
|
-
function WaffoPancakeProvider({ buyer, children }) {
|
|
50
|
+
function WaffoPancakeProvider({ customer, buyer, children }) {
|
|
51
|
+
const config = customer ?? buyer;
|
|
52
|
+
if (!config) throw new Error("WaffoPancakeProvider: the `customer` prop is required");
|
|
47
53
|
const tokenRef = (0, import_react.useRef)(null);
|
|
48
54
|
const refreshPromiseRef = (0, import_react.useRef)(null);
|
|
49
|
-
const [
|
|
55
|
+
const [isCustomerReady, setIsCustomerReady] = (0, import_react.useState)(false);
|
|
50
56
|
const refreshToken = (0, import_react.useCallback)(async () => {
|
|
51
|
-
const result = await
|
|
52
|
-
buyerIdentity:
|
|
53
|
-
storeId:
|
|
54
|
-
productId:
|
|
57
|
+
const result = await config.issueToken({
|
|
58
|
+
buyerIdentity: config.identity,
|
|
59
|
+
storeId: config.storeId,
|
|
60
|
+
productId: config.productId
|
|
55
61
|
});
|
|
56
62
|
tokenRef.current = {
|
|
57
63
|
token: result.token,
|
|
58
64
|
expiresAt: new Date(result.expiresAt).getTime()
|
|
59
65
|
};
|
|
60
66
|
return result.token;
|
|
61
|
-
}, [
|
|
62
|
-
const
|
|
67
|
+
}, [config]);
|
|
68
|
+
const getCustomerToken = (0, import_react.useCallback)(async () => {
|
|
63
69
|
const current = tokenRef.current;
|
|
64
70
|
if (current && Date.now() < current.expiresAt - REFRESH_BUFFER_MS) {
|
|
65
71
|
return current.token;
|
|
@@ -72,16 +78,16 @@ function WaffoPancakeProvider({ buyer, children }) {
|
|
|
72
78
|
return refreshPromiseRef.current;
|
|
73
79
|
}, [refreshToken]);
|
|
74
80
|
(0, import_react.useEffect)(() => {
|
|
75
|
-
refreshToken().then(() =>
|
|
81
|
+
refreshToken().then(() => setIsCustomerReady(true)).catch(() => setIsCustomerReady(true));
|
|
76
82
|
}, [refreshToken]);
|
|
77
83
|
const value = (0, import_react.useMemo)(
|
|
78
84
|
() => ({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
getCustomerToken,
|
|
86
|
+
customerSessionAction: config.sessionAction,
|
|
87
|
+
hasCustomer: true,
|
|
88
|
+
isCustomerReady
|
|
83
89
|
}),
|
|
84
|
-
[
|
|
90
|
+
[getCustomerToken, config.sessionAction, isCustomerReady]
|
|
85
91
|
);
|
|
86
92
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PancakeContext.Provider, { value, children });
|
|
87
93
|
}
|
|
@@ -165,9 +171,9 @@ function CheckoutButton(props) {
|
|
|
165
171
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: checkout, disabled: disabled || isLoading, className, style, children: isLoading ? loadingChildren ?? children : children });
|
|
166
172
|
}
|
|
167
173
|
|
|
168
|
-
// src/use-
|
|
174
|
+
// src/use-customer.ts
|
|
169
175
|
var import_react3 = require("react");
|
|
170
|
-
function
|
|
176
|
+
function useCustomerAction(actionFn) {
|
|
171
177
|
const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
|
|
172
178
|
const [error, setError] = (0, import_react3.useState)(null);
|
|
173
179
|
const [data, setData] = (0, import_react3.useState)(null);
|
|
@@ -189,34 +195,34 @@ function useBuyerAction(actionFn) {
|
|
|
189
195
|
);
|
|
190
196
|
return { execute, isLoading, error, data };
|
|
191
197
|
}
|
|
192
|
-
function
|
|
198
|
+
function useCustomer() {
|
|
193
199
|
const ctx = (0, import_react3.useContext)(PancakeContext);
|
|
194
|
-
if (!ctx) throw new Error("
|
|
195
|
-
const {
|
|
200
|
+
if (!ctx) throw new Error("useCustomer: must be used within <WaffoPancakeProvider>");
|
|
201
|
+
const { getCustomerToken, customerSessionAction } = ctx;
|
|
196
202
|
const callAction = (0, import_react3.useCallback)(
|
|
197
203
|
async (actionType, params) => {
|
|
198
|
-
const token = await
|
|
199
|
-
return
|
|
204
|
+
const token = await getCustomerToken();
|
|
205
|
+
return customerSessionAction(token, actionType, params);
|
|
200
206
|
},
|
|
201
|
-
[
|
|
207
|
+
[getCustomerToken, customerSessionAction]
|
|
202
208
|
);
|
|
203
|
-
const cancelSubscription =
|
|
209
|
+
const cancelSubscription = useCustomerAction(
|
|
204
210
|
(0, import_react3.useCallback)((params) => callAction("cancelSubscription", params), [callAction])
|
|
205
211
|
);
|
|
206
|
-
const cancelOnetimeOrder =
|
|
212
|
+
const cancelOnetimeOrder = useCustomerAction(
|
|
207
213
|
(0, import_react3.useCallback)((params) => callAction("cancelOnetimeOrder", params), [callAction])
|
|
208
214
|
);
|
|
209
|
-
const reactivateSubscription =
|
|
215
|
+
const reactivateSubscription = useCustomerAction(
|
|
210
216
|
(0, import_react3.useCallback)((params) => callAction("reactivateSubscription", params), [callAction])
|
|
211
217
|
);
|
|
212
|
-
const createRefundTicket =
|
|
218
|
+
const createRefundTicket = useCustomerAction(
|
|
213
219
|
(0, import_react3.useCallback)((params) => callAction("createRefundTicket", params), [callAction])
|
|
214
220
|
);
|
|
215
221
|
const createRefundTicketMapped = (0, import_react3.useMemo)(
|
|
216
222
|
() => ({ ...createRefundTicket, data: createRefundTicket.data?.ticket ?? null }),
|
|
217
223
|
[createRefundTicket]
|
|
218
224
|
);
|
|
219
|
-
const resubmitRefundTicket =
|
|
225
|
+
const resubmitRefundTicket = useCustomerAction(
|
|
220
226
|
(0, import_react3.useCallback)((params) => callAction("resubmitRefundTicket", params), [callAction])
|
|
221
227
|
);
|
|
222
228
|
const resubmitRefundTicketMapped = (0, import_react3.useMemo)(
|
|
@@ -225,10 +231,10 @@ function useBuyer() {
|
|
|
225
231
|
);
|
|
226
232
|
const query = (0, import_react3.useCallback)(
|
|
227
233
|
async (params) => {
|
|
228
|
-
const token = await
|
|
229
|
-
return
|
|
234
|
+
const token = await getCustomerToken();
|
|
235
|
+
return customerSessionAction(token, "query", params);
|
|
230
236
|
},
|
|
231
|
-
[
|
|
237
|
+
[getCustomerToken, customerSessionAction]
|
|
232
238
|
);
|
|
233
239
|
return {
|
|
234
240
|
cancelSubscription,
|
|
@@ -239,8 +245,9 @@ function useBuyer() {
|
|
|
239
245
|
query
|
|
240
246
|
};
|
|
241
247
|
}
|
|
248
|
+
var useBuyer = useCustomer;
|
|
242
249
|
|
|
243
|
-
// src/use-
|
|
250
|
+
// src/use-customer-data.ts
|
|
244
251
|
var import_react5 = require("react");
|
|
245
252
|
|
|
246
253
|
// src/use-query.ts
|
|
@@ -261,8 +268,8 @@ function useQuery(queryFn, ready) {
|
|
|
261
268
|
return { data, isLoading, error, refetch: fetch };
|
|
262
269
|
}
|
|
263
270
|
|
|
264
|
-
// src/use-
|
|
265
|
-
var
|
|
271
|
+
// src/use-customer-data.ts
|
|
272
|
+
var CUSTOMER_ORDERS_QUERY = `query {
|
|
266
273
|
onetimeOrders(limit: 50) {
|
|
267
274
|
id status currency buyerEmail createdAt
|
|
268
275
|
product { id name }
|
|
@@ -274,12 +281,12 @@ var BUYER_ORDERS_QUERY = `query {
|
|
|
274
281
|
payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }
|
|
275
282
|
}
|
|
276
283
|
}`;
|
|
277
|
-
var
|
|
284
|
+
var CUSTOMER_PAYMENTS_QUERY = `query {
|
|
278
285
|
payments(limit: 50) {
|
|
279
286
|
id orderId status snapshotDisplayAmount snapshotDisplayCurrency failureReason createdAt
|
|
280
287
|
}
|
|
281
288
|
}`;
|
|
282
|
-
var
|
|
289
|
+
var CUSTOMER_REFUND_TICKETS_QUERY = `query {
|
|
283
290
|
refundTickets(limit: 50) {
|
|
284
291
|
id status versionNumber
|
|
285
292
|
versionData {
|
|
@@ -289,28 +296,31 @@ var BUYER_REFUND_TICKETS_QUERY = `query {
|
|
|
289
296
|
createdAt
|
|
290
297
|
}
|
|
291
298
|
}`;
|
|
292
|
-
function
|
|
299
|
+
function useCustomerQuery(query) {
|
|
293
300
|
const ctx = (0, import_react5.useContext)(PancakeContext);
|
|
294
|
-
if (!ctx) throw new Error("
|
|
295
|
-
const {
|
|
301
|
+
if (!ctx) throw new Error("Customer data hook: must be used within <WaffoPancakeProvider>");
|
|
302
|
+
const { getCustomerToken, customerSessionAction, isCustomerReady } = ctx;
|
|
296
303
|
const queryFn = (0, import_react5.useCallback)(async () => {
|
|
297
|
-
const token = await
|
|
298
|
-
const result = await
|
|
304
|
+
const token = await getCustomerToken();
|
|
305
|
+
const result = await customerSessionAction(token, "query", { query });
|
|
299
306
|
return result.data;
|
|
300
|
-
}, [
|
|
301
|
-
return useQuery(queryFn,
|
|
307
|
+
}, [getCustomerToken, customerSessionAction, query]);
|
|
308
|
+
return useQuery(queryFn, isCustomerReady);
|
|
302
309
|
}
|
|
303
|
-
function
|
|
304
|
-
return
|
|
310
|
+
function useCustomerOrders() {
|
|
311
|
+
return useCustomerQuery(CUSTOMER_ORDERS_QUERY);
|
|
305
312
|
}
|
|
306
|
-
function
|
|
307
|
-
const result =
|
|
313
|
+
function useCustomerPayments() {
|
|
314
|
+
const result = useCustomerQuery(CUSTOMER_PAYMENTS_QUERY);
|
|
308
315
|
return { ...result, data: result.data?.payments ?? null };
|
|
309
316
|
}
|
|
310
|
-
function
|
|
311
|
-
const result =
|
|
317
|
+
function useCustomerRefundTickets() {
|
|
318
|
+
const result = useCustomerQuery(CUSTOMER_REFUND_TICKETS_QUERY);
|
|
312
319
|
return { ...result, data: result.data?.refundTickets ?? null };
|
|
313
320
|
}
|
|
321
|
+
var useBuyerOrders = useCustomerOrders;
|
|
322
|
+
var useBuyerPayments = useCustomerPayments;
|
|
323
|
+
var useBuyerRefundTickets = useCustomerRefundTickets;
|
|
314
324
|
|
|
315
325
|
// src/use-merchant-data.ts
|
|
316
326
|
var import_react6 = require("react");
|
|
@@ -464,6 +474,10 @@ var import_pancake_ts2 = require("@waffo/pancake-ts");
|
|
|
464
474
|
useBuyerPayments,
|
|
465
475
|
useBuyerRefundTickets,
|
|
466
476
|
useCheckout,
|
|
477
|
+
useCustomer,
|
|
478
|
+
useCustomerOrders,
|
|
479
|
+
useCustomerPayments,
|
|
480
|
+
useCustomerRefundTickets,
|
|
467
481
|
useMerchantOrders,
|
|
468
482
|
useMerchantSales,
|
|
469
483
|
useMerchantSubscriptions
|