@tagadapay/headless-sdk 1.5.1 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/react/index.ts", "../src/react/provider.tsx", "../src/core/errors.ts", "../src/core/http.ts", "../src/core/modules/checkout.ts", "../src/core/modules/payment.ts", "../src/core/modules/offers.ts", "../src/core/modules/customer.ts", "../src/core/modules/catalog.ts", "../src/core/client.ts", "../src/react/hooks/useCheckout.ts", "../src/react/hooks/usePayment.ts", "../src/react/hooks/useOffers.ts", "../src/react/hooks/useCustomer.ts", "../src/react/hooks/useCatalog.ts", "../src/react/hooks/useGoogleAutocomplete.ts", "../src/core/helpers/autocomplete.ts", "../src/react/hooks/useISOData.ts", "../src/core/helpers/iso3166.ts", "../src/core/helpers/countries.ts", "../src/core/helpers/currency.ts"],
4
- "sourcesContent": ["export { TagadaHeadlessProvider, useHeadlessClient } from './provider.js';\nexport type { TagadaHeadlessProviderProps } from './provider.js';\n\nexport { useCheckout } from './hooks/useCheckout.js';\nexport type { UseCheckoutReturn } from './hooks/useCheckout.js';\n\nexport { usePayment } from './hooks/usePayment.js';\nexport type { UsePaymentReturn, UsePaymentOptions } from './hooks/usePayment.js';\n\nexport { useOffers } from './hooks/useOffers.js';\nexport type { UseOffersReturn } from './hooks/useOffers.js';\n\nexport { useCustomer } from './hooks/useCustomer.js';\nexport type { UseCustomerReturn } from './hooks/useCustomer.js';\n\nexport { useCatalog } from './hooks/useCatalog.js';\nexport type { UseCatalogReturn } from './hooks/useCatalog.js';\n\n// Helpers hooks\nexport { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete.js';\nexport type { UseGoogleAutocompleteOptions, UseGoogleAutocompleteReturn } from './hooks/useGoogleAutocomplete.js';\n\nexport { useISOData, useCountryOptions, useRegionOptions } from './hooks/useISOData.js';\nexport type { UseISODataReturn } from './hooks/useISOData.js';\n\n// Re-export helper types used by hooks\nexport type {\n GooglePrediction,\n GooglePlaceDetails,\n ExtractedAddress,\n FormattedAddress,\n SupportedLanguage,\n ISOCountry,\n ISORegion,\n Currency,\n} from '../core/helpers/index.js';\n\nexport { formatMoney, CurrencyUtils, ISODataCore, GoogleAutocompleteCore, loadGoogleMapsScript } from '../core/helpers/index.js';\n\nexport type {\n HeadlessConfig,\n Environment,\n CheckoutSession,\n CheckoutLineItem,\n CheckoutTotals,\n CheckoutCustomer,\n Address,\n ShippingRate,\n LineItem,\n PaymentSetupConfig,\n PaymentMethodConfig,\n ExpressMethods,\n ExpressMethod,\n StoreConfig,\n PayResult,\n PayOptions,\n PaymentStatus,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n Offer,\n OfferLineItem,\n OfferPreview,\n OfferPreviewItem,\n OfferPayResult,\n Customer,\n Order,\n Subscription,\n CatalogProduct,\n CatalogVariant,\n CatalogPrice,\n CurrencyOption,\n StripeExpressOptions,\n} from '../core/types.js';\n", "import React, { createContext, useContext, useMemo } from 'react';\nimport { HeadlessClient, createHeadlessClient } from '../core/client.js';\nimport type { HeadlessConfig, Environment } from '../core/types.js';\n\ninterface TagadaHeadlessContextValue {\n client: HeadlessClient;\n}\n\nconst TagadaHeadlessContext = createContext<TagadaHeadlessContextValue | null>(null);\n\nexport interface TagadaHeadlessProviderProps {\n /** Your TagadaPay store ID. */\n storeId: string;\n /** Environment. Defaults to \"production\". */\n environment?: Environment;\n /** Public API key for authenticated requests. */\n apiKey?: string;\n /** Override the base API URL. */\n baseUrl?: string;\n /** Full config object (alternative to individual props). */\n config?: HeadlessConfig;\n children: React.ReactNode;\n}\n\n/**\n * Root provider for the TagadaPay Headless SDK React integration.\n * Creates a single HeadlessClient and shares it via context.\n *\n * @example\n * ```tsx\n * <TagadaHeadlessProvider storeId=\"store_abc123\" environment=\"production\">\n * <App />\n * </TagadaHeadlessProvider>\n * ```\n */\nexport function TagadaHeadlessProvider({\n storeId,\n environment,\n apiKey,\n baseUrl,\n config,\n children,\n}: TagadaHeadlessProviderProps) {\n const client = useMemo(() => {\n const cfg: HeadlessConfig = config ?? { storeId, environment, apiKey, baseUrl };\n return createHeadlessClient(cfg);\n }, [storeId, environment, apiKey, baseUrl, config]);\n\n const value = useMemo(() => ({ client }), [client]);\n\n return (\n <TagadaHeadlessContext.Provider value={value}>\n {children}\n </TagadaHeadlessContext.Provider>\n );\n}\n\n/** Access the HeadlessClient from context. Throws if used outside the provider. */\nexport function useHeadlessClient(): HeadlessClient {\n const ctx = useContext(TagadaHeadlessContext);\n if (!ctx) {\n throw new Error('useHeadlessClient must be used within <TagadaHeadlessProvider>');\n }\n return ctx.client;\n}\n", "/** Base error for all TagadaPay headless SDK errors. */\nexport class TagadaError extends Error {\n public readonly code: string;\n public readonly statusCode?: number;\n public readonly details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'TagadaError';\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n }\n}\n\n/** Thrown when the API returns 401/403. */\nexport class TagadaAuthError extends TagadaError {\n constructor(message = 'Authentication failed. Check your API key or checkout token.') {\n super(message, 'auth_error', 401);\n this.name = 'TagadaAuthError';\n }\n}\n\n/** Thrown when the API returns 422 with validation errors. */\nexport class TagadaValidationError extends TagadaError {\n public readonly errors: Array<{ field: string; message: string }>;\n\n constructor(\n message: string,\n errors: Array<{ field: string; message: string }> = [],\n ) {\n super(message, 'validation_error', 422, { errors });\n this.name = 'TagadaValidationError';\n this.errors = errors;\n }\n}\n\n/** Thrown when a resource is not found (404). */\nexport class TagadaNotFoundError extends TagadaError {\n constructor(resource: string, id: string) {\n super(`${resource} \"${id}\" not found.`, 'not_found', 404);\n this.name = 'TagadaNotFoundError';\n }\n}\n\n/** Thrown when the API returns 429. */\nexport class TagadaRateLimitError extends TagadaError {\n public readonly retryAfterMs: number;\n\n constructor(retryAfterMs = 1000) {\n super(`Rate limited. Retry after ${retryAfterMs}ms.`, 'rate_limit', 429);\n this.name = 'TagadaRateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n/** Thrown when a payment fails or requires action. */\nexport class TagadaPaymentError extends TagadaError {\n public readonly paymentId?: string;\n public readonly requireAction?: string;\n\n constructor(\n message: string,\n opts?: { paymentId?: string; requireAction?: string; details?: Record<string, unknown> },\n ) {\n super(message, 'payment_error', undefined, opts?.details);\n this.name = 'TagadaPaymentError';\n this.paymentId = opts?.paymentId;\n this.requireAction = opts?.requireAction;\n }\n}\n\n/** Thrown on network / fetch failures. */\nexport class TagadaNetworkError extends TagadaError {\n constructor(message = 'Network request failed. Check your connection.') {\n super(message, 'network_error');\n this.name = 'TagadaNetworkError';\n }\n}\n", "import {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaNetworkError,\n} from './errors.js';\nimport type { Environment, HttpRequestOptions } from './types.js';\n\nconst BASE_URLS: Record<Environment, string> = {\n production: 'https://api.tagada.io',\n development: 'https://api.tagada.dev',\n local: 'http://localhost:3000',\n};\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n apiKey?: string;\n getToken?: () => string | undefined;\n}\n\n/**\n * Lightweight HTTP client built on native fetch.\n * Zero dependencies -- works in browser, edge runtimes, and Node 18+.\n */\nexport class HttpClient {\n readonly baseUrl: string;\n private timeout: number;\n private apiKey?: string;\n private getToken?: () => string | undefined;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.timeout = config.timeout;\n this.apiKey = config.apiKey;\n this.getToken = config.getToken;\n }\n\n static resolveBaseUrl(environment: Environment, override?: string): string {\n return override ?? BASE_URLS[environment] ?? BASE_URLS.production;\n }\n\n async request<T = unknown>(path: string, options: HttpRequestOptions = {}): Promise<T> {\n const { method = 'GET', body, headers = {}, params, token, signal } = options;\n\n let url = `${this.baseUrl}${path}`;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined) qs.set(k, String(v));\n }\n const str = qs.toString();\n if (str) url += `?${str}`;\n }\n\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...headers,\n };\n\n const authToken = token ?? this.apiKey ?? this.getToken?.();\n if (authToken) {\n reqHeaders['x-cms-token'] = authToken;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body != null ? JSON.stringify(body) : undefined,\n signal: signal ?? controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (res.ok) {\n const text = await res.text();\n return text ? (JSON.parse(text) as T) : ({} as T);\n }\n\n await this.handleErrorResponse(res, path);\n throw new TagadaError('Unexpected error', 'unknown', res.status);\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof TagadaError) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new TagadaNetworkError(`Request to ${path} timed out after ${this.timeout}ms.`);\n }\n throw new TagadaNetworkError(\n err instanceof Error ? err.message : 'Network request failed.',\n );\n }\n }\n\n get<T = unknown>(path: string, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'GET' });\n }\n\n post<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'POST', body });\n }\n\n patch<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'PATCH', body });\n }\n\n put<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'PUT', body });\n }\n\n delete<T = unknown>(path: string, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'DELETE' });\n }\n\n private async handleErrorResponse(res: Response, path: string): Promise<never> {\n let parsed: Record<string, unknown> = {};\n try {\n parsed = (await res.json()) as Record<string, unknown>;\n } catch {\n // response isn't JSON\n }\n\n const msg =\n (parsed.message as string) ??\n (parsed.error as string) ??\n `Request failed: ${res.status} ${res.statusText} on ${path}`;\n\n switch (res.status) {\n case 401:\n case 403:\n throw new TagadaAuthError(msg);\n case 404:\n throw new TagadaNotFoundError(path, '');\n case 422: {\n const fieldErrors = Array.isArray(parsed.errors)\n ? (parsed.errors as Array<{ field: string; message: string }>)\n : [];\n throw new TagadaValidationError(msg, fieldErrors);\n }\n case 429: {\n const retryAfter = Number(res.headers.get('Retry-After') ?? '1') * 1000;\n throw new TagadaRateLimitError(retryAfter);\n }\n default:\n throw new TagadaError(msg, 'api_error', res.status, parsed);\n }\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type {\n CheckoutSession,\n LineItem,\n ShippingRate,\n Address,\n CheckoutCustomer,\n} from '../types.js';\n\n/**\n * Result returned by `updateCart()`. Mirrors the\n * `POST /checkout-sessions/:id/line-items` payload (mutation stats, NOT\n * a refreshed session). Call `loadSession()` to get an updated session.\n */\nexport interface UpdateCartResult {\n success: boolean;\n /** Number of existing line items updated. */\n updated: number;\n /** Number of new line items created. */\n created: number;\n /** Total number of line items in the cart after the mutation. */\n total: number;\n}\n\n/**\n * Manages checkout sessions \u2014 load, update cart, apply promo codes, handle shipping.\n *\n * Works for both **shipped** and **digital** products:\n *\n * **Shipped products** (physical goods):\n * ```\n * updateCustomer(id, { email, firstName, lastName })\n * updateAddress(id, { shippingAddress: { line1, city, ... } })\n * getShippingRates(id)\n * selectShippingRate(id, rateId)\n * ```\n *\n * **Digital products** (no shipping needed):\n * ```\n * updateCustomer(id, { email, firstName, lastName })\n * updateAddress(id, { billingAddress: { line1, city, country } })\n * // Skip shipping rates \u2014 go straight to payment\n * ```\n */\nexport class CheckoutModule {\n private sessionToken: string | undefined;\n private customerEmail: string | undefined;\n private customerFirstName: string | undefined;\n private customerLastName: string | undefined;\n private customerPhone: string | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly onTokenChange?: (token: string) => void,\n ) {}\n\n /**\n * Load an existing checkout session by its checkout token.\n *\n * @param checkoutToken The checkout token (from URL param `checkoutToken`).\n * @param sessionToken The JWT session token (from URL param `token`). Required for auth.\n * @param opts.currency Optional presentment currency override (e.g. 'EUR').\n * Only applied when the session has no currency set yet (first load).\n * Once set, currency is locked to the session and this param is ignored.\n *\n * Both `checkoutToken` and `sessionToken` come from the redirect URL returned by `createSession()`.\n * Example URL: `/checkout?checkoutToken=abc123&token=eyJ...`\n */\n async loadSession(\n checkoutToken: string,\n sessionToken?: string,\n opts?: { currency?: string },\n ): Promise<CheckoutSession> {\n if (sessionToken) {\n this.sessionToken = sessionToken;\n this.onTokenChange?.(sessionToken);\n }\n\n const params: Record<string, string> = { skipAsyncWait: 'false' };\n if (opts?.currency) {\n params.currency = opts.currency;\n }\n\n const raw = await this.http.get<{ checkoutSession: unknown; summary: unknown }>(\n `/api/v1/checkout-sessions/${checkoutToken}/v2`,\n {\n params,\n token: this.sessionToken,\n },\n );\n\n return this.normalizeSession(raw);\n }\n\n /**\n * Create a new checkout session.\n *\n * Returns a `checkoutToken` and `sessionToken` (JWT) needed for all subsequent calls.\n * Also returns a `checkoutUrl` (the full Tagada-hosted checkout URL, for reference).\n */\n async createSession(opts: {\n items: LineItem[];\n currency?: string;\n returnUrl?: string;\n customerEmail?: string;\n customerFirstName?: string;\n customerLastName?: string;\n }): Promise<{ checkoutUrl: string; checkoutToken: string; sessionToken: string; customerId: string }> {\n const lineItems = opts.items.map((i) => ({\n variantId: i.variantId,\n priceId: i.priceId,\n quantity: i.quantity,\n }));\n\n const body: Record<string, unknown> = {\n storeId: this.storeId,\n lineItems,\n };\n if (opts.returnUrl) body.returnUrl = opts.returnUrl;\n\n // Always send currency in customer object (backend reads customer.currency)\n const customerData: Record<string, unknown> = {};\n if (opts.currency) customerData.currency = opts.currency;\n if (opts.customerEmail) {\n customerData.email = opts.customerEmail;\n customerData.firstName = opts.customerFirstName;\n customerData.lastName = opts.customerLastName;\n }\n if (Object.keys(customerData).length > 0) {\n body.customer = customerData;\n }\n\n const res = await this.http.post<{\n checkoutUrl: string;\n checkoutToken: string;\n customerId: string;\n }>('/api/v1/checkout/session/init', body);\n\n const url = new URL(res.checkoutUrl);\n const sessionToken = url.searchParams.get('token') ?? '';\n this.sessionToken = sessionToken;\n if (sessionToken) this.onTokenChange?.(sessionToken);\n\n return {\n checkoutUrl: res.checkoutUrl,\n checkoutToken: res.checkoutToken,\n sessionToken,\n customerId: res.customerId,\n };\n }\n\n /**\n * Replace the cart items for an existing session.\n *\n * Returns a server-side mutation summary (counts of created/updated rows).\n * It does NOT return the updated `CheckoutSession` \u2014 the underlying\n * `POST /checkout-sessions/:id/line-items` endpoint never has and the\n * previous typing was a lie that quietly assigned `{ success, updated, ... }`\n * into a `CheckoutSession` slot in `useCheckout`.\n *\n * Call `loadSession()` after this if you need the refreshed session\n * (the React `useCheckout` hook does this for you).\n */\n async updateCart(sessionId: string, items: LineItem[]): Promise<UpdateCartResult> {\n return this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/line-items`,\n { items },\n { token: this.sessionToken },\n );\n }\n\n /**\n * Update customer identity (email, name, phone).\n *\n * Call this before `updateAddress()` \u2014 the SDK remembers the values and\n * includes them automatically when addresses are submitted.\n *\n * If you prefer a single call, use `updateCustomerAndAddress()` instead.\n */\n async updateCustomer(\n sessionId: string,\n customer: Partial<CheckoutCustomer>,\n ): Promise<void> {\n if (customer.email) this.customerEmail = customer.email;\n if (customer.firstName) this.customerFirstName = customer.firstName;\n if (customer.lastName) this.customerLastName = customer.lastName;\n if (customer.phone) this.customerPhone = customer.phone;\n }\n\n /**\n * Update shipping and/or billing address on the session.\n *\n * Automatically includes customer name/phone stored from `updateCustomer()`.\n * Uses the same atomic API call as the production checkout, so email,\n * customer name, and addresses are all persisted together.\n *\n * **Shipped products**: pass `shippingAddress`. If `billingAddress` is omitted,\n * the shipping address is automatically used as billing.\n *\n * **Digital products**: pass only `billingAddress` (no shipping needed).\n *\n * @example\n * // Shipped product \u2014 billing = shipping automatically\n * await checkout.updateAddress(sessionId, {\n * shippingAddress: { line1: '10 Rue de la Paix', city: 'Paris', postalCode: '75002', country: 'FR' },\n * });\n *\n * @example\n * // Digital product \u2014 billing only\n * await checkout.updateAddress(sessionId, {\n * billingAddress: { country: 'FR' },\n * });\n */\n async updateAddress(\n sessionId: string,\n addresses: { shippingAddress?: Address; billingAddress?: Address },\n ): Promise<void> {\n const shipping = this.mapAddress(addresses.shippingAddress);\n const billing = this.mapAddress(addresses.billingAddress);\n\n const effectiveShipping = shipping ?? billing ?? {};\n const effectiveBilling = billing ?? shipping;\n const differentBilling = !!(addresses.billingAddress && addresses.shippingAddress);\n\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/customer-and-session-info`,\n {\n checkoutSessionId: sessionId,\n customerData: {\n email: this.customerEmail,\n },\n shippingAddress: effectiveShipping,\n billingAddress: effectiveBilling ?? {},\n differentBillingAddress: differentBilling,\n },\n { token: this.sessionToken },\n );\n }\n\n /**\n * Set customer info + addresses in one call (mirrors production checkout).\n *\n * Equivalent to calling `updateCustomer()` then `updateAddress()`, but\n * in a single network request.\n */\n async updateCustomerAndAddress(\n sessionId: string,\n data: {\n customer: Partial<CheckoutCustomer>;\n shippingAddress?: Address;\n billingAddress?: Address;\n },\n ): Promise<void> {\n if (data.customer.email) this.customerEmail = data.customer.email;\n if (data.customer.firstName) this.customerFirstName = data.customer.firstName;\n if (data.customer.lastName) this.customerLastName = data.customer.lastName;\n if (data.customer.phone) this.customerPhone = data.customer.phone;\n\n const shipping = this.mapAddress(data.shippingAddress);\n const billing = this.mapAddress(data.billingAddress);\n\n const effectiveShipping = shipping ?? billing ?? {};\n const effectiveBilling = billing ?? shipping;\n const differentBilling = !!(data.billingAddress && data.shippingAddress);\n\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/customer-and-session-info`,\n {\n checkoutSessionId: sessionId,\n customerData: {\n email: this.customerEmail,\n },\n shippingAddress: effectiveShipping,\n billingAddress: effectiveBilling ?? {},\n differentBillingAddress: differentBilling,\n },\n { token: this.sessionToken },\n );\n }\n\n /** Map an SDK Address to the API shape, injecting stored customer fields. */\n private mapAddress(a?: Address): Record<string, unknown> | undefined {\n if (!a) return undefined;\n return stripEmpty({\n firstName: a.firstName ?? this.customerFirstName,\n lastName: a.lastName ?? this.customerLastName,\n phone: a.phone ?? this.customerPhone,\n address1: a.line1,\n address2: a.line2,\n city: a.city,\n state: a.state,\n postal: a.postalCode,\n country: a.country,\n });\n }\n\n /** Apply a promotion code to the session. */\n async applyPromoCode(sessionId: string, code: string): Promise<void> {\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/promotions/apply`,\n { checkoutSessionId: sessionId, code },\n { token: this.sessionToken },\n );\n }\n\n /** Remove a promotion from the session by promotion ID. */\n async removePromoCode(sessionId: string, promotionId?: string): Promise<void> {\n const promoId = promotionId ?? 'default';\n await this.http.delete(\n `/api/v1/checkout-sessions/${sessionId}/promotions/${promoId}`,\n { token: this.sessionToken },\n );\n }\n\n /**\n * Fetch available shipping rates for the session's address.\n * Only relevant for **shipped products** \u2014 digital products can skip this step.\n *\n * Requires a shipping address to be set first via `updateAddress()`.\n * Returns an empty array if no rates are configured or address is missing.\n */\n async getShippingRates(sessionId: string): Promise<ShippingRate[]> {\n const res = await this.http.get<{ rates: ShippingRate[] }>(\n `/api/v1/checkout-sessions/${sessionId}/shipping-rates`,\n { token: this.sessionToken },\n );\n return res.rates ?? [];\n }\n\n /**\n * Select a shipping rate for the session.\n * Only relevant for **shipped products** \u2014 digital products can skip this step.\n */\n async selectShippingRate(sessionId: string, rateId: string): Promise<void> {\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/shipping-rate`,\n { checkoutSessionId: sessionId, shippingRateId: rateId },\n { token: this.sessionToken },\n );\n }\n\n /**\n * Normalize the raw v2 API response into a cleaner CheckoutSession shape.\n * The raw response has nested `checkoutSession` + `summary` -- we flatten it.\n */\n private normalizeSession(raw: { checkoutSession: unknown; summary: unknown }): CheckoutSession {\n const cs = raw.checkoutSession as Record<string, unknown>;\n const orderSummaries = (cs.orderSummaries ?? []) as Array<Record<string, unknown>>;\n const summary = (raw.summary ?? cs.summary ?? orderSummaries[0] ?? {}) as Record<string, unknown>;\n const lineItems = (cs.sessionLineItems ?? []) as Array<Record<string, unknown>>;\n const customer = cs.customer as Record<string, unknown> | undefined;\n const sessionCurrency = ((summary.currency ?? cs.selectedPresentmentCurrency) as string | undefined)?.toUpperCase();\n\n const items = lineItems.map((li) => {\n const price = li.price as Record<string, unknown> | undefined;\n const variant = (price?.variant ?? {}) as Record<string, unknown>;\n const product = (variant.product ?? {}) as Record<string, unknown>;\n const currencyOpts = (price?.currencyOptions ?? {}) as Record<string, { amount: number }>;\n // Pick the amount bucket matching the session's presentment currency, then fall back to first available\n const priceEntry = (sessionCurrency ? currencyOpts[sessionCurrency] : undefined)\n ?? currencyOpts[Object.keys(currencyOpts)[0]];\n const amount = priceEntry?.amount ?? 0;\n return {\n id: li.id as string,\n variantId: li.variantId as string,\n priceId: li.priceId as string,\n productName: (product.name ?? '') as string,\n variantName: (variant.name ?? '') as string,\n quantity: (li.quantity ?? 1) as number,\n unitAmount: amount,\n totalAmount: amount * ((li.quantity ?? 1) as number),\n currency: (sessionCurrency ?? 'USD') as string,\n imageUrl: (variant.imageUrl ?? '') as string,\n };\n });\n\n const summaryItems = (summary.items ?? []) as Array<Record<string, unknown>>;\n\n return {\n id: cs.id as string,\n storeId: cs.storeId as string,\n checkoutToken: cs.checkoutToken as string,\n currency: (sessionCurrency ?? 'USD') as string,\n items,\n totals: {\n subtotal: (summary.subtotalAmount ?? 0) as number,\n discount: (summary.totalPromotionAmount ?? 0) as number,\n shipping: (summary.shippingCost ?? 0) as number,\n tax: (summary.totalTaxAmount ?? 0) as number,\n total: (summary.totalAmount ?? summaryItems.reduce((s: number, i: Record<string, unknown>) => s + ((i.amount ?? 0) as number), 0)) as number,\n currency: (sessionCurrency ?? 'USD') as string,\n },\n customer: customer\n ? {\n id: customer.id as string,\n email: customer.email as string | undefined,\n firstName: customer.firstName as string | undefined,\n lastName: customer.lastName as string | undefined,\n phone: customer.phone as string | undefined,\n }\n : undefined,\n shippingAddress: this.normalizeAddress(cs.shippingAddress),\n billingAddress: this.normalizeAddress(cs.billingAddress),\n selectedShippingRateId: (cs.shippingRateId ?? null) as string | null,\n metadata: cs.metadata as Record<string, unknown>,\n };\n }\n\n /**\n * Map the raw API address shape (`address1`, `address2`, `postal`) onto\n * the SDK's `Address` shape (`line1`, `line2`, `postalCode`). Without\n * this, `session.shippingAddress.line1` is silently undefined after a\n * reload \u2014 the type was lying about the actual key names \u2014 which is\n * what makes the demo lose form state on refresh.\n */\n private normalizeAddress(raw: unknown): Address | undefined {\n if (!raw || typeof raw !== 'object') return undefined;\n const a = raw as Record<string, unknown>;\n const out: Address = {\n firstName: a.firstName as string | undefined,\n lastName: a.lastName as string | undefined,\n line1: (a.line1 ?? a.address1) as string | undefined,\n line2: (a.line2 ?? a.address2) as string | undefined,\n city: a.city as string | undefined,\n state: a.state as string | undefined,\n postalCode: (a.postalCode ?? a.postal) as string | undefined,\n country: a.country as string | undefined,\n phone: a.phone as string | undefined,\n };\n // If every field is undefined the API returned an empty address slot.\n // Hand back undefined so consumers can `if (session.shippingAddress)`.\n return Object.values(out).some((v) => v !== undefined && v !== '') ? out : undefined;\n }\n}\n\n/**\n * Remove keys with empty-string / null / undefined values from an object.\n * Prevents sending `\"\"` to APIs that reject empty values (e.g. Stripe `country`).\n */\nfunction stripEmpty<T extends Record<string, unknown>>(obj: T): T {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined && v !== null && v !== '') {\n result[k] = v;\n }\n }\n return (Object.keys(result).length > 0 ? result : undefined) as T;\n}\n", "import type { HttpClient } from '../http.js';\nimport type {\n Environment,\n PaymentSetupConfig,\n PaymentMethodConfig,\n ExpressMethods,\n StoreConfig,\n PayResult,\n PayOptions,\n PayDirectOptions,\n CreateInstrumentOptions,\n PaymentInstrument,\n ThreedsSession,\n PaymentStatus,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n} from '../types.js';\n\n/**\n * Full payment lifecycle -- discover APMs, tokenize, create instruments,\n * process payments, handle 3DS, and poll for status.\n *\n * Wraps the same REST endpoints that plugin-sdk uses internally.\n *\n * @remarks PCI DSS compliance notice\n *\n * This SDK collects card data (PAN, expiry, CVC) in the merchant's page\n * context and sends it directly to Basis Theory for tokenization. Card data\n * never reaches TagadaPay servers.\n *\n * Because card data transits through the merchant's JavaScript environment,\n * merchants using this SDK are responsible for **PCI DSS SAQ-A-EP**\n * compliance. This includes quarterly ASV scans, secure page delivery\n * (TLS), and ensuring no unauthorized scripts can access cardholder data.\n *\n * TagadaPay is PCI DSS Level 1 certified. The merchant's PCI scope is\n * determined by their integration method, not by TagadaPay's certification.\n *\n * See: https://docs.tagada.io/developer-tools/headless-sdk/pci-compliance\n */\nexport class PaymentModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly environment: Environment,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Discovery: what payment methods are available?\n // ---------------------------------------------------------------------------\n\n /**\n * Get the full payment setup config for a checkout session.\n * Returns a map of payment methods with their configuration\n * (card, apple_pay, google_pay, klarna, etc.).\n *\n * Priority chain:\n * 1. Explicit `paymentSetupConfig` parameter (developer override)\n * 2. `window.__TGD_STEP_CONFIG__` injection (Tagada routing infra)\n * 3. API fallback (`GET /api/v1/payment-methods`)\n */\n async getPaymentSetup(\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ): Promise<PaymentSetupConfig> {\n if (opts?.paymentSetupConfig) {\n return opts.paymentSetupConfig;\n }\n\n const injected = this.readInjectedStepConfig();\n if (injected) {\n return injected;\n }\n\n const methods = await this.http.get<{ methods: PaymentMethodConfig[] }>(\n '/api/v1/payment-methods',\n { params: { checkoutSessionId } },\n );\n\n const config: PaymentSetupConfig = {};\n for (const m of methods.methods ?? []) {\n const key = m.provider ? `${m.method}:${m.provider}` : m.method;\n config[key] = m;\n }\n return config;\n }\n\n /**\n * Get express payment methods (Apple Pay, Google Pay, PayPal, etc.)\n * filtered to only those available in the current browser.\n */\n async getExpressMethods(\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ): Promise<ExpressMethods> {\n const setup = await this.getPaymentSetup(checkoutSessionId, opts);\n const result: ExpressMethods = {};\n\n for (const [key, config] of Object.entries(setup)) {\n if (!config.enabled) continue;\n\n // Handle express_checkout:processorId entries (from paymentSetupConfig injection)\n // These have a `methods` map like { apple_pay: { enabled: true }, google_pay: { enabled: true } }\n if (key.startsWith('express_checkout:') && config.methods) {\n const base = {\n available: true,\n processorId: config.processorId,\n publishableKey: config.publishableKey,\n metadata: config.metadata,\n };\n if (config.methods.apple_pay?.enabled) {\n const hasApplePay =\n typeof window !== 'undefined' &&\n 'ApplePaySession' in window &&\n (window as unknown as Record<string, { canMakePayments?: () => boolean }>)\n .ApplePaySession?.canMakePayments?.();\n result.applePay = { ...base, type: 'apple_pay', available: !!hasApplePay };\n }\n if (config.methods.google_pay?.enabled) {\n result.googlePay = { ...base, type: 'google_pay' };\n }\n if (config.methods.paypal?.enabled) {\n result.paypal = { ...base, type: 'paypal' };\n }\n if (config.methods.link?.enabled) {\n result.link = { ...base, type: 'link' };\n }\n if (config.methods.klarna_express?.enabled) {\n result.klarna = { ...base, type: 'klarna_express' };\n }\n continue;\n }\n\n if (!config.express) continue;\n\n const method = config.method;\n const base = {\n type: method,\n available: true,\n processorId: config.processorId,\n publishableKey: config.publishableKey,\n metadata: config.metadata,\n };\n\n if (method === 'apple_pay' || config.type === 'apple_pay') {\n const hasApplePay =\n typeof window !== 'undefined' &&\n 'ApplePaySession' in window &&\n (window as unknown as Record<string, { canMakePayments?: () => boolean }>)\n .ApplePaySession?.canMakePayments?.();\n result.applePay = { ...base, available: !!hasApplePay };\n } else if (method === 'google_pay' || config.type === 'google_pay') {\n result.googlePay = base;\n } else if (method === 'paypal') {\n result.paypal = base;\n } else if (method === 'klarna' || method === 'klarna_express') {\n result.klarna = base;\n } else if (method === 'link') {\n result.link = base;\n }\n }\n\n return result;\n }\n\n /**\n * Get store-level payment config (3DS flags, default flow ID, etc.).\n */\n async getStoreConfig(): Promise<StoreConfig> {\n const res = await this.http.get<{ config: StoreConfig }>(\n '/api/v1/checkout/config',\n { params: { storeId: this.storeId } },\n );\n return res.config ?? (res as unknown as StoreConfig);\n }\n\n /**\n * Convenience: return only enabled payment method keys.\n */\n async getEnabledMethods(\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ): Promise<string[]> {\n const setup = await this.getPaymentSetup(checkoutSessionId, opts);\n return Object.entries(setup)\n .filter(([, c]) => c.enabled)\n .map(([key]) => key);\n }\n\n // ---------------------------------------------------------------------------\n // Tokenization (delegates to @tagadapay/core-js if available)\n // ---------------------------------------------------------------------------\n\n /**\n * Tokenize a card using @tagadapay/core-js.\n * Requires `@tagadapay/core-js` to be installed as a peer dependency.\n *\n * Card data is sent directly to Basis Theory for tokenization and never\n * reaches TagadaPay servers. The returned `tagadaToken` is safe to pass\n * to the TagadaPay API.\n *\n * **PCI note:** Using this method means card data passes through your\n * JavaScript environment. You are responsible for PCI DSS SAQ-A-EP\n * compliance. See https://docs.tagada.io/developer-tools/headless-sdk/pci-compliance\n *\n * @returns tagadaToken (base64 string) and rawToken with SCA metadata.\n */\n async tokenizeCard(card: {\n cardNumber: string;\n expiryDate: string;\n cvc: string;\n cardholderName?: string;\n }): Promise<{ tagadaToken: string; rawToken: Record<string, unknown> }> {\n const coreJs = await this.loadCoreJs();\n\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n\n const sanitized: Record<string, string> = {\n cardNumber: card.cardNumber,\n expiryDate: card.expiryDate,\n cvc: card.cvc,\n };\n if (card.cardholderName) sanitized.cardholderName = card.cardholderName;\n\n const [tagadaToken, rawToken] = await Promise.all([\n tokenizer.tokenizeCard(sanitized),\n tokenizer.tokenizeCardRaw(sanitized),\n ]);\n\n return { tagadaToken, rawToken };\n }\n\n // ---------------------------------------------------------------------------\n // Instrument creation\n // ---------------------------------------------------------------------------\n\n /**\n * Create a reusable payment instrument from a TagadaToken.\n * Session-authenticated (uses the checkout session JWT).\n */\n async createInstrument(\n opts: CreateInstrumentOptions,\n ): Promise<{ paymentInstrument: PaymentInstrument }> {\n return this.http.post('/api/v1/payment/create-instrument-from-token', {\n tagadaToken: opts.tagadaToken,\n });\n }\n\n // ---------------------------------------------------------------------------\n // 3DS\n // ---------------------------------------------------------------------------\n\n /**\n * Create a 3DS session on the TagadaPay backend.\n * This persists the session so the processor can use it during payment.\n */\n async create3dsSession(opts: {\n paymentInstrumentId: string;\n sessionData: { sessionId: string; metadata?: Record<string, unknown> };\n provider?: string;\n }): Promise<ThreedsSession> {\n return this.http.post('/api/public/v1/threeds/create-session', {\n provider: opts.provider ?? 'basis_theory',\n storeId: this.storeId,\n paymentInstrumentId: opts.paymentInstrumentId,\n sessionData: opts.sessionData,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Payment processing\n // ---------------------------------------------------------------------------\n\n /**\n * High-level pay: single API call that decodes tagadaToken server-side,\n * creates the payment instrument, and processes payment.\n *\n * Also accepts `paymentInstrumentId` directly for pre-created instruments.\n */\n async pay(opts: PayOptions): Promise<PayResult> {\n if (opts.tagadaToken && !opts.paymentInstrumentId) {\n return this.http.post<PayResult>('/api/v1/payment/pay-with-token', {\n tagadaToken: opts.tagadaToken,\n checkoutSessionId: opts.checkoutSessionId,\n returnUrl: opts.returnUrl,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n });\n }\n\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId,\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n threedsSessionId: opts.threedsSessionId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n });\n }\n\n /**\n * Low-level pay: process payment with an existing instrument or for APM/express flows\n * where no instrument is needed (redirect-based methods).\n */\n async payDirect(opts: PayDirectOptions): Promise<PayResult> {\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId ?? '',\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n threedsSessionId: opts.threedsSessionId,\n });\n }\n\n /**\n * Process an Apple Pay payment.\n * Tokenizes the Apple Pay token and processes payment in one call.\n */\n async processApplePay(opts: {\n checkoutSessionId: string;\n applePayToken: unknown;\n paymentFlowId?: string;\n processorId?: string;\n }): Promise<PayResult> {\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n const { tagadaToken } = await tokenizer.tokenizeApplePay(opts.applePayToken);\n\n return this.pay({\n checkoutSessionId: opts.checkoutSessionId,\n tagadaToken,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: 'apple_pay',\n isExpress: true,\n });\n }\n\n /**\n * Process a Google Pay payment.\n * Tokenizes the Google Pay token and processes payment in one call.\n */\n async processGooglePay(opts: {\n checkoutSessionId: string;\n googlePayToken: string;\n paymentFlowId?: string;\n processorId?: string;\n }): Promise<PayResult> {\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n const { tagadaToken } = await tokenizer.tokenizeGooglePay(opts.googlePayToken);\n\n return this.pay({\n checkoutSessionId: opts.checkoutSessionId,\n tagadaToken,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: 'google_pay',\n isExpress: true,\n });\n }\n\n /**\n * Process an APM payment (Klarna, iDEAL, etc.) via redirect.\n * These typically don't require a payment instrument -- the processor handles the redirect.\n */\n async processApm(opts: {\n checkoutSessionId: string;\n paymentMethod: string;\n processorId: string;\n paymentFlowId?: string;\n }): Promise<PayResult> {\n return this.payDirect({\n checkoutSessionId: opts.checkoutSessionId,\n paymentMethod: opts.paymentMethod,\n processorId: opts.processorId,\n paymentFlowId: opts.paymentFlowId,\n });\n }\n\n /**\n * Initiate a Stripe Express Checkout payment (Apple Pay, Google Pay, Link, etc.).\n *\n * Calls `pay-v2` with `isExpress: true`, which returns a `clientSecret` in\n * `payment.requireActionData.metadata.stripeExpressCheckout.clientSecret`.\n * The caller must then call `stripe.confirmPayment()` with that secret.\n *\n * Used by the `StripeExpressCheckout` class and `useStripeExpress` hook.\n * Not typically called directly \u2014 use the Stripe integration classes instead.\n */\n async processStripeExpress(opts: {\n checkoutSessionId: string;\n processorId: string;\n paymentMethod: string;\n }): Promise<PayResult> {\n return this.payDirect({\n checkoutSessionId: opts.checkoutSessionId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // High-level orchestrator \u2014 the ONE function beginners should call\n // ---------------------------------------------------------------------------\n\n /**\n * Process a payment end-to-end: pay, handle 3DS / redirects, poll until done.\n *\n * This is the **recommended** way to process payments. It wraps `pay()`, detects\n * `requireAction`, runs 3DS challenges (if `@tagadapay/core-js` is installed),\n * and polls until a terminal status.\n *\n * Returns a discriminated union so you can pattern-match on `result.status`:\n *\n * @example\n * ```ts\n * const result = await payment.processPayment({\n * checkoutSessionId: session.id,\n * tagadaToken,\n * });\n *\n * switch (result.status) {\n * case 'succeeded':\n * console.log('Paid!', result.payment.id);\n * break;\n * case 'requires_redirect':\n * // In browser: window.location.href = result.redirectUrl\n * // The React hook handles this automatically.\n * break;\n * case 'failed':\n * console.error(result.error);\n * break;\n * }\n * ```\n */\n async processPayment(opts: ProcessPaymentOptions): Promise<ProcessPaymentResult> {\n if (!opts.returnUrl && typeof window !== 'undefined') {\n opts = { ...opts, returnUrl: window.location.href };\n }\n const payResult = await this.pay(opts);\n const payment = payResult.payment;\n\n if (payment.status === 'succeeded') {\n return { status: 'succeeded', payment, order: payResult.order };\n }\n\n if (payment.status === 'failed' || payment.status === 'declined') {\n const msg = payment.requireActionData?.message\n || payment.requireActionData?.errorCode\n || `Payment ${payment.status}`;\n return { status: 'failed', error: msg, payment };\n }\n\n if (payment.requireAction && payment.requireAction !== 'none' && payment.requireActionData) {\n return this.handlePaymentAction(payment, opts);\n }\n\n // status is 'pending' or 'requires_action' without explicit actionData \u2014 poll\n return this.pollUntilDone(payment.id);\n }\n\n /**\n * Resume a payment after the user returns from a redirect (3DS, processor auth, APM).\n *\n * Called automatically by `usePayment()` in React when it detects return-URL params.\n * You can also call it manually in non-React apps.\n */\n async resumeAfterRedirect(paymentId: string): Promise<ProcessPaymentResult> {\n return this.pollUntilDone(paymentId);\n }\n\n // ---------------------------------------------------------------------------\n // Status polling\n // ---------------------------------------------------------------------------\n\n /** Get current status of a payment. */\n async getPaymentStatus(paymentId: string): Promise<PaymentStatus> {\n return this.http.get<PaymentStatus>(`/api/v1/payments/${paymentId}`);\n }\n\n /**\n * Poll a payment until it reaches a terminal status.\n * Returns the final status or throws on timeout.\n */\n async pollPaymentStatus(\n paymentId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<PaymentStatus> {\n const interval = opts?.intervalMs ?? 1500;\n const timeout = opts?.timeoutMs ?? 60_000;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const status = await this.getPaymentStatus(paymentId);\n if (status.status === 'succeeded' || status.status === 'failed' || status.status === 'declined') {\n return status;\n }\n await new Promise((r) => setTimeout(r, interval));\n }\n\n throw new Error(`Payment ${paymentId} did not reach terminal status within ${timeout}ms.`);\n }\n\n /** Finalize a payment after a 3DS challenge completes. */\n async completeAfter3ds(paymentId: string): Promise<PaymentStatus> {\n return this.http.post<PaymentStatus>('/api/v1/payments/complete-after-3ds', {\n paymentId,\n });\n }\n\n /** Tell the server this action has been seen / is being processed. */\n async markActionProcessed(paymentId: string): Promise<void> {\n try {\n await this.http.post('/api/v1/payments/require-action/processed', {\n paymentId,\n });\n } catch {\n // Best-effort \u2014 don't block the payment flow if this fails\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal: action routing\n // ---------------------------------------------------------------------------\n\n /**\n * Route a payment action to the appropriate handler.\n * Returns `requires_redirect` for browser-level redirects,\n * or attempts 3DS inline and polls to completion.\n */\n private async handlePaymentAction(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const actionData = payment.requireActionData!;\n\n await this.markActionProcessed(payment.id);\n\n const actionType = actionData.type;\n\n switch (actionType) {\n case 'threeds_auth':\n return this.handleThreedsAuth(payment, opts);\n\n case 'processor_auth':\n case 'redirect_to_payment':\n return this.extractRedirect(payment, actionData);\n\n case 'redirect':\n return this.extractRedirect(payment, actionData);\n\n case 'error':\n return {\n status: 'failed',\n error: actionData.message || actionData.errorCode || 'Payment failed',\n payment,\n };\n\n default:\n // Unknown action type \u2014 try to extract a redirect URL (forward-compatible)\n return this.extractRedirect(payment, actionData);\n }\n }\n\n /**\n * Extract redirect info from actionData.\n * Works for processor_auth (GET or POST), redirect, and any unknown type with a URL.\n */\n private extractRedirect(\n payment: PayResult['payment'],\n actionData: NonNullable<PayResult['payment']['requireActionData']>,\n ): ProcessPaymentResult {\n const redirect = actionData.metadata?.redirect;\n const url = redirect?.redirectUrl || actionData.redirectUrl;\n\n if (!url) {\n return {\n status: 'failed',\n error: `Payment requires action (${actionData.type}) but no redirect URL was provided`,\n payment,\n };\n }\n\n return {\n status: 'requires_redirect',\n redirectUrl: url,\n method: (redirect?.method?.toUpperCase() as 'GET' | 'POST') || 'GET',\n postData: redirect?.data,\n paymentId: payment.id,\n };\n }\n\n /**\n * Run a 3DS challenge using @tagadapay/core-js.\n * If core-js is not installed, falls back to redirect.\n */\n private async handleThreedsAuth(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const session = payment.requireActionData?.metadata?.threedsSession;\n\n // If no 3DS session data, fall back to redirect (acsChallengeUrl)\n if (!session?.externalSessionId) {\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Try to run the challenge inline via core-js\n let coreJs: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n try {\n coreJs = await import('@tagadapay/core-js');\n } catch {\n // core-js not installed \u2014 fall back to redirect if possible\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Run BasisTheory 3DS challenge in a modal iframe\n try {\n const manager = new coreJs.ThreedsManager({ provider: 'basis_theory' });\n await manager.initialize({ apiKey: undefined });\n\n await manager.startChallenge({\n sessionId: session.externalSessionId,\n acsChallengeUrl: session.acsChallengeUrl,\n acsTransactionId: session.acsTransID,\n threeDSVersion: session.messageVersion,\n });\n\n // Challenge done \u2014 tell backend and poll\n await this.completeAfter3ds(payment.id);\n return this.pollUntilDone(payment.id);\n } catch {\n // 3DS challenge failed \u2014 fall back to redirect\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return {\n status: 'failed',\n error: '3D Secure authentication failed',\n payment,\n };\n }\n }\n\n /**\n * Poll until the payment reaches a terminal status, then return a ProcessPaymentResult.\n * Also handles new requireAction that may appear during polling.\n */\n private async pollUntilDone(\n paymentId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<ProcessPaymentResult> {\n const interval = opts?.intervalMs ?? 1500;\n const timeout = opts?.timeoutMs ?? 60_000;\n const start = Date.now();\n let consecutiveErrors = 0;\n\n while (Date.now() - start < timeout) {\n let status: PaymentStatus;\n try {\n status = await this.getPaymentStatus(paymentId);\n consecutiveErrors = 0;\n } catch {\n consecutiveErrors++;\n if (consecutiveErrors >= 3) {\n return { status: 'failed', error: 'Payment verification failed due to network errors' };\n }\n await new Promise((r) => setTimeout(r, interval));\n continue;\n }\n\n if (\n status.status === 'succeeded' ||\n (status.status === 'pending' && status.subStatus === 'authorized')\n ) {\n return { status: 'succeeded', payment: status as unknown as PayResult['payment'], order: status.order };\n }\n\n if (status.status === 'failed' || status.status === 'declined') {\n return { status: 'failed', error: status.status, payment: status as unknown as PayResult['payment'] };\n }\n\n // New unprocessed action appeared during polling\n if (\n status.requireAction &&\n status.requireAction !== 'none' &&\n status.requireActionData &&\n !status.requireActionData.processed\n ) {\n return this.handlePaymentAction(\n status as unknown as PayResult['payment'],\n {} as ProcessPaymentOptions,\n );\n }\n\n await new Promise((r) => setTimeout(r, interval));\n }\n\n return { status: 'pending', paymentId };\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Read paymentSetupConfig from the Tagada routing injection.\n * Only available when running on Tagada infra (not on external hosting like Vercel).\n */\n private readInjectedStepConfig(): PaymentSetupConfig | null {\n if (typeof window === 'undefined') return null;\n const raw = (window as unknown as Record<string, unknown>).__TGD_STEP_CONFIG__;\n if (!raw) return null;\n try {\n const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;\n return (parsed as Record<string, unknown>)?.paymentSetupConfig as PaymentSetupConfig ?? null;\n } catch {\n return null;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private async loadCoreJs(): Promise<any> {\n try {\n return await import('@tagadapay/core-js');\n } catch {\n throw new Error(\n 'This method requires @tagadapay/core-js. Install it: npm install @tagadapay/core-js',\n );\n }\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { Offer, OfferPreview, OfferPayResult } from '../types.js';\n\n/**\n * Offers \u2014 upsells, downsells, order bumps, and post-purchase offers.\n *\n * Endpoints align with the plugin-sdk patterns:\n * GET /api/v1/offers/:id \u2014 single offer\n * GET /api/v1/stores/:storeId/offers \u2014 list store offers\n * POST /api/v1/offers/:offerId/preview \u2014 preview pricing\n * POST /api/v1/offers/:offerId/pay-preview \u2014 pay a previewed offer (one-click)\n * POST /api/v1/checkout-sessions/:id/toggle-order-bump \u2014 toggle order bump\n * GET /api/v1/post-purchase/:orderId/offers \u2014 post-purchase offers for an order\n * POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/accept \u2014 accept\n * POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/decline \u2014 decline\n */\nexport class OffersModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Offer loading\n // ---------------------------------------------------------------------------\n\n /** Get a single offer by ID. */\n async getOffer(offerId: string): Promise<Offer> {\n return this.http.get<Offer>(`/api/v1/offers/${offerId}`);\n }\n\n /** List offers for the current store. Optionally filter by type or a set of IDs. */\n async listOffers(opts?: {\n type?: 'upsell' | 'orderbump';\n ids?: string[];\n }): Promise<Offer[]> {\n let url = `/api/v1/stores/${this.storeId}/offers`;\n\n const queryParts: string[] = [];\n if (opts?.type) queryParts.push(`type=${encodeURIComponent(opts.type)}`);\n if (opts?.ids?.length) {\n for (const id of opts.ids) queryParts.push(`ids=${encodeURIComponent(id)}`);\n }\n if (queryParts.length) url += `?${queryParts.join('&')}`;\n\n const res = await this.http.get<{ offers: Offer[] }>(url);\n return res.offers ?? [];\n }\n\n // ---------------------------------------------------------------------------\n // Preview & pay (one-click upsell flow from plugin-sdk)\n // ---------------------------------------------------------------------------\n\n /** Preview offer pricing. Returns line items with amounts and totals. */\n async previewOffer(opts: {\n offerId: string;\n currency?: string;\n lineItems?: Array<{ lineItemId?: string; productId?: string; variantId: string; quantity: number }>;\n }): Promise<OfferPreview> {\n return this.http.post<OfferPreview>(`/api/v1/offers/${opts.offerId}/preview`, {\n offerId: opts.offerId,\n currency: opts.currency ?? '',\n lineItems: opts.lineItems,\n });\n }\n\n /**\n * Pay a previously previewed offer (one-click charge).\n * Used after a main order so the stored payment instrument is reused.\n */\n async payPreviewedOffer(opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ lineItemId?: string; productId?: string; variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }): Promise<OfferPayResult> {\n return this.http.post<OfferPayResult>(`/api/v1/offers/${opts.offerId}/pay-preview`, {\n offerId: opts.offerId,\n currency: opts.currency ?? '',\n lineItems: opts.lineItems,\n returnUrl: opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),\n mainOrderId: opts.mainOrderId,\n paymentInstrumentId: opts.paymentInstrumentId,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Order bumps (checkout-session scoped)\n // ---------------------------------------------------------------------------\n\n /** Toggle an order bump on/off within a checkout session. */\n async toggleOrderBump(opts: {\n checkoutSessionId: string;\n orderBumpOfferId: string;\n selected: boolean;\n }): Promise<unknown> {\n return this.http.post(\n `/api/v1/checkout-sessions/${opts.checkoutSessionId}/toggle-order-bump`,\n {\n orderBumpOfferId: opts.orderBumpOfferId,\n selected: opts.selected,\n },\n );\n }\n\n // ---------------------------------------------------------------------------\n // Post-purchase offers (order-scoped)\n // ---------------------------------------------------------------------------\n\n /** List post-purchase offers for an order. */\n async listPostPurchaseOffers(orderId: string): Promise<Offer[]> {\n const res = await this.http.get<Offer[]>(`/api/v1/post-purchase/${orderId}/offers`);\n return Array.isArray(res) ? res : [];\n }\n\n /** Accept a post-purchase offer. */\n async acceptPostPurchaseOffer(opts: {\n orderId: string;\n offerId: string;\n items?: Array<{ variantId: string; quantity: number }>;\n }): Promise<{ success: boolean; error?: string }> {\n return this.http.post(\n `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/accept`,\n { items: opts.items ?? [] },\n );\n }\n\n /** Decline a post-purchase offer. */\n async declinePostPurchaseOffer(opts: {\n orderId: string;\n offerId: string;\n }): Promise<{ success: boolean; error?: string }> {\n return this.http.post(\n `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/decline`,\n );\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { Customer, Order, Subscription } from '../types.js';\n\n/**\n * Customer data -- profile, orders, subscriptions.\n *\n * Requires either an API key or a session token for authentication.\n */\nexport class CustomerModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n /** Get customer profile by ID. */\n async getProfile(customerId: string): Promise<Customer> {\n const res = await this.http.get<{ customer: Customer }>(\n `/api/v1/customers/${customerId}`,\n { params: { storeId: this.storeId } },\n );\n return res.customer;\n }\n\n /** Get customer profile by email. */\n async getByEmail(email: string): Promise<Customer | null> {\n try {\n const res = await this.http.get<{ customer: Customer }>(\n '/api/v1/customers/by-email',\n { params: { email, storeId: this.storeId } },\n );\n return res.customer;\n } catch {\n return null;\n }\n }\n\n /** Update customer profile fields. */\n async updateProfile(\n customerId: string,\n data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone' | 'metadata'>>,\n ): Promise<Customer> {\n const res = await this.http.patch<{ customer: Customer }>(\n `/api/v1/customers/${customerId}`,\n { storeId: this.storeId, ...data },\n );\n return res.customer;\n }\n\n /** List orders for a customer. */\n async getOrders(\n customerId: string,\n opts?: { limit?: number; offset?: number },\n ): Promise<{ orders: Order[]; total: number }> {\n return this.http.get<{ orders: Order[]; total: number }>(\n `/api/v1/customers/${customerId}/orders`,\n { params: { storeId: this.storeId, limit: opts?.limit, offset: opts?.offset } },\n );\n }\n\n /** Get a single order by ID. */\n async getOrder(orderId: string): Promise<Order> {\n const res = await this.http.get<{ order: Order }>(`/api/v1/orders/${orderId}`, {\n params: { storeId: this.storeId },\n });\n return res.order;\n }\n\n /** List subscriptions for a customer. */\n async getSubscriptions(customerId: string): Promise<Subscription[]> {\n const res = await this.http.get<{ subscriptions: Subscription[] }>(\n `/api/v1/customers/${customerId}/subscriptions`,\n { params: { storeId: this.storeId } },\n );\n return res.subscriptions;\n }\n\n /** Get a single subscription by ID. */\n async getSubscription(subscriptionId: string): Promise<Subscription> {\n const res = await this.http.get<{ subscription: Subscription }>(\n `/api/v1/subscriptions/${subscriptionId}`,\n { params: { storeId: this.storeId } },\n );\n return res.subscription;\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { CatalogProduct } from '../types.js';\n\n/**\n * Fetches the product catalog for a store.\n *\n * Uses the public `/api/v1/products` endpoint (no auth required).\n */\nexport class CatalogModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n /**\n * List all active products for the store, including variants and prices.\n *\n * @param opts.productIds Optional filter to specific product IDs.\n * @param opts.variantIds Optional filter to products containing these variant IDs.\n */\n async getProducts(opts?: {\n productIds?: string[];\n variantIds?: string[];\n }): Promise<CatalogProduct[]> {\n const body: Record<string, unknown> = {\n storeId: this.storeId,\n includeVariants: true,\n includePrices: true,\n };\n if (opts?.productIds?.length) body.productIds = opts.productIds;\n if (opts?.variantIds?.length) body.variantIds = opts.variantIds;\n\n const res = await this.http.post<{ items: CatalogProduct[] }>(\n '/api/v1/products',\n body,\n );\n\n return res.items ?? [];\n }\n\n /**\n * Get a single product by ID.\n */\n async getProduct(productId: string): Promise<CatalogProduct | null> {\n const items = await this.getProducts({ productIds: [productId] });\n return items[0] ?? null;\n }\n}\n", "import { HttpClient } from './http.js';\nimport { CheckoutModule } from './modules/checkout.js';\nimport { PaymentModule } from './modules/payment.js';\nimport { OffersModule } from './modules/offers.js';\nimport { CustomerModule } from './modules/customer.js';\nimport { CatalogModule } from './modules/catalog.js';\nimport type { HeadlessConfig, Environment } from './types.js';\n\n/**\n * Main entry point for the TagadaPay Headless SDK.\n *\n * Composes all domain modules (checkout, payment, offers, customer, catalog)\n * over a single lightweight HTTP client built on native fetch.\n *\n * **PCI DSS notice:** Card tokenization via `payment.tokenizeCard()` sends\n * card data directly to Basis Theory \u2014 it never reaches TagadaPay servers.\n * However, because card data passes through your JavaScript environment,\n * merchants using this SDK are responsible for PCI DSS SAQ-A-EP compliance.\n * See https://docs.tagada.io/developer-tools/headless-sdk/pci-compliance\n */\nexport class HeadlessClient {\n readonly config: Required<Pick<HeadlessConfig, 'storeId' | 'environment'>> & HeadlessConfig;\n\n private readonly http: HttpClient;\n\n /** Shared session token used by all modules for authenticated API calls. */\n private _sessionToken: string | undefined;\n\n /** Checkout session management -- load, update cart, apply promos, shipping. */\n readonly checkout: CheckoutModule;\n\n /** Payment processing -- setup config, APMs, tokenize, pay, 3DS, poll. */\n readonly payment: PaymentModule;\n\n /** Offers -- preview, pay, accept/decline upsells and order bumps. */\n readonly offers: OffersModule;\n\n /** Customer data -- profile, orders, subscriptions. */\n readonly customer: CustomerModule;\n\n /** Product catalog -- list products, variants, and prices. */\n readonly catalog: CatalogModule;\n\n constructor(config: HeadlessConfig) {\n const environment: Environment = config.environment ?? 'production';\n const baseUrl = HttpClient.resolveBaseUrl(environment, config.baseUrl);\n\n this.config = {\n ...config,\n environment,\n baseUrl,\n timeout: config.timeout ?? 30_000,\n };\n\n this.http = new HttpClient({\n baseUrl,\n timeout: this.config.timeout!,\n apiKey: config.apiKey,\n getToken: () => this._sessionToken,\n });\n\n const setToken = (token: string) => {\n this._sessionToken = token;\n };\n\n this.checkout = new CheckoutModule(this.http, this.config.storeId, setToken);\n this.payment = new PaymentModule(this.http, this.config.storeId, environment);\n this.offers = new OffersModule(this.http, this.config.storeId);\n this.customer = new CustomerModule(this.http, this.config.storeId);\n this.catalog = new CatalogModule(this.http, this.config.storeId);\n }\n\n /** Manually set the session token (e.g. from URL params on page load). */\n setSessionToken(token: string) {\n this._sessionToken = token;\n }\n}\n\n/**\n * Create a new HeadlessClient instance.\n *\n * @example\n * ```ts\n * import { createHeadlessClient } from '@tagadapay/headless-sdk';\n *\n * const tagada = createHeadlessClient({\n * storeId: 'store_abc123',\n * environment: 'production',\n * });\n *\n * const session = await tagada.checkout.loadSession(checkoutToken);\n * ```\n */\nexport function createHeadlessClient(config: HeadlessConfig): HeadlessClient {\n return new HeadlessClient(config);\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { CheckoutSession, LineItem, ShippingRate, Address, CheckoutCustomer } from '../../core/types.js';\n\nexport interface UseCheckoutReturn {\n session: CheckoutSession | null;\n isLoading: boolean;\n error: Error | null;\n /** Reload the session from the server. */\n refresh: () => Promise<void>;\n /** Create a new checkout session (auto-loads it after creation). */\n createSession: (opts: {\n items: LineItem[];\n currency?: string;\n returnUrl?: string;\n customerEmail?: string;\n }) => Promise<void>;\n /** Replace cart items. */\n updateCart: (items: LineItem[]) => Promise<void>;\n /** Update customer info on the session. */\n updateCustomer: (customer: Partial<CheckoutCustomer>) => Promise<void>;\n /** Update address on the session. */\n updateAddress: (addresses: { shippingAddress?: Address; billingAddress?: Address }) => Promise<void>;\n /**\n * Update customer info AND address in a single call. Prefer this over\n * calling `updateCustomer` then `updateAddress` separately \u2014 the\n * underlying server action is destructive on partial saves\n * (`customers.firstName = shippingAddress.firstName ?? null`), so\n * sending the address without the customer name will silently wipe\n * `customer.firstName` / `customer.lastName` from the session.\n */\n updateCustomerAndAddress: (data: {\n customer: Partial<CheckoutCustomer>;\n shippingAddress?: Address;\n billingAddress?: Address;\n }) => Promise<void>;\n /** Apply a promo code. */\n applyPromo: (code: string) => Promise<void>;\n /** Remove the applied promo code. */\n removePromo: (promotionId?: string) => Promise<void>;\n /** Fetch shipping rates. */\n getShippingRates: () => Promise<ShippingRate[]>;\n /** Select a shipping rate. */\n selectShippingRate: (rateId: string) => Promise<void>;\n}\n\n/**\n * React hook for checkout session management.\n *\n * @param checkoutToken - The checkout token from the URL (e.g. `?checkoutToken=xxx`).\n * @param sessionToken - Optional JWT session token (from URL param `token`).\n *\n * @example\n * ```tsx\n * const { session, isLoading, applyPromo, createSession } = useCheckout(checkoutToken, sessionToken);\n * ```\n */\nexport function useCheckout(\n checkoutToken: string | null | undefined,\n sessionToken?: string,\n): UseCheckoutReturn {\n const client = useHeadlessClient();\n const [session, setSession] = useState<CheckoutSession | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const loadSession = useCallback(async () => {\n if (!checkoutToken) return;\n setIsLoading(true);\n setError(null);\n try {\n const s = await client.checkout.loadSession(checkoutToken, sessionToken);\n setSession(s);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, checkoutToken, sessionToken]);\n\n useEffect(() => {\n loadSession();\n }, [loadSession]);\n\n const createSession = useCallback(async (opts: {\n items: LineItem[];\n currency?: string;\n returnUrl?: string;\n customerEmail?: string;\n }) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.checkout.createSession(opts);\n\n const newUrl = new URL(window.location.href);\n newUrl.searchParams.set('checkoutToken', result.checkoutToken);\n newUrl.searchParams.set('token', result.sessionToken);\n window.history.replaceState({}, '', newUrl.toString());\n\n const s = await client.checkout.loadSession(result.checkoutToken, result.sessionToken);\n setSession(s);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n const updateCart = useCallback(async (items: LineItem[]) => {\n if (!session) return;\n // `updateCart` returns mutation stats (counts), not a CheckoutSession.\n // We previously assigned that result into `setSession`, which silently\n // replaced the session with `{ success, updated, created, total }`.\n // Mirror the same pattern as `updateAddress`: mutate, then reload.\n await client.checkout.updateCart(session.id, items);\n await loadSession();\n }, [client, session, loadSession]);\n\n const updateCustomer = useCallback(async (customer: Partial<CheckoutCustomer>) => {\n if (!session) return;\n await client.checkout.updateCustomer(session.id, customer);\n }, [client, session]);\n\n const updateAddress = useCallback(async (addresses: { shippingAddress?: Address; billingAddress?: Address }) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.updateAddress(session.id, addresses);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const updateCustomerAndAddress = useCallback(async (data: {\n customer: Partial<CheckoutCustomer>;\n shippingAddress?: Address;\n billingAddress?: Address;\n }) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.updateCustomerAndAddress(session.id, data);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const applyPromo = useCallback(async (code: string) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.applyPromoCode(session.id, code);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const removePromo = useCallback(async (promotionId?: string) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.removePromoCode(session.id, promotionId);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const getShippingRates = useCallback(async () => {\n if (!session) return [];\n return client.checkout.getShippingRates(session.id);\n }, [client, session]);\n\n const selectShippingRate = useCallback(async (rateId: string) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.selectShippingRate(session.id, rateId);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n return {\n session,\n isLoading,\n error,\n refresh: loadSession,\n createSession,\n updateCart,\n updateCustomer,\n updateAddress,\n updateCustomerAndAddress,\n applyPromo,\n removePromo,\n getShippingRates,\n selectShippingRate,\n };\n}\n", "import { useState, useCallback, useRef, useEffect } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type {\n PaymentSetupConfig,\n ExpressMethods,\n StoreConfig,\n PayResult,\n PayOptions,\n PaymentStatus,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n} from '../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Hook options (passed to usePayment for callback-based flows)\n// ---------------------------------------------------------------------------\n\nexport interface UsePaymentOptions {\n /**\n * Called when a payment succeeds (including after 3DS redirect return).\n * Use this to navigate to a confirmation page.\n */\n onPaymentSuccess?: (result: ProcessPaymentResult & { status: 'succeeded' }) => void;\n /**\n * Called when a payment fails (including after redirect return).\n */\n onPaymentFailed?: (result: ProcessPaymentResult & { status: 'failed' }) => void;\n /**\n * Explicit paymentSetupConfig override.\n * When provided, the SDK skips both __TGD_STEP_CONFIG__ detection and the API call.\n * Useful when a developer fetches the config from their own backend.\n */\n paymentSetupConfig?: PaymentSetupConfig;\n}\n\nexport interface UsePaymentReturn {\n /** Full payment setup config (all methods with their enabled/disabled state). */\n paymentSetup: PaymentSetupConfig | null;\n /** Express methods (Apple Pay, Google Pay, etc.) with browser availability. */\n expressMethods: ExpressMethods | null;\n /** Store-level config (3DS flags, etc.). */\n storeConfig: StoreConfig | null;\n /** Whether a payment is currently being processed (including polling after redirect). */\n isProcessing: boolean;\n /** Last payment result. */\n result: PayResult | null;\n /** Last error. */\n error: Error | null;\n /**\n * Load payment setup for a checkout session. Call this once when the session is ready.\n * Optionally pass `paymentSetupConfig` to override auto-detection.\n */\n loadPaymentSetup: (checkoutSessionId: string, opts?: { paymentSetupConfig?: PaymentSetupConfig }) => Promise<void>;\n\n /**\n * **Recommended**. Tokenize + pay + handle 3DS/redirects + poll \u2014 all in one call.\n *\n * - If the payment succeeds immediately, resolves with `{ status: 'succeeded' }`.\n * - If 3DS redirect is needed, automatically redirects the browser.\n * When the user comes back, the hook auto-detects the return and polls.\n * - If the payment fails, resolves with `{ status: 'failed', error: '...' }`.\n */\n processPayment: (opts: ProcessPaymentOptions) => Promise<ProcessPaymentResult>;\n\n /** Low-level pay (returns raw API response, no automatic action handling). */\n pay: (opts: PayOptions) => Promise<PayResult>;\n /**\n * Tokenize a card (returns tagadaToken). Requires @tagadapay/core-js.\n *\n * PCI note: card data passes through your JS environment.\n * You are responsible for PCI DSS SAQ-A-EP compliance.\n */\n tokenizeCard: (card: {\n cardNumber: string;\n expiryDate: string;\n cvc: string;\n cardholderName?: string;\n }) => Promise<{ tagadaToken: string; rawToken: Record<string, unknown> }>;\n /** Process Apple Pay. */\n processApplePay: (opts: {\n checkoutSessionId: string;\n applePayToken: unknown;\n }) => Promise<PayResult>;\n /** Process Google Pay. */\n processGooglePay: (opts: {\n checkoutSessionId: string;\n googlePayToken: string;\n }) => Promise<PayResult>;\n /** Process redirect-based APM (Klarna, iDEAL, etc.). */\n processApm: (opts: {\n checkoutSessionId: string;\n paymentMethod: string;\n processorId: string;\n }) => Promise<PayResult>;\n /** Poll a payment until terminal status. */\n pollStatus: (paymentId: string) => Promise<PaymentStatus>;\n}\n\n/**\n * React hook for payment processing.\n *\n * Handles the full payment lifecycle including 3DS redirects and return-URL detection.\n *\n * @example\n * ```tsx\n * const { processPayment, isProcessing, error } = usePayment({\n * onPaymentSuccess: (result) => router.push('/confirmation'),\n * onPaymentFailed: (result) => toast.error(result.error),\n * });\n *\n * // On submit \u2014 one function handles everything\n * const result = await processPayment({\n * checkoutSessionId: session.id,\n * tagadaToken,\n * });\n * ```\n */\nexport function usePayment(options?: UsePaymentOptions): UsePaymentReturn {\n const client = useHeadlessClient();\n const [paymentSetup, setPaymentSetup] = useState<PaymentSetupConfig | null>(null);\n const [expressMethods, setExpressMethods] = useState<ExpressMethods | null>(null);\n const [storeConfig, setStoreConfig] = useState<StoreConfig | null>(null);\n const [isProcessing, setIsProcessing] = useState(false);\n const [result, setResult] = useState<PayResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const loadedRef = useRef(false);\n const redirectReturnProcessedRef = useRef(false);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // ---------------------------------------------------------------------------\n // Return-URL detection: auto-resume after 3DS / processor redirect\n // ---------------------------------------------------------------------------\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (redirectReturnProcessedRef.current) return;\n\n const params = new URLSearchParams(window.location.search);\n const paymentAction = params.get('paymentAction');\n const paymentActionStatus = params.get('paymentActionStatus');\n const paymentId = params.get('paymentId');\n\n if (paymentAction !== 'requireAction' || paymentActionStatus !== 'completed' || !paymentId) {\n return;\n }\n\n redirectReturnProcessedRef.current = true;\n setIsProcessing(true);\n setError(null);\n\n const resume = async () => {\n try {\n const resumeResult = await client.payment.resumeAfterRedirect(paymentId);\n\n // Clean payment-related query params from URL\n const cleanParams = new URLSearchParams(window.location.search);\n ['paymentAction', 'paymentActionStatus', 'paymentId', 'payment_intent', 'payment_intent_client_secret', 'source_type', 'redirect_status'].forEach(\n (p) => cleanParams.delete(p),\n );\n const newUrl = cleanParams.toString()\n ? `${window.location.pathname}?${cleanParams.toString()}`\n : window.location.pathname;\n window.history.replaceState({}, document.title, newUrl);\n\n if (resumeResult.status === 'succeeded') {\n optionsRef.current?.onPaymentSuccess?.(resumeResult);\n } else if (resumeResult.status === 'failed') {\n setError(new Error(resumeResult.error));\n optionsRef.current?.onPaymentFailed?.(resumeResult);\n }\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsProcessing(false);\n }\n };\n\n void resume();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ---------------------------------------------------------------------------\n // Load payment setup\n // ---------------------------------------------------------------------------\n const loadPaymentSetup = useCallback(async (\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ) => {\n if (loadedRef.current) return;\n loadedRef.current = true;\n const setupOpts = opts?.paymentSetupConfig\n ? { paymentSetupConfig: opts.paymentSetupConfig }\n : optionsRef.current?.paymentSetupConfig\n ? { paymentSetupConfig: optionsRef.current.paymentSetupConfig }\n : undefined;\n try {\n const [setup, express, config] = await Promise.all([\n client.payment.getPaymentSetup(checkoutSessionId, setupOpts),\n client.payment.getExpressMethods(checkoutSessionId, setupOpts),\n client.payment.getStoreConfig(),\n ]);\n setPaymentSetup(setup);\n setExpressMethods(express);\n setStoreConfig(config);\n } catch (err) {\n loadedRef.current = false;\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n // ---------------------------------------------------------------------------\n // processPayment \u2014 high-level, handles everything\n // ---------------------------------------------------------------------------\n const processPayment = useCallback(\n async (opts: ProcessPaymentOptions): Promise<ProcessPaymentResult> => {\n setIsProcessing(true);\n setError(null);\n try {\n const payResult = await client.payment.processPayment(opts);\n\n if (payResult.status === 'requires_redirect') {\n // Browser redirect \u2014 the hook will resume on return via the useEffect above\n if (payResult.method === 'POST' && payResult.postData) {\n const form = document.createElement('form');\n form.method = 'POST';\n form.action = payResult.redirectUrl;\n for (const [key, value] of Object.entries(payResult.postData)) {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = key;\n input.value = value;\n form.appendChild(input);\n }\n document.body.appendChild(form);\n form.submit();\n } else {\n window.location.href = payResult.redirectUrl;\n }\n // Don't setIsProcessing(false) \u2014 page is navigating away\n return payResult;\n }\n\n if (payResult.status === 'succeeded') {\n optionsRef.current?.onPaymentSuccess?.(payResult);\n } else if (payResult.status === 'failed') {\n setError(new Error(payResult.error));\n optionsRef.current?.onPaymentFailed?.(payResult);\n }\n\n return payResult;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n return { status: 'failed', error: e.message };\n } finally {\n setIsProcessing(false);\n }\n },\n [client],\n );\n\n // ---------------------------------------------------------------------------\n // Low-level pay (raw API, no action handling)\n // ---------------------------------------------------------------------------\n const wrapAsync = useCallback(\n <T,>(fn: () => Promise<T>) =>\n async (): Promise<T> => {\n setIsProcessing(true);\n setError(null);\n try {\n const r = await fn();\n return r;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsProcessing(false);\n }\n },\n [],\n );\n\n const pay = useCallback(\n async (opts: PayOptions): Promise<PayResult> => {\n setIsProcessing(true);\n setError(null);\n try {\n const r = await client.payment.pay(opts);\n setResult(r);\n return r;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsProcessing(false);\n }\n },\n [client],\n );\n\n const tokenizeCard = useCallback(\n (card: { cardNumber: string; expiryDate: string; cvc: string; cardholderName?: string }) =>\n client.payment.tokenizeCard(card),\n [client],\n );\n\n const processApplePay = useCallback(\n async (opts: { checkoutSessionId: string; applePayToken: unknown }) => {\n const fn = wrapAsync(() => client.payment.processApplePay(opts));\n const r = await fn();\n setResult(r);\n return r;\n },\n [client, wrapAsync],\n );\n\n const processGooglePay = useCallback(\n async (opts: { checkoutSessionId: string; googlePayToken: string }) => {\n const fn = wrapAsync(() => client.payment.processGooglePay(opts));\n const r = await fn();\n setResult(r);\n return r;\n },\n [client, wrapAsync],\n );\n\n const processApm = useCallback(\n async (opts: { checkoutSessionId: string; paymentMethod: string; processorId: string }) => {\n const fn = wrapAsync(() => client.payment.processApm(opts));\n const r = await fn();\n setResult(r);\n return r;\n },\n [client, wrapAsync],\n );\n\n const pollStatus = useCallback(\n (paymentId: string) => client.payment.pollPaymentStatus(paymentId),\n [client],\n );\n\n return {\n paymentSetup,\n expressMethods,\n storeConfig,\n isProcessing,\n result,\n error,\n loadPaymentSetup,\n processPayment,\n pay,\n tokenizeCard,\n processApplePay,\n processGooglePay,\n processApm,\n pollStatus,\n };\n}\n", "import { useState, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { Offer, OfferPreview, OfferPayResult } from '../../core/types.js';\n\nexport interface UseOffersReturn {\n /** Current loaded offer. */\n offer: Offer | null;\n /** Current preview (pricing breakdown). */\n preview: OfferPreview | null;\n /** Whether an operation is in progress. */\n isLoading: boolean;\n /** Last error. */\n error: Error | null;\n\n /** Get a single offer by ID. */\n getOffer: (offerId: string) => Promise<Offer>;\n /** List offers for the store, optionally filtered by type or IDs. */\n listOffers: (opts?: { type?: 'upsell' | 'orderbump'; ids?: string[] }) => Promise<Offer[]>;\n /** Preview offer pricing (line items with amounts). */\n previewOffer: (opts: {\n offerId: string;\n currency?: string;\n lineItems?: Array<{ variantId: string; quantity: number }>;\n }) => Promise<OfferPreview>;\n /** Pay a previewed offer (one-click upsell charge using stored instrument). */\n payPreviewedOffer: (opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }) => Promise<OfferPayResult>;\n\n /** Toggle an order bump on/off within a checkout session. */\n toggleOrderBump: (opts: {\n checkoutSessionId: string;\n orderBumpOfferId: string;\n selected: boolean;\n }) => Promise<unknown>;\n\n /** List post-purchase offers for an order. */\n listPostPurchaseOffers: (orderId: string) => Promise<Offer[]>;\n /** Accept a post-purchase offer. */\n acceptPostPurchaseOffer: (opts: {\n orderId: string;\n offerId: string;\n items?: Array<{ variantId: string; quantity: number }>;\n }) => Promise<{ success: boolean; error?: string }>;\n /** Decline a post-purchase offer. */\n declinePostPurchaseOffer: (opts: {\n orderId: string;\n offerId: string;\n }) => Promise<{ success: boolean; error?: string }>;\n}\n\n/**\n * React hook for offers \u2014 upsells, order bumps, and post-purchase offers.\n *\n * @example\n * ```tsx\n * const { getOffer, previewOffer, payPreviewedOffer, listPostPurchaseOffers } = useOffers();\n *\n * // Preview an upsell offer\n * const preview = await previewOffer({ offerId: 'offer_xxx' });\n *\n * // One-click pay (reuses stored instrument from main order)\n * await payPreviewedOffer({ offerId: 'offer_xxx', mainOrderId: 'order_yyy' });\n *\n * // Or list post-purchase offers\n * const ppOffers = await listPostPurchaseOffers('order_yyy');\n * ```\n */\nexport function useOffers(): UseOffersReturn {\n const client = useHeadlessClient();\n const [offer, setOffer] = useState<Offer | null>(null);\n const [preview, setPreview] = useState<OfferPreview | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const getOffer = useCallback(\n (offerId: string) =>\n wrap(async () => {\n const o = await client.offers.getOffer(offerId);\n setOffer(o);\n return o;\n }),\n [client, wrap],\n );\n\n const listOffers = useCallback(\n (opts?: { type?: 'upsell' | 'orderbump'; ids?: string[] }) =>\n client.offers.listOffers(opts),\n [client],\n );\n\n const previewOffer = useCallback(\n (opts: { offerId: string; currency?: string; lineItems?: Array<{ variantId: string; quantity: number }> }) =>\n wrap(async () => {\n const p = await client.offers.previewOffer(opts);\n setPreview(p);\n return p;\n }),\n [client, wrap],\n );\n\n const payPreviewedOffer = useCallback(\n (opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }) => wrap(() => client.offers.payPreviewedOffer(opts)),\n [client, wrap],\n );\n\n const toggleOrderBump = useCallback(\n (opts: { checkoutSessionId: string; orderBumpOfferId: string; selected: boolean }) =>\n client.offers.toggleOrderBump(opts),\n [client],\n );\n\n const listPostPurchaseOffers = useCallback(\n (orderId: string) => client.offers.listPostPurchaseOffers(orderId),\n [client],\n );\n\n const acceptPostPurchaseOffer = useCallback(\n (opts: { orderId: string; offerId: string; items?: Array<{ variantId: string; quantity: number }> }) =>\n wrap(() => client.offers.acceptPostPurchaseOffer(opts)),\n [client, wrap],\n );\n\n const declinePostPurchaseOffer = useCallback(\n (opts: { orderId: string; offerId: string }) =>\n wrap(() => client.offers.declinePostPurchaseOffer(opts)),\n [client, wrap],\n );\n\n return {\n offer,\n preview,\n isLoading,\n error,\n getOffer,\n listOffers,\n previewOffer,\n payPreviewedOffer,\n toggleOrderBump,\n listPostPurchaseOffers,\n acceptPostPurchaseOffer,\n declinePostPurchaseOffer,\n };\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { Customer, Order, Subscription } from '../../core/types.js';\n\nexport interface UseCustomerReturn {\n customer: Customer | null;\n orders: Order[];\n subscriptions: Subscription[];\n isLoading: boolean;\n error: Error | null;\n /** Load customer profile by ID. */\n loadCustomer: (customerId: string) => Promise<void>;\n /** Load customer orders. */\n loadOrders: (customerId: string) => Promise<void>;\n /** Load customer subscriptions. */\n loadSubscriptions: (customerId: string) => Promise<void>;\n /** Update customer profile. */\n updateProfile: (customerId: string, data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone'>>) => Promise<void>;\n}\n\n/**\n * React hook for customer data -- profile, orders, subscriptions.\n *\n * @param customerId - Auto-loads the customer profile when provided.\n *\n * @example\n * ```tsx\n * const { customer, orders, loadOrders } = useCustomer(session?.customer?.id);\n * ```\n */\nexport function useCustomer(customerId?: string | null): UseCustomerReturn {\n const client = useHeadlessClient();\n const [customer, setCustomer] = useState<Customer | null>(null);\n const [orders, setOrders] = useState<Order[]>([]);\n const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const loadCustomer = useCallback(async (id: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const c = await client.customer.getProfile(id);\n setCustomer(c);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n const loadOrders = useCallback(async (id: string) => {\n try {\n const res = await client.customer.getOrders(id);\n setOrders(res.orders);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n const loadSubscriptions = useCallback(async (id: string) => {\n try {\n const subs = await client.customer.getSubscriptions(id);\n setSubscriptions(subs);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n const updateProfile = useCallback(async (\n id: string,\n data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone'>>,\n ) => {\n try {\n const updated = await client.customer.updateProfile(id, data);\n setCustomer(updated);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n useEffect(() => {\n if (customerId) loadCustomer(customerId);\n }, [customerId, loadCustomer]);\n\n return {\n customer,\n orders,\n subscriptions,\n isLoading,\n error,\n loadCustomer,\n loadOrders,\n loadSubscriptions,\n updateProfile,\n };\n}\n", "import { useState, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { CatalogProduct } from '../../core/types.js';\n\nexport interface UseCatalogReturn {\n products: CatalogProduct[];\n isLoading: boolean;\n error: Error | null;\n /** Fetch all products for the store. */\n loadProducts: (opts?: { productIds?: string[]; variantIds?: string[] }) => Promise<CatalogProduct[]>;\n /** Fetch a single product by ID. */\n loadProduct: (productId: string) => Promise<CatalogProduct | null>;\n}\n\n/**\n * React hook for browsing the store's product catalog.\n *\n * @example\n * ```tsx\n * const { products, isLoading, loadProducts } = useCatalog();\n *\n * useEffect(() => { loadProducts(); }, []);\n * ```\n */\nexport function useCatalog(): UseCatalogReturn {\n const client = useHeadlessClient();\n const [products, setProducts] = useState<CatalogProduct[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const loadProducts = useCallback(async (opts?: { productIds?: string[]; variantIds?: string[] }) => {\n setIsLoading(true);\n setError(null);\n try {\n const items = await client.catalog.getProducts(opts);\n setProducts(items);\n return items;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n const loadProduct = useCallback(async (productId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n return await client.catalog.getProduct(productId);\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n return {\n products,\n isLoading,\n error,\n loadProducts,\n loadProduct,\n };\n}\n", "/**\n * React hook for Google Places Autocomplete \u2014 handles script injection,\n * debounced prediction search, place detail fetching, and address extraction.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n GoogleAutocompleteCore,\n loadGoogleMapsScript,\n type GooglePrediction,\n type GooglePlaceDetails,\n type ExtractedAddress,\n type FormattedAddress,\n} from '../../core/helpers/autocomplete.js';\n\nexport type { GooglePrediction, GooglePlaceDetails, ExtractedAddress, FormattedAddress };\n\nexport interface UseGoogleAutocompleteOptions {\n apiKey: string;\n language?: string;\n region?: string;\n version?: string;\n /** Defer script loading until searchPlaces() is first called. Default: false. */\n defer?: boolean;\n}\n\nexport interface UseGoogleAutocompleteReturn {\n predictions: GooglePrediction[];\n isLoading: boolean;\n isScriptLoaded: boolean;\n searchPlaces: (input: string, countryRestriction?: string) => void;\n getPlaceDetails: (placeId: string) => Promise<GooglePlaceDetails | null>;\n extractAddressComponents: (place: GooglePlaceDetails) => ExtractedAddress;\n extractFormattedAddress: (place: GooglePlaceDetails) => FormattedAddress;\n clearPredictions: () => void;\n}\n\nexport function useGoogleAutocomplete(options: UseGoogleAutocompleteOptions): UseGoogleAutocompleteReturn {\n const { apiKey, language, region, version, defer = false } = options;\n\n const [predictions, setPredictions] = useState<GooglePrediction[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [isScriptLoaded, setIsScriptLoaded] = useState(false);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingRef = useRef<{ input: string; country?: string } | null>(null);\n\n const inject = useCallback(() => {\n loadGoogleMapsScript(apiKey, { language, region, version }).then(() => setIsScriptLoaded(true));\n }, [apiKey, language, region, version]);\n\n // Eager load unless defer\n useEffect(() => {\n if (!apiKey || defer) return;\n inject();\n }, [apiKey, defer, inject]);\n\n // Replay pending search after deferred load\n useEffect(() => {\n if (isScriptLoaded && pendingRef.current) {\n const { input, country } = pendingRef.current;\n pendingRef.current = null;\n doSearch(input, country);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isScriptLoaded]);\n\n const doSearch = useCallback(\n (input: string, countryRestriction?: string) => {\n if (!isScriptLoaded) {\n if (defer) { pendingRef.current = { input, country: countryRestriction }; inject(); }\n return;\n }\n\n if (input.length < 3) { setPredictions([]); return; }\n\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(async () => {\n setIsLoading(true);\n const results = await GoogleAutocompleteCore.searchPlaces(input, {\n componentRestrictions: countryRestriction ? { country: countryRestriction.toLowerCase() } : undefined,\n });\n setPredictions(results);\n setIsLoading(false);\n }, 300);\n },\n [isScriptLoaded, defer, inject],\n );\n\n const getPlaceDetails = useCallback(\n (placeId: string) => GoogleAutocompleteCore.getPlaceDetails(placeId),\n [],\n );\n\n const extractAddressComponents = useCallback(\n (place: GooglePlaceDetails) => GoogleAutocompleteCore.extractAddressComponents(place),\n [],\n );\n\n const extractFormattedAddress = useCallback(\n (place: GooglePlaceDetails) => GoogleAutocompleteCore.extractFormattedAddress(place),\n [],\n );\n\n const clearPredictions = useCallback(() => setPredictions([]), []);\n\n return {\n predictions,\n isLoading,\n isScriptLoaded,\n searchPlaces: doSearch,\n getPlaceDetails,\n extractAddressComponents,\n extractFormattedAddress,\n clearPredictions,\n };\n}\n", "/**\n * Google Places Autocomplete \u2014 script injection + address extraction.\n * Works standalone (no external dependencies beyond the Google Maps JS API).\n */\n\ndeclare global {\n interface Window {\n google?: {\n maps?: {\n places?: {\n AutocompleteService: new () => any;\n PlacesService: new (el: any) => any;\n PlacesServiceStatus: { OK: string; ZERO_RESULTS: string };\n };\n Map: new (el: HTMLElement) => any;\n };\n };\n }\n}\n\nexport interface GooglePrediction {\n place_id: string;\n description: string;\n structured_formatting?: { main_text: string; secondary_text: string };\n}\n\nexport interface GooglePlaceDetails {\n place_id: string;\n formatted_address: string;\n address_components: Array<{ long_name: string; short_name: string; types: string[] }>;\n geometry?: { location: { lat: number; lng: number } };\n}\n\nexport interface ExtractedAddress {\n subpremise: string;\n streetNumber: string;\n route: string;\n locality: string;\n administrativeAreaLevel1: string;\n administrativeAreaLevel1Long: string;\n administrativeAreaLevel2: string;\n administrativeAreaLevel2Long: string;\n country: string;\n postalCode: string;\n fullStreetAddress: string;\n}\n\nexport interface FormattedAddress {\n address1: string;\n city: string;\n country: string;\n state: string;\n postal: string;\n}\n\n// ---------------------------------------------------------------------------\n// Script injection\n// ---------------------------------------------------------------------------\n\nlet scriptInjected = false;\nlet scriptReady = false;\nconst readyCallbacks: Array<() => void> = [];\n\nfunction onScriptReady() {\n scriptReady = true;\n for (const cb of readyCallbacks) cb();\n readyCallbacks.length = 0;\n}\n\n/**\n * Inject the Google Maps JS SDK into the page (idempotent).\n * Resolves once `window.google.maps.places` is available.\n */\nexport function loadGoogleMapsScript(\n apiKey: string,\n opts: { language?: string; region?: string; version?: string } = {},\n): Promise<void> {\n if (scriptReady || window.google?.maps?.places) {\n onScriptReady();\n return Promise.resolve();\n }\n\n if (scriptInjected) {\n return new Promise<void>((resolve) => readyCallbacks.push(resolve));\n }\n\n scriptInjected = true;\n\n return new Promise<void>((resolve, reject) => {\n readyCallbacks.push(resolve);\n\n const existing = document.querySelector('script[src*=\"maps.googleapis.com\"]');\n if (existing) {\n const poll = () => {\n if (window.google?.maps?.places) { onScriptReady(); }\n else { setTimeout(poll, 100); }\n };\n poll();\n return;\n }\n\n const params = new URLSearchParams({\n key: apiKey,\n libraries: 'places',\n v: opts.version ?? 'weekly',\n });\n if (opts.language) params.set('language', opts.language);\n if (opts.region) params.set('region', opts.region);\n\n const script = document.createElement('script');\n script.src = `https://maps.googleapis.com/maps/api/js?${params}`;\n script.async = true;\n script.defer = true;\n script.onload = () => onScriptReady();\n script.onerror = () => reject(new Error('Failed to load Google Maps script'));\n document.head.appendChild(script);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Core class\n// ---------------------------------------------------------------------------\n\nexport class GoogleAutocompleteCore {\n /** Search for address predictions. */\n static async searchPlaces(\n input: string,\n options: { types?: string[]; componentRestrictions?: { country: string } } = {},\n ): Promise<GooglePrediction[]> {\n if (!window.google?.maps?.places || !input.trim()) return [];\n\n const service = new window.google.maps.places.AutocompleteService();\n return new Promise((resolve) => {\n service.getPlacePredictions(\n { input, types: options.types ?? ['address'], componentRestrictions: options.componentRestrictions },\n (predictions: GooglePrediction[] | null, status: string) => {\n resolve(status === window.google?.maps?.places?.PlacesServiceStatus.OK && predictions ? predictions : []);\n },\n );\n });\n }\n\n /** Get full place details by place_id. */\n static async getPlaceDetails(placeId: string): Promise<GooglePlaceDetails | null> {\n if (!window.google?.maps?.places) return null;\n\n const svc = new window.google.maps.places.PlacesService(document.createElement('div'));\n return new Promise((resolve) => {\n svc.getDetails(\n { placeId, fields: ['place_id', 'formatted_address', 'address_components', 'geometry'] },\n (place: GooglePlaceDetails | null, status: string) => {\n resolve(status === window.google?.maps?.places?.PlacesServiceStatus.OK && place ? place : null);\n },\n );\n });\n }\n\n /** Extract structured address fields from a Google PlaceDetails result. */\n static extractAddressComponents(place: GooglePlaceDetails): ExtractedAddress {\n const out: ExtractedAddress = {\n subpremise: '', streetNumber: '', route: '', locality: '',\n administrativeAreaLevel1: '', administrativeAreaLevel1Long: '',\n administrativeAreaLevel2: '', administrativeAreaLevel2Long: '',\n country: '', postalCode: '', fullStreetAddress: '',\n };\n\n let premise = '';\n let neighborhood = '';\n let sublocality5 = '', sublocality4 = '', sublocality3 = '', sublocality2 = '', sublocality1 = '';\n let postalTown = '';\n\n for (const c of place.address_components ?? []) {\n const t = c.types;\n if (t.includes('subpremise')) out.subpremise = c.long_name;\n if (t.includes('street_number')) out.streetNumber = c.long_name;\n if (t.includes('premise')) premise = c.long_name;\n if (t.includes('route')) out.route = c.long_name;\n if (t.includes('neighborhood')) neighborhood = c.long_name;\n if (t.includes('sublocality_level_5')) sublocality5 = c.long_name;\n if (t.includes('sublocality_level_4')) sublocality4 = c.long_name;\n if (t.includes('sublocality_level_3')) sublocality3 = c.long_name;\n if (t.includes('sublocality_level_2')) sublocality2 = c.long_name;\n if (t.includes('sublocality_level_1')) sublocality1 = c.long_name;\n if (t.includes('locality')) out.locality = c.long_name;\n if (t.includes('postal_town')) postalTown = c.long_name;\n if (t.includes('administrative_area_level_2')) {\n out.administrativeAreaLevel2 = c.short_name;\n out.administrativeAreaLevel2Long = c.long_name;\n }\n if (t.includes('administrative_area_level_1')) {\n out.administrativeAreaLevel1 = c.short_name;\n out.administrativeAreaLevel1Long = c.long_name;\n }\n if (t.includes('country')) out.country = c.short_name;\n if (t.includes('postal_code')) out.postalCode = c.long_name;\n }\n\n // Locality fallbacks (UK postal_town, Asian sublocalities)\n if (!out.locality) out.locality = postalTown || sublocality2 || sublocality1 || '';\n\n // French-style fallback: use d\u00E9partement when r\u00E9gion is missing\n if (!out.administrativeAreaLevel1 && out.administrativeAreaLevel2) {\n out.administrativeAreaLevel1 = out.administrativeAreaLevel2Long || out.administrativeAreaLevel2;\n out.administrativeAreaLevel1Long = out.administrativeAreaLevel2Long;\n }\n\n // Build full street address\n const buildingNumber = out.streetNumber || premise;\n const streetName = out.route || sublocality5 || sublocality4 || sublocality3 || neighborhood;\n\n if (out.subpremise && buildingNumber && streetName) {\n out.fullStreetAddress = `${out.subpremise}/${buildingNumber} ${streetName}`;\n } else if (buildingNumber && streetName) {\n if (premise && sublocality4 && sublocality3) {\n let addr = `${sublocality3}-${sublocality4}-${premise}`;\n if (sublocality2) addr = `${addr} ${sublocality2}`;\n out.fullStreetAddress = addr;\n } else {\n out.fullStreetAddress = `${buildingNumber} ${streetName}`;\n }\n } else if (streetName) {\n out.fullStreetAddress = streetName;\n } else if (buildingNumber) {\n out.fullStreetAddress = buildingNumber;\n }\n\n out.fullStreetAddress = out.fullStreetAddress.trim();\n return out;\n }\n\n /** Shorthand: extract into the flat shape used by address forms. */\n static extractFormattedAddress(place: GooglePlaceDetails): FormattedAddress {\n const a = GoogleAutocompleteCore.extractAddressComponents(place);\n return {\n address1: a.fullStreetAddress,\n city: a.locality,\n country: a.country,\n state: a.administrativeAreaLevel1,\n postal: a.postalCode,\n };\n }\n}\n", "/**\n * React hooks for ISO country/region data \u2014 CDN-backed,\n * with Google Places \u2192 ISO region mapping.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n ISODataCore,\n type ISOCountry,\n type ISORegion,\n type SupportedLanguage,\n} from '../../core/helpers/countries.js';\nimport { ensureGeoDataLoaded, isLanguageLoaded } from '../../core/helpers/iso3166.js';\n\nexport type { ISOCountry, ISORegion, SupportedLanguage };\n\n// ---------------------------------------------------------------------------\n// useISOData \u2014 full access to countries, regions, and Google\u2192ISO mapping\n// ---------------------------------------------------------------------------\n\nexport interface UseISODataReturn {\n countries: Record<string, ISOCountry>;\n getRegions: (countryCode: string) => ISORegion[];\n findRegion: (countryCode: string, regionCode: string) => ISORegion | null;\n mapGoogleToISO: (googleState: string, googleStateLong: string, countryCode: string) => ISORegion | null;\n isLoaded: boolean;\n}\n\nexport function useISOData(language: SupportedLanguage = 'en'): UseISODataReturn {\n const [isLoaded, setIsLoaded] = useState(isLanguageLoaded(language));\n\n useEffect(() => {\n let cancelled = false;\n ensureGeoDataLoaded(language)\n .then(() => { if (!cancelled) setIsLoaded(true); })\n .catch((err) => console.error('[headless-sdk] Failed to load geodata:', err));\n return () => { cancelled = true; };\n }, [language]);\n\n return useMemo(() => {\n if (!isLoaded) {\n return {\n countries: {},\n getRegions: () => [],\n findRegion: () => null,\n mapGoogleToISO: () => null,\n isLoaded: false,\n };\n }\n\n return {\n countries: ISODataCore.getCountries(language),\n getRegions: (cc: string) => ISODataCore.getRegions(cc, language),\n findRegion: (cc: string, rc: string) => ISODataCore.findRegion(cc, rc, language),\n mapGoogleToISO: (gs: string, gsl: string, cc: string) => ISODataCore.mapGoogleToISO(gs, gsl, cc, language),\n isLoaded: true,\n };\n }, [language, isLoaded]);\n}\n\n// ---------------------------------------------------------------------------\n// useCountryOptions \u2014 countries as select options\n// ---------------------------------------------------------------------------\n\nexport function useCountryOptions(language: SupportedLanguage = 'en'): Array<{ value: string; label: string }> {\n const { countries, isLoaded } = useISOData(language);\n return useMemo(() => {\n if (!isLoaded) return [];\n return Object.values(countries)\n .map((c) => ({ value: c.iso, label: c.name }))\n .sort((a, b) => a.label.localeCompare(b.label));\n }, [countries, isLoaded]);\n}\n\n// ---------------------------------------------------------------------------\n// useRegionOptions \u2014 regions/states for a country as select options\n// ---------------------------------------------------------------------------\n\nexport function useRegionOptions(\n countryCode: string,\n language: SupportedLanguage = 'en',\n): Array<{ value: string; label: string }> {\n const { getRegions, isLoaded } = useISOData(language);\n return useMemo(() => {\n if (!isLoaded || !countryCode) return [];\n return getRegions(countryCode)\n .map((r) => ({ value: r.iso, label: r.name }))\n .sort((a, b) => a.label.localeCompare(b.label));\n }, [countryCode, getRegions, isLoaded]);\n}\n", "/**\n * Geodata \u2014 CDN-backed country/region data.\n *\n * Fetches slim JSON from Vercel Blob CDN on demand:\n * - countries.json (~10KB) \u2014 fetched once on first getCountries() call\n * - regions.json (~95KB) \u2014 fetched lazily on first getStatesForCountry() call\n *\n * Both are cached in memory after first fetch.\n */\n\nconst GEODATA_CDN_BASE = 'https://cvwnizdbugpz6jwk.public.blob.vercel-storage.com/geodata/v1';\n\nexport const AVAILABLE_LANGUAGES = ['en', 'ru', 'de', 'da', 'fr', 'es', 'zh', 'hi', 'pt', 'ja', 'ar', 'it', 'he'] as const;\nexport type SupportedLanguage = (typeof AVAILABLE_LANGUAGES)[number];\n\nexport interface Country {\n code: string;\n name: string;\n iso3?: string;\n numeric?: number;\n}\n\nexport interface State {\n code: string;\n name: string;\n countryCode: string;\n}\n\ninterface CdnCountries { [iso2: string]: { n: string; i3?: string; nu?: number } }\ninterface CdnRegions { [iso2: string]: [string, string][] }\n\nconst countriesCache = new Map<SupportedLanguage, CdnCountries>();\nconst regionsCache = new Map<SupportedLanguage, CdnRegions>();\nconst inflightCountries = new Map<SupportedLanguage, Promise<CdnCountries>>();\nconst inflightRegions = new Map<SupportedLanguage, Promise<CdnRegions>>();\n\nasync function fetchCountriesRaw(language: SupportedLanguage): Promise<CdnCountries> {\n const cached = countriesCache.get(language);\n if (cached) return cached;\n\n let inflight = inflightCountries.get(language);\n if (inflight) return inflight;\n\n inflight = (async () => {\n const url = `${GEODATA_CDN_BASE}/${language}/countries.json`;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geodata fetch failed: ${url} (${res.status})`);\n const data: CdnCountries = await res.json();\n countriesCache.set(language, data);\n inflightCountries.delete(language);\n return data;\n })();\n\n inflightCountries.set(language, inflight);\n return inflight;\n}\n\nasync function fetchRegionsRaw(language: SupportedLanguage): Promise<CdnRegions> {\n const cached = regionsCache.get(language);\n if (cached) return cached;\n\n let inflight = inflightRegions.get(language);\n if (inflight) return inflight;\n\n inflight = (async () => {\n const url = `${GEODATA_CDN_BASE}/${language}/regions.json`;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geodata fetch failed: ${url} (${res.status})`);\n const data: CdnRegions = await res.json();\n regionsCache.set(language, data);\n inflightRegions.delete(language);\n return data;\n })();\n\n inflightRegions.set(language, inflight);\n return inflight;\n}\n\nfunction getCountriesCached(language: SupportedLanguage): CdnCountries {\n return countriesCache.get(language) || countriesCache.get('en') || {};\n}\n\nfunction getRegionsCached(language: SupportedLanguage): CdnRegions {\n return regionsCache.get(language) || regionsCache.get('en') || {};\n}\n\n/** Fetch countries + regions from CDN for a language. Call before sync getters. */\nexport async function ensureGeoDataLoaded(language: SupportedLanguage = 'en'): Promise<void> {\n await Promise.all([fetchCountriesRaw(language), fetchRegionsRaw(language)]);\n}\n\nexport const getCountries = (language: SupportedLanguage = 'en'): Country[] => {\n const raw = getCountriesCached(language);\n return Object.entries(raw)\n .map(([code, c]) => ({ code, name: c.n, iso3: c.i3, numeric: c.nu }))\n .sort((a, b) => a.name.localeCompare(b.name));\n};\n\nexport const getStatesForCountry = (countryCode: string, language: SupportedLanguage = 'en'): State[] => {\n const raw = getRegionsCached(language);\n const tuples = raw[countryCode];\n if (!tuples) return [];\n return tuples\n .map(([iso, name]) => ({ code: iso, name, countryCode }))\n .sort((a, b) => a.name.localeCompare(b.name));\n};\n\nexport function isLanguageLoaded(language: SupportedLanguage): boolean {\n return countriesCache.has(language);\n}\n", "/**\n * ISO country/region helpers \u2014 countries list, regions by country,\n * and Google Places state \u2192 ISO region mapping.\n */\n\nimport {\n getCountries,\n getStatesForCountry,\n ensureGeoDataLoaded,\n isLanguageLoaded,\n AVAILABLE_LANGUAGES,\n type SupportedLanguage,\n type Country,\n type State,\n} from './iso3166.js';\n\nexport type { SupportedLanguage, Country, State };\nexport { AVAILABLE_LANGUAGES };\n\nexport interface ISOCountry {\n iso: string;\n iso3: string;\n numeric: number;\n name: string;\n}\n\nexport interface ISORegion {\n iso: string;\n name: string;\n}\n\nexport class ISODataCore {\n /** Fetch countries + regions from CDN for a language. Call before sync getters. */\n static ensureLoaded(language: SupportedLanguage = 'en'): Promise<void> {\n return ensureGeoDataLoaded(language);\n }\n\n /** Get all countries as a Record keyed by ISO code. */\n static getCountries(language: SupportedLanguage = 'en'): Record<string, ISOCountry> {\n const arr = getCountries(language);\n const result: Record<string, ISOCountry> = {};\n for (const c of arr) {\n result[c.code] = { iso: c.code, iso3: c.iso3 ?? '', numeric: c.numeric ?? 0, name: c.name };\n }\n return result;\n }\n\n /** Get all countries as a sorted array of { value, label } for select inputs. */\n static getCountryOptions(language: SupportedLanguage = 'en'): Array<{ value: string; label: string }> {\n return getCountries(language).map((c) => ({ value: c.code, label: c.name }));\n }\n\n /** Get regions/states for a country. */\n static getRegions(countryCode: string, language: SupportedLanguage = 'en'): ISORegion[] {\n return getStatesForCountry(countryCode, language).map((s) => ({ iso: s.code, name: s.name }));\n }\n\n /** Get regions as a sorted array of { value, label } for select inputs. */\n static getRegionOptions(countryCode: string, language: SupportedLanguage = 'en'): Array<{ value: string; label: string }> {\n return ISODataCore.getRegions(countryCode, language).map((r) => ({ value: r.iso, label: r.name }));\n }\n\n /** Find a specific region by ISO code. */\n static findRegion(countryCode: string, regionCode: string, language: SupportedLanguage = 'en'): ISORegion | null {\n return ISODataCore.getRegions(countryCode, language).find((r) => r.iso === regionCode) ?? null;\n }\n\n /**\n * Map a Google Places administrative_area to an ISO region.\n * Tries exact ISO match, then name match, then partial match.\n */\n static mapGoogleToISO(\n googleState: string,\n googleStateLong: string,\n countryCode: string,\n language: SupportedLanguage = 'en',\n ): ISORegion | null {\n const regions = ISODataCore.getRegions(countryCode, language);\n if (regions.length === 0) return null;\n\n let match = regions.find((r) => r.iso === googleState);\n if (match) return match;\n\n match = regions.find((r) => r.name.toLowerCase() === googleState.toLowerCase());\n if (match) return match;\n\n match = regions.find((r) => r.name.toLowerCase() === googleStateLong.toLowerCase());\n if (match) return match;\n\n match = regions.find(\n (r) =>\n r.name.toLowerCase().includes(googleStateLong.toLowerCase()) ||\n googleStateLong.toLowerCase().includes(r.name.toLowerCase()),\n );\n\n return match ?? null;\n }\n\n static isLanguageLoaded(language: SupportedLanguage): boolean {\n return isLanguageLoaded(language);\n }\n\n static getAvailableLanguages(): readonly SupportedLanguage[] {\n return AVAILABLE_LANGUAGES;\n }\n}\n", "/**\n * Currency formatting utilities \u2014 symbol lookup, decimal handling,\n * and Intl.NumberFormat-based money formatting from minor units (cents).\n */\n\nexport interface Currency {\n code: string;\n symbol: string;\n name: string;\n decimalPlaces: number;\n}\n\nconst SYMBOLS: Record<string, string> = {\n USD: '$', EUR: '\u20AC', GBP: '\u00A3', JPY: '\u00A5', CAD: 'C$', AUD: 'A$', CHF: 'CHF',\n CNY: '\u00A5', SEK: 'kr', NOK: 'kr', DKK: 'kr', PLN: 'z\u0142', CZK: 'K\u010D', HUF: 'Ft',\n RON: 'lei', BGN: '\u043B\u0432', HRK: 'kn', RUB: '\u20BD', UAH: '\u20B4', TRY: '\u20BA', BRL: 'R$',\n MXN: '$', ZAR: 'R', INR: '\u20B9', KRW: '\u20A9', THB: '\u0E3F', VND: '\u20AB', IDR: 'Rp',\n MYR: 'RM', SGD: 'S$', PHP: '\u20B1', TWD: 'NT$', HKD: 'HK$', ILS: '\u20AA', AED: '\u062F.\u0625',\n SAR: '\u0631.\u0633', QAR: '\u0631.\u0642', KWD: '\u062F.\u0643', BHD: '\u062F.\u0628', OMR: '\u0631.\u0639.', EGP: '\u00A3',\n NGN: '\u20A6', KES: 'KSh', GHS: '\u20B5', COP: '$', ARS: '$', CLP: '$', PEN: 'S/',\n CRC: '\u20A1', DOP: 'RD$', JMD: 'J$', BOB: 'Bs', PYG: '\u20B2', GTQ: 'Q',\n NIO: 'C$', PAB: 'B/.', PKR: '\u20A8', BDT: '\u09F3', LKR: '\u20A8', NPR: '\u20A8',\n GEL: '\u20BE', AMD: '\u058F', AZN: '\u20BC', KZT: '\u20B8',\n};\n\nconst NAMES: Record<string, string> = {\n USD: 'US Dollar', EUR: 'Euro', GBP: 'British Pound', JPY: 'Japanese Yen',\n CAD: 'Canadian Dollar', AUD: 'Australian Dollar', CHF: 'Swiss Franc',\n CNY: 'Chinese Yuan', SEK: 'Swedish Krona', NOK: 'Norwegian Krone',\n DKK: 'Danish Krone', PLN: 'Polish Zloty', CZK: 'Czech Koruna', HUF: 'Hungarian Forint',\n BRL: 'Brazilian Real', MXN: 'Mexican Peso', INR: 'Indian Rupee', KRW: 'South Korean Won',\n THB: 'Thai Baht', SGD: 'Singapore Dollar', HKD: 'Hong Kong Dollar', TWD: 'Taiwan Dollar',\n ILS: 'Israeli Shekel', AED: 'UAE Dirham', SAR: 'Saudi Riyal', ZAR: 'South African Rand',\n TRY: 'Turkish Lira', RUB: 'Russian Ruble', NGN: 'Nigerian Naira',\n};\n\nconst ZERO_DECIMAL: Set<string> = new Set([\n 'JPY', 'KRW', 'VND', 'IDR', 'LAK', 'KHR', 'MMK', 'PYG',\n]);\n\nexport class CurrencyUtils {\n static getSymbol(code: string): string {\n return SYMBOLS[code] ?? code;\n }\n\n static getName(code: string): string {\n return NAMES[code] ?? code;\n }\n\n static getDecimalPlaces(code: string): number {\n return ZERO_DECIMAL.has(code) ? 0 : 2;\n }\n\n static getCurrency(code: string): Currency {\n return {\n code,\n symbol: CurrencyUtils.getSymbol(code),\n name: CurrencyUtils.getName(code),\n decimalPlaces: CurrencyUtils.getDecimalPlaces(code),\n };\n }\n}\n\n/**\n * Format an amount expressed in minor units (cents) into a locale-aware string.\n *\n * @example\n * formatMoney(12345, 'USD') // \"$123.45\"\n * formatMoney(10000, 'EUR', 'de-DE') // \"100,00 \u20AC\"\n * formatMoney(1000, 'JPY') // \"\u00A51,000\"\n */\nexport function formatMoney(amountMinorUnits: number, currencyCode = 'USD', locale = 'en-US'): string {\n const decimals = CurrencyUtils.getDecimalPlaces(currencyCode);\n const value = amountMinorUnits / (decimals === 0 ? 100 : Math.pow(10, decimals));\n\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(value);\n } catch {\n return `${CurrencyUtils.getSymbol(currencyCode)}${value.toFixed(decimals)}`;\n }\n}\n"],
5
- "mappings": ";;;;;u2BAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,mBAAAE,EAAA,2BAAAC,EAAA,gBAAAC,EAAA,2BAAAC,GAAA,gBAAAC,GAAA,yBAAAC,EAAA,eAAAC,GAAA,gBAAAC,GAAA,sBAAAC,GAAA,gBAAAC,GAAA,0BAAAC,GAAA,sBAAAC,EAAA,eAAAC,GAAA,cAAAC,GAAA,eAAAC,GAAA,qBAAAC,KCAA,IAAAC,EAA0D,WCCnD,IAAMC,EAAN,cAA0B,KAAM,CAKrC,YACEC,EACAC,EACAC,EACAC,EACA,CACA,MAAMH,CAAO,EACb,KAAK,KAAO,cACZ,KAAK,KAAOC,EACZ,KAAK,WAAaC,EAClB,KAAK,QAAUC,CACjB,CACF,EAGaC,GAAN,cAA8BL,CAAY,CAC/C,YAAYC,EAAU,+DAAgE,CACpF,MAAMA,EAAS,aAAc,GAAG,EAChC,KAAK,KAAO,iBACd,CACF,EAGaK,GAAN,cAAoCN,CAAY,CAGrD,YACEC,EACAM,EAAoD,CAAC,EACrD,CACA,MAAMN,EAAS,mBAAoB,IAAK,CAAE,OAAAM,CAAO,CAAC,EAClD,KAAK,KAAO,wBACZ,KAAK,OAASA,CAChB,CACF,EAGaC,GAAN,cAAkCR,CAAY,CACnD,YAAYS,EAAkBC,EAAY,CACxC,MAAM,GAAGD,CAAQ,KAAKC,CAAE,eAAgB,YAAa,GAAG,EACxD,KAAK,KAAO,qBACd,CACF,EAGaC,GAAN,cAAmCX,CAAY,CAGpD,YAAYY,EAAe,IAAM,CAC/B,MAAM,6BAA6BA,CAAY,MAAO,aAAc,GAAG,EACvE,KAAK,KAAO,uBACZ,KAAK,aAAeA,CACtB,CACF,EAmBO,IAAMC,EAAN,cAAiCC,CAAY,CAClD,YAAYC,EAAU,iDAAkD,CACtE,MAAMA,EAAS,eAAe,EAC9B,KAAK,KAAO,oBACd,CACF,ECzEA,IAAMC,GAAyC,CAC7C,WAAY,wBACZ,YAAa,yBACb,MAAO,uBACT,EAaaC,EAAN,KAAiB,CAMtB,YAAYC,EAA0B,CACpC,KAAK,QAAUA,EAAO,QAAQ,QAAQ,MAAO,EAAE,EAC/C,KAAK,QAAUA,EAAO,QACtB,KAAK,OAASA,EAAO,OACrB,KAAK,SAAWA,EAAO,QACzB,CAEA,OAAO,eAAeC,EAA0BC,EAA2B,CACzE,OAAOA,GAAYJ,GAAUG,CAAW,GAAKH,GAAU,UACzD,CAEA,MAAM,QAAqBK,EAAcC,EAA8B,CAAC,EAAe,CA5CzF,IAAAC,EA6CI,GAAM,CAAE,OAAAC,EAAS,MAAO,KAAAC,EAAM,QAAAC,EAAU,CAAC,EAAG,OAAAC,EAAQ,MAAAC,EAAO,OAAAC,CAAO,EAAIP,EAElEQ,EAAM,GAAG,KAAK,OAAO,GAAGT,CAAI,GAChC,GAAIM,EAAQ,CACV,IAAMI,EAAK,IAAI,gBACf,OAAW,CAACC,EAAGC,CAAC,IAAK,OAAO,QAAQN,CAAM,EACpCM,IAAM,QAAWF,EAAG,IAAIC,EAAG,OAAOC,CAAC,CAAC,EAE1C,IAAMC,EAAMH,EAAG,SAAS,EACpBG,IAAKJ,GAAO,IAAII,CAAG,GACzB,CAEA,IAAMC,EAAqC,CACzC,eAAgB,mBAChB,GAAGT,CACL,EAEMU,EAAYR,GAAS,KAAK,UAAUL,EAAA,KAAK,WAAL,YAAAA,EAAA,YACtCa,IACFD,EAAW,aAAa,EAAIC,GAG9B,IAAMC,EAAa,IAAI,gBACjBC,EAAY,WAAW,IAAMD,EAAW,MAAM,EAAG,KAAK,OAAO,EAEnE,GAAI,CACF,IAAME,EAAM,MAAM,MAAMT,EAAK,CAC3B,OAAAN,EACA,QAASW,EACT,KAAMV,GAAQ,KAAO,KAAK,UAAUA,CAAI,EAAI,OAC5C,OAAQI,GAAUQ,EAAW,MAC/B,CAAC,EAID,GAFA,aAAaC,CAAS,EAElBC,EAAI,GAAI,CACV,IAAMC,EAAO,MAAMD,EAAI,KAAK,EAC5B,OAAOC,EAAQ,KAAK,MAAMA,CAAI,EAAW,CAAC,CAC5C,CAEA,YAAM,KAAK,oBAAoBD,EAAKlB,CAAI,EAClC,IAAIoB,EAAY,mBAAoB,UAAWF,EAAI,MAAM,CACjE,OAASG,EAAK,CAEZ,MADA,aAAaJ,CAAS,EAClBI,aAAeD,EAAmBC,EAClCA,aAAe,cAAgBA,EAAI,OAAS,aACxC,IAAIC,EAAmB,cAActB,CAAI,oBAAoB,KAAK,OAAO,KAAK,EAEhF,IAAIsB,EACRD,aAAe,MAAQA,EAAI,QAAU,yBACvC,CACF,CACF,CAEA,IAAiBrB,EAAcC,EAA0C,CACvE,OAAO,KAAK,QAAWD,EAAM,CAAE,GAAGC,EAAS,OAAQ,KAAM,CAAC,CAC5D,CAEA,KAAkBD,EAAcI,EAAgBH,EAA0C,CACxF,OAAO,KAAK,QAAWD,EAAM,CAAE,GAAGC,EAAS,OAAQ,OAAQ,KAAAG,CAAK,CAAC,CACnE,CAEA,MAAmBJ,EAAcI,EAAgBH,EAA0C,CACzF,OAAO,KAAK,QAAWD,EAAM,CAAE,GAAGC,EAAS,OAAQ,QAAS,KAAAG,CAAK,CAAC,CACpE,CAEA,IAAiBJ,EAAcI,EAAgBH,EAA0C,CACvF,OAAO,KAAK,QAAWD,EAAM,CAAE,GAAGC,EAAS,OAAQ,MAAO,KAAAG,CAAK,CAAC,CAClE,CAEA,OAAoBJ,EAAcC,EAA0C,CAC1E,OAAO,KAAK,QAAWD,EAAM,CAAE,GAAGC,EAAS,OAAQ,QAAS,CAAC,CAC/D,CAEA,MAAc,oBAAoBiB,EAAelB,EAA8B,CAC7E,IAAIuB,EAAkC,CAAC,EACvC,GAAI,CACFA,EAAU,MAAML,EAAI,KAAK,CAC3B,MAAQ,CAER,CAEA,IAAMM,EACHD,EAAO,SACPA,EAAO,OACR,mBAAmBL,EAAI,MAAM,IAAIA,EAAI,UAAU,OAAOlB,CAAI,GAE5D,OAAQkB,EAAI,OAAQ,CAClB,IAAK,KACL,IAAK,KACH,MAAM,IAAIO,GAAgBD,CAAG,EAC/B,IAAK,KACH,MAAM,IAAIE,GAAoB1B,EAAM,EAAE,EACxC,IAAK,KAAK,CACR,IAAM2B,EAAc,MAAM,QAAQJ,EAAO,MAAM,EAC1CA,EAAO,OACR,CAAC,EACL,MAAM,IAAIK,GAAsBJ,EAAKG,CAAW,CAClD,CACA,IAAK,KAAK,CACR,IAAME,EAAa,OAAOX,EAAI,QAAQ,IAAI,aAAa,GAAK,GAAG,EAAI,IACnE,MAAM,IAAIY,GAAqBD,CAAU,CAC3C,CACA,QACE,MAAM,IAAIT,EAAYI,EAAK,YAAaN,EAAI,OAAQK,CAAM,CAC9D,CACF,CACF,EC5GO,IAAMQ,GAAN,KAAqB,CAO1B,YACmBC,EACAC,EACAC,EACjB,CAHiB,UAAAF,EACA,aAAAC,EACA,mBAAAC,CAChB,CAcH,MAAM,YACJC,EACAC,EACAC,EAC0B,CAzE9B,IAAAC,EA0EQF,IACF,KAAK,aAAeA,GACpBE,EAAA,KAAK,gBAAL,MAAAA,EAAA,UAAqBF,IAGvB,IAAMG,EAAiC,CAAE,cAAe,OAAQ,EAC5DF,GAAA,MAAAA,EAAM,WACRE,EAAO,SAAWF,EAAK,UAGzB,IAAMG,EAAM,MAAM,KAAK,KAAK,IAC1B,6BAA6BL,CAAa,MAC1C,CACE,OAAAI,EACA,MAAO,KAAK,YACd,CACF,EAEA,OAAO,KAAK,iBAAiBC,CAAG,CAClC,CAQA,MAAM,cAAcH,EAOkF,CA5GxG,IAAAC,EA6GI,IAAMG,EAAYJ,EAAK,MAAM,IAAKK,IAAO,CACvC,UAAWA,EAAE,UACb,QAASA,EAAE,QACX,SAAUA,EAAE,QACd,EAAE,EAEIC,EAAgC,CACpC,QAAS,KAAK,QACd,UAAAF,CACF,EACIJ,EAAK,YAAWM,EAAK,UAAYN,EAAK,WAG1C,IAAMO,EAAwC,CAAC,EAC3CP,EAAK,WAAUO,EAAa,SAAWP,EAAK,UAC5CA,EAAK,gBACPO,EAAa,MAAQP,EAAK,cAC1BO,EAAa,UAAYP,EAAK,kBAC9BO,EAAa,SAAWP,EAAK,kBAE3B,OAAO,KAAKO,CAAY,EAAE,OAAS,IACrCD,EAAK,SAAWC,GAGlB,IAAMC,EAAM,MAAM,KAAK,KAAK,KAIzB,gCAAiCF,CAAI,EAGlCP,EADM,IAAI,IAAIS,EAAI,WAAW,EACV,aAAa,IAAI,OAAO,GAAK,GACtD,YAAK,aAAeT,EAChBA,KAAcE,EAAA,KAAK,gBAAL,MAAAA,EAAA,UAAqBF,IAEhC,CACL,YAAaS,EAAI,YACjB,cAAeA,EAAI,cACnB,aAAAT,EACA,WAAYS,EAAI,UAClB,CACF,CAcA,MAAM,WAAWC,EAAmBC,EAA8C,CAChF,OAAO,KAAK,KAAK,KACf,6BAA6BD,CAAS,cACtC,CAAE,MAAAC,CAAM,EACR,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAUA,MAAM,eACJD,EACAE,EACe,CACXA,EAAS,QAAO,KAAK,cAAgBA,EAAS,OAC9CA,EAAS,YAAW,KAAK,kBAAoBA,EAAS,WACtDA,EAAS,WAAU,KAAK,iBAAmBA,EAAS,UACpDA,EAAS,QAAO,KAAK,cAAgBA,EAAS,MACpD,CA0BA,MAAM,cACJF,EACAG,EACe,CACf,IAAMC,EAAW,KAAK,WAAWD,EAAU,eAAe,EACpDE,EAAU,KAAK,WAAWF,EAAU,cAAc,EAElDG,EAAoBF,GAAYC,GAAW,CAAC,EAC5CE,EAAmBF,GAAWD,EAC9BI,EAAmB,CAAC,EAAEL,EAAU,gBAAkBA,EAAU,iBAElE,MAAM,KAAK,KAAK,KACd,6BAA6BH,CAAS,6BACtC,CACE,kBAAmBA,EACnB,aAAc,CACZ,MAAO,KAAK,aACd,EACA,gBAAiBM,EACjB,eAAgBC,GAAoB,CAAC,EACrC,wBAAyBC,CAC3B,EACA,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAQA,MAAM,yBACJR,EACAS,EAKe,CACXA,EAAK,SAAS,QAAO,KAAK,cAAgBA,EAAK,SAAS,OACxDA,EAAK,SAAS,YAAW,KAAK,kBAAoBA,EAAK,SAAS,WAChEA,EAAK,SAAS,WAAU,KAAK,iBAAmBA,EAAK,SAAS,UAC9DA,EAAK,SAAS,QAAO,KAAK,cAAgBA,EAAK,SAAS,OAE5D,IAAML,EAAW,KAAK,WAAWK,EAAK,eAAe,EAC/CJ,EAAU,KAAK,WAAWI,EAAK,cAAc,EAE7CH,EAAoBF,GAAYC,GAAW,CAAC,EAC5CE,EAAmBF,GAAWD,EAC9BI,EAAmB,CAAC,EAAEC,EAAK,gBAAkBA,EAAK,iBAExD,MAAM,KAAK,KAAK,KACd,6BAA6BT,CAAS,6BACtC,CACE,kBAAmBA,EACnB,aAAc,CACZ,MAAO,KAAK,aACd,EACA,gBAAiBM,EACjB,eAAgBC,GAAoB,CAAC,EACrC,wBAAyBC,CAC3B,EACA,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAGQ,WAAWE,EAAkD,CACnE,GAAKA,EACL,OAAOC,GAAW,CAChB,UAAWD,EAAE,WAAa,KAAK,kBAC/B,SAAUA,EAAE,UAAY,KAAK,iBAC7B,MAAOA,EAAE,OAAS,KAAK,cACvB,SAAUA,EAAE,MACZ,SAAUA,EAAE,MACZ,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,OAAQA,EAAE,WACV,QAASA,EAAE,OACb,CAAC,CACH,CAGA,MAAM,eAAeV,EAAmBY,EAA6B,CACnE,MAAM,KAAK,KAAK,KACd,6BAA6BZ,CAAS,oBACtC,CAAE,kBAAmBA,EAAW,KAAAY,CAAK,EACrC,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAGA,MAAM,gBAAgBZ,EAAmBa,EAAqC,CAC5E,IAAMC,EAAUD,GAAe,UAC/B,MAAM,KAAK,KAAK,OACd,6BAA6Bb,CAAS,eAAec,CAAO,GAC5D,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CASA,MAAM,iBAAiBd,EAA4C,CAKjE,OAJY,MAAM,KAAK,KAAK,IAC1B,6BAA6BA,CAAS,kBACtC,CAAE,MAAO,KAAK,YAAa,CAC7B,GACW,OAAS,CAAC,CACvB,CAMA,MAAM,mBAAmBA,EAAmBe,EAA+B,CACzE,MAAM,KAAK,KAAK,KACd,6BAA6Bf,CAAS,iBACtC,CAAE,kBAAmBA,EAAW,eAAgBe,CAAO,EACvD,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAMQ,iBAAiBrB,EAAsE,CA1VjG,IAAAF,EA2VI,IAAMwB,EAAKtB,EAAI,gBACTuB,EAAkBD,EAAG,gBAAkB,CAAC,EACxCE,EAAWxB,EAAI,SAAWsB,EAAG,SAAWC,EAAe,CAAC,GAAK,CAAC,EAC9DtB,EAAaqB,EAAG,kBAAoB,CAAC,EACrCd,EAAWc,EAAG,SACdG,GAAoB3B,EAAA0B,EAAQ,UAAYF,EAAG,8BAAvB,YAAAxB,EAA4E,cAEhGS,EAAQN,EAAU,IAAKyB,GAAO,CAClC,IAAMC,EAAQD,EAAG,MACXE,GAAWD,GAAA,YAAAA,EAAO,UAAW,CAAC,EAC9BE,EAAWD,EAAQ,SAAW,CAAC,EAC/BE,GAAgBH,GAAA,YAAAA,EAAO,kBAAmB,CAAC,EAE3CI,GAAcN,EAAkBK,EAAaL,CAAe,EAAI,SACjEK,EAAa,OAAO,KAAKA,CAAY,EAAE,CAAC,CAAC,EACxCE,GAASD,GAAA,YAAAA,EAAY,SAAU,EACrC,MAAO,CACL,GAAIL,EAAG,GACP,UAAWA,EAAG,UACd,QAASA,EAAG,QACZ,YAAcG,EAAQ,MAAQ,GAC9B,YAAcD,EAAQ,MAAQ,GAC9B,SAAWF,EAAG,UAAY,EAC1B,WAAYM,EACZ,YAAaA,GAAWN,EAAG,UAAY,GACvC,SAAWD,GAAmB,MAC9B,SAAWG,EAAQ,UAAY,EACjC,CACF,CAAC,EAEKK,EAAgBT,EAAQ,OAAS,CAAC,EAExC,MAAO,CACL,GAAIF,EAAG,GACP,QAASA,EAAG,QACZ,cAAeA,EAAG,cAClB,SAAWG,GAAmB,MAC9B,MAAAlB,EACA,OAAQ,CACN,SAAWiB,EAAQ,gBAAkB,EACrC,SAAWA,EAAQ,sBAAwB,EAC3C,SAAWA,EAAQ,cAAgB,EACnC,IAAMA,EAAQ,gBAAkB,EAChC,MAAQA,EAAQ,aAAeS,EAAa,OAAO,CAACC,EAAWhC,IAA+BgC,GAAMhC,EAAE,QAAU,GAAe,CAAC,EAChI,SAAWuB,GAAmB,KAChC,EACA,SAAUjB,EACN,CACE,GAAIA,EAAS,GACb,MAAOA,EAAS,MAChB,UAAWA,EAAS,UACpB,SAAUA,EAAS,SACnB,MAAOA,EAAS,KAClB,EACA,OACJ,gBAAiB,KAAK,iBAAiBc,EAAG,eAAe,EACzD,eAAgB,KAAK,iBAAiBA,EAAG,cAAc,EACvD,uBAAyBA,EAAG,gBAAkB,KAC9C,SAAUA,EAAG,QACf,CACF,CASQ,iBAAiBtB,EAAmC,CAC1D,GAAI,CAACA,GAAO,OAAOA,GAAQ,SAAU,OACrC,IAAMgB,EAAIhB,EACJmC,EAAe,CACnB,UAAWnB,EAAE,UACb,SAAUA,EAAE,SACZ,MAAQA,EAAE,OAASA,EAAE,SACrB,MAAQA,EAAE,OAASA,EAAE,SACrB,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,WAAaA,EAAE,YAAcA,EAAE,OAC/B,QAASA,EAAE,QACX,MAAOA,EAAE,KACX,EAGA,OAAO,OAAO,OAAOmB,CAAG,EAAE,KAAMC,GAAMA,IAAM,QAAaA,IAAM,EAAE,EAAID,EAAM,MAC7E,CACF,EAMA,SAASlB,GAA8CoB,EAAW,CAChE,IAAMC,EAAkC,CAAC,EACzC,OAAW,CAACC,EAAGH,CAAC,IAAK,OAAO,QAAQC,CAAG,EACdD,GAAM,MAAQA,IAAM,KACzCE,EAAOC,CAAC,EAAIH,GAGhB,OAAQ,OAAO,KAAKE,CAAM,EAAE,OAAS,EAAIA,EAAS,MACpD,CCxZO,IAAME,GAAN,KAAoB,CACzB,YACmBC,EACAC,EACAC,EACjB,CAHiB,UAAAF,EACA,aAAAC,EACA,iBAAAC,CAChB,CAgBH,MAAM,gBACJC,EACAC,EAC6B,CAC7B,GAAIA,GAAA,MAAAA,EAAM,mBACR,OAAOA,EAAK,mBAGd,IAAMC,EAAW,KAAK,uBAAuB,EAC7C,GAAIA,EACF,OAAOA,EAGT,IAAMC,EAAU,MAAM,KAAK,KAAK,IAC9B,0BACA,CAAE,OAAQ,CAAE,kBAAAH,CAAkB,CAAE,CAClC,EAEMI,EAA6B,CAAC,EACpC,QAAWC,KAAKF,EAAQ,SAAW,CAAC,EAAG,CACrC,IAAMG,EAAMD,EAAE,SAAW,GAAGA,EAAE,MAAM,IAAIA,EAAE,QAAQ,GAAKA,EAAE,OACzDD,EAAOE,CAAG,EAAID,CAChB,CACA,OAAOD,CACT,CAMA,MAAM,kBACJJ,EACAC,EACyB,CA9F7B,IAAAM,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EA+FI,IAAMC,EAAQ,MAAM,KAAK,gBAAgBhB,EAAmBC,CAAI,EAC1DgB,EAAyB,CAAC,EAEhC,OAAW,CAACX,EAAKF,CAAM,IAAK,OAAO,QAAQY,CAAK,EAAG,CACjD,GAAI,CAACZ,EAAO,QAAS,SAIrB,GAAIE,EAAI,WAAW,mBAAmB,GAAKF,EAAO,QAAS,CACzD,IAAMc,EAAO,CACX,UAAW,GACX,YAAad,EAAO,YACpB,eAAgBA,EAAO,eACvB,SAAUA,EAAO,QACnB,EACA,IAAIG,EAAAH,EAAO,QAAQ,YAAf,MAAAG,EAA0B,QAAS,CACrC,IAAMY,EACJ,OAAO,OAAW,KAClB,oBAAqB,UACpBV,GAAAD,EAAA,OACE,kBADF,YAAAA,EACmB,kBADnB,YAAAC,EAAA,KAAAD,IAEHS,EAAO,SAAW,CAAE,GAAGC,EAAM,KAAM,YAAa,UAAW,CAAC,CAACC,CAAY,CAC3E,EACIT,EAAAN,EAAO,QAAQ,aAAf,MAAAM,EAA2B,UAC7BO,EAAO,UAAY,CAAE,GAAGC,EAAM,KAAM,YAAa,IAE/CP,EAAAP,EAAO,QAAQ,SAAf,MAAAO,EAAuB,UACzBM,EAAO,OAAS,CAAE,GAAGC,EAAM,KAAM,QAAS,IAExCN,EAAAR,EAAO,QAAQ,OAAf,MAAAQ,EAAqB,UACvBK,EAAO,KAAO,CAAE,GAAGC,EAAM,KAAM,MAAO,IAEpCL,EAAAT,EAAO,QAAQ,iBAAf,MAAAS,EAA+B,UACjCI,EAAO,OAAS,CAAE,GAAGC,EAAM,KAAM,gBAAiB,GAEpD,QACF,CAEA,GAAI,CAACd,EAAO,QAAS,SAErB,IAAMgB,EAAShB,EAAO,OAChBc,EAAO,CACX,KAAME,EACN,UAAW,GACX,YAAahB,EAAO,YACpB,eAAgBA,EAAO,eACvB,SAAUA,EAAO,QACnB,EAEA,GAAIgB,IAAW,aAAehB,EAAO,OAAS,YAAa,CACzD,IAAMe,EACJ,OAAO,OAAW,KAClB,oBAAqB,UACpBJ,GAAAD,EAAA,OACE,kBADF,YAAAA,EACmB,kBADnB,YAAAC,EAAA,KAAAD,IAEHG,EAAO,SAAW,CAAE,GAAGC,EAAM,UAAW,CAAC,CAACC,CAAY,CACxD,MAAWC,IAAW,cAAgBhB,EAAO,OAAS,aACpDa,EAAO,UAAYC,EACVE,IAAW,SACpBH,EAAO,OAASC,EACPE,IAAW,UAAYA,IAAW,iBAC3CH,EAAO,OAASC,EACPE,IAAW,SACpBH,EAAO,KAAOC,EAElB,CAEA,OAAOD,CACT,CAKA,MAAM,gBAAuC,CAC3C,IAAMI,EAAM,MAAM,KAAK,KAAK,IAC1B,0BACA,CAAE,OAAQ,CAAE,QAAS,KAAK,OAAQ,CAAE,CACtC,EACA,OAAOA,EAAI,QAAWA,CACxB,CAKA,MAAM,kBACJrB,EACAC,EACmB,CACnB,IAAMe,EAAQ,MAAM,KAAK,gBAAgBhB,EAAmBC,CAAI,EAChE,OAAO,OAAO,QAAQe,CAAK,EACxB,OAAO,CAAC,CAAC,CAAEM,CAAC,IAAMA,EAAE,OAAO,EAC3B,IAAI,CAAC,CAAChB,CAAG,IAAMA,CAAG,CACvB,CAoBA,MAAM,aAAaiB,EAKqD,CACtE,IAAMC,EAAS,MAAM,KAAK,WAAW,EAE/BC,EAAY,IAAID,EAAO,UAAU,CAAE,YAAa,KAAK,WAAY,CAAC,EACxE,MAAMC,EAAU,WAAW,EAE3B,IAAMC,EAAoC,CACxC,WAAYH,EAAK,WACjB,WAAYA,EAAK,WACjB,IAAKA,EAAK,GACZ,EACIA,EAAK,iBAAgBG,EAAU,eAAiBH,EAAK,gBAEzD,GAAM,CAACI,EAAaC,CAAQ,EAAI,MAAM,QAAQ,IAAI,CAChDH,EAAU,aAAaC,CAAS,EAChCD,EAAU,gBAAgBC,CAAS,CACrC,CAAC,EAED,MAAO,CAAE,YAAAC,EAAa,SAAAC,CAAS,CACjC,CAUA,MAAM,iBACJ3B,EACmD,CACnD,OAAO,KAAK,KAAK,KAAK,+CAAgD,CACpE,YAAaA,EAAK,WACpB,CAAC,CACH,CAUA,MAAM,iBAAiBA,EAIK,CAC1B,OAAO,KAAK,KAAK,KAAK,wCAAyC,CAC7D,SAAUA,EAAK,UAAY,eAC3B,QAAS,KAAK,QACd,oBAAqBA,EAAK,oBAC1B,YAAaA,EAAK,WACpB,CAAC,CACH,CAYA,MAAM,IAAIA,EAAsC,CAC9C,OAAIA,EAAK,aAAe,CAACA,EAAK,oBACrB,KAAK,KAAK,KAAgB,iCAAkC,CACjE,YAAaA,EAAK,YAClB,kBAAmBA,EAAK,kBACxB,UAAWA,EAAK,UAChB,cAAeA,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAeA,EAAK,cACpB,UAAWA,EAAK,UAChB,SAAUA,EAAK,QACjB,CAAC,EAGI,KAAK,KAAK,KAAgB,iCAAkC,CACjE,kBAAmBA,EAAK,kBACxB,oBAAqBA,EAAK,oBAC1B,QAAS,KAAK,QACd,cAAeA,EAAK,cACpB,iBAAkBA,EAAK,iBACvB,YAAaA,EAAK,YAClB,cAAeA,EAAK,cACpB,UAAWA,EAAK,UAChB,SAAUA,EAAK,QACjB,CAAC,CACH,CAMA,MAAM,UAAUA,EAA4C,CAC1D,OAAO,KAAK,KAAK,KAAgB,iCAAkC,CACjE,kBAAmBA,EAAK,kBACxB,oBAAqBA,EAAK,qBAAuB,GACjD,QAAS,KAAK,QACd,cAAeA,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAeA,EAAK,cACpB,UAAWA,EAAK,UAChB,iBAAkBA,EAAK,gBACzB,CAAC,CACH,CAMA,MAAM,gBAAgBA,EAKC,CACrB,IAAMuB,EAAS,MAAM,KAAK,WAAW,EAC/BC,EAAY,IAAID,EAAO,UAAU,CAAE,YAAa,KAAK,WAAY,CAAC,EACxE,MAAMC,EAAU,WAAW,EAC3B,GAAM,CAAE,YAAAE,CAAY,EAAI,MAAMF,EAAU,iBAAiBxB,EAAK,aAAa,EAE3E,OAAO,KAAK,IAAI,CACd,kBAAmBA,EAAK,kBACxB,YAAA0B,EACA,cAAe1B,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAe,YACf,UAAW,EACb,CAAC,CACH,CAMA,MAAM,iBAAiBA,EAKA,CACrB,IAAMuB,EAAS,MAAM,KAAK,WAAW,EAC/BC,EAAY,IAAID,EAAO,UAAU,CAAE,YAAa,KAAK,WAAY,CAAC,EACxE,MAAMC,EAAU,WAAW,EAC3B,GAAM,CAAE,YAAAE,CAAY,EAAI,MAAMF,EAAU,kBAAkBxB,EAAK,cAAc,EAE7E,OAAO,KAAK,IAAI,CACd,kBAAmBA,EAAK,kBACxB,YAAA0B,EACA,cAAe1B,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAe,aACf,UAAW,EACb,CAAC,CACH,CAMA,MAAM,WAAWA,EAKM,CACrB,OAAO,KAAK,UAAU,CACpB,kBAAmBA,EAAK,kBACxB,cAAeA,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAeA,EAAK,aACtB,CAAC,CACH,CAYA,MAAM,qBAAqBA,EAIJ,CACrB,OAAO,KAAK,UAAU,CACpB,kBAAmBA,EAAK,kBACxB,YAAaA,EAAK,YAClB,cAAeA,EAAK,cACpB,UAAW,EACb,CAAC,CACH,CAoCA,MAAM,eAAeA,EAA4D,CAjcnF,IAAAM,EAAAC,EAkcQ,CAACP,EAAK,WAAa,OAAO,OAAW,MACvCA,EAAO,CAAE,GAAGA,EAAM,UAAW,OAAO,SAAS,IAAK,GAEpD,IAAM4B,EAAY,MAAM,KAAK,IAAI5B,CAAI,EAC/B6B,EAAUD,EAAU,QAE1B,OAAIC,EAAQ,SAAW,YACd,CAAE,OAAQ,YAAa,QAAAA,EAAS,MAAOD,EAAU,KAAM,EAG5DC,EAAQ,SAAW,UAAYA,EAAQ,SAAW,WAI7C,CAAE,OAAQ,SAAU,QAHfvB,EAAAuB,EAAQ,oBAAR,YAAAvB,EAA2B,YAClCC,EAAAsB,EAAQ,oBAAR,YAAAtB,EAA2B,YAC3B,WAAWsB,EAAQ,MAAM,GACS,QAAAA,CAAQ,EAG7CA,EAAQ,eAAiBA,EAAQ,gBAAkB,QAAUA,EAAQ,kBAChE,KAAK,oBAAoBA,EAAS7B,CAAI,EAIxC,KAAK,cAAc6B,EAAQ,EAAE,CACtC,CAQA,MAAM,oBAAoBC,EAAkD,CAC1E,OAAO,KAAK,cAAcA,CAAS,CACrC,CAOA,MAAM,iBAAiBA,EAA2C,CAChE,OAAO,KAAK,KAAK,IAAmB,oBAAoBA,CAAS,EAAE,CACrE,CAMA,MAAM,kBACJA,EACA9B,EACwB,CACxB,IAAM+B,GAAW/B,GAAA,YAAAA,EAAM,aAAc,KAC/BgC,GAAUhC,GAAA,YAAAA,EAAM,YAAa,IAC7BiC,EAAQ,KAAK,IAAI,EAEvB,KAAO,KAAK,IAAI,EAAIA,EAAQD,GAAS,CACnC,IAAME,EAAS,MAAM,KAAK,iBAAiBJ,CAAS,EACpD,GAAII,EAAO,SAAW,aAAeA,EAAO,SAAW,UAAYA,EAAO,SAAW,WACnF,OAAOA,EAET,MAAM,IAAI,QAASC,GAAM,WAAWA,EAAGJ,CAAQ,CAAC,CAClD,CAEA,MAAM,IAAI,MAAM,WAAWD,CAAS,yCAAyCE,CAAO,KAAK,CAC3F,CAGA,MAAM,iBAAiBF,EAA2C,CAChE,OAAO,KAAK,KAAK,KAAoB,sCAAuC,CAC1E,UAAAA,CACF,CAAC,CACH,CAGA,MAAM,oBAAoBA,EAAkC,CAC1D,GAAI,CACF,MAAM,KAAK,KAAK,KAAK,4CAA6C,CAChE,UAAAA,CACF,CAAC,CACH,MAAQ,CAER,CACF,CAWA,MAAc,oBACZD,EACA7B,EAC+B,CAC/B,IAAMoC,EAAaP,EAAQ,kBAM3B,OAJA,MAAM,KAAK,oBAAoBA,EAAQ,EAAE,EAEtBO,EAAW,KAEV,CAClB,IAAK,eACH,OAAO,KAAK,kBAAkBP,EAAS7B,CAAI,EAE7C,IAAK,iBACL,IAAK,sBACH,OAAO,KAAK,gBAAgB6B,EAASO,CAAU,EAEjD,IAAK,WACH,OAAO,KAAK,gBAAgBP,EAASO,CAAU,EAEjD,IAAK,QACH,MAAO,CACL,OAAQ,SACR,MAAOA,EAAW,SAAWA,EAAW,WAAa,iBACrD,QAAAP,CACF,EAEF,QAEE,OAAO,KAAK,gBAAgBA,EAASO,CAAU,CACnD,CACF,CAMQ,gBACNP,EACAO,EACsB,CAzkB1B,IAAA9B,EAAAC,EA0kBI,IAAM8B,GAAW/B,EAAA8B,EAAW,WAAX,YAAA9B,EAAqB,SAChCgC,GAAMD,GAAA,YAAAA,EAAU,cAAeD,EAAW,YAEhD,OAAKE,EAQE,CACL,OAAQ,oBACR,YAAaA,EACb,SAAS/B,EAAA8B,GAAA,YAAAA,EAAU,SAAV,YAAA9B,EAAkB,gBAAoC,MAC/D,SAAU8B,GAAA,YAAAA,EAAU,KACpB,UAAWR,EAAQ,EACrB,EAbS,CACL,OAAQ,SACR,MAAO,4BAA4BO,EAAW,IAAI,qCAClD,QAAAP,CACF,CAUJ,CAMA,MAAc,kBACZA,EACA7B,EAC+B,CArmBnC,IAAAM,EAAAC,EAsmBI,IAAMgC,GAAUhC,GAAAD,EAAAuB,EAAQ,oBAAR,YAAAvB,EAA2B,WAA3B,YAAAC,EAAqC,eAGrD,GAAI,EAACgC,GAAA,MAAAA,EAAS,mBACZ,OAAO,KAAK,gBAAgBV,EAASA,EAAQ,iBAAkB,EAIjE,IAAIN,EACJ,GAAI,CACFA,EAAS,KAAM,QAAO,oBAAoB,CAC5C,MAAQ,CAEN,OAAIgB,EAAQ,gBACH,CACL,OAAQ,oBACR,YAAaA,EAAQ,gBACrB,UAAWV,EAAQ,EACrB,EAEK,KAAK,gBAAgBA,EAASA,EAAQ,iBAAkB,CACjE,CAGA,GAAI,CACF,IAAMW,EAAU,IAAIjB,EAAO,eAAe,CAAE,SAAU,cAAe,CAAC,EACtE,aAAMiB,EAAQ,WAAW,CAAE,OAAQ,MAAU,CAAC,EAE9C,MAAMA,EAAQ,eAAe,CAC3B,UAAWD,EAAQ,kBACnB,gBAAiBA,EAAQ,gBACzB,iBAAkBA,EAAQ,WAC1B,eAAgBA,EAAQ,cAC1B,CAAC,EAGD,MAAM,KAAK,iBAAiBV,EAAQ,EAAE,EAC/B,KAAK,cAAcA,EAAQ,EAAE,CACtC,MAAQ,CAEN,OAAIU,EAAQ,gBACH,CACL,OAAQ,oBACR,YAAaA,EAAQ,gBACrB,UAAWV,EAAQ,EACrB,EAEK,CACL,OAAQ,SACR,MAAO,kCACP,QAAAA,CACF,CACF,CACF,CAMA,MAAc,cACZC,EACA9B,EAC+B,CAC/B,IAAM+B,GAAW/B,GAAA,YAAAA,EAAM,aAAc,KAC/BgC,GAAUhC,GAAA,YAAAA,EAAM,YAAa,IAC7BiC,EAAQ,KAAK,IAAI,EACnBQ,EAAoB,EAExB,KAAO,KAAK,IAAI,EAAIR,EAAQD,GAAS,CACnC,IAAIE,EACJ,GAAI,CACFA,EAAS,MAAM,KAAK,iBAAiBJ,CAAS,EAC9CW,EAAoB,CACtB,MAAQ,CAEN,GADAA,IACIA,GAAqB,EACvB,MAAO,CAAE,OAAQ,SAAU,MAAO,mDAAoD,EAExF,MAAM,IAAI,QAASN,GAAM,WAAWA,EAAGJ,CAAQ,CAAC,EAChD,QACF,CAEA,GACEG,EAAO,SAAW,aACjBA,EAAO,SAAW,WAAaA,EAAO,YAAc,aAErD,MAAO,CAAE,OAAQ,YAAa,QAASA,EAA2C,MAAOA,EAAO,KAAM,EAGxG,GAAIA,EAAO,SAAW,UAAYA,EAAO,SAAW,WAClD,MAAO,CAAE,OAAQ,SAAU,MAAOA,EAAO,OAAQ,QAASA,CAA0C,EAItG,GACEA,EAAO,eACPA,EAAO,gBAAkB,QACzBA,EAAO,mBACP,CAACA,EAAO,kBAAkB,UAE1B,OAAO,KAAK,oBACVA,EACA,CAAC,CACH,EAGF,MAAM,IAAI,QAASC,GAAM,WAAWA,EAAGJ,CAAQ,CAAC,CAClD,CAEA,MAAO,CAAE,OAAQ,UAAW,UAAAD,CAAU,CACxC,CAUQ,wBAAoD,CAC1D,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,IAAMY,EAAO,OAA8C,oBAC3D,GAAI,CAACA,EAAK,OAAO,KACjB,GAAI,CACF,IAAMC,EAAS,OAAOD,GAAQ,SAAW,KAAK,MAAMA,CAAG,EAAIA,EAC3D,OAAQC,GAAA,YAAAA,EAAoC,qBAA4C,IAC1F,MAAQ,CACN,OAAO,IACT,CACF,CAGA,MAAc,YAA2B,CACvC,GAAI,CACF,OAAO,KAAM,QAAO,oBAAoB,CAC1C,MAAQ,CACN,MAAM,IAAI,MACR,qFACF,CACF,CACF,CACF,ECpuBO,IAAMC,GAAN,KAAmB,CACxB,YACmBC,EACAC,EACjB,CAFiB,UAAAD,EACA,aAAAC,CAChB,CAOH,MAAM,SAASC,EAAiC,CAC9C,OAAO,KAAK,KAAK,IAAW,kBAAkBA,CAAO,EAAE,CACzD,CAGA,MAAM,WAAWC,EAGI,CAnCvB,IAAAC,EAoCI,IAAIC,EAAM,kBAAkB,KAAK,OAAO,UAElCC,EAAuB,CAAC,EAE9B,GADIH,GAAA,MAAAA,EAAM,MAAMG,EAAW,KAAK,QAAQ,mBAAmBH,EAAK,IAAI,CAAC,EAAE,GACnEC,EAAAD,GAAA,YAAAA,EAAM,MAAN,MAAAC,EAAW,OACb,QAAWG,KAAMJ,EAAK,IAAKG,EAAW,KAAK,OAAO,mBAAmBC,CAAE,CAAC,EAAE,EAE5E,OAAID,EAAW,SAAQD,GAAO,IAAIC,EAAW,KAAK,GAAG,CAAC,KAE1C,MAAM,KAAK,KAAK,IAAyBD,CAAG,GAC7C,QAAU,CAAC,CACxB,CAOA,MAAM,aAAaF,EAIO,CACxB,OAAO,KAAK,KAAK,KAAmB,kBAAkBA,EAAK,OAAO,WAAY,CAC5E,QAASA,EAAK,QACd,SAAUA,EAAK,UAAY,GAC3B,UAAWA,EAAK,SAClB,CAAC,CACH,CAMA,MAAM,kBAAkBA,EAOI,CAC1B,OAAO,KAAK,KAAK,KAAqB,kBAAkBA,EAAK,OAAO,eAAgB,CAClF,QAASA,EAAK,QACd,SAAUA,EAAK,UAAY,GAC3B,UAAWA,EAAK,UAChB,UAAWA,EAAK,YAAc,OAAO,OAAW,IAAc,OAAO,SAAS,KAAO,IACrF,YAAaA,EAAK,YAClB,oBAAqBA,EAAK,mBAC5B,CAAC,CACH,CAOA,MAAM,gBAAgBA,EAID,CACnB,OAAO,KAAK,KAAK,KACf,6BAA6BA,EAAK,iBAAiB,qBACnD,CACE,iBAAkBA,EAAK,iBACvB,SAAUA,EAAK,QACjB,CACF,CACF,CAOA,MAAM,uBAAuBK,EAAmC,CAC9D,IAAMC,EAAM,MAAM,KAAK,KAAK,IAAa,yBAAyBD,CAAO,SAAS,EAClF,OAAO,MAAM,QAAQC,CAAG,EAAIA,EAAM,CAAC,CACrC,CAGA,MAAM,wBAAwBN,EAIoB,CAChD,OAAO,KAAK,KAAK,KACf,kBAAkBA,EAAK,OAAO,yBAAyBA,EAAK,OAAO,UACnE,CAAE,MAAOA,EAAK,OAAS,CAAC,CAAE,CAC5B,CACF,CAGA,MAAM,yBAAyBA,EAGmB,CAChD,OAAO,KAAK,KAAK,KACf,kBAAkBA,EAAK,OAAO,yBAAyBA,EAAK,OAAO,UACrE,CACF,CACF,EClIO,IAAMO,GAAN,KAAqB,CAC1B,YACmBC,EACAC,EACjB,CAFiB,UAAAD,EACA,aAAAC,CAChB,CAGH,MAAM,WAAWC,EAAuC,CAKtD,OAJY,MAAM,KAAK,KAAK,IAC1B,qBAAqBA,CAAU,GAC/B,CAAE,OAAQ,CAAE,QAAS,KAAK,OAAQ,CAAE,CACtC,GACW,QACb,CAGA,MAAM,WAAWC,EAAyC,CACxD,GAAI,CAKF,OAJY,MAAM,KAAK,KAAK,IAC1B,6BACA,CAAE,OAAQ,CAAE,MAAAA,EAAO,QAAS,KAAK,OAAQ,CAAE,CAC7C,GACW,QACb,MAAQ,CACN,OAAO,IACT,CACF,CAGA,MAAM,cACJD,EACAE,EACmB,CAKnB,OAJY,MAAM,KAAK,KAAK,MAC1B,qBAAqBF,CAAU,GAC/B,CAAE,QAAS,KAAK,QAAS,GAAGE,CAAK,CACnC,GACW,QACb,CAGA,MAAM,UACJF,EACAG,EAC6C,CAC7C,OAAO,KAAK,KAAK,IACf,qBAAqBH,CAAU,UAC/B,CAAE,OAAQ,CAAE,QAAS,KAAK,QAAS,MAAOG,GAAA,YAAAA,EAAM,MAAO,OAAQA,GAAA,YAAAA,EAAM,MAAO,CAAE,CAChF,CACF,CAGA,MAAM,SAASC,EAAiC,CAI9C,OAHY,MAAM,KAAK,KAAK,IAAsB,kBAAkBA,CAAO,GAAI,CAC7E,OAAQ,CAAE,QAAS,KAAK,OAAQ,CAClC,CAAC,GACU,KACb,CAGA,MAAM,iBAAiBJ,EAA6C,CAKlE,OAJY,MAAM,KAAK,KAAK,IAC1B,qBAAqBA,CAAU,iBAC/B,CAAE,OAAQ,CAAE,QAAS,KAAK,OAAQ,CAAE,CACtC,GACW,aACb,CAGA,MAAM,gBAAgBK,EAA+C,CAKnE,OAJY,MAAM,KAAK,KAAK,IAC1B,yBAAyBA,CAAc,GACvC,CAAE,OAAQ,CAAE,QAAS,KAAK,OAAQ,CAAE,CACtC,GACW,YACb,CACF,EC5EO,IAAMC,GAAN,KAAoB,CACzB,YACmBC,EACAC,EACjB,CAFiB,UAAAD,EACA,aAAAC,CAChB,CAQH,MAAM,YAAYC,EAGY,CAvBhC,IAAAC,EAAAC,EAwBI,IAAMC,EAAgC,CACpC,QAAS,KAAK,QACd,gBAAiB,GACjB,cAAe,EACjB,EACA,OAAIF,EAAAD,GAAA,YAAAA,EAAM,aAAN,MAAAC,EAAkB,SAAQE,EAAK,WAAaH,EAAK,aACjDE,EAAAF,GAAA,YAAAA,EAAM,aAAN,MAAAE,EAAkB,SAAQC,EAAK,WAAaH,EAAK,aAEzC,MAAM,KAAK,KAAK,KAC1B,mBACAG,CACF,GAEW,OAAS,CAAC,CACvB,CAKA,MAAM,WAAWC,EAAmD,CAElE,OADc,MAAM,KAAK,YAAY,CAAE,WAAY,CAACA,CAAS,CAAE,CAAC,GACnD,CAAC,GAAK,IACrB,CACF,EC3BO,IAAMC,GAAN,KAAqB,CAuB1B,YAAYC,EAAwB,CAClC,IAAMC,EAA2BD,EAAO,aAAe,aACjDE,EAAUC,EAAW,eAAeF,EAAaD,EAAO,OAAO,EAErE,KAAK,OAAS,CACZ,GAAGA,EACH,YAAAC,EACA,QAAAC,EACA,QAASF,EAAO,SAAW,GAC7B,EAEA,KAAK,KAAO,IAAIG,EAAW,CACzB,QAAAD,EACA,QAAS,KAAK,OAAO,QACrB,OAAQF,EAAO,OACf,SAAU,IAAM,KAAK,aACvB,CAAC,EAED,IAAMI,EAAYC,GAAkB,CAClC,KAAK,cAAgBA,CACvB,EAEA,KAAK,SAAW,IAAIC,GAAe,KAAK,KAAM,KAAK,OAAO,QAASF,CAAQ,EAC3E,KAAK,QAAU,IAAIG,GAAc,KAAK,KAAM,KAAK,OAAO,QAASN,CAAW,EAC5E,KAAK,OAAS,IAAIO,GAAa,KAAK,KAAM,KAAK,OAAO,OAAO,EAC7D,KAAK,SAAW,IAAIC,GAAe,KAAK,KAAM,KAAK,OAAO,OAAO,EACjE,KAAK,QAAU,IAAIC,GAAc,KAAK,KAAM,KAAK,OAAO,OAAO,CACjE,CAGA,gBAAgBL,EAAe,CAC7B,KAAK,cAAgBA,CACvB,CACF,EAiBO,SAASM,GAAqBX,EAAwC,CAC3E,OAAO,IAAID,GAAeC,CAAM,CAClC,CR5CI,IAAAY,GAAA,uBA3CEC,MAAwB,iBAAiD,IAAI,EA2B5E,SAASC,GAAuB,CACrC,QAAAC,EACA,YAAAC,EACA,OAAAC,EACA,QAAAC,EACA,OAAAC,EACA,SAAAC,CACF,EAAgC,CAC9B,IAAMC,KAAS,WAAQ,IAEdC,GADqBH,GAAU,CAAE,QAAAJ,EAAS,YAAAC,EAAa,OAAAC,EAAQ,QAAAC,CAAQ,CAC/C,EAC9B,CAACH,EAASC,EAAaC,EAAQC,EAASC,CAAM,CAAC,EAE5CI,KAAQ,WAAQ,KAAO,CAAE,OAAAF,CAAO,GAAI,CAACA,CAAM,CAAC,EAElD,SACE,QAACR,GAAsB,SAAtB,CAA+B,MAAOU,EACpC,SAAAH,EACH,CAEJ,CAGO,SAASI,GAAoC,CAClD,IAAMC,KAAM,cAAWZ,EAAqB,EAC5C,GAAI,CAACY,EACH,MAAM,IAAI,MAAM,gEAAgE,EAElF,OAAOA,EAAI,MACb,CShEA,IAAAC,EAAiD,WAyD1C,SAASC,GACdC,EACAC,EACmB,CACnB,IAAMC,EAASC,EAAkB,EAC3B,CAACC,EAASC,CAAU,KAAI,YAAiC,IAAI,EAC7D,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,KAAI,YAAuB,IAAI,EAE/CC,KAAc,eAAY,SAAY,CAC1C,GAAKV,EACL,CAAAO,EAAa,EAAI,EACjBE,EAAS,IAAI,EACb,GAAI,CACF,IAAME,EAAI,MAAMT,EAAO,SAAS,YAAYF,EAAeC,CAAY,EACvEI,EAAWM,CAAC,CACd,OAASC,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,EACF,EAAG,CAACL,EAAQF,EAAeC,CAAY,CAAC,KAExC,aAAU,IAAM,CACdS,EAAY,CACd,EAAG,CAACA,CAAW,CAAC,EAEhB,IAAMG,KAAgB,eAAY,MAAOC,GAKnC,CACJP,EAAa,EAAI,EACjBE,EAAS,IAAI,EACb,GAAI,CACF,IAAMM,EAAS,MAAMb,EAAO,SAAS,cAAcY,CAAI,EAEjDE,EAAS,IAAI,IAAI,OAAO,SAAS,IAAI,EAC3CA,EAAO,aAAa,IAAI,gBAAiBD,EAAO,aAAa,EAC7DC,EAAO,aAAa,IAAI,QAASD,EAAO,YAAY,EACpD,OAAO,QAAQ,aAAa,CAAC,EAAG,GAAIC,EAAO,SAAS,CAAC,EAErD,IAAML,EAAI,MAAMT,EAAO,SAAS,YAAYa,EAAO,cAAeA,EAAO,YAAY,EACrFV,EAAWM,CAAC,CACd,OAASC,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,CACF,EAAG,CAACL,CAAM,CAAC,EAELe,KAAa,eAAY,MAAOC,GAAsB,CACrDd,IAKL,MAAMF,EAAO,SAAS,WAAWE,EAAQ,GAAIc,CAAK,EAClD,MAAMR,EAAY,EACpB,EAAG,CAACR,EAAQE,EAASM,CAAW,CAAC,EAE3BS,KAAiB,eAAY,MAAOC,GAAwC,CAC3EhB,GACL,MAAMF,EAAO,SAAS,eAAeE,EAAQ,GAAIgB,CAAQ,CAC3D,EAAG,CAAClB,EAAQE,CAAO,CAAC,EAEdiB,KAAgB,eAAY,MAAOC,GAAuE,CAC9G,GAAKlB,EACL,CAAAG,EAAa,EAAI,EACjB,GAAI,CACF,MAAML,EAAO,SAAS,cAAcE,EAAQ,GAAIkB,CAAS,EACzD,MAAMZ,EAAY,CACpB,OAASE,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,EACF,EAAG,CAACL,EAAQE,EAASM,CAAW,CAAC,EAE3Ba,KAA2B,eAAY,MAAOC,GAI9C,CACJ,GAAKpB,EACL,CAAAG,EAAa,EAAI,EACjB,GAAI,CACF,MAAML,EAAO,SAAS,yBAAyBE,EAAQ,GAAIoB,CAAI,EAC/D,MAAMd,EAAY,CACpB,OAASE,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,EACF,EAAG,CAACL,EAAQE,EAASM,CAAW,CAAC,EAE3Be,KAAa,eAAY,MAAOC,GAAiB,CACrD,GAAKtB,EACL,CAAAG,EAAa,EAAI,EACjB,GAAI,CACF,MAAML,EAAO,SAAS,eAAeE,EAAQ,GAAIsB,CAAI,EACrD,MAAMhB,EAAY,CACpB,OAASE,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,EACF,EAAG,CAACL,EAAQE,EAASM,CAAW,CAAC,EAE3BiB,KAAc,eAAY,MAAOC,GAAyB,CAC9D,GAAKxB,EACL,CAAAG,EAAa,EAAI,EACjB,GAAI,CACF,MAAML,EAAO,SAAS,gBAAgBE,EAAQ,GAAIwB,CAAW,EAC7D,MAAMlB,EAAY,CACpB,OAASE,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,EACF,EAAG,CAACL,EAAQE,EAASM,CAAW,CAAC,EAE3BmB,KAAmB,eAAY,SAC9BzB,EACEF,EAAO,SAAS,iBAAiBE,EAAQ,EAAE,EAD7B,CAAC,EAErB,CAACF,EAAQE,CAAO,CAAC,EAEd0B,KAAqB,eAAY,MAAOC,GAAmB,CAC/D,GAAK3B,EACL,CAAAG,EAAa,EAAI,EACjB,GAAI,CACF,MAAML,EAAO,SAAS,mBAAmBE,EAAQ,GAAI2B,CAAM,EAC3D,MAAMrB,EAAY,CACpB,OAASE,EAAK,CACZH,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAL,EAAa,EAAK,CACpB,EACF,EAAG,CAACL,EAAQE,EAASM,CAAW,CAAC,EAEjC,MAAO,CACL,QAAAN,EACA,UAAAE,EACA,MAAAE,EACA,QAASE,EACT,cAAAG,EACA,WAAAI,EACA,eAAAE,EACA,cAAAE,EACA,yBAAAE,EACA,WAAAE,EACA,YAAAE,EACA,iBAAAE,EACA,mBAAAC,CACF,CACF,CCrNA,IAAAE,EAAyD,WAqHlD,SAASC,GAAWC,EAA+C,CACxE,IAAMC,EAASC,EAAkB,EAC3B,CAACC,EAAcC,CAAe,KAAI,YAAoC,IAAI,EAC1E,CAACC,EAAgBC,CAAiB,KAAI,YAAgC,IAAI,EAC1E,CAACC,EAAaC,CAAc,KAAI,YAA6B,IAAI,EACjE,CAACC,EAAcC,CAAe,KAAI,YAAS,EAAK,EAChD,CAACC,EAAQC,CAAS,KAAI,YAA2B,IAAI,EACrD,CAACC,EAAOC,CAAQ,KAAI,YAAuB,IAAI,EAC/CC,KAAY,UAAO,EAAK,EACxBC,KAA6B,UAAO,EAAK,EACzCC,KAAa,UAAOjB,CAAO,EACjCiB,EAAW,QAAUjB,KAKrB,aAAU,IAAM,CAEd,GADI,OAAO,OAAW,KAClBgB,EAA2B,QAAS,OAExC,IAAME,EAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM,EACnDC,EAAgBD,EAAO,IAAI,eAAe,EAC1CE,EAAsBF,EAAO,IAAI,qBAAqB,EACtDG,EAAYH,EAAO,IAAI,WAAW,EAExC,GAAIC,IAAkB,iBAAmBC,IAAwB,aAAe,CAACC,EAC/E,OAGFL,EAA2B,QAAU,GACrCN,EAAgB,EAAI,EACpBI,EAAS,IAAI,GAEE,SAAY,CAtJ/B,IAAAQ,EAAAC,EAAAC,EAAAC,EAuJM,GAAI,CACF,IAAMC,EAAe,MAAMzB,EAAO,QAAQ,oBAAoBoB,CAAS,EAGjEM,GAAc,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAC9D,CAAC,gBAAiB,sBAAuB,YAAa,iBAAkB,+BAAgC,cAAe,iBAAiB,EAAE,QACvIC,IAAMD,GAAY,OAAOC,EAAC,CAC7B,EACA,IAAMC,GAASF,GAAY,SAAS,EAChC,GAAG,OAAO,SAAS,QAAQ,IAAIA,GAAY,SAAS,CAAC,GACrD,OAAO,SAAS,SACpB,OAAO,QAAQ,aAAa,CAAC,EAAG,SAAS,MAAOE,EAAM,EAElDH,EAAa,SAAW,aAC1BH,GAAAD,EAAAL,EAAW,UAAX,YAAAK,EAAoB,mBAApB,MAAAC,EAAA,KAAAD,EAAuCI,GAC9BA,EAAa,SAAW,WACjCZ,EAAS,IAAI,MAAMY,EAAa,KAAK,CAAC,GACtCD,GAAAD,EAAAP,EAAW,UAAX,YAAAO,EAAoB,kBAApB,MAAAC,EAAA,KAAAD,EAAsCE,GAE1C,OAASI,EAAK,CACZhB,EAASgB,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACApB,EAAgB,EAAK,CACvB,CACF,GAEY,CACd,EAAG,CAACT,CAAM,CAAC,EAKX,IAAM8B,KAAmB,eAAY,MACnCC,EACAC,IACG,CA1LP,IAAAX,EA2LI,GAAIP,EAAU,QAAS,OACvBA,EAAU,QAAU,GACpB,IAAMmB,EAAYD,GAAA,MAAAA,EAAM,mBACpB,CAAE,mBAAoBA,EAAK,kBAAmB,GAC9CX,EAAAL,EAAW,UAAX,MAAAK,EAAoB,mBAClB,CAAE,mBAAoBL,EAAW,QAAQ,kBAAmB,EAC5D,OACN,GAAI,CACF,GAAM,CAACkB,EAAOC,EAASC,CAAM,EAAI,MAAM,QAAQ,IAAI,CACjDpC,EAAO,QAAQ,gBAAgB+B,EAAmBE,CAAS,EAC3DjC,EAAO,QAAQ,kBAAkB+B,EAAmBE,CAAS,EAC7DjC,EAAO,QAAQ,eAAe,CAChC,CAAC,EACDG,EAAgB+B,CAAK,EACrB7B,EAAkB8B,CAAO,EACzB5B,EAAe6B,CAAM,CACvB,OAASP,EAAK,CACZf,EAAU,QAAU,GACpBD,EAASgB,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,CACF,EAAG,CAAC7B,CAAM,CAAC,EAKLqC,KAAiB,eACrB,MAAOL,GAA+D,CArN1E,IAAAX,EAAAC,EAAAC,EAAAC,EAsNMf,EAAgB,EAAI,EACpBI,EAAS,IAAI,EACb,GAAI,CACF,IAAMyB,EAAY,MAAMtC,EAAO,QAAQ,eAAegC,CAAI,EAE1D,GAAIM,EAAU,SAAW,oBAAqB,CAE5C,GAAIA,EAAU,SAAW,QAAUA,EAAU,SAAU,CACrD,IAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,OAAS,OACdA,EAAK,OAASD,EAAU,YACxB,OAAW,CAACE,EAAKC,CAAK,IAAK,OAAO,QAAQH,EAAU,QAAQ,EAAG,CAC7D,IAAMI,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,KAAO,SACbA,EAAM,KAAOF,EACbE,EAAM,MAAQD,EACdF,EAAK,YAAYG,CAAK,CACxB,CACA,SAAS,KAAK,YAAYH,CAAI,EAC9BA,EAAK,OAAO,CACd,MACE,OAAO,SAAS,KAAOD,EAAU,YAGnC,OAAOA,CACT,CAEA,OAAIA,EAAU,SAAW,aACvBhB,GAAAD,EAAAL,EAAW,UAAX,YAAAK,EAAoB,mBAApB,MAAAC,EAAA,KAAAD,EAAuCiB,GAC9BA,EAAU,SAAW,WAC9BzB,EAAS,IAAI,MAAMyB,EAAU,KAAK,CAAC,GACnCd,GAAAD,EAAAP,EAAW,UAAX,YAAAO,EAAoB,kBAApB,MAAAC,EAAA,KAAAD,EAAsCe,IAGjCA,CACT,OAAST,EAAK,CACZ,IAAMc,EAAId,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D,OAAAhB,EAAS8B,CAAC,EACH,CAAE,OAAQ,SAAU,MAAOA,EAAE,OAAQ,CAC9C,QAAE,CACAlC,EAAgB,EAAK,CACvB,CACF,EACA,CAACT,CAAM,CACT,EAKM4C,KAAY,eACXC,GACH,SAAwB,CACtBpC,EAAgB,EAAI,EACpBI,EAAS,IAAI,EACb,GAAI,CAEF,OADU,MAAMgC,EAAG,CAErB,OAAShB,EAAK,CACZ,IAAMc,EAAId,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D,MAAAhB,EAAS8B,CAAC,EACJA,CACR,QAAE,CACAlC,EAAgB,EAAK,CACvB,CACF,EACF,CAAC,CACH,EAEMqC,KAAM,eACV,MAAOd,GAAyC,CAC9CvB,EAAgB,EAAI,EACpBI,EAAS,IAAI,EACb,GAAI,CACF,IAAMkC,EAAI,MAAM/C,EAAO,QAAQ,IAAIgC,CAAI,EACvC,OAAArB,EAAUoC,CAAC,EACJA,CACT,OAASlB,EAAK,CACZ,IAAMc,EAAId,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D,MAAAhB,EAAS8B,CAAC,EACJA,CACR,QAAE,CACAlC,EAAgB,EAAK,CACvB,CACF,EACA,CAACT,CAAM,CACT,EAEMgD,KAAe,eAClBC,GACCjD,EAAO,QAAQ,aAAaiD,CAAI,EAClC,CAACjD,CAAM,CACT,EAEMkD,KAAkB,eACtB,MAAOlB,GAAgE,CAErE,IAAMe,EAAI,MADCH,EAAU,IAAM5C,EAAO,QAAQ,gBAAgBgC,CAAI,CAAC,EAC5C,EACnB,OAAArB,EAAUoC,CAAC,EACJA,CACT,EACA,CAAC/C,EAAQ4C,CAAS,CACpB,EAEMO,MAAmB,eACvB,MAAOnB,GAAgE,CAErE,IAAMe,EAAI,MADCH,EAAU,IAAM5C,EAAO,QAAQ,iBAAiBgC,CAAI,CAAC,EAC7C,EACnB,OAAArB,EAAUoC,CAAC,EACJA,CACT,EACA,CAAC/C,EAAQ4C,CAAS,CACpB,EAEMQ,MAAa,eACjB,MAAOpB,GAAoF,CAEzF,IAAMe,EAAI,MADCH,EAAU,IAAM5C,EAAO,QAAQ,WAAWgC,CAAI,CAAC,EACvC,EACnB,OAAArB,EAAUoC,CAAC,EACJA,CACT,EACA,CAAC/C,EAAQ4C,CAAS,CACpB,EAEMS,MAAa,eAChBjC,GAAsBpB,EAAO,QAAQ,kBAAkBoB,CAAS,EACjE,CAACpB,CAAM,CACT,EAEA,MAAO,CACL,aAAAE,EACA,eAAAE,EACA,YAAAE,EACA,aAAAE,EACA,OAAAE,EACA,MAAAE,EACA,iBAAAkB,EACA,eAAAO,EACA,IAAAS,EACA,aAAAE,EACA,gBAAAE,EACA,iBAAAC,GACA,WAAAC,GACA,WAAAC,EACF,CACF,CCtWA,IAAAC,EAAsC,WAyE/B,SAASC,IAA6B,CAC3C,IAAMC,EAASC,EAAkB,EAC3B,CAACC,EAAOC,CAAQ,KAAI,YAAuB,IAAI,EAC/C,CAACC,EAASC,CAAU,KAAI,YAA8B,IAAI,EAC1D,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,KAAI,YAAuB,IAAI,EAE/CC,KAAO,eAAY,MAAUC,GAAqC,CACtEJ,EAAa,EAAI,EACjBE,EAAS,IAAI,EACb,GAAI,CACF,OAAO,MAAME,EAAG,CAClB,OAASC,EAAK,CACZ,IAAMC,EAAID,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D,MAAAH,EAASI,CAAC,EACJA,CACR,QAAE,CACAN,EAAa,EAAK,CACpB,CACF,EAAG,CAAC,CAAC,EAECO,KAAW,eACdC,GACCL,EAAK,SAAY,CACf,IAAMM,EAAI,MAAMhB,EAAO,OAAO,SAASe,CAAO,EAC9C,OAAAZ,EAASa,CAAC,EACHA,CACT,CAAC,EACH,CAAChB,EAAQU,CAAI,CACf,EAEMO,KAAa,eAChBC,GACClB,EAAO,OAAO,WAAWkB,CAAI,EAC/B,CAAClB,CAAM,CACT,EAEMmB,KAAe,eAClBD,GACCR,EAAK,SAAY,CACf,IAAMU,EAAI,MAAMpB,EAAO,OAAO,aAAakB,CAAI,EAC/C,OAAAb,EAAWe,CAAC,EACLA,CACT,CAAC,EACH,CAACpB,EAAQU,CAAI,CACf,EAEMW,KAAoB,eACvBH,GAOKR,EAAK,IAAMV,EAAO,OAAO,kBAAkBkB,CAAI,CAAC,EACtD,CAAClB,EAAQU,CAAI,CACf,EAEMY,KAAkB,eACrBJ,GACClB,EAAO,OAAO,gBAAgBkB,CAAI,EACpC,CAAClB,CAAM,CACT,EAEMuB,KAAyB,eAC5BC,GAAoBxB,EAAO,OAAO,uBAAuBwB,CAAO,EACjE,CAACxB,CAAM,CACT,EAEMyB,KAA0B,eAC7BP,GACCR,EAAK,IAAMV,EAAO,OAAO,wBAAwBkB,CAAI,CAAC,EACxD,CAAClB,EAAQU,CAAI,CACf,EAEMgB,KAA2B,eAC9BR,GACCR,EAAK,IAAMV,EAAO,OAAO,yBAAyBkB,CAAI,CAAC,EACzD,CAAClB,EAAQU,CAAI,CACf,EAEA,MAAO,CACL,MAAAR,EACA,QAAAE,EACA,UAAAE,EACA,MAAAE,EACA,SAAAM,EACA,WAAAG,EACA,aAAAE,EACA,kBAAAE,EACA,gBAAAC,EACA,uBAAAC,EACA,wBAAAE,EACA,yBAAAC,CACF,CACF,CCzKA,IAAAC,EAAiD,WA8B1C,SAASC,GAAYC,EAA+C,CACzE,IAAMC,EAASC,EAAkB,EAC3B,CAACC,EAAUC,CAAW,KAAI,YAA0B,IAAI,EACxD,CAACC,EAAQC,CAAS,KAAI,YAAkB,CAAC,CAAC,EAC1C,CAACC,EAAeC,CAAgB,KAAI,YAAyB,CAAC,CAAC,EAC/D,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,KAAI,YAAuB,IAAI,EAE/CC,KAAe,eAAY,MAAOC,GAAe,CACrDJ,EAAa,EAAI,EACjBE,EAAS,IAAI,EACb,GAAI,CACF,IAAMG,EAAI,MAAMd,EAAO,SAAS,WAAWa,CAAE,EAC7CV,EAAYW,CAAC,CACf,OAASC,EAAK,CACZJ,EAASI,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,QAAE,CACAN,EAAa,EAAK,CACpB,CACF,EAAG,CAACT,CAAM,CAAC,EAELgB,KAAa,eAAY,MAAOH,GAAe,CACnD,GAAI,CACF,IAAMI,EAAM,MAAMjB,EAAO,SAAS,UAAUa,CAAE,EAC9CR,EAAUY,EAAI,MAAM,CACtB,OAASF,EAAK,CACZJ,EAASI,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,CACF,EAAG,CAACf,CAAM,CAAC,EAELkB,KAAoB,eAAY,MAAOL,GAAe,CAC1D,GAAI,CACF,IAAMM,EAAO,MAAMnB,EAAO,SAAS,iBAAiBa,CAAE,EACtDN,EAAiBY,CAAI,CACvB,OAASJ,EAAK,CACZJ,EAASI,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,CACF,EAAG,CAACf,CAAM,CAAC,EAELoB,KAAgB,eAAY,MAChCP,EACAQ,IACG,CACH,GAAI,CACF,IAAMC,EAAU,MAAMtB,EAAO,SAAS,cAAca,EAAIQ,CAAI,EAC5DlB,EAAYmB,CAAO,CACrB,OAASP,EAAK,CACZJ,EAASI,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC9D,CACF,EAAG,CAACf,CAAM,CAAC,EAEX,sBAAU,IAAM,CACVD,GAAYa,EAAab,CAAU,CACzC,EAAG,CAACA,EAAYa,CAAY,CAAC,EAEtB,CACL,SAAAV,EACA,OAAAE,EACA,cAAAE,EACA,UAAAE,EACA,MAAAE,EACA,aAAAE,EACA,WAAAI,EACA,kBAAAE,EACA,cAAAE,CACF,CACF,CChGA,IAAAG,EAAsC,WAwB/B,SAASC,IAA+B,CAC7C,IAAMC,EAASC,EAAkB,EAC3B,CAACC,EAAUC,CAAW,KAAI,YAA2B,CAAC,CAAC,EACvD,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,KAAI,YAAuB,IAAI,EAE/CC,KAAe,eAAY,MAAOC,GAA4D,CAClGJ,EAAa,EAAI,EACjBE,EAAS,IAAI,EACb,GAAI,CACF,IAAMG,EAAQ,MAAMV,EAAO,QAAQ,YAAYS,CAAI,EACnD,OAAAN,EAAYO,CAAK,EACVA,CACT,OAASC,EAAK,CACZ,IAAMC,EAAID,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D,MAAAJ,EAASK,CAAC,EACJA,CACR,QAAE,CACAP,EAAa,EAAK,CACpB,CACF,EAAG,CAACL,CAAM,CAAC,EAELa,KAAc,eAAY,MAAOC,GAAsB,CAC3DT,EAAa,EAAI,EACjBE,EAAS,IAAI,EACb,GAAI,CACF,OAAO,MAAMP,EAAO,QAAQ,WAAWc,CAAS,CAClD,OAASH,EAAK,CACZ,IAAMC,EAAID,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D,MAAAJ,EAASK,CAAC,EACJA,CACR,QAAE,CACAP,EAAa,EAAK,CACpB,CACF,EAAG,CAACL,CAAM,CAAC,EAEX,MAAO,CACL,SAAAE,EACA,UAAAE,EACA,MAAAE,EACA,aAAAE,EACA,YAAAK,CACF,CACF,CC9DA,IAAAE,EAAyD,WCsDzD,IAAIC,GAAiB,GACjBC,GAAc,GACZC,GAAoC,CAAC,EAE3C,SAASC,IAAgB,CACvBF,GAAc,GACd,QAAWG,KAAMF,GAAgBE,EAAG,EACpCF,GAAe,OAAS,CAC1B,CAMO,SAASG,EACdC,EACAC,EAAiE,CAAC,EACnD,CA5EjB,IAAAC,EAAAC,EA6EE,OAAIR,KAAeQ,GAAAD,EAAA,OAAO,SAAP,YAAAA,EAAe,OAAf,MAAAC,EAAqB,QACtCN,GAAc,EACP,QAAQ,QAAQ,GAGrBH,GACK,IAAI,QAAeU,GAAYR,GAAe,KAAKQ,CAAO,CAAC,GAGpEV,GAAiB,GAEV,IAAI,QAAc,CAACU,EAASC,IAAW,CAI5C,GAHAT,GAAe,KAAKQ,CAAO,EAEV,SAAS,cAAc,oCAAoC,EAC9D,CACZ,IAAME,EAAO,IAAM,CA7FzB,IAAAJ,EAAAC,GA8FYA,GAAAD,EAAA,OAAO,SAAP,YAAAA,EAAe,OAAf,MAAAC,EAAqB,OAAUN,GAAc,EAC1C,WAAWS,EAAM,GAAG,CAC7B,EACAA,EAAK,EACL,MACF,CAEA,IAAMC,EAAS,IAAI,gBAAgB,CACjC,IAAKP,EACL,UAAW,SACX,EAAGC,EAAK,SAAW,QACrB,CAAC,EACGA,EAAK,UAAUM,EAAO,IAAI,WAAYN,EAAK,QAAQ,EACnDA,EAAK,QAAQM,EAAO,IAAI,SAAUN,EAAK,MAAM,EAEjD,IAAMO,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAM,2CAA2CD,CAAM,GAC9DC,EAAO,MAAQ,GACfA,EAAO,MAAQ,GACfA,EAAO,OAAS,IAAMX,GAAc,EACpCW,EAAO,QAAU,IAAMH,EAAO,IAAI,MAAM,mCAAmC,CAAC,EAC5E,SAAS,KAAK,YAAYG,CAAM,CAClC,CAAC,EACH,CAMO,IAAMC,EAAN,MAAMC,CAAuB,CAElC,aAAa,aACXC,EACAC,EAA6E,CAAC,EACjD,CAhIjC,IAAAV,EAAAC,EAiII,GAAI,GAACA,GAAAD,EAAA,OAAO,SAAP,YAAAA,EAAe,OAAf,MAAAC,EAAqB,SAAU,CAACQ,EAAM,KAAK,EAAG,MAAO,CAAC,EAE3D,IAAME,EAAU,IAAI,OAAO,OAAO,KAAK,OAAO,oBAC9C,OAAO,IAAI,QAAST,GAAY,CAC9BS,EAAQ,oBACN,CAAE,MAAAF,EAAO,MAAOC,EAAQ,OAAS,CAAC,SAAS,EAAG,sBAAuBA,EAAQ,qBAAsB,EACnG,CAACE,EAAwCC,IAAmB,CAvIpE,IAAAb,EAAAC,EAAAa,EAwIUZ,EAAQW,MAAWC,GAAAb,GAAAD,EAAA,OAAO,SAAP,YAAAA,EAAe,OAAf,YAAAC,EAAqB,SAArB,YAAAa,EAA6B,oBAAoB,KAAMF,EAAcA,EAAc,CAAC,CAAC,CAC1G,CACF,CACF,CAAC,CACH,CAGA,aAAa,gBAAgBG,EAAqD,CA/IpF,IAAAf,EAAAC,EAgJI,GAAI,GAACA,GAAAD,EAAA,OAAO,SAAP,YAAAA,EAAe,OAAf,MAAAC,EAAqB,QAAQ,OAAO,KAEzC,IAAMe,EAAM,IAAI,OAAO,OAAO,KAAK,OAAO,cAAc,SAAS,cAAc,KAAK,CAAC,EACrF,OAAO,IAAI,QAASd,GAAY,CAC9Bc,EAAI,WACF,CAAE,QAAAD,EAAS,OAAQ,CAAC,WAAY,oBAAqB,qBAAsB,UAAU,CAAE,EACvF,CAACE,EAAkCJ,IAAmB,CAtJ9D,IAAAb,EAAAC,EAAAa,EAuJUZ,EAAQW,MAAWC,GAAAb,GAAAD,EAAA,OAAO,SAAP,YAAAA,EAAe,OAAf,YAAAC,EAAqB,SAArB,YAAAa,EAA6B,oBAAoB,KAAMG,EAAQA,EAAQ,IAAI,CAChG,CACF,CACF,CAAC,CACH,CAGA,OAAO,yBAAyBA,EAA6C,CAC3E,IAAMC,EAAwB,CAC5B,WAAY,GAAI,aAAc,GAAI,MAAO,GAAI,SAAU,GACvD,yBAA0B,GAAI,6BAA8B,GAC5D,yBAA0B,GAAI,6BAA8B,GAC5D,QAAS,GAAI,WAAY,GAAI,kBAAmB,EAClD,EAEIC,EAAU,GACVC,EAAe,GACfC,EAAe,GAAIC,EAAe,GAAIC,EAAe,GAAIC,EAAe,GAAIC,EAAe,GAC3FC,EAAa,GAEjB,QAAWC,KAAKV,EAAM,oBAAsB,CAAC,EAAG,CAC9C,IAAMW,EAAID,EAAE,MACRC,EAAE,SAAS,YAAY,IAAoBV,EAAI,WAAaS,EAAE,WAC9DC,EAAE,SAAS,eAAe,IAAiBV,EAAI,aAAeS,EAAE,WAChEC,EAAE,SAAS,SAAS,IAAuBT,EAAUQ,EAAE,WACvDC,EAAE,SAAS,OAAO,IAAyBV,EAAI,MAAQS,EAAE,WACzDC,EAAE,SAAS,cAAc,IAAkBR,EAAeO,EAAE,WAC5DC,EAAE,SAAS,qBAAqB,IAAWP,EAAeM,EAAE,WAC5DC,EAAE,SAAS,qBAAqB,IAAWN,EAAeK,EAAE,WAC5DC,EAAE,SAAS,qBAAqB,IAAWL,EAAeI,EAAE,WAC5DC,EAAE,SAAS,qBAAqB,IAAWJ,EAAeG,EAAE,WAC5DC,EAAE,SAAS,qBAAqB,IAAWH,EAAeE,EAAE,WAC5DC,EAAE,SAAS,UAAU,IAAsBV,EAAI,SAAWS,EAAE,WAC5DC,EAAE,SAAS,aAAa,IAAmBF,EAAaC,EAAE,WAC1DC,EAAE,SAAS,6BAA6B,IAC1CV,EAAI,yBAA2BS,EAAE,WACjCT,EAAI,6BAA+BS,EAAE,WAEnCC,EAAE,SAAS,6BAA6B,IAC1CV,EAAI,yBAA2BS,EAAE,WACjCT,EAAI,6BAA+BS,EAAE,WAEnCC,EAAE,SAAS,SAAS,IAAQV,EAAI,QAAUS,EAAE,YAC5CC,EAAE,SAAS,aAAa,IAAIV,EAAI,WAAaS,EAAE,UACrD,CAGKT,EAAI,WAAUA,EAAI,SAAWQ,GAAcF,GAAgBC,GAAgB,IAG5E,CAACP,EAAI,0BAA4BA,EAAI,2BACvCA,EAAI,yBAA2BA,EAAI,8BAAgCA,EAAI,yBACvEA,EAAI,6BAA+BA,EAAI,8BAIzC,IAAMW,EAAiBX,EAAI,cAAgBC,EACrCW,EAAaZ,EAAI,OAASG,GAAgBC,GAAgBC,GAAgBH,EAEhF,GAAIF,EAAI,YAAcW,GAAkBC,EACtCZ,EAAI,kBAAoB,GAAGA,EAAI,UAAU,IAAIW,CAAc,IAAIC,CAAU,WAChED,GAAkBC,EAC3B,GAAIX,GAAWG,GAAgBC,EAAc,CAC3C,IAAIQ,EAAO,GAAGR,CAAY,IAAID,CAAY,IAAIH,CAAO,GACjDK,IAAcO,EAAO,GAAGA,CAAI,IAAIP,CAAY,IAChDN,EAAI,kBAAoBa,CAC1B,MACEb,EAAI,kBAAoB,GAAGW,CAAc,IAAIC,CAAU,QAEhDA,EACTZ,EAAI,kBAAoBY,EACfD,IACTX,EAAI,kBAAoBW,GAG1B,OAAAX,EAAI,kBAAoBA,EAAI,kBAAkB,KAAK,EAC5CA,CACT,CAGA,OAAO,wBAAwBD,EAA6C,CAC1E,IAAMe,EAAIxB,EAAuB,yBAAyBS,CAAK,EAC/D,MAAO,CACL,SAAUe,EAAE,kBACZ,KAAMA,EAAE,SACR,QAASA,EAAE,QACX,MAAOA,EAAE,yBACT,OAAQA,EAAE,UACZ,CACF,CACF,ED5MO,SAASC,GAAsBC,EAAoE,CACxG,GAAM,CAAE,OAAAC,EAAQ,SAAAC,EAAU,OAAAC,EAAQ,QAAAC,EAAS,MAAAC,EAAQ,EAAM,EAAIL,EAEvD,CAACM,EAAaC,CAAc,KAAI,YAA6B,CAAC,CAAC,EAC/D,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAK,EAC1C,CAACC,EAAgBC,CAAiB,KAAI,YAAS,EAAK,EACpDC,KAAc,UAA6C,IAAI,EAC/DC,KAAa,UAAmD,IAAI,EAEpEC,KAAS,eAAY,IAAM,CAC/BC,EAAqBd,EAAQ,CAAE,SAAAC,EAAU,OAAAC,EAAQ,QAAAC,CAAQ,CAAC,EAAE,KAAK,IAAMO,EAAkB,EAAI,CAAC,CAChG,EAAG,CAACV,EAAQC,EAAUC,EAAQC,CAAO,CAAC,KAGtC,aAAU,IAAM,CACV,CAACH,GAAUI,GACfS,EAAO,CACT,EAAG,CAACb,EAAQI,EAAOS,CAAM,CAAC,KAG1B,aAAU,IAAM,CACd,GAAIJ,GAAkBG,EAAW,QAAS,CACxC,GAAM,CAAE,MAAAG,EAAO,QAAAC,CAAQ,EAAIJ,EAAW,QACtCA,EAAW,QAAU,KACrBK,EAASF,EAAOC,CAAO,CACzB,CAEF,EAAG,CAACP,CAAc,CAAC,EAEnB,IAAMQ,KAAW,eACf,CAACF,EAAeG,IAAgC,CAC9C,GAAI,CAACT,EAAgB,CACfL,IAASQ,EAAW,QAAU,CAAE,MAAAG,EAAO,QAASG,CAAmB,EAAGL,EAAO,GACjF,MACF,CAEA,GAAIE,EAAM,OAAS,EAAG,CAAET,EAAe,CAAC,CAAC,EAAG,MAAQ,CAEhDK,EAAY,SAAS,aAAaA,EAAY,OAAO,EACzDA,EAAY,QAAU,WAAW,SAAY,CAC3CH,EAAa,EAAI,EACjB,IAAMW,EAAU,MAAMC,EAAuB,aAAaL,EAAO,CAC/D,sBAAuBG,EAAqB,CAAE,QAASA,EAAmB,YAAY,CAAE,EAAI,MAC9F,CAAC,EACDZ,EAAea,CAAO,EACtBX,EAAa,EAAK,CACpB,EAAG,GAAG,CACR,EACA,CAACC,EAAgBL,EAAOS,CAAM,CAChC,EAEMQ,KAAkB,eACrBC,GAAoBF,EAAuB,gBAAgBE,CAAO,EACnE,CAAC,CACH,EAEMC,KAA2B,eAC9BC,GAA8BJ,EAAuB,yBAAyBI,CAAK,EACpF,CAAC,CACH,EAEMC,KAA0B,eAC7BD,GAA8BJ,EAAuB,wBAAwBI,CAAK,EACnF,CAAC,CACH,EAEME,KAAmB,eAAY,IAAMpB,EAAe,CAAC,CAAC,EAAG,CAAC,CAAC,EAEjE,MAAO,CACL,YAAAD,EACA,UAAAE,EACA,eAAAE,EACA,aAAcQ,EACd,gBAAAI,EACA,yBAAAE,EACA,wBAAAE,EACA,iBAAAC,CACF,CACF,CE9GA,IAAAC,EAA0D,WCK1D,IAAMC,GAAmB,qEAEZC,GAAsB,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAI,EAmB1GC,EAAiB,IAAI,IACrBC,GAAiB,IAAI,IACrBC,GAAoB,IAAI,IACxBC,GAAoB,IAAI,IAE9B,eAAeC,GAAkBC,EAAoD,CACnF,IAAMC,EAASN,EAAe,IAAIK,CAAQ,EAC1C,GAAIC,EAAQ,OAAOA,EAEnB,IAAIC,EAAWL,GAAkB,IAAIG,CAAQ,EAC7C,OAAIE,IAEJA,GAAY,SAAY,CACtB,IAAMC,EAAM,GAAGV,EAAgB,IAAIO,CAAQ,kBACrCI,EAAM,MAAM,MAAMD,CAAG,EAC3B,GAAI,CAACC,EAAI,GAAI,MAAM,IAAI,MAAM,yBAAyBD,CAAG,KAAKC,EAAI,MAAM,GAAG,EAC3E,IAAMC,EAAqB,MAAMD,EAAI,KAAK,EAC1C,OAAAT,EAAe,IAAIK,EAAUK,CAAI,EACjCR,GAAkB,OAAOG,CAAQ,EAC1BK,CACT,GAAG,EAEHR,GAAkB,IAAIG,EAAUE,CAAQ,EACjCA,EACT,CAEA,eAAeI,GAAgBN,EAAkD,CAC/E,IAAMC,EAASL,GAAa,IAAII,CAAQ,EACxC,GAAIC,EAAQ,OAAOA,EAEnB,IAAIC,EAAWJ,GAAgB,IAAIE,CAAQ,EAC3C,OAAIE,IAEJA,GAAY,SAAY,CACtB,IAAMC,EAAM,GAAGV,EAAgB,IAAIO,CAAQ,gBACrCI,EAAM,MAAM,MAAMD,CAAG,EAC3B,GAAI,CAACC,EAAI,GAAI,MAAM,IAAI,MAAM,yBAAyBD,CAAG,KAAKC,EAAI,MAAM,GAAG,EAC3E,IAAMC,EAAmB,MAAMD,EAAI,KAAK,EACxC,OAAAR,GAAa,IAAII,EAAUK,CAAI,EAC/BP,GAAgB,OAAOE,CAAQ,EACxBK,CACT,GAAG,EAEHP,GAAgB,IAAIE,EAAUE,CAAQ,EAC/BA,EACT,CAEA,SAASK,GAAmBP,EAA2C,CACrE,OAAOL,EAAe,IAAIK,CAAQ,GAAKL,EAAe,IAAI,IAAI,GAAK,CAAC,CACtE,CAEA,SAASa,GAAiBR,EAAyC,CACjE,OAAOJ,GAAa,IAAII,CAAQ,GAAKJ,GAAa,IAAI,IAAI,GAAK,CAAC,CAClE,CAGA,eAAsBa,EAAoBT,EAA8B,KAAqB,CAC3F,MAAM,QAAQ,IAAI,CAACD,GAAkBC,CAAQ,EAAGM,GAAgBN,CAAQ,CAAC,CAAC,CAC5E,CAEO,IAAMU,GAAe,CAACV,EAA8B,OAAoB,CAC7E,IAAMW,EAAMJ,GAAmBP,CAAQ,EACvC,OAAO,OAAO,QAAQW,CAAG,EACtB,IAAI,CAAC,CAACC,EAAMC,CAAC,KAAO,CAAE,KAAAD,EAAM,KAAMC,EAAE,EAAG,KAAMA,EAAE,GAAI,QAASA,EAAE,EAAG,EAAE,EACnE,KAAK,CAACC,EAAGC,IAAMD,EAAE,KAAK,cAAcC,EAAE,IAAI,CAAC,CAChD,EAEaC,GAAsB,CAACC,EAAqBjB,EAA8B,OAAkB,CAEvG,IAAMkB,EADMV,GAAiBR,CAAQ,EAClBiB,CAAW,EAC9B,OAAKC,EACEA,EACJ,IAAI,CAAC,CAACC,EAAKC,CAAI,KAAO,CAAE,KAAMD,EAAK,KAAAC,EAAM,YAAAH,CAAY,EAAE,EACvD,KAAK,CAACH,EAAGC,IAAMD,EAAE,KAAK,cAAcC,EAAE,IAAI,CAAC,EAH1B,CAAC,CAIvB,EAEO,SAASM,EAAiBrB,EAAsC,CACrE,OAAOL,EAAe,IAAIK,CAAQ,CACpC,CC9EO,IAAMsB,EAAN,MAAMC,CAAY,CAEvB,OAAO,aAAaC,EAA8B,KAAqB,CACrE,OAAOC,EAAoBD,CAAQ,CACrC,CAGA,OAAO,aAAaA,EAA8B,KAAkC,CAClF,IAAME,EAAMC,GAAaH,CAAQ,EAC3BI,EAAqC,CAAC,EAC5C,QAAWC,KAAKH,EACdE,EAAOC,EAAE,IAAI,EAAI,CAAE,IAAKA,EAAE,KAAM,KAAMA,EAAE,MAAQ,GAAI,QAASA,EAAE,SAAW,EAAG,KAAMA,EAAE,IAAK,EAE5F,OAAOD,CACT,CAGA,OAAO,kBAAkBJ,EAA8B,KAA+C,CACpG,OAAOG,GAAaH,CAAQ,EAAE,IAAKK,IAAO,CAAE,MAAOA,EAAE,KAAM,MAAOA,EAAE,IAAK,EAAE,CAC7E,CAGA,OAAO,WAAWC,EAAqBN,EAA8B,KAAmB,CACtF,OAAOO,GAAoBD,EAAaN,CAAQ,EAAE,IAAKQ,IAAO,CAAE,IAAKA,EAAE,KAAM,KAAMA,EAAE,IAAK,EAAE,CAC9F,CAGA,OAAO,iBAAiBF,EAAqBN,EAA8B,KAA+C,CACxH,OAAOD,EAAY,WAAWO,EAAaN,CAAQ,EAAE,IAAK,IAAO,CAAE,MAAO,EAAE,IAAK,MAAO,EAAE,IAAK,EAAE,CACnG,CAGA,OAAO,WAAWM,EAAqBG,EAAoBT,EAA8B,KAAwB,CAC/G,OAAOD,EAAY,WAAWO,EAAaN,CAAQ,EAAE,KAAMU,GAAMA,EAAE,MAAQD,CAAU,GAAK,IAC5F,CAMA,OAAO,eACLE,EACAC,EACAN,EACAN,EAA8B,KACZ,CAClB,IAAMa,EAAUd,EAAY,WAAWO,EAAaN,CAAQ,EAC5D,GAAIa,EAAQ,SAAW,EAAG,OAAO,KAEjC,IAAIC,EAAQD,EAAQ,KAAMH,GAAMA,EAAE,MAAQC,CAAW,EAOrD,OANIG,IAEJA,EAAQD,EAAQ,KAAMH,GAAMA,EAAE,KAAK,YAAY,IAAMC,EAAY,YAAY,CAAC,EAC1EG,KAEJA,EAAQD,EAAQ,KAAMH,GAAMA,EAAE,KAAK,YAAY,IAAME,EAAgB,YAAY,CAAC,EAC9EE,GAAcA,GAElBA,EAAQD,EAAQ,KACbH,GACCA,EAAE,KAAK,YAAY,EAAE,SAASE,EAAgB,YAAY,CAAC,GAC3DA,EAAgB,YAAY,EAAE,SAASF,EAAE,KAAK,YAAY,CAAC,CAC/D,EAEOI,GAAS,KAClB,CAEA,OAAO,iBAAiBd,EAAsC,CAC5D,OAAOe,EAAiBf,CAAQ,CAClC,CAEA,OAAO,uBAAsD,CAC3D,OAAOgB,EACT,CACF,EF7EO,SAASC,GAAWC,EAA8B,KAAwB,CAC/E,GAAM,CAACC,EAAUC,CAAW,KAAI,YAASC,EAAiBH,CAAQ,CAAC,EAEnE,sBAAU,IAAM,CACd,IAAII,EAAY,GAChB,OAAAC,EAAoBL,CAAQ,EACzB,KAAK,IAAM,CAAOI,GAAWF,EAAY,EAAI,CAAG,CAAC,EACjD,MAAOI,GAAQ,QAAQ,MAAM,yCAA0CA,CAAG,CAAC,EACvE,IAAM,CAAEF,EAAY,EAAM,CACnC,EAAG,CAACJ,CAAQ,CAAC,KAEN,WAAQ,IACRC,EAUE,CACL,UAAWM,EAAY,aAAaP,CAAQ,EAC5C,WAAaQ,GAAeD,EAAY,WAAWC,EAAIR,CAAQ,EAC/D,WAAY,CAACQ,EAAYC,IAAeF,EAAY,WAAWC,EAAIC,EAAIT,CAAQ,EAC/E,eAAgB,CAACU,EAAYC,EAAaH,IAAeD,EAAY,eAAeG,EAAIC,EAAKH,EAAIR,CAAQ,EACzG,SAAU,EACZ,EAfS,CACL,UAAW,CAAC,EACZ,WAAY,IAAM,CAAC,EACnB,WAAY,IAAM,KAClB,eAAgB,IAAM,KACtB,SAAU,EACZ,EAUD,CAACA,EAAUC,CAAQ,CAAC,CACzB,CAMO,SAASW,GAAkBZ,EAA8B,KAA+C,CAC7G,GAAM,CAAE,UAAAa,EAAW,SAAAZ,CAAS,EAAIF,GAAWC,CAAQ,EACnD,SAAO,WAAQ,IACRC,EACE,OAAO,OAAOY,CAAS,EAC3B,IAAKC,IAAO,CAAE,MAAOA,EAAE,IAAK,MAAOA,EAAE,IAAK,EAAE,EAC5C,KAAK,CAACC,EAAGC,IAAMD,EAAE,MAAM,cAAcC,EAAE,KAAK,CAAC,EAH1B,CAAC,EAItB,CAACH,EAAWZ,CAAQ,CAAC,CAC1B,CAMO,SAASgB,GACdC,EACAlB,EAA8B,KACW,CACzC,GAAM,CAAE,WAAAmB,EAAY,SAAAlB,CAAS,EAAIF,GAAWC,CAAQ,EACpD,SAAO,WAAQ,IACT,CAACC,GAAY,CAACiB,EAAoB,CAAC,EAChCC,EAAWD,CAAW,EAC1B,IAAKE,IAAO,CAAE,MAAOA,EAAE,IAAK,MAAOA,EAAE,IAAK,EAAE,EAC5C,KAAK,CAACL,EAAGC,IAAMD,EAAE,MAAM,cAAcC,EAAE,KAAK,CAAC,EAC/C,CAACE,EAAaC,EAAYlB,CAAQ,CAAC,CACxC,CG7EA,IAAMoB,GAAkC,CACtC,IAAK,IAAK,IAAK,SAAK,IAAK,OAAK,IAAK,OAAK,IAAK,KAAM,IAAK,KAAM,IAAK,MACnE,IAAK,OAAK,IAAK,KAAM,IAAK,KAAM,IAAK,KAAM,IAAK,UAAM,IAAK,UAAM,IAAK,KACtE,IAAK,MAAO,IAAK,eAAM,IAAK,KAAM,IAAK,SAAK,IAAK,SAAK,IAAK,SAAK,IAAK,KACrE,IAAK,IAAK,IAAK,IAAK,IAAK,SAAK,IAAK,SAAK,IAAK,SAAK,IAAK,SAAK,IAAK,KACjE,IAAK,KAAM,IAAK,KAAM,IAAK,SAAK,IAAK,MAAO,IAAK,MAAO,IAAK,SAAK,IAAK,gBACvE,IAAK,gBAAO,IAAK,gBAAO,IAAK,gBAAO,IAAK,gBAAO,IAAK,iBAAQ,IAAK,OAClE,IAAK,SAAK,IAAK,MAAO,IAAK,SAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KACnE,IAAK,SAAK,IAAK,MAAO,IAAK,KAAM,IAAK,KAAM,IAAK,SAAK,IAAK,IAC3D,IAAK,KAAM,IAAK,MAAO,IAAK,SAAK,IAAK,SAAK,IAAK,SAAK,IAAK,SAC1D,IAAK,SAAK,IAAK,SAAK,IAAK,SAAK,IAAK,QACrC,EAEMC,GAAgC,CACpC,IAAK,YAAa,IAAK,OAAQ,IAAK,gBAAiB,IAAK,eAC1D,IAAK,kBAAmB,IAAK,oBAAqB,IAAK,cACvD,IAAK,eAAgB,IAAK,gBAAiB,IAAK,kBAChD,IAAK,eAAgB,IAAK,eAAgB,IAAK,eAAgB,IAAK,mBACpE,IAAK,iBAAkB,IAAK,eAAgB,IAAK,eAAgB,IAAK,mBACtE,IAAK,YAAa,IAAK,mBAAoB,IAAK,mBAAoB,IAAK,gBACzE,IAAK,iBAAkB,IAAK,aAAc,IAAK,cAAe,IAAK,qBACnE,IAAK,eAAgB,IAAK,gBAAiB,IAAK,gBAClD,EAEMC,GAA4B,IAAI,IAAI,CACxC,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,KACnD,CAAC,EAEYC,EAAN,MAAMC,CAAc,CACzB,OAAO,UAAUC,EAAsB,CACrC,OAAOL,GAAQK,CAAI,GAAKA,CAC1B,CAEA,OAAO,QAAQA,EAAsB,CACnC,OAAOJ,GAAMI,CAAI,GAAKA,CACxB,CAEA,OAAO,iBAAiBA,EAAsB,CAC5C,OAAOH,GAAa,IAAIG,CAAI,EAAI,EAAI,CACtC,CAEA,OAAO,YAAYA,EAAwB,CACzC,MAAO,CACL,KAAAA,EACA,OAAQD,EAAc,UAAUC,CAAI,EACpC,KAAMD,EAAc,QAAQC,CAAI,EAChC,cAAeD,EAAc,iBAAiBC,CAAI,CACpD,CACF,CACF,EAUO,SAASC,GAAYC,EAA0BC,EAAe,MAAOC,EAAS,QAAiB,CACpG,IAAMC,EAAWP,EAAc,iBAAiBK,CAAY,EACtDG,EAAQJ,GAAoBG,IAAa,EAAI,IAAM,KAAK,IAAI,GAAIA,CAAQ,GAE9E,GAAI,CACF,OAAO,IAAI,KAAK,aAAaD,EAAQ,CACnC,MAAO,WACP,SAAUD,EACV,sBAAuBE,EACvB,sBAAuBA,CACzB,CAAC,EAAE,OAAOC,CAAK,CACjB,MAAQ,CACN,MAAO,GAAGR,EAAc,UAAUK,CAAY,CAAC,GAAGG,EAAM,QAAQD,CAAQ,CAAC,EAC3E,CACF",
4
+ "sourcesContent": ["export { TagadaHeadlessProvider, useHeadlessClient } from './provider.js';\nexport type { TagadaHeadlessProviderProps } from './provider.js';\n\nexport { useCheckout } from './hooks/useCheckout.js';\nexport type { UseCheckoutReturn } from './hooks/useCheckout.js';\n\nexport { usePayment } from './hooks/usePayment.js';\nexport type { UsePaymentReturn, UsePaymentOptions } from './hooks/usePayment.js';\n\nexport { useOffers } from './hooks/useOffers.js';\nexport type { UseOffersReturn } from './hooks/useOffers.js';\n\nexport { useCustomer } from './hooks/useCustomer.js';\nexport type { UseCustomerReturn } from './hooks/useCustomer.js';\n\nexport { useCatalog } from './hooks/useCatalog.js';\nexport type { UseCatalogReturn } from './hooks/useCatalog.js';\n\n// Helpers hooks\nexport { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete.js';\nexport type { UseGoogleAutocompleteOptions, UseGoogleAutocompleteReturn } from './hooks/useGoogleAutocomplete.js';\n\nexport { useISOData, useCountryOptions, useRegionOptions } from './hooks/useISOData.js';\nexport type { UseISODataReturn } from './hooks/useISOData.js';\n\n// Re-export helper types used by hooks\nexport type {\n GooglePrediction,\n GooglePlaceDetails,\n ExtractedAddress,\n FormattedAddress,\n SupportedLanguage,\n ISOCountry,\n ISORegion,\n Currency,\n} from '../core/helpers/index.js';\n\nexport { formatMoney, CurrencyUtils, ISODataCore, GoogleAutocompleteCore, loadGoogleMapsScript } from '../core/helpers/index.js';\n\nexport type {\n HeadlessConfig,\n Environment,\n CheckoutSession,\n CheckoutLineItem,\n CheckoutTotals,\n CheckoutCustomer,\n Address,\n ShippingRate,\n LineItem,\n PaymentSetupConfig,\n PaymentMethodConfig,\n ExpressMethods,\n ExpressMethod,\n StoreConfig,\n PayResult,\n PayOptions,\n PaymentStatus,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n Offer,\n OfferLineItem,\n OfferPreview,\n OfferPreviewItem,\n OfferPayResult,\n Customer,\n Order,\n Subscription,\n CatalogProduct,\n CatalogVariant,\n CatalogPrice,\n CurrencyOption,\n StripeExpressOptions,\n} from '../core/types.js';\n", "import React, { createContext, useContext, useMemo } from 'react';\nimport { HeadlessClient, createHeadlessClient } from '../core/client.js';\nimport type { HeadlessConfig, Environment } from '../core/types.js';\n\ninterface TagadaHeadlessContextValue {\n client: HeadlessClient;\n}\n\nconst TagadaHeadlessContext = createContext<TagadaHeadlessContextValue | null>(null);\n\nexport interface TagadaHeadlessProviderProps {\n /** Your TagadaPay store ID. */\n storeId: string;\n /** Environment. Defaults to \"production\". */\n environment?: Environment;\n /** Public API key for authenticated requests. */\n apiKey?: string;\n /** Override the base API URL. */\n baseUrl?: string;\n /** Full config object (alternative to individual props). */\n config?: HeadlessConfig;\n children: React.ReactNode;\n}\n\n/**\n * Root provider for the TagadaPay Headless SDK React integration.\n * Creates a single HeadlessClient and shares it via context.\n *\n * @example\n * ```tsx\n * <TagadaHeadlessProvider storeId=\"store_abc123\" environment=\"production\">\n * <App />\n * </TagadaHeadlessProvider>\n * ```\n */\nexport function TagadaHeadlessProvider({\n storeId,\n environment,\n apiKey,\n baseUrl,\n config,\n children,\n}: TagadaHeadlessProviderProps) {\n const client = useMemo(() => {\n const cfg: HeadlessConfig = config ?? { storeId, environment, apiKey, baseUrl };\n return createHeadlessClient(cfg);\n }, [storeId, environment, apiKey, baseUrl, config]);\n\n const value = useMemo(() => ({ client }), [client]);\n\n return (\n <TagadaHeadlessContext.Provider value={value}>\n {children}\n </TagadaHeadlessContext.Provider>\n );\n}\n\n/** Access the HeadlessClient from context. Throws if used outside the provider. */\nexport function useHeadlessClient(): HeadlessClient {\n const ctx = useContext(TagadaHeadlessContext);\n if (!ctx) {\n throw new Error('useHeadlessClient must be used within <TagadaHeadlessProvider>');\n }\n return ctx.client;\n}\n", "/** Base error for all TagadaPay headless SDK errors. */\nexport class TagadaError extends Error {\n public readonly code: string;\n public readonly statusCode?: number;\n public readonly details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'TagadaError';\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n }\n}\n\n/** Thrown when the API returns 401/403. */\nexport class TagadaAuthError extends TagadaError {\n constructor(message = 'Authentication failed. Check your API key or checkout token.') {\n super(message, 'auth_error', 401);\n this.name = 'TagadaAuthError';\n }\n}\n\n/** Thrown when the API returns 422 with validation errors. */\nexport class TagadaValidationError extends TagadaError {\n public readonly errors: Array<{ field: string; message: string }>;\n\n constructor(\n message: string,\n errors: Array<{ field: string; message: string }> = [],\n ) {\n super(message, 'validation_error', 422, { errors });\n this.name = 'TagadaValidationError';\n this.errors = errors;\n }\n}\n\n/** Thrown when a resource is not found (404). */\nexport class TagadaNotFoundError extends TagadaError {\n constructor(resource: string, id: string) {\n super(`${resource} \"${id}\" not found.`, 'not_found', 404);\n this.name = 'TagadaNotFoundError';\n }\n}\n\n/** Thrown when the API returns 429. */\nexport class TagadaRateLimitError extends TagadaError {\n public readonly retryAfterMs: number;\n\n constructor(retryAfterMs = 1000) {\n super(`Rate limited. Retry after ${retryAfterMs}ms.`, 'rate_limit', 429);\n this.name = 'TagadaRateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\n/** Thrown when a payment fails or requires action. */\nexport class TagadaPaymentError extends TagadaError {\n public readonly paymentId?: string;\n public readonly requireAction?: string;\n\n constructor(\n message: string,\n opts?: { paymentId?: string; requireAction?: string; details?: Record<string, unknown> },\n ) {\n super(message, 'payment_error', undefined, opts?.details);\n this.name = 'TagadaPaymentError';\n this.paymentId = opts?.paymentId;\n this.requireAction = opts?.requireAction;\n }\n}\n\n/** Thrown on network / fetch failures. */\nexport class TagadaNetworkError extends TagadaError {\n constructor(message = 'Network request failed. Check your connection.') {\n super(message, 'network_error');\n this.name = 'TagadaNetworkError';\n }\n}\n", "import {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaNetworkError,\n} from './errors.js';\nimport type { Environment, HttpRequestOptions } from './types.js';\n\nconst BASE_URLS: Record<Environment, string> = {\n production: 'https://api.tagada.io',\n development: 'https://api.tagada.dev',\n local: 'http://localhost:3000',\n};\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n apiKey?: string;\n getToken?: () => string | undefined;\n}\n\n/**\n * Lightweight HTTP client built on native fetch.\n * Zero dependencies -- works in browser, edge runtimes, and Node 18+.\n */\nexport class HttpClient {\n readonly baseUrl: string;\n private timeout: number;\n private apiKey?: string;\n private getToken?: () => string | undefined;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.timeout = config.timeout;\n this.apiKey = config.apiKey;\n this.getToken = config.getToken;\n }\n\n static resolveBaseUrl(environment: Environment, override?: string): string {\n return override ?? BASE_URLS[environment] ?? BASE_URLS.production;\n }\n\n async request<T = unknown>(path: string, options: HttpRequestOptions = {}): Promise<T> {\n const { method = 'GET', body, headers = {}, params, token, signal } = options;\n\n let url = `${this.baseUrl}${path}`;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined) qs.set(k, String(v));\n }\n const str = qs.toString();\n if (str) url += `?${str}`;\n }\n\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...headers,\n };\n\n const authToken = token ?? this.apiKey ?? this.getToken?.();\n if (authToken) {\n reqHeaders['x-cms-token'] = authToken;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body != null ? JSON.stringify(body) : undefined,\n signal: signal ?? controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (res.ok) {\n const text = await res.text();\n return text ? (JSON.parse(text) as T) : ({} as T);\n }\n\n await this.handleErrorResponse(res, path);\n throw new TagadaError('Unexpected error', 'unknown', res.status);\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof TagadaError) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new TagadaNetworkError(`Request to ${path} timed out after ${this.timeout}ms.`);\n }\n throw new TagadaNetworkError(\n err instanceof Error ? err.message : 'Network request failed.',\n );\n }\n }\n\n get<T = unknown>(path: string, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'GET' });\n }\n\n post<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'POST', body });\n }\n\n patch<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'PATCH', body });\n }\n\n put<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'PUT', body });\n }\n\n delete<T = unknown>(path: string, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'DELETE' });\n }\n\n private async handleErrorResponse(res: Response, path: string): Promise<never> {\n let parsed: Record<string, unknown> = {};\n try {\n parsed = (await res.json()) as Record<string, unknown>;\n } catch {\n // response isn't JSON\n }\n\n const msg =\n (parsed.message as string) ??\n (parsed.error as string) ??\n `Request failed: ${res.status} ${res.statusText} on ${path}`;\n\n switch (res.status) {\n case 401:\n case 403:\n throw new TagadaAuthError(msg);\n case 404:\n throw new TagadaNotFoundError(path, '');\n case 422: {\n const fieldErrors = Array.isArray(parsed.errors)\n ? (parsed.errors as Array<{ field: string; message: string }>)\n : [];\n throw new TagadaValidationError(msg, fieldErrors);\n }\n case 429: {\n const retryAfter = Number(res.headers.get('Retry-After') ?? '1') * 1000;\n throw new TagadaRateLimitError(retryAfter);\n }\n default:\n throw new TagadaError(msg, 'api_error', res.status, parsed);\n }\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type {\n CheckoutSession,\n LineItem,\n ShippingRate,\n Address,\n CheckoutCustomer,\n} from '../types.js';\n\n/**\n * Result returned by `updateCart()`. Mirrors the\n * `POST /checkout-sessions/:id/line-items` payload (mutation stats, NOT\n * a refreshed session). Call `loadSession()` to get an updated session.\n */\nexport interface UpdateCartResult {\n success: boolean;\n /** Number of existing line items updated. */\n updated: number;\n /** Number of new line items created. */\n created: number;\n /** Total number of line items in the cart after the mutation. */\n total: number;\n}\n\n/**\n * Manages checkout sessions \u2014 load, update cart, apply promo codes, handle shipping.\n *\n * Works for both **shipped** and **digital** products:\n *\n * **Shipped products** (physical goods):\n * ```\n * updateCustomer(id, { email, firstName, lastName })\n * updateAddress(id, { shippingAddress: { line1, city, ... } })\n * getShippingRates(id)\n * selectShippingRate(id, rateId)\n * ```\n *\n * **Digital products** (no shipping needed):\n * ```\n * updateCustomer(id, { email, firstName, lastName })\n * updateAddress(id, { billingAddress: { line1, city, country } })\n * // Skip shipping rates \u2014 go straight to payment\n * ```\n */\nexport class CheckoutModule {\n private sessionToken: string | undefined;\n private customerEmail: string | undefined;\n private customerFirstName: string | undefined;\n private customerLastName: string | undefined;\n private customerPhone: string | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly onTokenChange?: (token: string) => void,\n ) {}\n\n /**\n * Load an existing checkout session by its checkout token.\n *\n * @param checkoutToken The checkout token (from URL param `checkoutToken`).\n * @param sessionToken The JWT session token (from URL param `token`). Required for auth.\n * @param opts.currency Optional presentment currency override (e.g. 'EUR').\n * Only applied when the session has no currency set yet (first load).\n * Once set, currency is locked to the session and this param is ignored.\n *\n * Both `checkoutToken` and `sessionToken` come from the redirect URL returned by `createSession()`.\n * Example URL: `/checkout?checkoutToken=abc123&token=eyJ...`\n */\n async loadSession(\n checkoutToken: string,\n sessionToken?: string,\n opts?: { currency?: string },\n ): Promise<CheckoutSession> {\n if (sessionToken) {\n this.sessionToken = sessionToken;\n this.onTokenChange?.(sessionToken);\n }\n\n const params: Record<string, string> = { skipAsyncWait: 'false' };\n if (opts?.currency) {\n params.currency = opts.currency;\n }\n\n const raw = await this.http.get<{ checkoutSession: unknown; summary: unknown }>(\n `/api/v1/checkout-sessions/${checkoutToken}/v2`,\n {\n params,\n token: this.sessionToken,\n },\n );\n\n return this.normalizeSession(raw);\n }\n\n /**\n * Create a new checkout session.\n *\n * Returns a `checkoutToken` and `sessionToken` (JWT) needed for all subsequent calls.\n * Also returns a `checkoutUrl` (the full Tagada-hosted checkout URL, for reference).\n */\n async createSession(opts: {\n items: LineItem[];\n currency?: string;\n returnUrl?: string;\n customerEmail?: string;\n customerFirstName?: string;\n customerLastName?: string;\n }): Promise<{ checkoutUrl: string; checkoutToken: string; sessionToken: string; customerId: string }> {\n const lineItems = opts.items.map((i) => ({\n variantId: i.variantId,\n priceId: i.priceId,\n quantity: i.quantity,\n }));\n\n const body: Record<string, unknown> = {\n storeId: this.storeId,\n lineItems,\n };\n if (opts.returnUrl) body.returnUrl = opts.returnUrl;\n\n // Always send currency in customer object (backend reads customer.currency)\n const customerData: Record<string, unknown> = {};\n if (opts.currency) customerData.currency = opts.currency;\n if (opts.customerEmail) {\n customerData.email = opts.customerEmail;\n customerData.firstName = opts.customerFirstName;\n customerData.lastName = opts.customerLastName;\n }\n if (Object.keys(customerData).length > 0) {\n body.customer = customerData;\n }\n\n const res = await this.http.post<{\n checkoutUrl: string;\n checkoutToken: string;\n customerId: string;\n }>('/api/v1/checkout/session/init', body);\n\n const url = new URL(res.checkoutUrl);\n const sessionToken = url.searchParams.get('token') ?? '';\n this.sessionToken = sessionToken;\n if (sessionToken) this.onTokenChange?.(sessionToken);\n\n return {\n checkoutUrl: res.checkoutUrl,\n checkoutToken: res.checkoutToken,\n sessionToken,\n customerId: res.customerId,\n };\n }\n\n /**\n * Replace the cart items for an existing session.\n *\n * Returns a server-side mutation summary (counts of created/updated rows).\n * It does NOT return the updated `CheckoutSession` \u2014 the underlying\n * `POST /checkout-sessions/:id/line-items` endpoint never has and the\n * previous typing was a lie that quietly assigned `{ success, updated, ... }`\n * into a `CheckoutSession` slot in `useCheckout`.\n *\n * Call `loadSession()` after this if you need the refreshed session\n * (the React `useCheckout` hook does this for you).\n */\n async updateCart(sessionId: string, items: LineItem[]): Promise<UpdateCartResult> {\n return this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/line-items`,\n { items },\n { token: this.sessionToken },\n );\n }\n\n /**\n * Update customer identity (email, name, phone).\n *\n * Call this before `updateAddress()` \u2014 the SDK remembers the values and\n * includes them automatically when addresses are submitted.\n *\n * If you prefer a single call, use `updateCustomerAndAddress()` instead.\n */\n async updateCustomer(\n sessionId: string,\n customer: Partial<CheckoutCustomer>,\n ): Promise<void> {\n if (customer.email) this.customerEmail = customer.email;\n if (customer.firstName) this.customerFirstName = customer.firstName;\n if (customer.lastName) this.customerLastName = customer.lastName;\n if (customer.phone) this.customerPhone = customer.phone;\n }\n\n /**\n * Update shipping and/or billing address on the session.\n *\n * Automatically includes customer name/phone stored from `updateCustomer()`.\n * Uses the same atomic API call as the production checkout, so email,\n * customer name, and addresses are all persisted together.\n *\n * **Shipped products**: pass `shippingAddress`. If `billingAddress` is omitted,\n * the shipping address is automatically used as billing.\n *\n * **Digital products**: pass only `billingAddress` (no shipping needed).\n *\n * @example\n * // Shipped product \u2014 billing = shipping automatically\n * await checkout.updateAddress(sessionId, {\n * shippingAddress: { line1: '10 Rue de la Paix', city: 'Paris', postalCode: '75002', country: 'FR' },\n * });\n *\n * @example\n * // Digital product \u2014 billing only\n * await checkout.updateAddress(sessionId, {\n * billingAddress: { country: 'FR' },\n * });\n */\n async updateAddress(\n sessionId: string,\n addresses: { shippingAddress?: Address; billingAddress?: Address },\n ): Promise<void> {\n const shipping = this.mapAddress(addresses.shippingAddress);\n const billing = this.mapAddress(addresses.billingAddress);\n\n const effectiveShipping = shipping ?? billing ?? {};\n const effectiveBilling = billing ?? shipping;\n const differentBilling = !!(addresses.billingAddress && addresses.shippingAddress);\n\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/customer-and-session-info`,\n {\n checkoutSessionId: sessionId,\n customerData: {\n email: this.customerEmail,\n },\n shippingAddress: effectiveShipping,\n billingAddress: effectiveBilling ?? {},\n differentBillingAddress: differentBilling,\n },\n { token: this.sessionToken },\n );\n }\n\n /**\n * Set customer info + addresses in one call (mirrors production checkout).\n *\n * Equivalent to calling `updateCustomer()` then `updateAddress()`, but\n * in a single network request.\n */\n async updateCustomerAndAddress(\n sessionId: string,\n data: {\n customer: Partial<CheckoutCustomer>;\n shippingAddress?: Address;\n billingAddress?: Address;\n },\n ): Promise<void> {\n if (data.customer.email) this.customerEmail = data.customer.email;\n if (data.customer.firstName) this.customerFirstName = data.customer.firstName;\n if (data.customer.lastName) this.customerLastName = data.customer.lastName;\n if (data.customer.phone) this.customerPhone = data.customer.phone;\n\n const shipping = this.mapAddress(data.shippingAddress);\n const billing = this.mapAddress(data.billingAddress);\n\n const effectiveShipping = shipping ?? billing ?? {};\n const effectiveBilling = billing ?? shipping;\n const differentBilling = !!(data.billingAddress && data.shippingAddress);\n\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/customer-and-session-info`,\n {\n checkoutSessionId: sessionId,\n customerData: {\n email: this.customerEmail,\n },\n shippingAddress: effectiveShipping,\n billingAddress: effectiveBilling ?? {},\n differentBillingAddress: differentBilling,\n },\n { token: this.sessionToken },\n );\n }\n\n /** Map an SDK Address to the API shape, injecting stored customer fields. */\n private mapAddress(a?: Address): Record<string, unknown> | undefined {\n if (!a) return undefined;\n return stripEmpty({\n firstName: a.firstName ?? this.customerFirstName,\n lastName: a.lastName ?? this.customerLastName,\n phone: a.phone ?? this.customerPhone,\n address1: a.line1,\n address2: a.line2,\n city: a.city,\n state: a.state,\n postal: a.postalCode,\n country: a.country,\n });\n }\n\n /** Apply a promotion code to the session. */\n async applyPromoCode(sessionId: string, code: string): Promise<void> {\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/promotions/apply`,\n { checkoutSessionId: sessionId, code },\n { token: this.sessionToken },\n );\n }\n\n /** Remove a promotion from the session by promotion ID. */\n async removePromoCode(sessionId: string, promotionId?: string): Promise<void> {\n const promoId = promotionId ?? 'default';\n await this.http.delete(\n `/api/v1/checkout-sessions/${sessionId}/promotions/${promoId}`,\n { token: this.sessionToken },\n );\n }\n\n /**\n * Fetch available shipping rates for the session's address.\n * Only relevant for **shipped products** \u2014 digital products can skip this step.\n *\n * Requires a shipping address to be set first via `updateAddress()`.\n * Returns an empty array if no rates are configured or address is missing.\n */\n async getShippingRates(sessionId: string): Promise<ShippingRate[]> {\n const res = await this.http.get<{ rates: ShippingRate[] }>(\n `/api/v1/checkout-sessions/${sessionId}/shipping-rates`,\n { token: this.sessionToken },\n );\n return res.rates ?? [];\n }\n\n /**\n * Select a shipping rate for the session.\n * Only relevant for **shipped products** \u2014 digital products can skip this step.\n */\n async selectShippingRate(sessionId: string, rateId: string): Promise<void> {\n await this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/shipping-rate`,\n { checkoutSessionId: sessionId, shippingRateId: rateId },\n { token: this.sessionToken },\n );\n }\n\n /**\n * Normalize the raw v2 API response into a cleaner CheckoutSession shape.\n * The raw response has nested `checkoutSession` + `summary` -- we flatten it.\n */\n private normalizeSession(raw: { checkoutSession: unknown; summary: unknown }): CheckoutSession {\n const cs = raw.checkoutSession as Record<string, unknown>;\n const orderSummaries = (cs.orderSummaries ?? []) as Array<Record<string, unknown>>;\n const summary = (raw.summary ?? cs.summary ?? orderSummaries[0] ?? {}) as Record<string, unknown>;\n const lineItems = (cs.sessionLineItems ?? []) as Array<Record<string, unknown>>;\n const customer = cs.customer as Record<string, unknown> | undefined;\n const sessionCurrency = ((summary.currency ?? cs.selectedPresentmentCurrency) as string | undefined)?.toUpperCase();\n\n const items = lineItems.map((li) => {\n const price = li.price as Record<string, unknown> | undefined;\n // The v2 endpoint returns `product` and `variant` as siblings of\n // `price` on each line item \u2014 not nested under `price`. Reading\n // them from `price.variant.product` (the old code) silently gave\n // back empty objects, which is why the order summary rendered\n // blank product names and a placeholder image instead of the\n // actual product art.\n const variant = (li.variant ?? price?.variant ?? {}) as Record<string, unknown>;\n const product = (li.product ?? variant.product ?? {}) as Record<string, unknown>;\n const currencyOpts = (price?.currencyOptions ?? {}) as Record<string, { amount: number }>;\n // Pick the amount bucket matching the session's presentment currency, then fall back to first available\n const priceEntry = (sessionCurrency ? currencyOpts[sessionCurrency] : undefined)\n ?? currencyOpts[Object.keys(currencyOpts)[0]];\n const amount = priceEntry?.amount ?? 0;\n return {\n id: li.id as string,\n variantId: li.variantId as string,\n priceId: li.priceId as string,\n productName: (product.name ?? '') as string,\n variantName: (variant.name ?? '') as string,\n quantity: (li.quantity ?? 1) as number,\n unitAmount: amount,\n totalAmount: amount * ((li.quantity ?? 1) as number),\n currency: (sessionCurrency ?? 'USD') as string,\n imageUrl: (variant.imageUrl ?? product.imageUrl ?? '') as string,\n };\n });\n\n const summaryItems = (summary.items ?? []) as Array<Record<string, unknown>>;\n\n return {\n id: cs.id as string,\n storeId: cs.storeId as string,\n checkoutToken: cs.checkoutToken as string,\n currency: (sessionCurrency ?? 'USD') as string,\n items,\n totals: {\n subtotal: (summary.subtotalAmount ?? 0) as number,\n discount: (summary.totalPromotionAmount ?? 0) as number,\n shipping: (summary.shippingCost ?? 0) as number,\n tax: (summary.totalTaxAmount ?? 0) as number,\n total: (summary.totalAmount ?? summaryItems.reduce((s: number, i: Record<string, unknown>) => s + ((i.amount ?? 0) as number), 0)) as number,\n currency: (sessionCurrency ?? 'USD') as string,\n },\n customer: customer\n ? {\n id: customer.id as string,\n email: customer.email as string | undefined,\n firstName: customer.firstName as string | undefined,\n lastName: customer.lastName as string | undefined,\n phone: customer.phone as string | undefined,\n }\n : undefined,\n shippingAddress: this.normalizeAddress(cs.shippingAddress),\n billingAddress: this.normalizeAddress(cs.billingAddress),\n selectedShippingRateId: (cs.shippingRateId ?? null) as string | null,\n metadata: cs.metadata as Record<string, unknown>,\n };\n }\n\n /**\n * Map the raw API address shape (`address1`, `address2`, `postal`) onto\n * the SDK's `Address` shape (`line1`, `line2`, `postalCode`). Without\n * this, `session.shippingAddress.line1` is silently undefined after a\n * reload \u2014 the type was lying about the actual key names \u2014 which is\n * what makes the demo lose form state on refresh.\n */\n private normalizeAddress(raw: unknown): Address | undefined {\n if (!raw || typeof raw !== 'object') return undefined;\n const a = raw as Record<string, unknown>;\n const out: Address = {\n firstName: a.firstName as string | undefined,\n lastName: a.lastName as string | undefined,\n line1: (a.line1 ?? a.address1) as string | undefined,\n line2: (a.line2 ?? a.address2) as string | undefined,\n city: a.city as string | undefined,\n state: a.state as string | undefined,\n postalCode: (a.postalCode ?? a.postal) as string | undefined,\n country: a.country as string | undefined,\n phone: a.phone as string | undefined,\n };\n // If every field is undefined the API returned an empty address slot.\n // Hand back undefined so consumers can `if (session.shippingAddress)`.\n return Object.values(out).some((v) => v !== undefined && v !== '') ? out : undefined;\n }\n}\n\n/**\n * Remove keys with empty-string / null / undefined values from an object.\n * Prevents sending `\"\"` to APIs that reject empty values (e.g. Stripe `country`).\n */\nfunction stripEmpty<T extends Record<string, unknown>>(obj: T): T {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined && v !== null && v !== '') {\n result[k] = v;\n }\n }\n return (Object.keys(result).length > 0 ? result : undefined) as T;\n}\n", "import type { HttpClient } from '../http.js';\nimport type {\n Environment,\n PaymentSetupConfig,\n PaymentMethodConfig,\n ExpressMethods,\n StoreConfig,\n PayResult,\n PayOptions,\n PayDirectOptions,\n CreateInstrumentOptions,\n PaymentInstrument,\n ThreedsSession,\n PaymentStatus,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n} from '../types.js';\n\n/**\n * Full payment lifecycle -- discover APMs, tokenize, create instruments,\n * process payments, handle 3DS, and poll for status.\n *\n * Wraps the same REST endpoints that plugin-sdk uses internally.\n *\n * @remarks PCI DSS compliance notice\n *\n * This SDK collects card data (PAN, expiry, CVC) in the merchant's page\n * context and sends it directly to Basis Theory for tokenization. Card data\n * never reaches TagadaPay servers.\n *\n * Because card data transits through the merchant's JavaScript environment,\n * merchants using this SDK are responsible for **PCI DSS SAQ-A-EP**\n * compliance. This includes quarterly ASV scans, secure page delivery\n * (TLS), and ensuring no unauthorized scripts can access cardholder data.\n *\n * TagadaPay is PCI DSS Level 1 certified. The merchant's PCI scope is\n * determined by their integration method, not by TagadaPay's certification.\n *\n * See: https://docs.tagada.io/developer-tools/headless-sdk/pci-compliance\n */\nexport class PaymentModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly environment: Environment,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Discovery: what payment methods are available?\n // ---------------------------------------------------------------------------\n\n /**\n * Get the full payment setup config for a checkout session.\n * Returns a map of payment methods with their configuration\n * (card, apple_pay, google_pay, klarna, etc.).\n *\n * Priority chain:\n * 1. Explicit `paymentSetupConfig` parameter (developer override)\n * 2. `window.__TGD_STEP_CONFIG__` injection (Tagada routing infra)\n * 3. API fallback (`GET /api/v1/payment-methods`)\n */\n async getPaymentSetup(\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ): Promise<PaymentSetupConfig> {\n if (opts?.paymentSetupConfig) {\n return opts.paymentSetupConfig;\n }\n\n const injected = this.readInjectedStepConfig();\n if (injected) {\n return injected;\n }\n\n const methods = await this.http.get<{ methods: PaymentMethodConfig[] }>(\n '/api/v1/payment-methods',\n { params: { checkoutSessionId } },\n );\n\n const config: PaymentSetupConfig = {};\n for (const m of methods.methods ?? []) {\n const key = m.provider ? `${m.method}:${m.provider}` : m.method;\n config[key] = m;\n }\n return config;\n }\n\n /**\n * Get express payment methods (Apple Pay, Google Pay, PayPal, etc.)\n * filtered to only those available in the current browser.\n */\n async getExpressMethods(\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ): Promise<ExpressMethods> {\n const setup = await this.getPaymentSetup(checkoutSessionId, opts);\n const result: ExpressMethods = {};\n\n for (const [key, config] of Object.entries(setup)) {\n if (!config.enabled) continue;\n\n // Handle express_checkout:processorId entries (from paymentSetupConfig injection)\n // These have a `methods` map like { apple_pay: { enabled: true }, google_pay: { enabled: true } }\n if (key.startsWith('express_checkout:') && config.methods) {\n const base = {\n available: true,\n processorId: config.processorId,\n publishableKey: config.publishableKey,\n metadata: config.metadata,\n };\n if (config.methods.apple_pay?.enabled) {\n const hasApplePay =\n typeof window !== 'undefined' &&\n 'ApplePaySession' in window &&\n (window as unknown as Record<string, { canMakePayments?: () => boolean }>)\n .ApplePaySession?.canMakePayments?.();\n result.applePay = { ...base, type: 'apple_pay', available: !!hasApplePay };\n }\n if (config.methods.google_pay?.enabled) {\n result.googlePay = { ...base, type: 'google_pay' };\n }\n if (config.methods.paypal?.enabled) {\n result.paypal = { ...base, type: 'paypal' };\n }\n if (config.methods.link?.enabled) {\n result.link = { ...base, type: 'link' };\n }\n if (config.methods.klarna_express?.enabled) {\n result.klarna = { ...base, type: 'klarna_express' };\n }\n continue;\n }\n\n if (!config.express) continue;\n\n const method = config.method;\n const base = {\n type: method,\n available: true,\n processorId: config.processorId,\n publishableKey: config.publishableKey,\n metadata: config.metadata,\n };\n\n if (method === 'apple_pay' || config.type === 'apple_pay') {\n const hasApplePay =\n typeof window !== 'undefined' &&\n 'ApplePaySession' in window &&\n (window as unknown as Record<string, { canMakePayments?: () => boolean }>)\n .ApplePaySession?.canMakePayments?.();\n result.applePay = { ...base, available: !!hasApplePay };\n } else if (method === 'google_pay' || config.type === 'google_pay') {\n result.googlePay = base;\n } else if (method === 'paypal') {\n result.paypal = base;\n } else if (method === 'klarna' || method === 'klarna_express') {\n result.klarna = base;\n } else if (method === 'link') {\n result.link = base;\n }\n }\n\n return result;\n }\n\n /**\n * Get store-level payment config (3DS flags, default flow ID, etc.).\n */\n async getStoreConfig(): Promise<StoreConfig> {\n const res = await this.http.get<{ config: StoreConfig }>(\n '/api/v1/checkout/config',\n { params: { storeId: this.storeId } },\n );\n return res.config ?? (res as unknown as StoreConfig);\n }\n\n /**\n * Convenience: return only enabled payment method keys.\n */\n async getEnabledMethods(\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ): Promise<string[]> {\n const setup = await this.getPaymentSetup(checkoutSessionId, opts);\n return Object.entries(setup)\n .filter(([, c]) => c.enabled)\n .map(([key]) => key);\n }\n\n // ---------------------------------------------------------------------------\n // Tokenization (delegates to @tagadapay/core-js if available)\n // ---------------------------------------------------------------------------\n\n /**\n * Tokenize a card using @tagadapay/core-js.\n * Requires `@tagadapay/core-js` to be installed as a peer dependency.\n *\n * Card data is sent directly to Basis Theory for tokenization and never\n * reaches TagadaPay servers. The returned `tagadaToken` is safe to pass\n * to the TagadaPay API.\n *\n * **PCI note:** Using this method means card data passes through your\n * JavaScript environment. You are responsible for PCI DSS SAQ-A-EP\n * compliance. See https://docs.tagada.io/developer-tools/headless-sdk/pci-compliance\n *\n * @returns tagadaToken (base64 string) and rawToken with SCA metadata.\n */\n async tokenizeCard(card: {\n cardNumber: string;\n expiryDate: string;\n cvc: string;\n cardholderName?: string;\n }): Promise<{ tagadaToken: string; rawToken: Record<string, unknown> }> {\n const coreJs = await this.loadCoreJs();\n\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n\n const sanitized: Record<string, string> = {\n cardNumber: card.cardNumber,\n expiryDate: card.expiryDate,\n cvc: card.cvc,\n };\n if (card.cardholderName) sanitized.cardholderName = card.cardholderName;\n\n const [tagadaToken, rawToken] = await Promise.all([\n tokenizer.tokenizeCard(sanitized),\n tokenizer.tokenizeCardRaw(sanitized),\n ]);\n\n return { tagadaToken, rawToken };\n }\n\n // ---------------------------------------------------------------------------\n // Instrument creation\n // ---------------------------------------------------------------------------\n\n /**\n * Create a reusable payment instrument from a TagadaToken.\n * Session-authenticated (uses the checkout session JWT).\n */\n async createInstrument(\n opts: CreateInstrumentOptions,\n ): Promise<{ paymentInstrument: PaymentInstrument }> {\n return this.http.post('/api/v1/payment/create-instrument-from-token', {\n tagadaToken: opts.tagadaToken,\n });\n }\n\n // ---------------------------------------------------------------------------\n // 3DS\n // ---------------------------------------------------------------------------\n\n /**\n * Create a 3DS session on the TagadaPay backend.\n * This persists the session so the processor can use it during payment.\n */\n async create3dsSession(opts: {\n paymentInstrumentId: string;\n sessionData: { sessionId: string; metadata?: Record<string, unknown> };\n provider?: string;\n }): Promise<ThreedsSession> {\n return this.http.post('/api/public/v1/threeds/create-session', {\n provider: opts.provider ?? 'basis_theory',\n storeId: this.storeId,\n paymentInstrumentId: opts.paymentInstrumentId,\n sessionData: opts.sessionData,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Payment processing\n // ---------------------------------------------------------------------------\n\n /**\n * High-level pay: single API call that decodes tagadaToken server-side,\n * creates the payment instrument, and processes payment.\n *\n * Also accepts `paymentInstrumentId` directly for pre-created instruments.\n */\n async pay(opts: PayOptions): Promise<PayResult> {\n if (opts.tagadaToken && !opts.paymentInstrumentId) {\n return this.http.post<PayResult>('/api/v1/payment/pay-with-token', {\n tagadaToken: opts.tagadaToken,\n checkoutSessionId: opts.checkoutSessionId,\n returnUrl: opts.returnUrl,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n });\n }\n\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId,\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n threedsSessionId: opts.threedsSessionId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n });\n }\n\n /**\n * Low-level pay: process payment with an existing instrument or for APM/express flows\n * where no instrument is needed (redirect-based methods).\n */\n async payDirect(opts: PayDirectOptions): Promise<PayResult> {\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId ?? '',\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n threedsSessionId: opts.threedsSessionId,\n });\n }\n\n /**\n * Process an Apple Pay payment.\n * Tokenizes the Apple Pay token and processes payment in one call.\n */\n async processApplePay(opts: {\n checkoutSessionId: string;\n applePayToken: unknown;\n paymentFlowId?: string;\n processorId?: string;\n }): Promise<PayResult> {\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n const { tagadaToken } = await tokenizer.tokenizeApplePay(opts.applePayToken);\n\n return this.pay({\n checkoutSessionId: opts.checkoutSessionId,\n tagadaToken,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: 'apple_pay',\n isExpress: true,\n });\n }\n\n /**\n * Process a Google Pay payment.\n * Tokenizes the Google Pay token and processes payment in one call.\n */\n async processGooglePay(opts: {\n checkoutSessionId: string;\n googlePayToken: string;\n paymentFlowId?: string;\n processorId?: string;\n }): Promise<PayResult> {\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n const { tagadaToken } = await tokenizer.tokenizeGooglePay(opts.googlePayToken);\n\n return this.pay({\n checkoutSessionId: opts.checkoutSessionId,\n tagadaToken,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: 'google_pay',\n isExpress: true,\n });\n }\n\n /**\n * Process an APM payment (Klarna, iDEAL, etc.) via redirect.\n * These typically don't require a payment instrument -- the processor handles the redirect.\n */\n async processApm(opts: {\n checkoutSessionId: string;\n paymentMethod: string;\n processorId: string;\n paymentFlowId?: string;\n }): Promise<PayResult> {\n return this.payDirect({\n checkoutSessionId: opts.checkoutSessionId,\n paymentMethod: opts.paymentMethod,\n processorId: opts.processorId,\n paymentFlowId: opts.paymentFlowId,\n });\n }\n\n /**\n * Initiate a Stripe Express Checkout payment (Apple Pay, Google Pay, Link, etc.).\n *\n * Calls `pay-v2` with `isExpress: true`, which returns a `clientSecret` in\n * `payment.requireActionData.metadata.stripeExpressCheckout.clientSecret`.\n * The caller must then call `stripe.confirmPayment()` with that secret.\n *\n * Used by the `StripeExpressCheckout` class and `useStripeExpress` hook.\n * Not typically called directly \u2014 use the Stripe integration classes instead.\n */\n async processStripeExpress(opts: {\n checkoutSessionId: string;\n processorId: string;\n paymentMethod: string;\n }): Promise<PayResult> {\n return this.payDirect({\n checkoutSessionId: opts.checkoutSessionId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // High-level orchestrator \u2014 the ONE function beginners should call\n // ---------------------------------------------------------------------------\n\n /**\n * Process a payment end-to-end: pay, handle 3DS / redirects, poll until done.\n *\n * This is the **recommended** way to process payments. It wraps `pay()`, detects\n * `requireAction`, runs 3DS challenges (if `@tagadapay/core-js` is installed),\n * and polls until a terminal status.\n *\n * Returns a discriminated union so you can pattern-match on `result.status`:\n *\n * @example\n * ```ts\n * const result = await payment.processPayment({\n * checkoutSessionId: session.id,\n * tagadaToken,\n * });\n *\n * switch (result.status) {\n * case 'succeeded':\n * console.log('Paid!', result.payment.id);\n * break;\n * case 'requires_redirect':\n * // In browser: window.location.href = result.redirectUrl\n * // The React hook handles this automatically.\n * break;\n * case 'failed':\n * console.error(result.error);\n * break;\n * }\n * ```\n */\n async processPayment(opts: ProcessPaymentOptions): Promise<ProcessPaymentResult> {\n if (!opts.returnUrl && typeof window !== 'undefined') {\n opts = { ...opts, returnUrl: window.location.href };\n }\n const payResult = await this.pay(opts);\n const payment = payResult.payment;\n\n if (payment.status === 'succeeded') {\n return { status: 'succeeded', payment, order: payResult.order };\n }\n\n if (payment.status === 'failed' || payment.status === 'declined') {\n const msg = payment.requireActionData?.message\n || payment.requireActionData?.errorCode\n || `Payment ${payment.status}`;\n return { status: 'failed', error: msg, payment };\n }\n\n if (payment.requireAction && payment.requireAction !== 'none' && payment.requireActionData) {\n return this.handlePaymentAction(payment, opts);\n }\n\n // status is 'pending' or 'requires_action' without explicit actionData \u2014 poll\n return this.pollUntilDone(payment.id);\n }\n\n /**\n * Resume a payment after the user returns from a redirect (3DS, processor auth, APM).\n *\n * Called automatically by `usePayment()` in React when it detects return-URL params.\n * You can also call it manually in non-React apps.\n */\n async resumeAfterRedirect(paymentId: string): Promise<ProcessPaymentResult> {\n return this.pollUntilDone(paymentId);\n }\n\n // ---------------------------------------------------------------------------\n // Status polling\n // ---------------------------------------------------------------------------\n\n /** Get current status of a payment. */\n async getPaymentStatus(paymentId: string): Promise<PaymentStatus> {\n return this.http.get<PaymentStatus>(`/api/v1/payments/${paymentId}`);\n }\n\n /**\n * Poll a payment until it reaches a terminal status.\n * Returns the final status or throws on timeout.\n */\n async pollPaymentStatus(\n paymentId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<PaymentStatus> {\n const interval = opts?.intervalMs ?? 1500;\n const timeout = opts?.timeoutMs ?? 60_000;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const status = await this.getPaymentStatus(paymentId);\n if (status.status === 'succeeded' || status.status === 'failed' || status.status === 'declined') {\n return status;\n }\n await new Promise((r) => setTimeout(r, interval));\n }\n\n throw new Error(`Payment ${paymentId} did not reach terminal status within ${timeout}ms.`);\n }\n\n /** Finalize a payment after a 3DS challenge completes. */\n async completeAfter3ds(paymentId: string): Promise<PaymentStatus> {\n return this.http.post<PaymentStatus>('/api/v1/payments/complete-after-3ds', {\n paymentId,\n });\n }\n\n /** Tell the server this action has been seen / is being processed. */\n async markActionProcessed(paymentId: string): Promise<void> {\n try {\n await this.http.post('/api/v1/payments/require-action/processed', {\n paymentId,\n });\n } catch {\n // Best-effort \u2014 don't block the payment flow if this fails\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal: action routing\n // ---------------------------------------------------------------------------\n\n /**\n * Route a payment action to the appropriate handler.\n * Returns `requires_redirect` for browser-level redirects,\n * or attempts 3DS inline and polls to completion.\n */\n private async handlePaymentAction(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const actionData = payment.requireActionData!;\n\n await this.markActionProcessed(payment.id);\n\n const actionType = actionData.type;\n\n switch (actionType) {\n case 'threeds_auth':\n return this.handleThreedsAuth(payment, opts);\n\n case 'processor_auth':\n case 'redirect_to_payment':\n return this.extractRedirect(payment, actionData);\n\n case 'redirect':\n return this.extractRedirect(payment, actionData);\n\n case 'error':\n return {\n status: 'failed',\n error: actionData.message || actionData.errorCode || 'Payment failed',\n payment,\n };\n\n default:\n // Unknown action type \u2014 try to extract a redirect URL (forward-compatible)\n return this.extractRedirect(payment, actionData);\n }\n }\n\n /**\n * Extract redirect info from actionData.\n * Works for processor_auth (GET or POST), redirect, and any unknown type with a URL.\n */\n private extractRedirect(\n payment: PayResult['payment'],\n actionData: NonNullable<PayResult['payment']['requireActionData']>,\n ): ProcessPaymentResult {\n const redirect = actionData.metadata?.redirect;\n const url = redirect?.redirectUrl || actionData.redirectUrl;\n\n if (!url) {\n return {\n status: 'failed',\n error: `Payment requires action (${actionData.type}) but no redirect URL was provided`,\n payment,\n };\n }\n\n return {\n status: 'requires_redirect',\n redirectUrl: url,\n method: (redirect?.method?.toUpperCase() as 'GET' | 'POST') || 'GET',\n postData: redirect?.data,\n paymentId: payment.id,\n };\n }\n\n /**\n * Run a 3DS challenge using @tagadapay/core-js.\n * If core-js is not installed, falls back to redirect.\n */\n private async handleThreedsAuth(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const session = payment.requireActionData?.metadata?.threedsSession;\n\n // If no 3DS session data, fall back to redirect (acsChallengeUrl)\n if (!session?.externalSessionId) {\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Try to run the challenge inline via core-js\n let coreJs: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n try {\n coreJs = await import('@tagadapay/core-js');\n } catch {\n // core-js not installed \u2014 fall back to redirect if possible\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Run BasisTheory 3DS challenge in a modal iframe\n try {\n const manager = new coreJs.ThreedsManager({ provider: 'basis_theory' });\n await manager.initialize({ apiKey: undefined });\n\n await manager.startChallenge({\n sessionId: session.externalSessionId,\n acsChallengeUrl: session.acsChallengeUrl,\n acsTransactionId: session.acsTransID,\n threeDSVersion: session.messageVersion,\n });\n\n // Challenge done \u2014 tell backend and poll\n await this.completeAfter3ds(payment.id);\n return this.pollUntilDone(payment.id);\n } catch {\n // 3DS challenge failed \u2014 fall back to redirect\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return {\n status: 'failed',\n error: '3D Secure authentication failed',\n payment,\n };\n }\n }\n\n /**\n * Poll until the payment reaches a terminal status, then return a ProcessPaymentResult.\n * Also handles new requireAction that may appear during polling.\n */\n private async pollUntilDone(\n paymentId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<ProcessPaymentResult> {\n const interval = opts?.intervalMs ?? 1500;\n const timeout = opts?.timeoutMs ?? 60_000;\n const start = Date.now();\n let consecutiveErrors = 0;\n\n while (Date.now() - start < timeout) {\n let status: PaymentStatus;\n try {\n status = await this.getPaymentStatus(paymentId);\n consecutiveErrors = 0;\n } catch {\n consecutiveErrors++;\n if (consecutiveErrors >= 3) {\n return { status: 'failed', error: 'Payment verification failed due to network errors' };\n }\n await new Promise((r) => setTimeout(r, interval));\n continue;\n }\n\n if (\n status.status === 'succeeded' ||\n (status.status === 'pending' && status.subStatus === 'authorized')\n ) {\n return { status: 'succeeded', payment: status as unknown as PayResult['payment'], order: status.order };\n }\n\n if (status.status === 'failed' || status.status === 'declined') {\n return { status: 'failed', error: status.status, payment: status as unknown as PayResult['payment'] };\n }\n\n // New unprocessed action appeared during polling\n if (\n status.requireAction &&\n status.requireAction !== 'none' &&\n status.requireActionData &&\n !status.requireActionData.processed\n ) {\n return this.handlePaymentAction(\n status as unknown as PayResult['payment'],\n {} as ProcessPaymentOptions,\n );\n }\n\n await new Promise((r) => setTimeout(r, interval));\n }\n\n return { status: 'pending', paymentId };\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Read paymentSetupConfig from the Tagada routing injection.\n * Only available when running on Tagada infra (not on external hosting like Vercel).\n */\n private readInjectedStepConfig(): PaymentSetupConfig | null {\n if (typeof window === 'undefined') return null;\n const raw = (window as unknown as Record<string, unknown>).__TGD_STEP_CONFIG__;\n if (!raw) return null;\n try {\n const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;\n return (parsed as Record<string, unknown>)?.paymentSetupConfig as PaymentSetupConfig ?? null;\n } catch {\n return null;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private async loadCoreJs(): Promise<any> {\n try {\n return await import('@tagadapay/core-js');\n } catch {\n throw new Error(\n 'This method requires @tagadapay/core-js. Install it: npm install @tagadapay/core-js',\n );\n }\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { Offer, OfferPreview, OfferPayResult } from '../types.js';\n\n/**\n * Offers \u2014 upsells, downsells, order bumps, and post-purchase offers.\n *\n * Endpoints align with the plugin-sdk patterns:\n * GET /api/v1/offers/:id \u2014 single offer\n * GET /api/v1/stores/:storeId/offers \u2014 list store offers\n * POST /api/v1/offers/:offerId/preview \u2014 preview pricing\n * POST /api/v1/offers/:offerId/pay-preview \u2014 pay a previewed offer (one-click)\n * POST /api/v1/checkout-sessions/:id/toggle-order-bump \u2014 toggle order bump\n * GET /api/v1/post-purchase/:orderId/offers \u2014 post-purchase offers for an order\n * POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/accept \u2014 accept\n * POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/decline \u2014 decline\n */\nexport class OffersModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Offer loading\n // ---------------------------------------------------------------------------\n\n /** Get a single offer by ID. */\n async getOffer(offerId: string): Promise<Offer> {\n return this.http.get<Offer>(`/api/v1/offers/${offerId}`);\n }\n\n /** List offers for the current store. Optionally filter by type or a set of IDs. */\n async listOffers(opts?: {\n type?: 'upsell' | 'orderbump';\n ids?: string[];\n }): Promise<Offer[]> {\n let url = `/api/v1/stores/${this.storeId}/offers`;\n\n const queryParts: string[] = [];\n if (opts?.type) queryParts.push(`type=${encodeURIComponent(opts.type)}`);\n if (opts?.ids?.length) {\n for (const id of opts.ids) queryParts.push(`ids=${encodeURIComponent(id)}`);\n }\n if (queryParts.length) url += `?${queryParts.join('&')}`;\n\n const res = await this.http.get<{ offers: Offer[] }>(url);\n return res.offers ?? [];\n }\n\n // ---------------------------------------------------------------------------\n // Preview & pay (one-click upsell flow from plugin-sdk)\n // ---------------------------------------------------------------------------\n\n /** Preview offer pricing. Returns line items with amounts and totals. */\n async previewOffer(opts: {\n offerId: string;\n currency?: string;\n lineItems?: Array<{ lineItemId?: string; productId?: string; variantId: string; quantity: number }>;\n }): Promise<OfferPreview> {\n return this.http.post<OfferPreview>(`/api/v1/offers/${opts.offerId}/preview`, {\n offerId: opts.offerId,\n currency: opts.currency ?? '',\n lineItems: opts.lineItems,\n });\n }\n\n /**\n * Pay a previously previewed offer (one-click charge).\n * Used after a main order so the stored payment instrument is reused.\n */\n async payPreviewedOffer(opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ lineItemId?: string; productId?: string; variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }): Promise<OfferPayResult> {\n return this.http.post<OfferPayResult>(`/api/v1/offers/${opts.offerId}/pay-preview`, {\n offerId: opts.offerId,\n currency: opts.currency ?? '',\n lineItems: opts.lineItems,\n returnUrl: opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),\n mainOrderId: opts.mainOrderId,\n paymentInstrumentId: opts.paymentInstrumentId,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Order bumps (checkout-session scoped)\n // ---------------------------------------------------------------------------\n\n /** Toggle an order bump on/off within a checkout session. */\n async toggleOrderBump(opts: {\n checkoutSessionId: string;\n orderBumpOfferId: string;\n selected: boolean;\n }): Promise<unknown> {\n return this.http.post(\n `/api/v1/checkout-sessions/${opts.checkoutSessionId}/toggle-order-bump`,\n {\n orderBumpOfferId: opts.orderBumpOfferId,\n selected: opts.selected,\n },\n );\n }\n\n // ---------------------------------------------------------------------------\n // Post-purchase offers (order-scoped)\n // ---------------------------------------------------------------------------\n\n /** List post-purchase offers for an order. */\n async listPostPurchaseOffers(orderId: string): Promise<Offer[]> {\n const res = await this.http.get<Offer[]>(`/api/v1/post-purchase/${orderId}/offers`);\n return Array.isArray(res) ? res : [];\n }\n\n /** Accept a post-purchase offer. */\n async acceptPostPurchaseOffer(opts: {\n orderId: string;\n offerId: string;\n items?: Array<{ variantId: string; quantity: number }>;\n }): Promise<{ success: boolean; error?: string }> {\n return this.http.post(\n `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/accept`,\n { items: opts.items ?? [] },\n );\n }\n\n /** Decline a post-purchase offer. */\n async declinePostPurchaseOffer(opts: {\n orderId: string;\n offerId: string;\n }): Promise<{ success: boolean; error?: string }> {\n return this.http.post(\n `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/decline`,\n );\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { Customer, Order, Subscription } from '../types.js';\n\n/**\n * Customer data -- profile, orders, subscriptions.\n *\n * Requires either an API key or a session token for authentication.\n */\nexport class CustomerModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n /** Get customer profile by ID. */\n async getProfile(customerId: string): Promise<Customer> {\n const res = await this.http.get<{ customer: Customer }>(\n `/api/v1/customers/${customerId}`,\n { params: { storeId: this.storeId } },\n );\n return res.customer;\n }\n\n /** Get customer profile by email. */\n async getByEmail(email: string): Promise<Customer | null> {\n try {\n const res = await this.http.get<{ customer: Customer }>(\n '/api/v1/customers/by-email',\n { params: { email, storeId: this.storeId } },\n );\n return res.customer;\n } catch {\n return null;\n }\n }\n\n /** Update customer profile fields. */\n async updateProfile(\n customerId: string,\n data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone' | 'metadata'>>,\n ): Promise<Customer> {\n const res = await this.http.patch<{ customer: Customer }>(\n `/api/v1/customers/${customerId}`,\n { storeId: this.storeId, ...data },\n );\n return res.customer;\n }\n\n /** List orders for a customer. */\n async getOrders(\n customerId: string,\n opts?: { limit?: number; offset?: number },\n ): Promise<{ orders: Order[]; total: number }> {\n return this.http.get<{ orders: Order[]; total: number }>(\n `/api/v1/customers/${customerId}/orders`,\n { params: { storeId: this.storeId, limit: opts?.limit, offset: opts?.offset } },\n );\n }\n\n /** Get a single order by ID. */\n async getOrder(orderId: string): Promise<Order> {\n const res = await this.http.get<{ order: Order }>(`/api/v1/orders/${orderId}`, {\n params: { storeId: this.storeId },\n });\n return res.order;\n }\n\n /** List subscriptions for a customer. */\n async getSubscriptions(customerId: string): Promise<Subscription[]> {\n const res = await this.http.get<{ subscriptions: Subscription[] }>(\n `/api/v1/customers/${customerId}/subscriptions`,\n { params: { storeId: this.storeId } },\n );\n return res.subscriptions;\n }\n\n /** Get a single subscription by ID. */\n async getSubscription(subscriptionId: string): Promise<Subscription> {\n const res = await this.http.get<{ subscription: Subscription }>(\n `/api/v1/subscriptions/${subscriptionId}`,\n { params: { storeId: this.storeId } },\n );\n return res.subscription;\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { CatalogProduct } from '../types.js';\n\n/**\n * Fetches the product catalog for a store.\n *\n * Uses the public `/api/v1/products` endpoint (no auth required).\n */\nexport class CatalogModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n /**\n * List all active products for the store, including variants and prices.\n *\n * @param opts.productIds Optional filter to specific product IDs.\n * @param opts.variantIds Optional filter to products containing these variant IDs.\n */\n async getProducts(opts?: {\n productIds?: string[];\n variantIds?: string[];\n }): Promise<CatalogProduct[]> {\n const body: Record<string, unknown> = {\n storeId: this.storeId,\n includeVariants: true,\n includePrices: true,\n };\n if (opts?.productIds?.length) body.productIds = opts.productIds;\n if (opts?.variantIds?.length) body.variantIds = opts.variantIds;\n\n const res = await this.http.post<{ items: CatalogProduct[] }>(\n '/api/v1/products',\n body,\n );\n\n return res.items ?? [];\n }\n\n /**\n * Get a single product by ID.\n */\n async getProduct(productId: string): Promise<CatalogProduct | null> {\n const items = await this.getProducts({ productIds: [productId] });\n return items[0] ?? null;\n }\n}\n", "import { HttpClient } from './http.js';\nimport { CheckoutModule } from './modules/checkout.js';\nimport { PaymentModule } from './modules/payment.js';\nimport { OffersModule } from './modules/offers.js';\nimport { CustomerModule } from './modules/customer.js';\nimport { CatalogModule } from './modules/catalog.js';\nimport type { HeadlessConfig, Environment } from './types.js';\n\n/**\n * Main entry point for the TagadaPay Headless SDK.\n *\n * Composes all domain modules (checkout, payment, offers, customer, catalog)\n * over a single lightweight HTTP client built on native fetch.\n *\n * **PCI DSS notice:** Card tokenization via `payment.tokenizeCard()` sends\n * card data directly to Basis Theory \u2014 it never reaches TagadaPay servers.\n * However, because card data passes through your JavaScript environment,\n * merchants using this SDK are responsible for PCI DSS SAQ-A-EP compliance.\n * See https://docs.tagada.io/developer-tools/headless-sdk/pci-compliance\n */\nexport class HeadlessClient {\n readonly config: Required<Pick<HeadlessConfig, 'storeId' | 'environment'>> & HeadlessConfig;\n\n private readonly http: HttpClient;\n\n /** Shared session token used by all modules for authenticated API calls. */\n private _sessionToken: string | undefined;\n\n /** Checkout session management -- load, update cart, apply promos, shipping. */\n readonly checkout: CheckoutModule;\n\n /** Payment processing -- setup config, APMs, tokenize, pay, 3DS, poll. */\n readonly payment: PaymentModule;\n\n /** Offers -- preview, pay, accept/decline upsells and order bumps. */\n readonly offers: OffersModule;\n\n /** Customer data -- profile, orders, subscriptions. */\n readonly customer: CustomerModule;\n\n /** Product catalog -- list products, variants, and prices. */\n readonly catalog: CatalogModule;\n\n constructor(config: HeadlessConfig) {\n const environment: Environment = config.environment ?? 'production';\n const baseUrl = HttpClient.resolveBaseUrl(environment, config.baseUrl);\n\n this.config = {\n ...config,\n environment,\n baseUrl,\n timeout: config.timeout ?? 30_000,\n };\n\n this.http = new HttpClient({\n baseUrl,\n timeout: this.config.timeout!,\n apiKey: config.apiKey,\n getToken: () => this._sessionToken,\n });\n\n const setToken = (token: string) => {\n this._sessionToken = token;\n };\n\n this.checkout = new CheckoutModule(this.http, this.config.storeId, setToken);\n this.payment = new PaymentModule(this.http, this.config.storeId, environment);\n this.offers = new OffersModule(this.http, this.config.storeId);\n this.customer = new CustomerModule(this.http, this.config.storeId);\n this.catalog = new CatalogModule(this.http, this.config.storeId);\n }\n\n /** Manually set the session token (e.g. from URL params on page load). */\n setSessionToken(token: string) {\n this._sessionToken = token;\n }\n}\n\n/**\n * Create a new HeadlessClient instance.\n *\n * @example\n * ```ts\n * import { createHeadlessClient } from '@tagadapay/headless-sdk';\n *\n * const tagada = createHeadlessClient({\n * storeId: 'store_abc123',\n * environment: 'production',\n * });\n *\n * const session = await tagada.checkout.loadSession(checkoutToken);\n * ```\n */\nexport function createHeadlessClient(config: HeadlessConfig): HeadlessClient {\n return new HeadlessClient(config);\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { CheckoutSession, LineItem, ShippingRate, Address, CheckoutCustomer } from '../../core/types.js';\n\nexport interface UseCheckoutReturn {\n session: CheckoutSession | null;\n isLoading: boolean;\n error: Error | null;\n /** Reload the session from the server. */\n refresh: () => Promise<void>;\n /** Create a new checkout session (auto-loads it after creation). */\n createSession: (opts: {\n items: LineItem[];\n currency?: string;\n returnUrl?: string;\n customerEmail?: string;\n }) => Promise<void>;\n /** Replace cart items. */\n updateCart: (items: LineItem[]) => Promise<void>;\n /** Update customer info on the session. */\n updateCustomer: (customer: Partial<CheckoutCustomer>) => Promise<void>;\n /** Update address on the session. */\n updateAddress: (addresses: { shippingAddress?: Address; billingAddress?: Address }) => Promise<void>;\n /**\n * Update customer info AND address in a single call. Prefer this over\n * calling `updateCustomer` then `updateAddress` separately \u2014 the\n * underlying server action is destructive on partial saves\n * (`customers.firstName = shippingAddress.firstName ?? null`), so\n * sending the address without the customer name will silently wipe\n * `customer.firstName` / `customer.lastName` from the session.\n */\n updateCustomerAndAddress: (data: {\n customer: Partial<CheckoutCustomer>;\n shippingAddress?: Address;\n billingAddress?: Address;\n }) => Promise<void>;\n /** Apply a promo code. */\n applyPromo: (code: string) => Promise<void>;\n /** Remove the applied promo code. */\n removePromo: (promotionId?: string) => Promise<void>;\n /** Fetch shipping rates. */\n getShippingRates: () => Promise<ShippingRate[]>;\n /** Select a shipping rate. */\n selectShippingRate: (rateId: string) => Promise<void>;\n}\n\n/**\n * React hook for checkout session management.\n *\n * @param checkoutToken - The checkout token from the URL (e.g. `?checkoutToken=xxx`).\n * @param sessionToken - Optional JWT session token (from URL param `token`).\n *\n * @example\n * ```tsx\n * const { session, isLoading, applyPromo, createSession } = useCheckout(checkoutToken, sessionToken);\n * ```\n */\nexport function useCheckout(\n checkoutToken: string | null | undefined,\n sessionToken?: string,\n): UseCheckoutReturn {\n const client = useHeadlessClient();\n const [session, setSession] = useState<CheckoutSession | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const loadSession = useCallback(async () => {\n if (!checkoutToken) return;\n setIsLoading(true);\n setError(null);\n try {\n const s = await client.checkout.loadSession(checkoutToken, sessionToken);\n setSession(s);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, checkoutToken, sessionToken]);\n\n useEffect(() => {\n loadSession();\n }, [loadSession]);\n\n const createSession = useCallback(async (opts: {\n items: LineItem[];\n currency?: string;\n returnUrl?: string;\n customerEmail?: string;\n }) => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await client.checkout.createSession(opts);\n\n const newUrl = new URL(window.location.href);\n newUrl.searchParams.set('checkoutToken', result.checkoutToken);\n newUrl.searchParams.set('token', result.sessionToken);\n window.history.replaceState({}, '', newUrl.toString());\n\n const s = await client.checkout.loadSession(result.checkoutToken, result.sessionToken);\n setSession(s);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n const updateCart = useCallback(async (items: LineItem[]) => {\n if (!session) return;\n // `updateCart` returns mutation stats (counts), not a CheckoutSession.\n // We previously assigned that result into `setSession`, which silently\n // replaced the session with `{ success, updated, created, total }`.\n // Mirror the same pattern as `updateAddress`: mutate, then reload.\n await client.checkout.updateCart(session.id, items);\n await loadSession();\n }, [client, session, loadSession]);\n\n const updateCustomer = useCallback(async (customer: Partial<CheckoutCustomer>) => {\n if (!session) return;\n await client.checkout.updateCustomer(session.id, customer);\n }, [client, session]);\n\n const updateAddress = useCallback(async (addresses: { shippingAddress?: Address; billingAddress?: Address }) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.updateAddress(session.id, addresses);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const updateCustomerAndAddress = useCallback(async (data: {\n customer: Partial<CheckoutCustomer>;\n shippingAddress?: Address;\n billingAddress?: Address;\n }) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.updateCustomerAndAddress(session.id, data);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const applyPromo = useCallback(async (code: string) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.applyPromoCode(session.id, code);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const removePromo = useCallback(async (promotionId?: string) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.removePromoCode(session.id, promotionId);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n const getShippingRates = useCallback(async () => {\n if (!session) return [];\n return client.checkout.getShippingRates(session.id);\n }, [client, session]);\n\n const selectShippingRate = useCallback(async (rateId: string) => {\n if (!session) return;\n setIsLoading(true);\n try {\n await client.checkout.selectShippingRate(session.id, rateId);\n await loadSession();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client, session, loadSession]);\n\n return {\n session,\n isLoading,\n error,\n refresh: loadSession,\n createSession,\n updateCart,\n updateCustomer,\n updateAddress,\n updateCustomerAndAddress,\n applyPromo,\n removePromo,\n getShippingRates,\n selectShippingRate,\n };\n}\n", "import { useState, useCallback, useRef, useEffect } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type {\n PaymentSetupConfig,\n ExpressMethods,\n StoreConfig,\n PayResult,\n PayOptions,\n PaymentStatus,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n} from '../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Hook options (passed to usePayment for callback-based flows)\n// ---------------------------------------------------------------------------\n\nexport interface UsePaymentOptions {\n /**\n * Called when a payment succeeds (including after 3DS redirect return).\n * Use this to navigate to a confirmation page.\n */\n onPaymentSuccess?: (result: ProcessPaymentResult & { status: 'succeeded' }) => void;\n /**\n * Called when a payment fails (including after redirect return).\n */\n onPaymentFailed?: (result: ProcessPaymentResult & { status: 'failed' }) => void;\n /**\n * Explicit paymentSetupConfig override.\n * When provided, the SDK skips both __TGD_STEP_CONFIG__ detection and the API call.\n * Useful when a developer fetches the config from their own backend.\n */\n paymentSetupConfig?: PaymentSetupConfig;\n}\n\nexport interface UsePaymentReturn {\n /** Full payment setup config (all methods with their enabled/disabled state). */\n paymentSetup: PaymentSetupConfig | null;\n /** Express methods (Apple Pay, Google Pay, etc.) with browser availability. */\n expressMethods: ExpressMethods | null;\n /** Store-level config (3DS flags, etc.). */\n storeConfig: StoreConfig | null;\n /** Whether a payment is currently being processed (including polling after redirect). */\n isProcessing: boolean;\n /** Last payment result. */\n result: PayResult | null;\n /** Last error. */\n error: Error | null;\n /**\n * Load payment setup for a checkout session. Call this once when the session is ready.\n * Optionally pass `paymentSetupConfig` to override auto-detection.\n */\n loadPaymentSetup: (checkoutSessionId: string, opts?: { paymentSetupConfig?: PaymentSetupConfig }) => Promise<void>;\n\n /**\n * **Recommended**. Tokenize + pay + handle 3DS/redirects + poll \u2014 all in one call.\n *\n * - If the payment succeeds immediately, resolves with `{ status: 'succeeded' }`.\n * - If 3DS redirect is needed, automatically redirects the browser.\n * When the user comes back, the hook auto-detects the return and polls.\n * - If the payment fails, resolves with `{ status: 'failed', error: '...' }`.\n */\n processPayment: (opts: ProcessPaymentOptions) => Promise<ProcessPaymentResult>;\n\n /** Low-level pay (returns raw API response, no automatic action handling). */\n pay: (opts: PayOptions) => Promise<PayResult>;\n /**\n * Tokenize a card (returns tagadaToken). Requires @tagadapay/core-js.\n *\n * PCI note: card data passes through your JS environment.\n * You are responsible for PCI DSS SAQ-A-EP compliance.\n */\n tokenizeCard: (card: {\n cardNumber: string;\n expiryDate: string;\n cvc: string;\n cardholderName?: string;\n }) => Promise<{ tagadaToken: string; rawToken: Record<string, unknown> }>;\n /** Process Apple Pay. */\n processApplePay: (opts: {\n checkoutSessionId: string;\n applePayToken: unknown;\n }) => Promise<PayResult>;\n /** Process Google Pay. */\n processGooglePay: (opts: {\n checkoutSessionId: string;\n googlePayToken: string;\n }) => Promise<PayResult>;\n /** Process redirect-based APM (Klarna, iDEAL, etc.). */\n processApm: (opts: {\n checkoutSessionId: string;\n paymentMethod: string;\n processorId: string;\n }) => Promise<PayResult>;\n /** Poll a payment until terminal status. */\n pollStatus: (paymentId: string) => Promise<PaymentStatus>;\n}\n\n/**\n * React hook for payment processing.\n *\n * Handles the full payment lifecycle including 3DS redirects and return-URL detection.\n *\n * @example\n * ```tsx\n * const { processPayment, isProcessing, error } = usePayment({\n * onPaymentSuccess: (result) => router.push('/confirmation'),\n * onPaymentFailed: (result) => toast.error(result.error),\n * });\n *\n * // On submit \u2014 one function handles everything\n * const result = await processPayment({\n * checkoutSessionId: session.id,\n * tagadaToken,\n * });\n * ```\n */\nexport function usePayment(options?: UsePaymentOptions): UsePaymentReturn {\n const client = useHeadlessClient();\n const [paymentSetup, setPaymentSetup] = useState<PaymentSetupConfig | null>(null);\n const [expressMethods, setExpressMethods] = useState<ExpressMethods | null>(null);\n const [storeConfig, setStoreConfig] = useState<StoreConfig | null>(null);\n const [isProcessing, setIsProcessing] = useState(false);\n const [result, setResult] = useState<PayResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const loadedRef = useRef(false);\n const redirectReturnProcessedRef = useRef(false);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // ---------------------------------------------------------------------------\n // Return-URL detection: auto-resume after 3DS / processor redirect\n // ---------------------------------------------------------------------------\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (redirectReturnProcessedRef.current) return;\n\n const params = new URLSearchParams(window.location.search);\n const paymentAction = params.get('paymentAction');\n const paymentActionStatus = params.get('paymentActionStatus');\n const paymentId = params.get('paymentId');\n\n if (paymentAction !== 'requireAction' || paymentActionStatus !== 'completed' || !paymentId) {\n return;\n }\n\n redirectReturnProcessedRef.current = true;\n setIsProcessing(true);\n setError(null);\n\n const resume = async () => {\n try {\n const resumeResult = await client.payment.resumeAfterRedirect(paymentId);\n\n // Clean payment-related query params from URL\n const cleanParams = new URLSearchParams(window.location.search);\n ['paymentAction', 'paymentActionStatus', 'paymentId', 'payment_intent', 'payment_intent_client_secret', 'source_type', 'redirect_status'].forEach(\n (p) => cleanParams.delete(p),\n );\n const newUrl = cleanParams.toString()\n ? `${window.location.pathname}?${cleanParams.toString()}`\n : window.location.pathname;\n window.history.replaceState({}, document.title, newUrl);\n\n if (resumeResult.status === 'succeeded') {\n optionsRef.current?.onPaymentSuccess?.(resumeResult);\n } else if (resumeResult.status === 'failed') {\n setError(new Error(resumeResult.error));\n optionsRef.current?.onPaymentFailed?.(resumeResult);\n }\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsProcessing(false);\n }\n };\n\n void resume();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ---------------------------------------------------------------------------\n // Load payment setup\n // ---------------------------------------------------------------------------\n const loadPaymentSetup = useCallback(async (\n checkoutSessionId: string,\n opts?: { paymentSetupConfig?: PaymentSetupConfig },\n ) => {\n if (loadedRef.current) return;\n loadedRef.current = true;\n const setupOpts = opts?.paymentSetupConfig\n ? { paymentSetupConfig: opts.paymentSetupConfig }\n : optionsRef.current?.paymentSetupConfig\n ? { paymentSetupConfig: optionsRef.current.paymentSetupConfig }\n : undefined;\n try {\n const [setup, express, config] = await Promise.all([\n client.payment.getPaymentSetup(checkoutSessionId, setupOpts),\n client.payment.getExpressMethods(checkoutSessionId, setupOpts),\n client.payment.getStoreConfig(),\n ]);\n setPaymentSetup(setup);\n setExpressMethods(express);\n setStoreConfig(config);\n } catch (err) {\n loadedRef.current = false;\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n // ---------------------------------------------------------------------------\n // processPayment \u2014 high-level, handles everything\n // ---------------------------------------------------------------------------\n const processPayment = useCallback(\n async (opts: ProcessPaymentOptions): Promise<ProcessPaymentResult> => {\n setIsProcessing(true);\n setError(null);\n try {\n const payResult = await client.payment.processPayment(opts);\n\n if (payResult.status === 'requires_redirect') {\n // Browser redirect \u2014 the hook will resume on return via the useEffect above\n if (payResult.method === 'POST' && payResult.postData) {\n const form = document.createElement('form');\n form.method = 'POST';\n form.action = payResult.redirectUrl;\n for (const [key, value] of Object.entries(payResult.postData)) {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = key;\n input.value = value;\n form.appendChild(input);\n }\n document.body.appendChild(form);\n form.submit();\n } else {\n window.location.href = payResult.redirectUrl;\n }\n // Don't setIsProcessing(false) \u2014 page is navigating away\n return payResult;\n }\n\n if (payResult.status === 'succeeded') {\n optionsRef.current?.onPaymentSuccess?.(payResult);\n } else if (payResult.status === 'failed') {\n setError(new Error(payResult.error));\n optionsRef.current?.onPaymentFailed?.(payResult);\n }\n\n return payResult;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n return { status: 'failed', error: e.message };\n } finally {\n setIsProcessing(false);\n }\n },\n [client],\n );\n\n // ---------------------------------------------------------------------------\n // Low-level pay (raw API, no action handling)\n // ---------------------------------------------------------------------------\n const wrapAsync = useCallback(\n <T,>(fn: () => Promise<T>) =>\n async (): Promise<T> => {\n setIsProcessing(true);\n setError(null);\n try {\n const r = await fn();\n return r;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsProcessing(false);\n }\n },\n [],\n );\n\n const pay = useCallback(\n async (opts: PayOptions): Promise<PayResult> => {\n setIsProcessing(true);\n setError(null);\n try {\n const r = await client.payment.pay(opts);\n setResult(r);\n return r;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsProcessing(false);\n }\n },\n [client],\n );\n\n const tokenizeCard = useCallback(\n (card: { cardNumber: string; expiryDate: string; cvc: string; cardholderName?: string }) =>\n client.payment.tokenizeCard(card),\n [client],\n );\n\n const processApplePay = useCallback(\n async (opts: { checkoutSessionId: string; applePayToken: unknown }) => {\n const fn = wrapAsync(() => client.payment.processApplePay(opts));\n const r = await fn();\n setResult(r);\n return r;\n },\n [client, wrapAsync],\n );\n\n const processGooglePay = useCallback(\n async (opts: { checkoutSessionId: string; googlePayToken: string }) => {\n const fn = wrapAsync(() => client.payment.processGooglePay(opts));\n const r = await fn();\n setResult(r);\n return r;\n },\n [client, wrapAsync],\n );\n\n const processApm = useCallback(\n async (opts: { checkoutSessionId: string; paymentMethod: string; processorId: string }) => {\n const fn = wrapAsync(() => client.payment.processApm(opts));\n const r = await fn();\n setResult(r);\n return r;\n },\n [client, wrapAsync],\n );\n\n const pollStatus = useCallback(\n (paymentId: string) => client.payment.pollPaymentStatus(paymentId),\n [client],\n );\n\n return {\n paymentSetup,\n expressMethods,\n storeConfig,\n isProcessing,\n result,\n error,\n loadPaymentSetup,\n processPayment,\n pay,\n tokenizeCard,\n processApplePay,\n processGooglePay,\n processApm,\n pollStatus,\n };\n}\n", "import { useState, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { Offer, OfferPreview, OfferPayResult } from '../../core/types.js';\n\nexport interface UseOffersReturn {\n /** Current loaded offer. */\n offer: Offer | null;\n /** Current preview (pricing breakdown). */\n preview: OfferPreview | null;\n /** Whether an operation is in progress. */\n isLoading: boolean;\n /** Last error. */\n error: Error | null;\n\n /** Get a single offer by ID. */\n getOffer: (offerId: string) => Promise<Offer>;\n /** List offers for the store, optionally filtered by type or IDs. */\n listOffers: (opts?: { type?: 'upsell' | 'orderbump'; ids?: string[] }) => Promise<Offer[]>;\n /** Preview offer pricing (line items with amounts). */\n previewOffer: (opts: {\n offerId: string;\n currency?: string;\n lineItems?: Array<{ variantId: string; quantity: number }>;\n }) => Promise<OfferPreview>;\n /** Pay a previewed offer (one-click upsell charge using stored instrument). */\n payPreviewedOffer: (opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }) => Promise<OfferPayResult>;\n\n /** Toggle an order bump on/off within a checkout session. */\n toggleOrderBump: (opts: {\n checkoutSessionId: string;\n orderBumpOfferId: string;\n selected: boolean;\n }) => Promise<unknown>;\n\n /** List post-purchase offers for an order. */\n listPostPurchaseOffers: (orderId: string) => Promise<Offer[]>;\n /** Accept a post-purchase offer. */\n acceptPostPurchaseOffer: (opts: {\n orderId: string;\n offerId: string;\n items?: Array<{ variantId: string; quantity: number }>;\n }) => Promise<{ success: boolean; error?: string }>;\n /** Decline a post-purchase offer. */\n declinePostPurchaseOffer: (opts: {\n orderId: string;\n offerId: string;\n }) => Promise<{ success: boolean; error?: string }>;\n}\n\n/**\n * React hook for offers \u2014 upsells, order bumps, and post-purchase offers.\n *\n * @example\n * ```tsx\n * const { getOffer, previewOffer, payPreviewedOffer, listPostPurchaseOffers } = useOffers();\n *\n * // Preview an upsell offer\n * const preview = await previewOffer({ offerId: 'offer_xxx' });\n *\n * // One-click pay (reuses stored instrument from main order)\n * await payPreviewedOffer({ offerId: 'offer_xxx', mainOrderId: 'order_yyy' });\n *\n * // Or list post-purchase offers\n * const ppOffers = await listPostPurchaseOffers('order_yyy');\n * ```\n */\nexport function useOffers(): UseOffersReturn {\n const client = useHeadlessClient();\n const [offer, setOffer] = useState<Offer | null>(null);\n const [preview, setPreview] = useState<OfferPreview | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const getOffer = useCallback(\n (offerId: string) =>\n wrap(async () => {\n const o = await client.offers.getOffer(offerId);\n setOffer(o);\n return o;\n }),\n [client, wrap],\n );\n\n const listOffers = useCallback(\n (opts?: { type?: 'upsell' | 'orderbump'; ids?: string[] }) =>\n client.offers.listOffers(opts),\n [client],\n );\n\n const previewOffer = useCallback(\n (opts: { offerId: string; currency?: string; lineItems?: Array<{ variantId: string; quantity: number }> }) =>\n wrap(async () => {\n const p = await client.offers.previewOffer(opts);\n setPreview(p);\n return p;\n }),\n [client, wrap],\n );\n\n const payPreviewedOffer = useCallback(\n (opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }) => wrap(() => client.offers.payPreviewedOffer(opts)),\n [client, wrap],\n );\n\n const toggleOrderBump = useCallback(\n (opts: { checkoutSessionId: string; orderBumpOfferId: string; selected: boolean }) =>\n client.offers.toggleOrderBump(opts),\n [client],\n );\n\n const listPostPurchaseOffers = useCallback(\n (orderId: string) => client.offers.listPostPurchaseOffers(orderId),\n [client],\n );\n\n const acceptPostPurchaseOffer = useCallback(\n (opts: { orderId: string; offerId: string; items?: Array<{ variantId: string; quantity: number }> }) =>\n wrap(() => client.offers.acceptPostPurchaseOffer(opts)),\n [client, wrap],\n );\n\n const declinePostPurchaseOffer = useCallback(\n (opts: { orderId: string; offerId: string }) =>\n wrap(() => client.offers.declinePostPurchaseOffer(opts)),\n [client, wrap],\n );\n\n return {\n offer,\n preview,\n isLoading,\n error,\n getOffer,\n listOffers,\n previewOffer,\n payPreviewedOffer,\n toggleOrderBump,\n listPostPurchaseOffers,\n acceptPostPurchaseOffer,\n declinePostPurchaseOffer,\n };\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { Customer, Order, Subscription } from '../../core/types.js';\n\nexport interface UseCustomerReturn {\n customer: Customer | null;\n orders: Order[];\n subscriptions: Subscription[];\n isLoading: boolean;\n error: Error | null;\n /** Load customer profile by ID. */\n loadCustomer: (customerId: string) => Promise<void>;\n /** Load customer orders. */\n loadOrders: (customerId: string) => Promise<void>;\n /** Load customer subscriptions. */\n loadSubscriptions: (customerId: string) => Promise<void>;\n /** Update customer profile. */\n updateProfile: (customerId: string, data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone'>>) => Promise<void>;\n}\n\n/**\n * React hook for customer data -- profile, orders, subscriptions.\n *\n * @param customerId - Auto-loads the customer profile when provided.\n *\n * @example\n * ```tsx\n * const { customer, orders, loadOrders } = useCustomer(session?.customer?.id);\n * ```\n */\nexport function useCustomer(customerId?: string | null): UseCustomerReturn {\n const client = useHeadlessClient();\n const [customer, setCustomer] = useState<Customer | null>(null);\n const [orders, setOrders] = useState<Order[]>([]);\n const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const loadCustomer = useCallback(async (id: string) => {\n setIsLoading(true);\n setError(null);\n try {\n const c = await client.customer.getProfile(id);\n setCustomer(c);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n const loadOrders = useCallback(async (id: string) => {\n try {\n const res = await client.customer.getOrders(id);\n setOrders(res.orders);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n const loadSubscriptions = useCallback(async (id: string) => {\n try {\n const subs = await client.customer.getSubscriptions(id);\n setSubscriptions(subs);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n const updateProfile = useCallback(async (\n id: string,\n data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone'>>,\n ) => {\n try {\n const updated = await client.customer.updateProfile(id, data);\n setCustomer(updated);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [client]);\n\n useEffect(() => {\n if (customerId) loadCustomer(customerId);\n }, [customerId, loadCustomer]);\n\n return {\n customer,\n orders,\n subscriptions,\n isLoading,\n error,\n loadCustomer,\n loadOrders,\n loadSubscriptions,\n updateProfile,\n };\n}\n", "import { useState, useCallback } from 'react';\nimport { useHeadlessClient } from '../provider.js';\nimport type { CatalogProduct } from '../../core/types.js';\n\nexport interface UseCatalogReturn {\n products: CatalogProduct[];\n isLoading: boolean;\n error: Error | null;\n /** Fetch all products for the store. */\n loadProducts: (opts?: { productIds?: string[]; variantIds?: string[] }) => Promise<CatalogProduct[]>;\n /** Fetch a single product by ID. */\n loadProduct: (productId: string) => Promise<CatalogProduct | null>;\n}\n\n/**\n * React hook for browsing the store's product catalog.\n *\n * @example\n * ```tsx\n * const { products, isLoading, loadProducts } = useCatalog();\n *\n * useEffect(() => { loadProducts(); }, []);\n * ```\n */\nexport function useCatalog(): UseCatalogReturn {\n const client = useHeadlessClient();\n const [products, setProducts] = useState<CatalogProduct[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const loadProducts = useCallback(async (opts?: { productIds?: string[]; variantIds?: string[] }) => {\n setIsLoading(true);\n setError(null);\n try {\n const items = await client.catalog.getProducts(opts);\n setProducts(items);\n return items;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n const loadProduct = useCallback(async (productId: string) => {\n setIsLoading(true);\n setError(null);\n try {\n return await client.catalog.getProduct(productId);\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n return {\n products,\n isLoading,\n error,\n loadProducts,\n loadProduct,\n };\n}\n", "/**\n * React hook for Google Places Autocomplete \u2014 handles script injection,\n * debounced prediction search, place detail fetching, and address extraction.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n GoogleAutocompleteCore,\n loadGoogleMapsScript,\n type GooglePrediction,\n type GooglePlaceDetails,\n type ExtractedAddress,\n type FormattedAddress,\n} from '../../core/helpers/autocomplete.js';\n\nexport type { GooglePrediction, GooglePlaceDetails, ExtractedAddress, FormattedAddress };\n\nexport interface UseGoogleAutocompleteOptions {\n apiKey: string;\n language?: string;\n region?: string;\n version?: string;\n /** Defer script loading until searchPlaces() is first called. Default: false. */\n defer?: boolean;\n}\n\nexport interface UseGoogleAutocompleteReturn {\n predictions: GooglePrediction[];\n isLoading: boolean;\n isScriptLoaded: boolean;\n searchPlaces: (input: string, countryRestriction?: string) => void;\n getPlaceDetails: (placeId: string) => Promise<GooglePlaceDetails | null>;\n extractAddressComponents: (place: GooglePlaceDetails) => ExtractedAddress;\n extractFormattedAddress: (place: GooglePlaceDetails) => FormattedAddress;\n clearPredictions: () => void;\n}\n\nexport function useGoogleAutocomplete(options: UseGoogleAutocompleteOptions): UseGoogleAutocompleteReturn {\n const { apiKey, language, region, version, defer = false } = options;\n\n const [predictions, setPredictions] = useState<GooglePrediction[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [isScriptLoaded, setIsScriptLoaded] = useState(false);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingRef = useRef<{ input: string; country?: string } | null>(null);\n\n const inject = useCallback(() => {\n loadGoogleMapsScript(apiKey, { language, region, version }).then(() => setIsScriptLoaded(true));\n }, [apiKey, language, region, version]);\n\n // Eager load unless defer\n useEffect(() => {\n if (!apiKey || defer) return;\n inject();\n }, [apiKey, defer, inject]);\n\n // Replay pending search after deferred load\n useEffect(() => {\n if (isScriptLoaded && pendingRef.current) {\n const { input, country } = pendingRef.current;\n pendingRef.current = null;\n doSearch(input, country);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isScriptLoaded]);\n\n const doSearch = useCallback(\n (input: string, countryRestriction?: string) => {\n if (!isScriptLoaded) {\n if (defer) { pendingRef.current = { input, country: countryRestriction }; inject(); }\n return;\n }\n\n if (input.length < 3) { setPredictions([]); return; }\n\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(async () => {\n setIsLoading(true);\n const results = await GoogleAutocompleteCore.searchPlaces(input, {\n componentRestrictions: countryRestriction ? { country: countryRestriction.toLowerCase() } : undefined,\n });\n setPredictions(results);\n setIsLoading(false);\n }, 300);\n },\n [isScriptLoaded, defer, inject],\n );\n\n const getPlaceDetails = useCallback(\n (placeId: string) => GoogleAutocompleteCore.getPlaceDetails(placeId),\n [],\n );\n\n const extractAddressComponents = useCallback(\n (place: GooglePlaceDetails) => GoogleAutocompleteCore.extractAddressComponents(place),\n [],\n );\n\n const extractFormattedAddress = useCallback(\n (place: GooglePlaceDetails) => GoogleAutocompleteCore.extractFormattedAddress(place),\n [],\n );\n\n const clearPredictions = useCallback(() => setPredictions([]), []);\n\n return {\n predictions,\n isLoading,\n isScriptLoaded,\n searchPlaces: doSearch,\n getPlaceDetails,\n extractAddressComponents,\n extractFormattedAddress,\n clearPredictions,\n };\n}\n", "/**\n * Google Places Autocomplete \u2014 script injection + address extraction.\n * Works standalone (no external dependencies beyond the Google Maps JS API).\n */\n\ndeclare global {\n interface Window {\n google?: {\n maps?: {\n places?: {\n AutocompleteService: new () => any;\n PlacesService: new (el: any) => any;\n PlacesServiceStatus: { OK: string; ZERO_RESULTS: string };\n };\n Map: new (el: HTMLElement) => any;\n };\n };\n }\n}\n\nexport interface GooglePrediction {\n place_id: string;\n description: string;\n structured_formatting?: { main_text: string; secondary_text: string };\n}\n\nexport interface GooglePlaceDetails {\n place_id: string;\n formatted_address: string;\n address_components: Array<{ long_name: string; short_name: string; types: string[] }>;\n geometry?: { location: { lat: number; lng: number } };\n}\n\nexport interface ExtractedAddress {\n subpremise: string;\n streetNumber: string;\n route: string;\n locality: string;\n administrativeAreaLevel1: string;\n administrativeAreaLevel1Long: string;\n administrativeAreaLevel2: string;\n administrativeAreaLevel2Long: string;\n country: string;\n postalCode: string;\n fullStreetAddress: string;\n}\n\nexport interface FormattedAddress {\n address1: string;\n city: string;\n country: string;\n state: string;\n postal: string;\n}\n\n// ---------------------------------------------------------------------------\n// Script injection\n// ---------------------------------------------------------------------------\n\nlet scriptInjected = false;\nlet scriptReady = false;\nconst readyCallbacks: Array<() => void> = [];\n\nfunction onScriptReady() {\n scriptReady = true;\n for (const cb of readyCallbacks) cb();\n readyCallbacks.length = 0;\n}\n\n/**\n * Inject the Google Maps JS SDK into the page (idempotent).\n * Resolves once `window.google.maps.places` is available.\n */\nexport function loadGoogleMapsScript(\n apiKey: string,\n opts: { language?: string; region?: string; version?: string } = {},\n): Promise<void> {\n if (scriptReady || window.google?.maps?.places) {\n onScriptReady();\n return Promise.resolve();\n }\n\n if (scriptInjected) {\n return new Promise<void>((resolve) => readyCallbacks.push(resolve));\n }\n\n scriptInjected = true;\n\n return new Promise<void>((resolve, reject) => {\n readyCallbacks.push(resolve);\n\n const existing = document.querySelector('script[src*=\"maps.googleapis.com\"]');\n if (existing) {\n const poll = () => {\n if (window.google?.maps?.places) { onScriptReady(); }\n else { setTimeout(poll, 100); }\n };\n poll();\n return;\n }\n\n const params = new URLSearchParams({\n key: apiKey,\n libraries: 'places',\n v: opts.version ?? 'weekly',\n });\n if (opts.language) params.set('language', opts.language);\n if (opts.region) params.set('region', opts.region);\n\n const script = document.createElement('script');\n script.src = `https://maps.googleapis.com/maps/api/js?${params}`;\n script.async = true;\n script.defer = true;\n script.onload = () => onScriptReady();\n script.onerror = () => reject(new Error('Failed to load Google Maps script'));\n document.head.appendChild(script);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Core class\n// ---------------------------------------------------------------------------\n\nexport class GoogleAutocompleteCore {\n /** Search for address predictions. */\n static async searchPlaces(\n input: string,\n options: { types?: string[]; componentRestrictions?: { country: string } } = {},\n ): Promise<GooglePrediction[]> {\n if (!window.google?.maps?.places || !input.trim()) return [];\n\n const service = new window.google.maps.places.AutocompleteService();\n return new Promise((resolve) => {\n service.getPlacePredictions(\n { input, types: options.types ?? ['address'], componentRestrictions: options.componentRestrictions },\n (predictions: GooglePrediction[] | null, status: string) => {\n resolve(status === window.google?.maps?.places?.PlacesServiceStatus.OK && predictions ? predictions : []);\n },\n );\n });\n }\n\n /** Get full place details by place_id. */\n static async getPlaceDetails(placeId: string): Promise<GooglePlaceDetails | null> {\n if (!window.google?.maps?.places) return null;\n\n const svc = new window.google.maps.places.PlacesService(document.createElement('div'));\n return new Promise((resolve) => {\n svc.getDetails(\n { placeId, fields: ['place_id', 'formatted_address', 'address_components', 'geometry'] },\n (place: GooglePlaceDetails | null, status: string) => {\n resolve(status === window.google?.maps?.places?.PlacesServiceStatus.OK && place ? place : null);\n },\n );\n });\n }\n\n /** Extract structured address fields from a Google PlaceDetails result. */\n static extractAddressComponents(place: GooglePlaceDetails): ExtractedAddress {\n const out: ExtractedAddress = {\n subpremise: '', streetNumber: '', route: '', locality: '',\n administrativeAreaLevel1: '', administrativeAreaLevel1Long: '',\n administrativeAreaLevel2: '', administrativeAreaLevel2Long: '',\n country: '', postalCode: '', fullStreetAddress: '',\n };\n\n let premise = '';\n let neighborhood = '';\n let sublocality5 = '', sublocality4 = '', sublocality3 = '', sublocality2 = '', sublocality1 = '';\n let postalTown = '';\n\n for (const c of place.address_components ?? []) {\n const t = c.types;\n if (t.includes('subpremise')) out.subpremise = c.long_name;\n if (t.includes('street_number')) out.streetNumber = c.long_name;\n if (t.includes('premise')) premise = c.long_name;\n if (t.includes('route')) out.route = c.long_name;\n if (t.includes('neighborhood')) neighborhood = c.long_name;\n if (t.includes('sublocality_level_5')) sublocality5 = c.long_name;\n if (t.includes('sublocality_level_4')) sublocality4 = c.long_name;\n if (t.includes('sublocality_level_3')) sublocality3 = c.long_name;\n if (t.includes('sublocality_level_2')) sublocality2 = c.long_name;\n if (t.includes('sublocality_level_1')) sublocality1 = c.long_name;\n if (t.includes('locality')) out.locality = c.long_name;\n if (t.includes('postal_town')) postalTown = c.long_name;\n if (t.includes('administrative_area_level_2')) {\n out.administrativeAreaLevel2 = c.short_name;\n out.administrativeAreaLevel2Long = c.long_name;\n }\n if (t.includes('administrative_area_level_1')) {\n out.administrativeAreaLevel1 = c.short_name;\n out.administrativeAreaLevel1Long = c.long_name;\n }\n if (t.includes('country')) out.country = c.short_name;\n if (t.includes('postal_code')) out.postalCode = c.long_name;\n }\n\n // Locality fallbacks (UK postal_town, Asian sublocalities)\n if (!out.locality) out.locality = postalTown || sublocality2 || sublocality1 || '';\n\n // French-style fallback: use d\u00E9partement when r\u00E9gion is missing\n if (!out.administrativeAreaLevel1 && out.administrativeAreaLevel2) {\n out.administrativeAreaLevel1 = out.administrativeAreaLevel2Long || out.administrativeAreaLevel2;\n out.administrativeAreaLevel1Long = out.administrativeAreaLevel2Long;\n }\n\n // Build full street address\n const buildingNumber = out.streetNumber || premise;\n const streetName = out.route || sublocality5 || sublocality4 || sublocality3 || neighborhood;\n\n if (out.subpremise && buildingNumber && streetName) {\n out.fullStreetAddress = `${out.subpremise}/${buildingNumber} ${streetName}`;\n } else if (buildingNumber && streetName) {\n if (premise && sublocality4 && sublocality3) {\n let addr = `${sublocality3}-${sublocality4}-${premise}`;\n if (sublocality2) addr = `${addr} ${sublocality2}`;\n out.fullStreetAddress = addr;\n } else {\n out.fullStreetAddress = `${buildingNumber} ${streetName}`;\n }\n } else if (streetName) {\n out.fullStreetAddress = streetName;\n } else if (buildingNumber) {\n out.fullStreetAddress = buildingNumber;\n }\n\n out.fullStreetAddress = out.fullStreetAddress.trim();\n return out;\n }\n\n /** Shorthand: extract into the flat shape used by address forms. */\n static extractFormattedAddress(place: GooglePlaceDetails): FormattedAddress {\n const a = GoogleAutocompleteCore.extractAddressComponents(place);\n return {\n address1: a.fullStreetAddress,\n city: a.locality,\n country: a.country,\n state: a.administrativeAreaLevel1,\n postal: a.postalCode,\n };\n }\n}\n", "/**\n * React hooks for ISO country/region data \u2014 CDN-backed,\n * with Google Places \u2192 ISO region mapping.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n ISODataCore,\n type ISOCountry,\n type ISORegion,\n type SupportedLanguage,\n} from '../../core/helpers/countries.js';\nimport { ensureGeoDataLoaded, isLanguageLoaded } from '../../core/helpers/iso3166.js';\n\nexport type { ISOCountry, ISORegion, SupportedLanguage };\n\n// ---------------------------------------------------------------------------\n// useISOData \u2014 full access to countries, regions, and Google\u2192ISO mapping\n// ---------------------------------------------------------------------------\n\nexport interface UseISODataReturn {\n countries: Record<string, ISOCountry>;\n getRegions: (countryCode: string) => ISORegion[];\n findRegion: (countryCode: string, regionCode: string) => ISORegion | null;\n mapGoogleToISO: (googleState: string, googleStateLong: string, countryCode: string) => ISORegion | null;\n isLoaded: boolean;\n}\n\nexport function useISOData(language: SupportedLanguage = 'en'): UseISODataReturn {\n const [isLoaded, setIsLoaded] = useState(isLanguageLoaded(language));\n\n useEffect(() => {\n let cancelled = false;\n ensureGeoDataLoaded(language)\n .then(() => { if (!cancelled) setIsLoaded(true); })\n .catch((err) => console.error('[headless-sdk] Failed to load geodata:', err));\n return () => { cancelled = true; };\n }, [language]);\n\n return useMemo(() => {\n if (!isLoaded) {\n return {\n countries: {},\n getRegions: () => [],\n findRegion: () => null,\n mapGoogleToISO: () => null,\n isLoaded: false,\n };\n }\n\n return {\n countries: ISODataCore.getCountries(language),\n getRegions: (cc: string) => ISODataCore.getRegions(cc, language),\n findRegion: (cc: string, rc: string) => ISODataCore.findRegion(cc, rc, language),\n mapGoogleToISO: (gs: string, gsl: string, cc: string) => ISODataCore.mapGoogleToISO(gs, gsl, cc, language),\n isLoaded: true,\n };\n }, [language, isLoaded]);\n}\n\n// ---------------------------------------------------------------------------\n// useCountryOptions \u2014 countries as select options\n// ---------------------------------------------------------------------------\n\nexport function useCountryOptions(language: SupportedLanguage = 'en'): Array<{ value: string; label: string }> {\n const { countries, isLoaded } = useISOData(language);\n return useMemo(() => {\n if (!isLoaded) return [];\n return Object.values(countries)\n .map((c) => ({ value: c.iso, label: c.name }))\n .sort((a, b) => a.label.localeCompare(b.label));\n }, [countries, isLoaded]);\n}\n\n// ---------------------------------------------------------------------------\n// useRegionOptions \u2014 regions/states for a country as select options\n// ---------------------------------------------------------------------------\n\nexport function useRegionOptions(\n countryCode: string,\n language: SupportedLanguage = 'en',\n): Array<{ value: string; label: string }> {\n const { getRegions, isLoaded } = useISOData(language);\n return useMemo(() => {\n if (!isLoaded || !countryCode) return [];\n return getRegions(countryCode)\n .map((r) => ({ value: r.iso, label: r.name }))\n .sort((a, b) => a.label.localeCompare(b.label));\n }, [countryCode, getRegions, isLoaded]);\n}\n", "/**\n * Geodata \u2014 CDN-backed country/region data.\n *\n * Fetches slim JSON from Vercel Blob CDN on demand:\n * - countries.json (~10KB) \u2014 fetched once on first getCountries() call\n * - regions.json (~95KB) \u2014 fetched lazily on first getStatesForCountry() call\n *\n * Both are cached in memory after first fetch.\n */\n\nconst GEODATA_CDN_BASE = 'https://cvwnizdbugpz6jwk.public.blob.vercel-storage.com/geodata/v1';\n\nexport const AVAILABLE_LANGUAGES = ['en', 'ru', 'de', 'da', 'fr', 'es', 'zh', 'hi', 'pt', 'ja', 'ar', 'it', 'he'] as const;\nexport type SupportedLanguage = (typeof AVAILABLE_LANGUAGES)[number];\n\nexport interface Country {\n code: string;\n name: string;\n iso3?: string;\n numeric?: number;\n}\n\nexport interface State {\n code: string;\n name: string;\n countryCode: string;\n}\n\ninterface CdnCountries { [iso2: string]: { n: string; i3?: string; nu?: number } }\ninterface CdnRegions { [iso2: string]: [string, string][] }\n\nconst countriesCache = new Map<SupportedLanguage, CdnCountries>();\nconst regionsCache = new Map<SupportedLanguage, CdnRegions>();\nconst inflightCountries = new Map<SupportedLanguage, Promise<CdnCountries>>();\nconst inflightRegions = new Map<SupportedLanguage, Promise<CdnRegions>>();\n\nasync function fetchCountriesRaw(language: SupportedLanguage): Promise<CdnCountries> {\n const cached = countriesCache.get(language);\n if (cached) return cached;\n\n let inflight = inflightCountries.get(language);\n if (inflight) return inflight;\n\n inflight = (async () => {\n const url = `${GEODATA_CDN_BASE}/${language}/countries.json`;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geodata fetch failed: ${url} (${res.status})`);\n const data: CdnCountries = await res.json();\n countriesCache.set(language, data);\n inflightCountries.delete(language);\n return data;\n })();\n\n inflightCountries.set(language, inflight);\n return inflight;\n}\n\nasync function fetchRegionsRaw(language: SupportedLanguage): Promise<CdnRegions> {\n const cached = regionsCache.get(language);\n if (cached) return cached;\n\n let inflight = inflightRegions.get(language);\n if (inflight) return inflight;\n\n inflight = (async () => {\n const url = `${GEODATA_CDN_BASE}/${language}/regions.json`;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geodata fetch failed: ${url} (${res.status})`);\n const data: CdnRegions = await res.json();\n regionsCache.set(language, data);\n inflightRegions.delete(language);\n return data;\n })();\n\n inflightRegions.set(language, inflight);\n return inflight;\n}\n\nfunction getCountriesCached(language: SupportedLanguage): CdnCountries {\n return countriesCache.get(language) || countriesCache.get('en') || {};\n}\n\nfunction getRegionsCached(language: SupportedLanguage): CdnRegions {\n return regionsCache.get(language) || regionsCache.get('en') || {};\n}\n\n/** Fetch countries + regions from CDN for a language. Call before sync getters. */\nexport async function ensureGeoDataLoaded(language: SupportedLanguage = 'en'): Promise<void> {\n await Promise.all([fetchCountriesRaw(language), fetchRegionsRaw(language)]);\n}\n\nexport const getCountries = (language: SupportedLanguage = 'en'): Country[] => {\n const raw = getCountriesCached(language);\n return Object.entries(raw)\n .map(([code, c]) => ({ code, name: c.n, iso3: c.i3, numeric: c.nu }))\n .sort((a, b) => a.name.localeCompare(b.name));\n};\n\nexport const getStatesForCountry = (countryCode: string, language: SupportedLanguage = 'en'): State[] => {\n const raw = getRegionsCached(language);\n const tuples = raw[countryCode];\n if (!tuples) return [];\n return tuples\n .map(([iso, name]) => ({ code: iso, name, countryCode }))\n .sort((a, b) => a.name.localeCompare(b.name));\n};\n\nexport function isLanguageLoaded(language: SupportedLanguage): boolean {\n return countriesCache.has(language);\n}\n", "/**\n * ISO country/region helpers \u2014 countries list, regions by country,\n * and Google Places state \u2192 ISO region mapping.\n */\n\nimport {\n getCountries,\n getStatesForCountry,\n ensureGeoDataLoaded,\n isLanguageLoaded,\n AVAILABLE_LANGUAGES,\n type SupportedLanguage,\n type Country,\n type State,\n} from './iso3166.js';\n\nexport type { SupportedLanguage, Country, State };\nexport { AVAILABLE_LANGUAGES };\n\nexport interface ISOCountry {\n iso: string;\n iso3: string;\n numeric: number;\n name: string;\n}\n\nexport interface ISORegion {\n iso: string;\n name: string;\n}\n\nexport class ISODataCore {\n /** Fetch countries + regions from CDN for a language. Call before sync getters. */\n static ensureLoaded(language: SupportedLanguage = 'en'): Promise<void> {\n return ensureGeoDataLoaded(language);\n }\n\n /** Get all countries as a Record keyed by ISO code. */\n static getCountries(language: SupportedLanguage = 'en'): Record<string, ISOCountry> {\n const arr = getCountries(language);\n const result: Record<string, ISOCountry> = {};\n for (const c of arr) {\n result[c.code] = { iso: c.code, iso3: c.iso3 ?? '', numeric: c.numeric ?? 0, name: c.name };\n }\n return result;\n }\n\n /** Get all countries as a sorted array of { value, label } for select inputs. */\n static getCountryOptions(language: SupportedLanguage = 'en'): Array<{ value: string; label: string }> {\n return getCountries(language).map((c) => ({ value: c.code, label: c.name }));\n }\n\n /** Get regions/states for a country. */\n static getRegions(countryCode: string, language: SupportedLanguage = 'en'): ISORegion[] {\n return getStatesForCountry(countryCode, language).map((s) => ({ iso: s.code, name: s.name }));\n }\n\n /** Get regions as a sorted array of { value, label } for select inputs. */\n static getRegionOptions(countryCode: string, language: SupportedLanguage = 'en'): Array<{ value: string; label: string }> {\n return ISODataCore.getRegions(countryCode, language).map((r) => ({ value: r.iso, label: r.name }));\n }\n\n /** Find a specific region by ISO code. */\n static findRegion(countryCode: string, regionCode: string, language: SupportedLanguage = 'en'): ISORegion | null {\n return ISODataCore.getRegions(countryCode, language).find((r) => r.iso === regionCode) ?? null;\n }\n\n /**\n * Map a Google Places administrative_area to an ISO region.\n * Tries exact ISO match, then name match, then partial match.\n */\n static mapGoogleToISO(\n googleState: string,\n googleStateLong: string,\n countryCode: string,\n language: SupportedLanguage = 'en',\n ): ISORegion | null {\n const regions = ISODataCore.getRegions(countryCode, language);\n if (regions.length === 0) return null;\n\n let match = regions.find((r) => r.iso === googleState);\n if (match) return match;\n\n match = regions.find((r) => r.name.toLowerCase() === googleState.toLowerCase());\n if (match) return match;\n\n match = regions.find((r) => r.name.toLowerCase() === googleStateLong.toLowerCase());\n if (match) return match;\n\n match = regions.find(\n (r) =>\n r.name.toLowerCase().includes(googleStateLong.toLowerCase()) ||\n googleStateLong.toLowerCase().includes(r.name.toLowerCase()),\n );\n\n return match ?? null;\n }\n\n static isLanguageLoaded(language: SupportedLanguage): boolean {\n return isLanguageLoaded(language);\n }\n\n static getAvailableLanguages(): readonly SupportedLanguage[] {\n return AVAILABLE_LANGUAGES;\n }\n}\n", "/**\n * Currency formatting utilities \u2014 symbol lookup, decimal handling,\n * and Intl.NumberFormat-based money formatting from minor units (cents).\n */\n\nexport interface Currency {\n code: string;\n symbol: string;\n name: string;\n decimalPlaces: number;\n}\n\nconst SYMBOLS: Record<string, string> = {\n USD: '$', EUR: '\u20AC', GBP: '\u00A3', JPY: '\u00A5', CAD: 'C$', AUD: 'A$', CHF: 'CHF',\n CNY: '\u00A5', SEK: 'kr', NOK: 'kr', DKK: 'kr', PLN: 'z\u0142', CZK: 'K\u010D', HUF: 'Ft',\n RON: 'lei', BGN: '\u043B\u0432', HRK: 'kn', RUB: '\u20BD', UAH: '\u20B4', TRY: '\u20BA', BRL: 'R$',\n MXN: '$', ZAR: 'R', INR: '\u20B9', KRW: '\u20A9', THB: '\u0E3F', VND: '\u20AB', IDR: 'Rp',\n MYR: 'RM', SGD: 'S$', PHP: '\u20B1', TWD: 'NT$', HKD: 'HK$', ILS: '\u20AA', AED: '\u062F.\u0625',\n SAR: '\u0631.\u0633', QAR: '\u0631.\u0642', KWD: '\u062F.\u0643', BHD: '\u062F.\u0628', OMR: '\u0631.\u0639.', EGP: '\u00A3',\n NGN: '\u20A6', KES: 'KSh', GHS: '\u20B5', COP: '$', ARS: '$', CLP: '$', PEN: 'S/',\n CRC: '\u20A1', DOP: 'RD$', JMD: 'J$', BOB: 'Bs', PYG: '\u20B2', GTQ: 'Q',\n NIO: 'C$', PAB: 'B/.', PKR: '\u20A8', BDT: '\u09F3', LKR: '\u20A8', NPR: '\u20A8',\n GEL: '\u20BE', AMD: '\u058F', AZN: '\u20BC', KZT: '\u20B8',\n};\n\nconst NAMES: Record<string, string> = {\n USD: 'US Dollar', EUR: 'Euro', GBP: 'British Pound', JPY: 'Japanese Yen',\n CAD: 'Canadian Dollar', AUD: 'Australian Dollar', CHF: 'Swiss Franc',\n CNY: 'Chinese Yuan', SEK: 'Swedish Krona', NOK: 'Norwegian Krone',\n DKK: 'Danish Krone', PLN: 'Polish Zloty', CZK: 'Czech Koruna', HUF: 'Hungarian Forint',\n BRL: 'Brazilian Real', MXN: 'Mexican Peso', INR: 'Indian Rupee', KRW: 'South Korean Won',\n THB: 'Thai Baht', SGD: 'Singapore Dollar', HKD: 'Hong Kong Dollar', TWD: 'Taiwan Dollar',\n ILS: 'Israeli Shekel', AED: 'UAE Dirham', SAR: 'Saudi Riyal', ZAR: 'South African Rand',\n TRY: 'Turkish Lira', RUB: 'Russian Ruble', NGN: 'Nigerian Naira',\n};\n\nconst ZERO_DECIMAL: Set<string> = new Set([\n 'JPY', 'KRW', 'VND', 'IDR', 'LAK', 'KHR', 'MMK', 'PYG',\n]);\n\nexport class CurrencyUtils {\n static getSymbol(code: string): string {\n return SYMBOLS[code] ?? code;\n }\n\n static getName(code: string): string {\n return NAMES[code] ?? code;\n }\n\n static getDecimalPlaces(code: string): number {\n return ZERO_DECIMAL.has(code) ? 0 : 2;\n }\n\n static getCurrency(code: string): Currency {\n return {\n code,\n symbol: CurrencyUtils.getSymbol(code),\n name: CurrencyUtils.getName(code),\n decimalPlaces: CurrencyUtils.getDecimalPlaces(code),\n };\n }\n}\n\n/**\n * Format an amount expressed in minor units (cents) into a locale-aware string.\n *\n * @example\n * formatMoney(12345, 'USD') // \"$123.45\"\n * formatMoney(10000, 'EUR', 'de-DE') // \"100,00 \u20AC\"\n * formatMoney(1000, 'JPY') // \"\u00A51,000\"\n */\nexport function formatMoney(amountMinorUnits: number, currencyCode = 'USD', locale = 'en-US'): string {\n const decimals = CurrencyUtils.getDecimalPlaces(currencyCode);\n const value = amountMinorUnits / (decimals === 0 ? 100 : Math.pow(10, decimals));\n\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(value);\n } catch {\n return `${CurrencyUtils.getSymbol(currencyCode)}${value.toFixed(decimals)}`;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["react_exports", "__export", "CurrencyUtils", "GoogleAutocompleteCore", "ISODataCore", "TagadaHeadlessProvider", "formatMoney", "loadGoogleMapsScript", "useCatalog", "useCheckout", "useCountryOptions", "useCustomer", "useGoogleAutocomplete", "useHeadlessClient", "useISOData", "useOffers", "usePayment", "useRegionOptions", "import_react", "TagadaError", "message", "code", "statusCode", "details", "TagadaAuthError", "TagadaValidationError", "errors", "TagadaNotFoundError", "resource", "id", "TagadaRateLimitError", "retryAfterMs", "TagadaNetworkError", "TagadaError", "message", "BASE_URLS", "HttpClient", "config", "environment", "override", "path", "options", "_a", "method", "body", "headers", "params", "token", "signal", "url", "qs", "k", "v", "str", "reqHeaders", "authToken", "controller", "timeoutId", "res", "text", "TagadaError", "err", "TagadaNetworkError", "parsed", "msg", "TagadaAuthError", "TagadaNotFoundError", "fieldErrors", "TagadaValidationError", "retryAfter", "TagadaRateLimitError", "CheckoutModule", "http", "storeId", "onTokenChange", "checkoutToken", "sessionToken", "opts", "_a", "params", "raw", "lineItems", "i", "body", "customerData", "res", "sessionId", "items", "customer", "addresses", "shipping", "billing", "effectiveShipping", "effectiveBilling", "differentBilling", "data", "a", "stripEmpty", "code", "promotionId", "promoId", "rateId", "cs", "orderSummaries", "summary", "sessionCurrency", "li", "price", "variant", "product", "currencyOpts", "priceEntry", "amount", "summaryItems", "s", "out", "v", "obj", "result", "k", "PaymentModule", "http", "storeId", "environment", "checkoutSessionId", "opts", "injected", "methods", "config", "m", "key", "_a", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "setup", "result", "base", "hasApplePay", "method", "res", "c", "card", "coreJs", "tokenizer", "sanitized", "tagadaToken", "rawToken", "payResult", "payment", "paymentId", "interval", "timeout", "start", "status", "r", "actionData", "redirect", "url", "session", "manager", "consecutiveErrors", "raw", "parsed", "OffersModule", "http", "storeId", "offerId", "opts", "_a", "url", "queryParts", "id", "orderId", "res", "CustomerModule", "http", "storeId", "customerId", "email", "data", "opts", "orderId", "subscriptionId", "CatalogModule", "http", "storeId", "opts", "_a", "_b", "body", "productId", "HeadlessClient", "config", "environment", "baseUrl", "HttpClient", "setToken", "token", "CheckoutModule", "PaymentModule", "OffersModule", "CustomerModule", "CatalogModule", "createHeadlessClient", "import_jsx_runtime", "TagadaHeadlessContext", "TagadaHeadlessProvider", "storeId", "environment", "apiKey", "baseUrl", "config", "children", "client", "createHeadlessClient", "value", "useHeadlessClient", "ctx", "import_react", "useCheckout", "checkoutToken", "sessionToken", "client", "useHeadlessClient", "session", "setSession", "isLoading", "setIsLoading", "error", "setError", "loadSession", "s", "err", "createSession", "opts", "result", "newUrl", "updateCart", "items", "updateCustomer", "customer", "updateAddress", "addresses", "updateCustomerAndAddress", "data", "applyPromo", "code", "removePromo", "promotionId", "getShippingRates", "selectShippingRate", "rateId", "import_react", "usePayment", "options", "client", "useHeadlessClient", "paymentSetup", "setPaymentSetup", "expressMethods", "setExpressMethods", "storeConfig", "setStoreConfig", "isProcessing", "setIsProcessing", "result", "setResult", "error", "setError", "loadedRef", "redirectReturnProcessedRef", "optionsRef", "params", "paymentAction", "paymentActionStatus", "paymentId", "_a", "_b", "_c", "_d", "resumeResult", "cleanParams", "p", "newUrl", "err", "loadPaymentSetup", "checkoutSessionId", "opts", "setupOpts", "setup", "express", "config", "processPayment", "payResult", "form", "key", "value", "input", "e", "wrapAsync", "fn", "pay", "r", "tokenizeCard", "card", "processApplePay", "processGooglePay", "processApm", "pollStatus", "import_react", "useOffers", "client", "useHeadlessClient", "offer", "setOffer", "preview", "setPreview", "isLoading", "setIsLoading", "error", "setError", "wrap", "fn", "err", "e", "getOffer", "offerId", "o", "listOffers", "opts", "previewOffer", "p", "payPreviewedOffer", "toggleOrderBump", "listPostPurchaseOffers", "orderId", "acceptPostPurchaseOffer", "declinePostPurchaseOffer", "import_react", "useCustomer", "customerId", "client", "useHeadlessClient", "customer", "setCustomer", "orders", "setOrders", "subscriptions", "setSubscriptions", "isLoading", "setIsLoading", "error", "setError", "loadCustomer", "id", "c", "err", "loadOrders", "res", "loadSubscriptions", "subs", "updateProfile", "data", "updated", "import_react", "useCatalog", "client", "useHeadlessClient", "products", "setProducts", "isLoading", "setIsLoading", "error", "setError", "loadProducts", "opts", "items", "err", "e", "loadProduct", "productId", "import_react", "scriptInjected", "scriptReady", "readyCallbacks", "onScriptReady", "cb", "loadGoogleMapsScript", "apiKey", "opts", "_a", "_b", "resolve", "reject", "poll", "params", "script", "GoogleAutocompleteCore", "_GoogleAutocompleteCore", "input", "options", "service", "predictions", "status", "_c", "placeId", "svc", "place", "out", "premise", "neighborhood", "sublocality5", "sublocality4", "sublocality3", "sublocality2", "sublocality1", "postalTown", "c", "t", "buildingNumber", "streetName", "addr", "a", "useGoogleAutocomplete", "options", "apiKey", "language", "region", "version", "defer", "predictions", "setPredictions", "isLoading", "setIsLoading", "isScriptLoaded", "setIsScriptLoaded", "debounceRef", "pendingRef", "inject", "loadGoogleMapsScript", "input", "country", "doSearch", "countryRestriction", "results", "GoogleAutocompleteCore", "getPlaceDetails", "placeId", "extractAddressComponents", "place", "extractFormattedAddress", "clearPredictions", "import_react", "GEODATA_CDN_BASE", "AVAILABLE_LANGUAGES", "countriesCache", "regionsCache", "inflightCountries", "inflightRegions", "fetchCountriesRaw", "language", "cached", "inflight", "url", "res", "data", "fetchRegionsRaw", "getCountriesCached", "getRegionsCached", "ensureGeoDataLoaded", "getCountries", "raw", "code", "c", "a", "b", "getStatesForCountry", "countryCode", "tuples", "iso", "name", "isLanguageLoaded", "ISODataCore", "_ISODataCore", "language", "ensureGeoDataLoaded", "arr", "getCountries", "result", "c", "countryCode", "getStatesForCountry", "s", "regionCode", "r", "googleState", "googleStateLong", "regions", "match", "isLanguageLoaded", "AVAILABLE_LANGUAGES", "useISOData", "language", "isLoaded", "setIsLoaded", "isLanguageLoaded", "cancelled", "ensureGeoDataLoaded", "err", "ISODataCore", "cc", "rc", "gs", "gsl", "useCountryOptions", "countries", "c", "a", "b", "useRegionOptions", "countryCode", "getRegions", "r", "SYMBOLS", "NAMES", "ZERO_DECIMAL", "CurrencyUtils", "_CurrencyUtils", "code", "formatMoney", "amountMinorUnits", "currencyCode", "locale", "decimals", "value"]
7
7
  }