@waffo/pancake-ts 0.1.9 → 0.2.1
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 -5
- package/README.md +98 -12
- package/dist/index.cjs +343 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +259 -15
- package/dist/index.d.ts +259 -15
- package/dist/index.js +343 -6
- package/dist/index.js.map +1 -1
- package/docs/api-reference.md +92 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,22 +4,39 @@ All notable changes to `@waffo/pancake-ts` 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.1
|
|
7
|
+
## [0.2.1] - 2026-04-02
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Client-side input validation** — All resource methods now validate inputs before sending network requests. Checks include: required field presence, Short ID format (`STO_xxx`, `PROD_xxx`, etc.), ISO 4217 currency codes, ISO 3166-1 country codes, display-format amount strings, enum value ranges, and positive integers. Validation errors throw `WaffoPancakeError` with `status: 400` and `layer: "sdk"`, so developers catch them uniformly with API errors.
|
|
12
|
+
- **`ErrorLayer.Sdk`** — New `"sdk"` value in the `ErrorLayer` enum for client-side validation errors.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **Types** — `RefundTicketStatus` enum now includes all 9 statuses: added `UnderReview`, `Returned`, `Cancelled` (previously missing 3 values)
|
|
17
|
+
- **Types** — `RefundTicket.currentVersionId` corrected to `string | null` (was `string`)
|
|
18
|
+
- **Types** — `RefundTicket.versionNumber` corrected to `number | null` (was `number`)
|
|
19
|
+
- **Types** — `RefundTicket.versionData` corrected to `Record<string, unknown> | null` (was non-nullable)
|
|
20
|
+
- **Types** — `RefundTicket` now includes `createdAt` and `updatedAt` fields (previously missing)
|
|
21
|
+
- **Types** — `PriceInfo`, `Prices`, `WebhookEvent` JSDoc examples corrected from numeric amounts to display-format strings
|
|
22
|
+
|
|
23
|
+
## [0.2.0] - 2026-04-02
|
|
8
24
|
|
|
9
25
|
### Added
|
|
10
26
|
|
|
11
27
|
- **Checkout convenience methods** — `client.checkout.authenticated.create()` and `client.checkout.anonymous.create()` wrap the full checkout flow into a single call. Authenticated mode issues a session token, creates a checkout session, and returns a URL with the token appended as a URL fragment. Anonymous mode creates a session directly.
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
28
|
+
- **Buyer self-service** — `client.buyer(token)` creates a session-token-authenticated buyer session with methods: `cancelSubscription()`, `cancelOnetimeOrder()`, `reactivateSubscription()`, `createRefundTicket()`, `resubmitRefundTicket()`, and `graphql.query()`.
|
|
29
|
+
- **Types** — `AuthenticatedCheckoutParams`, `AuthenticatedCheckoutResult`, `AnonymousCheckoutParams`, `CancelOnetimeOrderParams`, `CancelOnetimeOrderResult`, `ReactivateSubscriptionParams`, `ReactivateSubscriptionResult`, `CreateRefundTicketParams`, `ResubmitRefundTicketParams`, `RefundTicket`, `RequestedAmount`
|
|
30
|
+
- **Resources** — `CheckoutAnonymousResource`, `CheckoutAuthenticatedResource`, `BuyerSession`, `BuyerHttpClient`
|
|
14
31
|
|
|
15
32
|
### Changed
|
|
16
33
|
|
|
17
34
|
- **Base URL** — Default API endpoint changed from `waffo-pancake-auth-service.vercel.app` to `api.waffo.ai`
|
|
18
35
|
- **Package** — `docs/` directory now included in npm package (`files` field)
|
|
19
|
-
- **Docs** — `docs/api-reference.md` synced with endpoint docs: fixed `storeId` required status, added `BillingDetail` conditional field rules, fixed price amount format (display string, not integer), added subscription product group UUID note
|
|
36
|
+
- **Docs** — `docs/api-reference.md` synced with endpoint docs: fixed `storeId` required status, added `BillingDetail` conditional field rules, fixed price amount format (display string, not integer), added subscription product group UUID note, added Buyer Self-Service section
|
|
20
37
|
- **Docs** — `docs/graphql-guide.md` rewritten: corrected query names (`onetimeOrders` / `subscriptionOrders`), added product version queries, exchange rate query, webhook/email delivery log queries, 9 analytics queries (`orderStatistics`, `paymentStatistics`, `productStatistics`, `trendAnalysis`, `distributionAnalysis`, `customerAnalysis`, `taxAnalysis`, `subscriptionAnalysis`, `refundTicketAnalysis`), updated count query list and filter examples
|
|
21
38
|
- **Docs** — `docs/webhook-guide.md` fixed `amount` / `taxAmount` type from `number` to `string` (display format), added retry mechanism section with delivery status table
|
|
22
|
-
- **README** — Reorganized by use-case priority (checkout → webhooks → GraphQL → programmatic management), added checkout mode comparison and recommendation rationale
|
|
39
|
+
- **README** — Reorganized by use-case priority (checkout → webhooks → buyer self-service → GraphQL → programmatic management), added checkout mode comparison and recommendation rationale
|
|
23
40
|
|
|
24
41
|
## [0.1.8] - 2026-03-20
|
|
25
42
|
|
package/README.md
CHANGED
|
@@ -66,32 +66,54 @@ Waffo supports two checkout modes based on whether the merchant knows the buyer'
|
|
|
66
66
|
|
|
67
67
|
> **We recommend authenticated checkout whenever possible.** The most important reason: authenticated checkout binds the order to the `buyerIdentity` you provide, which is a **merchant-controlled stable identifier**. Even if the buyer changes the email on the checkout form, the order is still tied to the identity you specified. In anonymous mode, the buyer self-reports their email on the form — if they enter a different address, the system treats them as a new user, which means **previous orders become unlinked** and **subscription trial periods can be exploited** (a new email = a new user = a fresh trial).
|
|
68
68
|
>
|
|
69
|
-
>
|
|
70
|
-
>
|
|
71
|
-
> | | Authenticated (`customer`) | Anonymous (`shopper`) |
|
|
69
|
+
> | | Authenticated | Anonymous |
|
|
72
70
|
> |---|---|---|
|
|
73
71
|
> | **Identity** | Merchant-provided, stable across orders | Self-reported email, may vary |
|
|
74
|
-
> | **
|
|
75
|
-
> | **
|
|
76
|
-
> | **
|
|
72
|
+
> | **Form** | Pre-filled from merchant-provided identity | Empty, buyer fills manually |
|
|
73
|
+
> | **Post-purchase** | Full self-service (see [Buyer Self-Service](#buyer-self-service)) | Create orders only — no post-purchase self-service |
|
|
74
|
+
> | **Session** | 5-minute TTL, auto-refreshes | 1-minute, single-use |
|
|
75
|
+
|
|
76
|
+
Both modes support **dynamic pricing** and **trial control** at checkout time:
|
|
77
|
+
|
|
78
|
+
- `priceSnapshot` — override the product's stored price with a custom amount (e.g., coupon, volume discount)
|
|
79
|
+
- `withTrial` — explicitly enable or disable the trial period for subscriptions (`true` = force trial, `false` = skip trial, omit = use default rules)
|
|
77
80
|
|
|
78
81
|
### Authenticated Checkout (Recommended)
|
|
79
82
|
|
|
80
83
|
The merchant provides buyer identity — the SDK issues a session token, creates a checkout session, and returns a checkout URL with the token appended as a URL fragment. One call does everything.
|
|
81
84
|
|
|
82
85
|
```typescript
|
|
86
|
+
// Basic — buyer identity only
|
|
87
|
+
const result = await client.checkout.authenticated.create({
|
|
88
|
+
storeId: "STO_xxx",
|
|
89
|
+
productId: "PROD_xxx",
|
|
90
|
+
productType: "onetime",
|
|
91
|
+
currency: "USD",
|
|
92
|
+
buyerIdentity: "customer@example.com",
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// With dynamic pricing — override stored price (e.g., coupon, volume discount)
|
|
83
96
|
const result = await client.checkout.authenticated.create({
|
|
84
97
|
storeId: "STO_xxx",
|
|
85
98
|
productId: "PROD_xxx",
|
|
86
99
|
productType: "onetime",
|
|
87
100
|
currency: "USD",
|
|
88
101
|
buyerIdentity: "customer@example.com",
|
|
89
|
-
|
|
102
|
+
priceSnapshot: { amount: "19.99", taxCategory: "digital_goods" },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Subscription with trial control + billing detail pre-fill
|
|
106
|
+
const result = await client.checkout.authenticated.create({
|
|
107
|
+
storeId: "STO_xxx",
|
|
108
|
+
productId: "PROD_xxx",
|
|
109
|
+
productType: "subscription",
|
|
110
|
+
currency: "USD",
|
|
111
|
+
buyerIdentity: "customer@example.com",
|
|
112
|
+
withTrial: true, // force enable trial (false = skip, omit = default rules)
|
|
90
113
|
billingDetail: { country: "US", isBusiness: false },
|
|
91
114
|
});
|
|
92
|
-
// result.checkoutUrl = "https://pancake.waffo.ai/store/{slug}/checkout/{sessionId}#token={JWT}"
|
|
93
115
|
|
|
94
|
-
//
|
|
116
|
+
// result.checkoutUrl = "https://pancake.waffo.ai/store/{slug}/checkout/{sessionId}#token={JWT}"
|
|
95
117
|
window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
|
|
96
118
|
```
|
|
97
119
|
|
|
@@ -108,7 +130,16 @@ const result = await client.checkout.anonymous.create({
|
|
|
108
130
|
productType: "onetime",
|
|
109
131
|
currency: "USD",
|
|
110
132
|
});
|
|
111
|
-
|
|
133
|
+
|
|
134
|
+
// Also supports priceSnapshot and withTrial
|
|
135
|
+
const result = await client.checkout.anonymous.create({
|
|
136
|
+
storeId: "STO_xxx",
|
|
137
|
+
productId: "PROD_xxx",
|
|
138
|
+
productType: "subscription",
|
|
139
|
+
currency: "USD",
|
|
140
|
+
priceSnapshot: { amount: "4.99", taxCategory: "saas" },
|
|
141
|
+
withTrial: false, // skip trial for this session
|
|
142
|
+
});
|
|
112
143
|
|
|
113
144
|
window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
|
|
114
145
|
```
|
|
@@ -195,6 +226,57 @@ const event = client.webhooks.verify(rawBody, sig, { environment: "prod" });
|
|
|
195
226
|
|
|
196
227
|
See [Webhook Guide](docs/webhook-guide.md) for event types, dual-environment key architecture, key resolution chain, retry mechanism, and best practices.
|
|
197
228
|
|
|
229
|
+
## Buyer Self-Service
|
|
230
|
+
|
|
231
|
+
Beyond checkout, you can let buyers manage their own orders and subscriptions — for example, embedding a "Cancel Subscription" or "Request Refund" button in your site.
|
|
232
|
+
|
|
233
|
+
Issue a session token, then use `client.buyer(token)` to get a session with self-service methods:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
// Your backend — issue a session token for the buyer
|
|
237
|
+
const { token } = await client.auth.issueSessionToken({
|
|
238
|
+
storeId: "STO_xxx",
|
|
239
|
+
buyerIdentity: req.user.email,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Create a buyer session
|
|
243
|
+
const buyer = client.buyer(token);
|
|
244
|
+
|
|
245
|
+
// Cancel a subscription
|
|
246
|
+
const { orderId, status } = await buyer.cancelSubscription({ orderId: "ORD_xxx" });
|
|
247
|
+
// status: "canceling" (active) or "canceled" (pending)
|
|
248
|
+
|
|
249
|
+
// Reactivate a canceled subscription
|
|
250
|
+
await buyer.reactivateSubscription({ orderId: "ORD_xxx" });
|
|
251
|
+
|
|
252
|
+
// Cancel a one-time order (while payment is pending)
|
|
253
|
+
await buyer.cancelOnetimeOrder({ orderId: "ORD_yyy" });
|
|
254
|
+
|
|
255
|
+
// Submit a refund request
|
|
256
|
+
const { ticket } = await buyer.createRefundTicket({
|
|
257
|
+
paymentId: "PAY_xxx",
|
|
258
|
+
reason: "Product not as described",
|
|
259
|
+
requestedAmount: { amount: "29.00", currency: "USD" },
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Resubmit a rejected refund ticket
|
|
263
|
+
await buyer.resubmitRefundTicket({
|
|
264
|
+
ticketId: "TKT_xxx",
|
|
265
|
+
paymentId: "PAY_xxx",
|
|
266
|
+
reason: "Updated reason with more detail",
|
|
267
|
+
requestedAmount: { amount: "29.00", currency: "USD" },
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Query the buyer's own orders via GraphQL
|
|
271
|
+
const result = await buyer.graphql.query({
|
|
272
|
+
query: `query { orders { id status createdAt } }`,
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The token is scoped to the specified store and buyer identity — buyers can only access their own data. Token TTL is 5 minutes and auto-refreshes on each API call.
|
|
277
|
+
|
|
278
|
+
> **Note**: This uses the same `buyerIdentity` as `checkout.authenticated.create()`. Orders placed via authenticated checkout are automatically tied to this identity, so the buyer can manage them later with a token issued here.
|
|
279
|
+
|
|
198
280
|
## GraphQL — Typed Queries
|
|
199
281
|
|
|
200
282
|
```typescript
|
|
@@ -361,8 +443,10 @@ try {
|
|
|
361
443
|
| `client.checkout.authenticated` | `create()` | Authenticated checkout (recommended) |
|
|
362
444
|
| `client.checkout.anonymous` | `create()` | Anonymous checkout |
|
|
363
445
|
| `client.checkout` | `createSession()` | Low-level checkout session |
|
|
446
|
+
| `client.buyer(token)` | `cancelSubscription()` `cancelOnetimeOrder()` `reactivateSubscription()` `createRefundTicket()` `resubmitRefundTicket()` | Buyer self-service |
|
|
447
|
+
| `client.buyer(token).graphql` | `query<T>()` | Buyer-scoped GraphQL queries |
|
|
364
448
|
| `client.webhooks` | `verify<T>()` | Webhook signature verification |
|
|
365
|
-
| `client.graphql` | `query<T>()` |
|
|
449
|
+
| `client.graphql` | `query<T>()` | Merchant GraphQL queries |
|
|
366
450
|
| `client.auth` | `issueSessionToken()` | Issue a buyer session token (JWT) |
|
|
367
451
|
| `client.stores` | `create()` `update()` `delete()` | Store management |
|
|
368
452
|
| `client.storeMerchants` | `add()` `remove()` `updateRole()` | Store members (coming soon) |
|
|
@@ -430,7 +514,8 @@ npm run build # tsup → ESM + CJS + DTS
|
|
|
430
514
|
src/
|
|
431
515
|
├── index.ts # Unified export entry
|
|
432
516
|
├── client.ts # WaffoPancake main class
|
|
433
|
-
├── http-client.ts # HTTP client (auto-signing + idempotency)
|
|
517
|
+
├── http-client.ts # HTTP client (API Key, auto-signing + idempotency)
|
|
518
|
+
├── buyer-http-client.ts # HTTP client (Bearer token, buyer self-service)
|
|
434
519
|
├── signing.ts # RSA-SHA256 request signing
|
|
435
520
|
├── errors.ts # WaffoPancakeError
|
|
436
521
|
├── webhooks.ts # Webhook verification (embedded keys)
|
|
@@ -443,6 +528,7 @@ src/
|
|
|
443
528
|
├── onetime-products.ts
|
|
444
529
|
├── subscription-products.ts
|
|
445
530
|
├── subscription-product-groups.ts
|
|
531
|
+
├── buyer.ts
|
|
446
532
|
├── orders.ts
|
|
447
533
|
├── checkout.ts
|
|
448
534
|
├── checkout-anonymous.ts
|