@waffo/pancake-ts 0.19.0 → 0.19.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/dist/index.cjs +17 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -4
- package/dist/index.d.ts +18 -4
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/customer-http-client.ts","../src/http-client.ts","../src/signing.ts","../src/resources/internal.ts","../src/validation.ts","../src/resources/auth.ts","../src/resources/checkout-anonymous.ts","../src/resources/checkout-authenticated.ts","../src/resources/checkout.ts","../src/resources/content-safety.ts","../src/resources/customer.ts","../src/resources/graphql.ts","../src/resources/onetime-products.ts","../src/resources/orders.ts","../src/resources/store-merchants.ts","../src/resources/stores.ts","../src/resources/subscription-product-groups.ts","../src/resources/subscription-products.ts","../src/webhooks.ts","../src/resources/webhooks.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["import type { ApiError } from \"./types.js\";\n\n/**\n * Error thrown when the API returns a non-success response.\n *\n * @example\n * try {\n * await client.stores.create({ name: \"My Store\" });\n * } catch (err) {\n * if (err instanceof WaffoPancakeError) {\n * console.log(err.status); // 400\n * console.log(err.errors[0]); // { message: \"...\", layer: \"store\" }\n * }\n * }\n */\nexport class WaffoPancakeError extends Error {\n readonly status: number;\n readonly errors: ApiError[];\n\n constructor(status: number, errors: ApiError[]) {\n const rootCause = errors[0]?.message ?? \"Unknown error\";\n super(rootCause);\n this.name = \"WaffoPancakeError\";\n this.status = status;\n this.errors = errors;\n }\n}\n","import { WaffoPancakeError } from \"./errors.js\";\n\nimport type { Environment, PostResult, WaffoPancakeConfig } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.waffo.ai\";\n\n/**\n * Internal HTTP client for customer-side requests using Bearer token authentication.\n *\n * Unlike {@link HttpClient} which signs requests with RSA-SHA256 (API Key auth),\n * this client attaches a session token as `Authorization: Bearer <token>` and\n * never sends an idempotency key (customer session actions are not protected by\n * gateway idempotency in the current architecture).\n *\n * Session tokens carry no environment of their own, so every request also sends\n * `X-Environment`. The gateway treats a Bearer credential without it as an\n * incomplete JWT header set and answers HTTP 400.\n *\n * Not exported publicly — used internally by {@link CustomerSession}.\n */\nexport class CustomerHttpClient {\n private readonly token: string;\n private readonly environment: `${Environment}`;\n private readonly baseUrl: string;\n private readonly _fetch: typeof fetch;\n\n constructor(token: string, environment: `${Environment}`, config: Pick<WaffoPancakeConfig, \"baseUrl\" | \"fetch\">) {\n this.token = token;\n this.environment = environment;\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Send a Bearer-authenticated POST and return the full envelope plus HTTP status.\n *\n * Sends `Authorization: Bearer <token>` and `X-Environment` — the gateway\n * requires both to accept a session token.\n *\n * Does NOT throw on `errors[]` or non-2xx status — caller inspects the result.\n * Throws {@link WaffoPancakeError} only when the response body is not valid JSON.\n */\n async post<T>(path: string, body: object): Promise<PostResult<T>> {\n const response = await this._fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.token}`,\n \"X-Environment\": this.environment,\n },\n body: JSON.stringify(body),\n });\n\n let envelope: { data: T | null; errors?: PostResult<T>[\"errors\"]; warnings?: PostResult<T>[\"warnings\"] };\n try {\n envelope = (await response.json()) as typeof envelope;\n } catch {\n throw new WaffoPancakeError(response.status, [{ message: `Non-JSON response from ${path}`, layer: \"sdk\" }]);\n }\n return { status: response.status, ...envelope };\n }\n}\n","import { createHash } from \"node:crypto\";\n\nimport { WaffoPancakeError } from \"./errors.js\";\nimport { normalizePrivateKey, signRequest } from \"./signing.js\";\n\nimport type { PostOptions, PostResult, WaffoPancakeConfig } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.waffo.ai\";\n\n/**\n * Internal HTTP client that auto-signs requests.\n *\n * The transport is intentionally thin: one {@link post} method that signs,\n * sends, and parses the {data, errors?, warnings?} envelope. It does NOT\n * unwrap `data`, throw on `errors[]`, or hide `warnings` — those are policy\n * choices that belong to the resource layer. See handbook\n * `coding-standards/code-style-guide/command-layer.md`.\n *\n * The `X-Merchant-Id` header is sent in `MER_{base62}` format as provided\n * by the user. The gateway decodes it to a raw UUID before forwarding.\n *\n * Not exported publicly — used by resource classes via {@link WaffoPancake}.\n */\nexport class HttpClient {\n private readonly merchantId: string;\n private readonly privateKey: string;\n private readonly baseUrl: string;\n private readonly _fetch: typeof fetch;\n\n constructor(config: WaffoPancakeConfig) {\n this.merchantId = config.merchantId;\n this.privateKey = normalizePrivateKey(config.privateKey);\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Send a signed POST and return the full envelope plus HTTP status.\n *\n * Behavior:\n * - Builds RSA-SHA256 signature (`X-Merchant-Id` / `X-Timestamp` / `X-Signature`)\n * - Attaches `X-Idempotency-Key` (deterministic `sha256(merchantId + path + body)`)\n * unless `options.noIdempotency` is set\n * - When `options.idempotencyWindow` is set, a floored timestamp is mixed into the\n * key so identical params produce a new key after the window elapses\n * - Does NOT throw on `errors[]` or non-2xx status — caller inspects the result\n * - Throws {@link WaffoPancakeError} only on transport failures (non-JSON body)\n *\n * @param path - API path (e.g. `/v1/actions/store/create-store`, `/v1/graphql`)\n * @param body - Request body object\n * @param options - Optional settings\n * @returns Parsed envelope with HTTP status\n * @throws {WaffoPancakeError} When the response body is not valid JSON\n */\n async post<T>(path: string, body: object, options?: PostOptions): Promise<PostResult<T>> {\n const bodyStr = JSON.stringify(body);\n const timestampSec = Math.floor(Date.now() / 1000);\n const timestamp = timestampSec.toString();\n const signature = signRequest(\"POST\", path, timestamp, bodyStr, this.privateKey);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-Merchant-Id\": this.merchantId,\n \"X-Timestamp\": timestamp,\n \"X-Signature\": signature,\n };\n if (!options?.noIdempotency) {\n headers[\"X-Idempotency-Key\"] = computeIdempotencyKey(this.merchantId, path, bodyStr, timestampSec, options);\n }\n\n const response = await this._fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers,\n body: bodyStr,\n });\n\n let envelope: { data: T | null; errors?: PostResult<T>[\"errors\"]; warnings?: PostResult<T>[\"warnings\"] };\n try {\n envelope = (await response.json()) as typeof envelope;\n } catch {\n throw new WaffoPancakeError(response.status, [{ message: `Non-JSON response from ${path}`, layer: \"sdk\" }]);\n }\n return { status: response.status, ...envelope };\n }\n}\n\nfunction computeIdempotencyKey(merchantId: string, path: string, bodyStr: string, timestampSec: number, options?: PostOptions): string {\n const base = `${merchantId}:${path}:${bodyStr}`;\n const input = options?.idempotencyWindow ? `${base}:${Math.floor(timestampSec / options.idempotencyWindow)}` : base;\n return createHash(\"sha256\").update(input).digest(\"hex\");\n}\n","import { createHash, createPrivateKey, createPublicKey, createSign } from \"node:crypto\";\n\nconst PKCS8_HEADER = \"-----BEGIN PRIVATE KEY-----\";\nconst PKCS8_FOOTER = \"-----END PRIVATE KEY-----\";\nconst PKCS1_HEADER = \"-----BEGIN RSA PRIVATE KEY-----\";\nconst PKCS1_FOOTER = \"-----END RSA PRIVATE KEY-----\";\n\nconst SPKI_HEADER = \"-----BEGIN PUBLIC KEY-----\";\nconst SPKI_FOOTER = \"-----END PUBLIC KEY-----\";\nconst PKCS1_PUB_HEADER = \"-----BEGIN RSA PUBLIC KEY-----\";\nconst PKCS1_PUB_FOOTER = \"-----END RSA PUBLIC KEY-----\";\n\n/**\n * Normalize a PEM private key string into a valid PEM format.\n *\n * Handles common issues:\n * - Literal `\\n` from environment variables (e.g. `PRIVATE_KEY=\"-----BEGIN...\\\\n...\"`)\n * - Windows-style `\\r\\n` line endings\n * - Leading/trailing whitespace and blank lines\n * - Missing PEM header/footer (raw base64 input, assumed PKCS#8)\n * - Base64 content on a single line (re-wrapped to 64-char lines)\n * - PKCS#1 (`BEGIN RSA PRIVATE KEY`) accepted as-is\n *\n * @param raw - Private key string in any of the above formats\n * @returns A well-formed PEM string\n * @throws {Error} If the input is empty or contains no base64 content\n *\n * @example\n * // Env var with literal \\n\n * normalizePrivateKey(\"-----BEGIN PRIVATE KEY-----\\\\nMIIE...\\\\n-----END PRIVATE KEY-----\")\n *\n * @example\n * // Raw base64 without PEM wrapper\n * normalizePrivateKey(\"MIIEvQIBADANBgkqhki...\")\n */\nexport function normalizePrivateKey(raw: string): string {\n if (!raw || !raw.trim()) {\n throw new Error(\"Private key is empty. Provide an RSA private key in PEM format.\");\n }\n\n // 1. Replace literal \\n / \\r\\n with real newlines\n let pem = raw.replace(/\\\\n/g, \"\\n\").replace(/\\r\\n/g, \"\\n\");\n\n // 2. Trim leading/trailing whitespace\n pem = pem.trim();\n\n // 3. Detect whether PEM headers are present\n const hasPkcs8Header = pem.includes(PKCS8_HEADER);\n const hasPkcs1Header = pem.includes(PKCS1_HEADER);\n const hasHeader = hasPkcs8Header || hasPkcs1Header;\n\n if (hasHeader) {\n // Strip headers/footers, extract pure base64\n const base64 = pem\n .replace(/-----BEGIN (?:RSA )?PRIVATE KEY-----/g, \"\")\n .replace(/-----END (?:RSA )?PRIVATE KEY-----/g, \"\")\n .replace(/\\s+/g, \"\");\n\n if (!base64) {\n throw new Error(\"Private key contains PEM headers but no key data. Check the key content.\");\n }\n\n // Re-wrap to 64-char lines with the original header type\n const header = hasPkcs1Header ? PKCS1_HEADER : PKCS8_HEADER;\n const footer = hasPkcs1Header ? PKCS1_FOOTER : PKCS8_FOOTER;\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${header}\\n${wrapped}\\n${footer}`;\n } else {\n // No PEM header — treat as raw base64, wrap with PKCS#8 headers\n const base64 = pem.replace(/\\s+/g, \"\");\n\n if (!/^[A-Za-z0-9+/]+=*$/.test(base64)) {\n throw new Error(\"Private key is not valid PEM or base64. Expected an RSA private key in PEM format or raw base64.\");\n }\n\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${PKCS8_HEADER}\\n${wrapped}\\n${PKCS8_FOOTER}`;\n }\n\n // 4. Validate the key is actually parseable by Node.js crypto\n try {\n createPrivateKey(pem);\n } catch {\n throw new Error(\"Private key could not be parsed. Ensure it is a valid RSA private key in PKCS#8 or PKCS#1 (PEM) format.\");\n }\n\n return pem;\n}\n\n/**\n * Normalize a PEM public key string into a valid PEM format.\n *\n * Handles common issues:\n * - Literal `\\n` from environment variables\n * - Windows-style `\\r\\n` line endings\n * - Leading/trailing whitespace and blank lines\n * - Missing PEM header/footer (raw base64 input, assumed SPKI)\n * - Base64 content on a single line (re-wrapped to 64-char lines)\n * - PKCS#1 (`BEGIN RSA PUBLIC KEY`) accepted as-is\n *\n * @param raw - Public key string in any of the above formats\n * @returns A well-formed PEM string\n * @throws {Error} If the input is empty or contains no base64 content\n *\n * @example\n * // Env var with literal \\n\n * normalizePublicKey(\"-----BEGIN PUBLIC KEY-----\\\\nMIIB...\\\\n-----END PUBLIC KEY-----\")\n *\n * @example\n * // Raw base64 without PEM wrapper\n * normalizePublicKey(\"MIIBIjANBgkqhki...\")\n */\nexport function normalizePublicKey(raw: string): string {\n if (!raw || !raw.trim()) {\n throw new Error(\"Public key is empty. Provide an RSA public key in PEM format.\");\n }\n\n // 1. Replace literal \\n / \\r\\n with real newlines\n let pem = raw.replace(/\\\\n/g, \"\\n\").replace(/\\r\\n/g, \"\\n\");\n\n // 2. Trim leading/trailing whitespace\n pem = pem.trim();\n\n // 3. Detect whether PEM headers are present\n const hasSpkiHeader = pem.includes(SPKI_HEADER);\n const hasPkcs1PubHeader = pem.includes(PKCS1_PUB_HEADER);\n const hasHeader = hasSpkiHeader || hasPkcs1PubHeader;\n\n if (hasHeader) {\n // Strip headers/footers, extract pure base64\n const base64 = pem\n .replace(/-----BEGIN (?:RSA )?PUBLIC KEY-----/g, \"\")\n .replace(/-----END (?:RSA )?PUBLIC KEY-----/g, \"\")\n .replace(/\\s+/g, \"\");\n\n if (!base64) {\n throw new Error(\"Public key contains PEM headers but no key data. Check the key content.\");\n }\n\n // Re-wrap to 64-char lines with the original header type\n const header = hasPkcs1PubHeader ? PKCS1_PUB_HEADER : SPKI_HEADER;\n const footer = hasPkcs1PubHeader ? PKCS1_PUB_FOOTER : SPKI_FOOTER;\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${header}\\n${wrapped}\\n${footer}`;\n } else {\n // No PEM header — treat as raw base64, wrap with SPKI headers\n const base64 = pem.replace(/\\s+/g, \"\");\n\n if (!/^[A-Za-z0-9+/]+=*$/.test(base64)) {\n throw new Error(\"Public key is not valid PEM or base64. Expected an RSA public key in PEM format or raw base64.\");\n }\n\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${SPKI_HEADER}\\n${wrapped}\\n${SPKI_FOOTER}`;\n }\n\n // 4. Validate the key is actually parseable by Node.js crypto\n try {\n createPublicKey(pem);\n } catch {\n throw new Error(\"Public key could not be parsed. Ensure it is a valid RSA public key in SPKI or PKCS#1 (PEM) format.\");\n }\n\n return pem;\n}\n\n/**\n * Build canonical request string and sign with RSA-SHA256.\n *\n * Canonical request format:\n * METHOD\\nPATH\\nTIMESTAMP\\nSHA256(BODY)\n *\n * @param method - HTTP method (e.g. \"POST\")\n * @param path - Request path (e.g. \"/v1/actions/store/create-store\")\n * @param timestamp - Unix epoch seconds string\n * @param body - Serialized JSON body\n * @param privateKey - RSA private key in PEM format\n * @returns Base64-encoded RSA-SHA256 signature\n */\nexport function signRequest(method: string, path: string, timestamp: string, body: string, privateKey: string): string {\n const bodyHash = createHash(\"sha256\").update(body).digest(\"base64\");\n const canonicalRequest = `${method}\\n${path}\\n${timestamp}\\n${bodyHash}`;\n\n const sign = createSign(\"sha256\");\n sign.update(canonicalRequest);\n return sign.sign(privateKey, \"base64\");\n}\n","import { WaffoPancakeError } from \"../errors.js\";\n\nimport type { Notice, PostResult } from \"../types.js\";\n\n/**\n * Resource-layer helper: unwrap a REST write-action envelope.\n *\n * - Throws {@link WaffoPancakeError} when `errors[]` is non-empty\n * - Otherwise returns the data block merged with `warnings` (if any), so callers\n * can read structured `aiHint` notices alongside the typed result\n *\n * Use only for REST write endpoints where errors signal a failed action. Read\n * paths (e.g. GraphQL) should return the full envelope without unwrapping.\n *\n * @internal\n */\nexport function unwrapAction<T>(r: PostResult<T>): T & { warnings?: Notice[] } {\n if (r.errors?.length) {\n throw new WaffoPancakeError(r.status, r.errors);\n }\n return { ...(r.data as T), ...(r.warnings ? { warnings: r.warnings } : {}) };\n}\n","/**\n * Client-side input validation.\n *\n * These checks catch obviously invalid inputs before making a network request.\n * They do NOT validate data existence (e.g., whether a store/product actually exists).\n *\n * All validation errors throw `WaffoPancakeError` with `status: 400` and `layer: \"sdk\"`,\n * so developers can catch them uniformly with API errors.\n *\n * Not exported publicly — used internally by resource classes.\n */\n\nimport { WaffoPancakeError } from \"./errors.js\";\n\nconst SHORT_ID_REGEX = /^[A-Z]{2,5}_[0-9A-Za-z]{22}$/;\nconst CURRENCY_CODE_REGEX = /^[A-Z]{3}$/;\nconst COUNTRY_CODE_REGEX = /^[A-Z]{2}$/;\nconst AMOUNT_STRING_REGEX = /^\\d+(\\.\\d+)?$/;\n\nconst SHORT_ID_LABELS: Record<string, string> = {\n STO: \"Store\",\n PROD: \"Product\",\n ORD: \"Order\",\n PAY: \"Payment\",\n REF: \"Refund\",\n TKT: \"Ticket\",\n MER: \"Merchant\",\n};\n\nfunction fail(message: string): never {\n throw new WaffoPancakeError(400, [{ message, layer: \"sdk\" }]);\n}\n\n/**\n * Validate that a required field is present and non-empty.\n */\nexport function validateRequired(field: string, value: unknown): void {\n if (value === undefined || value === null) {\n fail(`Missing required field: ${field}`);\n }\n if (typeof value === \"string\" && value.trim() === \"\") {\n fail(`${field} cannot be empty`);\n }\n}\n\n/**\n * Validate Short ID format (`{PREFIX}_{base62}`).\n */\nexport function validateShortId(field: string, value: string, prefix: string): void {\n validateRequired(field, value);\n const label = SHORT_ID_LABELS[prefix] ?? prefix;\n if (!SHORT_ID_REGEX.test(value)) {\n fail(`Invalid ${field}: expected ${label} Short ID format (${prefix}_xxx), got \"${value}\"`);\n }\n if (!value.startsWith(`${prefix}_`)) {\n fail(`Invalid ${field}: expected ${prefix}_ prefix (${label}), got \"${value.split(\"_\")[0]}_\"`);\n }\n}\n\n/**\n * Validate ISO 4217 currency code format (3 uppercase letters).\n */\nexport function validateCurrencyCode(field: string, value: string): void {\n validateRequired(field, value);\n if (!CURRENCY_CODE_REGEX.test(value)) {\n fail(`Invalid ${field}: expected 3-letter ISO 4217 currency code (e.g., \"USD\"), got \"${value}\"`);\n }\n}\n\n/**\n * Validate that amount is a valid numeric string in display format.\n */\nexport function validateAmountString(field: string, value: string): void {\n validateRequired(field, value);\n if (!AMOUNT_STRING_REGEX.test(value)) {\n fail(`Invalid ${field}: expected numeric string in display format (e.g., \"9.99\", \"1000\"), got \"${value}\"`);\n }\n}\n\n/**\n * Validate that a value is one of the allowed enum values.\n */\nexport function validateEnum(field: string, value: string, allowed: string[]): void {\n validateRequired(field, value);\n if (!allowed.includes(value)) {\n fail(`Invalid ${field}: expected one of [${allowed.join(\", \")}], got \"${value}\"`);\n }\n}\n\n/**\n * Validate that an optional string does not exceed `max` characters.\n */\nexport function validateMaxLength(field: string, value: string | undefined, max: number): void {\n if (value !== undefined && value.length > max) {\n fail(`${field} must be at most ${max} characters, got ${value.length}`);\n }\n}\n\n/**\n * Validate that a value is a positive integer.\n */\nexport function validatePositiveInteger(field: string, value: number): void {\n if (!Number.isInteger(value) || value <= 0) {\n fail(`Invalid ${field}: expected positive integer, got ${value}`);\n }\n}\n\n/**\n * Validate ISO 3166-1 alpha-2 country code (2 uppercase letters).\n */\nexport function validateCountryCode(field: string, value: string): void {\n validateRequired(field, value);\n if (!COUNTRY_CODE_REGEX.test(value)) {\n fail(`Invalid ${field}: expected 2-letter ISO 3166-1 country code (e.g., \"US\"), got \"${value}\"`);\n }\n}\n\n/**\n * Validate Prices object — each currency key and price amount.\n */\nexport function validatePrices(field: string, prices: Record<string, { amount: string; taxCategory: string }>): void {\n validateRequired(field, prices);\n const entries = Object.entries(prices);\n if (entries.length === 0) {\n fail(`${field} must contain at least one currency`);\n }\n for (const [currency, info] of entries) {\n validateCurrencyCode(`${field}.${currency} (key)`, currency);\n validateAmountString(`${field}.${currency}.amount`, info.amount);\n validateRequired(`${field}.${currency}.taxCategory`, info.taxCategory);\n }\n}\n\n/**\n * Validate BillingDetail fields (when present).\n */\nexport function validateBillingDetail(detail: { country: string; isBusiness: boolean }): void {\n validateCountryCode(\"billingDetail.country\", detail.country);\n if (typeof detail.isBusiness !== \"boolean\") {\n fail(`Invalid billingDetail.isBusiness: expected boolean, got ${typeof detail.isBusiness}`);\n }\n}\n\n/**\n * Validate checkout session common fields.\n */\nexport function validateCheckoutCommon(params: {\n productId: string;\n currency: string;\n priceSnapshot?: { amount: string; taxCategory: string };\n billingDetail?: { country: string; isBusiness: boolean };\n expiresInSeconds?: number;\n orderMerchantExternalId?: string;\n}): void {\n validateShortId(\"productId\", params.productId, \"PROD\");\n validateCurrencyCode(\"currency\", params.currency);\n if (params.priceSnapshot) {\n validateAmountString(\"priceSnapshot.amount\", params.priceSnapshot.amount);\n validateRequired(\"priceSnapshot.taxCategory\", params.priceSnapshot.taxCategory);\n }\n if (params.billingDetail) {\n validateBillingDetail(params.billingDetail);\n }\n if (params.expiresInSeconds !== undefined) {\n validatePositiveInteger(\"expiresInSeconds\", params.expiresInSeconds);\n }\n validateMaxLength(\"orderMerchantExternalId\", params.orderMerchantExternalId, 128);\n}\n","import { WaffoPancakeError } from \"../errors.js\";\nimport { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { IssueSessionTokenParams, Notice, SessionToken } from \"../types.js\";\n\n/** Authentication resource — issue session tokens for customers. */\nexport class AuthResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Issue a session token for a customer.\n *\n * @param params - Token issuance parameters\n * @returns Issued session token with expiration\n *\n * @example\n * // By store ID\n * const { token, expiresAt } = await client.auth.issueSessionToken({\n * storeId: \"STO_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n *\n * @example\n * // By product ID (store derived automatically)\n * const { token, expiresAt } = await client.auth.issueSessionToken({\n * productId: \"PROD_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n */\n async issueSessionToken(params: IssueSessionTokenParams): Promise<SessionToken & { warnings?: Notice[] }> {\n if (!params.storeId && !params.productId) {\n throw new WaffoPancakeError(400, [{ message: \"Missing required field: provide storeId or productId\", layer: \"sdk\" }]);\n }\n if (params.storeId) {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n }\n if (params.productId) {\n validateShortId(\"productId\", params.productId, \"PROD\");\n }\n validateRequired(\"buyerIdentity\", params.buyerIdentity);\n return unwrapAction(await this.http.post<SessionToken>(\"/v1/actions/auth/issue-session-token\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateCheckoutCommon } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { AnonymousCheckoutParams, CheckoutSessionResult, Notice } from \"../types.js\";\n\n/**\n * Anonymous checkout — no customer identity provided.\n *\n * The customer reaches the checkout page without a session token. Merchants may still\n * pre-fill `buyerEmail` and `billingDetail` on the page by passing them here.\n * Internally creates a checkout session and returns the redirect URL.\n */\nexport class CheckoutAnonymousResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create an anonymous checkout session.\n *\n * @param params - Checkout parameters (no customer identity required)\n * @returns Session ID, checkout URL, and expiration\n *\n * @example\n * // Minimal — customer fills everything on the page\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * @example\n * // Pre-fill email + billing + attach business-side order reference\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerEmail: \"customer@example.com\",\n * billingDetail: { country: \"US\", isBusiness: false, postcode: \"10001\" },\n * orderMerchantExternalId: \"ORDER-2026-00891\",\n * });\n */\n async create(params: AnonymousCheckoutParams): Promise<CheckoutSessionResult & { warnings?: Notice[] }> {\n validateCheckoutCommon(params);\n return unwrapAction(\n await this.http.post<CheckoutSessionResult>(\"/v1/actions/checkout/create-session\", params, { idempotencyWindow: 60 }),\n );\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateCheckoutCommon, validateRequired } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { AuthenticatedCheckoutParams, AuthenticatedCheckoutResult, CheckoutSessionResult, Notice, SessionToken } from \"../types.js\";\n\n/**\n * Authenticated checkout — merchant provides customer identity.\n *\n * Issues a session token, creates a checkout session, and returns a\n * checkout URL with the token appended as a URL fragment (`#token=...`).\n * The checkout page reads the fragment to pre-fill customer information.\n */\nexport class CheckoutAuthenticatedResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create an authenticated checkout session.\n *\n * Behavior:\n * - Issues a session token via `issue-session-token` (receives `buyerIdentity` + `productId` only)\n * - Creates a checkout session via `create-session` (receives every other field unchanged)\n * - Appends the token to the checkout URL as a URL fragment (`#token=...`)\n *\n * `buyerIdentity` and `buyerEmail` are independent inputs: identity is for the JWT,\n * email is for pre-filling the checkout page. The SDK forwards each to its own endpoint.\n *\n * @param params - Checkout parameters including customer identity\n * @returns Session details with token-appended checkout URL\n *\n * @example\n * const result = await client.checkout.authenticated.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerIdentity: \"user-123\",\n * buyerEmail: \"customer@example.com\",\n * orderMerchantExternalId: \"ORDER-2026-00891\",\n * });\n * // Redirect to result.checkoutUrl (includes #token=...)\n */\n async create(params: AuthenticatedCheckoutParams): Promise<AuthenticatedCheckoutResult & { warnings?: Notice[] }> {\n validateCheckoutCommon(params);\n validateRequired(\"buyerIdentity\", params.buyerIdentity);\n const { buyerIdentity, ...sessionParams } = params;\n\n const [tokenResult, sessionResult] = await Promise.all([\n this.http.post<SessionToken>(\n \"/v1/actions/auth/issue-session-token\",\n {\n productId: params.productId,\n buyerIdentity,\n },\n { idempotencyWindow: 60 },\n ),\n this.http.post<CheckoutSessionResult>(\"/v1/actions/checkout/create-session\", sessionParams, { idempotencyWindow: 60 }),\n ]);\n\n const token = unwrapAction(tokenResult);\n const session = unwrapAction(sessionResult);\n const warnings: Notice[] = [...(token.warnings ?? []), ...(session.warnings ?? [])];\n\n return {\n sessionId: session.sessionId,\n checkoutUrl: `${session.checkoutUrl}#token=${token.token}`,\n expiresAt: session.expiresAt,\n token: token.token,\n tokenExpiresAt: token.expiresAt,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n}\n","import { CheckoutAnonymousResource } from \"./checkout-anonymous.js\";\nimport { CheckoutAuthenticatedResource } from \"./checkout-authenticated.js\";\nimport { unwrapAction } from \"./internal.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { CheckoutSessionResult, CreateCheckoutSessionParams, Notice } from \"../types.js\";\n\n/**\n * Checkout resource — create checkout sessions for payments.\n *\n * Provides two convenience sub-resources for the common checkout flows:\n * - `anonymous` — no customer identity, empty form\n * - `authenticated` — merchant provides customer identity, pre-filled form + token\n *\n * The low-level `createSession()` method is still available for full control.\n *\n * @example\n * // Anonymous checkout (no identity)\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * @example\n * // Authenticated checkout (with customer identity)\n * const result = await client.checkout.authenticated.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerIdentity: \"userIdInYourSystem\",\n * buyerEmail: \"customer@example.com\",\n * });\n * // result.checkoutUrl includes #token=...\n */\nexport class CheckoutResource {\n /** Anonymous checkout — no customer identity, empty form. */\n readonly anonymous: CheckoutAnonymousResource;\n /** Authenticated checkout — merchant provides customer identity. */\n readonly authenticated: CheckoutAuthenticatedResource;\n\n constructor(private readonly http: HttpClient) {\n this.anonymous = new CheckoutAnonymousResource(http);\n this.authenticated = new CheckoutAuthenticatedResource(http);\n }\n\n /**\n * Create a checkout session (low-level). Returns a URL to redirect the customer to.\n *\n * For most use cases, prefer `checkout.anonymous.create()` or\n * `checkout.authenticated.create()` which handle the full flow automatically.\n *\n * @param params - Checkout session parameters\n * @returns Session ID, checkout URL, and expiration\n *\n * @example\n * const session = await client.checkout.createSession({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerEmail: \"customer@example.com\",\n * });\n * // Redirect to session.checkoutUrl\n */\n async createSession(params: CreateCheckoutSessionParams): Promise<CheckoutSessionResult & { warnings?: Notice[] }> {\n return unwrapAction(\n await this.http.post<CheckoutSessionResult>(\"/v1/actions/checkout/create-session\", params, { idempotencyWindow: 60 }),\n );\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { ScanPromptParams, ScanResult } from \"../types.js\";\n\n/** Content safety resource — scan user prompts before AIGC generation. */\nexport class ContentSafetyResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Scan a user's text prompt for content-safety compliance before AIGC\n * generation. Call this before invoking your image/video model and continue\n * only when `action` is `allow`.\n *\n * Stateless — the check never stores prompt text. If the safety service is\n * briefly unavailable, the verdict fails closed to `review` so an\n * unmoderated prompt is never let through.\n *\n * @param params - Scan parameters (prompt required; locale / semantic optional)\n * @returns Redacted scan verdict\n *\n * @example\n * const verdict = await client.contentSafety.scanPrompt({ prompt: \"a cat riding a bike\" });\n * if (verdict.action !== \"allow\") {\n * // do not generate\n * }\n */\n async scanPrompt(params: ScanPromptParams): Promise<ScanResult> {\n validateRequired(\"prompt\", params.prompt);\n return unwrapAction(await this.http.post<ScanResult>(\"/v1/actions/verification/scan-prompt\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateAmountString, validateCurrencyCode, validateMaxLength, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { CustomerHttpClient } from \"../customer-http-client.js\";\nimport type {\n CancelOnetimeOrderParams,\n CancelOnetimeOrderResult,\n CancelSubscriptionParams,\n CancelSubscriptionResult,\n CreateRefundTicketParams,\n GraphQLParams,\n GraphQLResponse,\n Notice,\n ReactivateSubscriptionParams,\n ReactivateSubscriptionResult,\n RefundTicket,\n ResubmitRefundTicketParams,\n} from \"../types.js\";\n\n/**\n * Customer session — lets authenticated customers manage their own orders and subscriptions.\n *\n * Created via `client.customer(token)` using a session token issued by\n * `client.auth.issueSessionToken()`. All requests use Bearer token authentication.\n *\n * @example\n * const { token } = await client.auth.issueSessionToken({\n * storeId: \"STO_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n * const customer = client.customer(token);\n * await customer.cancelSubscription({ orderId: \"ORD_xxx\" });\n */\nexport class CustomerSession {\n /** GraphQL query access scoped to the customer's data. */\n readonly graphql: CustomerGraphQL;\n\n constructor(private readonly http: CustomerHttpClient) {\n this.graphql = new CustomerGraphQL(http);\n }\n\n /**\n * Cancel a subscription order.\n *\n * @param params - Order to cancel\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await customer.cancelSubscription({ orderId: \"ORD_xxx\" });\n * // status: \"canceled\" (was pending) or \"canceling\" (was active)\n */\n async cancelSubscription(params: CancelSubscriptionParams): Promise<CancelSubscriptionResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<CancelSubscriptionResult>(\"/v1/actions/subscription-order/cancel-order\", params));\n }\n\n /**\n * Cancel a one-time order (only while payment is still pending).\n *\n * @param params - Order to cancel\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await customer.cancelOnetimeOrder({ orderId: \"ORD_xxx\" });\n */\n async cancelOnetimeOrder(params: CancelOnetimeOrderParams): Promise<CancelOnetimeOrderResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<CancelOnetimeOrderResult>(\"/v1/actions/onetime-order/cancel-order\", params));\n }\n\n /**\n * Reactivate a subscription that is in `canceling` status.\n *\n * @param params - Order to reactivate\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await customer.reactivateSubscription({ orderId: \"ORD_xxx\" });\n * // status: \"active\"\n */\n async reactivateSubscription(params: ReactivateSubscriptionParams): Promise<ReactivateSubscriptionResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<ReactivateSubscriptionResult>(\"/v1/actions/subscription-order/reactivate-order\", params));\n }\n\n /**\n * Submit a refund request for a payment.\n *\n * @param params - Refund ticket details\n * @returns Created refund ticket\n *\n * @example\n * const { ticket } = await customer.createRefundTicket({\n * paymentId: \"PAY_xxx\",\n * reason: \"Product not as described\",\n * requestedAmount: { amount: \"29.00\", currency: \"USD\" },\n * refundTicketMerchantExternalId: \"REF-2026-00891\",\n * });\n */\n async createRefundTicket(params: CreateRefundTicketParams): Promise<{ ticket: RefundTicket; warnings?: Notice[] }> {\n validateShortId(\"paymentId\", params.paymentId, \"PAY\");\n validateRequired(\"reason\", params.reason);\n validateAmountString(\"requestedAmount.amount\", params.requestedAmount.amount);\n validateCurrencyCode(\"requestedAmount.currency\", params.requestedAmount.currency);\n validateMaxLength(\"refundTicketMerchantExternalId\", params.refundTicketMerchantExternalId, 128);\n return unwrapAction(await this.http.post<{ ticket: RefundTicket }>(\"/v1/actions/refund-ticket/create-ticket\", params));\n }\n\n /**\n * Resubmit a previously rejected refund ticket with updated details.\n *\n * @param params - Updated ticket details\n * @returns Updated refund ticket\n *\n * @example\n * const { ticket } = await customer.resubmitRefundTicket({\n * ticketId: \"TKT_xxx\",\n * paymentId: \"PAY_xxx\",\n * reason: \"Updated reason with more detail\",\n * requestedAmount: { amount: \"29.00\", currency: \"USD\" },\n * });\n */\n async resubmitRefundTicket(params: ResubmitRefundTicketParams): Promise<{ ticket: RefundTicket; warnings?: Notice[] }> {\n validateShortId(\"ticketId\", params.ticketId, \"TKT\");\n validateShortId(\"paymentId\", params.paymentId, \"PAY\");\n validateRequired(\"reason\", params.reason);\n validateAmountString(\"requestedAmount.amount\", params.requestedAmount.amount);\n validateCurrencyCode(\"requestedAmount.currency\", params.requestedAmount.currency);\n return unwrapAction(await this.http.post<{ ticket: RefundTicket }>(\"/v1/actions/refund-ticket/resubmit-ticket\", params));\n }\n}\n\n/**\n * GraphQL access scoped to the customer's session token.\n */\nclass CustomerGraphQL {\n constructor(private readonly http: CustomerHttpClient) {}\n\n /**\n * Execute a GraphQL query scoped to the customer's data.\n *\n * @param params - GraphQL query and variables\n * @returns GraphQL response\n *\n * @example\n * const result = await customer.graphql.query({\n * query: `query { orders { id status } }`,\n * });\n */\n async query<T = Record<string, unknown>>(params: GraphQLParams): Promise<GraphQLResponse<T>> {\n validateRequired(\"query\", params.query);\n const result = await this.http.post<T>(\"/v1/graphql\", params);\n return { data: result.data, errors: result.errors, warnings: result.warnings };\n }\n}\n","import { validateRequired } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { GraphQLParams, GraphQLResponse } from \"../types.js\";\n\n/** GraphQL query resource (Query only, no Mutations). */\nexport class GraphQLResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Execute a GraphQL query (Query only, no Mutations).\n *\n * @param params - GraphQL query and optional variables\n * @returns GraphQL response with data and optional errors\n *\n * @example\n * const result = await client.graphql.query<{ stores: Array<{ id: string; name: string }> }>({\n * query: `query { stores { id name status } }`,\n * });\n * console.log(result.data?.stores);\n *\n * @example\n * const result = await client.graphql.query({\n * query: `query ($id: ID!) { onetimeProduct(id: $id) { id name prices } }`,\n * variables: { id: \"PROD_xxx\" },\n * });\n */\n async query<T = Record<string, unknown>>(params: GraphQLParams): Promise<GraphQLResponse<T>> {\n validateRequired(\"query\", params.query);\n const result = await this.http.post<T>(\"/v1/graphql\", params, { noIdempotency: true });\n return { data: result.data, errors: result.errors, warnings: result.warnings };\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateEnum, validatePrices, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n CreateOnetimeProductParams,\n Notice,\n OnetimeProductDetail,\n PublishOnetimeProductParams,\n UpdateOnetimeProductParams,\n UpdateOnetimeStatusParams,\n} from \"../types.js\";\n\n/** One-time product management resource. */\nexport class OnetimeProductsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a one-time product with multi-currency pricing.\n *\n * @param params - Product creation parameters\n * @returns Created product detail\n *\n * @example\n * const { product } = await client.onetimeProducts.create({\n * storeId: \"STO_xxx\",\n * name: \"E-Book\",\n * prices: { USD: { amount: \"29.00\", taxCategory: \"digital_goods\" } },\n * });\n */\n async create(params: CreateOnetimeProductParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"name\", params.name);\n validatePrices(\"prices\", params.prices);\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/create-product\", params));\n }\n\n /**\n * Update a one-time product. Creates a new version; skips if unchanged.\n *\n * @param params - Product update parameters (only `id` is required)\n * @returns Updated product detail\n *\n * @example\n * // Update only the name\n * const { product } = await client.onetimeProducts.update({\n * id: \"PROD_xxx\",\n * name: \"E-Book v2\",\n * });\n *\n * @example\n * // Update prices while preserving other fields\n * const { product } = await client.onetimeProducts.update({\n * id: \"PROD_xxx\",\n * prices: { USD: { amount: \"39.00\", taxCategory: \"digital_goods\" } },\n * });\n */\n async update(params: UpdateOnetimeProductParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n if (params.name !== undefined) validateRequired(\"name\", params.name);\n if (params.prices) validatePrices(\"prices\", params.prices);\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/update-product\", params));\n }\n\n /**\n * Publish a one-time product's test version to production.\n *\n * @param params - Product to publish\n * @returns Published product detail\n *\n * @example\n * const { product } = await client.onetimeProducts.publish({ id: \"PROD_xxx\" });\n */\n async publish(params: PublishOnetimeProductParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/publish-product\", params));\n }\n\n /**\n * Update a one-time product's status (active/inactive).\n *\n * @param params - Status update parameters\n * @returns Updated product detail\n *\n * @example\n * const { product } = await client.onetimeProducts.updateStatus({\n * id: \"PROD_xxx\",\n * status: ProductVersionStatus.Inactive,\n * });\n */\n async updateStatus(params: UpdateOnetimeStatusParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n validateEnum(\"status\", params.status, [\"active\", \"inactive\"]);\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/update-status\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { CancelSubscriptionParams, CancelSubscriptionResult, Notice } from \"../types.js\";\n\n/** Order management resource. */\nexport class OrdersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Cancel a subscription order.\n *\n * - pending -> canceled (immediate)\n * - active/trialing -> canceling (PSP cancel, webhook updates later)\n *\n * @param params - Order to cancel\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await client.orders.cancelSubscription({\n * orderId: \"ORD_xxx\",\n * });\n * // status: \"canceled\" or \"canceling\"\n */\n async cancelSubscription(params: CancelSubscriptionParams): Promise<CancelSubscriptionResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<CancelSubscriptionResult>(\"/v1/actions/subscription-order/cancel-order\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateEnum, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n AddMerchantParams,\n AddMerchantResult,\n Notice,\n RemoveMerchantParams,\n RemoveMerchantResult,\n UpdateRoleParams,\n UpdateRoleResult,\n} from \"../types.js\";\n\n/** Store merchant management resource (coming soon — endpoints return 501). */\nexport class StoreMerchantsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Add a merchant to a store.\n *\n * @param params - Merchant addition parameters\n * @returns Added merchant details\n *\n * @example\n * const result = await client.storeMerchants.add({\n * storeId: \"STO_xxx\",\n * email: \"member@example.com\",\n * role: \"admin\",\n * });\n */\n async add(params: AddMerchantParams): Promise<AddMerchantResult & { warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"email\", params.email);\n validateEnum(\"role\", params.role, [\"admin\", \"member\"]);\n return unwrapAction(await this.http.post<AddMerchantResult>(\"/v1/actions/store-merchant/add-merchant\", params));\n }\n\n /**\n * Remove a merchant from a store.\n *\n * @param params - Merchant removal parameters\n * @returns Removal confirmation\n *\n * @example\n * const result = await client.storeMerchants.remove({\n * storeId: \"STO_xxx\",\n * merchantId: \"MER_xxx\",\n * });\n */\n async remove(params: RemoveMerchantParams): Promise<RemoveMerchantResult & { warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateShortId(\"merchantId\", params.merchantId, \"MER\");\n return unwrapAction(await this.http.post<RemoveMerchantResult>(\"/v1/actions/store-merchant/remove-merchant\", params));\n }\n\n /**\n * Update a merchant's role in a store.\n *\n * @param params - Role update parameters\n * @returns Updated role details\n *\n * @example\n * const result = await client.storeMerchants.updateRole({\n * storeId: \"STO_xxx\",\n * merchantId: \"MER_xxx\",\n * role: \"member\",\n * });\n */\n async updateRole(params: UpdateRoleParams): Promise<UpdateRoleResult & { warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateShortId(\"merchantId\", params.merchantId, \"MER\");\n validateEnum(\"role\", params.role, [\"admin\", \"member\"]);\n return unwrapAction(await this.http.post<UpdateRoleResult>(\"/v1/actions/store-merchant/update-role\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { CreateStoreParams, DeleteStoreParams, Notice, Store, UpdateStoreParams } from \"../types.js\";\n\n/** Store management resource — create, update, and delete stores. */\nexport class StoresResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a new store. Slug is auto-generated from the name.\n *\n * @param params - Store creation parameters\n * @returns Created store entity\n *\n * @example\n * const { store } = await client.stores.create({ name: \"My Store\" });\n */\n async create(params: CreateStoreParams): Promise<{ store: Store; warnings?: Notice[] }> {\n validateRequired(\"name\", params.name);\n return unwrapAction(await this.http.post<{ store: Store }>(\"/v1/actions/store/create-store\", params));\n }\n\n /**\n * Update an existing store's settings.\n *\n * Settings objects (`notificationSettings`, `checkoutSettings`) support\n * partial updates: omitted sub-fields keep existing values, `null` clears a\n * field. Pass the entire settings object as `null` to clear all fields.\n *\n * **BREAKING (2026-05)**: the legacy `webhookSettings` parameter is removed.\n * Use `client.webhooks.add / update / remove` to manage webhook endpoints,\n * and query the configured webhook list via GraphQL `Store.storeWebhooks`.\n *\n * @param params - Fields to update (only provided fields are changed)\n * @returns Updated store entity\n *\n * @example\n * // Update name\n * const { store } = await client.stores.update({\n * id: \"STO_xxx\",\n * name: \"Updated Name\",\n * });\n *\n * @example\n * // Toggle a notification preference\n * const { store } = await client.stores.update({\n * id: \"STO_xxx\",\n * notificationSettings: { emailOrderConfirmation: false },\n * });\n */\n async update(params: UpdateStoreParams): Promise<{ store: Store; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"STO\");\n return unwrapAction(await this.http.post<{ store: Store }>(\"/v1/actions/store/update-store\", params));\n }\n\n /**\n * Soft-delete a store. Only the owner can delete.\n *\n * @param params - Store to delete\n * @returns Deleted store entity (with `deletedAt` set)\n *\n * @example\n * const { store } = await client.stores.delete({ id: \"STO_xxx\" });\n */\n async delete(params: DeleteStoreParams): Promise<{ store: Store; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"STO\");\n return unwrapAction(await this.http.post<{ store: Store }>(\"/v1/actions/store/delete-store\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n CreateSubscriptionProductGroupParams,\n DeleteSubscriptionProductGroupParams,\n Notice,\n PublishSubscriptionProductGroupParams,\n SubscriptionProductGroup,\n UpdateSubscriptionProductGroupParams,\n} from \"../types.js\";\n\n/** Subscription product group management resource (shared trial, plan switching). */\nexport class SubscriptionProductGroupsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a subscription product group for shared-trial or plan switching.\n *\n * @param params - Group creation parameters\n * @returns Created group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.create({\n * storeId: \"STO_xxx\",\n * name: \"Pro Plans\",\n * rules: { sharedTrial: true },\n * productIds: [\"PROD_aaa\", \"PROD_bbb\"],\n * });\n */\n async create(params: CreateSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"name\", params.name);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/create-group\", params),\n );\n }\n\n /**\n * Update a subscription product group. `productIds` is a full replacement.\n *\n * @param params - Group update parameters\n * @returns Updated group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.update({\n * id: \"GRP_xxx\",\n * productIds: [\"PROD_aaa\", \"PROD_bbb\", \"PROD_ccc\"],\n * });\n */\n async update(params: UpdateSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/update-group\", params),\n );\n }\n\n /**\n * Hard-delete a subscription product group.\n *\n * @param params - Group to delete\n * @returns Deleted group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.delete({ id: \"GRP_xxx\" });\n */\n async delete(params: DeleteSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/delete-group\", params),\n );\n }\n\n /**\n * Publish a test-environment group to production (upsert).\n *\n * @param params - Group to publish\n * @returns Published group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.publish({ id: \"GRP_xxx\" });\n */\n async publish(params: PublishSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/publish-group\", params),\n );\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateEnum, validatePrices, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n CreateSubscriptionProductParams,\n Notice,\n PublishSubscriptionProductParams,\n SubscriptionProductDetail,\n UpdateSubscriptionProductParams,\n UpdateSubscriptionStatusParams,\n} from \"../types.js\";\n\n/** Subscription product management resource. */\nexport class SubscriptionProductsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a subscription product with billing period and multi-currency pricing.\n *\n * @param params - Product creation parameters\n * @returns Created product detail\n *\n * @example\n * const { product } = await client.subscriptionProducts.create({\n * storeId: \"STO_xxx\",\n * name: \"Pro Plan\",\n * billingPeriod: \"monthly\",\n * prices: { USD: { amount: \"9.99\", taxCategory: \"saas\" } },\n * });\n */\n async create(params: CreateSubscriptionProductParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"name\", params.name);\n validateEnum(\"billingPeriod\", params.billingPeriod, [\"weekly\", \"monthly\", \"quarterly\", \"yearly\"]);\n validatePrices(\"prices\", params.prices);\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/create-product\", params),\n );\n }\n\n /**\n * Update a subscription product. Creates a new version; skips if unchanged.\n *\n * @param params - Product update parameters (only `id` is required)\n * @returns Updated product detail\n *\n * @example\n * // Update only the name\n * const { product } = await client.subscriptionProducts.update({\n * id: \"PROD_xxx\",\n * name: \"Pro Plan v2\",\n * });\n *\n * @example\n * // Update prices and billing period\n * const { product } = await client.subscriptionProducts.update({\n * id: \"PROD_xxx\",\n * billingPeriod: \"yearly\",\n * prices: { USD: { amount: \"99.00\", taxCategory: \"saas\" } },\n * });\n */\n async update(params: UpdateSubscriptionProductParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n if (params.name !== undefined) validateRequired(\"name\", params.name);\n if (params.billingPeriod !== undefined)\n validateEnum(\"billingPeriod\", params.billingPeriod, [\"weekly\", \"monthly\", \"quarterly\", \"yearly\"]);\n if (params.prices) validatePrices(\"prices\", params.prices);\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/update-product\", params),\n );\n }\n\n /**\n * Publish a subscription product's test version to production.\n *\n * @param params - Product to publish\n * @returns Published product detail\n *\n * @example\n * const { product } = await client.subscriptionProducts.publish({ id: \"PROD_xxx\" });\n */\n async publish(params: PublishSubscriptionProductParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/publish-product\", params),\n );\n }\n\n /**\n * Update a subscription product's status (active/inactive).\n *\n * @param params - Status update parameters\n * @returns Updated product detail\n *\n * @example\n * const { product } = await client.subscriptionProducts.updateStatus({\n * id: \"PROD_xxx\",\n * status: ProductVersionStatus.Active,\n * });\n */\n async updateStatus(params: UpdateSubscriptionStatusParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n validateEnum(\"status\", params.status, [\"active\", \"inactive\"]);\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/update-status\", params),\n );\n }\n}\n","import { createVerify } from \"node:crypto\";\n\nimport { normalizePublicKey } from \"./signing.js\";\n\nimport type { VerifyWebhookOptions, WebhookEvent, WebhookPublicKeys } from \"./types.js\";\n\n/** Default tolerance: 5 minutes */\n/**\n * Replay-protection window for timestamps in the past.\n *\n * The signature timestamp is stamped once, before the first delivery attempt —\n * retries carry the original header, so by the last attempt the timestamp is as\n * old as the whole retry schedule (observed above 31 minutes). A window shorter\n * than that rejects legitimate retries. 45 minutes covers the schedule plus\n * clock skew on the receiving server.\n *\n * A window this wide does not make replay attacks cheap on its own: every event\n * carries a stable `id`, and handlers are expected to be idempotent on it.\n */\nconst DEFAULT_TOLERANCE_MS = 45 * 60 * 1000;\n\n/**\n * Replay-protection window for timestamps in the future, matching the gateway's\n * API Key check. Only clock skew puts a timestamp ahead of now, so this stays\n * tight.\n */\nconst DEFAULT_FUTURE_TOLERANCE_MS = 60 * 1000;\n\n/** Waffo Pancake test environment webhook verification public key. */\nconst TEST_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxnmRY6yMMA3lVqmAU6ZG\nb1sjL/+r/z6E+ZjkXaDAKiqOhk9rpazni0bNsGXwmftTPk9jy2wn+j6JHODD/WH/\nSCnSfvKkLIjy4Hk7BuCgB174C0ydan7J+KgXLkOwgCAxxB68t2tezldwo74ZpXgn\nF49opzMvQ9prEwIAWOE+kV9iK6gx/AckSMtHIHpUesoPDkldpmFHlB2qpf1vsFTZ\n5kD6DmGl+2GIVK01aChy2lk8pLv0yUMu18v44sLkO5M44TkGPJD9qG09wrvVG2wp\nOTVCn1n5pP8P+HRLcgzbUB3OlZVfdFurn6EZwtyL4ZD9kdkQ4EZE/9inKcp3c1h4\nxwIDAQAB\n-----END PUBLIC KEY-----`;\n\n/** Waffo Pancake production environment webhook verification public key. */\nconst PROD_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+xApdTIb4ua+DgZKQ54\niBsD82ybyhGCLRETONW4Jgbb3A8DUM1LqBk6r/CmTOCHqLalTQHNigvP3R5zkDNX\niRJz6gA4MJ/+8K0+mnEE2RISQzN+Qu65TNd6svb+INm/kMaftY4uIXr6y6kchtTJ\ndwnQhcKdAL2v7h7IFnkVelQsKxDdb2PqX8xX/qwd01iXvMcpCCaXovUwZsxH2QN5\nZKBTseJivbhUeyJCco4fdUyxOMHe2ybCVhyvim2uxAl1nkvL5L8RCWMCAV55LLo0\n9OhmLahz/DYNu13YLVP6dvIT09ZFBYU6Owj1NxdinTynlJCFS9VYwBgmftosSE1U\ndwIDAQAB\n-----END PUBLIC KEY-----`;\n\n/**\n * Parse `X-Waffo-Signature` header.\n *\n * Format: `t=<timestamp>,v1=<base64signature>`\n *\n * @returns Parsed `t` (timestamp string) and `v1` (base64 signature)\n */\nfunction parseSignatureHeader(header: string): { t: string; v1: string } {\n let t = \"\";\n let v1 = \"\";\n for (const pair of header.split(\",\")) {\n const eqIdx = pair.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const key = pair.slice(0, eqIdx).trim();\n const value = pair.slice(eqIdx + 1).trim();\n if (key === \"t\") t = value;\n else if (key === \"v1\") v1 = value;\n }\n return { t, v1 };\n}\n\n/**\n * Verify RSA-SHA256 signature against a public key.\n *\n * @param signatureInput - The string to verify (`${t}.${rawBody}`)\n * @param v1 - Base64-encoded signature\n * @param publicKey - PEM public key\n * @returns Whether the signature is valid\n */\nfunction rsaVerify(signatureInput: string, v1: string, publicKey: string): boolean {\n const verifier = createVerify(\"RSA-SHA256\");\n verifier.update(signatureInput);\n return verifier.verify(publicKey, v1, \"base64\");\n}\n\n/**\n * Resolve the public key for a given environment using the multi-level fallback chain.\n *\n * Resolution order:\n * 1. `configKeys[env]` or `configKeys` (if string) — from WaffoPancakeConfig\n * 2. `WAFFO_WEBHOOK_TEST_PUBLIC_KEY` / `WAFFO_WEBHOOK_PROD_PUBLIC_KEY` — env var per-env\n * 3. `WAFFO_WEBHOOK_PUBLIC_KEY` — env var shared\n * 4. Built-in hardcoded key\n *\n * @param env - Target environment\n * @param configKeys - Config-level public key(s)\n * @returns Resolved and normalized PEM public key\n */\nfunction resolveKeyForEnv(env: \"test\" | \"prod\", configKeys?: WebhookPublicKeys): string {\n // 1. Config-level key\n if (typeof configKeys === \"string\") {\n return normalizePublicKey(configKeys);\n }\n if (configKeys?.[env]) {\n return normalizePublicKey(configKeys[env]);\n }\n\n // 2. Environment variable (per-env)\n const envSpecific = env === \"test\" ? process.env.WAFFO_WEBHOOK_TEST_PUBLIC_KEY : process.env.WAFFO_WEBHOOK_PROD_PUBLIC_KEY;\n if (envSpecific) {\n return normalizePublicKey(envSpecific);\n }\n\n // 3. Environment variable (shared)\n const generic = process.env.WAFFO_WEBHOOK_PUBLIC_KEY;\n if (generic) {\n return normalizePublicKey(generic);\n }\n\n // 4. Built-in hardcoded key\n return env === \"test\" ? TEST_PUBLIC_KEY : PROD_PUBLIC_KEY;\n}\n\n/**\n * Verify and parse an incoming Waffo Pancake webhook event.\n *\n * Public key resolution (per environment):\n * 1. `options.publicKey` — per-call override (highest priority, skips all other resolution)\n * 2. `options.publicKeys[env]` or `options.publicKeys` (string) — config-level\n * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable\n * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable\n * 5. Built-in hardcoded key\n *\n * Behavior:\n * - Parses the `X-Waffo-Signature` header (`t=<timestamp>,v1=<base64sig>`)\n * - Builds signature input `${t}.${rawBody}` and verifies with RSA-SHA256\n * - When `environment` is not specified, tries prod key first, then test key\n * - Optional: checks timestamp to prevent replay attacks (default 5-minute tolerance)\n *\n * @param payload - Raw request body string (must be unparsed)\n * @param signatureHeader - Value of the `X-Waffo-Signature` header\n * @param options - Verification options\n * @returns Parsed webhook event\n * @throws Error if header is missing/malformed, signature is invalid, or timestamp is stale\n *\n * @example\n * // Express (use raw body!)\n * app.post(\"/webhooks\", express.raw({ type: \"application/json\" }), (req, res) => {\n * try {\n * const event = verifyWebhook(\n * req.body.toString(\"utf-8\"),\n * req.headers[\"x-waffo-signature\"] as string,\n * );\n * res.status(200).send(\"OK\");\n * handleEventAsync(event).catch(console.error);\n * } catch {\n * res.status(401).send(\"Invalid signature\");\n * }\n * });\n *\n * @example\n * // Next.js App Router\n * export async function POST(request: Request) {\n * const body = await request.text();\n * const sig = request.headers.get(\"x-waffo-signature\");\n * const event = verifyWebhook(body, sig);\n * // handle event ...\n * return new Response(\"OK\");\n * }\n *\n * @example\n * // Specify environment explicitly\n * const event = verifyWebhook(body, sig, { environment: \"prod\" });\n *\n * @example\n * // Disable replay protection\n * const event = verifyWebhook(body, sig, { toleranceMs: 0 });\n */\nexport function verifyWebhook<T = Record<string, unknown>>(\n payload: string,\n signatureHeader: string | undefined | null,\n options?: VerifyWebhookOptions,\n): WebhookEvent<T> {\n if (!signatureHeader) {\n throw new Error(\"Missing X-Waffo-Signature header\");\n }\n\n const { t, v1 } = parseSignatureHeader(signatureHeader);\n if (!t || !v1) {\n throw new Error(\"Malformed X-Waffo-Signature header: missing t or v1\");\n }\n\n // Replay protection — asymmetric, matching the gateway's API Key check\n const toleranceMs = options?.toleranceMs ?? DEFAULT_TOLERANCE_MS;\n if (toleranceMs > 0) {\n const timestampMs = Number(t);\n if (Number.isNaN(timestampMs)) {\n throw new Error(\"Invalid timestamp in X-Waffo-Signature header\");\n }\n const futureToleranceMs = options?.futureToleranceMs ?? DEFAULT_FUTURE_TOLERANCE_MS;\n const ageMs = Date.now() - timestampMs;\n if (ageMs > toleranceMs || ageMs < -futureToleranceMs) {\n throw new Error(\"Webhook timestamp outside tolerance window (possible replay attack)\");\n }\n }\n\n // RSA-SHA256 verification\n const signatureInput = `${t}.${payload}`;\n const directKey = options?.publicKey;\n\n if (directKey) {\n // Per-call override — highest priority, skip all resolution\n const normalizedKey = normalizePublicKey(directKey);\n if (!rsaVerify(signatureInput, v1, normalizedKey)) {\n throw new Error(\"Invalid webhook signature (custom key)\");\n }\n } else {\n const configKeys = options?.publicKeys;\n const env = options?.environment;\n\n if (env === \"test\" || env === \"prod\") {\n const key = resolveKeyForEnv(env, configKeys);\n if (!rsaVerify(signatureInput, v1, key)) {\n throw new Error(`Invalid webhook signature (${env} key)`);\n }\n } else {\n // Auto-detect: try prod first, then test\n const prodKey = resolveKeyForEnv(\"prod\", configKeys);\n if (!rsaVerify(signatureInput, v1, prodKey)) {\n const testKey = resolveKeyForEnv(\"test\", configKeys);\n if (!rsaVerify(signatureInput, v1, testKey)) {\n throw new Error(\"Invalid webhook signature (tried both prod and test keys)\");\n }\n }\n }\n }\n\n return JSON.parse(payload) as WebhookEvent<T>;\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\nimport { verifyWebhook } from \"../webhooks.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n AddWebhookParams,\n Notice,\n RemoveWebhookParams,\n StoreWebhook,\n UpdateWebhookParams,\n VerifyWebhookOptions,\n WebhookEvent,\n WebhookPublicKeys,\n} from \"../types.js\";\n\n/**\n * Webhook resource — manages webhook configurations (HTTP / Feishu / Discord\n * / Telegram / Slack) and verifies inbound webhook signatures.\n *\n * **Mutations only**: `add`, `update`, `remove` all hit POST endpoints.\n * To list a store's webhooks, use GraphQL `Store.storeWebhooks` via\n * `client.graphql.query`.\n *\n * Verification (`verify`) is a local cryptographic operation that does not\n * require API calls.\n */\nexport class WebhooksResource {\n /**\n * @param http - HTTP client (used for add/update/remove)\n * @param publicKeys - Optional config-level public key(s) from WaffoPancakeConfig\n */\n constructor(\n private readonly http: HttpClient,\n private readonly publicKeys: WebhookPublicKeys | undefined,\n ) {}\n\n /**\n * Add a webhook endpoint to a store.\n *\n * @param params - Webhook configuration\n * @returns Created webhook entity\n *\n * @example\n * // HTTP webhook (RSA-signed envelope, default)\n * const { webhook } = await client.webhooks.add({\n * storeId: \"STO_xxx\",\n * channel: \"http\",\n * url: \"https://example.com/webhook\",\n * events: [\"order.completed\", \"refund.succeeded\"],\n * testMode: false,\n * });\n *\n * @example\n * // Discord webhook (uses Discord embed format)\n * await client.webhooks.add({\n * storeId: \"STO_xxx\",\n * channel: \"discord\",\n * url: \"https://discord.com/api/webhooks/...\",\n * events: [\"order.completed\"],\n * testMode: false,\n * });\n *\n * @example\n * // Telegram bot — chat_id goes in `secret`; URL is the bot's sendMessage endpoint\n * await client.webhooks.add({\n * storeId: \"STO_xxx\",\n * channel: \"telegram\",\n * url: \"https://api.telegram.org/bot123:ABC/sendMessage\",\n * events: [\"order.completed\"],\n * testMode: false,\n * secret: \"8737101383\",\n * });\n */\n async add(params: AddWebhookParams): Promise<{ webhook: StoreWebhook; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"channel\", params.channel);\n validateRequired(\"url\", params.url);\n return unwrapAction(await this.http.post<{ webhook: StoreWebhook }>(\"/v1/actions/store/add-webhook\", params));\n }\n\n /**\n * Update an existing webhook (only `url`, `events`, and `secret` are mutable).\n *\n * `channel` and `testMode` cannot be changed — remove the webhook and\n * re-add it instead. URL changes must remain on the same channel host\n * whitelist.\n *\n * @param params - Fields to update\n * @returns Updated webhook entity\n *\n * @example\n * await client.webhooks.update({\n * id: \"11111111-2222-3333-4444-555555555555\",\n * events: [\"order.completed\", \"refund.succeeded\", \"subscription.canceled\"],\n * });\n */\n async update(params: UpdateWebhookParams): Promise<{ webhook: StoreWebhook; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(await this.http.post<{ webhook: StoreWebhook }>(\"/v1/actions/store/update-webhook\", params));\n }\n\n /**\n * Hard-delete a webhook. Historical `webhook_deliveries` rows are retained\n * (with `storeWebhookId` set to null) for audit purposes.\n *\n * @param params - Webhook to remove\n * @returns The removed webhook entity (snapshot before deletion)\n *\n * @example\n * await client.webhooks.remove({ id: \"11111111-...\" });\n */\n async remove(params: RemoveWebhookParams): Promise<{ webhook: StoreWebhook; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(await this.http.post<{ webhook: StoreWebhook }>(\"/v1/actions/store/remove-webhook\", params));\n }\n\n /**\n * Verify and parse an incoming webhook event.\n *\n * Key resolution order:\n * 1. `options.publicKey` — per-call override (highest priority)\n * 2. `config.webhookPublicKey[env]` or `config.webhookPublicKey` (string)\n * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable\n * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable\n * 5. Built-in hardcoded key\n *\n * @param payload - Raw request body string (must be unparsed)\n * @param signatureHeader - Value of the `X-Waffo-Signature` header\n * @param options - Verification options (optional)\n * @returns Parsed webhook event\n * @throws Error if signature is invalid, header is malformed, or timestamp is stale\n *\n * @example\n * const event = client.webhooks.verify(rawBody, signatureHeader);\n *\n * @example\n * // Specify environment\n * const event = client.webhooks.verify(rawBody, sig, { environment: \"test\" });\n *\n * @example\n * // Per-call key override\n * const event = client.webhooks.verify(rawBody, sig, { publicKey: oneOffKey });\n */\n verify<T = Record<string, unknown>>(\n payload: string,\n signatureHeader: string | undefined | null,\n options?: VerifyWebhookOptions,\n ): WebhookEvent<T> {\n const mergedOptions: VerifyWebhookOptions = {\n ...options,\n publicKeys: options?.publicKeys ?? this.publicKeys,\n };\n return verifyWebhook<T>(payload, signatureHeader, mergedOptions);\n }\n}\n","import { CustomerHttpClient } from \"./customer-http-client.js\";\nimport { WaffoPancakeError } from \"./errors.js\";\nimport { HttpClient } from \"./http-client.js\";\nimport { AuthResource } from \"./resources/auth.js\";\nimport { CheckoutResource } from \"./resources/checkout.js\";\nimport { ContentSafetyResource } from \"./resources/content-safety.js\";\nimport { CustomerSession } from \"./resources/customer.js\";\nimport { GraphQLResource } from \"./resources/graphql.js\";\nimport { OnetimeProductsResource } from \"./resources/onetime-products.js\";\nimport { OrdersResource } from \"./resources/orders.js\";\nimport { StoreMerchantsResource } from \"./resources/store-merchants.js\";\nimport { StoresResource } from \"./resources/stores.js\";\nimport { SubscriptionProductGroupsResource } from \"./resources/subscription-product-groups.js\";\nimport { SubscriptionProductsResource } from \"./resources/subscription-products.js\";\nimport { WebhooksResource } from \"./resources/webhooks.js\";\nimport { validateEnum, validateShortId } from \"./validation.js\";\n\nimport type { CustomerSessionOptions, WaffoPancakeConfig } from \"./types.js\";\n\n/**\n * Waffo Pancake TypeScript SDK client.\n *\n * Uses Merchant API Key (RSA-SHA256) authentication. All requests are\n * automatically signed — no manual header construction needed.\n *\n * @example\n * import { WaffoPancake } from \"@waffo/pancake-ts\";\n *\n * const client = new WaffoPancake({\n * merchantId: \"MER_2D5F8G3H1K4M6N9P0Q7R8S\", // MER_{base62} format\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n *\n * // Create a store — IDs are returned in {prefix}_{base62} format\n * const { store } = await client.stores.create({ name: \"My Store\" });\n * // => store.id = \"STO_...\"\n *\n * // Create a product\n * const { product } = await client.onetimeProducts.create({\n * storeId: store.id, // \"STO_...\"\n * name: \"E-Book\",\n * prices: { USD: { amount: \"29.00\", taxCategory: \"digital_goods\" } },\n * });\n * // => product.id = \"PROD_...\"\n *\n * // Create a checkout session\n * const session = await client.checkout.createSession({\n * productId: product.id,\n * currency: \"USD\",\n * });\n * // => redirect customer to session.checkoutUrl\n *\n * // Query data via GraphQL\n * const result = await client.graphql.query({\n * query: `query { stores { id name status } }`,\n * });\n *\n * @example\n * // Per-environment webhook public keys\n * const client = new WaffoPancake({\n * merchantId: \"...\",\n * privateKey: \"...\",\n * webhookPublicKey: {\n * test: process.env.WAFFO_TEST_PUB_KEY!,\n * prod: process.env.WAFFO_PROD_PUB_KEY!,\n * },\n * });\n * const event = client.webhooks.verify(rawBody, signatureHeader);\n */\nexport class WaffoPancake {\n private readonly http: HttpClient;\n private readonly config: WaffoPancakeConfig;\n\n readonly auth: AuthResource;\n readonly stores: StoresResource;\n readonly storeMerchants: StoreMerchantsResource;\n readonly onetimeProducts: OnetimeProductsResource;\n readonly subscriptionProducts: SubscriptionProductsResource;\n readonly subscriptionProductGroups: SubscriptionProductGroupsResource;\n readonly orders: OrdersResource;\n readonly checkout: CheckoutResource;\n readonly graphql: GraphQLResource;\n readonly webhooks: WebhooksResource;\n readonly contentSafety: ContentSafetyResource;\n\n constructor(config: WaffoPancakeConfig) {\n validateShortId(\"merchantId\", config.merchantId, \"MER\");\n this.config = config;\n this.http = new HttpClient(config);\n\n this.auth = new AuthResource(this.http);\n this.stores = new StoresResource(this.http);\n this.storeMerchants = new StoreMerchantsResource(this.http);\n this.onetimeProducts = new OnetimeProductsResource(this.http);\n this.subscriptionProducts = new SubscriptionProductsResource(this.http);\n this.subscriptionProductGroups = new SubscriptionProductGroupsResource(this.http);\n this.orders = new OrdersResource(this.http);\n this.checkout = new CheckoutResource(this.http);\n this.graphql = new GraphQLResource(this.http);\n this.webhooks = new WebhooksResource(this.http, config.webhookPublicKey);\n this.contentSafety = new ContentSafetyResource(this.http);\n }\n\n /**\n * Create a customer session for self-service operations.\n *\n * The returned session uses Bearer token authentication and provides\n * methods for order cancellation, subscription management, refund tickets,\n * and scoped GraphQL queries.\n *\n * Session tokens expire 5 minutes after issuance, so issue one right before\n * use rather than caching it.\n *\n * @param token - Session token from `client.auth.issueSessionToken()`\n * @param options - Per-session overrides\n * @returns A customer session with self-service methods\n * @throws {WaffoPancakeError} When no environment is available from either\n * `options.environment` or `WaffoPancakeConfig.environment`\n *\n * @example\n * const { token } = await client.auth.issueSessionToken({\n * storeId: \"STO_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n * const customer = client.customer(token, { environment: \"test\" });\n * await customer.cancelSubscription({ orderId: \"ORD_xxx\" });\n *\n * @example\n * // Set the environment once on the client instead\n * const client = new WaffoPancake({ merchantId, privateKey, environment: \"test\" });\n * const customer = client.customer(token);\n */\n customer(token: string, options?: CustomerSessionOptions): CustomerSession {\n const environment = options?.environment ?? this.config.environment;\n if (environment === undefined) {\n throw new WaffoPancakeError(400, [\n {\n message:\n \"Missing required field: environment — set it on the client config or pass client.customer(token, { environment: 'test' | 'prod' })\",\n layer: \"sdk\",\n },\n ]);\n }\n validateEnum(\"environment\", environment, [\"test\", \"prod\"]);\n\n const customerHttp = new CustomerHttpClient(token, environment, {\n baseUrl: this.config.baseUrl,\n fetch: this.config.fetch,\n });\n return new CustomerSession(customerHttp);\n }\n\n /**\n * Create a customer session for self-service operations.\n *\n * @param token - Session token from `client.auth.issueSessionToken()`\n * @param options - Per-session overrides\n * @returns A customer session with self-service methods\n *\n * @example\n * ```typescript\n * const session = client.buyer(token); // prefer client.customer(token)\n * ```\n *\n * @deprecated Use {@link WaffoPancake.customer} instead.\n */\n buyer(token: string, options?: CustomerSessionOptions): CustomerSession {\n return this.customer(token, options);\n }\n}\n","// ---------------------------------------------------------------------------\n// Client config\n// ---------------------------------------------------------------------------\n\nexport interface WaffoPancakeConfig {\n /** Merchant ID in `MER_{base62}` format (sent as X-Merchant-Id header) */\n merchantId: string;\n /** RSA private key in PEM format for request signing */\n privateKey: string;\n /** Base URL override (default: https://api.waffo.ai) */\n baseUrl?: string;\n /** Custom fetch implementation (default: global fetch) */\n fetch?: typeof fetch;\n /**\n * Environment that customer sessions operate in (sent as the `X-Environment`\n * header alongside the session token's Bearer credential).\n *\n * API Key requests do not need this — the gateway derives their environment\n * from the key itself. Session tokens carry no environment, so the gateway\n * requires the header and rejects the request with HTTP 400 without it.\n *\n * There is no default: a wrong guess would route the call to the other\n * environment. Supply it here, or per session via\n * {@link CustomerSessionOptions.environment}.\n *\n * @see {@link WaffoPancake.customer}\n */\n environment?: `${Environment}`;\n /**\n * Custom RSA public key(s) for webhook signature verification.\n *\n * - `string` — single key used for both test and prod environments\n * - `{ test?, prod? }` — per-environment keys\n *\n * Resolution order per environment: config key → env var → built-in key.\n * @see {@link VerifyWebhookOptions} for per-call overrides\n */\n webhookPublicKey?: WebhookPublicKeys;\n}\n\n/** Options for {@link WaffoPancake.customer}. */\nexport interface CustomerSessionOptions {\n /**\n * Environment this session operates in, overriding\n * {@link WaffoPancakeConfig.environment} for a single session.\n *\n * Required when the client config omits `environment`.\n */\n environment?: `${Environment}`;\n}\n\n// ---------------------------------------------------------------------------\n// Internal HTTP options\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link HttpClient.post}.\n * Not exported publicly — used by resource classes.\n */\nexport interface PostOptions {\n /**\n * Time window in seconds for idempotency key rotation.\n * When set, a floored timestamp is mixed into the key so identical params\n * produce a new key after the window elapses (e.g. 60 = per-minute dedup).\n */\n idempotencyWindow?: number;\n /**\n * Skip the X-Idempotency-Key header entirely. Set for read-only queries\n * (e.g. GraphQL) so the gateway's 24h idempotency cache does not serve\n * stale data on identical repeat queries.\n */\n noIdempotency?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// API response envelope\n// ---------------------------------------------------------------------------\n\n/**\n * Single Notice entry within `errors` or `warnings` arrays.\n *\n * Both REST and GraphQL envelopes use the same Notice shape. `aiHint` is the\n * structured migration instruction for LLM consumers (see handbook\n * `command-layer.md` aiHint four-line template).\n *\n * @example\n * { message: \"Store slug already exists\", layer: \"store\" }\n * @example\n * { message: \"webhookSettings field ignored\", layer: \"store\",\n * aiHint: \"Switch to client.webhooks.add / update / remove\" }\n */\nexport interface Notice {\n /** Human-readable message */\n message: string;\n /** Layer that produced this notice */\n layer: `${ErrorLayer}`;\n /** Structured migration / remediation instruction for LLM consumers */\n aiHint?: string;\n}\n\n/** @deprecated Use {@link Notice}. Kept for backwards compatibility with existing imports. */\nexport type ApiError = Notice;\n\n/**\n * API response envelope. Both REST writes and GraphQL queries return this shape:\n * - Success: `{ data: T }` (optionally with `warnings`)\n * - Failure: `{ data: null, errors: Notice[] }`\n * - Partial success (GraphQL only): `{ data: T, errors: Notice[] }`\n *\n * `errors` are ordered by call stack: `[0]` is the deepest layer, `[n]` is the outermost.\n *\n * See handbook `coding-standards/code-style-guide/command-layer.md` for the wire contract.\n */\nexport interface Envelope<T> {\n data: T | null;\n errors?: Notice[];\n warnings?: Notice[];\n}\n\n/** Transport-layer result: HTTP status plus the parsed envelope. */\nexport interface PostResult<T> extends Envelope<T> {\n /** HTTP status code from the response */\n status: number;\n}\n\n// ---------------------------------------------------------------------------\n// Enums (runtime-accessible values)\n// ---------------------------------------------------------------------------\n\n/**\n * Environment type.\n * @see docs/api-reference/authentication.mdx\n */\nexport enum Environment {\n Test = \"test\",\n Prod = \"prod\",\n}\n\n/**\n * Tax category for products.\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport enum TaxCategory {\n DigitalGoods = \"digital_goods\",\n SaaS = \"saas\",\n Software = \"software\",\n Ebook = \"ebook\",\n OnlineCourse = \"online_course\",\n Consulting = \"consulting\",\n ProfessionalService = \"professional_service\",\n}\n\n/**\n * Subscription billing period.\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport enum BillingPeriod {\n Weekly = \"weekly\",\n Monthly = \"monthly\",\n Quarterly = \"quarterly\",\n Yearly = \"yearly\",\n}\n\n/**\n * Product version status.\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport enum ProductVersionStatus {\n Active = \"active\",\n Inactive = \"inactive\",\n}\n\n/**\n * Store entity status.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport enum EntityStatus {\n Active = \"active\",\n Inactive = \"inactive\",\n Suspended = \"suspended\",\n}\n\n/**\n * Store member role.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport enum StoreRole {\n Owner = \"owner\",\n Admin = \"admin\",\n Member = \"member\",\n}\n\n/**\n * One-time order status.\n * @see docs/api-reference/endpoints/orders/overview.mdx\n */\nexport enum OnetimeOrderStatus {\n Pending = \"pending\",\n Completed = \"completed\",\n Canceled = \"canceled\",\n}\n\n/**\n * Subscription order status.\n *\n * State machine:\n * - pending -> active, canceled, closed (PSP CLOSE from never-activated)\n * - active -> canceling, past_due, canceled, expired\n * - canceling -> active, canceled\n * - past_due -> active, canceled\n * - closed -> terminal (never-activated subscription closed by PSP)\n * - canceled -> terminal\n * - expired -> terminal\n *\n * @see docs/api-reference/endpoints/subscriptions/overview.mdx\n */\nexport enum SubscriptionOrderStatus {\n Pending = \"pending\",\n Active = \"active\",\n Canceling = \"canceling\",\n PastDue = \"past_due\",\n Closed = \"closed\",\n Canceled = \"canceled\",\n Expired = \"expired\",\n}\n\n/**\n * Payment status.\n * @see docs/api-reference/endpoints/orders/overview.mdx\n */\nexport enum PaymentStatus {\n Pending = \"pending\",\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n Canceled = \"canceled\",\n}\n\n/**\n * Refund ticket status.\n * @see docs/api-reference/endpoints/refunds/overview.mdx\n */\nexport enum RefundTicketStatus {\n Pending = \"pending\",\n UnderReview = \"under_review\",\n Approved = \"approved\",\n Rejected = \"rejected\",\n Returned = \"returned\",\n Processing = \"processing\",\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n Cancelled = \"cancelled\",\n}\n\n/**\n * Refund status.\n * @see docs/api-reference/endpoints/refunds/overview.mdx\n */\nexport enum RefundStatus {\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n}\n\n/**\n * Media asset type.\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport enum MediaType {\n Image = \"image\",\n Video = \"video\",\n}\n\n/** Error layer identifier in the call stack. */\nexport enum ErrorLayer {\n Gateway = \"gateway\",\n User = \"user\",\n Store = \"store\",\n Product = \"product\",\n Order = \"order\",\n Ticket = \"ticket\",\n GraphQL = \"graphql\",\n Resource = \"resource\",\n /** SDK-specific layer for email delivery errors (not part of the service-side error layers). */\n Email = \"email\",\n /** SDK-side input validation (caught before network request). */\n Sdk = \"sdk\",\n}\n\n// ---------------------------------------------------------------------------\n// Auth\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for issuing a customer session token.\n *\n * Provide either `storeId` or `productId` (at least one required).\n * When `productId` is given without `storeId`, the server derives the store from the product.\n *\n * @see docs/api-reference/endpoints/auth/issue-session-token.mdx\n */\nexport interface IssueSessionTokenParams {\n /**\n * Customer identity — encoded into the JWT payload for merchant-side customer\n * identification. Accepts an email or any merchant-provided identifier string.\n * To pre-fill the checkout page's email field, use `buyerEmail` on\n * `checkout.authenticated.create`.\n */\n buyerIdentity: string;\n /** Store ID (optional when `productId` is provided) */\n storeId?: string;\n /** Product ID — used to derive the store when `storeId` is omitted */\n productId?: string;\n}\n\n/**\n * Issued session token response.\n *\n * @example\n * { token: \"eyJhbGciOi...\", expiresAt: \"2026-03-10T09:00:00.000Z\" }\n */\nexport interface SessionToken {\n /** JWT token string */\n token: string;\n /** Expiration time (ISO 8601 UTC) */\n expiresAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Store — from waffo-pancake-store-service\n// ---------------------------------------------------------------------------\n\n/**\n * Webhook channel — HTTP for the standard RSA-signed envelope, the rest for\n * IM platform native payloads (Feishu / Discord / Telegram / Slack).\n */\nexport type WebhookChannel = \"http\" | \"feishu\" | \"discord\" | \"telegram\" | \"slack\";\n\n/**\n * Configured webhook endpoint (one row of `store.store_webhooks`).\n *\n * @see docs/api-reference/endpoints/webhooks/overview.mdx\n */\nexport interface StoreWebhook {\n /** Webhook UUID (not Short ID) */\n id: string;\n /** Owning store Short ID (`STO_…`) */\n storeId: string;\n channel: WebhookChannel;\n /** Target webhook URL */\n url: string;\n /** Subscribed event types (use `WebhookEventType` enum or its string literal) */\n events: `${WebhookEventType}`[];\n /** Whether this webhook fires in test or prod environment */\n testMode: boolean;\n /** Channel-specific credential (e.g. Telegram chat_id) */\n secret: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** Parameters for creating a webhook. */\nexport interface AddWebhookParams {\n /** Store Short ID (`STO_…`) */\n storeId: string;\n channel: WebhookChannel;\n /** Target webhook URL */\n url: string;\n /** Subscribed event types (use `WebhookEventType` enum or its string literal) */\n events: `${WebhookEventType}`[];\n /** Whether this webhook fires in test (true) or prod (false) */\n testMode: boolean;\n /** Channel-specific credential (e.g. Telegram chat_id) */\n secret?: string | null;\n}\n\n/** Parameters for updating a webhook. `channel` and `testMode` are immutable. */\nexport interface UpdateWebhookParams {\n /** Webhook UUID */\n id: string;\n /** Replace target URL (must remain on the same channel host) */\n url?: string;\n /** Replace subscribed event types (use `WebhookEventType` enum or its string literal) */\n events?: `${WebhookEventType}`[];\n /** Replace channel-specific credential */\n secret?: string | null;\n}\n\n/** Parameters for hard-deleting a webhook. */\nexport interface RemoveWebhookParams {\n /** Webhook UUID */\n id: string;\n}\n\n/**\n * Notification settings (all default to true).\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface NotificationSettings {\n emailOrderConfirmation: boolean;\n emailSubscriptionConfirmation: boolean;\n emailSubscriptionCycled: boolean;\n emailSubscriptionCanceled: boolean;\n emailSubscriptionRevoked: boolean;\n emailSubscriptionPastDue: boolean;\n emailTrialStarted: boolean;\n emailTrialEnding: boolean;\n emailUpcomingCharge: boolean;\n notifyNewOrders: boolean;\n notifyNewSubscriptions: boolean;\n notifySubscriptionCanceled: boolean;\n notifySubscriptionEnded: boolean;\n notifySubscriptionPastDue: boolean;\n notifySubscriptionRenewed: boolean;\n notifySubscriptionUncanceled: boolean;\n notifySubscriptionUpdated: boolean;\n notifyChargeback: boolean;\n}\n\n/**\n * Merchant-writable subset of {@link NotificationSettings}.\n *\n * Consumer-email toggles (`email*`) are managed by the PANCAKE platform and **not**\n * writable from this SDK; they would be silently dropped by the `update-store`\n * endpoint if included. Payout result notifications are platform-managed and always\n * delivered — they have no toggle key. Use this type for any merchant-side update.\n */\nexport type MerchantWritableNotificationSettings = Pick<\n NotificationSettings,\n | \"notifyNewOrders\"\n | \"notifyNewSubscriptions\"\n | \"notifySubscriptionCanceled\"\n | \"notifySubscriptionEnded\"\n | \"notifySubscriptionPastDue\"\n | \"notifySubscriptionRenewed\"\n | \"notifySubscriptionUncanceled\"\n | \"notifySubscriptionUpdated\"\n | \"notifyChargeback\"\n>;\n\n/**\n * Single-theme checkout page styling.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface CheckoutThemeSettings {\n checkoutLogo: string | null;\n checkoutColorPrimary: string;\n checkoutColorBackground: string;\n checkoutColorCard: string;\n checkoutColorText: string;\n checkoutBorderRadius: string;\n}\n\n/**\n * Checkout page configuration (light and dark themes).\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface CheckoutSettings {\n defaultDarkMode: boolean;\n light: CheckoutThemeSettings;\n dark: CheckoutThemeSettings;\n}\n\n/**\n * Store entity.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface Store {\n id: string;\n name: string;\n status: EntityStatus;\n logo: string | null;\n supportEmail: string | null;\n website: string | null;\n slug: string | null;\n prodEnabled: boolean;\n notificationSettings: NotificationSettings | null;\n checkoutSettings: CheckoutSettings | null;\n deletedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** Parameters for creating a store. */\nexport interface CreateStoreParams {\n /** Store name (slug is auto-generated) */\n name: string;\n}\n\n/**\n * Parameters for updating a store.\n *\n * Settings objects support partial updates — omitted sub-fields keep their\n * existing values, `null` clears a field, and a concrete value sets it.\n * Pass the entire settings object as `null` to clear all fields in the group.\n *\n * `supportEmail` and `website` are not writable here. They are derived from\n * ownership verification and are set only by the flows that prove it: email\n * code binding and domain verification, or KYB approval. Read them back from\n * {@link Store}.\n *\n * **BREAKING (2026-05)**: the legacy `webhookSettings` field is removed.\n * Manage webhooks via `client.webhooks.add / update / remove`; query the\n * webhook list through GraphQL `Store.storeWebhooks`.\n */\nexport interface UpdateStoreParams {\n /** Store ID */\n id: string;\n /** Store display name */\n name?: string;\n /** Store status */\n status?: EntityStatus;\n /** Store logo URL (set to `null` to remove) */\n logo?: string | null;\n /** Notification preferences (partial update — omitted fields keep existing values, set to `null` to clear all) */\n notificationSettings?: Partial<MerchantWritableNotificationSettings> | null;\n /** Checkout page theme configuration (partial update — omitted fields keep existing values, set to `null` to clear all) */\n checkoutSettings?: Partial<CheckoutSettings> | null;\n}\n\n/** Parameters for deleting (soft-delete) a store. */\nexport interface DeleteStoreParams {\n /** Store ID */\n id: string;\n}\n\n// ---------------------------------------------------------------------------\n// Store Merchant (coming soon — endpoints return 501)\n// ---------------------------------------------------------------------------\n\n/** Parameters for adding a merchant to a store. */\nexport interface AddMerchantParams {\n storeId: string;\n email: string;\n role: \"admin\" | \"member\";\n}\n\n/** Result of adding a merchant to a store. */\nexport interface AddMerchantResult {\n storeId: string;\n merchantId: string;\n email: string;\n role: string;\n status: string;\n addedAt: string;\n}\n\n/** Parameters for removing a merchant from a store. */\nexport interface RemoveMerchantParams {\n storeId: string;\n merchantId: string;\n}\n\n/** Result of removing a merchant from a store. */\nexport interface RemoveMerchantResult {\n message: string;\n removedAt: string;\n}\n\n/** Parameters for updating a merchant's role. */\nexport interface UpdateRoleParams {\n storeId: string;\n merchantId: string;\n role: \"admin\" | \"member\";\n}\n\n/** Result of updating a merchant's role. */\nexport interface UpdateRoleResult {\n storeId: string;\n merchantId: string;\n role: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Product — shared types from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * Price for a single currency.\n *\n * Amounts are represented as display strings (e.g., \"9.99\" for USD, \"1000\" for JPY).\n * The server handles conversion to/from smallest currency units internally.\n *\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n *\n * @example\n * // USD $9.99\n * { amount: \"9.99\", taxCategory: \"saas\" }\n *\n * @example\n * // JPY ¥1000\n * { amount: \"1000\", taxCategory: \"software\" }\n *\n * @example\n * // USD $9.99 with a $1.00 trial period (subscription products only)\n * { amount: \"9.99\", taxCategory: \"saas\", trialAmount: \"1.00\" }\n */\nexport interface PriceInfo {\n /** Price amount as display string (e.g., \"9.99\" for USD, \"1000\" for JPY) */\n amount: string;\n /** Tax category */\n taxCategory: TaxCategory;\n /** Trial period price as display string; requires `metadata.trialDays` and must be lower than `amount` */\n trialAmount?: string;\n}\n\n/**\n * Multi-currency prices (keyed by ISO 4217 currency code).\n *\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n *\n * @example\n * {\n * \"USD\": { amount: \"9.99\", taxCategory: \"saas\" },\n * \"EUR\": { amount: \"8.99\", taxCategory: \"saas\" }\n * }\n */\nexport type Prices = Record<string, PriceInfo>;\n\n/**\n * Media asset (image or video).\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport interface MediaItem {\n /** Media type */\n type: `${MediaType}`;\n /** Asset URL */\n url: string;\n /** Alt text */\n alt?: string;\n /** Thumbnail URL */\n thumbnail?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Onetime Product — from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * One-time product detail (public API shape).\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport interface OnetimeProductDetail {\n id: string;\n storeId: string;\n name: string;\n description: string | null;\n prices: Prices;\n media: MediaItem[];\n successUrl: string | null;\n metadata: Record<string, unknown>;\n status: ProductVersionStatus;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Parameters for creating a one-time product.\n * @see docs/api-reference/endpoints/onetime-products/create-product.mdx\n */\nexport interface CreateOnetimeProductParams {\n storeId: string;\n name: string;\n prices: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Parameters for updating a one-time product (creates a new version; skips if unchanged).\n * @see docs/api-reference/endpoints/onetime-products/update-product.mdx\n */\nexport interface UpdateOnetimeProductParams {\n id: string;\n name?: string;\n prices?: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/** Parameters for publishing a one-time product's test version to production. */\nexport interface PublishOnetimeProductParams {\n /** Product ID */\n id: string;\n}\n\n/**\n * Parameters for updating a one-time product's status.\n * @see docs/api-reference/endpoints/onetime-products/update-status.mdx\n */\nexport interface UpdateOnetimeStatusParams {\n id: string;\n status: ProductVersionStatus;\n}\n\n// ---------------------------------------------------------------------------\n// Subscription Product — from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * Subscription product detail (public API shape).\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport interface SubscriptionProductDetail {\n id: string;\n storeId: string;\n name: string;\n description: string | null;\n billingPeriod: BillingPeriod;\n prices: Prices;\n media: MediaItem[];\n successUrl: string | null;\n metadata: Record<string, unknown>;\n status: ProductVersionStatus;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Parameters for creating a subscription product.\n * @see docs/api-reference/endpoints/subscription-products/create-product.mdx\n */\nexport interface CreateSubscriptionProductParams {\n storeId: string;\n name: string;\n billingPeriod: BillingPeriod;\n prices: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Parameters for updating a subscription product (creates a new version; skips if unchanged).\n * @see docs/api-reference/endpoints/subscription-products/update-product.mdx\n */\nexport interface UpdateSubscriptionProductParams {\n id: string;\n name?: string;\n billingPeriod?: BillingPeriod;\n prices?: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/** Parameters for publishing a subscription product's test version to production. */\nexport interface PublishSubscriptionProductParams {\n /** Product ID */\n id: string;\n}\n\n/**\n * Parameters for updating a subscription product's status.\n * @see docs/api-reference/endpoints/subscription-products/update-status.mdx\n */\nexport interface UpdateSubscriptionStatusParams {\n id: string;\n status: ProductVersionStatus;\n}\n\n// ---------------------------------------------------------------------------\n// Subscription Product Group — from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * Group rules for subscription product groups.\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport interface GroupRules {\n /** Whether trial period is shared across products in the group */\n sharedTrial: boolean;\n}\n\n/**\n * Subscription product group entity.\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport interface SubscriptionProductGroup {\n id: string;\n storeId: string;\n name: string;\n description: string | null;\n rules: GroupRules;\n productIds: string[];\n environment: Environment;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Parameters for creating a subscription product group.\n * @see docs/api-reference/endpoints/subscription-products/create-group.mdx\n */\nexport interface CreateSubscriptionProductGroupParams {\n storeId: string;\n name: string;\n description?: string;\n rules?: GroupRules;\n productIds?: string[];\n}\n\n/**\n * Parameters for updating a subscription product group (`productIds` is a full replacement).\n * @see docs/api-reference/endpoints/subscription-products/update-group.mdx\n */\nexport interface UpdateSubscriptionProductGroupParams {\n id: string;\n name?: string;\n description?: string;\n rules?: GroupRules;\n productIds?: string[];\n}\n\n/** Parameters for hard-deleting a subscription product group. */\nexport interface DeleteSubscriptionProductGroupParams {\n /** Group ID */\n id: string;\n}\n\n/** Parameters for publishing a test-environment group to production (upsert). */\nexport interface PublishSubscriptionProductGroupParams {\n /** Group ID */\n id: string;\n}\n\n// ---------------------------------------------------------------------------\n// Order — from waffo-pancake-order-service\n// ---------------------------------------------------------------------------\n\n/** Parameters for canceling a subscription order. */\nexport interface CancelSubscriptionParams {\n /** Order ID */\n orderId: string;\n}\n\n/**\n * Result of canceling a subscription order.\n * @see docs/api-reference/endpoints/subscriptions/cancel-subscription.mdx\n */\nexport interface CancelSubscriptionResult {\n orderId: string;\n /** Status after cancellation (`\"canceled\"` or `\"canceling\"`) */\n status: `${SubscriptionOrderStatus}`;\n}\n\n/**\n * Customer billing details for checkout.\n * @see docs/api-reference/endpoints/orders/overview.mdx\n */\nexport interface BillingDetail {\n /** Country code (ISO 3166-1 alpha-2) */\n country: string;\n /** Whether this is a business purchase */\n isBusiness: boolean;\n /** Postal / ZIP code (required for US, at least one of postcode/state for CA) */\n postcode?: string;\n /** State / province code (at least one of state/postcode for CA) */\n state?: string;\n /** Business name (recommended for invoicing, does not affect tax calculation) */\n businessName?: string;\n /** Tax ID / VAT number (EU businesses: triggers reverse charge 0% when provided) */\n taxId?: string;\n}\n\n/**\n * Supported checkout cashier languages (IETF BCP 47 tags).\n *\n * The default language of the hosted checkout page. Pass one of these values as\n * {@link CreateCheckoutSessionParams.language}; the customer can still switch language\n * on the checkout page. Language×currency mismatches are rejected by the payment provider.\n */\nexport type CashierLanguage =\n | \"en\"\n | \"pt-BR\"\n | \"es-MX\"\n | \"id-ID\"\n | \"vi-VN\"\n | \"ru-RU\"\n | \"en-KE\"\n | \"es-PE\"\n | \"es-CO\"\n | \"es-CL\"\n | \"zh-Hant-TW\"\n | \"zh-Hant-HK\"\n | \"th-TH\"\n | \"ja-JP\"\n | \"en-NG\"\n | \"ko-KR\"\n | \"en-HK\"\n | \"zh-Hans-HK\"\n | \"pl-PL\"\n | \"tr-TR\"\n | \"zh-Hans\"\n | \"ms-MY\";\n\n/**\n * Payment methods that can be offered on the hosted checkout page.\n *\n * Availability depends on the product type × currency pair. One-time: `USD` supports all four;\n * `EUR` / `GBP` / `HKD` / `JPY` support `card` / `applepay` / `googlepay`; `CNY` supports `wechat`.\n * Subscription: `USD` / `EUR` / `GBP` / `HKD` / `JPY` support `card` / `applepay` / `googlepay`.\n * Currencies outside this matrix cannot be charged at all — checkout session creation is rejected with a 400.\n */\nexport type PaymentMethod = \"card\" | \"applepay\" | \"googlepay\" | \"wechat\";\n\n/**\n * Session-level price override, accepted with API Key authentication only.\n * For subscription products it replaces the regular period price; the trial price comes from the locked product version.\n * @see docs/api-reference/endpoints/orders/create-checkout-session.mdx\n */\nexport interface PriceSnapshot {\n /** Price amount as display string (e.g., \"9.99\" for USD, \"1000\" for JPY) */\n amount: string;\n /** Tax category */\n taxCategory: TaxCategory;\n}\n\n/**\n * Parameters for creating a checkout session.\n * @see docs/api-reference/endpoints/orders/create-checkout-session.mdx\n */\nexport interface CreateCheckoutSessionParams {\n /** Product ID */\n productId: string;\n /** Currency code (ISO 4217) */\n currency: string;\n /** Optional price snapshot override (reads from DB if omitted) */\n priceSnapshot?: PriceSnapshot;\n /** Trial toggle override (subscription only) */\n withTrial?: boolean;\n /** Pre-filled customer email */\n buyerEmail?: string;\n /**\n * Pre-filled billing details. Passing this couples the cashier to the order's billing country: it then offers\n * only that country's payment market and the customer cannot switch. The country that applies is the one on the\n * finished order, not the one you sent; a country outside the payment markets we cover applies no restriction.\n * Omit to leave the cashier unrestricted.\n */\n billingDetail?: BillingDetail;\n /** Redirect URL after successful payment */\n successUrl?: string;\n /** Session expiration in seconds (default: 45 minutes) */\n expiresInSeconds?: number;\n /** Dark mode override (true=dark, false=light, omit=use store default) */\n darkMode?: boolean;\n /** Custom metadata */\n metadata?: Record<string, string>;\n /** Order-side business identifier (max 128 chars); inherited by orders, payments, refunds */\n orderMerchantExternalId?: string;\n /**\n * Default language of the hosted checkout page ({@link CashierLanguage}, IETF BCP 47).\n * The customer can switch language on the checkout page. Omit to let the provider infer.\n */\n language?: CashierLanguage;\n /**\n * Whitelist — offer only these payment methods ({@link PaymentMethod}).\n * Every value must be supported by the product type × currency pair, otherwise the request is rejected.\n * Mutually exclusive with {@link CreateCheckoutSessionParams.excludePaymentMethods}.\n * Omit both to offer every method the currency supports.\n */\n includePaymentMethods?: PaymentMethod[];\n /**\n * Blacklist — offer every method the currency supports except these ({@link PaymentMethod}).\n * Values the currency does not offer are ignored, so one blacklist can be reused across currencies.\n * Mutually exclusive with {@link CreateCheckoutSessionParams.includePaymentMethods}.\n */\n excludePaymentMethods?: PaymentMethod[];\n}\n\n/** Result of creating a checkout session. */\nexport interface CheckoutSessionResult {\n /** Session ID */\n sessionId: string;\n /** URL to redirect the customer to */\n checkoutUrl: string;\n /** Session expiration time (ISO 8601 UTC) */\n expiresAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Customer self-service\n// ---------------------------------------------------------------------------\n\n/** Parameters for canceling a one-time order (customer-side). */\nexport interface CancelOnetimeOrderParams {\n /** Order ID */\n orderId: string;\n}\n\n/** Result of canceling a one-time order. */\nexport interface CancelOnetimeOrderResult {\n /** Order ID */\n orderId: string;\n /** Resulting status (`\"canceled\"`) */\n status: string;\n}\n\n/** Parameters for reactivating a subscription (customer-side). */\nexport interface ReactivateSubscriptionParams {\n /** Subscription order ID */\n orderId: string;\n}\n\n/** Result of reactivating a subscription. */\nexport interface ReactivateSubscriptionResult {\n /** Order ID */\n orderId: string;\n /** Resulting status (`\"active\"`) */\n status: string;\n}\n\n/** Requested refund amount. */\nexport interface RequestedAmount {\n /** Refund amount in display format (e.g., `\"29.00\"`) */\n amount: string;\n /** Currency code (ISO 4217) */\n currency: string;\n}\n\n/**\n * Per-version data for a refund ticket. Each ticket can be submitted/resubmitted\n * multiple times; this is the shape of a single submission.\n */\nexport interface RefundTicketVersionData {\n /** Refund reason supplied by the customer */\n reason: string;\n /** Requested refund amount; `null` if the version has no amount recorded */\n requestedAmount: RequestedAmount | null;\n}\n\n/** Parameters for creating a refund ticket (customer-side). */\nexport interface CreateRefundTicketParams {\n /** Payment ID to refund */\n paymentId: string;\n /** Reason for the refund request */\n reason: string;\n /** Requested refund amount */\n requestedAmount: RequestedAmount;\n /** Custom metadata */\n metadata?: Record<string, unknown>;\n /** Refund-ticket business-side identifier (max 128 chars); inherited by the executed refund on PSP success */\n refundTicketMerchantExternalId?: string;\n}\n\n/** Parameters for resubmitting a rejected refund ticket (customer-side). */\nexport interface ResubmitRefundTicketParams {\n /** Existing ticket ID */\n ticketId: string;\n /** Payment ID */\n paymentId: string;\n /** Updated reason */\n reason: string;\n /** Updated requested amount */\n requestedAmount: RequestedAmount;\n}\n\n/** Refund ticket entity returned from create/resubmit operations. */\nexport interface RefundTicket {\n /** Ticket ID */\n id: string;\n /** Ticket type (e.g., `\"refund\"`) */\n type: string;\n /** Ticket status (e.g., `\"pending\"`, `\"approved\"`, `\"rejected\"`) */\n status: string;\n /** Associated payment ID */\n subjectId: string;\n /** Submitter identifier (email or merchant ID) */\n submitterId: string;\n /** Submitter type (e.g., `\"customer\"`, `\"merchant\"`) */\n submitterType: string;\n /** Current version ID */\n currentVersionId: string | null;\n /** Reviewer ID (null if not yet reviewed) */\n reviewerId: string | null;\n /** Review timestamp (ISO 8601, null if not yet reviewed) */\n reviewedAt: string | null;\n /** Reviewer's note */\n reviewNote: string | null;\n /** Rejection reason (null if approved or pending) */\n rejectReason: string | null;\n /** Execution timestamp (ISO 8601, null if not yet executed) */\n executedAt: string | null;\n /** Custom metadata */\n metadata: Record<string, unknown>;\n /** Refund-ticket business-side identifier (max 128 chars, immutable across resubmits) */\n refundTicketMerchantExternalId: string | null;\n /** Current version number */\n versionNumber: number | null;\n /** Current (latest) version data */\n versionData: RefundTicketVersionData | null;\n /** Creation timestamp (ISO 8601) */\n createdAt: string;\n /** Last update timestamp (ISO 8601) */\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Checkout — convenience wrappers\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for anonymous checkout.\n *\n * The customer reaches the checkout page without a session token. Merchants may still\n * pre-fill `buyerEmail` and `billingDetail`; omitting them leaves the form blank.\n *\n * Accepts every field of {@link CreateCheckoutSessionParams} — this wrapper simply\n * forwards the params unchanged to `/v1/actions/checkout/create-session`.\n *\n * @example\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n * // Redirect to result.checkoutUrl\n */\nexport type AnonymousCheckoutParams = CreateCheckoutSessionParams;\n\n/**\n * Parameters for authenticated checkout.\n *\n * Merges the checkout-session fields ({@link CreateCheckoutSessionParams}) with the\n * extra `buyerIdentity` required by `issue-session-token`. The wrapper splits the\n * input: `buyerIdentity` goes to the token call; everything else (including\n * `buyerEmail`) goes to the create-session call. The two fields are independent.\n *\n * @example\n * const result = await client.checkout.authenticated.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerIdentity: \"user-123\", // merchant-side customer id (goes into JWT)\n * buyerEmail: \"customer@example.com\", // pre-filled on the checkout page\n * });\n * // Redirect to result.checkoutUrl (includes #token=...)\n */\nexport interface AuthenticatedCheckoutParams extends CreateCheckoutSessionParams {\n /**\n * Customer identity — sent to `issue-session-token` and encoded into the JWT\n * payload for merchant-side customer identification. Accepts an email or any\n * merchant-provided identifier string. Use `buyerEmail` to pre-fill the\n * checkout page's email input.\n */\n buyerIdentity: string;\n}\n\n/**\n * Result of an authenticated checkout creation.\n *\n * Extends the base session result with the issued token details.\n */\nexport interface AuthenticatedCheckoutResult {\n /** Session ID */\n sessionId: string;\n /** Checkout URL with session token appended as URL fragment (`#token=...`) */\n checkoutUrl: string;\n /** Session expiration time (ISO 8601 UTC) */\n expiresAt: string;\n /** Issued JWT token */\n token: string;\n /** Token expiration time (ISO 8601 UTC) */\n tokenExpiresAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// GraphQL\n// ---------------------------------------------------------------------------\n\n/** Parameters for a GraphQL query. */\nexport interface GraphQLParams {\n /** GraphQL query string */\n query: string;\n /** Query variables */\n variables?: Record<string, unknown>;\n}\n\n/**\n * GraphQL response envelope. Same shape as {@link Envelope}, but `errors` entries\n * may additionally carry `locations` and `path` (graphql-js fields). The `layer`\n * field is optional on GraphQL because resolver errors don't carry one.\n */\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data: T | null;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: string[];\n aiHint?: string;\n /** Service stage that produced the error (\"graphql\", \"gateway\"). Resolver errors omit it. */\n layer?: string;\n }>;\n warnings?: Notice[];\n}\n\n// ---------------------------------------------------------------------------\n// Webhook\n// ---------------------------------------------------------------------------\n\n/**\n * Webhook event types.\n * @see docs/api-reference/webhooks.mdx\n */\nexport enum WebhookEventType {\n /** One-time order first payment succeeded */\n OrderCompleted = \"order.completed\",\n /** Subscription first payment succeeded (newly activated) */\n SubscriptionActivated = \"subscription.activated\",\n /** Subscription renewal payment succeeded */\n SubscriptionPaymentSucceeded = \"subscription.payment_succeeded\",\n /** Customer initiated cancellation (expires at end of current period) */\n SubscriptionCanceling = \"subscription.canceling\",\n /** Customer withdrew cancellation (subscription restored) */\n SubscriptionUncanceled = \"subscription.uncanceled\",\n /** Subscription product changed (upgrade/downgrade) */\n SubscriptionUpdated = \"subscription.updated\",\n /** Subscription fully terminated */\n SubscriptionCanceled = \"subscription.canceled\",\n /** Renewal payment failed (past due) */\n SubscriptionPastDue = \"subscription.past_due\",\n /** Refund succeeded */\n RefundSucceeded = \"refund.succeeded\",\n /** Refund failed */\n RefundFailed = \"refund.failed\",\n}\n\n/**\n * Common data fields in a webhook event payload.\n * @see docs/api-reference/webhooks.mdx\n */\nexport interface WebhookEventData {\n // Order\n orderId: string;\n /** Order status (e.g., \"completed\", \"active\", \"canceling\") */\n orderStatus?: string;\n buyerEmail: string;\n /** Merchant-provided customer identity from checkout session */\n merchantProvidedBuyerIdentity?: string;\n /** Order business identifier; present on order/payment + refund events (inherited from order) */\n orderMerchantExternalId?: string;\n /** Refund-ticket business identifier; only present on refund.* events */\n refundTicketMerchantExternalId?: string;\n currency: string;\n /** Billing/shipping address (structured object) */\n billingDetail?: Record<string, unknown>;\n /** Order-level metadata from checkout session (flat key-value pairs) */\n orderMetadata?: Record<string, string>;\n\n // Amount\n /** Amount as display string (e.g., \"9.99\" for USD, \"1000\" for JPY) */\n amount: string;\n /** Tax amount as display string (e.g., \"0.91\" for USD) */\n taxAmount: string;\n /** Tax rate as decimal (e.g., 0.1 for 10%) */\n taxRate?: number;\n /** Tax name (e.g., \"Consumption Tax\") */\n taxName?: string;\n /** Subtotal as display string (before tax) */\n subtotal?: string;\n /** Total as display string (after tax) */\n total?: string;\n\n // Product\n productName: string;\n /** Product description */\n productDescription?: string;\n /** Product-level metadata set when creating/updating the product */\n productMetadata?: Record<string, string>;\n\n // Payment (present for payment events: order.completed, subscription.payment_succeeded)\n /** Payment ID */\n paymentId?: string;\n /** Payment status (e.g., \"succeeded\", \"failed\") */\n paymentStatus?: string;\n /** Payment method type (e.g., \"card\") */\n paymentMethod?: string;\n /** Last 4 digits of payment instrument */\n paymentLast4?: string;\n /** Payment failure reason (present when payment failed) */\n paymentFailureReason?: string;\n /** Payment date (ISO 8601 date, e.g., \"2026-04-18\") */\n paymentDate?: string;\n\n // Subscription (present for subscription events)\n /** Billing period: \"weekly\", \"monthly\", \"quarterly\", \"yearly\" */\n billingPeriod?: string;\n /** Current billing period start date (ISO 8601, e.g., \"2026-04-01\") */\n currentPeriodStart?: string;\n /** Current billing period end date (ISO 8601, e.g., \"2026-05-01\") */\n currentPeriodEnd?: string;\n /** Subscription cancellation timestamp (ISO 8601, present when canceled) */\n canceledAt?: string;\n\n // Refund (present for refund events: refund.succeeded, refund.failed)\n /** Refund status (e.g., \"succeeded\", \"failed\") */\n refundStatus?: string;\n /** Refund reason */\n refundReason?: string;\n /** Refund creation timestamp (ISO 8601) */\n refundCreatedAt?: string;\n}\n\n/**\n * Webhook event payload.\n *\n * @see docs/api-reference/webhooks.mdx\n *\n * @example\n * {\n * id: \"550e8400-...\",\n * timestamp: \"2026-03-10T08:30:00.000Z\",\n * eventType: \"order.completed\",\n * eventId: \"PAY_5xK9mRtYvWnPqLsJ3hBfDe\",\n * storeId: \"STO_2aUyqjCzEIiEcYMKj7TZtw\",\n * storeName: \"My Store\",\n * mode: \"prod\",\n * data: { orderId: \"...\", buyerEmail: \"...\", currency: \"USD\", amount: \"29.00\", taxAmount: \"2.90\", productName: \"Pro Plan\", orderMetadata: { planId: \"pro\" } }\n * }\n */\nexport interface WebhookEvent<T = WebhookEventData> {\n /** Delivery record unique ID (UUID), usable for idempotent deduplication */\n id: string;\n /** Event timestamp (ISO 8601 UTC) */\n timestamp: string;\n /** Event type */\n eventType: `${WebhookEventType}` | (string & {});\n /** Business event ID (e.g. payment ID, order ID) */\n eventId: string;\n /** Store ID the event belongs to */\n storeId: string;\n /** Store name */\n storeName: string;\n /** Environment identifier */\n mode: `${Environment}`;\n /** Event data */\n data: T;\n}\n\n/**\n * Webhook public key configuration.\n *\n * - `string` — single key used for both test and prod environments\n * - `{ test?, prod? }` — per-environment keys\n */\nexport type WebhookPublicKeys = string | { test?: string; prod?: string };\n\n/** Options for {@link verifyWebhook}. */\nexport interface VerifyWebhookOptions {\n /**\n * Specify which environment's public key to use for verification.\n * When omitted, both keys are tried automatically (prod first).\n * Ignored when `publicKey` is provided.\n */\n environment?: `${Environment}`;\n /**\n * How far in the past a signature timestamp may be, in milliseconds.\n * Set to 0 to skip timestamp checking entirely (this also skips\n * {@link futureToleranceMs}).\n *\n * The default covers the full delivery retry schedule: the timestamp is\n * stamped before the first attempt and retries reuse it, so the last retry\n * arrives with a timestamp as old as the schedule itself.\n *\n * @default 2700000 (45 minutes)\n */\n toleranceMs?: number;\n /**\n * How far in the future a signature timestamp may be, in milliseconds.\n * Only clock skew on the receiving server puts a timestamp ahead of now, so\n * this stays tight — it matches the gateway's API Key check.\n *\n * Ignored when `toleranceMs` is 0.\n *\n * @default 60000 (1 minute)\n */\n futureToleranceMs?: number;\n /**\n * Per-call public key override (highest priority).\n * When provided, skips all other key resolution (config, env vars, built-in).\n */\n publicKey?: string;\n /**\n * Config-level public key(s) for the resolution chain.\n * When using `client.webhooks.verify()`, this is set automatically from `WaffoPancakeConfig.webhookPublicKey`.\n * When using the standalone `verifyWebhook()`, you can pass this directly for config-level key injection.\n *\n * Resolution order per environment:\n * 1. `publicKey` (per-call override)\n * 2. `publicKeys[env]` or `publicKeys` (config)\n * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` (env var)\n * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` (env var)\n * 5. Built-in hardcoded key\n */\n publicKeys?: WebhookPublicKeys;\n}\n\n// ---------------------------------------------------------------------------\n// Content Safety — from waffo-pancake-verification-service\n// ---------------------------------------------------------------------------\n\n/**\n * Content-safety scan verdict.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanAction {\n Allow = \"allow\",\n Review = \"review\",\n Block = \"block\",\n}\n\n/**\n * Scan verdict reason code.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanReasonCode {\n Allowed = \"allowed\",\n ReviewRequired = \"review_required\",\n RestrictedContent = \"restricted_content\",\n ServiceDegraded = \"service_degraded\",\n}\n\n/**\n * Matched content-safety policy category.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanPolicyCategory {\n CsamMinor = \"csam_minor\",\n SexualViolenceNonconsensual = \"sexual_violence_nonconsensual\",\n UndressTransform = \"undress_transform\",\n FaceSwapIdentity = \"face_swap_identity\",\n BestialityRestricted = \"bestiality_restricted\",\n AdultNsfw = \"adult_nsfw\",\n}\n\n/**\n * Semantic scan channel mode.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanSemanticMode {\n Off = \"off\",\n Shadow = \"shadow\",\n Enforce = \"enforce\",\n}\n\n/**\n * Semantic scan channel status.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanSemanticStatus {\n Disabled = \"disabled\",\n Scored = \"scored\",\n ShadowScored = \"shadow_scored\",\n SkippedRulesBlock = \"skipped_rules_block\",\n SkippedBudget = \"skipped_budget\",\n ProviderTimeout = \"provider_timeout\",\n ProviderError = \"provider_error\",\n}\n\n/** Parameters for scanning a prompt before AIGC generation. */\nexport interface ScanPromptParams {\n /** The user's text prompt to scan (1–10,000 characters). */\n prompt: string;\n /** Prompt text language (default \"en\"). */\n locale?: \"ja\" | \"en\" | \"zh\";\n /** How the external semantic channel participates. */\n semantic?: ScanSemanticMode;\n}\n\n/** Redacted scan verdict — no scores, thresholds, or keyword text. */\nexport interface ScanResult {\n /** Final verdict; continue only when `allow`. */\n action: ScanAction;\n /** Stable machine-readable reason. */\n reasonCode: ScanReasonCode;\n /** Matched policy categories; empty when allowed. */\n matchedCategories: ScanPolicyCategory[];\n /** Correlation id for support and appeals; safe to log. */\n requestId: string;\n /** Whether/how the semantic channel contributed to this scan. */\n semanticStatus: ScanSemanticStatus;\n}\n"],"mappings":"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","names":["createHash","DEFAULT_BASE_URL","createHash","Environment","TaxCategory","BillingPeriod","ProductVersionStatus","EntityStatus","StoreRole","OnetimeOrderStatus","SubscriptionOrderStatus","PaymentStatus","RefundTicketStatus","RefundStatus","MediaType","ErrorLayer","WebhookEventType","ScanAction","ScanReasonCode","ScanPolicyCategory","ScanSemanticMode","ScanSemanticStatus"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/customer-http-client.ts","../src/http-client.ts","../src/signing.ts","../src/resources/internal.ts","../src/validation.ts","../src/resources/auth.ts","../src/resources/checkout-anonymous.ts","../src/resources/checkout-authenticated.ts","../src/resources/checkout.ts","../src/resources/content-safety.ts","../src/resources/customer.ts","../src/resources/graphql.ts","../src/resources/onetime-products.ts","../src/resources/orders.ts","../src/resources/store-merchants.ts","../src/resources/stores.ts","../src/resources/subscription-product-groups.ts","../src/resources/subscription-products.ts","../src/webhooks.ts","../src/resources/webhooks.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["import type { ApiError } from \"./types.js\";\n\n/**\n * Error thrown when the API returns a non-success response.\n *\n * @example\n * try {\n * await client.stores.create({ name: \"My Store\" });\n * } catch (err) {\n * if (err instanceof WaffoPancakeError) {\n * console.log(err.status); // 400\n * console.log(err.errors[0]); // { message: \"...\", layer: \"store\" }\n * }\n * }\n */\nexport class WaffoPancakeError extends Error {\n readonly status: number;\n readonly errors: ApiError[];\n\n constructor(status: number, errors: ApiError[]) {\n const rootCause = errors[0]?.message ?? \"Unknown error\";\n super(rootCause);\n this.name = \"WaffoPancakeError\";\n this.status = status;\n this.errors = errors;\n }\n}\n","import { WaffoPancakeError } from \"./errors.js\";\n\nimport type { Environment, PostResult, WaffoPancakeConfig } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.waffo.ai\";\n\n/**\n * Internal HTTP client for customer-side requests using Bearer token authentication.\n *\n * Unlike {@link HttpClient} which signs requests with RSA-SHA256 (API Key auth),\n * this client attaches a session token as `Authorization: Bearer <token>` and\n * never sends an idempotency key (customer session actions are not protected by\n * gateway idempotency in the current architecture).\n *\n * Session tokens carry no environment of their own, so every request also sends\n * `X-Environment`. The gateway treats a Bearer credential without it as an\n * incomplete JWT header set and answers HTTP 400.\n *\n * Not exported publicly — used internally by {@link CustomerSession}.\n */\nexport class CustomerHttpClient {\n private readonly token: string;\n private readonly environment: `${Environment}`;\n private readonly baseUrl: string;\n private readonly _fetch: typeof fetch;\n\n constructor(token: string, environment: `${Environment}`, config: Pick<WaffoPancakeConfig, \"baseUrl\" | \"fetch\">) {\n this.token = token;\n this.environment = environment;\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Send a Bearer-authenticated POST and return the full envelope plus HTTP status.\n *\n * Sends `Authorization: Bearer <token>` and `X-Environment` — the gateway\n * requires both to accept a session token.\n *\n * Does NOT throw on `errors[]` or non-2xx status — caller inspects the result.\n * Throws {@link WaffoPancakeError} only when the response body is not valid JSON.\n */\n async post<T>(path: string, body: object): Promise<PostResult<T>> {\n const response = await this._fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.token}`,\n \"X-Environment\": this.environment,\n },\n body: JSON.stringify(body),\n });\n\n let envelope: { data: T | null; errors?: PostResult<T>[\"errors\"]; warnings?: PostResult<T>[\"warnings\"] };\n try {\n envelope = (await response.json()) as typeof envelope;\n } catch {\n throw new WaffoPancakeError(response.status, [{ message: `Non-JSON response from ${path}`, layer: \"sdk\" }]);\n }\n return { status: response.status, ...envelope };\n }\n}\n","import { createHash } from \"node:crypto\";\n\nimport { WaffoPancakeError } from \"./errors.js\";\nimport { normalizePrivateKey, signRequest } from \"./signing.js\";\n\nimport type { PostOptions, PostResult, WaffoPancakeConfig } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.waffo.ai\";\n\n/**\n * Internal HTTP client that auto-signs requests.\n *\n * The transport is intentionally thin: one {@link post} method that signs,\n * sends, and parses the {data, errors?, warnings?} envelope. It does NOT\n * unwrap `data`, throw on `errors[]`, or hide `warnings` — those are policy\n * choices that belong to the resource layer. See handbook\n * `coding-standards/code-style-guide/command-layer.md`.\n *\n * The `X-Merchant-Id` header is sent in `MER_{base62}` format as provided\n * by the user. The gateway decodes it to a raw UUID before forwarding.\n *\n * Not exported publicly — used by resource classes via {@link WaffoPancake}.\n */\nexport class HttpClient {\n private readonly merchantId: string;\n private readonly privateKey: string;\n private readonly baseUrl: string;\n private readonly _fetch: typeof fetch;\n\n constructor(config: WaffoPancakeConfig) {\n this.merchantId = config.merchantId;\n this.privateKey = normalizePrivateKey(config.privateKey);\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Send a signed POST and return the full envelope plus HTTP status.\n *\n * Behavior:\n * - Builds RSA-SHA256 signature (`X-Merchant-Id` / `X-Timestamp` / `X-Signature`)\n * - Attaches `X-Idempotency-Key` (deterministic `sha256(merchantId + path + body)`)\n * unless `options.noIdempotency` is set\n * - When `options.idempotencyWindow` is set, a floored timestamp is mixed into the\n * key so identical params produce a new key after the window elapses\n * - Does NOT throw on `errors[]` or non-2xx status — caller inspects the result\n * - Throws {@link WaffoPancakeError} only on transport failures (non-JSON body)\n *\n * @param path - API path (e.g. `/v1/actions/store/create-store`, `/v1/graphql`)\n * @param body - Request body object\n * @param options - Optional settings\n * @returns Parsed envelope with HTTP status\n * @throws {WaffoPancakeError} When the response body is not valid JSON\n */\n async post<T>(path: string, body: object, options?: PostOptions): Promise<PostResult<T>> {\n const bodyStr = JSON.stringify(body);\n const timestampSec = Math.floor(Date.now() / 1000);\n const timestamp = timestampSec.toString();\n const signature = signRequest(\"POST\", path, timestamp, bodyStr, this.privateKey);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-Merchant-Id\": this.merchantId,\n \"X-Timestamp\": timestamp,\n \"X-Signature\": signature,\n };\n if (!options?.noIdempotency) {\n headers[\"X-Idempotency-Key\"] = computeIdempotencyKey(this.merchantId, path, bodyStr, timestampSec, options);\n }\n\n const response = await this._fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers,\n body: bodyStr,\n });\n\n let envelope: { data: T | null; errors?: PostResult<T>[\"errors\"]; warnings?: PostResult<T>[\"warnings\"] };\n try {\n envelope = (await response.json()) as typeof envelope;\n } catch {\n throw new WaffoPancakeError(response.status, [{ message: `Non-JSON response from ${path}`, layer: \"sdk\" }]);\n }\n return { status: response.status, ...envelope };\n }\n}\n\nfunction computeIdempotencyKey(merchantId: string, path: string, bodyStr: string, timestampSec: number, options?: PostOptions): string {\n const base = `${merchantId}:${path}:${bodyStr}`;\n const input = options?.idempotencyWindow ? `${base}:${Math.floor(timestampSec / options.idempotencyWindow)}` : base;\n return createHash(\"sha256\").update(input).digest(\"hex\");\n}\n","import { createHash, createPrivateKey, createPublicKey, createSign } from \"node:crypto\";\n\nconst PKCS8_HEADER = \"-----BEGIN PRIVATE KEY-----\";\nconst PKCS8_FOOTER = \"-----END PRIVATE KEY-----\";\nconst PKCS1_HEADER = \"-----BEGIN RSA PRIVATE KEY-----\";\nconst PKCS1_FOOTER = \"-----END RSA PRIVATE KEY-----\";\n\nconst SPKI_HEADER = \"-----BEGIN PUBLIC KEY-----\";\nconst SPKI_FOOTER = \"-----END PUBLIC KEY-----\";\nconst PKCS1_PUB_HEADER = \"-----BEGIN RSA PUBLIC KEY-----\";\nconst PKCS1_PUB_FOOTER = \"-----END RSA PUBLIC KEY-----\";\n\n/**\n * Normalize a PEM private key string into a valid PEM format.\n *\n * Handles common issues:\n * - Literal `\\n` from environment variables (e.g. `PRIVATE_KEY=\"-----BEGIN...\\\\n...\"`)\n * - Windows-style `\\r\\n` line endings\n * - Leading/trailing whitespace and blank lines\n * - Missing PEM header/footer (raw base64 input, assumed PKCS#8)\n * - Base64 content on a single line (re-wrapped to 64-char lines)\n * - PKCS#1 (`BEGIN RSA PRIVATE KEY`) accepted as-is\n *\n * @param raw - Private key string in any of the above formats\n * @returns A well-formed PEM string\n * @throws {Error} If the input is empty or contains no base64 content\n *\n * @example\n * // Env var with literal \\n\n * normalizePrivateKey(\"-----BEGIN PRIVATE KEY-----\\\\nMIIE...\\\\n-----END PRIVATE KEY-----\")\n *\n * @example\n * // Raw base64 without PEM wrapper\n * normalizePrivateKey(\"MIIEvQIBADANBgkqhki...\")\n */\nexport function normalizePrivateKey(raw: string): string {\n if (!raw || !raw.trim()) {\n throw new Error(\"Private key is empty. Provide an RSA private key in PEM format.\");\n }\n\n // 1. Replace literal \\n / \\r\\n with real newlines\n let pem = raw.replace(/\\\\n/g, \"\\n\").replace(/\\r\\n/g, \"\\n\");\n\n // 2. Trim leading/trailing whitespace\n pem = pem.trim();\n\n // 3. Detect whether PEM headers are present\n const hasPkcs8Header = pem.includes(PKCS8_HEADER);\n const hasPkcs1Header = pem.includes(PKCS1_HEADER);\n const hasHeader = hasPkcs8Header || hasPkcs1Header;\n\n if (hasHeader) {\n // Strip headers/footers, extract pure base64\n const base64 = pem\n .replace(/-----BEGIN (?:RSA )?PRIVATE KEY-----/g, \"\")\n .replace(/-----END (?:RSA )?PRIVATE KEY-----/g, \"\")\n .replace(/\\s+/g, \"\");\n\n if (!base64) {\n throw new Error(\"Private key contains PEM headers but no key data. Check the key content.\");\n }\n\n // Re-wrap to 64-char lines with the original header type\n const header = hasPkcs1Header ? PKCS1_HEADER : PKCS8_HEADER;\n const footer = hasPkcs1Header ? PKCS1_FOOTER : PKCS8_FOOTER;\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${header}\\n${wrapped}\\n${footer}`;\n } else {\n // No PEM header — treat as raw base64, wrap with PKCS#8 headers\n const base64 = pem.replace(/\\s+/g, \"\");\n\n if (!/^[A-Za-z0-9+/]+=*$/.test(base64)) {\n throw new Error(\"Private key is not valid PEM or base64. Expected an RSA private key in PEM format or raw base64.\");\n }\n\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${PKCS8_HEADER}\\n${wrapped}\\n${PKCS8_FOOTER}`;\n }\n\n // 4. Validate the key is actually parseable by Node.js crypto\n try {\n createPrivateKey(pem);\n } catch {\n throw new Error(\"Private key could not be parsed. Ensure it is a valid RSA private key in PKCS#8 or PKCS#1 (PEM) format.\");\n }\n\n return pem;\n}\n\n/**\n * Normalize a PEM public key string into a valid PEM format.\n *\n * Handles common issues:\n * - Literal `\\n` from environment variables\n * - Windows-style `\\r\\n` line endings\n * - Leading/trailing whitespace and blank lines\n * - Missing PEM header/footer (raw base64 input, assumed SPKI)\n * - Base64 content on a single line (re-wrapped to 64-char lines)\n * - PKCS#1 (`BEGIN RSA PUBLIC KEY`) accepted as-is\n *\n * @param raw - Public key string in any of the above formats\n * @returns A well-formed PEM string\n * @throws {Error} If the input is empty or contains no base64 content\n *\n * @example\n * // Env var with literal \\n\n * normalizePublicKey(\"-----BEGIN PUBLIC KEY-----\\\\nMIIB...\\\\n-----END PUBLIC KEY-----\")\n *\n * @example\n * // Raw base64 without PEM wrapper\n * normalizePublicKey(\"MIIBIjANBgkqhki...\")\n */\nexport function normalizePublicKey(raw: string): string {\n if (!raw || !raw.trim()) {\n throw new Error(\"Public key is empty. Provide an RSA public key in PEM format.\");\n }\n\n // 1. Replace literal \\n / \\r\\n with real newlines\n let pem = raw.replace(/\\\\n/g, \"\\n\").replace(/\\r\\n/g, \"\\n\");\n\n // 2. Trim leading/trailing whitespace\n pem = pem.trim();\n\n // 3. Detect whether PEM headers are present\n const hasSpkiHeader = pem.includes(SPKI_HEADER);\n const hasPkcs1PubHeader = pem.includes(PKCS1_PUB_HEADER);\n const hasHeader = hasSpkiHeader || hasPkcs1PubHeader;\n\n if (hasHeader) {\n // Strip headers/footers, extract pure base64\n const base64 = pem\n .replace(/-----BEGIN (?:RSA )?PUBLIC KEY-----/g, \"\")\n .replace(/-----END (?:RSA )?PUBLIC KEY-----/g, \"\")\n .replace(/\\s+/g, \"\");\n\n if (!base64) {\n throw new Error(\"Public key contains PEM headers but no key data. Check the key content.\");\n }\n\n // Re-wrap to 64-char lines with the original header type\n const header = hasPkcs1PubHeader ? PKCS1_PUB_HEADER : SPKI_HEADER;\n const footer = hasPkcs1PubHeader ? PKCS1_PUB_FOOTER : SPKI_FOOTER;\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${header}\\n${wrapped}\\n${footer}`;\n } else {\n // No PEM header — treat as raw base64, wrap with SPKI headers\n const base64 = pem.replace(/\\s+/g, \"\");\n\n if (!/^[A-Za-z0-9+/]+=*$/.test(base64)) {\n throw new Error(\"Public key is not valid PEM or base64. Expected an RSA public key in PEM format or raw base64.\");\n }\n\n const wrapped = base64.match(/.{1,64}/g)!.join(\"\\n\");\n pem = `${SPKI_HEADER}\\n${wrapped}\\n${SPKI_FOOTER}`;\n }\n\n // 4. Validate the key is actually parseable by Node.js crypto\n try {\n createPublicKey(pem);\n } catch {\n throw new Error(\"Public key could not be parsed. Ensure it is a valid RSA public key in SPKI or PKCS#1 (PEM) format.\");\n }\n\n return pem;\n}\n\n/**\n * Build canonical request string and sign with RSA-SHA256.\n *\n * Canonical request format:\n * METHOD\\nPATH\\nTIMESTAMP\\nSHA256(BODY)\n *\n * @param method - HTTP method (e.g. \"POST\")\n * @param path - Request path (e.g. \"/v1/actions/store/create-store\")\n * @param timestamp - Unix epoch seconds string\n * @param body - Serialized JSON body\n * @param privateKey - RSA private key in PEM format\n * @returns Base64-encoded RSA-SHA256 signature\n */\nexport function signRequest(method: string, path: string, timestamp: string, body: string, privateKey: string): string {\n const bodyHash = createHash(\"sha256\").update(body).digest(\"base64\");\n const canonicalRequest = `${method}\\n${path}\\n${timestamp}\\n${bodyHash}`;\n\n const sign = createSign(\"sha256\");\n sign.update(canonicalRequest);\n return sign.sign(privateKey, \"base64\");\n}\n","import { WaffoPancakeError } from \"../errors.js\";\n\nimport type { Notice, PostResult } from \"../types.js\";\n\n/**\n * Resource-layer helper: unwrap a REST write-action envelope.\n *\n * - Throws {@link WaffoPancakeError} when `errors[]` is non-empty\n * - Otherwise returns the data block merged with `warnings` (if any), so callers\n * can read structured `aiHint` notices alongside the typed result\n *\n * Use only for REST write endpoints where errors signal a failed action. Read\n * paths (e.g. GraphQL) should return the full envelope without unwrapping.\n *\n * @internal\n */\nexport function unwrapAction<T>(r: PostResult<T>): T & { warnings?: Notice[] } {\n if (r.errors?.length) {\n throw new WaffoPancakeError(r.status, r.errors);\n }\n return { ...(r.data as T), ...(r.warnings ? { warnings: r.warnings } : {}) };\n}\n","/**\n * Client-side input validation.\n *\n * These checks catch obviously invalid inputs before making a network request.\n * They do NOT validate data existence (e.g., whether a store/product actually exists).\n *\n * All validation errors throw `WaffoPancakeError` with `status: 400` and `layer: \"sdk\"`,\n * so developers can catch them uniformly with API errors.\n *\n * Not exported publicly — used internally by resource classes.\n */\n\nimport { WaffoPancakeError } from \"./errors.js\";\n\nconst SHORT_ID_REGEX = /^[A-Z]{2,5}_[0-9A-Za-z]{22}$/;\nconst CURRENCY_CODE_REGEX = /^[A-Z]{3}$/;\nconst COUNTRY_CODE_REGEX = /^[A-Z]{2}$/;\nconst AMOUNT_STRING_REGEX = /^\\d+(\\.\\d+)?$/;\n\nconst SHORT_ID_LABELS: Record<string, string> = {\n STO: \"Store\",\n PROD: \"Product\",\n ORD: \"Order\",\n PAY: \"Payment\",\n REF: \"Refund\",\n TKT: \"Ticket\",\n MER: \"Merchant\",\n};\n\nfunction fail(message: string): never {\n throw new WaffoPancakeError(400, [{ message, layer: \"sdk\" }]);\n}\n\n/**\n * Validate that a required field is present and non-empty.\n */\nexport function validateRequired(field: string, value: unknown): void {\n if (value === undefined || value === null) {\n fail(`Missing required field: ${field}`);\n }\n if (typeof value === \"string\" && value.trim() === \"\") {\n fail(`${field} cannot be empty`);\n }\n}\n\n/**\n * Validate Short ID format (`{PREFIX}_{base62}`).\n */\nexport function validateShortId(field: string, value: string, prefix: string): void {\n validateRequired(field, value);\n const label = SHORT_ID_LABELS[prefix] ?? prefix;\n if (!SHORT_ID_REGEX.test(value)) {\n fail(`Invalid ${field}: expected ${label} Short ID format (${prefix}_xxx), got \"${value}\"`);\n }\n if (!value.startsWith(`${prefix}_`)) {\n fail(`Invalid ${field}: expected ${prefix}_ prefix (${label}), got \"${value.split(\"_\")[0]}_\"`);\n }\n}\n\n/**\n * Validate ISO 4217 currency code format (3 uppercase letters).\n */\nexport function validateCurrencyCode(field: string, value: string): void {\n validateRequired(field, value);\n if (!CURRENCY_CODE_REGEX.test(value)) {\n fail(`Invalid ${field}: expected 3-letter ISO 4217 currency code (e.g., \"USD\"), got \"${value}\"`);\n }\n}\n\n/**\n * Validate that amount is a valid numeric string in display format.\n */\nexport function validateAmountString(field: string, value: string): void {\n validateRequired(field, value);\n if (!AMOUNT_STRING_REGEX.test(value)) {\n fail(`Invalid ${field}: expected numeric string in display format (e.g., \"9.99\", \"1000\"), got \"${value}\"`);\n }\n}\n\n/**\n * Validate that a value is one of the allowed enum values.\n */\nexport function validateEnum(field: string, value: string, allowed: string[]): void {\n validateRequired(field, value);\n if (!allowed.includes(value)) {\n fail(`Invalid ${field}: expected one of [${allowed.join(\", \")}], got \"${value}\"`);\n }\n}\n\n/**\n * Validate that an optional string does not exceed `max` characters.\n */\nexport function validateMaxLength(field: string, value: string | undefined, max: number): void {\n if (value !== undefined && value.length > max) {\n fail(`${field} must be at most ${max} characters, got ${value.length}`);\n }\n}\n\n/**\n * Validate that a value is a positive integer.\n */\nexport function validatePositiveInteger(field: string, value: number): void {\n if (!Number.isInteger(value) || value <= 0) {\n fail(`Invalid ${field}: expected positive integer, got ${value}`);\n }\n}\n\n/**\n * Validate ISO 3166-1 alpha-2 country code (2 uppercase letters).\n */\nexport function validateCountryCode(field: string, value: string): void {\n validateRequired(field, value);\n if (!COUNTRY_CODE_REGEX.test(value)) {\n fail(`Invalid ${field}: expected 2-letter ISO 3166-1 country code (e.g., \"US\"), got \"${value}\"`);\n }\n}\n\n/**\n * Validate Prices object — each currency key and price amount.\n */\nexport function validatePrices(field: string, prices: Record<string, { amount: string; taxCategory: string }>): void {\n validateRequired(field, prices);\n const entries = Object.entries(prices);\n if (entries.length === 0) {\n fail(`${field} must contain at least one currency`);\n }\n for (const [currency, info] of entries) {\n validateCurrencyCode(`${field}.${currency} (key)`, currency);\n validateAmountString(`${field}.${currency}.amount`, info.amount);\n validateRequired(`${field}.${currency}.taxCategory`, info.taxCategory);\n }\n}\n\n/**\n * Validate BillingDetail fields (when present).\n */\nexport function validateBillingDetail(detail: { country: string; isBusiness: boolean }): void {\n validateCountryCode(\"billingDetail.country\", detail.country);\n if (typeof detail.isBusiness !== \"boolean\") {\n fail(`Invalid billingDetail.isBusiness: expected boolean, got ${typeof detail.isBusiness}`);\n }\n}\n\n/**\n * Validate checkout session common fields.\n */\nexport function validateCheckoutCommon(params: {\n productId: string;\n currency: string;\n priceSnapshot?: { amount: string; taxCategory: string };\n billingDetail?: { country: string; isBusiness: boolean };\n expiresInSeconds?: number;\n orderMerchantExternalId?: string;\n}): void {\n validateShortId(\"productId\", params.productId, \"PROD\");\n validateCurrencyCode(\"currency\", params.currency);\n if (params.priceSnapshot) {\n validateAmountString(\"priceSnapshot.amount\", params.priceSnapshot.amount);\n validateRequired(\"priceSnapshot.taxCategory\", params.priceSnapshot.taxCategory);\n }\n if (params.billingDetail) {\n validateBillingDetail(params.billingDetail);\n }\n if (params.expiresInSeconds !== undefined) {\n validatePositiveInteger(\"expiresInSeconds\", params.expiresInSeconds);\n }\n validateMaxLength(\"orderMerchantExternalId\", params.orderMerchantExternalId, 128);\n}\n","import { WaffoPancakeError } from \"../errors.js\";\nimport { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { IssueSessionTokenParams, Notice, SessionToken } from \"../types.js\";\n\n/** Authentication resource — issue session tokens for customers. */\nexport class AuthResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Issue a session token for a customer.\n *\n * @param params - Token issuance parameters\n * @returns Issued session token with expiration\n *\n * @example\n * // By store ID\n * const { token, expiresAt } = await client.auth.issueSessionToken({\n * storeId: \"STO_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n *\n * @example\n * // By product ID (store derived automatically)\n * const { token, expiresAt } = await client.auth.issueSessionToken({\n * productId: \"PROD_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n */\n async issueSessionToken(params: IssueSessionTokenParams): Promise<SessionToken & { warnings?: Notice[] }> {\n if (!params.storeId && !params.productId) {\n throw new WaffoPancakeError(400, [{ message: \"Missing required field: provide storeId or productId\", layer: \"sdk\" }]);\n }\n if (params.storeId) {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n }\n if (params.productId) {\n validateShortId(\"productId\", params.productId, \"PROD\");\n }\n validateRequired(\"buyerIdentity\", params.buyerIdentity);\n return unwrapAction(await this.http.post<SessionToken>(\"/v1/actions/auth/issue-session-token\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateCheckoutCommon } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { AnonymousCheckoutParams, CheckoutSessionResult, Notice } from \"../types.js\";\n\n/**\n * Anonymous checkout — no customer identity provided.\n *\n * The customer reaches the checkout page without a session token. Merchants may still\n * pre-fill `buyerEmail` and `billingDetail` on the page by passing them here.\n * Internally creates a checkout session and returns the redirect URL.\n */\nexport class CheckoutAnonymousResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create an anonymous checkout session.\n *\n * @param params - Checkout parameters (no customer identity required)\n * @returns Session ID, checkout URL, and expiration\n *\n * @example\n * // Minimal — customer fills everything on the page\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * @example\n * // Pre-fill email + billing + attach business-side order reference\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerEmail: \"customer@example.com\",\n * billingDetail: { country: \"US\", isBusiness: false, postcode: \"10001\" },\n * orderMerchantExternalId: \"ORDER-2026-00891\",\n * });\n */\n async create(params: AnonymousCheckoutParams): Promise<CheckoutSessionResult & { warnings?: Notice[] }> {\n validateCheckoutCommon(params);\n return unwrapAction(\n await this.http.post<CheckoutSessionResult>(\"/v1/actions/checkout/create-session\", params, { idempotencyWindow: 60 }),\n );\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateCheckoutCommon, validateRequired } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { AuthenticatedCheckoutParams, AuthenticatedCheckoutResult, CheckoutSessionResult, Notice, SessionToken } from \"../types.js\";\n\n/**\n * Authenticated checkout — merchant provides customer identity.\n *\n * Issues a session token, creates a checkout session, and returns a\n * checkout URL with the token appended as a URL fragment (`#token=...`).\n * The checkout page reads the fragment to pre-fill customer information.\n */\nexport class CheckoutAuthenticatedResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create an authenticated checkout session.\n *\n * Behavior:\n * - Issues a session token via `issue-session-token` (receives `buyerIdentity` + `productId` only)\n * - Creates a checkout session via `create-session` (receives every other field unchanged)\n * - Appends the token to the checkout URL as a URL fragment (`#token=...`)\n *\n * `buyerIdentity` and `buyerEmail` are independent inputs: identity is for the JWT,\n * email is for pre-filling the checkout page. The SDK forwards each to its own endpoint.\n *\n * @param params - Checkout parameters including customer identity\n * @returns Session details with token-appended checkout URL\n *\n * @example\n * const result = await client.checkout.authenticated.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerIdentity: \"user-123\",\n * buyerEmail: \"customer@example.com\",\n * orderMerchantExternalId: \"ORDER-2026-00891\",\n * });\n * // Redirect to result.checkoutUrl (includes #token=...)\n */\n async create(params: AuthenticatedCheckoutParams): Promise<AuthenticatedCheckoutResult & { warnings?: Notice[] }> {\n validateCheckoutCommon(params);\n validateRequired(\"buyerIdentity\", params.buyerIdentity);\n const { buyerIdentity, ...sessionParams } = params;\n\n const [tokenResult, sessionResult] = await Promise.all([\n this.http.post<SessionToken>(\n \"/v1/actions/auth/issue-session-token\",\n {\n productId: params.productId,\n buyerIdentity,\n },\n { idempotencyWindow: 60 },\n ),\n this.http.post<CheckoutSessionResult>(\"/v1/actions/checkout/create-session\", sessionParams, { idempotencyWindow: 60 }),\n ]);\n\n const token = unwrapAction(tokenResult);\n const session = unwrapAction(sessionResult);\n const warnings: Notice[] = [...(token.warnings ?? []), ...(session.warnings ?? [])];\n\n return {\n sessionId: session.sessionId,\n checkoutUrl: `${session.checkoutUrl}#token=${token.token}`,\n expiresAt: session.expiresAt,\n token: token.token,\n tokenExpiresAt: token.expiresAt,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n}\n","import { CheckoutAnonymousResource } from \"./checkout-anonymous.js\";\nimport { CheckoutAuthenticatedResource } from \"./checkout-authenticated.js\";\nimport { unwrapAction } from \"./internal.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { CheckoutSessionResult, CreateCheckoutSessionParams, Notice } from \"../types.js\";\n\n/**\n * Checkout resource — create checkout sessions for payments.\n *\n * Provides two convenience sub-resources for the common checkout flows:\n * - `anonymous` — no customer identity, empty form\n * - `authenticated` — merchant provides customer identity, pre-filled form + token\n *\n * The low-level `createSession()` method is still available for full control.\n *\n * @example\n * // Anonymous checkout (no identity)\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * @example\n * // Authenticated checkout (with customer identity)\n * const result = await client.checkout.authenticated.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerIdentity: \"userIdInYourSystem\",\n * buyerEmail: \"customer@example.com\",\n * });\n * // result.checkoutUrl includes #token=...\n */\nexport class CheckoutResource {\n /** Anonymous checkout — no customer identity, empty form. */\n readonly anonymous: CheckoutAnonymousResource;\n /** Authenticated checkout — merchant provides customer identity. */\n readonly authenticated: CheckoutAuthenticatedResource;\n\n constructor(private readonly http: HttpClient) {\n this.anonymous = new CheckoutAnonymousResource(http);\n this.authenticated = new CheckoutAuthenticatedResource(http);\n }\n\n /**\n * Create a checkout session (low-level). Returns a URL to redirect the customer to.\n *\n * For most use cases, prefer `checkout.anonymous.create()` or\n * `checkout.authenticated.create()` which handle the full flow automatically.\n *\n * @param params - Checkout session parameters\n * @returns Session ID, checkout URL, and expiration\n *\n * @example\n * const session = await client.checkout.createSession({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerEmail: \"customer@example.com\",\n * });\n * // Redirect to session.checkoutUrl\n */\n async createSession(params: CreateCheckoutSessionParams): Promise<CheckoutSessionResult & { warnings?: Notice[] }> {\n return unwrapAction(\n await this.http.post<CheckoutSessionResult>(\"/v1/actions/checkout/create-session\", params, { idempotencyWindow: 60 }),\n );\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { ScanPromptParams, ScanResult } from \"../types.js\";\n\n/** Content safety resource — scan user prompts before AIGC generation. */\nexport class ContentSafetyResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Scan a user's text prompt for content-safety compliance before AIGC\n * generation. Call this before invoking your image/video model and continue\n * only when `action` is `allow`.\n *\n * Stateless — the check never stores prompt text. If the safety service is\n * briefly unavailable, the verdict fails closed to `review` so an\n * unmoderated prompt is never let through.\n *\n * @param params - Scan parameters (prompt required; locale / semantic optional)\n * @returns Redacted scan verdict\n *\n * @example\n * const verdict = await client.contentSafety.scanPrompt({ prompt: \"a cat riding a bike\" });\n * if (verdict.action !== \"allow\") {\n * // do not generate\n * }\n */\n async scanPrompt(params: ScanPromptParams): Promise<ScanResult> {\n validateRequired(\"prompt\", params.prompt);\n return unwrapAction(await this.http.post<ScanResult>(\"/v1/actions/verification/scan-prompt\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateAmountString, validateCurrencyCode, validateMaxLength, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { CustomerHttpClient } from \"../customer-http-client.js\";\nimport type {\n CancelOnetimeOrderParams,\n CancelOnetimeOrderResult,\n CancelSubscriptionParams,\n CancelSubscriptionResult,\n CreateRefundTicketParams,\n GraphQLParams,\n GraphQLResponse,\n Notice,\n ReactivateSubscriptionParams,\n ReactivateSubscriptionResult,\n RefundTicket,\n ResubmitRefundTicketParams,\n} from \"../types.js\";\n\n/**\n * Customer session — lets authenticated customers manage their own orders and subscriptions.\n *\n * Created via `client.customer(token)` using a session token issued by\n * `client.auth.issueSessionToken()`. All requests use Bearer token authentication.\n *\n * @example\n * const { token } = await client.auth.issueSessionToken({\n * storeId: \"STO_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n * const customer = client.customer(token);\n * await customer.cancelSubscription({ orderId: \"ORD_xxx\" });\n */\nexport class CustomerSession {\n /** GraphQL query access scoped to the customer's data. */\n readonly graphql: CustomerGraphQL;\n\n constructor(private readonly http: CustomerHttpClient) {\n this.graphql = new CustomerGraphQL(http);\n }\n\n /**\n * Cancel a subscription order.\n *\n * @param params - Order to cancel\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await customer.cancelSubscription({ orderId: \"ORD_xxx\" });\n * // status: \"canceled\" (was pending)\n * // or \"canceling\" (was active — stops at the end of the current period)\n * // or \"canceling\" (was past_due — stops immediately)\n */\n async cancelSubscription(params: CancelSubscriptionParams): Promise<CancelSubscriptionResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<CancelSubscriptionResult>(\"/v1/actions/subscription-order/cancel-order\", params));\n }\n\n /**\n * Cancel a one-time order (only while payment is still pending).\n *\n * @param params - Order to cancel\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await customer.cancelOnetimeOrder({ orderId: \"ORD_xxx\" });\n */\n async cancelOnetimeOrder(params: CancelOnetimeOrderParams): Promise<CancelOnetimeOrderResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<CancelOnetimeOrderResult>(\"/v1/actions/onetime-order/cancel-order\", params));\n }\n\n /**\n * Reactivate a subscription that is in `canceling` status.\n *\n * A subscription that had an unpaid charge at the moment cancellation was\n * requested is refused with 400 (`Subscription with an unpaid balance cannot\n * be reactivated`), which is worded differently from the 400 returned when\n * the order is not in `canceling` status. Cancelling a `past_due`\n * subscription always falls into the former category.\n *\n * @param params - Order to reactivate\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await customer.reactivateSubscription({ orderId: \"ORD_xxx\" });\n * // status: \"active\"\n */\n async reactivateSubscription(params: ReactivateSubscriptionParams): Promise<ReactivateSubscriptionResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<ReactivateSubscriptionResult>(\"/v1/actions/subscription-order/reactivate-order\", params));\n }\n\n /**\n * Submit a refund request for a payment.\n *\n * @param params - Refund ticket details\n * @returns Created refund ticket\n *\n * @example\n * const { ticket } = await customer.createRefundTicket({\n * paymentId: \"PAY_xxx\",\n * reason: \"Product not as described\",\n * requestedAmount: { amount: \"29.00\", currency: \"USD\" },\n * refundTicketMerchantExternalId: \"REF-2026-00891\",\n * });\n */\n async createRefundTicket(params: CreateRefundTicketParams): Promise<{ ticket: RefundTicket; warnings?: Notice[] }> {\n validateShortId(\"paymentId\", params.paymentId, \"PAY\");\n validateRequired(\"reason\", params.reason);\n validateAmountString(\"requestedAmount.amount\", params.requestedAmount.amount);\n validateCurrencyCode(\"requestedAmount.currency\", params.requestedAmount.currency);\n validateMaxLength(\"refundTicketMerchantExternalId\", params.refundTicketMerchantExternalId, 128);\n return unwrapAction(await this.http.post<{ ticket: RefundTicket }>(\"/v1/actions/refund-ticket/create-ticket\", params));\n }\n\n /**\n * Resubmit a previously rejected refund ticket with updated details.\n *\n * @param params - Updated ticket details\n * @returns Updated refund ticket\n *\n * @example\n * const { ticket } = await customer.resubmitRefundTicket({\n * ticketId: \"TKT_xxx\",\n * paymentId: \"PAY_xxx\",\n * reason: \"Updated reason with more detail\",\n * requestedAmount: { amount: \"29.00\", currency: \"USD\" },\n * });\n */\n async resubmitRefundTicket(params: ResubmitRefundTicketParams): Promise<{ ticket: RefundTicket; warnings?: Notice[] }> {\n validateShortId(\"ticketId\", params.ticketId, \"TKT\");\n validateShortId(\"paymentId\", params.paymentId, \"PAY\");\n validateRequired(\"reason\", params.reason);\n validateAmountString(\"requestedAmount.amount\", params.requestedAmount.amount);\n validateCurrencyCode(\"requestedAmount.currency\", params.requestedAmount.currency);\n return unwrapAction(await this.http.post<{ ticket: RefundTicket }>(\"/v1/actions/refund-ticket/resubmit-ticket\", params));\n }\n}\n\n/**\n * GraphQL access scoped to the customer's session token.\n */\nclass CustomerGraphQL {\n constructor(private readonly http: CustomerHttpClient) {}\n\n /**\n * Execute a GraphQL query scoped to the customer's data.\n *\n * @param params - GraphQL query and variables\n * @returns GraphQL response\n *\n * @example\n * const result = await customer.graphql.query({\n * query: `query { orders { id status } }`,\n * });\n */\n async query<T = Record<string, unknown>>(params: GraphQLParams): Promise<GraphQLResponse<T>> {\n validateRequired(\"query\", params.query);\n const result = await this.http.post<T>(\"/v1/graphql\", params);\n return { data: result.data, errors: result.errors, warnings: result.warnings };\n }\n}\n","import { validateRequired } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { GraphQLParams, GraphQLResponse } from \"../types.js\";\n\n/** GraphQL query resource (Query only, no Mutations). */\nexport class GraphQLResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Execute a GraphQL query (Query only, no Mutations).\n *\n * @param params - GraphQL query and optional variables\n * @returns GraphQL response with data and optional errors\n *\n * @example\n * const result = await client.graphql.query<{ stores: Array<{ id: string; name: string }> }>({\n * query: `query { stores { id name status } }`,\n * });\n * console.log(result.data?.stores);\n *\n * @example\n * const result = await client.graphql.query({\n * query: `query ($id: ID!) { onetimeProduct(id: $id) { id name prices } }`,\n * variables: { id: \"PROD_xxx\" },\n * });\n */\n async query<T = Record<string, unknown>>(params: GraphQLParams): Promise<GraphQLResponse<T>> {\n validateRequired(\"query\", params.query);\n const result = await this.http.post<T>(\"/v1/graphql\", params, { noIdempotency: true });\n return { data: result.data, errors: result.errors, warnings: result.warnings };\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateEnum, validatePrices, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n CreateOnetimeProductParams,\n Notice,\n OnetimeProductDetail,\n PublishOnetimeProductParams,\n UpdateOnetimeProductParams,\n UpdateOnetimeStatusParams,\n} from \"../types.js\";\n\n/** One-time product management resource. */\nexport class OnetimeProductsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a one-time product with multi-currency pricing.\n *\n * @param params - Product creation parameters\n * @returns Created product detail\n *\n * @example\n * const { product } = await client.onetimeProducts.create({\n * storeId: \"STO_xxx\",\n * name: \"E-Book\",\n * prices: { USD: { amount: \"29.00\", taxCategory: \"digital_goods\" } },\n * });\n */\n async create(params: CreateOnetimeProductParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"name\", params.name);\n validatePrices(\"prices\", params.prices);\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/create-product\", params));\n }\n\n /**\n * Update a one-time product. Creates a new version; skips if unchanged.\n *\n * @param params - Product update parameters (only `id` is required)\n * @returns Updated product detail\n *\n * @example\n * // Update only the name\n * const { product } = await client.onetimeProducts.update({\n * id: \"PROD_xxx\",\n * name: \"E-Book v2\",\n * });\n *\n * @example\n * // Update prices while preserving other fields\n * const { product } = await client.onetimeProducts.update({\n * id: \"PROD_xxx\",\n * prices: { USD: { amount: \"39.00\", taxCategory: \"digital_goods\" } },\n * });\n */\n async update(params: UpdateOnetimeProductParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n if (params.name !== undefined) validateRequired(\"name\", params.name);\n if (params.prices) validatePrices(\"prices\", params.prices);\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/update-product\", params));\n }\n\n /**\n * Publish a one-time product's test version to production.\n *\n * @param params - Product to publish\n * @returns Published product detail\n *\n * @example\n * const { product } = await client.onetimeProducts.publish({ id: \"PROD_xxx\" });\n */\n async publish(params: PublishOnetimeProductParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/publish-product\", params));\n }\n\n /**\n * Update a one-time product's status (active/inactive).\n *\n * @param params - Status update parameters\n * @returns Updated product detail\n *\n * @example\n * const { product } = await client.onetimeProducts.updateStatus({\n * id: \"PROD_xxx\",\n * status: ProductVersionStatus.Inactive,\n * });\n */\n async updateStatus(params: UpdateOnetimeStatusParams): Promise<{ product: OnetimeProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n validateEnum(\"status\", params.status, [\"active\", \"inactive\"]);\n return unwrapAction(await this.http.post<{ product: OnetimeProductDetail }>(\"/v1/actions/onetime-product/update-status\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { CancelSubscriptionParams, CancelSubscriptionResult, Notice } from \"../types.js\";\n\n/** Order management resource. */\nexport class OrdersResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Cancel a subscription order.\n *\n * - pending -> canceled (immediate, no PSP call)\n * - active/trialing -> canceling (PSP cancel scheduled for the end of the\n * current billing period; the subscription stays usable until then)\n * - past_due -> canceling (PSP cancel dispatched immediately; the billing\n * period has already lapsed, so nothing is left to use)\n *\n * In both canceling cases the terminal `canceled` status is written when the\n * PSP cancellation webhook arrives, not by this call.\n *\n * @param params - Order to cancel\n * @returns Order ID and resulting status\n *\n * @example\n * const { orderId, status } = await client.orders.cancelSubscription({\n * orderId: \"ORD_xxx\",\n * });\n * // status: \"canceled\" or \"canceling\"\n */\n async cancelSubscription(params: CancelSubscriptionParams): Promise<CancelSubscriptionResult & { warnings?: Notice[] }> {\n validateShortId(\"orderId\", params.orderId, \"ORD\");\n return unwrapAction(await this.http.post<CancelSubscriptionResult>(\"/v1/actions/subscription-order/cancel-order\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateEnum, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n AddMerchantParams,\n AddMerchantResult,\n Notice,\n RemoveMerchantParams,\n RemoveMerchantResult,\n UpdateRoleParams,\n UpdateRoleResult,\n} from \"../types.js\";\n\n/** Store merchant management resource (coming soon — endpoints return 501). */\nexport class StoreMerchantsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Add a merchant to a store.\n *\n * @param params - Merchant addition parameters\n * @returns Added merchant details\n *\n * @example\n * const result = await client.storeMerchants.add({\n * storeId: \"STO_xxx\",\n * email: \"member@example.com\",\n * role: \"admin\",\n * });\n */\n async add(params: AddMerchantParams): Promise<AddMerchantResult & { warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"email\", params.email);\n validateEnum(\"role\", params.role, [\"admin\", \"member\"]);\n return unwrapAction(await this.http.post<AddMerchantResult>(\"/v1/actions/store-merchant/add-merchant\", params));\n }\n\n /**\n * Remove a merchant from a store.\n *\n * @param params - Merchant removal parameters\n * @returns Removal confirmation\n *\n * @example\n * const result = await client.storeMerchants.remove({\n * storeId: \"STO_xxx\",\n * merchantId: \"MER_xxx\",\n * });\n */\n async remove(params: RemoveMerchantParams): Promise<RemoveMerchantResult & { warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateShortId(\"merchantId\", params.merchantId, \"MER\");\n return unwrapAction(await this.http.post<RemoveMerchantResult>(\"/v1/actions/store-merchant/remove-merchant\", params));\n }\n\n /**\n * Update a merchant's role in a store.\n *\n * @param params - Role update parameters\n * @returns Updated role details\n *\n * @example\n * const result = await client.storeMerchants.updateRole({\n * storeId: \"STO_xxx\",\n * merchantId: \"MER_xxx\",\n * role: \"member\",\n * });\n */\n async updateRole(params: UpdateRoleParams): Promise<UpdateRoleResult & { warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateShortId(\"merchantId\", params.merchantId, \"MER\");\n validateEnum(\"role\", params.role, [\"admin\", \"member\"]);\n return unwrapAction(await this.http.post<UpdateRoleResult>(\"/v1/actions/store-merchant/update-role\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type { CreateStoreParams, DeleteStoreParams, Notice, Store, UpdateStoreParams } from \"../types.js\";\n\n/** Store management resource — create, update, and delete stores. */\nexport class StoresResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a new store. Slug is auto-generated from the name.\n *\n * @param params - Store creation parameters\n * @returns Created store entity\n *\n * @example\n * const { store } = await client.stores.create({ name: \"My Store\" });\n */\n async create(params: CreateStoreParams): Promise<{ store: Store; warnings?: Notice[] }> {\n validateRequired(\"name\", params.name);\n return unwrapAction(await this.http.post<{ store: Store }>(\"/v1/actions/store/create-store\", params));\n }\n\n /**\n * Update an existing store's settings.\n *\n * Settings objects (`notificationSettings`, `checkoutSettings`) support\n * partial updates: omitted sub-fields keep existing values, `null` clears a\n * field. Pass the entire settings object as `null` to clear all fields.\n *\n * **BREAKING (2026-05)**: the legacy `webhookSettings` parameter is removed.\n * Use `client.webhooks.add / update / remove` to manage webhook endpoints,\n * and query the configured webhook list via GraphQL `Store.storeWebhooks`.\n *\n * @param params - Fields to update (only provided fields are changed)\n * @returns Updated store entity\n *\n * @example\n * // Update name\n * const { store } = await client.stores.update({\n * id: \"STO_xxx\",\n * name: \"Updated Name\",\n * });\n *\n * @example\n * // Toggle a notification preference\n * const { store } = await client.stores.update({\n * id: \"STO_xxx\",\n * notificationSettings: { emailOrderConfirmation: false },\n * });\n */\n async update(params: UpdateStoreParams): Promise<{ store: Store; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"STO\");\n return unwrapAction(await this.http.post<{ store: Store }>(\"/v1/actions/store/update-store\", params));\n }\n\n /**\n * Soft-delete a store. Only the owner can delete.\n *\n * @param params - Store to delete\n * @returns Deleted store entity (with `deletedAt` set)\n *\n * @example\n * const { store } = await client.stores.delete({ id: \"STO_xxx\" });\n */\n async delete(params: DeleteStoreParams): Promise<{ store: Store; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"STO\");\n return unwrapAction(await this.http.post<{ store: Store }>(\"/v1/actions/store/delete-store\", params));\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n CreateSubscriptionProductGroupParams,\n DeleteSubscriptionProductGroupParams,\n Notice,\n PublishSubscriptionProductGroupParams,\n SubscriptionProductGroup,\n UpdateSubscriptionProductGroupParams,\n} from \"../types.js\";\n\n/** Subscription product group management resource (shared trial, plan switching). */\nexport class SubscriptionProductGroupsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a subscription product group for shared-trial or plan switching.\n *\n * @param params - Group creation parameters\n * @returns Created group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.create({\n * storeId: \"STO_xxx\",\n * name: \"Pro Plans\",\n * rules: { sharedTrial: true },\n * productIds: [\"PROD_aaa\", \"PROD_bbb\"],\n * });\n */\n async create(params: CreateSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"name\", params.name);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/create-group\", params),\n );\n }\n\n /**\n * Update a subscription product group. `productIds` is a full replacement.\n *\n * @param params - Group update parameters\n * @returns Updated group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.update({\n * id: \"GRP_xxx\",\n * productIds: [\"PROD_aaa\", \"PROD_bbb\", \"PROD_ccc\"],\n * });\n */\n async update(params: UpdateSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/update-group\", params),\n );\n }\n\n /**\n * Hard-delete a subscription product group.\n *\n * @param params - Group to delete\n * @returns Deleted group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.delete({ id: \"GRP_xxx\" });\n */\n async delete(params: DeleteSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/delete-group\", params),\n );\n }\n\n /**\n * Publish a test-environment group to production (upsert).\n *\n * @param params - Group to publish\n * @returns Published group entity\n *\n * @example\n * const { group } = await client.subscriptionProductGroups.publish({ id: \"GRP_xxx\" });\n */\n async publish(params: PublishSubscriptionProductGroupParams): Promise<{ group: SubscriptionProductGroup; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(\n await this.http.post<{ group: SubscriptionProductGroup }>(\"/v1/actions/subscription-product-group/publish-group\", params),\n );\n }\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateEnum, validatePrices, validateRequired, validateShortId } from \"../validation.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n CreateSubscriptionProductParams,\n Notice,\n PublishSubscriptionProductParams,\n SubscriptionProductDetail,\n UpdateSubscriptionProductParams,\n UpdateSubscriptionStatusParams,\n} from \"../types.js\";\n\n/** Subscription product management resource. */\nexport class SubscriptionProductsResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a subscription product with billing period and multi-currency pricing.\n *\n * @param params - Product creation parameters\n * @returns Created product detail\n *\n * @example\n * const { product } = await client.subscriptionProducts.create({\n * storeId: \"STO_xxx\",\n * name: \"Pro Plan\",\n * billingPeriod: \"monthly\",\n * prices: { USD: { amount: \"9.99\", taxCategory: \"saas\" } },\n * });\n */\n async create(params: CreateSubscriptionProductParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"name\", params.name);\n validateEnum(\"billingPeriod\", params.billingPeriod, [\"weekly\", \"monthly\", \"quarterly\", \"yearly\"]);\n validatePrices(\"prices\", params.prices);\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/create-product\", params),\n );\n }\n\n /**\n * Update a subscription product. Creates a new version; skips if unchanged.\n *\n * @param params - Product update parameters (only `id` is required)\n * @returns Updated product detail\n *\n * @example\n * // Update only the name\n * const { product } = await client.subscriptionProducts.update({\n * id: \"PROD_xxx\",\n * name: \"Pro Plan v2\",\n * });\n *\n * @example\n * // Update prices and billing period\n * const { product } = await client.subscriptionProducts.update({\n * id: \"PROD_xxx\",\n * billingPeriod: \"yearly\",\n * prices: { USD: { amount: \"99.00\", taxCategory: \"saas\" } },\n * });\n */\n async update(params: UpdateSubscriptionProductParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n if (params.name !== undefined) validateRequired(\"name\", params.name);\n if (params.billingPeriod !== undefined)\n validateEnum(\"billingPeriod\", params.billingPeriod, [\"weekly\", \"monthly\", \"quarterly\", \"yearly\"]);\n if (params.prices) validatePrices(\"prices\", params.prices);\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/update-product\", params),\n );\n }\n\n /**\n * Publish a subscription product's test version to production.\n *\n * @param params - Product to publish\n * @returns Published product detail\n *\n * @example\n * const { product } = await client.subscriptionProducts.publish({ id: \"PROD_xxx\" });\n */\n async publish(params: PublishSubscriptionProductParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/publish-product\", params),\n );\n }\n\n /**\n * Update a subscription product's status (active/inactive).\n *\n * @param params - Status update parameters\n * @returns Updated product detail\n *\n * @example\n * const { product } = await client.subscriptionProducts.updateStatus({\n * id: \"PROD_xxx\",\n * status: ProductVersionStatus.Active,\n * });\n */\n async updateStatus(params: UpdateSubscriptionStatusParams): Promise<{ product: SubscriptionProductDetail; warnings?: Notice[] }> {\n validateShortId(\"id\", params.id, \"PROD\");\n validateEnum(\"status\", params.status, [\"active\", \"inactive\"]);\n return unwrapAction(\n await this.http.post<{ product: SubscriptionProductDetail }>(\"/v1/actions/subscription-product/update-status\", params),\n );\n }\n}\n","import { createVerify } from \"node:crypto\";\n\nimport { normalizePublicKey } from \"./signing.js\";\n\nimport type { VerifyWebhookOptions, WebhookEvent, WebhookPublicKeys } from \"./types.js\";\n\n/** Default tolerance: 5 minutes */\n/**\n * Replay-protection window for timestamps in the past.\n *\n * The signature timestamp is stamped once, before the first delivery attempt —\n * retries carry the original header, so by the last attempt the timestamp is as\n * old as the whole retry schedule (observed above 31 minutes). A window shorter\n * than that rejects legitimate retries. 45 minutes covers the schedule plus\n * clock skew on the receiving server.\n *\n * A window this wide does not make replay attacks cheap on its own: every event\n * carries a stable `id`, and handlers are expected to be idempotent on it.\n */\nconst DEFAULT_TOLERANCE_MS = 45 * 60 * 1000;\n\n/**\n * Replay-protection window for timestamps in the future, matching the gateway's\n * API Key check. Only clock skew puts a timestamp ahead of now, so this stays\n * tight.\n */\nconst DEFAULT_FUTURE_TOLERANCE_MS = 60 * 1000;\n\n/** Waffo Pancake test environment webhook verification public key. */\nconst TEST_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxnmRY6yMMA3lVqmAU6ZG\nb1sjL/+r/z6E+ZjkXaDAKiqOhk9rpazni0bNsGXwmftTPk9jy2wn+j6JHODD/WH/\nSCnSfvKkLIjy4Hk7BuCgB174C0ydan7J+KgXLkOwgCAxxB68t2tezldwo74ZpXgn\nF49opzMvQ9prEwIAWOE+kV9iK6gx/AckSMtHIHpUesoPDkldpmFHlB2qpf1vsFTZ\n5kD6DmGl+2GIVK01aChy2lk8pLv0yUMu18v44sLkO5M44TkGPJD9qG09wrvVG2wp\nOTVCn1n5pP8P+HRLcgzbUB3OlZVfdFurn6EZwtyL4ZD9kdkQ4EZE/9inKcp3c1h4\nxwIDAQAB\n-----END PUBLIC KEY-----`;\n\n/** Waffo Pancake production environment webhook verification public key. */\nconst PROD_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+xApdTIb4ua+DgZKQ54\niBsD82ybyhGCLRETONW4Jgbb3A8DUM1LqBk6r/CmTOCHqLalTQHNigvP3R5zkDNX\niRJz6gA4MJ/+8K0+mnEE2RISQzN+Qu65TNd6svb+INm/kMaftY4uIXr6y6kchtTJ\ndwnQhcKdAL2v7h7IFnkVelQsKxDdb2PqX8xX/qwd01iXvMcpCCaXovUwZsxH2QN5\nZKBTseJivbhUeyJCco4fdUyxOMHe2ybCVhyvim2uxAl1nkvL5L8RCWMCAV55LLo0\n9OhmLahz/DYNu13YLVP6dvIT09ZFBYU6Owj1NxdinTynlJCFS9VYwBgmftosSE1U\ndwIDAQAB\n-----END PUBLIC KEY-----`;\n\n/**\n * Parse `X-Waffo-Signature` header.\n *\n * Format: `t=<timestamp>,v1=<base64signature>`\n *\n * @returns Parsed `t` (timestamp string) and `v1` (base64 signature)\n */\nfunction parseSignatureHeader(header: string): { t: string; v1: string } {\n let t = \"\";\n let v1 = \"\";\n for (const pair of header.split(\",\")) {\n const eqIdx = pair.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const key = pair.slice(0, eqIdx).trim();\n const value = pair.slice(eqIdx + 1).trim();\n if (key === \"t\") t = value;\n else if (key === \"v1\") v1 = value;\n }\n return { t, v1 };\n}\n\n/**\n * Verify RSA-SHA256 signature against a public key.\n *\n * @param signatureInput - The string to verify (`${t}.${rawBody}`)\n * @param v1 - Base64-encoded signature\n * @param publicKey - PEM public key\n * @returns Whether the signature is valid\n */\nfunction rsaVerify(signatureInput: string, v1: string, publicKey: string): boolean {\n const verifier = createVerify(\"RSA-SHA256\");\n verifier.update(signatureInput);\n return verifier.verify(publicKey, v1, \"base64\");\n}\n\n/**\n * Resolve the public key for a given environment using the multi-level fallback chain.\n *\n * Resolution order:\n * 1. `configKeys[env]` or `configKeys` (if string) — from WaffoPancakeConfig\n * 2. `WAFFO_WEBHOOK_TEST_PUBLIC_KEY` / `WAFFO_WEBHOOK_PROD_PUBLIC_KEY` — env var per-env\n * 3. `WAFFO_WEBHOOK_PUBLIC_KEY` — env var shared\n * 4. Built-in hardcoded key\n *\n * @param env - Target environment\n * @param configKeys - Config-level public key(s)\n * @returns Resolved and normalized PEM public key\n */\nfunction resolveKeyForEnv(env: \"test\" | \"prod\", configKeys?: WebhookPublicKeys): string {\n // 1. Config-level key\n if (typeof configKeys === \"string\") {\n return normalizePublicKey(configKeys);\n }\n if (configKeys?.[env]) {\n return normalizePublicKey(configKeys[env]);\n }\n\n // 2. Environment variable (per-env)\n const envSpecific = env === \"test\" ? process.env.WAFFO_WEBHOOK_TEST_PUBLIC_KEY : process.env.WAFFO_WEBHOOK_PROD_PUBLIC_KEY;\n if (envSpecific) {\n return normalizePublicKey(envSpecific);\n }\n\n // 3. Environment variable (shared)\n const generic = process.env.WAFFO_WEBHOOK_PUBLIC_KEY;\n if (generic) {\n return normalizePublicKey(generic);\n }\n\n // 4. Built-in hardcoded key\n return env === \"test\" ? TEST_PUBLIC_KEY : PROD_PUBLIC_KEY;\n}\n\n/**\n * Verify and parse an incoming Waffo Pancake webhook event.\n *\n * Public key resolution (per environment):\n * 1. `options.publicKey` — per-call override (highest priority, skips all other resolution)\n * 2. `options.publicKeys[env]` or `options.publicKeys` (string) — config-level\n * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable\n * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable\n * 5. Built-in hardcoded key\n *\n * Behavior:\n * - Parses the `X-Waffo-Signature` header (`t=<timestamp>,v1=<base64sig>`)\n * - Builds signature input `${t}.${rawBody}` and verifies with RSA-SHA256\n * - When `environment` is not specified, tries prod key first, then test key\n * - Optional: checks timestamp to prevent replay attacks (default 5-minute tolerance)\n *\n * @param payload - Raw request body string (must be unparsed)\n * @param signatureHeader - Value of the `X-Waffo-Signature` header\n * @param options - Verification options\n * @returns Parsed webhook event\n * @throws Error if header is missing/malformed, signature is invalid, or timestamp is stale\n *\n * @example\n * // Express (use raw body!)\n * app.post(\"/webhooks\", express.raw({ type: \"application/json\" }), (req, res) => {\n * try {\n * const event = verifyWebhook(\n * req.body.toString(\"utf-8\"),\n * req.headers[\"x-waffo-signature\"] as string,\n * );\n * res.status(200).send(\"OK\");\n * handleEventAsync(event).catch(console.error);\n * } catch {\n * res.status(401).send(\"Invalid signature\");\n * }\n * });\n *\n * @example\n * // Next.js App Router\n * export async function POST(request: Request) {\n * const body = await request.text();\n * const sig = request.headers.get(\"x-waffo-signature\");\n * const event = verifyWebhook(body, sig);\n * // handle event ...\n * return new Response(\"OK\");\n * }\n *\n * @example\n * // Specify environment explicitly\n * const event = verifyWebhook(body, sig, { environment: \"prod\" });\n *\n * @example\n * // Disable replay protection\n * const event = verifyWebhook(body, sig, { toleranceMs: 0 });\n */\nexport function verifyWebhook<T = Record<string, unknown>>(\n payload: string,\n signatureHeader: string | undefined | null,\n options?: VerifyWebhookOptions,\n): WebhookEvent<T> {\n if (!signatureHeader) {\n throw new Error(\"Missing X-Waffo-Signature header\");\n }\n\n const { t, v1 } = parseSignatureHeader(signatureHeader);\n if (!t || !v1) {\n throw new Error(\"Malformed X-Waffo-Signature header: missing t or v1\");\n }\n\n // Replay protection — asymmetric, matching the gateway's API Key check\n const toleranceMs = options?.toleranceMs ?? DEFAULT_TOLERANCE_MS;\n if (toleranceMs > 0) {\n const timestampMs = Number(t);\n if (Number.isNaN(timestampMs)) {\n throw new Error(\"Invalid timestamp in X-Waffo-Signature header\");\n }\n const futureToleranceMs = options?.futureToleranceMs ?? DEFAULT_FUTURE_TOLERANCE_MS;\n const ageMs = Date.now() - timestampMs;\n if (ageMs > toleranceMs || ageMs < -futureToleranceMs) {\n throw new Error(\"Webhook timestamp outside tolerance window (possible replay attack)\");\n }\n }\n\n // RSA-SHA256 verification\n const signatureInput = `${t}.${payload}`;\n const directKey = options?.publicKey;\n\n if (directKey) {\n // Per-call override — highest priority, skip all resolution\n const normalizedKey = normalizePublicKey(directKey);\n if (!rsaVerify(signatureInput, v1, normalizedKey)) {\n throw new Error(\"Invalid webhook signature (custom key)\");\n }\n } else {\n const configKeys = options?.publicKeys;\n const env = options?.environment;\n\n if (env === \"test\" || env === \"prod\") {\n const key = resolveKeyForEnv(env, configKeys);\n if (!rsaVerify(signatureInput, v1, key)) {\n throw new Error(`Invalid webhook signature (${env} key)`);\n }\n } else {\n // Auto-detect: try prod first, then test\n const prodKey = resolveKeyForEnv(\"prod\", configKeys);\n if (!rsaVerify(signatureInput, v1, prodKey)) {\n const testKey = resolveKeyForEnv(\"test\", configKeys);\n if (!rsaVerify(signatureInput, v1, testKey)) {\n throw new Error(\"Invalid webhook signature (tried both prod and test keys)\");\n }\n }\n }\n }\n\n return JSON.parse(payload) as WebhookEvent<T>;\n}\n","import { unwrapAction } from \"./internal.js\";\nimport { validateRequired, validateShortId } from \"../validation.js\";\nimport { verifyWebhook } from \"../webhooks.js\";\n\nimport type { HttpClient } from \"../http-client.js\";\nimport type {\n AddWebhookParams,\n Notice,\n RemoveWebhookParams,\n StoreWebhook,\n UpdateWebhookParams,\n VerifyWebhookOptions,\n WebhookEvent,\n WebhookPublicKeys,\n} from \"../types.js\";\n\n/**\n * Webhook resource — manages webhook configurations (HTTP / Feishu / Discord\n * / Telegram / Slack) and verifies inbound webhook signatures.\n *\n * **Mutations only**: `add`, `update`, `remove` all hit POST endpoints.\n * To list a store's webhooks, use GraphQL `Store.storeWebhooks` via\n * `client.graphql.query`.\n *\n * Verification (`verify`) is a local cryptographic operation that does not\n * require API calls.\n */\nexport class WebhooksResource {\n /**\n * @param http - HTTP client (used for add/update/remove)\n * @param publicKeys - Optional config-level public key(s) from WaffoPancakeConfig\n */\n constructor(\n private readonly http: HttpClient,\n private readonly publicKeys: WebhookPublicKeys | undefined,\n ) {}\n\n /**\n * Add a webhook endpoint to a store.\n *\n * @param params - Webhook configuration\n * @returns Created webhook entity\n *\n * @example\n * // HTTP webhook (RSA-signed envelope, default)\n * const { webhook } = await client.webhooks.add({\n * storeId: \"STO_xxx\",\n * channel: \"http\",\n * url: \"https://example.com/webhook\",\n * events: [\"order.completed\", \"refund.succeeded\"],\n * testMode: false,\n * });\n *\n * @example\n * // Discord webhook (uses Discord embed format)\n * await client.webhooks.add({\n * storeId: \"STO_xxx\",\n * channel: \"discord\",\n * url: \"https://discord.com/api/webhooks/...\",\n * events: [\"order.completed\"],\n * testMode: false,\n * });\n *\n * @example\n * // Telegram bot — chat_id goes in `secret`; URL is the bot's sendMessage endpoint\n * await client.webhooks.add({\n * storeId: \"STO_xxx\",\n * channel: \"telegram\",\n * url: \"https://api.telegram.org/bot123:ABC/sendMessage\",\n * events: [\"order.completed\"],\n * testMode: false,\n * secret: \"8737101383\",\n * });\n */\n async add(params: AddWebhookParams): Promise<{ webhook: StoreWebhook; warnings?: Notice[] }> {\n validateShortId(\"storeId\", params.storeId, \"STO\");\n validateRequired(\"channel\", params.channel);\n validateRequired(\"url\", params.url);\n return unwrapAction(await this.http.post<{ webhook: StoreWebhook }>(\"/v1/actions/store/add-webhook\", params));\n }\n\n /**\n * Update an existing webhook (only `url`, `events`, and `secret` are mutable).\n *\n * `channel` and `testMode` cannot be changed — remove the webhook and\n * re-add it instead. URL changes must remain on the same channel host\n * whitelist.\n *\n * @param params - Fields to update\n * @returns Updated webhook entity\n *\n * @example\n * await client.webhooks.update({\n * id: \"11111111-2222-3333-4444-555555555555\",\n * events: [\"order.completed\", \"refund.succeeded\", \"subscription.canceled\"],\n * });\n */\n async update(params: UpdateWebhookParams): Promise<{ webhook: StoreWebhook; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(await this.http.post<{ webhook: StoreWebhook }>(\"/v1/actions/store/update-webhook\", params));\n }\n\n /**\n * Hard-delete a webhook. Historical `webhook_deliveries` rows are retained\n * (with `storeWebhookId` set to null) for audit purposes.\n *\n * @param params - Webhook to remove\n * @returns The removed webhook entity (snapshot before deletion)\n *\n * @example\n * await client.webhooks.remove({ id: \"11111111-...\" });\n */\n async remove(params: RemoveWebhookParams): Promise<{ webhook: StoreWebhook; warnings?: Notice[] }> {\n validateRequired(\"id\", params.id);\n return unwrapAction(await this.http.post<{ webhook: StoreWebhook }>(\"/v1/actions/store/remove-webhook\", params));\n }\n\n /**\n * Verify and parse an incoming webhook event.\n *\n * Key resolution order:\n * 1. `options.publicKey` — per-call override (highest priority)\n * 2. `config.webhookPublicKey[env]` or `config.webhookPublicKey` (string)\n * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` environment variable\n * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` environment variable\n * 5. Built-in hardcoded key\n *\n * @param payload - Raw request body string (must be unparsed)\n * @param signatureHeader - Value of the `X-Waffo-Signature` header\n * @param options - Verification options (optional)\n * @returns Parsed webhook event\n * @throws Error if signature is invalid, header is malformed, or timestamp is stale\n *\n * @example\n * const event = client.webhooks.verify(rawBody, signatureHeader);\n *\n * @example\n * // Specify environment\n * const event = client.webhooks.verify(rawBody, sig, { environment: \"test\" });\n *\n * @example\n * // Per-call key override\n * const event = client.webhooks.verify(rawBody, sig, { publicKey: oneOffKey });\n */\n verify<T = Record<string, unknown>>(\n payload: string,\n signatureHeader: string | undefined | null,\n options?: VerifyWebhookOptions,\n ): WebhookEvent<T> {\n const mergedOptions: VerifyWebhookOptions = {\n ...options,\n publicKeys: options?.publicKeys ?? this.publicKeys,\n };\n return verifyWebhook<T>(payload, signatureHeader, mergedOptions);\n }\n}\n","import { CustomerHttpClient } from \"./customer-http-client.js\";\nimport { WaffoPancakeError } from \"./errors.js\";\nimport { HttpClient } from \"./http-client.js\";\nimport { AuthResource } from \"./resources/auth.js\";\nimport { CheckoutResource } from \"./resources/checkout.js\";\nimport { ContentSafetyResource } from \"./resources/content-safety.js\";\nimport { CustomerSession } from \"./resources/customer.js\";\nimport { GraphQLResource } from \"./resources/graphql.js\";\nimport { OnetimeProductsResource } from \"./resources/onetime-products.js\";\nimport { OrdersResource } from \"./resources/orders.js\";\nimport { StoreMerchantsResource } from \"./resources/store-merchants.js\";\nimport { StoresResource } from \"./resources/stores.js\";\nimport { SubscriptionProductGroupsResource } from \"./resources/subscription-product-groups.js\";\nimport { SubscriptionProductsResource } from \"./resources/subscription-products.js\";\nimport { WebhooksResource } from \"./resources/webhooks.js\";\nimport { validateEnum, validateShortId } from \"./validation.js\";\n\nimport type { CustomerSessionOptions, WaffoPancakeConfig } from \"./types.js\";\n\n/**\n * Waffo Pancake TypeScript SDK client.\n *\n * Uses Merchant API Key (RSA-SHA256) authentication. All requests are\n * automatically signed — no manual header construction needed.\n *\n * @example\n * import { WaffoPancake } from \"@waffo/pancake-ts\";\n *\n * const client = new WaffoPancake({\n * merchantId: \"MER_2D5F8G3H1K4M6N9P0Q7R8S\", // MER_{base62} format\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n *\n * // Create a store — IDs are returned in {prefix}_{base62} format\n * const { store } = await client.stores.create({ name: \"My Store\" });\n * // => store.id = \"STO_...\"\n *\n * // Create a product\n * const { product } = await client.onetimeProducts.create({\n * storeId: store.id, // \"STO_...\"\n * name: \"E-Book\",\n * prices: { USD: { amount: \"29.00\", taxCategory: \"digital_goods\" } },\n * });\n * // => product.id = \"PROD_...\"\n *\n * // Create a checkout session\n * const session = await client.checkout.createSession({\n * productId: product.id,\n * currency: \"USD\",\n * });\n * // => redirect customer to session.checkoutUrl\n *\n * // Query data via GraphQL\n * const result = await client.graphql.query({\n * query: `query { stores { id name status } }`,\n * });\n *\n * @example\n * // Per-environment webhook public keys\n * const client = new WaffoPancake({\n * merchantId: \"...\",\n * privateKey: \"...\",\n * webhookPublicKey: {\n * test: process.env.WAFFO_TEST_PUB_KEY!,\n * prod: process.env.WAFFO_PROD_PUB_KEY!,\n * },\n * });\n * const event = client.webhooks.verify(rawBody, signatureHeader);\n */\nexport class WaffoPancake {\n private readonly http: HttpClient;\n private readonly config: WaffoPancakeConfig;\n\n readonly auth: AuthResource;\n readonly stores: StoresResource;\n readonly storeMerchants: StoreMerchantsResource;\n readonly onetimeProducts: OnetimeProductsResource;\n readonly subscriptionProducts: SubscriptionProductsResource;\n readonly subscriptionProductGroups: SubscriptionProductGroupsResource;\n readonly orders: OrdersResource;\n readonly checkout: CheckoutResource;\n readonly graphql: GraphQLResource;\n readonly webhooks: WebhooksResource;\n readonly contentSafety: ContentSafetyResource;\n\n constructor(config: WaffoPancakeConfig) {\n validateShortId(\"merchantId\", config.merchantId, \"MER\");\n this.config = config;\n this.http = new HttpClient(config);\n\n this.auth = new AuthResource(this.http);\n this.stores = new StoresResource(this.http);\n this.storeMerchants = new StoreMerchantsResource(this.http);\n this.onetimeProducts = new OnetimeProductsResource(this.http);\n this.subscriptionProducts = new SubscriptionProductsResource(this.http);\n this.subscriptionProductGroups = new SubscriptionProductGroupsResource(this.http);\n this.orders = new OrdersResource(this.http);\n this.checkout = new CheckoutResource(this.http);\n this.graphql = new GraphQLResource(this.http);\n this.webhooks = new WebhooksResource(this.http, config.webhookPublicKey);\n this.contentSafety = new ContentSafetyResource(this.http);\n }\n\n /**\n * Create a customer session for self-service operations.\n *\n * The returned session uses Bearer token authentication and provides\n * methods for order cancellation, subscription management, refund tickets,\n * and scoped GraphQL queries.\n *\n * Session tokens expire 5 minutes after issuance, so issue one right before\n * use rather than caching it.\n *\n * @param token - Session token from `client.auth.issueSessionToken()`\n * @param options - Per-session overrides\n * @returns A customer session with self-service methods\n * @throws {WaffoPancakeError} When no environment is available from either\n * `options.environment` or `WaffoPancakeConfig.environment`\n *\n * @example\n * const { token } = await client.auth.issueSessionToken({\n * storeId: \"STO_xxx\",\n * buyerIdentity: \"customer@example.com\",\n * });\n * const customer = client.customer(token, { environment: \"test\" });\n * await customer.cancelSubscription({ orderId: \"ORD_xxx\" });\n *\n * @example\n * // Set the environment once on the client instead\n * const client = new WaffoPancake({ merchantId, privateKey, environment: \"test\" });\n * const customer = client.customer(token);\n */\n customer(token: string, options?: CustomerSessionOptions): CustomerSession {\n const environment = options?.environment ?? this.config.environment;\n if (environment === undefined) {\n throw new WaffoPancakeError(400, [\n {\n message:\n \"Missing required field: environment — set it on the client config or pass client.customer(token, { environment: 'test' | 'prod' })\",\n layer: \"sdk\",\n },\n ]);\n }\n validateEnum(\"environment\", environment, [\"test\", \"prod\"]);\n\n const customerHttp = new CustomerHttpClient(token, environment, {\n baseUrl: this.config.baseUrl,\n fetch: this.config.fetch,\n });\n return new CustomerSession(customerHttp);\n }\n\n /**\n * Create a customer session for self-service operations.\n *\n * @param token - Session token from `client.auth.issueSessionToken()`\n * @param options - Per-session overrides\n * @returns A customer session with self-service methods\n *\n * @example\n * ```typescript\n * const session = client.buyer(token); // prefer client.customer(token)\n * ```\n *\n * @deprecated Use {@link WaffoPancake.customer} instead.\n */\n buyer(token: string, options?: CustomerSessionOptions): CustomerSession {\n return this.customer(token, options);\n }\n}\n","// ---------------------------------------------------------------------------\n// Client config\n// ---------------------------------------------------------------------------\n\nexport interface WaffoPancakeConfig {\n /** Merchant ID in `MER_{base62}` format (sent as X-Merchant-Id header) */\n merchantId: string;\n /** RSA private key in PEM format for request signing */\n privateKey: string;\n /** Base URL override (default: https://api.waffo.ai) */\n baseUrl?: string;\n /** Custom fetch implementation (default: global fetch) */\n fetch?: typeof fetch;\n /**\n * Environment that customer sessions operate in (sent as the `X-Environment`\n * header alongside the session token's Bearer credential).\n *\n * API Key requests do not need this — the gateway derives their environment\n * from the key itself. Session tokens carry no environment, so the gateway\n * requires the header and rejects the request with HTTP 400 without it.\n *\n * There is no default: a wrong guess would route the call to the other\n * environment. Supply it here, or per session via\n * {@link CustomerSessionOptions.environment}.\n *\n * @see {@link WaffoPancake.customer}\n */\n environment?: `${Environment}`;\n /**\n * Custom RSA public key(s) for webhook signature verification.\n *\n * - `string` — single key used for both test and prod environments\n * - `{ test?, prod? }` — per-environment keys\n *\n * Resolution order per environment: config key → env var → built-in key.\n * @see {@link VerifyWebhookOptions} for per-call overrides\n */\n webhookPublicKey?: WebhookPublicKeys;\n}\n\n/** Options for {@link WaffoPancake.customer}. */\nexport interface CustomerSessionOptions {\n /**\n * Environment this session operates in, overriding\n * {@link WaffoPancakeConfig.environment} for a single session.\n *\n * Required when the client config omits `environment`.\n */\n environment?: `${Environment}`;\n}\n\n// ---------------------------------------------------------------------------\n// Internal HTTP options\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link HttpClient.post}.\n * Not exported publicly — used by resource classes.\n */\nexport interface PostOptions {\n /**\n * Time window in seconds for idempotency key rotation.\n * When set, a floored timestamp is mixed into the key so identical params\n * produce a new key after the window elapses (e.g. 60 = per-minute dedup).\n */\n idempotencyWindow?: number;\n /**\n * Skip the X-Idempotency-Key header entirely. Set for read-only queries\n * (e.g. GraphQL) so the gateway's 24h idempotency cache does not serve\n * stale data on identical repeat queries.\n */\n noIdempotency?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// API response envelope\n// ---------------------------------------------------------------------------\n\n/**\n * Single Notice entry within `errors` or `warnings` arrays.\n *\n * Both REST and GraphQL envelopes use the same Notice shape. `aiHint` is the\n * structured migration instruction for LLM consumers (see handbook\n * `command-layer.md` aiHint four-line template).\n *\n * @example\n * { message: \"Store slug already exists\", layer: \"store\" }\n * @example\n * { message: \"webhookSettings field ignored\", layer: \"store\",\n * aiHint: \"Switch to client.webhooks.add / update / remove\" }\n */\nexport interface Notice {\n /** Human-readable message */\n message: string;\n /** Layer that produced this notice */\n layer: `${ErrorLayer}`;\n /** Structured migration / remediation instruction for LLM consumers */\n aiHint?: string;\n}\n\n/** @deprecated Use {@link Notice}. Kept for backwards compatibility with existing imports. */\nexport type ApiError = Notice;\n\n/**\n * API response envelope. Both REST writes and GraphQL queries return this shape:\n * - Success: `{ data: T }` (optionally with `warnings`)\n * - Failure: `{ data: null, errors: Notice[] }`\n * - Partial success (GraphQL only): `{ data: T, errors: Notice[] }`\n *\n * `errors` are ordered by call stack: `[0]` is the deepest layer, `[n]` is the outermost.\n *\n * See handbook `coding-standards/code-style-guide/command-layer.md` for the wire contract.\n */\nexport interface Envelope<T> {\n data: T | null;\n errors?: Notice[];\n warnings?: Notice[];\n}\n\n/** Transport-layer result: HTTP status plus the parsed envelope. */\nexport interface PostResult<T> extends Envelope<T> {\n /** HTTP status code from the response */\n status: number;\n}\n\n// ---------------------------------------------------------------------------\n// Enums (runtime-accessible values)\n// ---------------------------------------------------------------------------\n\n/**\n * Environment type.\n * @see docs/api-reference/authentication.mdx\n */\nexport enum Environment {\n Test = \"test\",\n Prod = \"prod\",\n}\n\n/**\n * Tax category for products.\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport enum TaxCategory {\n DigitalGoods = \"digital_goods\",\n SaaS = \"saas\",\n Software = \"software\",\n Ebook = \"ebook\",\n OnlineCourse = \"online_course\",\n Consulting = \"consulting\",\n ProfessionalService = \"professional_service\",\n}\n\n/**\n * Subscription billing period.\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport enum BillingPeriod {\n Weekly = \"weekly\",\n Monthly = \"monthly\",\n Quarterly = \"quarterly\",\n Yearly = \"yearly\",\n}\n\n/**\n * Product version status.\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport enum ProductVersionStatus {\n Active = \"active\",\n Inactive = \"inactive\",\n}\n\n/**\n * Store entity status.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport enum EntityStatus {\n Active = \"active\",\n Inactive = \"inactive\",\n Suspended = \"suspended\",\n}\n\n/**\n * Store member role.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport enum StoreRole {\n Owner = \"owner\",\n Admin = \"admin\",\n Member = \"member\",\n}\n\n/**\n * One-time order status.\n * @see docs/api-reference/endpoints/orders/overview.mdx\n */\nexport enum OnetimeOrderStatus {\n Pending = \"pending\",\n Completed = \"completed\",\n Canceled = \"canceled\",\n}\n\n/**\n * Subscription order status.\n *\n * State machine:\n * - pending -> active, canceled, closed (PSP CLOSE from never-activated)\n * - active -> canceling, past_due, canceled, expired\n * - canceling -> active, canceled\n * - past_due -> active, canceling, canceled\n * - closed -> terminal (never-activated subscription closed by PSP)\n * - canceled -> terminal\n * - expired -> terminal\n *\n * @see docs/api-reference/endpoints/subscriptions/overview.mdx\n */\nexport enum SubscriptionOrderStatus {\n Pending = \"pending\",\n Active = \"active\",\n Canceling = \"canceling\",\n PastDue = \"past_due\",\n Closed = \"closed\",\n Canceled = \"canceled\",\n Expired = \"expired\",\n}\n\n/**\n * Payment status.\n * @see docs/api-reference/endpoints/orders/overview.mdx\n */\nexport enum PaymentStatus {\n Pending = \"pending\",\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n Canceled = \"canceled\",\n}\n\n/**\n * Refund ticket status.\n * @see docs/api-reference/endpoints/refunds/overview.mdx\n */\nexport enum RefundTicketStatus {\n Pending = \"pending\",\n UnderReview = \"under_review\",\n Approved = \"approved\",\n Rejected = \"rejected\",\n Returned = \"returned\",\n Processing = \"processing\",\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n Cancelled = \"cancelled\",\n}\n\n/**\n * Refund status.\n * @see docs/api-reference/endpoints/refunds/overview.mdx\n */\nexport enum RefundStatus {\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n}\n\n/**\n * Media asset type.\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport enum MediaType {\n Image = \"image\",\n Video = \"video\",\n}\n\n/** Error layer identifier in the call stack. */\nexport enum ErrorLayer {\n Gateway = \"gateway\",\n User = \"user\",\n Store = \"store\",\n Product = \"product\",\n Order = \"order\",\n Ticket = \"ticket\",\n GraphQL = \"graphql\",\n Resource = \"resource\",\n /** SDK-specific layer for email delivery errors (not part of the service-side error layers). */\n Email = \"email\",\n /** SDK-side input validation (caught before network request). */\n Sdk = \"sdk\",\n}\n\n// ---------------------------------------------------------------------------\n// Auth\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for issuing a customer session token.\n *\n * Provide either `storeId` or `productId` (at least one required).\n * When `productId` is given without `storeId`, the server derives the store from the product.\n *\n * @see docs/api-reference/endpoints/auth/issue-session-token.mdx\n */\nexport interface IssueSessionTokenParams {\n /**\n * Customer identity — encoded into the JWT payload for merchant-side customer\n * identification. Accepts an email or any merchant-provided identifier string.\n * To pre-fill the checkout page's email field, use `buyerEmail` on\n * `checkout.authenticated.create`.\n */\n buyerIdentity: string;\n /** Store ID (optional when `productId` is provided) */\n storeId?: string;\n /** Product ID — used to derive the store when `storeId` is omitted */\n productId?: string;\n}\n\n/**\n * Issued session token response.\n *\n * @example\n * { token: \"eyJhbGciOi...\", expiresAt: \"2026-03-10T09:00:00.000Z\" }\n */\nexport interface SessionToken {\n /** JWT token string */\n token: string;\n /** Expiration time (ISO 8601 UTC) */\n expiresAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Store — from waffo-pancake-store-service\n// ---------------------------------------------------------------------------\n\n/**\n * Webhook channel — HTTP for the standard RSA-signed envelope, the rest for\n * IM platform native payloads (Feishu / Discord / Telegram / Slack).\n */\nexport type WebhookChannel = \"http\" | \"feishu\" | \"discord\" | \"telegram\" | \"slack\";\n\n/**\n * Configured webhook endpoint (one row of `store.store_webhooks`).\n *\n * @see docs/api-reference/endpoints/webhooks/overview.mdx\n */\nexport interface StoreWebhook {\n /** Webhook UUID (not Short ID) */\n id: string;\n /** Owning store Short ID (`STO_…`) */\n storeId: string;\n channel: WebhookChannel;\n /** Target webhook URL */\n url: string;\n /** Subscribed event types (use `WebhookEventType` enum or its string literal) */\n events: `${WebhookEventType}`[];\n /** Whether this webhook fires in test or prod environment */\n testMode: boolean;\n /** Channel-specific credential (e.g. Telegram chat_id) */\n secret: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** Parameters for creating a webhook. */\nexport interface AddWebhookParams {\n /** Store Short ID (`STO_…`) */\n storeId: string;\n channel: WebhookChannel;\n /** Target webhook URL */\n url: string;\n /** Subscribed event types (use `WebhookEventType` enum or its string literal) */\n events: `${WebhookEventType}`[];\n /** Whether this webhook fires in test (true) or prod (false) */\n testMode: boolean;\n /** Channel-specific credential (e.g. Telegram chat_id) */\n secret?: string | null;\n}\n\n/** Parameters for updating a webhook. `channel` and `testMode` are immutable. */\nexport interface UpdateWebhookParams {\n /** Webhook UUID */\n id: string;\n /** Replace target URL (must remain on the same channel host) */\n url?: string;\n /** Replace subscribed event types (use `WebhookEventType` enum or its string literal) */\n events?: `${WebhookEventType}`[];\n /** Replace channel-specific credential */\n secret?: string | null;\n}\n\n/** Parameters for hard-deleting a webhook. */\nexport interface RemoveWebhookParams {\n /** Webhook UUID */\n id: string;\n}\n\n/**\n * Notification settings (all default to true).\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface NotificationSettings {\n emailOrderConfirmation: boolean;\n emailSubscriptionConfirmation: boolean;\n emailSubscriptionCycled: boolean;\n emailSubscriptionCanceled: boolean;\n emailSubscriptionRevoked: boolean;\n emailSubscriptionPastDue: boolean;\n emailTrialStarted: boolean;\n emailTrialEnding: boolean;\n emailUpcomingCharge: boolean;\n notifyNewOrders: boolean;\n notifyNewSubscriptions: boolean;\n notifySubscriptionCanceled: boolean;\n notifySubscriptionEnded: boolean;\n notifySubscriptionPastDue: boolean;\n notifySubscriptionRenewed: boolean;\n notifySubscriptionUncanceled: boolean;\n notifySubscriptionUpdated: boolean;\n notifyChargeback: boolean;\n}\n\n/**\n * Merchant-writable subset of {@link NotificationSettings}.\n *\n * Consumer-email toggles (`email*`) are managed by the PANCAKE platform and **not**\n * writable from this SDK; they would be silently dropped by the `update-store`\n * endpoint if included. Payout result notifications are platform-managed and always\n * delivered — they have no toggle key. Use this type for any merchant-side update.\n */\nexport type MerchantWritableNotificationSettings = Pick<\n NotificationSettings,\n | \"notifyNewOrders\"\n | \"notifyNewSubscriptions\"\n | \"notifySubscriptionCanceled\"\n | \"notifySubscriptionEnded\"\n | \"notifySubscriptionPastDue\"\n | \"notifySubscriptionRenewed\"\n | \"notifySubscriptionUncanceled\"\n | \"notifySubscriptionUpdated\"\n | \"notifyChargeback\"\n>;\n\n/**\n * Single-theme checkout page styling.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface CheckoutThemeSettings {\n checkoutLogo: string | null;\n checkoutColorPrimary: string;\n checkoutColorBackground: string;\n checkoutColorCard: string;\n checkoutColorText: string;\n checkoutBorderRadius: string;\n}\n\n/**\n * Checkout page configuration (light and dark themes).\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface CheckoutSettings {\n defaultDarkMode: boolean;\n light: CheckoutThemeSettings;\n dark: CheckoutThemeSettings;\n}\n\n/**\n * Store entity.\n * @see docs/api-reference/endpoints/stores/overview.mdx\n */\nexport interface Store {\n id: string;\n name: string;\n status: EntityStatus;\n logo: string | null;\n supportEmail: string | null;\n website: string | null;\n slug: string | null;\n prodEnabled: boolean;\n notificationSettings: NotificationSettings | null;\n checkoutSettings: CheckoutSettings | null;\n deletedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** Parameters for creating a store. */\nexport interface CreateStoreParams {\n /** Store name (slug is auto-generated) */\n name: string;\n}\n\n/**\n * Parameters for updating a store.\n *\n * Settings objects support partial updates — omitted sub-fields keep their\n * existing values, `null` clears a field, and a concrete value sets it.\n * Pass the entire settings object as `null` to clear all fields in the group.\n *\n * `supportEmail` and `website` are not writable here. They are derived from\n * ownership verification and are set only by the flows that prove it: email\n * code binding and domain verification, or KYB approval. Read them back from\n * {@link Store}.\n *\n * **BREAKING (2026-05)**: the legacy `webhookSettings` field is removed.\n * Manage webhooks via `client.webhooks.add / update / remove`; query the\n * webhook list through GraphQL `Store.storeWebhooks`.\n */\nexport interface UpdateStoreParams {\n /** Store ID */\n id: string;\n /** Store display name */\n name?: string;\n /** Store status */\n status?: EntityStatus;\n /** Store logo URL (set to `null` to remove) */\n logo?: string | null;\n /** Notification preferences (partial update — omitted fields keep existing values, set to `null` to clear all) */\n notificationSettings?: Partial<MerchantWritableNotificationSettings> | null;\n /** Checkout page theme configuration (partial update — omitted fields keep existing values, set to `null` to clear all) */\n checkoutSettings?: Partial<CheckoutSettings> | null;\n}\n\n/** Parameters for deleting (soft-delete) a store. */\nexport interface DeleteStoreParams {\n /** Store ID */\n id: string;\n}\n\n// ---------------------------------------------------------------------------\n// Store Merchant (coming soon — endpoints return 501)\n// ---------------------------------------------------------------------------\n\n/** Parameters for adding a merchant to a store. */\nexport interface AddMerchantParams {\n storeId: string;\n email: string;\n role: \"admin\" | \"member\";\n}\n\n/** Result of adding a merchant to a store. */\nexport interface AddMerchantResult {\n storeId: string;\n merchantId: string;\n email: string;\n role: string;\n status: string;\n addedAt: string;\n}\n\n/** Parameters for removing a merchant from a store. */\nexport interface RemoveMerchantParams {\n storeId: string;\n merchantId: string;\n}\n\n/** Result of removing a merchant from a store. */\nexport interface RemoveMerchantResult {\n message: string;\n removedAt: string;\n}\n\n/** Parameters for updating a merchant's role. */\nexport interface UpdateRoleParams {\n storeId: string;\n merchantId: string;\n role: \"admin\" | \"member\";\n}\n\n/** Result of updating a merchant's role. */\nexport interface UpdateRoleResult {\n storeId: string;\n merchantId: string;\n role: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Product — shared types from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * Price for a single currency.\n *\n * Amounts are represented as display strings (e.g., \"9.99\" for USD, \"1000\" for JPY).\n * The server handles conversion to/from smallest currency units internally.\n *\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n *\n * @example\n * // USD $9.99\n * { amount: \"9.99\", taxCategory: \"saas\" }\n *\n * @example\n * // JPY ¥1000\n * { amount: \"1000\", taxCategory: \"software\" }\n *\n * @example\n * // USD $9.99 with a $1.00 trial period (subscription products only)\n * { amount: \"9.99\", taxCategory: \"saas\", trialAmount: \"1.00\" }\n */\nexport interface PriceInfo {\n /** Price amount as display string (e.g., \"9.99\" for USD, \"1000\" for JPY) */\n amount: string;\n /** Tax category */\n taxCategory: TaxCategory;\n /** Trial period price as display string; requires `metadata.trialDays` and must be lower than `amount` */\n trialAmount?: string;\n}\n\n/**\n * Multi-currency prices (keyed by ISO 4217 currency code).\n *\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n *\n * @example\n * {\n * \"USD\": { amount: \"9.99\", taxCategory: \"saas\" },\n * \"EUR\": { amount: \"8.99\", taxCategory: \"saas\" }\n * }\n */\nexport type Prices = Record<string, PriceInfo>;\n\n/**\n * Media asset (image or video).\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport interface MediaItem {\n /** Media type */\n type: `${MediaType}`;\n /** Asset URL */\n url: string;\n /** Alt text */\n alt?: string;\n /** Thumbnail URL */\n thumbnail?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Onetime Product — from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * One-time product detail (public API shape).\n * @see docs/api-reference/endpoints/onetime-products/overview.mdx\n */\nexport interface OnetimeProductDetail {\n id: string;\n storeId: string;\n name: string;\n description: string | null;\n prices: Prices;\n media: MediaItem[];\n successUrl: string | null;\n metadata: Record<string, unknown>;\n status: ProductVersionStatus;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Parameters for creating a one-time product.\n * @see docs/api-reference/endpoints/onetime-products/create-product.mdx\n */\nexport interface CreateOnetimeProductParams {\n storeId: string;\n name: string;\n prices: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Parameters for updating a one-time product (creates a new version; skips if unchanged).\n * @see docs/api-reference/endpoints/onetime-products/update-product.mdx\n */\nexport interface UpdateOnetimeProductParams {\n id: string;\n name?: string;\n prices?: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/** Parameters for publishing a one-time product's test version to production. */\nexport interface PublishOnetimeProductParams {\n /** Product ID */\n id: string;\n}\n\n/**\n * Parameters for updating a one-time product's status.\n * @see docs/api-reference/endpoints/onetime-products/update-status.mdx\n */\nexport interface UpdateOnetimeStatusParams {\n id: string;\n status: ProductVersionStatus;\n}\n\n// ---------------------------------------------------------------------------\n// Subscription Product — from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * Subscription product detail (public API shape).\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport interface SubscriptionProductDetail {\n id: string;\n storeId: string;\n name: string;\n description: string | null;\n billingPeriod: BillingPeriod;\n prices: Prices;\n media: MediaItem[];\n successUrl: string | null;\n metadata: Record<string, unknown>;\n status: ProductVersionStatus;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Parameters for creating a subscription product.\n * @see docs/api-reference/endpoints/subscription-products/create-product.mdx\n */\nexport interface CreateSubscriptionProductParams {\n storeId: string;\n name: string;\n billingPeriod: BillingPeriod;\n prices: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Parameters for updating a subscription product (creates a new version; skips if unchanged).\n * @see docs/api-reference/endpoints/subscription-products/update-product.mdx\n */\nexport interface UpdateSubscriptionProductParams {\n id: string;\n name?: string;\n billingPeriod?: BillingPeriod;\n prices?: Prices;\n description?: string | null;\n media?: MediaItem[];\n successUrl?: string | null;\n metadata?: Record<string, unknown>;\n}\n\n/** Parameters for publishing a subscription product's test version to production. */\nexport interface PublishSubscriptionProductParams {\n /** Product ID */\n id: string;\n}\n\n/**\n * Parameters for updating a subscription product's status.\n * @see docs/api-reference/endpoints/subscription-products/update-status.mdx\n */\nexport interface UpdateSubscriptionStatusParams {\n id: string;\n status: ProductVersionStatus;\n}\n\n// ---------------------------------------------------------------------------\n// Subscription Product Group — from waffo-pancake-product-service\n// ---------------------------------------------------------------------------\n\n/**\n * Group rules for subscription product groups.\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport interface GroupRules {\n /** Whether trial period is shared across products in the group */\n sharedTrial: boolean;\n}\n\n/**\n * Subscription product group entity.\n * @see docs/api-reference/endpoints/subscription-products/overview.mdx\n */\nexport interface SubscriptionProductGroup {\n id: string;\n storeId: string;\n name: string;\n description: string | null;\n rules: GroupRules;\n productIds: string[];\n environment: Environment;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Parameters for creating a subscription product group.\n * @see docs/api-reference/endpoints/subscription-products/create-group.mdx\n */\nexport interface CreateSubscriptionProductGroupParams {\n storeId: string;\n name: string;\n description?: string;\n rules?: GroupRules;\n productIds?: string[];\n}\n\n/**\n * Parameters for updating a subscription product group (`productIds` is a full replacement).\n * @see docs/api-reference/endpoints/subscription-products/update-group.mdx\n */\nexport interface UpdateSubscriptionProductGroupParams {\n id: string;\n name?: string;\n description?: string;\n rules?: GroupRules;\n productIds?: string[];\n}\n\n/** Parameters for hard-deleting a subscription product group. */\nexport interface DeleteSubscriptionProductGroupParams {\n /** Group ID */\n id: string;\n}\n\n/** Parameters for publishing a test-environment group to production (upsert). */\nexport interface PublishSubscriptionProductGroupParams {\n /** Group ID */\n id: string;\n}\n\n// ---------------------------------------------------------------------------\n// Order — from waffo-pancake-order-service\n// ---------------------------------------------------------------------------\n\n/** Parameters for canceling a subscription order. */\nexport interface CancelSubscriptionParams {\n /** Order ID */\n orderId: string;\n}\n\n/**\n * Result of canceling a subscription order.\n * @see docs/api-reference/endpoints/subscriptions/cancel-subscription.mdx\n */\nexport interface CancelSubscriptionResult {\n orderId: string;\n /** Status after cancellation (`\"canceled\"` or `\"canceling\"`) */\n status: `${SubscriptionOrderStatus}`;\n}\n\n/**\n * Customer billing details for checkout.\n * @see docs/api-reference/endpoints/orders/overview.mdx\n */\nexport interface BillingDetail {\n /** Country code (ISO 3166-1 alpha-2) */\n country: string;\n /** Whether this is a business purchase */\n isBusiness: boolean;\n /** Postal / ZIP code (required for US, at least one of postcode/state for CA) */\n postcode?: string;\n /** State / province code (at least one of state/postcode for CA) */\n state?: string;\n /** Business name (recommended for invoicing, does not affect tax calculation) */\n businessName?: string;\n /** Tax ID / VAT number (EU businesses: triggers reverse charge 0% when provided) */\n taxId?: string;\n}\n\n/**\n * Supported checkout cashier languages (IETF BCP 47 tags).\n *\n * The default language of the hosted checkout page. Pass one of these values as\n * {@link CreateCheckoutSessionParams.language}; the customer can still switch language\n * on the checkout page. Language×currency mismatches are rejected by the payment provider.\n */\nexport type CashierLanguage =\n | \"en\"\n | \"pt-BR\"\n | \"es-MX\"\n | \"id-ID\"\n | \"vi-VN\"\n | \"ru-RU\"\n | \"en-KE\"\n | \"es-PE\"\n | \"es-CO\"\n | \"es-CL\"\n | \"zh-Hant-TW\"\n | \"zh-Hant-HK\"\n | \"th-TH\"\n | \"ja-JP\"\n | \"en-NG\"\n | \"ko-KR\"\n | \"en-HK\"\n | \"zh-Hans-HK\"\n | \"pl-PL\"\n | \"tr-TR\"\n | \"zh-Hans\"\n | \"ms-MY\";\n\n/**\n * Payment methods that can be offered on the hosted checkout page.\n *\n * Availability depends on the product type × currency pair. One-time: `USD` supports all four;\n * `EUR` / `GBP` / `HKD` / `JPY` support `card` / `applepay` / `googlepay`; `CNY` supports `wechat`.\n * Subscription: `USD` / `EUR` / `GBP` / `HKD` / `JPY` support `card` / `applepay` / `googlepay`.\n * Currencies outside this matrix cannot be charged at all — checkout session creation is rejected with a 400.\n */\nexport type PaymentMethod = \"card\" | \"applepay\" | \"googlepay\" | \"wechat\";\n\n/**\n * Session-level price override, accepted with API Key authentication only.\n * For subscription products it replaces the regular period price; the trial price comes from the locked product version.\n * @see docs/api-reference/endpoints/orders/create-checkout-session.mdx\n */\nexport interface PriceSnapshot {\n /** Price amount as display string (e.g., \"9.99\" for USD, \"1000\" for JPY) */\n amount: string;\n /** Tax category */\n taxCategory: TaxCategory;\n}\n\n/**\n * Parameters for creating a checkout session.\n * @see docs/api-reference/endpoints/orders/create-checkout-session.mdx\n */\nexport interface CreateCheckoutSessionParams {\n /** Product ID */\n productId: string;\n /** Currency code (ISO 4217) */\n currency: string;\n /** Optional price snapshot override (reads from DB if omitted) */\n priceSnapshot?: PriceSnapshot;\n /** Trial toggle override (subscription only) */\n withTrial?: boolean;\n /** Pre-filled customer email */\n buyerEmail?: string;\n /**\n * Pre-filled billing details. Passing this couples the cashier to the order's billing country: it then offers\n * only that country's payment market and the customer cannot switch. The country that applies is the one on the\n * finished order, not the one you sent; a country outside the payment markets we cover applies no restriction.\n * Omit to leave the cashier unrestricted.\n */\n billingDetail?: BillingDetail;\n /** Redirect URL after successful payment */\n successUrl?: string;\n /** Session expiration in seconds (default: 45 minutes) */\n expiresInSeconds?: number;\n /** Dark mode override (true=dark, false=light, omit=use store default) */\n darkMode?: boolean;\n /** Custom metadata */\n metadata?: Record<string, string>;\n /** Order-side business identifier (max 128 chars); inherited by orders, payments, refunds */\n orderMerchantExternalId?: string;\n /**\n * Default language of the hosted checkout page ({@link CashierLanguage}, IETF BCP 47).\n * The customer can switch language on the checkout page. Omit to let the provider infer.\n */\n language?: CashierLanguage;\n /**\n * Whitelist — offer only these payment methods ({@link PaymentMethod}).\n * Every value must be supported by the product type × currency pair, otherwise the request is rejected.\n * Mutually exclusive with {@link CreateCheckoutSessionParams.excludePaymentMethods}.\n * Omit both to offer every method the currency supports.\n */\n includePaymentMethods?: PaymentMethod[];\n /**\n * Blacklist — offer every method the currency supports except these ({@link PaymentMethod}).\n * Values the currency does not offer are ignored, so one blacklist can be reused across currencies.\n * Mutually exclusive with {@link CreateCheckoutSessionParams.includePaymentMethods}.\n */\n excludePaymentMethods?: PaymentMethod[];\n}\n\n/** Result of creating a checkout session. */\nexport interface CheckoutSessionResult {\n /** Session ID */\n sessionId: string;\n /** URL to redirect the customer to */\n checkoutUrl: string;\n /** Session expiration time (ISO 8601 UTC) */\n expiresAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Customer self-service\n// ---------------------------------------------------------------------------\n\n/** Parameters for canceling a one-time order (customer-side). */\nexport interface CancelOnetimeOrderParams {\n /** Order ID */\n orderId: string;\n}\n\n/** Result of canceling a one-time order. */\nexport interface CancelOnetimeOrderResult {\n /** Order ID */\n orderId: string;\n /** Resulting status (`\"canceled\"`) */\n status: string;\n}\n\n/** Parameters for reactivating a subscription (customer-side). */\nexport interface ReactivateSubscriptionParams {\n /** Subscription order ID */\n orderId: string;\n}\n\n/** Result of reactivating a subscription. */\nexport interface ReactivateSubscriptionResult {\n /** Order ID */\n orderId: string;\n /** Resulting status (`\"active\"`) */\n status: string;\n}\n\n/** Requested refund amount. */\nexport interface RequestedAmount {\n /** Refund amount in display format (e.g., `\"29.00\"`) */\n amount: string;\n /** Currency code (ISO 4217) */\n currency: string;\n}\n\n/**\n * Per-version data for a refund ticket. Each ticket can be submitted/resubmitted\n * multiple times; this is the shape of a single submission.\n */\nexport interface RefundTicketVersionData {\n /** Refund reason supplied by the customer */\n reason: string;\n /** Requested refund amount; `null` if the version has no amount recorded */\n requestedAmount: RequestedAmount | null;\n}\n\n/** Parameters for creating a refund ticket (customer-side). */\nexport interface CreateRefundTicketParams {\n /** Payment ID to refund */\n paymentId: string;\n /** Reason for the refund request */\n reason: string;\n /** Requested refund amount */\n requestedAmount: RequestedAmount;\n /** Custom metadata */\n metadata?: Record<string, unknown>;\n /** Refund-ticket business-side identifier (max 128 chars); inherited by the executed refund on PSP success */\n refundTicketMerchantExternalId?: string;\n}\n\n/** Parameters for resubmitting a rejected refund ticket (customer-side). */\nexport interface ResubmitRefundTicketParams {\n /** Existing ticket ID */\n ticketId: string;\n /** Payment ID */\n paymentId: string;\n /** Updated reason */\n reason: string;\n /** Updated requested amount */\n requestedAmount: RequestedAmount;\n}\n\n/** Refund ticket entity returned from create/resubmit operations. */\nexport interface RefundTicket {\n /** Ticket ID */\n id: string;\n /** Ticket type (e.g., `\"refund\"`) */\n type: string;\n /** Ticket status (e.g., `\"pending\"`, `\"approved\"`, `\"rejected\"`) */\n status: string;\n /** Associated payment ID */\n subjectId: string;\n /** Submitter identifier (email or merchant ID) */\n submitterId: string;\n /** Submitter type (e.g., `\"customer\"`, `\"merchant\"`) */\n submitterType: string;\n /** Current version ID */\n currentVersionId: string | null;\n /** Reviewer ID (null if not yet reviewed) */\n reviewerId: string | null;\n /** Review timestamp (ISO 8601, null if not yet reviewed) */\n reviewedAt: string | null;\n /** Reviewer's note */\n reviewNote: string | null;\n /** Rejection reason (null if approved or pending) */\n rejectReason: string | null;\n /** Execution timestamp (ISO 8601, null if not yet executed) */\n executedAt: string | null;\n /** Custom metadata */\n metadata: Record<string, unknown>;\n /** Refund-ticket business-side identifier (max 128 chars, immutable across resubmits) */\n refundTicketMerchantExternalId: string | null;\n /** Current version number */\n versionNumber: number | null;\n /** Current (latest) version data */\n versionData: RefundTicketVersionData | null;\n /** Creation timestamp (ISO 8601) */\n createdAt: string;\n /** Last update timestamp (ISO 8601) */\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Checkout — convenience wrappers\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for anonymous checkout.\n *\n * The customer reaches the checkout page without a session token. Merchants may still\n * pre-fill `buyerEmail` and `billingDetail`; omitting them leaves the form blank.\n *\n * Accepts every field of {@link CreateCheckoutSessionParams} — this wrapper simply\n * forwards the params unchanged to `/v1/actions/checkout/create-session`.\n *\n * @example\n * const result = await client.checkout.anonymous.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n * // Redirect to result.checkoutUrl\n */\nexport type AnonymousCheckoutParams = CreateCheckoutSessionParams;\n\n/**\n * Parameters for authenticated checkout.\n *\n * Merges the checkout-session fields ({@link CreateCheckoutSessionParams}) with the\n * extra `buyerIdentity` required by `issue-session-token`. The wrapper splits the\n * input: `buyerIdentity` goes to the token call; everything else (including\n * `buyerEmail`) goes to the create-session call. The two fields are independent.\n *\n * @example\n * const result = await client.checkout.authenticated.create({\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * buyerIdentity: \"user-123\", // merchant-side customer id (goes into JWT)\n * buyerEmail: \"customer@example.com\", // pre-filled on the checkout page\n * });\n * // Redirect to result.checkoutUrl (includes #token=...)\n */\nexport interface AuthenticatedCheckoutParams extends CreateCheckoutSessionParams {\n /**\n * Customer identity — sent to `issue-session-token` and encoded into the JWT\n * payload for merchant-side customer identification. Accepts an email or any\n * merchant-provided identifier string. Use `buyerEmail` to pre-fill the\n * checkout page's email input.\n */\n buyerIdentity: string;\n}\n\n/**\n * Result of an authenticated checkout creation.\n *\n * Extends the base session result with the issued token details.\n */\nexport interface AuthenticatedCheckoutResult {\n /** Session ID */\n sessionId: string;\n /** Checkout URL with session token appended as URL fragment (`#token=...`) */\n checkoutUrl: string;\n /** Session expiration time (ISO 8601 UTC) */\n expiresAt: string;\n /** Issued JWT token */\n token: string;\n /** Token expiration time (ISO 8601 UTC) */\n tokenExpiresAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// GraphQL\n// ---------------------------------------------------------------------------\n\n/** Parameters for a GraphQL query. */\nexport interface GraphQLParams {\n /** GraphQL query string */\n query: string;\n /** Query variables */\n variables?: Record<string, unknown>;\n}\n\n/**\n * GraphQL response envelope. Same shape as {@link Envelope}, but `errors` entries\n * may additionally carry `locations` and `path` (graphql-js fields). The `layer`\n * field is optional on GraphQL because resolver errors don't carry one.\n */\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data: T | null;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: string[];\n aiHint?: string;\n /** Service stage that produced the error (\"graphql\", \"gateway\"). Resolver errors omit it. */\n layer?: string;\n }>;\n warnings?: Notice[];\n}\n\n// ---------------------------------------------------------------------------\n// Webhook\n// ---------------------------------------------------------------------------\n\n/**\n * Webhook event types.\n * @see docs/api-reference/webhooks.mdx\n */\nexport enum WebhookEventType {\n /** One-time order first payment succeeded */\n OrderCompleted = \"order.completed\",\n /** Subscription first payment succeeded (newly activated) */\n SubscriptionActivated = \"subscription.activated\",\n /** Subscription renewal payment succeeded */\n SubscriptionPaymentSucceeded = \"subscription.payment_succeeded\",\n /** Customer initiated cancellation (expires at end of current period) */\n SubscriptionCanceling = \"subscription.canceling\",\n /** Customer withdrew cancellation (subscription restored) */\n SubscriptionUncanceled = \"subscription.uncanceled\",\n /** Subscription product changed (upgrade/downgrade) */\n SubscriptionUpdated = \"subscription.updated\",\n /** Subscription fully terminated */\n SubscriptionCanceled = \"subscription.canceled\",\n /** Renewal payment failed (past due) */\n SubscriptionPastDue = \"subscription.past_due\",\n /** Refund succeeded */\n RefundSucceeded = \"refund.succeeded\",\n /** Refund failed */\n RefundFailed = \"refund.failed\",\n}\n\n/**\n * Common data fields in a webhook event payload.\n * @see docs/api-reference/webhooks.mdx\n */\nexport interface WebhookEventData {\n // Order\n orderId: string;\n /** Order status (e.g., \"completed\", \"active\", \"canceling\") */\n orderStatus?: string;\n buyerEmail: string;\n /** Merchant-provided customer identity from checkout session */\n merchantProvidedBuyerIdentity?: string;\n /** Order business identifier; present on order/payment + refund events (inherited from order) */\n orderMerchantExternalId?: string;\n /** Refund-ticket business identifier; only present on refund.* events */\n refundTicketMerchantExternalId?: string;\n currency: string;\n /** Billing/shipping address (structured object) */\n billingDetail?: Record<string, unknown>;\n /** Order-level metadata from checkout session (flat key-value pairs) */\n orderMetadata?: Record<string, string>;\n\n // Amount\n /** Amount as display string (e.g., \"9.99\" for USD, \"1000\" for JPY) */\n amount: string;\n /** Tax amount as display string (e.g., \"0.91\" for USD) */\n taxAmount: string;\n /** Tax rate as decimal (e.g., 0.1 for 10%) */\n taxRate?: number;\n /** Tax name (e.g., \"Consumption Tax\") */\n taxName?: string;\n /** Subtotal as display string (before tax) */\n subtotal?: string;\n /** Total as display string (after tax) */\n total?: string;\n\n // Product\n productName: string;\n /** Product description */\n productDescription?: string;\n /** Product-level metadata set when creating/updating the product */\n productMetadata?: Record<string, string>;\n\n // Payment (present for payment events: order.completed, subscription.payment_succeeded)\n /** Payment ID */\n paymentId?: string;\n /** Payment status (e.g., \"succeeded\", \"failed\") */\n paymentStatus?: string;\n /** Payment method type (e.g., \"card\") */\n paymentMethod?: string;\n /** Last 4 digits of payment instrument */\n paymentLast4?: string;\n /** Payment failure reason (present when payment failed) */\n paymentFailureReason?: string;\n /** Payment date (ISO 8601 date, e.g., \"2026-04-18\") */\n paymentDate?: string;\n\n // Subscription (present for subscription events)\n /** Billing period: \"weekly\", \"monthly\", \"quarterly\", \"yearly\" */\n billingPeriod?: string;\n /** Current billing period start date (ISO 8601, e.g., \"2026-04-01\") */\n currentPeriodStart?: string;\n /** Current billing period end date (ISO 8601, e.g., \"2026-05-01\") */\n currentPeriodEnd?: string;\n /** Subscription cancellation timestamp (ISO 8601, present when canceled) */\n canceledAt?: string;\n\n // Refund (present for refund events: refund.succeeded, refund.failed)\n /** Refund status (e.g., \"succeeded\", \"failed\") */\n refundStatus?: string;\n /** Refund reason */\n refundReason?: string;\n /** Refund creation timestamp (ISO 8601) */\n refundCreatedAt?: string;\n}\n\n/**\n * Webhook event payload.\n *\n * @see docs/api-reference/webhooks.mdx\n *\n * @example\n * {\n * id: \"550e8400-...\",\n * timestamp: \"2026-03-10T08:30:00.000Z\",\n * eventType: \"order.completed\",\n * eventId: \"PAY_5xK9mRtYvWnPqLsJ3hBfDe\",\n * storeId: \"STO_2aUyqjCzEIiEcYMKj7TZtw\",\n * storeName: \"My Store\",\n * mode: \"prod\",\n * data: { orderId: \"...\", buyerEmail: \"...\", currency: \"USD\", amount: \"29.00\", taxAmount: \"2.90\", productName: \"Pro Plan\", orderMetadata: { planId: \"pro\" } }\n * }\n */\nexport interface WebhookEvent<T = WebhookEventData> {\n /** Delivery record unique ID (UUID), usable for idempotent deduplication */\n id: string;\n /** Event timestamp (ISO 8601 UTC) */\n timestamp: string;\n /** Event type */\n eventType: `${WebhookEventType}` | (string & {});\n /** Business event ID (e.g. payment ID, order ID) */\n eventId: string;\n /** Store ID the event belongs to */\n storeId: string;\n /** Store name */\n storeName: string;\n /** Environment identifier */\n mode: `${Environment}`;\n /** Event data */\n data: T;\n}\n\n/**\n * Webhook public key configuration.\n *\n * - `string` — single key used for both test and prod environments\n * - `{ test?, prod? }` — per-environment keys\n */\nexport type WebhookPublicKeys = string | { test?: string; prod?: string };\n\n/** Options for {@link verifyWebhook}. */\nexport interface VerifyWebhookOptions {\n /**\n * Specify which environment's public key to use for verification.\n * When omitted, both keys are tried automatically (prod first).\n * Ignored when `publicKey` is provided.\n */\n environment?: `${Environment}`;\n /**\n * How far in the past a signature timestamp may be, in milliseconds.\n * Set to 0 to skip timestamp checking entirely (this also skips\n * {@link futureToleranceMs}).\n *\n * The default covers the full delivery retry schedule: the timestamp is\n * stamped before the first attempt and retries reuse it, so the last retry\n * arrives with a timestamp as old as the schedule itself.\n *\n * @default 2700000 (45 minutes)\n */\n toleranceMs?: number;\n /**\n * How far in the future a signature timestamp may be, in milliseconds.\n * Only clock skew on the receiving server puts a timestamp ahead of now, so\n * this stays tight — it matches the gateway's API Key check.\n *\n * Ignored when `toleranceMs` is 0.\n *\n * @default 60000 (1 minute)\n */\n futureToleranceMs?: number;\n /**\n * Per-call public key override (highest priority).\n * When provided, skips all other key resolution (config, env vars, built-in).\n */\n publicKey?: string;\n /**\n * Config-level public key(s) for the resolution chain.\n * When using `client.webhooks.verify()`, this is set automatically from `WaffoPancakeConfig.webhookPublicKey`.\n * When using the standalone `verifyWebhook()`, you can pass this directly for config-level key injection.\n *\n * Resolution order per environment:\n * 1. `publicKey` (per-call override)\n * 2. `publicKeys[env]` or `publicKeys` (config)\n * 3. `WAFFO_WEBHOOK_{TEST|PROD}_PUBLIC_KEY` (env var)\n * 4. `WAFFO_WEBHOOK_PUBLIC_KEY` (env var)\n * 5. Built-in hardcoded key\n */\n publicKeys?: WebhookPublicKeys;\n}\n\n// ---------------------------------------------------------------------------\n// Content Safety — from waffo-pancake-verification-service\n// ---------------------------------------------------------------------------\n\n/**\n * Content-safety scan verdict.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanAction {\n Allow = \"allow\",\n Review = \"review\",\n Block = \"block\",\n}\n\n/**\n * Scan verdict reason code.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanReasonCode {\n Allowed = \"allowed\",\n ReviewRequired = \"review_required\",\n RestrictedContent = \"restricted_content\",\n ServiceDegraded = \"service_degraded\",\n}\n\n/**\n * Matched content-safety policy category.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanPolicyCategory {\n CsamMinor = \"csam_minor\",\n SexualViolenceNonconsensual = \"sexual_violence_nonconsensual\",\n UndressTransform = \"undress_transform\",\n FaceSwapIdentity = \"face_swap_identity\",\n BestialityRestricted = \"bestiality_restricted\",\n AdultNsfw = \"adult_nsfw\",\n}\n\n/**\n * Semantic scan channel mode.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanSemanticMode {\n Off = \"off\",\n Shadow = \"shadow\",\n Enforce = \"enforce\",\n}\n\n/**\n * Semantic scan channel status.\n * @see docs/api-reference/endpoints/content-safety/scan-prompt.mdx\n */\nexport enum ScanSemanticStatus {\n Disabled = \"disabled\",\n Scored = \"scored\",\n ShadowScored = \"shadow_scored\",\n SkippedRulesBlock = \"skipped_rules_block\",\n SkippedBudget = \"skipped_budget\",\n ProviderTimeout = \"provider_timeout\",\n ProviderError = \"provider_error\",\n}\n\n/** Parameters for scanning a prompt before AIGC generation. */\nexport interface ScanPromptParams {\n /** The user's text prompt to scan (1–10,000 characters). */\n prompt: string;\n /** Prompt text language (default \"en\"). */\n locale?: \"ja\" | \"en\" | \"zh\";\n /** How the external semantic channel participates. */\n semantic?: ScanSemanticMode;\n}\n\n/** Redacted scan verdict — no scores, thresholds, or keyword text. */\nexport interface ScanResult {\n /** Final verdict; continue only when `allow`. */\n action: ScanAction;\n /** Stable machine-readable reason. */\n reasonCode: ScanReasonCode;\n /** Matched policy categories; empty when allowed. */\n matchedCategories: ScanPolicyCategory[];\n /** Correlation id for support and appeals; safe to log. */\n requestId: string;\n /** Whether/how the semantic channel contributed to this scan. */\n semanticStatus: ScanSemanticStatus;\n}\n"],"mappings":"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","names":["createHash","DEFAULT_BASE_URL","createHash","Environment","TaxCategory","BillingPeriod","ProductVersionStatus","EntityStatus","StoreRole","OnetimeOrderStatus","SubscriptionOrderStatus","PaymentStatus","RefundTicketStatus","RefundStatus","MediaType","ErrorLayer","WebhookEventType","ScanAction","ScanReasonCode","ScanPolicyCategory","ScanSemanticMode","ScanSemanticStatus"]}
|