@waffo/pancake-nextjs 0.1.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 +22 -0
- package/README.md +371 -0
- package/dist/index.cjs +466 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +560 -0
- package/dist/index.d.ts +560 -0
- package/dist/index.js +427 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +82 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +96 -0
- package/dist/server.d.ts +96 -0
- package/dist/server.js +54 -0
- package/dist/server.js.map +1 -0
- package/package.json +96 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@waffo/pancake-nextjs` will be documented in this file.
|
|
4
|
+
|
|
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
|
+
|
|
7
|
+
## [0.1.0] - 2026-04-10
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`<WaffoPancakeProvider>`** — Context provider that manages the Waffo Pancake client and buyer token lifecycle. Auto-issues session tokens, caches in memory, refreshes 30s before expiry. All buyer hooks read from context — no manual token management.
|
|
12
|
+
- **`<CheckoutButton>`** — React component for one-click checkout. Three modes: `type="link"` (instant redirect, no API call), anonymous (API session), `type="authenticated"` (API session + token). All props flattened directly on the component. Popup blocker avoidance via synchronous `window.open`.
|
|
13
|
+
- **`useCheckout()`** — React hook for programmatic checkout flow. Same three modes as `CheckoutButton`. Returns `{ checkout, isLoading, error }`.
|
|
14
|
+
- **`Webhook()`** — Next.js route handler factory for webhook signature verification. Auto-dispatches to 10 event-specific handlers (`onOrderCompleted`, `onSubscriptionActivated`, `onRefundSucceeded`, etc.). Supports catch-all `onPayload` handler.
|
|
15
|
+
- **`useBuyer()`** — React hook for buyer self-service actions. Works with Provider (no args) or standalone (client + token). Actions: `cancelSubscription`, `cancelOnetimeOrder`, `reactivateSubscription`, `createRefundTicket`, `resubmitRefundTicket`, `query`.
|
|
16
|
+
- **`useBuyerOrders()`** — Fetch buyer's order history (one-time + subscription) with product info, payments, and billing cycle.
|
|
17
|
+
- **`useBuyerPayments()`** — Fetch buyer's payment records with amounts, status, and failure reasons.
|
|
18
|
+
- **`useBuyerRefundTickets()`** — Fetch buyer's refund tickets with status and requested amounts.
|
|
19
|
+
- **`useMerchantOrders(client, { storeId })`** — Fetch recent orders for a store.
|
|
20
|
+
- **`useMerchantSales(client, storeId)`** — Fetch sales overview: revenue, order count, customer count, status breakdown, revenue trend.
|
|
21
|
+
- **`useMerchantSubscriptions(client, storeId)`** — Fetch subscription overview: active/canceling/pastDue counts + full list.
|
|
22
|
+
- **Re-exports from `@waffo/pancake-ts`** — `WaffoPancake`, `WaffoPancakeError`, `TaxCategory`, `WebhookEventType`, `PriceInfo`, `BillingDetail`, `WebhookEvent`, `WaffoPancakeConfig`. One package, all imports.
|
package/README.md
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# @waffo/pancake-nextjs
|
|
2
|
+
|
|
3
|
+
Next.js SDK for the [Waffo Pancake](https://waffo.ai) Merchant of Record (MoR) payment platform.
|
|
4
|
+
|
|
5
|
+
- Three checkout modes: link (instant redirect), anonymous (API), authenticated (API + token)
|
|
6
|
+
- Popup blocker avoidance — synchronous `window.open` in click handler
|
|
7
|
+
- Webhook route handler with automatic signature verification and event dispatch
|
|
8
|
+
- Buyer self-service hooks with automatic token lifecycle management
|
|
9
|
+
- Server action architecture — private keys never leave the server
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @waffo/pancake-nextjs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
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 buyer self-service** into your Next.js app.
|
|
20
|
+
|
|
21
|
+
The fastest integration — a link checkout button, no API keys needed:
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
25
|
+
|
|
26
|
+
// Product ID and store slug are available in Dashboard > Products
|
|
27
|
+
<CheckoutButton type="link" storeSlug="my-store" productId="PROD_xxx" currency="USD">
|
|
28
|
+
Buy Now
|
|
29
|
+
</CheckoutButton>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For API-level control (dynamic pricing, buyer identity, trial overrides), set up server actions first:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// app/lib/waffo.ts — define once, import everywhere
|
|
36
|
+
"use server";
|
|
37
|
+
import {
|
|
38
|
+
createCheckoutAction,
|
|
39
|
+
createBuyerTokenAction,
|
|
40
|
+
createBuyerSessionAction,
|
|
41
|
+
createMerchantQueryAction,
|
|
42
|
+
} from "@waffo/pancake-nextjs/server";
|
|
43
|
+
|
|
44
|
+
// Merchant ID and API Key are available in Dashboard > Settings > Developers
|
|
45
|
+
const config = {
|
|
46
|
+
merchantId: process.env.WAFFO_MERCHANT_ID!,
|
|
47
|
+
privateKey: process.env.WAFFO_PRIVATE_KEY!,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const checkout = createCheckoutAction(config);
|
|
51
|
+
export const issueBuyerToken = createBuyerTokenAction(config);
|
|
52
|
+
export const buyerAction = createBuyerSessionAction(config);
|
|
53
|
+
export const merchantQuery = createMerchantQueryAction(config);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Private keys are captured in server action closures — they never reach the browser.
|
|
57
|
+
|
|
58
|
+
## Checkout Integration
|
|
59
|
+
|
|
60
|
+
Waffo supports three checkout modes based on how much control the merchant needs:
|
|
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 buyer identity. Buyer fills in details on checkout page. |
|
|
66
|
+
| **Authenticated** | `"authenticated"` | Yes | Merchant provides buyer identity. Form pre-filled. Enables buyer self-service. |
|
|
67
|
+
|
|
68
|
+
> **We recommend authenticated checkout whenever possible.** It binds orders to a stable merchant-controlled identifier. In anonymous mode, the buyer self-reports their email — if they enter a different address, previous orders become unlinked and subscription trial periods can be exploited.
|
|
69
|
+
|
|
70
|
+
### Link Checkout
|
|
71
|
+
|
|
72
|
+
No server action needed. Builds a product page URL and redirects directly:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
76
|
+
|
|
77
|
+
// Basic
|
|
78
|
+
<CheckoutButton type="link" storeSlug="my-store" productId="PROD_xxx" currency="USD">
|
|
79
|
+
Buy Now — $29
|
|
80
|
+
</CheckoutButton>
|
|
81
|
+
|
|
82
|
+
// With all options
|
|
83
|
+
<CheckoutButton
|
|
84
|
+
type="link"
|
|
85
|
+
storeSlug="my-store"
|
|
86
|
+
productId="PROD_xxx"
|
|
87
|
+
currency="USD"
|
|
88
|
+
email="buyer@example.com"
|
|
89
|
+
successUrl="https://example.com/thank-you"
|
|
90
|
+
country="US"
|
|
91
|
+
test={false}
|
|
92
|
+
>
|
|
93
|
+
Buy Now
|
|
94
|
+
</CheckoutButton>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Anonymous Checkout
|
|
98
|
+
|
|
99
|
+
Creates a checkout session via server action, then redirects:
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
103
|
+
import { checkout } from "./lib/waffo";
|
|
104
|
+
|
|
105
|
+
// Basic — use product's stored price
|
|
106
|
+
<CheckoutButton action={checkout} productId="PROD_xxx" currency="USD">
|
|
107
|
+
Buy Now
|
|
108
|
+
</CheckoutButton>
|
|
109
|
+
|
|
110
|
+
// Dynamic pricing — override with a coupon or volume discount
|
|
111
|
+
<CheckoutButton action={checkout} productId="PROD_xxx" currency="USD" priceSnapshot={{ amount: "19.99", taxCategory: "digital_goods" }}>
|
|
112
|
+
Buy Now — $19.99 (20% off)
|
|
113
|
+
</CheckoutButton>
|
|
114
|
+
|
|
115
|
+
// Subscription with trial control + billing pre-fill
|
|
116
|
+
<CheckoutButton action={checkout} productId="PROD_xxx" currency="USD" withTrial={true} billingDetail={{ country: "JP", isBusiness: false }}>
|
|
117
|
+
Start Free Trial
|
|
118
|
+
</CheckoutButton>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Authenticated Checkout (Recommended)
|
|
122
|
+
|
|
123
|
+
Creates a session **and** a token. The checkout form arrives pre-filled with the buyer's identity:
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { CheckoutButton } from "@waffo/pancake-nextjs";
|
|
127
|
+
import { checkout } from "./lib/waffo";
|
|
128
|
+
|
|
129
|
+
// Basic — form pre-filled with email
|
|
130
|
+
<CheckoutButton type="authenticated" action={checkout} productId="PROD_xxx" currency="USD" buyerIdentity={user.email}>
|
|
131
|
+
Upgrade to Pro
|
|
132
|
+
</CheckoutButton>
|
|
133
|
+
|
|
134
|
+
// Dynamic pricing + popup mode (keeps your page open during checkout)
|
|
135
|
+
<CheckoutButton
|
|
136
|
+
type="authenticated"
|
|
137
|
+
action={checkout}
|
|
138
|
+
productId="PROD_xxx"
|
|
139
|
+
currency="USD"
|
|
140
|
+
buyerIdentity={user.email}
|
|
141
|
+
priceSnapshot={{ amount: "7.99", taxCategory: "saas" }}
|
|
142
|
+
mode="popup"
|
|
143
|
+
loadingChildren="Opening checkout..."
|
|
144
|
+
>
|
|
145
|
+
Upgrade — $7.99/mo
|
|
146
|
+
</CheckoutButton>
|
|
147
|
+
|
|
148
|
+
// Full pre-fill — identity + billing + skip trial
|
|
149
|
+
<CheckoutButton
|
|
150
|
+
type="authenticated"
|
|
151
|
+
action={checkout}
|
|
152
|
+
productId="PROD_xxx"
|
|
153
|
+
currency="USD"
|
|
154
|
+
buyerIdentity={user.email}
|
|
155
|
+
billingDetail={{ country: "US", isBusiness: true, state: "CA" }}
|
|
156
|
+
withTrial={false}
|
|
157
|
+
successUrl="https://example.com/dashboard?upgraded=true"
|
|
158
|
+
>
|
|
159
|
+
Skip Trial, Start Now
|
|
160
|
+
</CheckoutButton>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### useCheckout Hook
|
|
164
|
+
|
|
165
|
+
For programmatic control — same props as `CheckoutButton`, returns `{ checkout, isLoading, error }`:
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { useCheckout } from "@waffo/pancake-nextjs";
|
|
169
|
+
import { checkout as checkoutAction } from "./lib/waffo";
|
|
170
|
+
|
|
171
|
+
const { checkout, isLoading, error } = useCheckout({
|
|
172
|
+
type: "authenticated",
|
|
173
|
+
action: checkoutAction,
|
|
174
|
+
productId: "PROD_xxx",
|
|
175
|
+
currency: "USD",
|
|
176
|
+
buyerIdentity: user.email,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
<button onClick={checkout} disabled={isLoading}>
|
|
180
|
+
{isLoading ? "Creating session..." : "Buy Now"}
|
|
181
|
+
</button>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Navigation Modes
|
|
185
|
+
|
|
186
|
+
Both `CheckoutButton` and `useCheckout` support two navigation modes via the `mode` prop:
|
|
187
|
+
|
|
188
|
+
- `"redirect"` (default) — navigates the current page. Buyer returns via `successUrl`.
|
|
189
|
+
- `"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.
|
|
190
|
+
|
|
191
|
+
## Webhook Verification
|
|
192
|
+
|
|
193
|
+
After a buyer completes payment, Waffo sends webhook events to your server. The `Webhook` factory creates a Next.js route handler that verifies signatures and dispatches events:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
// app/api/webhooks/waffo/route.ts
|
|
197
|
+
import { Webhook } from "@waffo/pancake-nextjs";
|
|
198
|
+
|
|
199
|
+
export const POST = Webhook({
|
|
200
|
+
verifyOptions: { environment: "prod" },
|
|
201
|
+
|
|
202
|
+
// Event-specific handlers
|
|
203
|
+
onOrderCompleted: async (event) => {
|
|
204
|
+
console.log(`Order ${event.data.orderId} completed`);
|
|
205
|
+
await grantAccess(event.data.orderId, event.data.buyerEmail);
|
|
206
|
+
},
|
|
207
|
+
onSubscriptionActivated: async (event) => {
|
|
208
|
+
await enableSubscription(event.data.orderId);
|
|
209
|
+
},
|
|
210
|
+
onSubscriptionPaymentSucceeded: async (event) => {
|
|
211
|
+
await extendAccess(event.data.orderId);
|
|
212
|
+
},
|
|
213
|
+
onSubscriptionCanceled: async (event) => {
|
|
214
|
+
await revokeAccess(event.data.orderId);
|
|
215
|
+
},
|
|
216
|
+
onRefundSucceeded: async (event) => {
|
|
217
|
+
await revokeAccess(event.data.orderId);
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
// Catch-all — fires for every event (optional)
|
|
221
|
+
onPayload: async (event) => {
|
|
222
|
+
console.log(`Received ${event.eventType}`, event.data);
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
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`.
|
|
228
|
+
|
|
229
|
+
## Buyer Self-Service
|
|
230
|
+
|
|
231
|
+
Beyond checkout, you can let buyers manage their own orders and subscriptions. Wrap with `WaffoPancakeProvider` — it auto-issues tokens and refreshes them before expiry:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
import { WaffoPancakeProvider, useBuyer, useBuyerOrders, useBuyerPayments, useBuyerRefundTickets } from "@waffo/pancake-nextjs";
|
|
235
|
+
import { issueBuyerToken, buyerAction } from "./lib/waffo";
|
|
236
|
+
|
|
237
|
+
// Wrap once — provider manages token lifecycle
|
|
238
|
+
export default function AccountLayout({ user }: { user: { email: string } }) {
|
|
239
|
+
return (
|
|
240
|
+
<WaffoPancakeProvider buyer={{ identity: user.email, storeId: "STO_xxx", issueToken: issueBuyerToken, sessionAction: buyerAction }}>
|
|
241
|
+
<AccountPage />
|
|
242
|
+
</WaffoPancakeProvider>
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// All hooks work without passing token or client
|
|
247
|
+
function AccountPage() {
|
|
248
|
+
const { data: orders, isLoading, refetch } = useBuyerOrders();
|
|
249
|
+
const { data: payments } = useBuyerPayments();
|
|
250
|
+
const { data: tickets } = useBuyerRefundTickets();
|
|
251
|
+
const buyer = useBuyer();
|
|
252
|
+
|
|
253
|
+
if (isLoading) return <p>Loading...</p>;
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<div>
|
|
257
|
+
{/* Subscription management */}
|
|
258
|
+
{orders?.subscriptionOrders.map((sub) => (
|
|
259
|
+
<div key={sub.id}>
|
|
260
|
+
<p>{sub.product?.name} — {sub.status}</p>
|
|
261
|
+
{sub.status === "active" && (
|
|
262
|
+
<button onClick={() => buyer.cancelSubscription.execute({ orderId: sub.id })}>
|
|
263
|
+
Cancel
|
|
264
|
+
</button>
|
|
265
|
+
)}
|
|
266
|
+
{sub.status === "canceling" && (
|
|
267
|
+
<button onClick={() => buyer.reactivateSubscription.execute({ orderId: sub.id })}>
|
|
268
|
+
Undo Cancellation
|
|
269
|
+
</button>
|
|
270
|
+
)}
|
|
271
|
+
</div>
|
|
272
|
+
))}
|
|
273
|
+
|
|
274
|
+
{/* Order history */}
|
|
275
|
+
{orders?.onetimeOrders.map((order) => (
|
|
276
|
+
<p key={order.id}>{order.product?.name} — {order.status}</p>
|
|
277
|
+
))}
|
|
278
|
+
</div>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Buyer Hooks
|
|
284
|
+
|
|
285
|
+
| Hook | Returns | Auto-fetches? |
|
|
286
|
+
|------|---------|:-------------:|
|
|
287
|
+
| `useBuyer()` | `cancelSubscription`, `cancelOnetimeOrder`, `reactivateSubscription`, `createRefundTicket`, `resubmitRefundTicket`, `query` | No — call `.execute()` |
|
|
288
|
+
| `useBuyerOrders()` | `{ onetimeOrders, subscriptionOrders }` with product, payments, billing cycle | Yes |
|
|
289
|
+
| `useBuyerPayments()` | Payment records — amount, status, failure reason | Yes |
|
|
290
|
+
| `useBuyerRefundTickets()` | Refund tickets — status, reason, amount | Yes |
|
|
291
|
+
|
|
292
|
+
Action hooks return `{ execute, isLoading, error, data }`. Data hooks return `{ data, isLoading, error, refetch }`.
|
|
293
|
+
|
|
294
|
+
## Merchant Data
|
|
295
|
+
|
|
296
|
+
Pre-built hooks for merchant dashboards. Pass a server action and store ID:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import { useMerchantSales, useMerchantOrders, useMerchantSubscriptions } from "@waffo/pancake-nextjs";
|
|
300
|
+
import { merchantQuery } from "./lib/waffo";
|
|
301
|
+
|
|
302
|
+
function Dashboard() {
|
|
303
|
+
const storeId = "STO_xxx";
|
|
304
|
+
const { data: sales } = useMerchantSales(merchantQuery, storeId);
|
|
305
|
+
const { data: orders, refetch } = useMerchantOrders(merchantQuery, { storeId, limit: 10 });
|
|
306
|
+
const { data: subs } = useMerchantSubscriptions(merchantQuery, storeId);
|
|
307
|
+
|
|
308
|
+
// sales: { totalRevenue, totalOrders, totalCustomers, currency, ordersByStatus, revenueByPeriod }
|
|
309
|
+
// orders: { onetimeOrders, subscriptionOrders } — each with product, payments, testMode
|
|
310
|
+
// subs: { activeCount, cancelingCount, pastDueCount, totalCount, subscriptions }
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
All merchant hooks return `{ data, isLoading, error, refetch }`.
|
|
315
|
+
|
|
316
|
+
## Server Actions
|
|
317
|
+
|
|
318
|
+
| Factory | Returns | Description |
|
|
319
|
+
|---------|---------|-------------|
|
|
320
|
+
| `createCheckoutAction(config)` | `CheckoutAction` | Checkout session creation (anonymous + authenticated) |
|
|
321
|
+
| `createBuyerTokenAction(config)` | `BuyerTokenAction` | Buyer session token issuance |
|
|
322
|
+
| `createBuyerSessionAction(config)` | `BuyerSessionAction` | Buyer self-service operations |
|
|
323
|
+
| `createMerchantQueryAction(config)` | `MerchantQueryAction` | Merchant GraphQL queries |
|
|
324
|
+
|
|
325
|
+
Import from `@waffo/pancake-nextjs/server`. Config requires `merchantId` and `privateKey`.
|
|
326
|
+
|
|
327
|
+
## Exports
|
|
328
|
+
|
|
329
|
+
### Classes & Enums
|
|
330
|
+
|
|
331
|
+
| Export | Description |
|
|
332
|
+
|--------|-------------|
|
|
333
|
+
| `WaffoPancakeError` | API error with HTTP status and call-stack errors |
|
|
334
|
+
| `TaxCategory` | `DigitalGoods`, `SaaS`, `Software`, `Ebook`, `OnlineCourse`, `Consulting`, `ProfessionalService` |
|
|
335
|
+
| `WebhookEventType` | `OrderCompleted`, `SubscriptionActivated`, `SubscriptionCanceled`, etc. |
|
|
336
|
+
|
|
337
|
+
### Types
|
|
338
|
+
|
|
339
|
+
Key types: `PriceInfo`, `BillingDetail`, `WebhookEvent`, `CheckoutAction`, `BuyerTokenAction`, `BuyerSessionAction`, `MerchantQueryAction`, `BuyerConfig`, `CheckoutButtonProps`, `CheckoutMode`, `UseCheckoutReturn`, `UseBuyerReturn`, `BuyerActionState<T>`, `QueryState<T>`, `SalesOverview`, `SubscriptionOverview`, `WebhookConfig`.
|
|
340
|
+
|
|
341
|
+
## Development
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
npm run lint # ESLint 9 (TypeScript ESLint + import order + JSDoc + react-hooks)
|
|
345
|
+
npm run test # Vitest (jsdom)
|
|
346
|
+
npm run test:watch # Vitest in watch mode
|
|
347
|
+
npm run test:coverage # Vitest with v8 coverage
|
|
348
|
+
npm run build # tsup → client (ESM+CJS "use client") + server (ESM+CJS)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## Project Structure
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
src/
|
|
355
|
+
├── index.ts # Client barrel export ("use client")
|
|
356
|
+
├── server.ts # Server barrel export (action factories)
|
|
357
|
+
├── types.ts # Shared type definitions
|
|
358
|
+
├── provider.tsx # <WaffoPancakeProvider> — token lifecycle
|
|
359
|
+
├── checkout-button.tsx # <CheckoutButton> component
|
|
360
|
+
├── use-checkout.ts # useCheckout() — link + anonymous + authenticated
|
|
361
|
+
├── use-buyer.ts # useBuyer() — buyer actions
|
|
362
|
+
├── use-buyer-data.ts # useBuyerOrders / useBuyerPayments / useBuyerRefundTickets
|
|
363
|
+
├── use-merchant-data.ts # useMerchantOrders / useMerchantSales / useMerchantSubscriptions
|
|
364
|
+
├── use-query.ts # Shared useQuery helper
|
|
365
|
+
├── webhook.ts # Webhook() route handler factory
|
|
366
|
+
└── __tests__/
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## License
|
|
370
|
+
|
|
371
|
+
MIT
|