@waffo/pancake-ts 0.3.0 → 0.3.2

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.
@@ -438,12 +438,12 @@ const counts = await client.graphql.query({
438
438
 
439
439
  ## Filter Types
440
440
 
441
- | Filter Type | Operations | Example Fields |
442
- |-------------|------------|----------------|
443
- | `StringFilter` | `eq`, `ne`, `contains`, `startsWith`, `endsWith`, `in` | `status`, `name`, `email`, `currency` |
444
- | `DateTimeFilter` | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `createdAt`, `updatedAt`, `expiresAt` |
445
- | `IntFilter` | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `amount`, `totalAmount` |
446
- | `BooleanFilter` | `eq` | `prodEnabled`, `testMode` |
441
+ | Filter Type | Operations | Example Fields |
442
+ | ---------------- | ------------------------------------------------------ | ------------------------------------- |
443
+ | `StringFilter` | `eq`, `ne`, `contains`, `startsWith`, `endsWith`, `in` | `status`, `name`, `email`, `currency` |
444
+ | `DateTimeFilter` | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `createdAt`, `updatedAt`, `expiresAt` |
445
+ | `IntFilter` | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `amount`, `totalAmount` |
446
+ | `BooleanFilter` | `eq` | `prodEnabled`, `testMode` |
447
447
 
448
448
  > To see which filter fields are available for a specific entity, use introspection:
449
449
  > `__type(name: "OnetimeOrderFilter") { fields { name type { name } } }`
@@ -456,12 +456,12 @@ Analytics queries provide aggregated statistics, trends, and insights. All analy
456
456
 
457
457
  ### AnalyticsFilterInput
458
458
 
459
- | Field | Type | Required | Description |
460
- |-------|------|----------|-------------|
461
- | `filter.timeRange.startDate` | `String` | Yes | Start time (ISO 8601) |
462
- | `filter.timeRange.endDate` | `String` | Yes | End time (ISO 8601) |
463
- | `filter.currency` | `String` | No | Currency filter (ISO 4217) |
464
- | `filter.status` | `String` | No | Status filter |
459
+ | Field | Type | Required | Description |
460
+ | ---------------------------- | -------- | -------- | -------------------------- |
461
+ | `filter.timeRange.startDate` | `String` | Yes | Start time (ISO 8601) |
462
+ | `filter.timeRange.endDate` | `String` | Yes | End time (ISO 8601) |
463
+ | `filter.currency` | `String` | No | Currency filter (ISO 4217) |
464
+ | `filter.status` | `String` | No | Status filter |
465
465
 
466
466
  ### TimePeriodGranularity
467
467
 
@@ -29,10 +29,7 @@ import { verifyWebhook, WebhookEventType } from "@waffo/pancake-ts";
29
29
  // IMPORTANT: Use raw body — parsed JSON will break signature verification
30
30
  app.post("/webhooks", express.raw({ type: "application/json" }), (req, res) => {
31
31
  try {
32
- const event = verifyWebhook(
33
- req.body.toString("utf-8"),
34
- req.headers["x-waffo-signature"] as string,
35
- );
32
+ const event = verifyWebhook(req.body.toString("utf-8"), req.headers["x-waffo-signature"] as string);
36
33
 
37
34
  // Respond immediately, process asynchronously
38
35
  res.status(200).send("OK");
@@ -92,20 +89,20 @@ const event = verifyWebhook(body, sig, { toleranceMs: 600000 });
92
89
 
93
90
  ## Parameters
94
91
 
95
- | Parameter | Type | Description |
96
- |-----------|------|-------------|
97
- | `payload` | `string` | Raw request body string (must be unparsed) |
92
+ | Parameter | Type | Description |
93
+ | ----------------- | ----------------------------- | ------------------------------------------------------------------------- |
94
+ | `payload` | `string` | Raw request body string (must be unparsed) |
98
95
  | `signatureHeader` | `string \| undefined \| null` | `X-Waffo-Signature` header value (format: `t=<timestamp>,v1=<signature>`) |
99
- | `options` | `VerifyWebhookOptions` | Optional configuration |
96
+ | `options` | `VerifyWebhookOptions` | Optional configuration |
100
97
 
101
98
  ### `VerifyWebhookOptions`
102
99
 
103
- | Field | Type | Default | Description |
104
- |-------|------|---------|-------------|
105
- | `environment` | `"test" \| "prod"` | auto-detect | Which environment's key to resolve. When omitted, tries prod first, then test. Ignored when `publicKey` is set. |
106
- | `toleranceMs` | `number` | `300000` (5 min) | Timestamp tolerance in ms. Set to `0` to skip timestamp check |
107
- | `publicKey` | `string` | — | Per-call public key override (highest priority, skips all resolution) |
108
- | `publicKeys` | `string \| { test?, prod? }` | — | Config-level key(s) for the resolution chain. Typically injected automatically by `client.webhooks.verify()` |
100
+ | Field | Type | Default | Description |
101
+ | ------------- | ---------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------- |
102
+ | `environment` | `"test" \| "prod"` | auto-detect | Which environment's key to resolve. When omitted, tries prod first, then test. Ignored when `publicKey` is set. |
103
+ | `toleranceMs` | `number` | `300000` (5 min) | Timestamp tolerance in ms. Set to `0` to skip timestamp check |
104
+ | `publicKey` | `string` | — | Per-call public key override (highest priority, skips all resolution) |
105
+ | `publicKeys` | `string \| { test?, prod? }` | — | Config-level key(s) for the resolution chain. Typically injected automatically by `client.webhooks.verify()` |
109
106
 
110
107
  ## Dual-Environment Public Key Architecture
111
108
 
@@ -233,10 +230,10 @@ const client = new WaffoPancake({
233
230
 
234
231
  When no config key is found, the SDK reads from process environment variables:
235
232
 
236
- | Environment | Variable Name |
237
- |-------------|---------------|
238
- | test | `WAFFO_WEBHOOK_TEST_PUBLIC_KEY` |
239
- | prod | `WAFFO_WEBHOOK_PROD_PUBLIC_KEY` |
233
+ | Environment | Variable Name |
234
+ | ----------- | ------------------------------- |
235
+ | test | `WAFFO_WEBHOOK_TEST_PUBLIC_KEY` |
236
+ | prod | `WAFFO_WEBHOOK_PROD_PUBLIC_KEY` |
240
237
 
241
238
  > **When built-in hardcoded keys become invalid (e.g., Waffo rotates platform keys, or you migrate to a self-hosted deployment), the minimum-effort fix is to set environment variables. No code changes, no redeployment of application code — just update the env vars in your hosting platform (Vercel, AWS, Docker, etc.) and the SDK picks them up automatically on the next request.**
242
239
 
@@ -271,8 +268,8 @@ client.webhooks.verify(body, sig, { environment: "prod" });
271
268
 
272
269
  A single env var for both environments:
273
270
 
274
- | Variable Name | Used for |
275
- |---------------|----------|
271
+ | Variable Name | Used for |
272
+ | -------------------------- | ------------------ |
276
273
  | `WAFFO_WEBHOOK_PUBLIC_KEY` | Both test and prod |
277
274
 
278
275
  ```bash
@@ -292,27 +289,27 @@ const event = verifyWebhook(body, sig);
292
289
 
293
290
  ### Resolution Examples
294
291
 
295
- | Scenario | Config | Env Var | Result (prod) |
296
- |----------|--------|---------|----------------|
297
- | Default (no config) | — | — | Built-in prod key |
298
- | Shared config key | `webhookPublicKey: "KEY_A"` | — | `KEY_A` |
299
- | Per-env config | `webhookPublicKey: { prod: "KEY_B" }` | — | `KEY_B` |
300
- | Env var only | — | `WAFFO_WEBHOOK_PROD_PUBLIC_KEY=KEY_C` | `KEY_C` |
301
- | Config + env var | `webhookPublicKey: { prod: "KEY_D" }` | `WAFFO_WEBHOOK_PROD_PUBLIC_KEY=KEY_E` | `KEY_D` (config wins) |
302
- | Per-call override | `webhookPublicKey: { prod: "KEY_F" }` | — | `options.publicKey` wins |
292
+ | Scenario | Config | Env Var | Result (prod) |
293
+ | ------------------- | ------------------------------------- | ------------------------------------- | ------------------------ |
294
+ | Default (no config) | — | — | Built-in prod key |
295
+ | Shared config key | `webhookPublicKey: "KEY_A"` | — | `KEY_A` |
296
+ | Per-env config | `webhookPublicKey: { prod: "KEY_B" }` | — | `KEY_B` |
297
+ | Env var only | — | `WAFFO_WEBHOOK_PROD_PUBLIC_KEY=KEY_C` | `KEY_C` |
298
+ | Config + env var | `webhookPublicKey: { prod: "KEY_D" }` | `WAFFO_WEBHOOK_PROD_PUBLIC_KEY=KEY_E` | `KEY_D` (config wins) |
299
+ | Per-call override | `webhookPublicKey: { prod: "KEY_F" }` | — | `options.publicKey` wins |
303
300
 
304
301
  ## Public Key Formats
305
302
 
306
303
  All public key inputs at every level (config, env vars, per-call) are automatically **normalized** by the SDK. The following formats are accepted:
307
304
 
308
- | Format | Example | Notes |
309
- |--------|---------|-------|
310
- | Standard SPKI PEM | `-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----` | Recommended |
311
- | PKCS#1 PEM | `-----BEGIN RSA PUBLIC KEY-----\n...` | Also accepted |
312
- | Literal `\n` (env vars) | `"-----BEGIN PUBLIC KEY-----\\nMIIB..."` | Common in `.env` files and CI secrets |
313
- | Windows line endings | `\r\n` | Converted to `\n` |
314
- | Raw base64 (no headers) | `MIIBIjANBgkqhki...` | Wrapped with SPKI headers automatically |
315
- | Single-line base64 | Header + all base64 on one line + footer | Re-wrapped to 64-char lines |
305
+ | Format | Example | Notes |
306
+ | ----------------------- | ----------------------------------------------------------- | --------------------------------------- |
307
+ | Standard SPKI PEM | `-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----` | Recommended |
308
+ | PKCS#1 PEM | `-----BEGIN RSA PUBLIC KEY-----\n...` | Also accepted |
309
+ | Literal `\n` (env vars) | `"-----BEGIN PUBLIC KEY-----\\nMIIB..."` | Common in `.env` files and CI secrets |
310
+ | Windows line endings | `\r\n` | Converted to `\n` |
311
+ | Raw base64 (no headers) | `MIIBIjANBgkqhki...` | Wrapped with SPKI headers automatically |
312
+ | Single-line base64 | Header + all base64 on one line + footer | Re-wrapped to 64-char lines |
316
313
 
317
314
  Normalization is applied **on every call** — there is no eager validation at construction time (unlike `privateKey`). Invalid keys produce a descriptive error at verification time.
318
315
 
@@ -325,9 +322,9 @@ Best for simple setups where you don't need the SDK client. Uses env vars and bu
325
322
  ```typescript
326
323
  import { verifyWebhook } from "@waffo/pancake-ts";
327
324
 
328
- const event = verifyWebhook(body, sig); // built-in keys
329
- const event = verifyWebhook(body, sig, { environment: "prod" }); // explicit env
330
- const event = verifyWebhook(body, sig, { publicKey: customKey }); // per-call key
325
+ const event = verifyWebhook(body, sig); // built-in keys
326
+ const event = verifyWebhook(body, sig, { environment: "prod" }); // explicit env
327
+ const event = verifyWebhook(body, sig, { publicKey: customKey }); // per-call key
331
328
  ```
332
329
 
333
330
  ### Client Instance Method — `client.webhooks.verify()`
@@ -346,9 +343,9 @@ const client = new WaffoPancake({
346
343
  },
347
344
  });
348
345
 
349
- const event = client.webhooks.verify(body, sig); // auto-detect with config keys
346
+ const event = client.webhooks.verify(body, sig); // auto-detect with config keys
350
347
  const event = client.webhooks.verify(body, sig, { environment: "test" }); // explicit env
351
- const event = client.webhooks.verify(body, sig, { publicKey: oneOff }); // per-call override
348
+ const event = client.webhooks.verify(body, sig, { publicKey: oneOff }); // per-call override
352
349
  ```
353
350
 
354
351
  Both APIs share the same underlying verification logic and resolution chain.
@@ -357,41 +354,41 @@ Both APIs share the same underlying verification logic and resolution chain.
357
354
 
358
355
  ### `WebhookEvent<T>`
359
356
 
360
- | Field | Type | Description |
361
- |-------|------|-------------|
362
- | `id` | `string` | Delivery record unique ID (UUID) — use for idempotent deduplication |
363
- | `timestamp` | `string` | Event timestamp (ISO 8601 UTC) |
364
- | `eventType` | `string` | Event type (e.g. `"order.completed"`) |
365
- | `eventId` | `string` | Business event ID (e.g. payment ID) |
366
- | `storeId` | `string` | Store ID the event belongs to |
367
- | `mode` | `string` | Environment (`"test"` or `"prod"`) |
368
- | `data` | `T` | Event data (defaults to `WebhookEventData`) |
357
+ | Field | Type | Description |
358
+ | ----------- | -------- | ------------------------------------------------------------------- |
359
+ | `id` | `string` | Delivery record unique ID (UUID) — use for idempotent deduplication |
360
+ | `timestamp` | `string` | Event timestamp (ISO 8601 UTC) |
361
+ | `eventType` | `string` | Event type (e.g. `"order.completed"`) |
362
+ | `eventId` | `string` | Business event ID (e.g. payment ID) |
363
+ | `storeId` | `string` | Store ID the event belongs to |
364
+ | `mode` | `string` | Environment (`"test"` or `"prod"`) |
365
+ | `data` | `T` | Event data (defaults to `WebhookEventData`) |
369
366
 
370
367
  ### `WebhookEventData`
371
368
 
372
- | Field | Type | Description |
373
- |-------|------|-------------|
374
- | `orderId` | `string` | Associated order ID |
375
- | `buyerEmail` | `string` | Buyer email address |
376
- | `currency` | `string` | Currency code (ISO 4217) |
377
- | `amount` | `string` | Amount in display format (e.g., `"29.00"` for $29.00 USD, `"4500"` for ¥4500 JPY) |
378
- | `taxAmount` | `string` | Tax amount in display format (e.g., `"2.90"`) |
379
- | `productName` | `string` | Product name |
369
+ | Field | Type | Description |
370
+ | ------------- | -------- | --------------------------------------------------------------------------------- |
371
+ | `orderId` | `string` | Associated order ID |
372
+ | `buyerEmail` | `string` | Buyer email address |
373
+ | `currency` | `string` | Currency code (ISO 4217) |
374
+ | `amount` | `string` | Amount in display format (e.g., `"29.00"` for $29.00 USD, `"4500"` for ¥4500 JPY) |
375
+ | `taxAmount` | `string` | Tax amount in display format (e.g., `"2.90"`) |
376
+ | `productName` | `string` | Product name |
380
377
 
381
378
  ## Event Types
382
379
 
383
- | Enum Value | String | Trigger |
384
- |------------|--------|---------|
385
- | `OrderCompleted` | `order.completed` | One-time order first payment succeeded |
386
- | `SubscriptionActivated` | `subscription.activated` | New subscription activated |
387
- | `SubscriptionPaymentSucceeded` | `subscription.payment_succeeded` | Subscription renewal payment succeeded |
388
- | `SubscriptionCanceling` | `subscription.canceling` | Buyer initiated cancellation (expires at end of billing period) |
389
- | `SubscriptionUncanceled` | `subscription.uncanceled` | Buyer withdrew cancellation request |
390
- | `SubscriptionUpdated` | `subscription.updated` | Subscription product changed (upgrade/downgrade) |
391
- | `SubscriptionCanceled` | `subscription.canceled` | Subscription fully terminated |
392
- | `SubscriptionPastDue` | `subscription.past_due` | Renewal payment failed (past due) |
393
- | `RefundSucceeded` | `refund.succeeded` | Refund completed successfully |
394
- | `RefundFailed` | `refund.failed` | Refund failed |
380
+ | Enum Value | String | Trigger |
381
+ | ------------------------------ | -------------------------------- | --------------------------------------------------------------- |
382
+ | `OrderCompleted` | `order.completed` | One-time order first payment succeeded |
383
+ | `SubscriptionActivated` | `subscription.activated` | New subscription activated |
384
+ | `SubscriptionPaymentSucceeded` | `subscription.payment_succeeded` | Subscription renewal payment succeeded |
385
+ | `SubscriptionCanceling` | `subscription.canceling` | Buyer initiated cancellation (expires at end of billing period) |
386
+ | `SubscriptionUncanceled` | `subscription.uncanceled` | Buyer withdrew cancellation request |
387
+ | `SubscriptionUpdated` | `subscription.updated` | Subscription product changed (upgrade/downgrade) |
388
+ | `SubscriptionCanceled` | `subscription.canceled` | Subscription fully terminated |
389
+ | `SubscriptionPastDue` | `subscription.past_due` | Renewal payment failed (past due) |
390
+ | `RefundSucceeded` | `refund.succeeded` | Refund completed successfully |
391
+ | `RefundFailed` | `refund.failed` | Refund failed |
395
392
 
396
393
  ## Key Rotation & Migration
397
394
 
@@ -423,23 +420,23 @@ When rotating keys, the old key remains valid for a transition period:
423
420
 
424
421
  ### Choosing the right level
425
422
 
426
- | Situation | Recommended Level | Why |
427
- |-----------|-------------------|-----|
428
- | Standard Waffo Pancake user | Level 6 (default) | Built-in keys just work, zero config |
429
- | Built-in keys expired | Level 4 (env var) | No code changes, set env var and done |
430
- | Self-hosted deployment | Level 2/3 (config) | Custom keys are part of your app config |
431
- | Testing a new key | Level 1 (per-call) | One-off override, no permanent change |
432
- | CI/CD with different keys | Level 4 (env var) | Each environment sets its own env var |
423
+ | Situation | Recommended Level | Why |
424
+ | --------------------------- | ------------------ | --------------------------------------- |
425
+ | Standard Waffo Pancake user | Level 6 (default) | Built-in keys just work, zero config |
426
+ | Built-in keys expired | Level 4 (env var) | No code changes, set env var and done |
427
+ | Self-hosted deployment | Level 2/3 (config) | Custom keys are part of your app config |
428
+ | Testing a new key | Level 1 (per-call) | One-off override, no permanent change |
429
+ | CI/CD with different keys | Level 4 (env var) | Each environment sets its own env var |
433
430
 
434
431
  ## Retry Mechanism
435
432
 
436
433
  When delivery fails (non-2xx response or timeout), the system automatically retries using **exponential backoff** (managed by the underlying message queue). Default: 3 retries.
437
434
 
438
- | Delivery Status | Description |
439
- |----------------|-------------|
440
- | `pending` | Created, waiting for delivery or retrying |
441
- | `success` | Delivery successful (server returned 2xx) |
442
- | `failed` | All retries exhausted, final failure |
435
+ | Delivery Status | Description |
436
+ | --------------- | ----------------------------------------- |
437
+ | `pending` | Created, waiting for delivery or retrying |
438
+ | `success` | Delivery successful (server returned 2xx) |
439
+ | `failed` | All retries exhausted, final failure |
443
440
 
444
441
  You can view each delivery's status, HTTP status code, and response content in the dashboard's Webhook logs.
445
442
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waffo/pancake-ts",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "TypeScript SDK for Waffo Pancake API (Merchant API Key authentication)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -30,13 +30,16 @@
30
30
  "test": "vitest run",
31
31
  "test:watch": "vitest",
32
32
  "test:coverage": "vitest run --coverage",
33
- "prepublishOnly": "npm run lint && npm run test && npm run build"
33
+ "prepublishOnly": "npm run lint && npm run test && npm run build",
34
+ "prepare": "husky"
34
35
  },
35
36
  "engines": {
36
37
  "node": ">=20.0.0"
37
38
  },
38
39
  "license": "MIT",
39
40
  "devDependencies": {
41
+ "@commitlint/cli": "^20.5.0",
42
+ "@commitlint/config-conventional": "^20.5.0",
40
43
  "@types/node": "^25.3.5",
41
44
  "@typescript-eslint/eslint-plugin": "^8.20.0",
42
45
  "@typescript-eslint/parser": "^8.20.0",
@@ -45,9 +48,19 @@
45
48
  "eslint-import-resolver-typescript": "^3.7.0",
46
49
  "eslint-plugin-import": "^2.31.0",
47
50
  "eslint-plugin-jsdoc": "^50.6.3",
51
+ "husky": "^9.1.7",
52
+ "lint-staged": "^16.4.0",
53
+ "prettier": "^3.8.1",
48
54
  "tsup": "^8.5.1",
49
55
  "typescript": "^5.4.0",
50
56
  "typescript-eslint": "^8.20.0",
51
57
  "vitest": "^4.0.16"
58
+ },
59
+ "lint-staged": {
60
+ "*.{ts,tsx}": [
61
+ "eslint --fix",
62
+ "prettier --write"
63
+ ],
64
+ "*.{json,md,css}": "prettier --write"
52
65
  }
53
66
  }