@waffo/pancake-nextjs 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/index.cjs +6 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -7
- package/dist/index.d.ts +22 -7
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ All notable changes to `@waffo/pancake-nextjs` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.1.3] - 2026-04-18
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Dependency `@waffo/pancake-ts` bumped to `^0.5.0`** — picks up enriched `WebhookEventData` with full transaction chain fields (order status, payment details, subscription info, refund data, metadata). Webhook handlers automatically receive the new fields via the existing `EventHandler<WebhookEventData>` generic type.
|
|
12
|
+
|
|
13
|
+
## [0.1.2] - 2026-04-15
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **`useBuyerRefundTickets`** — the underlying GraphQL query was selecting non-existent top-level fields (`reason`, `requestedAmount`, `requestedCurrency`); these live under `versionData` because each ticket can have multiple submissions. Query now selects `versionData { reason, requestedAmount { amount, currency } }` and `versionNumber`. The `BuyerRefundTicket` interface is updated accordingly. **Breaking shape change for any consumer that read these fields**: replace `ticket.reason` → `ticket.versionData?.reason`, and `ticket.requestedAmount` → `ticket.versionData?.requestedAmount?.amount` (now display-formatted, e.g. `"29.00"`, paired with `requestedAmount.currency`).
|
|
18
|
+
|
|
19
|
+
### Compatibility
|
|
20
|
+
|
|
21
|
+
- **`useMerchantSales`** — `SalesOverview.totalRevenue` and `SalesOverview.revenueByPeriod[].amount` are now display-formatted strings (e.g. `"9.99"`) instead of minor-currency-unit strings. The TypeScript type is unchanged (`string`), but consumers must drop any `parseInt() / 100` or similar conversion. JSDoc updated to reflect the semantic. Aligns with `waffo-pancake-graphql-service` v2026.04.15.1.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **Dependency `@waffo/pancake-ts` bumped to `^0.4.1`** — to pick up the new `RefundTicketVersionData` type. `BuyerRefundTicket.versionData` now uses that shared type instead of a locally redefined one.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **Re-exports from `@waffo/pancake-ts`** — `RequestedAmount` and `RefundTicketVersionData` are now re-exported from this package for direct use in client components.
|
|
30
|
+
|
|
7
31
|
## [0.1.1] - 2026-04-15
|
|
8
32
|
|
|
9
33
|
### Documentation
|
package/dist/index.cjs
CHANGED
|
@@ -281,7 +281,12 @@ var BUYER_PAYMENTS_QUERY = `query {
|
|
|
281
281
|
}`;
|
|
282
282
|
var BUYER_REFUND_TICKETS_QUERY = `query {
|
|
283
283
|
refundTickets(limit: 50) {
|
|
284
|
-
id status
|
|
284
|
+
id status versionNumber
|
|
285
|
+
versionData {
|
|
286
|
+
reason
|
|
287
|
+
requestedAmount { amount currency }
|
|
288
|
+
}
|
|
289
|
+
createdAt
|
|
285
290
|
}
|
|
286
291
|
}`;
|
|
287
292
|
function useBuyerQuery(query) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/use-checkout.ts","../src/checkout-button.tsx","../src/use-buyer.ts","../src/use-buyer-data.ts","../src/use-query.ts","../src/use-merchant-data.ts","../src/webhook.ts"],"sourcesContent":["export { WaffoPancakeProvider } from \"./provider.js\";\nexport { CheckoutButton } from \"./checkout-button.js\";\nexport { useCheckout } from \"./use-checkout.js\";\nexport { useBuyer } from \"./use-buyer.js\";\nexport { useBuyerOrders, useBuyerPayments, useBuyerRefundTickets } from \"./use-buyer-data.js\";\nexport { useMerchantOrders, useMerchantSales, useMerchantSubscriptions } from \"./use-merchant-data.js\";\nexport { Webhook } from \"./webhook.js\";\n\n// Re-export types commonly used in client components\nexport { WaffoPancakeError, TaxCategory, WebhookEventType } from \"@waffo/pancake-ts\";\n\nexport type { PriceInfo, BillingDetail, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n// Local types\nexport type {\n CheckoutMode,\n CheckoutBaseOptions,\n LinkCheckoutProps,\n AnonymousCheckoutProps,\n AuthenticatedCheckoutProps,\n CheckoutProps,\n UseCheckoutReturn,\n} from \"./types.js\";\n\nexport type { BuyerConfig, WaffoPancakeProviderProps } from \"./provider.js\";\n\nexport type {\n CheckoutButtonProps,\n LinkCheckoutButtonProps,\n AnonymousCheckoutButtonProps,\n AuthenticatedCheckoutButtonProps,\n} from \"./checkout-button.js\";\n\nexport type { BuyerActionState, UseBuyerReturn } from \"./use-buyer.js\";\n\nexport type { QueryState } from \"./use-query.js\";\n\nexport type { BuyerOnetimeOrder, BuyerSubscriptionOrder, BuyerPayment, BuyerRefundTicket } from \"./use-buyer-data.js\";\n\nexport type { MerchantOrder, MerchantSubscription, SalesOverview, SubscriptionOverview, MerchantOrdersOptions } from \"./use-merchant-data.js\";\n\nexport type { WebhookConfig } from \"./webhook.js\";\n\n// Server action types (for typing the action prop)\nexport type { CheckoutAction, CheckoutActionParams, CheckoutActionResult, BuyerTokenAction, BuyerSessionAction, MerchantQueryAction } from \"./server.js\";\n","\"use client\";\n\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { BuyerTokenAction, BuyerSessionAction } from \"./server.js\";\n\n/** Buyer configuration for automatic token management */\nexport interface BuyerConfig {\n /** Buyer identity (email or merchant-provided identifier) */\n identity: 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 /** Server action for issuing tokens — from `createBuyerTokenAction()` */\n issueToken: BuyerTokenAction;\n /** Server action for buyer operations — from `createBuyerSessionAction()` */\n sessionAction: BuyerSessionAction;\n}\n\ninterface TokenState {\n token: string;\n expiresAt: number;\n}\n\n/** @internal */\nexport interface PancakeContextValue {\n /** Get a valid buyer token (auto-refreshes if expired) */\n getBuyerToken: () => Promise<string>;\n /** Execute a buyer session operation via server action */\n buyerSessionAction: BuyerSessionAction;\n /** Whether buyer config is provided */\n hasBuyer: boolean;\n /** Whether the initial token is ready */\n isBuyerReady: boolean;\n}\n\n/** @internal Exported for direct useContext access in hooks */\nexport const PancakeContext = createContext<PancakeContextValue | null>(null);\n\n/** Token refresh buffer — refresh 30s before actual expiry */\nconst REFRESH_BUFFER_MS = 30_000;\n\nexport interface WaffoPancakeProviderProps {\n /** Buyer configuration for automatic token management */\n buyer: BuyerConfig;\n children: React.ReactNode;\n}\n\n/**\n * Provider that manages buyer token lifecycle via server actions.\n *\n * Auto-issues session tokens on mount and refreshes before expiry.\n * All buyer hooks (`useBuyer`, `useBuyerOrders`, etc.) read from context.\n *\n * The private key never leaves the server — token issuance and buyer\n * operations are delegated to server actions.\n *\n * @param props - Provider configuration\n * @param props.buyer - Buyer identity and server actions\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * // identity must match what you passed as `buyerIdentity` at checkout time —\n * // buyer-portal lookups are keyed by merchant_provided_buyer_identity\n * <WaffoPancakeProvider buyer={{\n * identity: user.id,\n * storeId: \"STO_xxx\",\n * issueToken, // from createBuyerTokenAction()\n * sessionAction, // from createBuyerSessionAction()\n * }}>\n * <App />\n * </WaffoPancakeProvider>\n * ```\n */\nexport function WaffoPancakeProvider({ buyer, children }: WaffoPancakeProviderProps) {\n const tokenRef = useRef<TokenState | null>(null);\n const refreshPromiseRef = useRef<Promise<string> | null>(null);\n const [isBuyerReady, setIsBuyerReady] = useState(false);\n\n const refreshToken = useCallback(async (): Promise<string> => {\n const result = await buyer.issueToken({\n buyerIdentity: buyer.identity,\n storeId: buyer.storeId,\n productId: buyer.productId,\n });\n\n tokenRef.current = {\n token: result.token,\n expiresAt: new Date(result.expiresAt).getTime(),\n };\n\n return result.token;\n }, [buyer]);\n\n const getBuyerToken = useCallback(async (): Promise<string> => {\n const current = tokenRef.current;\n if (current && Date.now() < current.expiresAt - REFRESH_BUFFER_MS) {\n return current.token;\n }\n\n // Deduplicate concurrent refresh calls\n if (!refreshPromiseRef.current) {\n refreshPromiseRef.current = refreshToken().finally(() => {\n refreshPromiseRef.current = null;\n });\n }\n\n return refreshPromiseRef.current;\n }, [refreshToken]);\n\n // Issue initial token on mount\n useEffect(() => {\n refreshToken()\n .then(() => setIsBuyerReady(true))\n .catch(() => setIsBuyerReady(true));\n }, [refreshToken]);\n\n const value = useMemo<PancakeContextValue>(\n () => ({\n getBuyerToken,\n buyerSessionAction: buyer.sessionAction,\n hasBuyer: true,\n isBuyerReady,\n }),\n [getBuyerToken, buyer.sessionAction, isBuyerReady],\n );\n\n return <PancakeContext.Provider value={value}>{children}</PancakeContext.Provider>;\n}\n\n/**\n * Access the Waffo Pancake context. Must be used within `<WaffoPancakeProvider>`.\n */\nexport function usePancakeContext(): PancakeContextValue {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"usePancakeContext: must be used within <WaffoPancakeProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\n\nimport type { CheckoutProps, LinkCheckoutProps, UseCheckoutReturn } from \"./types.js\";\nimport type { CheckoutSessionResult, AuthenticatedCheckoutResult } from \"@waffo/pancake-ts\";\n\n\nconst LOADING_HTML = `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Loading...</title><style>body{display:flex;align-items:center;justify-content:center;height:100vh;margin:0;font-family:system-ui,sans-serif;background:#f9fafb;color:#6b7280}@media(prefers-color-scheme:dark){body{background:#111827;color:#9ca3af}}</style></head><body><p>Redirecting to checkout...</p></body></html>`;\n\nconst DEFAULT_STOREFRONT_URL = \"https://pancake.waffo.ai\";\n\nconst SDK_FIELDS = new Set([\"action\", \"type\", \"mode\", \"popupLoadingUrl\", \"onSuccess\", \"onError\"]);\n\n/** Extract API checkout params from flattened props, removing SDK-specific fields */\nfunction extractApiParams(args: object): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(args)) {\n if (!SDK_FIELDS.has(key)) params[key] = value;\n }\n return params;\n}\n\n/**\n * Build a product page URL for link checkout.\n */\nfunction buildLinkUrl(props: LinkCheckoutProps): string {\n const base = (props.baseUrl ?? DEFAULT_STOREFRONT_URL).replace(/\\/+$/, \"\");\n const url = new URL(`${base}/store/${props.storeSlug}/product/${props.productId}`);\n\n if (props.currency) url.searchParams.set(\"currency\", props.currency);\n if (props.email) url.searchParams.set(\"email\", props.email);\n if (props.successUrl) url.searchParams.set(\"success_url\", props.successUrl);\n if (props.test) url.searchParams.set(\"test\", \"true\");\n if (props.country) url.searchParams.set(\"country\", props.country);\n if (props.isBusiness) url.searchParams.set(\"is_business\", \"true\");\n\n return url.toString();\n}\n\n/**\n * React hook for triggering a Waffo Pancake checkout flow.\n *\n * Supports three checkout types:\n * - **link**: Builds a product page URL and navigates directly (no API call, synchronous)\n * - **anonymous**: Calls a server action to create a checkout session, then navigates\n * - **authenticated**: Calls a server action to create a session + token, then navigates\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param args - Flattened checkout props\n * @returns `{ checkout, isLoading, error }`\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * const { checkout } = useCheckout({\n * type: \"link\",\n * storeSlug: \"my-store\",\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * // Anonymous checkout — via server action\n * const { checkout, isLoading } = useCheckout({\n * action: checkout, // from createCheckoutAction()\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n * ```\n */\nexport function useCheckout(args: CheckoutProps): UseCheckoutReturn {\n const { mode = \"redirect\", popupLoadingUrl, onError } = args;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const popupRef = useRef<Window | null>(null);\n\n const checkout = useCallback(() => {\n if (isLoading) return;\n\n // Link checkout — synchronous, no API call\n if (args.type === \"link\") {\n const url = buildLinkUrl(args);\n if (mode === \"popup\") {\n window.open(url, \"_blank\");\n } else {\n window.location.href = url;\n }\n return;\n }\n\n // Anonymous / Authenticated — server action\n if (mode === \"popup\") {\n const loadingUrl = popupLoadingUrl ?? `data:text/html;charset=utf-8,${encodeURIComponent(LOADING_HTML)}`;\n popupRef.current = window.open(loadingUrl, \"_blank\");\n }\n\n setIsLoading(true);\n setError(null);\n\n const { action } = args;\n const params = extractApiParams(args);\n const actionParams = args.type === \"authenticated\" ? { type: \"authenticated\" as const, ...params } : params;\n\n action(actionParams as unknown as Parameters<typeof action>[0])\n .then((result: CheckoutSessionResult | AuthenticatedCheckoutResult) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.location.href = result.checkoutUrl;\n } else {\n window.location.href = result.checkoutUrl;\n }\n if (\"onSuccess\" in args && args.onSuccess) {\n (args.onSuccess as (r: CheckoutSessionResult | AuthenticatedCheckoutResult) => void)(result);\n }\n })\n .catch((err: Error) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.close();\n popupRef.current = null;\n }\n setError(err);\n onError?.(err);\n })\n .finally(() => {\n setIsLoading(false);\n });\n }, [args, mode, popupLoadingUrl, onError, isLoading]);\n\n return { checkout, isLoading, error };\n}\n","\"use client\";\n\nimport React from \"react\";\n\nimport { useCheckout } from \"./use-checkout.js\";\n\nimport type { CheckoutProps, LinkCheckoutProps, AnonymousCheckoutProps, AuthenticatedCheckoutProps } from \"./types.js\";\n\ntype CheckoutButtonBaseProps = {\n /** Button content */\n children: React.ReactNode;\n /** Content shown while checkout session is being created */\n loadingChildren?: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Disabled state (merged with isLoading) */\n disabled?: boolean;\n} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\" | \"disabled\" | \"children\">;\n\n/** Props for CheckoutButton — link mode */\nexport type LinkCheckoutButtonProps = CheckoutButtonBaseProps & LinkCheckoutProps;\n\n/** Props for CheckoutButton — anonymous mode */\nexport type AnonymousCheckoutButtonProps = CheckoutButtonBaseProps & AnonymousCheckoutProps;\n\n/** Props for CheckoutButton — authenticated mode */\nexport type AuthenticatedCheckoutButtonProps = CheckoutButtonBaseProps & AuthenticatedCheckoutProps;\n\nexport type CheckoutButtonProps = LinkCheckoutButtonProps | AnonymousCheckoutButtonProps | AuthenticatedCheckoutButtonProps;\n\n/**\n * A button that triggers a Waffo Pancake checkout flow on click.\n *\n * Three checkout types:\n * - **link**: Instant redirect to product page URL (no server action needed)\n * - **anonymous**: Calls server action to create session, then redirects\n * - **authenticated**: Calls server action to create session + token, then redirects\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param props - Flattened checkout props, button content, and optional styling\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * <CheckoutButton type=\"link\" storeSlug=\"my-store\" productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Anonymous checkout — via server action\n * <CheckoutButton action={checkout} productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Authenticated checkout — via server action\n * <CheckoutButton action={checkout} type=\"authenticated\" productId=\"PROD_xxx\" currency=\"USD\" buyerIdentity=\"userIdInYourSystem\" buyerEmail=\"user@example.com\">\n * Buy Now\n * </CheckoutButton>\n * ```\n */\nexport function CheckoutButton(props: CheckoutButtonProps) {\n const { children, loadingChildren, className, style, disabled, ...checkoutProps } = props;\n\n const { checkout, isLoading } = useCheckout(checkoutProps as CheckoutProps);\n\n return (\n <button type=\"button\" onClick={checkout} disabled={disabled || isLoading} className={className} style={style}>\n {isLoading ? (loadingChildren ?? children) : children}\n </button>\n );\n}\n","\"use client\";\n\nimport { useCallback, useContext, useMemo, useState } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\n\nimport type {\n CancelSubscriptionParams,\n CancelSubscriptionResult,\n CancelOnetimeOrderParams,\n CancelOnetimeOrderResult,\n ReactivateSubscriptionParams,\n ReactivateSubscriptionResult,\n CreateRefundTicketParams,\n ResubmitRefundTicketParams,\n RefundTicket,\n GraphQLParams,\n GraphQLResponse,\n} from \"@waffo/pancake-ts\";\n\n/** State of an async buyer action */\nexport interface BuyerActionState<T = unknown> {\n /** Execute the action */\n execute: (params: T) => Promise<void>;\n /** Whether the action is in progress */\n isLoading: boolean;\n /** Error from the last attempt */\n error: Error | null;\n}\n\n/** Return type of useBuyer hook */\nexport interface UseBuyerReturn {\n /** Cancel a subscription order */\n cancelSubscription: BuyerActionState<CancelSubscriptionParams> & { data: CancelSubscriptionResult | null };\n /** Cancel a one-time order */\n cancelOnetimeOrder: BuyerActionState<CancelOnetimeOrderParams> & { data: CancelOnetimeOrderResult | null };\n /** Reactivate a canceling subscription */\n reactivateSubscription: BuyerActionState<ReactivateSubscriptionParams> & { data: ReactivateSubscriptionResult | null };\n /** Create a refund ticket */\n createRefundTicket: BuyerActionState<CreateRefundTicketParams> & { data: RefundTicket | null };\n /** Resubmit a rejected refund ticket */\n resubmitRefundTicket: BuyerActionState<ResubmitRefundTicketParams> & { data: RefundTicket | null };\n /** Execute a GraphQL query */\n query: <T = Record<string, unknown>>(params: GraphQLParams) => Promise<GraphQLResponse<T>>;\n}\n\nfunction useBuyerAction<TParams, TResult>(\n actionFn: (params: TParams) => Promise<TResult>,\n): BuyerActionState<TParams> & { data: TResult | null } {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TResult | null>(null);\n\n const execute = useCallback(\n async (params: TParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await actionFn(params);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [actionFn],\n );\n\n return { execute, isLoading, error, data };\n}\n\n/**\n * React hook for buyer self-service actions.\n *\n * Must be used within `<WaffoPancakeProvider>`. All operations are executed\n * via server actions — the private key never leaves the server.\n *\n * @returns Buyer action handlers with loading/error states\n *\n * @example\n * ```tsx\n * function AccountPage() {\n * const buyer = useBuyer();\n * return (\n * <button onClick={() => buyer.cancelSubscription.execute({ orderId: \"ORD_xxx\" })}>\n * Cancel\n * </button>\n * );\n * }\n * ```\n */\nexport function useBuyer(): UseBuyerReturn {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"useBuyer: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction } = ctx;\n\n const callAction = useCallback(\n async (actionType: string, params: unknown) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, actionType as never, params);\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n const cancelSubscription = useBuyerAction<CancelSubscriptionParams, CancelSubscriptionResult>(\n useCallback((params) => callAction(\"cancelSubscription\", params) as Promise<CancelSubscriptionResult>, [callAction]),\n );\n\n const cancelOnetimeOrder = useBuyerAction<CancelOnetimeOrderParams, CancelOnetimeOrderResult>(\n useCallback((params) => callAction(\"cancelOnetimeOrder\", params) as Promise<CancelOnetimeOrderResult>, [callAction]),\n );\n\n const reactivateSubscription = useBuyerAction<ReactivateSubscriptionParams, ReactivateSubscriptionResult>(\n useCallback((params) => callAction(\"reactivateSubscription\", params) as Promise<ReactivateSubscriptionResult>, [callAction]),\n );\n\n const createRefundTicket = useBuyerAction<CreateRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"createRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const createRefundTicketMapped = useMemo(\n () => ({ ...createRefundTicket, data: createRefundTicket.data?.ticket ?? null }),\n [createRefundTicket],\n );\n\n const resubmitRefundTicket = useBuyerAction<ResubmitRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"resubmitRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const resubmitRefundTicketMapped = useMemo(\n () => ({ ...resubmitRefundTicket, data: resubmitRefundTicket.data?.ticket ?? null }),\n [resubmitRefundTicket],\n );\n\n const query = useCallback(\n async <T = Record<string, unknown>>(params: GraphQLParams) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, \"query\", params) as Promise<GraphQLResponse<T>>;\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n return {\n cancelSubscription,\n cancelOnetimeOrder,\n reactivateSubscription,\n createRefundTicket: createRefundTicketMapped,\n resubmitRefundTicket: resubmitRefundTicketMapped,\n query,\n };\n}\n","\"use client\";\n\nimport { useCallback, useContext } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\nimport { useQuery } from \"./use-query.js\";\n\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/** A buyer's one-time order */\nexport interface BuyerOnetimeOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's subscription order */\nexport interface BuyerSubscriptionOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's payment record */\nexport interface BuyerPayment {\n id: string;\n orderId: string;\n status: string;\n snapshotDisplayAmount: string;\n snapshotDisplayCurrency: string;\n failureReason: string | null;\n createdAt: string;\n}\n\n/** A buyer's refund ticket */\nexport interface BuyerRefundTicket {\n id: string;\n status: string;\n reason: string;\n requestedAmount: string;\n requestedCurrency: string;\n createdAt: string;\n}\n\n// ============================================================\n// Queries\n// ============================================================\n\nconst BUYER_ORDERS_QUERY = `query {\n onetimeOrders(limit: 50) {\n id status currency buyerEmail createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n subscriptionOrders(limit: 50) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n}`;\n\nconst BUYER_PAYMENTS_QUERY = `query {\n payments(limit: 50) {\n id orderId status snapshotDisplayAmount snapshotDisplayCurrency failureReason createdAt\n }\n}`;\n\nconst BUYER_REFUND_TICKETS_QUERY = `query {\n refundTickets(limit: 50) {\n id status reason requestedAmount requestedCurrency createdAt\n }\n}`;\n\n// ============================================================\n// Internal helper\n// ============================================================\n\nfunction useBuyerQuery<T>(query: string): QueryState<T> {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"Buyer data hook: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction, isBuyerReady } = ctx;\n\n const queryFn = useCallback(async () => {\n const token = await getBuyerToken();\n const result = (await buyerSessionAction(token, \"query\", { query })) as unknown as GraphQLResponse<T>;\n return result.data as T;\n }, [getBuyerToken, buyerSessionAction, query]);\n\n return useQuery(queryFn, isBuyerReady);\n}\n\n// ============================================================\n// Hooks\n// ============================================================\n\ninterface BuyerOrdersData {\n onetimeOrders: BuyerOnetimeOrder[];\n subscriptionOrders: BuyerSubscriptionOrder[];\n}\n\n/**\n * Fetch the buyer's order history (one-time + subscription).\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Orders with product info and payment history\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useBuyerOrders();\n * // data.onetimeOrders + data.subscriptionOrders\n * ```\n */\nexport function useBuyerOrders(): QueryState<BuyerOrdersData> {\n return useBuyerQuery<BuyerOrdersData>(BUYER_ORDERS_QUERY);\n}\n\n/**\n * Fetch the buyer's payment history.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Payment records with amounts and status\n *\n * @example\n * ```tsx\n * const { data: payments, isLoading } = useBuyerPayments();\n * ```\n */\nexport function useBuyerPayments(): QueryState<BuyerPayment[]> {\n const result = useBuyerQuery<{ payments: BuyerPayment[] }>(BUYER_PAYMENTS_QUERY);\n return { ...result, data: result.data?.payments ?? null };\n}\n\n/**\n * Fetch the buyer's refund tickets.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Refund tickets with status and requested amounts\n *\n * @example\n * ```tsx\n * const { data: tickets, isLoading } = useBuyerRefundTickets();\n * ```\n */\nexport function useBuyerRefundTickets(): QueryState<BuyerRefundTicket[]> {\n const result = useBuyerQuery<{ refundTickets: BuyerRefundTicket[] }>(BUYER_REFUND_TICKETS_QUERY);\n return { ...result, data: result.data?.refundTickets ?? null };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\n/** Query state with typed data */\nexport interface QueryState<T> {\n data: T | null;\n isLoading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Internal hook for async data fetching with loading/error state.\n *\n * @param queryFn - Async function that returns the data\n * @param ready - Whether to start fetching (false = wait)\n * @returns Query state with data, loading, error, and refetch\n */\nexport function useQuery<T>(queryFn: () => Promise<T>, ready: boolean): QueryState<T> {\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(() => {\n if (!ready) return;\n setIsLoading(true);\n setError(null);\n queryFn()\n .then(setData)\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))))\n .finally(() => setIsLoading(false));\n }, [queryFn, ready]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\n\nimport { useQuery } from \"./use-query.js\";\n\nimport type { MerchantQueryAction } from \"./server.js\";\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Merchant Data Hooks (via server action)\n// ============================================================\n\n/** A merchant's recent order (one-time or subscription) */\nexport interface MerchantOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n testMode: boolean;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string }>;\n createdAt: string;\n}\n\n/** Sales overview statistics */\nexport interface SalesOverview {\n totalOrders: number;\n totalRevenue: string;\n totalCustomers: number;\n currency: string;\n ordersByStatus: Array<{ status: string; count: number }>;\n revenueByPeriod: Array<{ period: string; amount: string }>;\n}\n\n/** Subscription overview */\nexport interface SubscriptionOverview {\n activeCount: number;\n cancelingCount: number;\n pastDueCount: number;\n totalCount: number;\n subscriptions: MerchantSubscription[];\n}\n\n/** A merchant's subscription with status details */\nexport interface MerchantSubscription {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n createdAt: string;\n}\n\nexport interface MerchantOrdersOptions {\n /** Store ID to filter by */\n storeId: string;\n /** Max results (default: 20) */\n limit?: number;\n}\n\nconst MERCHANT_ORDERS_QUERY = `query ($storeId: ID!, $limit: Int) {\n onetimeOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n subscriptionOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n}`;\n\n/**\n * Fetch recent orders for a store (one-time + subscription).\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param options - Store ID and optional limit\n * @returns Recent orders with product info and payment summary\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useMerchantOrders(merchantQuery, { storeId: \"STO_xxx\" });\n * ```\n */\nexport function useMerchantOrders(\n query: MerchantQueryAction,\n options: MerchantOrdersOptions,\n): QueryState<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }> {\n const { storeId, limit = 20 } = options;\n\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_ORDERS_QUERY,\n variables: { storeId, limit },\n })) as unknown as GraphQLResponse<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }>;\n return result.data as { onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] };\n }, [query, storeId, limit]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SALES_QUERY = `query ($storeId: ID!) {\n orderStatistics(storeId: $storeId) {\n totalCount\n countByStatus { status count }\n }\n paymentStatistics(storeId: $storeId) {\n totalSucceededAmount\n totalSucceededCurrency\n totalSucceededCount\n }\n customerAnalysis(storeId: $storeId) {\n totalCustomers\n }\n trendAnalysis(storeId: $storeId) {\n revenueByPeriod { period amount }\n }\n}`;\n\ninterface SalesQueryData {\n orderStatistics: { totalCount: number; countByStatus: Array<{ status: string; count: number }> };\n paymentStatistics: { totalSucceededAmount: string; totalSucceededCurrency: string; totalSucceededCount: number };\n customerAnalysis: { totalCustomers: number };\n trendAnalysis: { revenueByPeriod: Array<{ period: string; amount: string }> };\n}\n\n/**\n * Fetch sales overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Aggregated sales statistics\n *\n * @example\n * ```tsx\n * const { data: sales } = useMerchantSales(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSales(query: MerchantQueryAction, storeId: string): QueryState<SalesOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SALES_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<SalesQueryData>;\n const d = result.data as SalesQueryData;\n return {\n totalOrders: d.orderStatistics.totalCount,\n totalRevenue: d.paymentStatistics.totalSucceededAmount,\n totalCustomers: d.customerAnalysis.totalCustomers,\n currency: d.paymentStatistics.totalSucceededCurrency,\n ordersByStatus: d.orderStatistics.countByStatus,\n revenueByPeriod: d.trendAnalysis.revenueByPeriod,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SUBSCRIPTIONS_QUERY = `query ($storeId: ID!) {\n subscriptionOrders(storeId: $storeId, limit: 100) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n }\n}`;\n\n/**\n * Fetch subscription overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Subscription counts and detailed list\n *\n * @example\n * ```tsx\n * const { data: subs } = useMerchantSubscriptions(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSubscriptions(query: MerchantQueryAction, storeId: string): QueryState<SubscriptionOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SUBSCRIPTIONS_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<{ subscriptionOrders: MerchantSubscription[] }>;\n const subs = (result.data as { subscriptionOrders: MerchantSubscription[] }).subscriptionOrders;\n return {\n activeCount: subs.filter((s) => s.status === \"active\").length,\n cancelingCount: subs.filter((s) => s.status === \"canceling\").length,\n pastDueCount: subs.filter((s) => s.status === \"past_due\").length,\n totalCount: subs.length,\n subscriptions: subs,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n","import { verifyWebhook } from \"@waffo/pancake-ts\";\n\nimport type { VerifyWebhookOptions, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n/** Handler function for a specific webhook event */\ntype EventHandler<T = WebhookEventData> = (event: WebhookEvent<T>) => void | Promise<void>;\n\n/** Configuration for the Webhook route handler factory */\nexport interface WebhookConfig {\n /** Webhook signature verification options (environment, publicKey, tolerance, etc.) */\n verifyOptions?: VerifyWebhookOptions;\n\n /** Catch-all handler — called for every event regardless of type */\n onPayload?: EventHandler;\n\n /** One-time order first payment succeeded */\n onOrderCompleted?: EventHandler;\n /** Subscription first payment succeeded (newly activated) */\n onSubscriptionActivated?: EventHandler;\n /** Subscription renewal payment succeeded */\n onSubscriptionPaymentSucceeded?: EventHandler;\n /** Buyer initiated cancellation (expires at end of current period) */\n onSubscriptionCanceling?: EventHandler;\n /** Buyer withdrew cancellation (subscription restored) */\n onSubscriptionUncanceled?: EventHandler;\n /** Subscription product changed (upgrade/downgrade) */\n onSubscriptionUpdated?: EventHandler;\n /** Subscription fully terminated */\n onSubscriptionCanceled?: EventHandler;\n /** Renewal payment failed (past due) */\n onSubscriptionPastDue?: EventHandler;\n /** Refund succeeded */\n onRefundSucceeded?: EventHandler;\n /** Refund failed */\n onRefundFailed?: EventHandler;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention -- event type keys use dot notation */\nconst EVENT_HANDLER_MAP: Record<string, keyof WebhookConfig> = {\n \"order.completed\": \"onOrderCompleted\",\n \"subscription.activated\": \"onSubscriptionActivated\",\n \"subscription.payment_succeeded\": \"onSubscriptionPaymentSucceeded\",\n \"subscription.canceling\": \"onSubscriptionCanceling\",\n \"subscription.uncanceled\": \"onSubscriptionUncanceled\",\n \"subscription.updated\": \"onSubscriptionUpdated\",\n \"subscription.canceled\": \"onSubscriptionCanceled\",\n \"subscription.past_due\": \"onSubscriptionPastDue\",\n \"refund.succeeded\": \"onRefundSucceeded\",\n \"refund.failed\": \"onRefundFailed\",\n};\n/* eslint-enable @typescript-eslint/naming-convention */\n\n/**\n * Create a Next.js POST route handler for Waffo Pancake webhooks.\n *\n * Automatically verifies the webhook signature using `@waffo/pancake-ts`,\n * then dispatches to the matching event handler.\n *\n * @param config - Verification options and event handlers\n * @returns A Next.js POST route handler\n *\n * @example\n * ```ts\n * // app/api/webhooks/waffo/route.ts\n * import { Webhook } from \"@waffo/pancake-nextjs\";\n *\n * export const POST = Webhook({\n * verifyOptions: { environment: \"prod\" },\n * onOrderCompleted: async (event) => {\n * console.log(\"Order completed:\", event.data.orderId);\n * // Grant access to the product\n * },\n * onSubscriptionActivated: async (event) => {\n * console.log(\"Subscription activated:\", event.data.orderId);\n * },\n * onRefundSucceeded: async (event) => {\n * console.log(\"Refund succeeded:\", event.data.refundId);\n * // Revoke access\n * },\n * });\n * ```\n */\nexport function Webhook(config: WebhookConfig) {\n return async function POST(request: Request): Promise<Response> {\n const payload = await request.text();\n const signature = request.headers.get(\"x-waffo-signature\");\n\n let event: WebhookEvent;\n try {\n event = verifyWebhook(payload, signature, config.verifyOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook verification failed\";\n return new Response(JSON.stringify({ error: message }), {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n try {\n // Catch-all handler\n if (config.onPayload) {\n await config.onPayload(event);\n }\n\n // Event-specific handler\n const handlerKey = EVENT_HANDLER_MAP[event.eventType];\n if (handlerKey) {\n const handler = config[handlerKey] as EventHandler | undefined;\n if (handler) {\n await handler(event);\n }\n }\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook handler error\";\n return new Response(JSON.stringify({ error: message }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n };\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_react","import_react","import_react","import_pancake_ts"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/use-checkout.ts","../src/checkout-button.tsx","../src/use-buyer.ts","../src/use-buyer-data.ts","../src/use-query.ts","../src/use-merchant-data.ts","../src/webhook.ts"],"sourcesContent":["export { WaffoPancakeProvider } from \"./provider.js\";\nexport { CheckoutButton } from \"./checkout-button.js\";\nexport { useCheckout } from \"./use-checkout.js\";\nexport { useBuyer } from \"./use-buyer.js\";\nexport { useBuyerOrders, useBuyerPayments, useBuyerRefundTickets } from \"./use-buyer-data.js\";\nexport { useMerchantOrders, useMerchantSales, useMerchantSubscriptions } from \"./use-merchant-data.js\";\nexport { Webhook } from \"./webhook.js\";\n\n// Re-export types commonly used in client components\nexport { WaffoPancakeError, TaxCategory, WebhookEventType } from \"@waffo/pancake-ts\";\n\nexport type { PriceInfo, BillingDetail, RequestedAmount, RefundTicketVersionData, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n// Local types\nexport type {\n CheckoutMode,\n CheckoutBaseOptions,\n LinkCheckoutProps,\n AnonymousCheckoutProps,\n AuthenticatedCheckoutProps,\n CheckoutProps,\n UseCheckoutReturn,\n} from \"./types.js\";\n\nexport type { BuyerConfig, WaffoPancakeProviderProps } from \"./provider.js\";\n\nexport type {\n CheckoutButtonProps,\n LinkCheckoutButtonProps,\n AnonymousCheckoutButtonProps,\n AuthenticatedCheckoutButtonProps,\n} from \"./checkout-button.js\";\n\nexport type { BuyerActionState, UseBuyerReturn } from \"./use-buyer.js\";\n\nexport type { QueryState } from \"./use-query.js\";\n\nexport type { BuyerOnetimeOrder, BuyerSubscriptionOrder, BuyerPayment, BuyerRefundTicket } from \"./use-buyer-data.js\";\n\nexport type {\n MerchantOrder,\n MerchantSubscription,\n SalesOverview,\n SubscriptionOverview,\n MerchantOrdersOptions,\n} from \"./use-merchant-data.js\";\n\nexport type { WebhookConfig } from \"./webhook.js\";\n\n// Server action types (for typing the action prop)\nexport type {\n CheckoutAction,\n CheckoutActionParams,\n CheckoutActionResult,\n BuyerTokenAction,\n BuyerSessionAction,\n MerchantQueryAction,\n} from \"./server.js\";\n","\"use client\";\n\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { BuyerTokenAction, BuyerSessionAction } from \"./server.js\";\n\n/** Buyer configuration for automatic token management */\nexport interface BuyerConfig {\n /** Buyer identity (email or merchant-provided identifier) */\n identity: 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 /** Server action for issuing tokens — from `createBuyerTokenAction()` */\n issueToken: BuyerTokenAction;\n /** Server action for buyer operations — from `createBuyerSessionAction()` */\n sessionAction: BuyerSessionAction;\n}\n\ninterface TokenState {\n token: string;\n expiresAt: number;\n}\n\n/** @internal */\nexport interface PancakeContextValue {\n /** Get a valid buyer token (auto-refreshes if expired) */\n getBuyerToken: () => Promise<string>;\n /** Execute a buyer session operation via server action */\n buyerSessionAction: BuyerSessionAction;\n /** Whether buyer config is provided */\n hasBuyer: boolean;\n /** Whether the initial token is ready */\n isBuyerReady: boolean;\n}\n\n/** @internal Exported for direct useContext access in hooks */\nexport const PancakeContext = createContext<PancakeContextValue | null>(null);\n\n/** Token refresh buffer — refresh 30s before actual expiry */\nconst REFRESH_BUFFER_MS = 30_000;\n\nexport interface WaffoPancakeProviderProps {\n /** Buyer configuration for automatic token management */\n buyer: BuyerConfig;\n children: React.ReactNode;\n}\n\n/**\n * Provider that manages buyer token lifecycle via server actions.\n *\n * Auto-issues session tokens on mount and refreshes before expiry.\n * All buyer hooks (`useBuyer`, `useBuyerOrders`, etc.) read from context.\n *\n * The private key never leaves the server — token issuance and buyer\n * operations are delegated to server actions.\n *\n * @param props - Provider configuration\n * @param props.buyer - Buyer identity and server actions\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * // identity must match what you passed as `buyerIdentity` at checkout time —\n * // buyer-portal lookups are keyed by merchant_provided_buyer_identity\n * <WaffoPancakeProvider buyer={{\n * identity: user.id,\n * storeId: \"STO_xxx\",\n * issueToken, // from createBuyerTokenAction()\n * sessionAction, // from createBuyerSessionAction()\n * }}>\n * <App />\n * </WaffoPancakeProvider>\n * ```\n */\nexport function WaffoPancakeProvider({ buyer, children }: WaffoPancakeProviderProps) {\n const tokenRef = useRef<TokenState | null>(null);\n const refreshPromiseRef = useRef<Promise<string> | null>(null);\n const [isBuyerReady, setIsBuyerReady] = useState(false);\n\n const refreshToken = useCallback(async (): Promise<string> => {\n const result = await buyer.issueToken({\n buyerIdentity: buyer.identity,\n storeId: buyer.storeId,\n productId: buyer.productId,\n });\n\n tokenRef.current = {\n token: result.token,\n expiresAt: new Date(result.expiresAt).getTime(),\n };\n\n return result.token;\n }, [buyer]);\n\n const getBuyerToken = useCallback(async (): Promise<string> => {\n const current = tokenRef.current;\n if (current && Date.now() < current.expiresAt - REFRESH_BUFFER_MS) {\n return current.token;\n }\n\n // Deduplicate concurrent refresh calls\n if (!refreshPromiseRef.current) {\n refreshPromiseRef.current = refreshToken().finally(() => {\n refreshPromiseRef.current = null;\n });\n }\n\n return refreshPromiseRef.current;\n }, [refreshToken]);\n\n // Issue initial token on mount\n useEffect(() => {\n refreshToken()\n .then(() => setIsBuyerReady(true))\n .catch(() => setIsBuyerReady(true));\n }, [refreshToken]);\n\n const value = useMemo<PancakeContextValue>(\n () => ({\n getBuyerToken,\n buyerSessionAction: buyer.sessionAction,\n hasBuyer: true,\n isBuyerReady,\n }),\n [getBuyerToken, buyer.sessionAction, isBuyerReady],\n );\n\n return <PancakeContext.Provider value={value}>{children}</PancakeContext.Provider>;\n}\n\n/**\n * Access the Waffo Pancake context. Must be used within `<WaffoPancakeProvider>`.\n */\nexport function usePancakeContext(): PancakeContextValue {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"usePancakeContext: must be used within <WaffoPancakeProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\n\nimport type { CheckoutProps, LinkCheckoutProps, UseCheckoutReturn } from \"./types.js\";\nimport type { CheckoutSessionResult, AuthenticatedCheckoutResult } from \"@waffo/pancake-ts\";\n\n\nconst LOADING_HTML = `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Loading...</title><style>body{display:flex;align-items:center;justify-content:center;height:100vh;margin:0;font-family:system-ui,sans-serif;background:#f9fafb;color:#6b7280}@media(prefers-color-scheme:dark){body{background:#111827;color:#9ca3af}}</style></head><body><p>Redirecting to checkout...</p></body></html>`;\n\nconst DEFAULT_STOREFRONT_URL = \"https://pancake.waffo.ai\";\n\nconst SDK_FIELDS = new Set([\"action\", \"type\", \"mode\", \"popupLoadingUrl\", \"onSuccess\", \"onError\"]);\n\n/** Extract API checkout params from flattened props, removing SDK-specific fields */\nfunction extractApiParams(args: object): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(args)) {\n if (!SDK_FIELDS.has(key)) params[key] = value;\n }\n return params;\n}\n\n/**\n * Build a product page URL for link checkout.\n */\nfunction buildLinkUrl(props: LinkCheckoutProps): string {\n const base = (props.baseUrl ?? DEFAULT_STOREFRONT_URL).replace(/\\/+$/, \"\");\n const url = new URL(`${base}/store/${props.storeSlug}/product/${props.productId}`);\n\n if (props.currency) url.searchParams.set(\"currency\", props.currency);\n if (props.email) url.searchParams.set(\"email\", props.email);\n if (props.successUrl) url.searchParams.set(\"success_url\", props.successUrl);\n if (props.test) url.searchParams.set(\"test\", \"true\");\n if (props.country) url.searchParams.set(\"country\", props.country);\n if (props.isBusiness) url.searchParams.set(\"is_business\", \"true\");\n\n return url.toString();\n}\n\n/**\n * React hook for triggering a Waffo Pancake checkout flow.\n *\n * Supports three checkout types:\n * - **link**: Builds a product page URL and navigates directly (no API call, synchronous)\n * - **anonymous**: Calls a server action to create a checkout session, then navigates\n * - **authenticated**: Calls a server action to create a session + token, then navigates\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param args - Flattened checkout props\n * @returns `{ checkout, isLoading, error }`\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * const { checkout } = useCheckout({\n * type: \"link\",\n * storeSlug: \"my-store\",\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * // Anonymous checkout — via server action\n * const { checkout, isLoading } = useCheckout({\n * action: checkout, // from createCheckoutAction()\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n * ```\n */\nexport function useCheckout(args: CheckoutProps): UseCheckoutReturn {\n const { mode = \"redirect\", popupLoadingUrl, onError } = args;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const popupRef = useRef<Window | null>(null);\n\n const checkout = useCallback(() => {\n if (isLoading) return;\n\n // Link checkout — synchronous, no API call\n if (args.type === \"link\") {\n const url = buildLinkUrl(args);\n if (mode === \"popup\") {\n window.open(url, \"_blank\");\n } else {\n window.location.href = url;\n }\n return;\n }\n\n // Anonymous / Authenticated — server action\n if (mode === \"popup\") {\n const loadingUrl = popupLoadingUrl ?? `data:text/html;charset=utf-8,${encodeURIComponent(LOADING_HTML)}`;\n popupRef.current = window.open(loadingUrl, \"_blank\");\n }\n\n setIsLoading(true);\n setError(null);\n\n const { action } = args;\n const params = extractApiParams(args);\n const actionParams = args.type === \"authenticated\" ? { type: \"authenticated\" as const, ...params } : params;\n\n action(actionParams as unknown as Parameters<typeof action>[0])\n .then((result: CheckoutSessionResult | AuthenticatedCheckoutResult) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.location.href = result.checkoutUrl;\n } else {\n window.location.href = result.checkoutUrl;\n }\n if (\"onSuccess\" in args && args.onSuccess) {\n (args.onSuccess as (r: CheckoutSessionResult | AuthenticatedCheckoutResult) => void)(result);\n }\n })\n .catch((err: Error) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.close();\n popupRef.current = null;\n }\n setError(err);\n onError?.(err);\n })\n .finally(() => {\n setIsLoading(false);\n });\n }, [args, mode, popupLoadingUrl, onError, isLoading]);\n\n return { checkout, isLoading, error };\n}\n","\"use client\";\n\nimport React from \"react\";\n\nimport { useCheckout } from \"./use-checkout.js\";\n\nimport type { CheckoutProps, LinkCheckoutProps, AnonymousCheckoutProps, AuthenticatedCheckoutProps } from \"./types.js\";\n\ntype CheckoutButtonBaseProps = {\n /** Button content */\n children: React.ReactNode;\n /** Content shown while checkout session is being created */\n loadingChildren?: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Disabled state (merged with isLoading) */\n disabled?: boolean;\n} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\" | \"disabled\" | \"children\">;\n\n/** Props for CheckoutButton — link mode */\nexport type LinkCheckoutButtonProps = CheckoutButtonBaseProps & LinkCheckoutProps;\n\n/** Props for CheckoutButton — anonymous mode */\nexport type AnonymousCheckoutButtonProps = CheckoutButtonBaseProps & AnonymousCheckoutProps;\n\n/** Props for CheckoutButton — authenticated mode */\nexport type AuthenticatedCheckoutButtonProps = CheckoutButtonBaseProps & AuthenticatedCheckoutProps;\n\nexport type CheckoutButtonProps = LinkCheckoutButtonProps | AnonymousCheckoutButtonProps | AuthenticatedCheckoutButtonProps;\n\n/**\n * A button that triggers a Waffo Pancake checkout flow on click.\n *\n * Three checkout types:\n * - **link**: Instant redirect to product page URL (no server action needed)\n * - **anonymous**: Calls server action to create session, then redirects\n * - **authenticated**: Calls server action to create session + token, then redirects\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param props - Flattened checkout props, button content, and optional styling\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * <CheckoutButton type=\"link\" storeSlug=\"my-store\" productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Anonymous checkout — via server action\n * <CheckoutButton action={checkout} productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Authenticated checkout — via server action\n * <CheckoutButton action={checkout} type=\"authenticated\" productId=\"PROD_xxx\" currency=\"USD\" buyerIdentity=\"userIdInYourSystem\" buyerEmail=\"user@example.com\">\n * Buy Now\n * </CheckoutButton>\n * ```\n */\nexport function CheckoutButton(props: CheckoutButtonProps) {\n const { children, loadingChildren, className, style, disabled, ...checkoutProps } = props;\n\n const { checkout, isLoading } = useCheckout(checkoutProps as CheckoutProps);\n\n return (\n <button type=\"button\" onClick={checkout} disabled={disabled || isLoading} className={className} style={style}>\n {isLoading ? (loadingChildren ?? children) : children}\n </button>\n );\n}\n","\"use client\";\n\nimport { useCallback, useContext, useMemo, useState } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\n\nimport type {\n CancelSubscriptionParams,\n CancelSubscriptionResult,\n CancelOnetimeOrderParams,\n CancelOnetimeOrderResult,\n ReactivateSubscriptionParams,\n ReactivateSubscriptionResult,\n CreateRefundTicketParams,\n ResubmitRefundTicketParams,\n RefundTicket,\n GraphQLParams,\n GraphQLResponse,\n} from \"@waffo/pancake-ts\";\n\n/** State of an async buyer action */\nexport interface BuyerActionState<T = unknown> {\n /** Execute the action */\n execute: (params: T) => Promise<void>;\n /** Whether the action is in progress */\n isLoading: boolean;\n /** Error from the last attempt */\n error: Error | null;\n}\n\n/** Return type of useBuyer hook */\nexport interface UseBuyerReturn {\n /** Cancel a subscription order */\n cancelSubscription: BuyerActionState<CancelSubscriptionParams> & { data: CancelSubscriptionResult | null };\n /** Cancel a one-time order */\n cancelOnetimeOrder: BuyerActionState<CancelOnetimeOrderParams> & { data: CancelOnetimeOrderResult | null };\n /** Reactivate a canceling subscription */\n reactivateSubscription: BuyerActionState<ReactivateSubscriptionParams> & { data: ReactivateSubscriptionResult | null };\n /** Create a refund ticket */\n createRefundTicket: BuyerActionState<CreateRefundTicketParams> & { data: RefundTicket | null };\n /** Resubmit a rejected refund ticket */\n resubmitRefundTicket: BuyerActionState<ResubmitRefundTicketParams> & { data: RefundTicket | null };\n /** Execute a GraphQL query */\n query: <T = Record<string, unknown>>(params: GraphQLParams) => Promise<GraphQLResponse<T>>;\n}\n\nfunction useBuyerAction<TParams, TResult>(\n actionFn: (params: TParams) => Promise<TResult>,\n): BuyerActionState<TParams> & { data: TResult | null } {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TResult | null>(null);\n\n const execute = useCallback(\n async (params: TParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await actionFn(params);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [actionFn],\n );\n\n return { execute, isLoading, error, data };\n}\n\n/**\n * React hook for buyer self-service actions.\n *\n * Must be used within `<WaffoPancakeProvider>`. All operations are executed\n * via server actions — the private key never leaves the server.\n *\n * @returns Buyer action handlers with loading/error states\n *\n * @example\n * ```tsx\n * function AccountPage() {\n * const buyer = useBuyer();\n * return (\n * <button onClick={() => buyer.cancelSubscription.execute({ orderId: \"ORD_xxx\" })}>\n * Cancel\n * </button>\n * );\n * }\n * ```\n */\nexport function useBuyer(): UseBuyerReturn {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"useBuyer: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction } = ctx;\n\n const callAction = useCallback(\n async (actionType: string, params: unknown) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, actionType as never, params);\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n const cancelSubscription = useBuyerAction<CancelSubscriptionParams, CancelSubscriptionResult>(\n useCallback((params) => callAction(\"cancelSubscription\", params) as Promise<CancelSubscriptionResult>, [callAction]),\n );\n\n const cancelOnetimeOrder = useBuyerAction<CancelOnetimeOrderParams, CancelOnetimeOrderResult>(\n useCallback((params) => callAction(\"cancelOnetimeOrder\", params) as Promise<CancelOnetimeOrderResult>, [callAction]),\n );\n\n const reactivateSubscription = useBuyerAction<ReactivateSubscriptionParams, ReactivateSubscriptionResult>(\n useCallback((params) => callAction(\"reactivateSubscription\", params) as Promise<ReactivateSubscriptionResult>, [callAction]),\n );\n\n const createRefundTicket = useBuyerAction<CreateRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"createRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const createRefundTicketMapped = useMemo(\n () => ({ ...createRefundTicket, data: createRefundTicket.data?.ticket ?? null }),\n [createRefundTicket],\n );\n\n const resubmitRefundTicket = useBuyerAction<ResubmitRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"resubmitRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const resubmitRefundTicketMapped = useMemo(\n () => ({ ...resubmitRefundTicket, data: resubmitRefundTicket.data?.ticket ?? null }),\n [resubmitRefundTicket],\n );\n\n const query = useCallback(\n async <T = Record<string, unknown>>(params: GraphQLParams) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, \"query\", params) as Promise<GraphQLResponse<T>>;\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n return {\n cancelSubscription,\n cancelOnetimeOrder,\n reactivateSubscription,\n createRefundTicket: createRefundTicketMapped,\n resubmitRefundTicket: resubmitRefundTicketMapped,\n query,\n };\n}\n","\"use client\";\n\nimport { useCallback, useContext } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\nimport { useQuery } from \"./use-query.js\";\n\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse, RefundTicketVersionData } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/** A buyer's one-time order */\nexport interface BuyerOnetimeOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's subscription order */\nexport interface BuyerSubscriptionOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's payment record */\nexport interface BuyerPayment {\n id: string;\n orderId: string;\n status: string;\n snapshotDisplayAmount: string;\n snapshotDisplayCurrency: string;\n failureReason: string | null;\n createdAt: string;\n}\n\n/**\n * A buyer's refund ticket.\n *\n * Ticket-level fields are flat; per-version fields (`reason`, `requestedAmount`)\n * live under `versionData` because the buyer can resubmit a rejected ticket and\n * each submission is a versioned record. `versionData` reflects the current\n * (latest) version. The `versionData` shape is shared with `@waffo/pancake-ts`'s\n * `RefundTicketVersionData`.\n */\nexport interface BuyerRefundTicket {\n id: string;\n status: string;\n versionNumber: number | null;\n versionData: RefundTicketVersionData | null;\n createdAt: string;\n}\n\n// ============================================================\n// Queries\n// ============================================================\n\nconst BUYER_ORDERS_QUERY = `query {\n onetimeOrders(limit: 50) {\n id status currency buyerEmail createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n subscriptionOrders(limit: 50) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n}`;\n\nconst BUYER_PAYMENTS_QUERY = `query {\n payments(limit: 50) {\n id orderId status snapshotDisplayAmount snapshotDisplayCurrency failureReason createdAt\n }\n}`;\n\nconst BUYER_REFUND_TICKETS_QUERY = `query {\n refundTickets(limit: 50) {\n id status versionNumber\n versionData {\n reason\n requestedAmount { amount currency }\n }\n createdAt\n }\n}`;\n\n// ============================================================\n// Internal helper\n// ============================================================\n\nfunction useBuyerQuery<T>(query: string): QueryState<T> {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"Buyer data hook: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction, isBuyerReady } = ctx;\n\n const queryFn = useCallback(async () => {\n const token = await getBuyerToken();\n const result = (await buyerSessionAction(token, \"query\", { query })) as unknown as GraphQLResponse<T>;\n return result.data as T;\n }, [getBuyerToken, buyerSessionAction, query]);\n\n return useQuery(queryFn, isBuyerReady);\n}\n\n// ============================================================\n// Hooks\n// ============================================================\n\ninterface BuyerOrdersData {\n onetimeOrders: BuyerOnetimeOrder[];\n subscriptionOrders: BuyerSubscriptionOrder[];\n}\n\n/**\n * Fetch the buyer's order history (one-time + subscription).\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Orders with product info and payment history\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useBuyerOrders();\n * // data.onetimeOrders + data.subscriptionOrders\n * ```\n */\nexport function useBuyerOrders(): QueryState<BuyerOrdersData> {\n return useBuyerQuery<BuyerOrdersData>(BUYER_ORDERS_QUERY);\n}\n\n/**\n * Fetch the buyer's payment history.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Payment records with amounts and status\n *\n * @example\n * ```tsx\n * const { data: payments, isLoading } = useBuyerPayments();\n * ```\n */\nexport function useBuyerPayments(): QueryState<BuyerPayment[]> {\n const result = useBuyerQuery<{ payments: BuyerPayment[] }>(BUYER_PAYMENTS_QUERY);\n return { ...result, data: result.data?.payments ?? null };\n}\n\n/**\n * Fetch the buyer's refund tickets.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Refund tickets with status and requested amounts\n *\n * @example\n * ```tsx\n * const { data: tickets, isLoading } = useBuyerRefundTickets();\n * ```\n */\nexport function useBuyerRefundTickets(): QueryState<BuyerRefundTicket[]> {\n const result = useBuyerQuery<{ refundTickets: BuyerRefundTicket[] }>(BUYER_REFUND_TICKETS_QUERY);\n return { ...result, data: result.data?.refundTickets ?? null };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\n/** Query state with typed data */\nexport interface QueryState<T> {\n data: T | null;\n isLoading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Internal hook for async data fetching with loading/error state.\n *\n * @param queryFn - Async function that returns the data\n * @param ready - Whether to start fetching (false = wait)\n * @returns Query state with data, loading, error, and refetch\n */\nexport function useQuery<T>(queryFn: () => Promise<T>, ready: boolean): QueryState<T> {\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(() => {\n if (!ready) return;\n setIsLoading(true);\n setError(null);\n queryFn()\n .then(setData)\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))))\n .finally(() => setIsLoading(false));\n }, [queryFn, ready]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\n\nimport { useQuery } from \"./use-query.js\";\n\nimport type { MerchantQueryAction } from \"./server.js\";\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Merchant Data Hooks (via server action)\n// ============================================================\n\n/** A merchant's recent order (one-time or subscription) */\nexport interface MerchantOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n testMode: boolean;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string }>;\n createdAt: string;\n}\n\n/**\n * Sales overview statistics.\n *\n * Monetary fields (`totalRevenue`, `revenueByPeriod[].amount`) are returned as\n * display-formatted strings (e.g., `\"9.99\"`), not minor-currency-unit integers.\n * The conversion happens server-side via the GraphQL `currencyDisplayLoader`.\n */\nexport interface SalesOverview {\n totalOrders: number;\n /** Total succeeded payment revenue as display string (e.g., `\"1234.56\"`) */\n totalRevenue: string;\n totalCustomers: number;\n currency: string;\n ordersByStatus: Array<{ status: string; count: number }>;\n /** Revenue by period; `amount` is a display string (e.g., `\"9.99\"`) */\n revenueByPeriod: Array<{ period: string; amount: string }>;\n}\n\n/** Subscription overview */\nexport interface SubscriptionOverview {\n activeCount: number;\n cancelingCount: number;\n pastDueCount: number;\n totalCount: number;\n subscriptions: MerchantSubscription[];\n}\n\n/** A merchant's subscription with status details */\nexport interface MerchantSubscription {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n createdAt: string;\n}\n\nexport interface MerchantOrdersOptions {\n /** Store ID to filter by */\n storeId: string;\n /** Max results (default: 20) */\n limit?: number;\n}\n\nconst MERCHANT_ORDERS_QUERY = `query ($storeId: ID!, $limit: Int) {\n onetimeOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n subscriptionOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n}`;\n\n/**\n * Fetch recent orders for a store (one-time + subscription).\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param options - Store ID and optional limit\n * @returns Recent orders with product info and payment summary\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useMerchantOrders(merchantQuery, { storeId: \"STO_xxx\" });\n * ```\n */\nexport function useMerchantOrders(\n query: MerchantQueryAction,\n options: MerchantOrdersOptions,\n): QueryState<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }> {\n const { storeId, limit = 20 } = options;\n\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_ORDERS_QUERY,\n variables: { storeId, limit },\n })) as unknown as GraphQLResponse<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }>;\n return result.data as { onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] };\n }, [query, storeId, limit]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SALES_QUERY = `query ($storeId: ID!) {\n orderStatistics(storeId: $storeId) {\n totalCount\n countByStatus { status count }\n }\n paymentStatistics(storeId: $storeId) {\n totalSucceededAmount\n totalSucceededCurrency\n totalSucceededCount\n }\n customerAnalysis(storeId: $storeId) {\n totalCustomers\n }\n trendAnalysis(storeId: $storeId) {\n revenueByPeriod { period amount }\n }\n}`;\n\ninterface SalesQueryData {\n orderStatistics: { totalCount: number; countByStatus: Array<{ status: string; count: number }> };\n paymentStatistics: { totalSucceededAmount: string; totalSucceededCurrency: string; totalSucceededCount: number };\n customerAnalysis: { totalCustomers: number };\n trendAnalysis: { revenueByPeriod: Array<{ period: string; amount: string }> };\n}\n\n/**\n * Fetch sales overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Aggregated sales statistics\n *\n * @example\n * ```tsx\n * const { data: sales } = useMerchantSales(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSales(query: MerchantQueryAction, storeId: string): QueryState<SalesOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SALES_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<SalesQueryData>;\n const d = result.data as SalesQueryData;\n return {\n totalOrders: d.orderStatistics.totalCount,\n totalRevenue: d.paymentStatistics.totalSucceededAmount,\n totalCustomers: d.customerAnalysis.totalCustomers,\n currency: d.paymentStatistics.totalSucceededCurrency,\n ordersByStatus: d.orderStatistics.countByStatus,\n revenueByPeriod: d.trendAnalysis.revenueByPeriod,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SUBSCRIPTIONS_QUERY = `query ($storeId: ID!) {\n subscriptionOrders(storeId: $storeId, limit: 100) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n }\n}`;\n\n/**\n * Fetch subscription overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Subscription counts and detailed list\n *\n * @example\n * ```tsx\n * const { data: subs } = useMerchantSubscriptions(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSubscriptions(query: MerchantQueryAction, storeId: string): QueryState<SubscriptionOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SUBSCRIPTIONS_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<{ subscriptionOrders: MerchantSubscription[] }>;\n const subs = (result.data as { subscriptionOrders: MerchantSubscription[] }).subscriptionOrders;\n return {\n activeCount: subs.filter((s) => s.status === \"active\").length,\n cancelingCount: subs.filter((s) => s.status === \"canceling\").length,\n pastDueCount: subs.filter((s) => s.status === \"past_due\").length,\n totalCount: subs.length,\n subscriptions: subs,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n","import { verifyWebhook } from \"@waffo/pancake-ts\";\n\nimport type { VerifyWebhookOptions, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n/** Handler function for a specific webhook event */\ntype EventHandler<T = WebhookEventData> = (event: WebhookEvent<T>) => void | Promise<void>;\n\n/** Configuration for the Webhook route handler factory */\nexport interface WebhookConfig {\n /** Webhook signature verification options (environment, publicKey, tolerance, etc.) */\n verifyOptions?: VerifyWebhookOptions;\n\n /** Catch-all handler — called for every event regardless of type */\n onPayload?: EventHandler;\n\n /** One-time order first payment succeeded */\n onOrderCompleted?: EventHandler;\n /** Subscription first payment succeeded (newly activated) */\n onSubscriptionActivated?: EventHandler;\n /** Subscription renewal payment succeeded */\n onSubscriptionPaymentSucceeded?: EventHandler;\n /** Buyer initiated cancellation (expires at end of current period) */\n onSubscriptionCanceling?: EventHandler;\n /** Buyer withdrew cancellation (subscription restored) */\n onSubscriptionUncanceled?: EventHandler;\n /** Subscription product changed (upgrade/downgrade) */\n onSubscriptionUpdated?: EventHandler;\n /** Subscription fully terminated */\n onSubscriptionCanceled?: EventHandler;\n /** Renewal payment failed (past due) */\n onSubscriptionPastDue?: EventHandler;\n /** Refund succeeded */\n onRefundSucceeded?: EventHandler;\n /** Refund failed */\n onRefundFailed?: EventHandler;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention -- event type keys use dot notation */\nconst EVENT_HANDLER_MAP: Record<string, keyof WebhookConfig> = {\n \"order.completed\": \"onOrderCompleted\",\n \"subscription.activated\": \"onSubscriptionActivated\",\n \"subscription.payment_succeeded\": \"onSubscriptionPaymentSucceeded\",\n \"subscription.canceling\": \"onSubscriptionCanceling\",\n \"subscription.uncanceled\": \"onSubscriptionUncanceled\",\n \"subscription.updated\": \"onSubscriptionUpdated\",\n \"subscription.canceled\": \"onSubscriptionCanceled\",\n \"subscription.past_due\": \"onSubscriptionPastDue\",\n \"refund.succeeded\": \"onRefundSucceeded\",\n \"refund.failed\": \"onRefundFailed\",\n};\n/* eslint-enable @typescript-eslint/naming-convention */\n\n/**\n * Create a Next.js POST route handler for Waffo Pancake webhooks.\n *\n * Automatically verifies the webhook signature using `@waffo/pancake-ts`,\n * then dispatches to the matching event handler.\n *\n * @param config - Verification options and event handlers\n * @returns A Next.js POST route handler\n *\n * @example\n * ```ts\n * // app/api/webhooks/waffo/route.ts\n * import { Webhook } from \"@waffo/pancake-nextjs\";\n *\n * export const POST = Webhook({\n * verifyOptions: { environment: \"prod\" },\n * onOrderCompleted: async (event) => {\n * console.log(\"Order completed:\", event.data.orderId);\n * // Grant access to the product\n * },\n * onSubscriptionActivated: async (event) => {\n * console.log(\"Subscription activated:\", event.data.orderId);\n * },\n * onRefundSucceeded: async (event) => {\n * console.log(\"Refund succeeded:\", event.data.refundId);\n * // Revoke access\n * },\n * });\n * ```\n */\nexport function Webhook(config: WebhookConfig) {\n return async function POST(request: Request): Promise<Response> {\n const payload = await request.text();\n const signature = request.headers.get(\"x-waffo-signature\");\n\n let event: WebhookEvent;\n try {\n event = verifyWebhook(payload, signature, config.verifyOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook verification failed\";\n return new Response(JSON.stringify({ error: message }), {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n try {\n // Catch-all handler\n if (config.onPayload) {\n await config.onPayload(event);\n }\n\n // Event-specific handler\n const handlerKey = EVENT_HANDLER_MAP[event.eventType];\n if (handlerKey) {\n const handler = config[handlerKey] as EventHandler | undefined;\n if (handler) {\n await handler(event);\n }\n }\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook handler error\";\n return new Response(JSON.stringify({ error: message }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n };\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_react","import_react","import_react","import_pancake_ts"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { AnonymousCheckoutParams, AuthenticatedCheckoutParams, CheckoutSessionResult, AuthenticatedCheckoutResult, IssueSessionTokenParams, SessionToken, GraphQLParams, GraphQLResponse, CancelSubscriptionParams, CancelSubscriptionResult, CancelOnetimeOrderParams, CancelOnetimeOrderResult, ReactivateSubscriptionParams, ReactivateSubscriptionResult, CreateRefundTicketParams, RefundTicket, ResubmitRefundTicketParams, VerifyWebhookOptions, WebhookEventData, WebhookEvent } from '@waffo/pancake-ts';
|
|
4
|
-
export { BillingDetail, PriceInfo, TaxCategory, WaffoPancakeError, WebhookEvent, WebhookEventData, WebhookEventType } from '@waffo/pancake-ts';
|
|
3
|
+
import { AnonymousCheckoutParams, AuthenticatedCheckoutParams, CheckoutSessionResult, AuthenticatedCheckoutResult, IssueSessionTokenParams, SessionToken, GraphQLParams, GraphQLResponse, CancelSubscriptionParams, CancelSubscriptionResult, CancelOnetimeOrderParams, CancelOnetimeOrderResult, ReactivateSubscriptionParams, ReactivateSubscriptionResult, CreateRefundTicketParams, RefundTicket, ResubmitRefundTicketParams, RefundTicketVersionData, VerifyWebhookOptions, WebhookEventData, WebhookEvent } from '@waffo/pancake-ts';
|
|
4
|
+
export { BillingDetail, PriceInfo, RefundTicketVersionData, RequestedAmount, TaxCategory, WaffoPancakeError, WebhookEvent, WebhookEventData, WebhookEventType } from '@waffo/pancake-ts';
|
|
5
5
|
|
|
6
6
|
/** Parameters for the checkout server action */
|
|
7
7
|
type CheckoutActionParams = ({
|
|
@@ -337,13 +337,20 @@ interface BuyerPayment {
|
|
|
337
337
|
failureReason: string | null;
|
|
338
338
|
createdAt: string;
|
|
339
339
|
}
|
|
340
|
-
/**
|
|
340
|
+
/**
|
|
341
|
+
* A buyer's refund ticket.
|
|
342
|
+
*
|
|
343
|
+
* Ticket-level fields are flat; per-version fields (`reason`, `requestedAmount`)
|
|
344
|
+
* live under `versionData` because the buyer can resubmit a rejected ticket and
|
|
345
|
+
* each submission is a versioned record. `versionData` reflects the current
|
|
346
|
+
* (latest) version. The `versionData` shape is shared with `@waffo/pancake-ts`'s
|
|
347
|
+
* `RefundTicketVersionData`.
|
|
348
|
+
*/
|
|
341
349
|
interface BuyerRefundTicket {
|
|
342
350
|
id: string;
|
|
343
351
|
status: string;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
requestedCurrency: string;
|
|
352
|
+
versionNumber: number | null;
|
|
353
|
+
versionData: RefundTicketVersionData | null;
|
|
347
354
|
createdAt: string;
|
|
348
355
|
}
|
|
349
356
|
interface BuyerOrdersData {
|
|
@@ -410,9 +417,16 @@ interface MerchantOrder {
|
|
|
410
417
|
}>;
|
|
411
418
|
createdAt: string;
|
|
412
419
|
}
|
|
413
|
-
/**
|
|
420
|
+
/**
|
|
421
|
+
* Sales overview statistics.
|
|
422
|
+
*
|
|
423
|
+
* Monetary fields (`totalRevenue`, `revenueByPeriod[].amount`) are returned as
|
|
424
|
+
* display-formatted strings (e.g., `"9.99"`), not minor-currency-unit integers.
|
|
425
|
+
* The conversion happens server-side via the GraphQL `currencyDisplayLoader`.
|
|
426
|
+
*/
|
|
414
427
|
interface SalesOverview {
|
|
415
428
|
totalOrders: number;
|
|
429
|
+
/** Total succeeded payment revenue as display string (e.g., `"1234.56"`) */
|
|
416
430
|
totalRevenue: string;
|
|
417
431
|
totalCustomers: number;
|
|
418
432
|
currency: string;
|
|
@@ -420,6 +434,7 @@ interface SalesOverview {
|
|
|
420
434
|
status: string;
|
|
421
435
|
count: number;
|
|
422
436
|
}>;
|
|
437
|
+
/** Revenue by period; `amount` is a display string (e.g., `"9.99"`) */
|
|
423
438
|
revenueByPeriod: Array<{
|
|
424
439
|
period: string;
|
|
425
440
|
amount: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { AnonymousCheckoutParams, AuthenticatedCheckoutParams, CheckoutSessionResult, AuthenticatedCheckoutResult, IssueSessionTokenParams, SessionToken, GraphQLParams, GraphQLResponse, CancelSubscriptionParams, CancelSubscriptionResult, CancelOnetimeOrderParams, CancelOnetimeOrderResult, ReactivateSubscriptionParams, ReactivateSubscriptionResult, CreateRefundTicketParams, RefundTicket, ResubmitRefundTicketParams, VerifyWebhookOptions, WebhookEventData, WebhookEvent } from '@waffo/pancake-ts';
|
|
4
|
-
export { BillingDetail, PriceInfo, TaxCategory, WaffoPancakeError, WebhookEvent, WebhookEventData, WebhookEventType } from '@waffo/pancake-ts';
|
|
3
|
+
import { AnonymousCheckoutParams, AuthenticatedCheckoutParams, CheckoutSessionResult, AuthenticatedCheckoutResult, IssueSessionTokenParams, SessionToken, GraphQLParams, GraphQLResponse, CancelSubscriptionParams, CancelSubscriptionResult, CancelOnetimeOrderParams, CancelOnetimeOrderResult, ReactivateSubscriptionParams, ReactivateSubscriptionResult, CreateRefundTicketParams, RefundTicket, ResubmitRefundTicketParams, RefundTicketVersionData, VerifyWebhookOptions, WebhookEventData, WebhookEvent } from '@waffo/pancake-ts';
|
|
4
|
+
export { BillingDetail, PriceInfo, RefundTicketVersionData, RequestedAmount, TaxCategory, WaffoPancakeError, WebhookEvent, WebhookEventData, WebhookEventType } from '@waffo/pancake-ts';
|
|
5
5
|
|
|
6
6
|
/** Parameters for the checkout server action */
|
|
7
7
|
type CheckoutActionParams = ({
|
|
@@ -337,13 +337,20 @@ interface BuyerPayment {
|
|
|
337
337
|
failureReason: string | null;
|
|
338
338
|
createdAt: string;
|
|
339
339
|
}
|
|
340
|
-
/**
|
|
340
|
+
/**
|
|
341
|
+
* A buyer's refund ticket.
|
|
342
|
+
*
|
|
343
|
+
* Ticket-level fields are flat; per-version fields (`reason`, `requestedAmount`)
|
|
344
|
+
* live under `versionData` because the buyer can resubmit a rejected ticket and
|
|
345
|
+
* each submission is a versioned record. `versionData` reflects the current
|
|
346
|
+
* (latest) version. The `versionData` shape is shared with `@waffo/pancake-ts`'s
|
|
347
|
+
* `RefundTicketVersionData`.
|
|
348
|
+
*/
|
|
341
349
|
interface BuyerRefundTicket {
|
|
342
350
|
id: string;
|
|
343
351
|
status: string;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
requestedCurrency: string;
|
|
352
|
+
versionNumber: number | null;
|
|
353
|
+
versionData: RefundTicketVersionData | null;
|
|
347
354
|
createdAt: string;
|
|
348
355
|
}
|
|
349
356
|
interface BuyerOrdersData {
|
|
@@ -410,9 +417,16 @@ interface MerchantOrder {
|
|
|
410
417
|
}>;
|
|
411
418
|
createdAt: string;
|
|
412
419
|
}
|
|
413
|
-
/**
|
|
420
|
+
/**
|
|
421
|
+
* Sales overview statistics.
|
|
422
|
+
*
|
|
423
|
+
* Monetary fields (`totalRevenue`, `revenueByPeriod[].amount`) are returned as
|
|
424
|
+
* display-formatted strings (e.g., `"9.99"`), not minor-currency-unit integers.
|
|
425
|
+
* The conversion happens server-side via the GraphQL `currencyDisplayLoader`.
|
|
426
|
+
*/
|
|
414
427
|
interface SalesOverview {
|
|
415
428
|
totalOrders: number;
|
|
429
|
+
/** Total succeeded payment revenue as display string (e.g., `"1234.56"`) */
|
|
416
430
|
totalRevenue: string;
|
|
417
431
|
totalCustomers: number;
|
|
418
432
|
currency: string;
|
|
@@ -420,6 +434,7 @@ interface SalesOverview {
|
|
|
420
434
|
status: string;
|
|
421
435
|
count: number;
|
|
422
436
|
}>;
|
|
437
|
+
/** Revenue by period; `amount` is a display string (e.g., `"9.99"`) */
|
|
423
438
|
revenueByPeriod: Array<{
|
|
424
439
|
period: string;
|
|
425
440
|
amount: string;
|
package/dist/index.js
CHANGED
|
@@ -243,7 +243,12 @@ var BUYER_PAYMENTS_QUERY = `query {
|
|
|
243
243
|
}`;
|
|
244
244
|
var BUYER_REFUND_TICKETS_QUERY = `query {
|
|
245
245
|
refundTickets(limit: 50) {
|
|
246
|
-
id status
|
|
246
|
+
id status versionNumber
|
|
247
|
+
versionData {
|
|
248
|
+
reason
|
|
249
|
+
requestedAmount { amount currency }
|
|
250
|
+
}
|
|
251
|
+
createdAt
|
|
247
252
|
}
|
|
248
253
|
}`;
|
|
249
254
|
function useBuyerQuery(query) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/use-checkout.ts","../src/checkout-button.tsx","../src/use-buyer.ts","../src/use-buyer-data.ts","../src/use-query.ts","../src/use-merchant-data.ts","../src/webhook.ts","../src/index.ts"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { BuyerTokenAction, BuyerSessionAction } from \"./server.js\";\n\n/** Buyer configuration for automatic token management */\nexport interface BuyerConfig {\n /** Buyer identity (email or merchant-provided identifier) */\n identity: 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 /** Server action for issuing tokens — from `createBuyerTokenAction()` */\n issueToken: BuyerTokenAction;\n /** Server action for buyer operations — from `createBuyerSessionAction()` */\n sessionAction: BuyerSessionAction;\n}\n\ninterface TokenState {\n token: string;\n expiresAt: number;\n}\n\n/** @internal */\nexport interface PancakeContextValue {\n /** Get a valid buyer token (auto-refreshes if expired) */\n getBuyerToken: () => Promise<string>;\n /** Execute a buyer session operation via server action */\n buyerSessionAction: BuyerSessionAction;\n /** Whether buyer config is provided */\n hasBuyer: boolean;\n /** Whether the initial token is ready */\n isBuyerReady: boolean;\n}\n\n/** @internal Exported for direct useContext access in hooks */\nexport const PancakeContext = createContext<PancakeContextValue | null>(null);\n\n/** Token refresh buffer — refresh 30s before actual expiry */\nconst REFRESH_BUFFER_MS = 30_000;\n\nexport interface WaffoPancakeProviderProps {\n /** Buyer configuration for automatic token management */\n buyer: BuyerConfig;\n children: React.ReactNode;\n}\n\n/**\n * Provider that manages buyer token lifecycle via server actions.\n *\n * Auto-issues session tokens on mount and refreshes before expiry.\n * All buyer hooks (`useBuyer`, `useBuyerOrders`, etc.) read from context.\n *\n * The private key never leaves the server — token issuance and buyer\n * operations are delegated to server actions.\n *\n * @param props - Provider configuration\n * @param props.buyer - Buyer identity and server actions\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * // identity must match what you passed as `buyerIdentity` at checkout time —\n * // buyer-portal lookups are keyed by merchant_provided_buyer_identity\n * <WaffoPancakeProvider buyer={{\n * identity: user.id,\n * storeId: \"STO_xxx\",\n * issueToken, // from createBuyerTokenAction()\n * sessionAction, // from createBuyerSessionAction()\n * }}>\n * <App />\n * </WaffoPancakeProvider>\n * ```\n */\nexport function WaffoPancakeProvider({ buyer, children }: WaffoPancakeProviderProps) {\n const tokenRef = useRef<TokenState | null>(null);\n const refreshPromiseRef = useRef<Promise<string> | null>(null);\n const [isBuyerReady, setIsBuyerReady] = useState(false);\n\n const refreshToken = useCallback(async (): Promise<string> => {\n const result = await buyer.issueToken({\n buyerIdentity: buyer.identity,\n storeId: buyer.storeId,\n productId: buyer.productId,\n });\n\n tokenRef.current = {\n token: result.token,\n expiresAt: new Date(result.expiresAt).getTime(),\n };\n\n return result.token;\n }, [buyer]);\n\n const getBuyerToken = useCallback(async (): Promise<string> => {\n const current = tokenRef.current;\n if (current && Date.now() < current.expiresAt - REFRESH_BUFFER_MS) {\n return current.token;\n }\n\n // Deduplicate concurrent refresh calls\n if (!refreshPromiseRef.current) {\n refreshPromiseRef.current = refreshToken().finally(() => {\n refreshPromiseRef.current = null;\n });\n }\n\n return refreshPromiseRef.current;\n }, [refreshToken]);\n\n // Issue initial token on mount\n useEffect(() => {\n refreshToken()\n .then(() => setIsBuyerReady(true))\n .catch(() => setIsBuyerReady(true));\n }, [refreshToken]);\n\n const value = useMemo<PancakeContextValue>(\n () => ({\n getBuyerToken,\n buyerSessionAction: buyer.sessionAction,\n hasBuyer: true,\n isBuyerReady,\n }),\n [getBuyerToken, buyer.sessionAction, isBuyerReady],\n );\n\n return <PancakeContext.Provider value={value}>{children}</PancakeContext.Provider>;\n}\n\n/**\n * Access the Waffo Pancake context. Must be used within `<WaffoPancakeProvider>`.\n */\nexport function usePancakeContext(): PancakeContextValue {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"usePancakeContext: must be used within <WaffoPancakeProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\n\nimport type { CheckoutProps, LinkCheckoutProps, UseCheckoutReturn } from \"./types.js\";\nimport type { CheckoutSessionResult, AuthenticatedCheckoutResult } from \"@waffo/pancake-ts\";\n\n\nconst LOADING_HTML = `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Loading...</title><style>body{display:flex;align-items:center;justify-content:center;height:100vh;margin:0;font-family:system-ui,sans-serif;background:#f9fafb;color:#6b7280}@media(prefers-color-scheme:dark){body{background:#111827;color:#9ca3af}}</style></head><body><p>Redirecting to checkout...</p></body></html>`;\n\nconst DEFAULT_STOREFRONT_URL = \"https://pancake.waffo.ai\";\n\nconst SDK_FIELDS = new Set([\"action\", \"type\", \"mode\", \"popupLoadingUrl\", \"onSuccess\", \"onError\"]);\n\n/** Extract API checkout params from flattened props, removing SDK-specific fields */\nfunction extractApiParams(args: object): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(args)) {\n if (!SDK_FIELDS.has(key)) params[key] = value;\n }\n return params;\n}\n\n/**\n * Build a product page URL for link checkout.\n */\nfunction buildLinkUrl(props: LinkCheckoutProps): string {\n const base = (props.baseUrl ?? DEFAULT_STOREFRONT_URL).replace(/\\/+$/, \"\");\n const url = new URL(`${base}/store/${props.storeSlug}/product/${props.productId}`);\n\n if (props.currency) url.searchParams.set(\"currency\", props.currency);\n if (props.email) url.searchParams.set(\"email\", props.email);\n if (props.successUrl) url.searchParams.set(\"success_url\", props.successUrl);\n if (props.test) url.searchParams.set(\"test\", \"true\");\n if (props.country) url.searchParams.set(\"country\", props.country);\n if (props.isBusiness) url.searchParams.set(\"is_business\", \"true\");\n\n return url.toString();\n}\n\n/**\n * React hook for triggering a Waffo Pancake checkout flow.\n *\n * Supports three checkout types:\n * - **link**: Builds a product page URL and navigates directly (no API call, synchronous)\n * - **anonymous**: Calls a server action to create a checkout session, then navigates\n * - **authenticated**: Calls a server action to create a session + token, then navigates\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param args - Flattened checkout props\n * @returns `{ checkout, isLoading, error }`\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * const { checkout } = useCheckout({\n * type: \"link\",\n * storeSlug: \"my-store\",\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * // Anonymous checkout — via server action\n * const { checkout, isLoading } = useCheckout({\n * action: checkout, // from createCheckoutAction()\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n * ```\n */\nexport function useCheckout(args: CheckoutProps): UseCheckoutReturn {\n const { mode = \"redirect\", popupLoadingUrl, onError } = args;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const popupRef = useRef<Window | null>(null);\n\n const checkout = useCallback(() => {\n if (isLoading) return;\n\n // Link checkout — synchronous, no API call\n if (args.type === \"link\") {\n const url = buildLinkUrl(args);\n if (mode === \"popup\") {\n window.open(url, \"_blank\");\n } else {\n window.location.href = url;\n }\n return;\n }\n\n // Anonymous / Authenticated — server action\n if (mode === \"popup\") {\n const loadingUrl = popupLoadingUrl ?? `data:text/html;charset=utf-8,${encodeURIComponent(LOADING_HTML)}`;\n popupRef.current = window.open(loadingUrl, \"_blank\");\n }\n\n setIsLoading(true);\n setError(null);\n\n const { action } = args;\n const params = extractApiParams(args);\n const actionParams = args.type === \"authenticated\" ? { type: \"authenticated\" as const, ...params } : params;\n\n action(actionParams as unknown as Parameters<typeof action>[0])\n .then((result: CheckoutSessionResult | AuthenticatedCheckoutResult) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.location.href = result.checkoutUrl;\n } else {\n window.location.href = result.checkoutUrl;\n }\n if (\"onSuccess\" in args && args.onSuccess) {\n (args.onSuccess as (r: CheckoutSessionResult | AuthenticatedCheckoutResult) => void)(result);\n }\n })\n .catch((err: Error) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.close();\n popupRef.current = null;\n }\n setError(err);\n onError?.(err);\n })\n .finally(() => {\n setIsLoading(false);\n });\n }, [args, mode, popupLoadingUrl, onError, isLoading]);\n\n return { checkout, isLoading, error };\n}\n","\"use client\";\n\nimport React from \"react\";\n\nimport { useCheckout } from \"./use-checkout.js\";\n\nimport type { CheckoutProps, LinkCheckoutProps, AnonymousCheckoutProps, AuthenticatedCheckoutProps } from \"./types.js\";\n\ntype CheckoutButtonBaseProps = {\n /** Button content */\n children: React.ReactNode;\n /** Content shown while checkout session is being created */\n loadingChildren?: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Disabled state (merged with isLoading) */\n disabled?: boolean;\n} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\" | \"disabled\" | \"children\">;\n\n/** Props for CheckoutButton — link mode */\nexport type LinkCheckoutButtonProps = CheckoutButtonBaseProps & LinkCheckoutProps;\n\n/** Props for CheckoutButton — anonymous mode */\nexport type AnonymousCheckoutButtonProps = CheckoutButtonBaseProps & AnonymousCheckoutProps;\n\n/** Props for CheckoutButton — authenticated mode */\nexport type AuthenticatedCheckoutButtonProps = CheckoutButtonBaseProps & AuthenticatedCheckoutProps;\n\nexport type CheckoutButtonProps = LinkCheckoutButtonProps | AnonymousCheckoutButtonProps | AuthenticatedCheckoutButtonProps;\n\n/**\n * A button that triggers a Waffo Pancake checkout flow on click.\n *\n * Three checkout types:\n * - **link**: Instant redirect to product page URL (no server action needed)\n * - **anonymous**: Calls server action to create session, then redirects\n * - **authenticated**: Calls server action to create session + token, then redirects\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param props - Flattened checkout props, button content, and optional styling\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * <CheckoutButton type=\"link\" storeSlug=\"my-store\" productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Anonymous checkout — via server action\n * <CheckoutButton action={checkout} productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Authenticated checkout — via server action\n * <CheckoutButton action={checkout} type=\"authenticated\" productId=\"PROD_xxx\" currency=\"USD\" buyerIdentity=\"userIdInYourSystem\" buyerEmail=\"user@example.com\">\n * Buy Now\n * </CheckoutButton>\n * ```\n */\nexport function CheckoutButton(props: CheckoutButtonProps) {\n const { children, loadingChildren, className, style, disabled, ...checkoutProps } = props;\n\n const { checkout, isLoading } = useCheckout(checkoutProps as CheckoutProps);\n\n return (\n <button type=\"button\" onClick={checkout} disabled={disabled || isLoading} className={className} style={style}>\n {isLoading ? (loadingChildren ?? children) : children}\n </button>\n );\n}\n","\"use client\";\n\nimport { useCallback, useContext, useMemo, useState } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\n\nimport type {\n CancelSubscriptionParams,\n CancelSubscriptionResult,\n CancelOnetimeOrderParams,\n CancelOnetimeOrderResult,\n ReactivateSubscriptionParams,\n ReactivateSubscriptionResult,\n CreateRefundTicketParams,\n ResubmitRefundTicketParams,\n RefundTicket,\n GraphQLParams,\n GraphQLResponse,\n} from \"@waffo/pancake-ts\";\n\n/** State of an async buyer action */\nexport interface BuyerActionState<T = unknown> {\n /** Execute the action */\n execute: (params: T) => Promise<void>;\n /** Whether the action is in progress */\n isLoading: boolean;\n /** Error from the last attempt */\n error: Error | null;\n}\n\n/** Return type of useBuyer hook */\nexport interface UseBuyerReturn {\n /** Cancel a subscription order */\n cancelSubscription: BuyerActionState<CancelSubscriptionParams> & { data: CancelSubscriptionResult | null };\n /** Cancel a one-time order */\n cancelOnetimeOrder: BuyerActionState<CancelOnetimeOrderParams> & { data: CancelOnetimeOrderResult | null };\n /** Reactivate a canceling subscription */\n reactivateSubscription: BuyerActionState<ReactivateSubscriptionParams> & { data: ReactivateSubscriptionResult | null };\n /** Create a refund ticket */\n createRefundTicket: BuyerActionState<CreateRefundTicketParams> & { data: RefundTicket | null };\n /** Resubmit a rejected refund ticket */\n resubmitRefundTicket: BuyerActionState<ResubmitRefundTicketParams> & { data: RefundTicket | null };\n /** Execute a GraphQL query */\n query: <T = Record<string, unknown>>(params: GraphQLParams) => Promise<GraphQLResponse<T>>;\n}\n\nfunction useBuyerAction<TParams, TResult>(\n actionFn: (params: TParams) => Promise<TResult>,\n): BuyerActionState<TParams> & { data: TResult | null } {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TResult | null>(null);\n\n const execute = useCallback(\n async (params: TParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await actionFn(params);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [actionFn],\n );\n\n return { execute, isLoading, error, data };\n}\n\n/**\n * React hook for buyer self-service actions.\n *\n * Must be used within `<WaffoPancakeProvider>`. All operations are executed\n * via server actions — the private key never leaves the server.\n *\n * @returns Buyer action handlers with loading/error states\n *\n * @example\n * ```tsx\n * function AccountPage() {\n * const buyer = useBuyer();\n * return (\n * <button onClick={() => buyer.cancelSubscription.execute({ orderId: \"ORD_xxx\" })}>\n * Cancel\n * </button>\n * );\n * }\n * ```\n */\nexport function useBuyer(): UseBuyerReturn {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"useBuyer: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction } = ctx;\n\n const callAction = useCallback(\n async (actionType: string, params: unknown) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, actionType as never, params);\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n const cancelSubscription = useBuyerAction<CancelSubscriptionParams, CancelSubscriptionResult>(\n useCallback((params) => callAction(\"cancelSubscription\", params) as Promise<CancelSubscriptionResult>, [callAction]),\n );\n\n const cancelOnetimeOrder = useBuyerAction<CancelOnetimeOrderParams, CancelOnetimeOrderResult>(\n useCallback((params) => callAction(\"cancelOnetimeOrder\", params) as Promise<CancelOnetimeOrderResult>, [callAction]),\n );\n\n const reactivateSubscription = useBuyerAction<ReactivateSubscriptionParams, ReactivateSubscriptionResult>(\n useCallback((params) => callAction(\"reactivateSubscription\", params) as Promise<ReactivateSubscriptionResult>, [callAction]),\n );\n\n const createRefundTicket = useBuyerAction<CreateRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"createRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const createRefundTicketMapped = useMemo(\n () => ({ ...createRefundTicket, data: createRefundTicket.data?.ticket ?? null }),\n [createRefundTicket],\n );\n\n const resubmitRefundTicket = useBuyerAction<ResubmitRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"resubmitRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const resubmitRefundTicketMapped = useMemo(\n () => ({ ...resubmitRefundTicket, data: resubmitRefundTicket.data?.ticket ?? null }),\n [resubmitRefundTicket],\n );\n\n const query = useCallback(\n async <T = Record<string, unknown>>(params: GraphQLParams) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, \"query\", params) as Promise<GraphQLResponse<T>>;\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n return {\n cancelSubscription,\n cancelOnetimeOrder,\n reactivateSubscription,\n createRefundTicket: createRefundTicketMapped,\n resubmitRefundTicket: resubmitRefundTicketMapped,\n query,\n };\n}\n","\"use client\";\n\nimport { useCallback, useContext } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\nimport { useQuery } from \"./use-query.js\";\n\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/** A buyer's one-time order */\nexport interface BuyerOnetimeOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's subscription order */\nexport interface BuyerSubscriptionOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's payment record */\nexport interface BuyerPayment {\n id: string;\n orderId: string;\n status: string;\n snapshotDisplayAmount: string;\n snapshotDisplayCurrency: string;\n failureReason: string | null;\n createdAt: string;\n}\n\n/** A buyer's refund ticket */\nexport interface BuyerRefundTicket {\n id: string;\n status: string;\n reason: string;\n requestedAmount: string;\n requestedCurrency: string;\n createdAt: string;\n}\n\n// ============================================================\n// Queries\n// ============================================================\n\nconst BUYER_ORDERS_QUERY = `query {\n onetimeOrders(limit: 50) {\n id status currency buyerEmail createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n subscriptionOrders(limit: 50) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n}`;\n\nconst BUYER_PAYMENTS_QUERY = `query {\n payments(limit: 50) {\n id orderId status snapshotDisplayAmount snapshotDisplayCurrency failureReason createdAt\n }\n}`;\n\nconst BUYER_REFUND_TICKETS_QUERY = `query {\n refundTickets(limit: 50) {\n id status reason requestedAmount requestedCurrency createdAt\n }\n}`;\n\n// ============================================================\n// Internal helper\n// ============================================================\n\nfunction useBuyerQuery<T>(query: string): QueryState<T> {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"Buyer data hook: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction, isBuyerReady } = ctx;\n\n const queryFn = useCallback(async () => {\n const token = await getBuyerToken();\n const result = (await buyerSessionAction(token, \"query\", { query })) as unknown as GraphQLResponse<T>;\n return result.data as T;\n }, [getBuyerToken, buyerSessionAction, query]);\n\n return useQuery(queryFn, isBuyerReady);\n}\n\n// ============================================================\n// Hooks\n// ============================================================\n\ninterface BuyerOrdersData {\n onetimeOrders: BuyerOnetimeOrder[];\n subscriptionOrders: BuyerSubscriptionOrder[];\n}\n\n/**\n * Fetch the buyer's order history (one-time + subscription).\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Orders with product info and payment history\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useBuyerOrders();\n * // data.onetimeOrders + data.subscriptionOrders\n * ```\n */\nexport function useBuyerOrders(): QueryState<BuyerOrdersData> {\n return useBuyerQuery<BuyerOrdersData>(BUYER_ORDERS_QUERY);\n}\n\n/**\n * Fetch the buyer's payment history.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Payment records with amounts and status\n *\n * @example\n * ```tsx\n * const { data: payments, isLoading } = useBuyerPayments();\n * ```\n */\nexport function useBuyerPayments(): QueryState<BuyerPayment[]> {\n const result = useBuyerQuery<{ payments: BuyerPayment[] }>(BUYER_PAYMENTS_QUERY);\n return { ...result, data: result.data?.payments ?? null };\n}\n\n/**\n * Fetch the buyer's refund tickets.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Refund tickets with status and requested amounts\n *\n * @example\n * ```tsx\n * const { data: tickets, isLoading } = useBuyerRefundTickets();\n * ```\n */\nexport function useBuyerRefundTickets(): QueryState<BuyerRefundTicket[]> {\n const result = useBuyerQuery<{ refundTickets: BuyerRefundTicket[] }>(BUYER_REFUND_TICKETS_QUERY);\n return { ...result, data: result.data?.refundTickets ?? null };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\n/** Query state with typed data */\nexport interface QueryState<T> {\n data: T | null;\n isLoading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Internal hook for async data fetching with loading/error state.\n *\n * @param queryFn - Async function that returns the data\n * @param ready - Whether to start fetching (false = wait)\n * @returns Query state with data, loading, error, and refetch\n */\nexport function useQuery<T>(queryFn: () => Promise<T>, ready: boolean): QueryState<T> {\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(() => {\n if (!ready) return;\n setIsLoading(true);\n setError(null);\n queryFn()\n .then(setData)\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))))\n .finally(() => setIsLoading(false));\n }, [queryFn, ready]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\n\nimport { useQuery } from \"./use-query.js\";\n\nimport type { MerchantQueryAction } from \"./server.js\";\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Merchant Data Hooks (via server action)\n// ============================================================\n\n/** A merchant's recent order (one-time or subscription) */\nexport interface MerchantOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n testMode: boolean;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string }>;\n createdAt: string;\n}\n\n/** Sales overview statistics */\nexport interface SalesOverview {\n totalOrders: number;\n totalRevenue: string;\n totalCustomers: number;\n currency: string;\n ordersByStatus: Array<{ status: string; count: number }>;\n revenueByPeriod: Array<{ period: string; amount: string }>;\n}\n\n/** Subscription overview */\nexport interface SubscriptionOverview {\n activeCount: number;\n cancelingCount: number;\n pastDueCount: number;\n totalCount: number;\n subscriptions: MerchantSubscription[];\n}\n\n/** A merchant's subscription with status details */\nexport interface MerchantSubscription {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n createdAt: string;\n}\n\nexport interface MerchantOrdersOptions {\n /** Store ID to filter by */\n storeId: string;\n /** Max results (default: 20) */\n limit?: number;\n}\n\nconst MERCHANT_ORDERS_QUERY = `query ($storeId: ID!, $limit: Int) {\n onetimeOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n subscriptionOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n}`;\n\n/**\n * Fetch recent orders for a store (one-time + subscription).\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param options - Store ID and optional limit\n * @returns Recent orders with product info and payment summary\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useMerchantOrders(merchantQuery, { storeId: \"STO_xxx\" });\n * ```\n */\nexport function useMerchantOrders(\n query: MerchantQueryAction,\n options: MerchantOrdersOptions,\n): QueryState<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }> {\n const { storeId, limit = 20 } = options;\n\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_ORDERS_QUERY,\n variables: { storeId, limit },\n })) as unknown as GraphQLResponse<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }>;\n return result.data as { onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] };\n }, [query, storeId, limit]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SALES_QUERY = `query ($storeId: ID!) {\n orderStatistics(storeId: $storeId) {\n totalCount\n countByStatus { status count }\n }\n paymentStatistics(storeId: $storeId) {\n totalSucceededAmount\n totalSucceededCurrency\n totalSucceededCount\n }\n customerAnalysis(storeId: $storeId) {\n totalCustomers\n }\n trendAnalysis(storeId: $storeId) {\n revenueByPeriod { period amount }\n }\n}`;\n\ninterface SalesQueryData {\n orderStatistics: { totalCount: number; countByStatus: Array<{ status: string; count: number }> };\n paymentStatistics: { totalSucceededAmount: string; totalSucceededCurrency: string; totalSucceededCount: number };\n customerAnalysis: { totalCustomers: number };\n trendAnalysis: { revenueByPeriod: Array<{ period: string; amount: string }> };\n}\n\n/**\n * Fetch sales overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Aggregated sales statistics\n *\n * @example\n * ```tsx\n * const { data: sales } = useMerchantSales(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSales(query: MerchantQueryAction, storeId: string): QueryState<SalesOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SALES_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<SalesQueryData>;\n const d = result.data as SalesQueryData;\n return {\n totalOrders: d.orderStatistics.totalCount,\n totalRevenue: d.paymentStatistics.totalSucceededAmount,\n totalCustomers: d.customerAnalysis.totalCustomers,\n currency: d.paymentStatistics.totalSucceededCurrency,\n ordersByStatus: d.orderStatistics.countByStatus,\n revenueByPeriod: d.trendAnalysis.revenueByPeriod,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SUBSCRIPTIONS_QUERY = `query ($storeId: ID!) {\n subscriptionOrders(storeId: $storeId, limit: 100) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n }\n}`;\n\n/**\n * Fetch subscription overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Subscription counts and detailed list\n *\n * @example\n * ```tsx\n * const { data: subs } = useMerchantSubscriptions(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSubscriptions(query: MerchantQueryAction, storeId: string): QueryState<SubscriptionOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SUBSCRIPTIONS_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<{ subscriptionOrders: MerchantSubscription[] }>;\n const subs = (result.data as { subscriptionOrders: MerchantSubscription[] }).subscriptionOrders;\n return {\n activeCount: subs.filter((s) => s.status === \"active\").length,\n cancelingCount: subs.filter((s) => s.status === \"canceling\").length,\n pastDueCount: subs.filter((s) => s.status === \"past_due\").length,\n totalCount: subs.length,\n subscriptions: subs,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n","import { verifyWebhook } from \"@waffo/pancake-ts\";\n\nimport type { VerifyWebhookOptions, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n/** Handler function for a specific webhook event */\ntype EventHandler<T = WebhookEventData> = (event: WebhookEvent<T>) => void | Promise<void>;\n\n/** Configuration for the Webhook route handler factory */\nexport interface WebhookConfig {\n /** Webhook signature verification options (environment, publicKey, tolerance, etc.) */\n verifyOptions?: VerifyWebhookOptions;\n\n /** Catch-all handler — called for every event regardless of type */\n onPayload?: EventHandler;\n\n /** One-time order first payment succeeded */\n onOrderCompleted?: EventHandler;\n /** Subscription first payment succeeded (newly activated) */\n onSubscriptionActivated?: EventHandler;\n /** Subscription renewal payment succeeded */\n onSubscriptionPaymentSucceeded?: EventHandler;\n /** Buyer initiated cancellation (expires at end of current period) */\n onSubscriptionCanceling?: EventHandler;\n /** Buyer withdrew cancellation (subscription restored) */\n onSubscriptionUncanceled?: EventHandler;\n /** Subscription product changed (upgrade/downgrade) */\n onSubscriptionUpdated?: EventHandler;\n /** Subscription fully terminated */\n onSubscriptionCanceled?: EventHandler;\n /** Renewal payment failed (past due) */\n onSubscriptionPastDue?: EventHandler;\n /** Refund succeeded */\n onRefundSucceeded?: EventHandler;\n /** Refund failed */\n onRefundFailed?: EventHandler;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention -- event type keys use dot notation */\nconst EVENT_HANDLER_MAP: Record<string, keyof WebhookConfig> = {\n \"order.completed\": \"onOrderCompleted\",\n \"subscription.activated\": \"onSubscriptionActivated\",\n \"subscription.payment_succeeded\": \"onSubscriptionPaymentSucceeded\",\n \"subscription.canceling\": \"onSubscriptionCanceling\",\n \"subscription.uncanceled\": \"onSubscriptionUncanceled\",\n \"subscription.updated\": \"onSubscriptionUpdated\",\n \"subscription.canceled\": \"onSubscriptionCanceled\",\n \"subscription.past_due\": \"onSubscriptionPastDue\",\n \"refund.succeeded\": \"onRefundSucceeded\",\n \"refund.failed\": \"onRefundFailed\",\n};\n/* eslint-enable @typescript-eslint/naming-convention */\n\n/**\n * Create a Next.js POST route handler for Waffo Pancake webhooks.\n *\n * Automatically verifies the webhook signature using `@waffo/pancake-ts`,\n * then dispatches to the matching event handler.\n *\n * @param config - Verification options and event handlers\n * @returns A Next.js POST route handler\n *\n * @example\n * ```ts\n * // app/api/webhooks/waffo/route.ts\n * import { Webhook } from \"@waffo/pancake-nextjs\";\n *\n * export const POST = Webhook({\n * verifyOptions: { environment: \"prod\" },\n * onOrderCompleted: async (event) => {\n * console.log(\"Order completed:\", event.data.orderId);\n * // Grant access to the product\n * },\n * onSubscriptionActivated: async (event) => {\n * console.log(\"Subscription activated:\", event.data.orderId);\n * },\n * onRefundSucceeded: async (event) => {\n * console.log(\"Refund succeeded:\", event.data.refundId);\n * // Revoke access\n * },\n * });\n * ```\n */\nexport function Webhook(config: WebhookConfig) {\n return async function POST(request: Request): Promise<Response> {\n const payload = await request.text();\n const signature = request.headers.get(\"x-waffo-signature\");\n\n let event: WebhookEvent;\n try {\n event = verifyWebhook(payload, signature, config.verifyOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook verification failed\";\n return new Response(JSON.stringify({ error: message }), {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n try {\n // Catch-all handler\n if (config.onPayload) {\n await config.onPayload(event);\n }\n\n // Event-specific handler\n const handlerKey = EVENT_HANDLER_MAP[event.eventType];\n if (handlerKey) {\n const handler = config[handlerKey] as EventHandler | undefined;\n if (handler) {\n await handler(event);\n }\n }\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook handler error\";\n return new Response(JSON.stringify({ error: message }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n };\n}\n","export { WaffoPancakeProvider } from \"./provider.js\";\nexport { CheckoutButton } from \"./checkout-button.js\";\nexport { useCheckout } from \"./use-checkout.js\";\nexport { useBuyer } from \"./use-buyer.js\";\nexport { useBuyerOrders, useBuyerPayments, useBuyerRefundTickets } from \"./use-buyer-data.js\";\nexport { useMerchantOrders, useMerchantSales, useMerchantSubscriptions } from \"./use-merchant-data.js\";\nexport { Webhook } from \"./webhook.js\";\n\n// Re-export types commonly used in client components\nexport { WaffoPancakeError, TaxCategory, WebhookEventType } from \"@waffo/pancake-ts\";\n\nexport type { PriceInfo, BillingDetail, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n// Local types\nexport type {\n CheckoutMode,\n CheckoutBaseOptions,\n LinkCheckoutProps,\n AnonymousCheckoutProps,\n AuthenticatedCheckoutProps,\n CheckoutProps,\n UseCheckoutReturn,\n} from \"./types.js\";\n\nexport type { BuyerConfig, WaffoPancakeProviderProps } from \"./provider.js\";\n\nexport type {\n CheckoutButtonProps,\n LinkCheckoutButtonProps,\n AnonymousCheckoutButtonProps,\n AuthenticatedCheckoutButtonProps,\n} from \"./checkout-button.js\";\n\nexport type { BuyerActionState, UseBuyerReturn } from \"./use-buyer.js\";\n\nexport type { QueryState } from \"./use-query.js\";\n\nexport type { BuyerOnetimeOrder, BuyerSubscriptionOrder, BuyerPayment, BuyerRefundTicket } from \"./use-buyer-data.js\";\n\nexport type { MerchantOrder, MerchantSubscription, SalesOverview, SubscriptionOverview, MerchantOrdersOptions } from \"./use-merchant-data.js\";\n\nexport type { WebhookConfig } from \"./webhook.js\";\n\n// Server action types (for typing the action prop)\nexport type { CheckoutAction, CheckoutActionParams, CheckoutActionResult, BuyerTokenAction, BuyerSessionAction, MerchantQueryAction } from \"./server.js\";\n"],"mappings":"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","names":["useCallback","useRef","useState","jsx","useCallback","useContext","useMemo","useState","useState","useCallback","useContext","useMemo","useCallback","useContext","useCallback","useEffect","useState","useContext","useCallback","useCallback","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/use-checkout.ts","../src/checkout-button.tsx","../src/use-buyer.ts","../src/use-buyer-data.ts","../src/use-query.ts","../src/use-merchant-data.ts","../src/webhook.ts","../src/index.ts"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { BuyerTokenAction, BuyerSessionAction } from \"./server.js\";\n\n/** Buyer configuration for automatic token management */\nexport interface BuyerConfig {\n /** Buyer identity (email or merchant-provided identifier) */\n identity: 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 /** Server action for issuing tokens — from `createBuyerTokenAction()` */\n issueToken: BuyerTokenAction;\n /** Server action for buyer operations — from `createBuyerSessionAction()` */\n sessionAction: BuyerSessionAction;\n}\n\ninterface TokenState {\n token: string;\n expiresAt: number;\n}\n\n/** @internal */\nexport interface PancakeContextValue {\n /** Get a valid buyer token (auto-refreshes if expired) */\n getBuyerToken: () => Promise<string>;\n /** Execute a buyer session operation via server action */\n buyerSessionAction: BuyerSessionAction;\n /** Whether buyer config is provided */\n hasBuyer: boolean;\n /** Whether the initial token is ready */\n isBuyerReady: boolean;\n}\n\n/** @internal Exported for direct useContext access in hooks */\nexport const PancakeContext = createContext<PancakeContextValue | null>(null);\n\n/** Token refresh buffer — refresh 30s before actual expiry */\nconst REFRESH_BUFFER_MS = 30_000;\n\nexport interface WaffoPancakeProviderProps {\n /** Buyer configuration for automatic token management */\n buyer: BuyerConfig;\n children: React.ReactNode;\n}\n\n/**\n * Provider that manages buyer token lifecycle via server actions.\n *\n * Auto-issues session tokens on mount and refreshes before expiry.\n * All buyer hooks (`useBuyer`, `useBuyerOrders`, etc.) read from context.\n *\n * The private key never leaves the server — token issuance and buyer\n * operations are delegated to server actions.\n *\n * @param props - Provider configuration\n * @param props.buyer - Buyer identity and server actions\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * // identity must match what you passed as `buyerIdentity` at checkout time —\n * // buyer-portal lookups are keyed by merchant_provided_buyer_identity\n * <WaffoPancakeProvider buyer={{\n * identity: user.id,\n * storeId: \"STO_xxx\",\n * issueToken, // from createBuyerTokenAction()\n * sessionAction, // from createBuyerSessionAction()\n * }}>\n * <App />\n * </WaffoPancakeProvider>\n * ```\n */\nexport function WaffoPancakeProvider({ buyer, children }: WaffoPancakeProviderProps) {\n const tokenRef = useRef<TokenState | null>(null);\n const refreshPromiseRef = useRef<Promise<string> | null>(null);\n const [isBuyerReady, setIsBuyerReady] = useState(false);\n\n const refreshToken = useCallback(async (): Promise<string> => {\n const result = await buyer.issueToken({\n buyerIdentity: buyer.identity,\n storeId: buyer.storeId,\n productId: buyer.productId,\n });\n\n tokenRef.current = {\n token: result.token,\n expiresAt: new Date(result.expiresAt).getTime(),\n };\n\n return result.token;\n }, [buyer]);\n\n const getBuyerToken = useCallback(async (): Promise<string> => {\n const current = tokenRef.current;\n if (current && Date.now() < current.expiresAt - REFRESH_BUFFER_MS) {\n return current.token;\n }\n\n // Deduplicate concurrent refresh calls\n if (!refreshPromiseRef.current) {\n refreshPromiseRef.current = refreshToken().finally(() => {\n refreshPromiseRef.current = null;\n });\n }\n\n return refreshPromiseRef.current;\n }, [refreshToken]);\n\n // Issue initial token on mount\n useEffect(() => {\n refreshToken()\n .then(() => setIsBuyerReady(true))\n .catch(() => setIsBuyerReady(true));\n }, [refreshToken]);\n\n const value = useMemo<PancakeContextValue>(\n () => ({\n getBuyerToken,\n buyerSessionAction: buyer.sessionAction,\n hasBuyer: true,\n isBuyerReady,\n }),\n [getBuyerToken, buyer.sessionAction, isBuyerReady],\n );\n\n return <PancakeContext.Provider value={value}>{children}</PancakeContext.Provider>;\n}\n\n/**\n * Access the Waffo Pancake context. Must be used within `<WaffoPancakeProvider>`.\n */\nexport function usePancakeContext(): PancakeContextValue {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"usePancakeContext: must be used within <WaffoPancakeProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\n\nimport type { CheckoutProps, LinkCheckoutProps, UseCheckoutReturn } from \"./types.js\";\nimport type { CheckoutSessionResult, AuthenticatedCheckoutResult } from \"@waffo/pancake-ts\";\n\n\nconst LOADING_HTML = `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Loading...</title><style>body{display:flex;align-items:center;justify-content:center;height:100vh;margin:0;font-family:system-ui,sans-serif;background:#f9fafb;color:#6b7280}@media(prefers-color-scheme:dark){body{background:#111827;color:#9ca3af}}</style></head><body><p>Redirecting to checkout...</p></body></html>`;\n\nconst DEFAULT_STOREFRONT_URL = \"https://pancake.waffo.ai\";\n\nconst SDK_FIELDS = new Set([\"action\", \"type\", \"mode\", \"popupLoadingUrl\", \"onSuccess\", \"onError\"]);\n\n/** Extract API checkout params from flattened props, removing SDK-specific fields */\nfunction extractApiParams(args: object): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(args)) {\n if (!SDK_FIELDS.has(key)) params[key] = value;\n }\n return params;\n}\n\n/**\n * Build a product page URL for link checkout.\n */\nfunction buildLinkUrl(props: LinkCheckoutProps): string {\n const base = (props.baseUrl ?? DEFAULT_STOREFRONT_URL).replace(/\\/+$/, \"\");\n const url = new URL(`${base}/store/${props.storeSlug}/product/${props.productId}`);\n\n if (props.currency) url.searchParams.set(\"currency\", props.currency);\n if (props.email) url.searchParams.set(\"email\", props.email);\n if (props.successUrl) url.searchParams.set(\"success_url\", props.successUrl);\n if (props.test) url.searchParams.set(\"test\", \"true\");\n if (props.country) url.searchParams.set(\"country\", props.country);\n if (props.isBusiness) url.searchParams.set(\"is_business\", \"true\");\n\n return url.toString();\n}\n\n/**\n * React hook for triggering a Waffo Pancake checkout flow.\n *\n * Supports three checkout types:\n * - **link**: Builds a product page URL and navigates directly (no API call, synchronous)\n * - **anonymous**: Calls a server action to create a checkout session, then navigates\n * - **authenticated**: Calls a server action to create a session + token, then navigates\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param args - Flattened checkout props\n * @returns `{ checkout, isLoading, error }`\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * const { checkout } = useCheckout({\n * type: \"link\",\n * storeSlug: \"my-store\",\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n *\n * // Anonymous checkout — via server action\n * const { checkout, isLoading } = useCheckout({\n * action: checkout, // from createCheckoutAction()\n * productId: \"PROD_xxx\",\n * currency: \"USD\",\n * });\n * ```\n */\nexport function useCheckout(args: CheckoutProps): UseCheckoutReturn {\n const { mode = \"redirect\", popupLoadingUrl, onError } = args;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const popupRef = useRef<Window | null>(null);\n\n const checkout = useCallback(() => {\n if (isLoading) return;\n\n // Link checkout — synchronous, no API call\n if (args.type === \"link\") {\n const url = buildLinkUrl(args);\n if (mode === \"popup\") {\n window.open(url, \"_blank\");\n } else {\n window.location.href = url;\n }\n return;\n }\n\n // Anonymous / Authenticated — server action\n if (mode === \"popup\") {\n const loadingUrl = popupLoadingUrl ?? `data:text/html;charset=utf-8,${encodeURIComponent(LOADING_HTML)}`;\n popupRef.current = window.open(loadingUrl, \"_blank\");\n }\n\n setIsLoading(true);\n setError(null);\n\n const { action } = args;\n const params = extractApiParams(args);\n const actionParams = args.type === \"authenticated\" ? { type: \"authenticated\" as const, ...params } : params;\n\n action(actionParams as unknown as Parameters<typeof action>[0])\n .then((result: CheckoutSessionResult | AuthenticatedCheckoutResult) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.location.href = result.checkoutUrl;\n } else {\n window.location.href = result.checkoutUrl;\n }\n if (\"onSuccess\" in args && args.onSuccess) {\n (args.onSuccess as (r: CheckoutSessionResult | AuthenticatedCheckoutResult) => void)(result);\n }\n })\n .catch((err: Error) => {\n if (mode === \"popup\" && popupRef.current) {\n popupRef.current.close();\n popupRef.current = null;\n }\n setError(err);\n onError?.(err);\n })\n .finally(() => {\n setIsLoading(false);\n });\n }, [args, mode, popupLoadingUrl, onError, isLoading]);\n\n return { checkout, isLoading, error };\n}\n","\"use client\";\n\nimport React from \"react\";\n\nimport { useCheckout } from \"./use-checkout.js\";\n\nimport type { CheckoutProps, LinkCheckoutProps, AnonymousCheckoutProps, AuthenticatedCheckoutProps } from \"./types.js\";\n\ntype CheckoutButtonBaseProps = {\n /** Button content */\n children: React.ReactNode;\n /** Content shown while checkout session is being created */\n loadingChildren?: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Disabled state (merged with isLoading) */\n disabled?: boolean;\n} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\" | \"disabled\" | \"children\">;\n\n/** Props for CheckoutButton — link mode */\nexport type LinkCheckoutButtonProps = CheckoutButtonBaseProps & LinkCheckoutProps;\n\n/** Props for CheckoutButton — anonymous mode */\nexport type AnonymousCheckoutButtonProps = CheckoutButtonBaseProps & AnonymousCheckoutProps;\n\n/** Props for CheckoutButton — authenticated mode */\nexport type AuthenticatedCheckoutButtonProps = CheckoutButtonBaseProps & AuthenticatedCheckoutProps;\n\nexport type CheckoutButtonProps = LinkCheckoutButtonProps | AnonymousCheckoutButtonProps | AuthenticatedCheckoutButtonProps;\n\n/**\n * A button that triggers a Waffo Pancake checkout flow on click.\n *\n * Three checkout types:\n * - **link**: Instant redirect to product page URL (no server action needed)\n * - **anonymous**: Calls server action to create session, then redirects\n * - **authenticated**: Calls server action to create session + token, then redirects\n *\n * The private key never leaves the server — anonymous and authenticated modes\n * use a server action created by `createCheckoutAction()`.\n *\n * @param props - Flattened checkout props, button content, and optional styling\n *\n * @example\n * ```tsx\n * // Link checkout — no server action needed\n * <CheckoutButton type=\"link\" storeSlug=\"my-store\" productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Anonymous checkout — via server action\n * <CheckoutButton action={checkout} productId=\"PROD_xxx\" currency=\"USD\">\n * Buy Now\n * </CheckoutButton>\n *\n * // Authenticated checkout — via server action\n * <CheckoutButton action={checkout} type=\"authenticated\" productId=\"PROD_xxx\" currency=\"USD\" buyerIdentity=\"userIdInYourSystem\" buyerEmail=\"user@example.com\">\n * Buy Now\n * </CheckoutButton>\n * ```\n */\nexport function CheckoutButton(props: CheckoutButtonProps) {\n const { children, loadingChildren, className, style, disabled, ...checkoutProps } = props;\n\n const { checkout, isLoading } = useCheckout(checkoutProps as CheckoutProps);\n\n return (\n <button type=\"button\" onClick={checkout} disabled={disabled || isLoading} className={className} style={style}>\n {isLoading ? (loadingChildren ?? children) : children}\n </button>\n );\n}\n","\"use client\";\n\nimport { useCallback, useContext, useMemo, useState } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\n\nimport type {\n CancelSubscriptionParams,\n CancelSubscriptionResult,\n CancelOnetimeOrderParams,\n CancelOnetimeOrderResult,\n ReactivateSubscriptionParams,\n ReactivateSubscriptionResult,\n CreateRefundTicketParams,\n ResubmitRefundTicketParams,\n RefundTicket,\n GraphQLParams,\n GraphQLResponse,\n} from \"@waffo/pancake-ts\";\n\n/** State of an async buyer action */\nexport interface BuyerActionState<T = unknown> {\n /** Execute the action */\n execute: (params: T) => Promise<void>;\n /** Whether the action is in progress */\n isLoading: boolean;\n /** Error from the last attempt */\n error: Error | null;\n}\n\n/** Return type of useBuyer hook */\nexport interface UseBuyerReturn {\n /** Cancel a subscription order */\n cancelSubscription: BuyerActionState<CancelSubscriptionParams> & { data: CancelSubscriptionResult | null };\n /** Cancel a one-time order */\n cancelOnetimeOrder: BuyerActionState<CancelOnetimeOrderParams> & { data: CancelOnetimeOrderResult | null };\n /** Reactivate a canceling subscription */\n reactivateSubscription: BuyerActionState<ReactivateSubscriptionParams> & { data: ReactivateSubscriptionResult | null };\n /** Create a refund ticket */\n createRefundTicket: BuyerActionState<CreateRefundTicketParams> & { data: RefundTicket | null };\n /** Resubmit a rejected refund ticket */\n resubmitRefundTicket: BuyerActionState<ResubmitRefundTicketParams> & { data: RefundTicket | null };\n /** Execute a GraphQL query */\n query: <T = Record<string, unknown>>(params: GraphQLParams) => Promise<GraphQLResponse<T>>;\n}\n\nfunction useBuyerAction<TParams, TResult>(\n actionFn: (params: TParams) => Promise<TResult>,\n): BuyerActionState<TParams> & { data: TResult | null } {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TResult | null>(null);\n\n const execute = useCallback(\n async (params: TParams) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await actionFn(params);\n setData(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [actionFn],\n );\n\n return { execute, isLoading, error, data };\n}\n\n/**\n * React hook for buyer self-service actions.\n *\n * Must be used within `<WaffoPancakeProvider>`. All operations are executed\n * via server actions — the private key never leaves the server.\n *\n * @returns Buyer action handlers with loading/error states\n *\n * @example\n * ```tsx\n * function AccountPage() {\n * const buyer = useBuyer();\n * return (\n * <button onClick={() => buyer.cancelSubscription.execute({ orderId: \"ORD_xxx\" })}>\n * Cancel\n * </button>\n * );\n * }\n * ```\n */\nexport function useBuyer(): UseBuyerReturn {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"useBuyer: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction } = ctx;\n\n const callAction = useCallback(\n async (actionType: string, params: unknown) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, actionType as never, params);\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n const cancelSubscription = useBuyerAction<CancelSubscriptionParams, CancelSubscriptionResult>(\n useCallback((params) => callAction(\"cancelSubscription\", params) as Promise<CancelSubscriptionResult>, [callAction]),\n );\n\n const cancelOnetimeOrder = useBuyerAction<CancelOnetimeOrderParams, CancelOnetimeOrderResult>(\n useCallback((params) => callAction(\"cancelOnetimeOrder\", params) as Promise<CancelOnetimeOrderResult>, [callAction]),\n );\n\n const reactivateSubscription = useBuyerAction<ReactivateSubscriptionParams, ReactivateSubscriptionResult>(\n useCallback((params) => callAction(\"reactivateSubscription\", params) as Promise<ReactivateSubscriptionResult>, [callAction]),\n );\n\n const createRefundTicket = useBuyerAction<CreateRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"createRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const createRefundTicketMapped = useMemo(\n () => ({ ...createRefundTicket, data: createRefundTicket.data?.ticket ?? null }),\n [createRefundTicket],\n );\n\n const resubmitRefundTicket = useBuyerAction<ResubmitRefundTicketParams, { ticket: RefundTicket }>(\n useCallback((params) => callAction(\"resubmitRefundTicket\", params) as Promise<{ ticket: RefundTicket }>, [callAction]),\n );\n const resubmitRefundTicketMapped = useMemo(\n () => ({ ...resubmitRefundTicket, data: resubmitRefundTicket.data?.ticket ?? null }),\n [resubmitRefundTicket],\n );\n\n const query = useCallback(\n async <T = Record<string, unknown>>(params: GraphQLParams) => {\n const token = await getBuyerToken();\n return buyerSessionAction(token, \"query\", params) as Promise<GraphQLResponse<T>>;\n },\n [getBuyerToken, buyerSessionAction],\n );\n\n return {\n cancelSubscription,\n cancelOnetimeOrder,\n reactivateSubscription,\n createRefundTicket: createRefundTicketMapped,\n resubmitRefundTicket: resubmitRefundTicketMapped,\n query,\n };\n}\n","\"use client\";\n\nimport { useCallback, useContext } from \"react\";\n\nimport { PancakeContext } from \"./provider.js\";\nimport { useQuery } from \"./use-query.js\";\n\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse, RefundTicketVersionData } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/** A buyer's one-time order */\nexport interface BuyerOnetimeOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's subscription order */\nexport interface BuyerSubscriptionOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string; createdAt: string }>;\n createdAt: string;\n}\n\n/** A buyer's payment record */\nexport interface BuyerPayment {\n id: string;\n orderId: string;\n status: string;\n snapshotDisplayAmount: string;\n snapshotDisplayCurrency: string;\n failureReason: string | null;\n createdAt: string;\n}\n\n/**\n * A buyer's refund ticket.\n *\n * Ticket-level fields are flat; per-version fields (`reason`, `requestedAmount`)\n * live under `versionData` because the buyer can resubmit a rejected ticket and\n * each submission is a versioned record. `versionData` reflects the current\n * (latest) version. The `versionData` shape is shared with `@waffo/pancake-ts`'s\n * `RefundTicketVersionData`.\n */\nexport interface BuyerRefundTicket {\n id: string;\n status: string;\n versionNumber: number | null;\n versionData: RefundTicketVersionData | null;\n createdAt: string;\n}\n\n// ============================================================\n// Queries\n// ============================================================\n\nconst BUYER_ORDERS_QUERY = `query {\n onetimeOrders(limit: 50) {\n id status currency buyerEmail createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n subscriptionOrders(limit: 50) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency createdAt }\n }\n}`;\n\nconst BUYER_PAYMENTS_QUERY = `query {\n payments(limit: 50) {\n id orderId status snapshotDisplayAmount snapshotDisplayCurrency failureReason createdAt\n }\n}`;\n\nconst BUYER_REFUND_TICKETS_QUERY = `query {\n refundTickets(limit: 50) {\n id status versionNumber\n versionData {\n reason\n requestedAmount { amount currency }\n }\n createdAt\n }\n}`;\n\n// ============================================================\n// Internal helper\n// ============================================================\n\nfunction useBuyerQuery<T>(query: string): QueryState<T> {\n const ctx = useContext(PancakeContext);\n if (!ctx) throw new Error(\"Buyer data hook: must be used within <WaffoPancakeProvider>\");\n\n const { getBuyerToken, buyerSessionAction, isBuyerReady } = ctx;\n\n const queryFn = useCallback(async () => {\n const token = await getBuyerToken();\n const result = (await buyerSessionAction(token, \"query\", { query })) as unknown as GraphQLResponse<T>;\n return result.data as T;\n }, [getBuyerToken, buyerSessionAction, query]);\n\n return useQuery(queryFn, isBuyerReady);\n}\n\n// ============================================================\n// Hooks\n// ============================================================\n\ninterface BuyerOrdersData {\n onetimeOrders: BuyerOnetimeOrder[];\n subscriptionOrders: BuyerSubscriptionOrder[];\n}\n\n/**\n * Fetch the buyer's order history (one-time + subscription).\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Orders with product info and payment history\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useBuyerOrders();\n * // data.onetimeOrders + data.subscriptionOrders\n * ```\n */\nexport function useBuyerOrders(): QueryState<BuyerOrdersData> {\n return useBuyerQuery<BuyerOrdersData>(BUYER_ORDERS_QUERY);\n}\n\n/**\n * Fetch the buyer's payment history.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Payment records with amounts and status\n *\n * @example\n * ```tsx\n * const { data: payments, isLoading } = useBuyerPayments();\n * ```\n */\nexport function useBuyerPayments(): QueryState<BuyerPayment[]> {\n const result = useBuyerQuery<{ payments: BuyerPayment[] }>(BUYER_PAYMENTS_QUERY);\n return { ...result, data: result.data?.payments ?? null };\n}\n\n/**\n * Fetch the buyer's refund tickets.\n *\n * Must be used within `<WaffoPancakeProvider>`. Token is auto-managed.\n *\n * @returns Refund tickets with status and requested amounts\n *\n * @example\n * ```tsx\n * const { data: tickets, isLoading } = useBuyerRefundTickets();\n * ```\n */\nexport function useBuyerRefundTickets(): QueryState<BuyerRefundTicket[]> {\n const result = useBuyerQuery<{ refundTickets: BuyerRefundTicket[] }>(BUYER_REFUND_TICKETS_QUERY);\n return { ...result, data: result.data?.refundTickets ?? null };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\n/** Query state with typed data */\nexport interface QueryState<T> {\n data: T | null;\n isLoading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Internal hook for async data fetching with loading/error state.\n *\n * @param queryFn - Async function that returns the data\n * @param ready - Whether to start fetching (false = wait)\n * @returns Query state with data, loading, error, and refetch\n */\nexport function useQuery<T>(queryFn: () => Promise<T>, ready: boolean): QueryState<T> {\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetch = useCallback(() => {\n if (!ready) return;\n setIsLoading(true);\n setError(null);\n queryFn()\n .then(setData)\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))))\n .finally(() => setIsLoading(false));\n }, [queryFn, ready]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { data, isLoading, error, refetch: fetch };\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\n\nimport { useQuery } from \"./use-query.js\";\n\nimport type { MerchantQueryAction } from \"./server.js\";\nimport type { QueryState } from \"./use-query.js\";\nimport type { GraphQLResponse } from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Merchant Data Hooks (via server action)\n// ============================================================\n\n/** A merchant's recent order (one-time or subscription) */\nexport interface MerchantOrder {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n testMode: boolean;\n product: { id: string; name: string } | null;\n payments: Array<{ id: string; status: string; snapshotDisplayAmount: string; snapshotDisplayCurrency: string }>;\n createdAt: string;\n}\n\n/**\n * Sales overview statistics.\n *\n * Monetary fields (`totalRevenue`, `revenueByPeriod[].amount`) are returned as\n * display-formatted strings (e.g., `\"9.99\"`), not minor-currency-unit integers.\n * The conversion happens server-side via the GraphQL `currencyDisplayLoader`.\n */\nexport interface SalesOverview {\n totalOrders: number;\n /** Total succeeded payment revenue as display string (e.g., `\"1234.56\"`) */\n totalRevenue: string;\n totalCustomers: number;\n currency: string;\n ordersByStatus: Array<{ status: string; count: number }>;\n /** Revenue by period; `amount` is a display string (e.g., `\"9.99\"`) */\n revenueByPeriod: Array<{ period: string; amount: string }>;\n}\n\n/** Subscription overview */\nexport interface SubscriptionOverview {\n activeCount: number;\n cancelingCount: number;\n pastDueCount: number;\n totalCount: number;\n subscriptions: MerchantSubscription[];\n}\n\n/** A merchant's subscription with status details */\nexport interface MerchantSubscription {\n id: string;\n status: string;\n currency: string;\n buyerEmail: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n cancelAt: string | null;\n product: { id: string; name: string; billingPeriod: string } | null;\n createdAt: string;\n}\n\nexport interface MerchantOrdersOptions {\n /** Store ID to filter by */\n storeId: string;\n /** Max results (default: 20) */\n limit?: number;\n}\n\nconst MERCHANT_ORDERS_QUERY = `query ($storeId: ID!, $limit: Int) {\n onetimeOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n subscriptionOrders(storeId: $storeId, limit: $limit) {\n id status currency buyerEmail testMode createdAt\n product { id name }\n payments { id status snapshotDisplayAmount snapshotDisplayCurrency }\n }\n}`;\n\n/**\n * Fetch recent orders for a store (one-time + subscription).\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param options - Store ID and optional limit\n * @returns Recent orders with product info and payment summary\n *\n * @example\n * ```tsx\n * const { data, isLoading, refetch } = useMerchantOrders(merchantQuery, { storeId: \"STO_xxx\" });\n * ```\n */\nexport function useMerchantOrders(\n query: MerchantQueryAction,\n options: MerchantOrdersOptions,\n): QueryState<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }> {\n const { storeId, limit = 20 } = options;\n\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_ORDERS_QUERY,\n variables: { storeId, limit },\n })) as unknown as GraphQLResponse<{ onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] }>;\n return result.data as { onetimeOrders: MerchantOrder[]; subscriptionOrders: MerchantOrder[] };\n }, [query, storeId, limit]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SALES_QUERY = `query ($storeId: ID!) {\n orderStatistics(storeId: $storeId) {\n totalCount\n countByStatus { status count }\n }\n paymentStatistics(storeId: $storeId) {\n totalSucceededAmount\n totalSucceededCurrency\n totalSucceededCount\n }\n customerAnalysis(storeId: $storeId) {\n totalCustomers\n }\n trendAnalysis(storeId: $storeId) {\n revenueByPeriod { period amount }\n }\n}`;\n\ninterface SalesQueryData {\n orderStatistics: { totalCount: number; countByStatus: Array<{ status: string; count: number }> };\n paymentStatistics: { totalSucceededAmount: string; totalSucceededCurrency: string; totalSucceededCount: number };\n customerAnalysis: { totalCustomers: number };\n trendAnalysis: { revenueByPeriod: Array<{ period: string; amount: string }> };\n}\n\n/**\n * Fetch sales overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Aggregated sales statistics\n *\n * @example\n * ```tsx\n * const { data: sales } = useMerchantSales(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSales(query: MerchantQueryAction, storeId: string): QueryState<SalesOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SALES_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<SalesQueryData>;\n const d = result.data as SalesQueryData;\n return {\n totalOrders: d.orderStatistics.totalCount,\n totalRevenue: d.paymentStatistics.totalSucceededAmount,\n totalCustomers: d.customerAnalysis.totalCustomers,\n currency: d.paymentStatistics.totalSucceededCurrency,\n ordersByStatus: d.orderStatistics.countByStatus,\n revenueByPeriod: d.trendAnalysis.revenueByPeriod,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n\nconst MERCHANT_SUBSCRIPTIONS_QUERY = `query ($storeId: ID!) {\n subscriptionOrders(storeId: $storeId, limit: 100) {\n id status currency buyerEmail currentPeriodStart currentPeriodEnd cancelAt createdAt\n product { id name billingPeriod }\n }\n}`;\n\n/**\n * Fetch subscription overview for a store.\n *\n * @param query - Server action from `createMerchantQueryAction()`\n * @param storeId - Store ID\n * @returns Subscription counts and detailed list\n *\n * @example\n * ```tsx\n * const { data: subs } = useMerchantSubscriptions(merchantQuery, \"STO_xxx\");\n * ```\n */\nexport function useMerchantSubscriptions(query: MerchantQueryAction, storeId: string): QueryState<SubscriptionOverview> {\n const queryFn = useCallback(async () => {\n const result = (await query({\n query: MERCHANT_SUBSCRIPTIONS_QUERY,\n variables: { storeId },\n })) as unknown as GraphQLResponse<{ subscriptionOrders: MerchantSubscription[] }>;\n const subs = (result.data as { subscriptionOrders: MerchantSubscription[] }).subscriptionOrders;\n return {\n activeCount: subs.filter((s) => s.status === \"active\").length,\n cancelingCount: subs.filter((s) => s.status === \"canceling\").length,\n pastDueCount: subs.filter((s) => s.status === \"past_due\").length,\n totalCount: subs.length,\n subscriptions: subs,\n };\n }, [query, storeId]);\n\n return useQuery(queryFn, true);\n}\n","import { verifyWebhook } from \"@waffo/pancake-ts\";\n\nimport type { VerifyWebhookOptions, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n/** Handler function for a specific webhook event */\ntype EventHandler<T = WebhookEventData> = (event: WebhookEvent<T>) => void | Promise<void>;\n\n/** Configuration for the Webhook route handler factory */\nexport interface WebhookConfig {\n /** Webhook signature verification options (environment, publicKey, tolerance, etc.) */\n verifyOptions?: VerifyWebhookOptions;\n\n /** Catch-all handler — called for every event regardless of type */\n onPayload?: EventHandler;\n\n /** One-time order first payment succeeded */\n onOrderCompleted?: EventHandler;\n /** Subscription first payment succeeded (newly activated) */\n onSubscriptionActivated?: EventHandler;\n /** Subscription renewal payment succeeded */\n onSubscriptionPaymentSucceeded?: EventHandler;\n /** Buyer initiated cancellation (expires at end of current period) */\n onSubscriptionCanceling?: EventHandler;\n /** Buyer withdrew cancellation (subscription restored) */\n onSubscriptionUncanceled?: EventHandler;\n /** Subscription product changed (upgrade/downgrade) */\n onSubscriptionUpdated?: EventHandler;\n /** Subscription fully terminated */\n onSubscriptionCanceled?: EventHandler;\n /** Renewal payment failed (past due) */\n onSubscriptionPastDue?: EventHandler;\n /** Refund succeeded */\n onRefundSucceeded?: EventHandler;\n /** Refund failed */\n onRefundFailed?: EventHandler;\n}\n\n/* eslint-disable @typescript-eslint/naming-convention -- event type keys use dot notation */\nconst EVENT_HANDLER_MAP: Record<string, keyof WebhookConfig> = {\n \"order.completed\": \"onOrderCompleted\",\n \"subscription.activated\": \"onSubscriptionActivated\",\n \"subscription.payment_succeeded\": \"onSubscriptionPaymentSucceeded\",\n \"subscription.canceling\": \"onSubscriptionCanceling\",\n \"subscription.uncanceled\": \"onSubscriptionUncanceled\",\n \"subscription.updated\": \"onSubscriptionUpdated\",\n \"subscription.canceled\": \"onSubscriptionCanceled\",\n \"subscription.past_due\": \"onSubscriptionPastDue\",\n \"refund.succeeded\": \"onRefundSucceeded\",\n \"refund.failed\": \"onRefundFailed\",\n};\n/* eslint-enable @typescript-eslint/naming-convention */\n\n/**\n * Create a Next.js POST route handler for Waffo Pancake webhooks.\n *\n * Automatically verifies the webhook signature using `@waffo/pancake-ts`,\n * then dispatches to the matching event handler.\n *\n * @param config - Verification options and event handlers\n * @returns A Next.js POST route handler\n *\n * @example\n * ```ts\n * // app/api/webhooks/waffo/route.ts\n * import { Webhook } from \"@waffo/pancake-nextjs\";\n *\n * export const POST = Webhook({\n * verifyOptions: { environment: \"prod\" },\n * onOrderCompleted: async (event) => {\n * console.log(\"Order completed:\", event.data.orderId);\n * // Grant access to the product\n * },\n * onSubscriptionActivated: async (event) => {\n * console.log(\"Subscription activated:\", event.data.orderId);\n * },\n * onRefundSucceeded: async (event) => {\n * console.log(\"Refund succeeded:\", event.data.refundId);\n * // Revoke access\n * },\n * });\n * ```\n */\nexport function Webhook(config: WebhookConfig) {\n return async function POST(request: Request): Promise<Response> {\n const payload = await request.text();\n const signature = request.headers.get(\"x-waffo-signature\");\n\n let event: WebhookEvent;\n try {\n event = verifyWebhook(payload, signature, config.verifyOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook verification failed\";\n return new Response(JSON.stringify({ error: message }), {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n try {\n // Catch-all handler\n if (config.onPayload) {\n await config.onPayload(event);\n }\n\n // Event-specific handler\n const handlerKey = EVENT_HANDLER_MAP[event.eventType];\n if (handlerKey) {\n const handler = config[handlerKey] as EventHandler | undefined;\n if (handler) {\n await handler(event);\n }\n }\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Webhook handler error\";\n return new Response(JSON.stringify({ error: message }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n };\n}\n","export { WaffoPancakeProvider } from \"./provider.js\";\nexport { CheckoutButton } from \"./checkout-button.js\";\nexport { useCheckout } from \"./use-checkout.js\";\nexport { useBuyer } from \"./use-buyer.js\";\nexport { useBuyerOrders, useBuyerPayments, useBuyerRefundTickets } from \"./use-buyer-data.js\";\nexport { useMerchantOrders, useMerchantSales, useMerchantSubscriptions } from \"./use-merchant-data.js\";\nexport { Webhook } from \"./webhook.js\";\n\n// Re-export types commonly used in client components\nexport { WaffoPancakeError, TaxCategory, WebhookEventType } from \"@waffo/pancake-ts\";\n\nexport type { PriceInfo, BillingDetail, RequestedAmount, RefundTicketVersionData, WebhookEvent, WebhookEventData } from \"@waffo/pancake-ts\";\n\n// Local types\nexport type {\n CheckoutMode,\n CheckoutBaseOptions,\n LinkCheckoutProps,\n AnonymousCheckoutProps,\n AuthenticatedCheckoutProps,\n CheckoutProps,\n UseCheckoutReturn,\n} from \"./types.js\";\n\nexport type { BuyerConfig, WaffoPancakeProviderProps } from \"./provider.js\";\n\nexport type {\n CheckoutButtonProps,\n LinkCheckoutButtonProps,\n AnonymousCheckoutButtonProps,\n AuthenticatedCheckoutButtonProps,\n} from \"./checkout-button.js\";\n\nexport type { BuyerActionState, UseBuyerReturn } from \"./use-buyer.js\";\n\nexport type { QueryState } from \"./use-query.js\";\n\nexport type { BuyerOnetimeOrder, BuyerSubscriptionOrder, BuyerPayment, BuyerRefundTicket } from \"./use-buyer-data.js\";\n\nexport type {\n MerchantOrder,\n MerchantSubscription,\n SalesOverview,\n SubscriptionOverview,\n MerchantOrdersOptions,\n} from \"./use-merchant-data.js\";\n\nexport type { WebhookConfig } from \"./webhook.js\";\n\n// Server action types (for typing the action prop)\nexport type {\n CheckoutAction,\n CheckoutActionParams,\n CheckoutActionResult,\n BuyerTokenAction,\n BuyerSessionAction,\n MerchantQueryAction,\n} from \"./server.js\";\n"],"mappings":"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","names":["useCallback","useRef","useState","jsx","useCallback","useContext","useMemo","useState","useState","useCallback","useContext","useMemo","useCallback","useContext","useCallback","useEffect","useState","useContext","useCallback","useCallback","useCallback"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waffo/pancake-nextjs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Next.js SDK for Waffo Pancake — checkout components and hooks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"prepublishOnly": "npm run lint && npm run test && npm run build"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@waffo/pancake-ts": "^0.
|
|
46
|
+
"@waffo/pancake-ts": "^0.5.0",
|
|
47
47
|
"next": ">=14.0.0",
|
|
48
48
|
"react": ">=18.0.0",
|
|
49
49
|
"react-dom": ">=18.0.0"
|