@waffo/pancake-ts 0.1.5 → 0.1.7

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/dist/index.d.ts CHANGED
@@ -7,8 +7,16 @@ interface WaffoPancakeConfig {
7
7
  baseUrl?: string;
8
8
  /** Custom fetch implementation (default: global fetch) */
9
9
  fetch?: typeof fetch;
10
- /** Custom RSA public key (PEM) for webhook signature verification. When set, overrides the built-in Waffo public keys. */
11
- webhookPublicKey?: string;
10
+ /**
11
+ * Custom RSA public key(s) for webhook signature verification.
12
+ *
13
+ * - `string` — single key used for both test and prod environments
14
+ * - `{ test?, prod? }` — per-environment keys
15
+ *
16
+ * Resolution order per environment: config key → env var → built-in key.
17
+ * @see {@link VerifyWebhookOptions} for per-call overrides
18
+ */
19
+ webhookPublicKey?: WebhookPublicKeys;
12
20
  }
13
21
  /**
14
22
  * Single error object within the `errors` array.
@@ -711,6 +719,16 @@ interface WebhookEvent<T = WebhookEventData> {
711
719
  /** Event data */
712
720
  data: T;
713
721
  }
722
+ /**
723
+ * Webhook public key configuration.
724
+ *
725
+ * - `string` — single key used for both test and prod environments
726
+ * - `{ test?, prod? }` — per-environment keys
727
+ */
728
+ type WebhookPublicKeys = string | {
729
+ test?: string;
730
+ prod?: string;
731
+ };
714
732
  /** Options for {@link verifyWebhook}. */
715
733
  interface VerifyWebhookOptions {
716
734
  /**
@@ -726,10 +744,23 @@ interface VerifyWebhookOptions {
726
744
  */
727
745
  toleranceMs?: number;
728
746
  /**
729
- * Custom RSA public key (PEM) for signature verification.
730
- * When provided, overrides both built-in keys and the `environment` option.
747
+ * Per-call public key override (highest priority).
748
+ * When provided, skips all other key resolution (config, env vars, built-in).
731
749
  */
732
750
  publicKey?: string;
751
+ /**
752
+ * Config-level public key(s) for the resolution chain.
753
+ * When using `client.webhooks.verify()`, this is set automatically from `WaffoPancakeConfig.webhookPublicKey`.
754
+ * When using the standalone `verifyWebhook()`, you can pass this directly for config-level key injection.
755
+ *
756
+ * Resolution order per environment:
757
+ * 1. `publicKey` (per-call override)
758
+ * 2. `publicKeys[env]` or `publicKeys` (config)
759
+ * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` (env var)
760
+ * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` (env var)
761
+ * 5. Built-in hardcoded key
762
+ */
763
+ publicKeys?: WebhookPublicKeys;
733
764
  }
734
765
 
735
766
  /**
@@ -1134,16 +1165,25 @@ declare class SubscriptionProductsResource {
1134
1165
  }>;
1135
1166
  }
1136
1167
 
1137
- /** Webhook signature verification resource. */
1168
+ /**
1169
+ * Webhook signature verification resource.
1170
+ *
1171
+ * Unlike other resources, this does not use HttpClient — webhook verification
1172
+ * is a local cryptographic operation that does not require API calls.
1173
+ */
1138
1174
  declare class WebhooksResource {
1139
- private readonly publicKey;
1140
- /** @param publicKey - Optional custom RSA public key (PEM or raw base64) */
1141
- constructor(publicKey: string | undefined);
1175
+ private readonly publicKeys;
1176
+ /** @param publicKeys - Optional config-level public key(s) from WaffoPancakeConfig */
1177
+ constructor(publicKeys: WebhookPublicKeys | undefined);
1142
1178
  /**
1143
1179
  * Verify and parse an incoming webhook event.
1144
1180
  *
1145
- * When the client was created with a `webhookPublicKey`, that key is used
1146
- * automatically. You can still override per-call via `options.publicKey`.
1181
+ * Key resolution order:
1182
+ * 1. `options.publicKey` per-call override (highest priority)
1183
+ * 2. `config.webhookPublicKey[env]` or `config.webhookPublicKey` (string)
1184
+ * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable
1185
+ * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable
1186
+ * 5. Built-in hardcoded key
1147
1187
  *
1148
1188
  * @param payload - Raw request body string (must be unparsed)
1149
1189
  * @param signatureHeader - Value of the `X-Waffo-Signature` header
@@ -1155,8 +1195,12 @@ declare class WebhooksResource {
1155
1195
  * const event = client.webhooks.verify(rawBody, signatureHeader);
1156
1196
  *
1157
1197
  * @example
1158
- * // Override tolerance per call
1159
- * const event = client.webhooks.verify(rawBody, sig, { toleranceMs: 0 });
1198
+ * // Specify environment
1199
+ * const event = client.webhooks.verify(rawBody, sig, { environment: "test" });
1200
+ *
1201
+ * @example
1202
+ * // Per-call key override
1203
+ * const event = client.webhooks.verify(rawBody, sig, { publicKey: oneOffKey });
1160
1204
  */
1161
1205
  verify<T = Record<string, unknown>>(payload: string, signatureHeader: string | undefined | null, options?: VerifyWebhookOptions): WebhookEvent<T>;
1162
1206
  }
@@ -1200,11 +1244,14 @@ declare class WebhooksResource {
1200
1244
  * });
1201
1245
  *
1202
1246
  * @example
1203
- * // Use a custom public key for webhook verification
1247
+ * // Per-environment webhook public keys
1204
1248
  * const client = new WaffoPancake({
1205
1249
  * merchantId: "...",
1206
1250
  * privateKey: "...",
1207
- * webhookPublicKey: myCustomPublicKeyPem,
1251
+ * webhookPublicKey: {
1252
+ * test: process.env.WAFFO_TEST_PUB_KEY!,
1253
+ * prod: process.env.WAFFO_PROD_PUB_KEY!,
1254
+ * },
1208
1255
  * });
1209
1256
  * const event = client.webhooks.verify(rawBody, signatureHeader);
1210
1257
  */
@@ -1245,8 +1292,12 @@ declare class WaffoPancakeError extends Error {
1245
1292
  /**
1246
1293
  * Verify and parse an incoming Waffo Pancake webhook event.
1247
1294
  *
1248
- * Uses built-in Waffo public keys (RSA-SHA256) for signature verification.
1249
- * Test and production environments use different key pairs; both are embedded in the SDK.
1295
+ * Public key resolution (per environment):
1296
+ * 1. `options.publicKey` per-call override (highest priority, skips all other resolution)
1297
+ * 2. `options.publicKeys[env]` or `options.publicKeys` (string) — config-level
1298
+ * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable
1299
+ * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable
1300
+ * 5. Built-in hardcoded key
1250
1301
  *
1251
1302
  * Behavior:
1252
1303
  * - Parses the `X-Waffo-Signature` header (`t=<timestamp>,v1=<base64sig>`)
@@ -1295,4 +1346,4 @@ declare class WaffoPancakeError extends Error {
1295
1346
  */
1296
1347
  declare function verifyWebhook<T = Record<string, unknown>>(payload: string, signatureHeader: string | undefined | null, options?: VerifyWebhookOptions): WebhookEvent<T>;
1297
1348
 
1298
- export { type AddMerchantParams, type AddMerchantResult, type ApiError, type ApiErrorResponse, type ApiResponse, type ApiSuccessResponse, type BillingDetail, BillingPeriod, type CancelSubscriptionParams, type CancelSubscriptionResult, CheckoutSessionProductType, type CheckoutSessionResult, type CheckoutSettings, type CheckoutThemeSettings, type CreateCheckoutSessionParams, type CreateOnetimeProductParams, type CreateStoreParams, type CreateSubscriptionProductGroupParams, type CreateSubscriptionProductParams, type DeleteStoreParams, type DeleteSubscriptionProductGroupParams, EntityStatus, Environment, ErrorLayer, type GraphQLParams, type GraphQLResponse, type GroupRules, type IssueSessionTokenParams, type MediaItem, MediaType, type NotificationSettings, OnetimeOrderStatus, type OnetimeProductDetail, PaymentStatus, type PriceInfo, type Prices, ProductVersionStatus, type PublishOnetimeProductParams, type PublishSubscriptionProductGroupParams, type PublishSubscriptionProductParams, RefundStatus, RefundTicketStatus, type RemoveMerchantParams, type RemoveMerchantResult, type SessionToken, type Store, StoreRole, SubscriptionOrderStatus, type SubscriptionProductDetail, type SubscriptionProductGroup, TaxCategory, type UpdateOnetimeProductParams, type UpdateOnetimeStatusParams, type UpdateRoleParams, type UpdateRoleResult, type UpdateStoreParams, type UpdateSubscriptionProductGroupParams, type UpdateSubscriptionProductParams, type UpdateSubscriptionStatusParams, type VerifyWebhookOptions, WaffoPancake, type WaffoPancakeConfig, WaffoPancakeError, type WebhookEvent, type WebhookEventData, WebhookEventType, type WebhookSettings, verifyWebhook };
1349
+ export { type AddMerchantParams, type AddMerchantResult, type ApiError, type ApiErrorResponse, type ApiResponse, type ApiSuccessResponse, type BillingDetail, BillingPeriod, type CancelSubscriptionParams, type CancelSubscriptionResult, CheckoutSessionProductType, type CheckoutSessionResult, type CheckoutSettings, type CheckoutThemeSettings, type CreateCheckoutSessionParams, type CreateOnetimeProductParams, type CreateStoreParams, type CreateSubscriptionProductGroupParams, type CreateSubscriptionProductParams, type DeleteStoreParams, type DeleteSubscriptionProductGroupParams, EntityStatus, Environment, ErrorLayer, type GraphQLParams, type GraphQLResponse, type GroupRules, type IssueSessionTokenParams, type MediaItem, MediaType, type NotificationSettings, OnetimeOrderStatus, type OnetimeProductDetail, PaymentStatus, type PriceInfo, type Prices, ProductVersionStatus, type PublishOnetimeProductParams, type PublishSubscriptionProductGroupParams, type PublishSubscriptionProductParams, RefundStatus, RefundTicketStatus, type RemoveMerchantParams, type RemoveMerchantResult, type SessionToken, type Store, StoreRole, SubscriptionOrderStatus, type SubscriptionProductDetail, type SubscriptionProductGroup, TaxCategory, type UpdateOnetimeProductParams, type UpdateOnetimeStatusParams, type UpdateRoleParams, type UpdateRoleResult, type UpdateStoreParams, type UpdateSubscriptionProductGroupParams, type UpdateSubscriptionProductParams, type UpdateSubscriptionStatusParams, type VerifyWebhookOptions, WaffoPancake, type WaffoPancakeConfig, WaffoPancakeError, type WebhookEvent, type WebhookEventData, WebhookEventType, type WebhookPublicKeys, type WebhookSettings, verifyWebhook };
package/dist/index.js CHANGED
@@ -611,6 +611,23 @@ function rsaVerify(signatureInput, v1, publicKey) {
611
611
  verifier.update(signatureInput);
612
612
  return verifier.verify(publicKey, v1, "base64");
613
613
  }
614
+ function resolveKeyForEnv(env, configKeys) {
615
+ if (typeof configKeys === "string") {
616
+ return normalizePublicKey(configKeys);
617
+ }
618
+ if (configKeys?.[env]) {
619
+ return normalizePublicKey(configKeys[env]);
620
+ }
621
+ const envSpecific = env === "test" ? process.env.WAFFO_WEBHOOK_TEST_PUBLIC_KEY : process.env.WAFFO_WEBHOOK_PROD_PUBLIC_KEY;
622
+ if (envSpecific) {
623
+ return normalizePublicKey(envSpecific);
624
+ }
625
+ const generic = process.env.WAFFO_WEBHOOK_PUBLIC_KEY;
626
+ if (generic) {
627
+ return normalizePublicKey(generic);
628
+ }
629
+ return env === "test" ? TEST_PUBLIC_KEY : PROD_PUBLIC_KEY;
630
+ }
614
631
  function verifyWebhook(payload, signatureHeader, options) {
615
632
  if (!signatureHeader) {
616
633
  throw new Error("Missing X-Waffo-Signature header");
@@ -630,27 +647,25 @@ function verifyWebhook(payload, signatureHeader, options) {
630
647
  }
631
648
  }
632
649
  const signatureInput = `${t}.${payload}`;
633
- const customKey = options?.publicKey;
634
- if (customKey) {
635
- const normalizedKey = normalizePublicKey(customKey);
650
+ const directKey = options?.publicKey;
651
+ if (directKey) {
652
+ const normalizedKey = normalizePublicKey(directKey);
636
653
  if (!rsaVerify(signatureInput, v1, normalizedKey)) {
637
654
  throw new Error("Invalid webhook signature (custom key)");
638
655
  }
639
656
  } else {
657
+ const configKeys = options?.publicKeys;
640
658
  const env = options?.environment;
641
- if (env === "test") {
642
- if (!rsaVerify(signatureInput, v1, TEST_PUBLIC_KEY)) {
643
- throw new Error("Invalid webhook signature (test key)");
644
- }
645
- } else if (env === "prod") {
646
- if (!rsaVerify(signatureInput, v1, PROD_PUBLIC_KEY)) {
647
- throw new Error("Invalid webhook signature (prod key)");
659
+ if (env === "test" || env === "prod") {
660
+ const key = resolveKeyForEnv(env, configKeys);
661
+ if (!rsaVerify(signatureInput, v1, key)) {
662
+ throw new Error(`Invalid webhook signature (${env} key)`);
648
663
  }
649
664
  } else {
650
- const prodValid = rsaVerify(signatureInput, v1, PROD_PUBLIC_KEY);
651
- if (!prodValid) {
652
- const testValid = rsaVerify(signatureInput, v1, TEST_PUBLIC_KEY);
653
- if (!testValid) {
665
+ const prodKey = resolveKeyForEnv("prod", configKeys);
666
+ if (!rsaVerify(signatureInput, v1, prodKey)) {
667
+ const testKey = resolveKeyForEnv("test", configKeys);
668
+ if (!rsaVerify(signatureInput, v1, testKey)) {
654
669
  throw new Error("Invalid webhook signature (tried both prod and test keys)");
655
670
  }
656
671
  }
@@ -661,15 +676,19 @@ function verifyWebhook(payload, signatureHeader, options) {
661
676
 
662
677
  // src/resources/webhooks.ts
663
678
  var WebhooksResource = class {
664
- /** @param publicKey - Optional custom RSA public key (PEM or raw base64) */
665
- constructor(publicKey) {
666
- this.publicKey = publicKey;
679
+ /** @param publicKeys - Optional config-level public key(s) from WaffoPancakeConfig */
680
+ constructor(publicKeys) {
681
+ this.publicKeys = publicKeys;
667
682
  }
668
683
  /**
669
684
  * Verify and parse an incoming webhook event.
670
685
  *
671
- * When the client was created with a `webhookPublicKey`, that key is used
672
- * automatically. You can still override per-call via `options.publicKey`.
686
+ * Key resolution order:
687
+ * 1. `options.publicKey` per-call override (highest priority)
688
+ * 2. `config.webhookPublicKey[env]` or `config.webhookPublicKey` (string)
689
+ * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable
690
+ * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable
691
+ * 5. Built-in hardcoded key
673
692
  *
674
693
  * @param payload - Raw request body string (must be unparsed)
675
694
  * @param signatureHeader - Value of the `X-Waffo-Signature` header
@@ -681,13 +700,17 @@ var WebhooksResource = class {
681
700
  * const event = client.webhooks.verify(rawBody, signatureHeader);
682
701
  *
683
702
  * @example
684
- * // Override tolerance per call
685
- * const event = client.webhooks.verify(rawBody, sig, { toleranceMs: 0 });
703
+ * // Specify environment
704
+ * const event = client.webhooks.verify(rawBody, sig, { environment: "test" });
705
+ *
706
+ * @example
707
+ * // Per-call key override
708
+ * const event = client.webhooks.verify(rawBody, sig, { publicKey: oneOffKey });
686
709
  */
687
710
  verify(payload, signatureHeader, options) {
688
711
  const mergedOptions = {
689
712
  ...options,
690
- publicKey: options?.publicKey ?? this.publicKey
713
+ publicKeys: options?.publicKeys ?? this.publicKeys
691
714
  };
692
715
  return verifyWebhook(payload, signatureHeader, mergedOptions);
693
716
  }