@tagadapay/headless-sdk 1.21.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +23 -0
- package/dist/core/helpers/paymentsApi.d.ts +5 -0
- package/dist/core/helpers/paymentsApi.d.ts.map +1 -1
- package/dist/core/helpers/paymentsApi.js +34 -0
- package/dist/core/helpers/paymentsApi.js.map +1 -1
- package/dist/core/helpers/paymentsApiAnswer.d.ts +4 -0
- package/dist/core/helpers/paymentsApiAnswer.d.ts.map +1 -1
- package/dist/core/helpers/paymentsApiAnswer.js +6 -1
- package/dist/core/helpers/paymentsApiAnswer.js.map +1 -1
- package/dist/core/helpers/stripeJs.d.ts +15 -0
- package/dist/core/helpers/stripeJs.d.ts.map +1 -0
- package/dist/core/helpers/stripeJs.js +24 -0
- package/dist/core/helpers/stripeJs.js.map +1 -0
- package/dist/core/helpers/stripeRadar.d.ts +14 -0
- package/dist/core/helpers/stripeRadar.d.ts.map +1 -0
- package/dist/core/helpers/stripeRadar.js +34 -0
- package/dist/core/helpers/stripeRadar.js.map +1 -0
- package/dist/core/modules/payment.d.ts +5 -0
- package/dist/core/modules/payment.d.ts.map +1 -1
- package/dist/core/modules/payment.js +6 -23
- package/dist/core/modules/payment.js.map +1 -1
- package/dist/core/modules/track.d.ts.map +1 -1
- package/dist/core/modules/track.js +7 -1
- package/dist/core/modules/track.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/pixels/engine.d.ts +3 -3
- package/dist/pixels/engine.d.ts.map +1 -1
- package/dist/pixels/engine.js +12 -8
- package/dist/pixels/engine.js.map +1 -1
- package/dist/pixels/pixelMapping.d.ts +37 -6
- package/dist/pixels/pixelMapping.d.ts.map +1 -1
- package/dist/pixels/pixelMapping.js +194 -3
- package/dist/pixels/pixelMapping.js.map +1 -1
- package/dist/pixels/pixelTracker.d.ts +10 -4
- package/dist/pixels/pixelTracker.d.ts.map +1 -1
- package/dist/pixels/pixelTracker.js +164 -7
- package/dist/pixels/pixelTracker.js.map +1 -1
- package/dist/pixels/types.d.ts +18 -2
- package/dist/pixels/types.d.ts.map +1 -1
- package/dist/pixels/types.js +1 -0
- package/dist/pixels/types.js.map +1 -1
- package/dist/react/hooks/usePayment.d.ts +3 -0
- package/dist/react/hooks/usePayment.d.ts.map +1 -1
- package/dist/react/hooks/usePayment.js.map +1 -1
- package/dist/tagada-headless-commerce.min.js +1 -1
- package/dist/tagada-headless-react.min.js +2 -2
- package/dist/tagada-headless-react.min.js.map +4 -4
- package/dist/tagada-headless.js +48 -30
- package/dist/tagada-headless.min.js +2 -2
- package/dist/tagada-headless.min.js.map +4 -4
- package/dist/tagada-pixels.min.js +2 -2
- package/dist/tagada-pixels.min.js.map +3 -3
- package/dist/tgd/contract/registry.d.ts +1 -1
- package/dist/tgd/contract/registry.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/core/index.ts", "../src/core/errors.ts", "../src/core/version.ts", "../src/core/http.ts", "../src/core/modules/checkout.ts", "../src/core/helpers/walletContact.ts", "../src/core/modules/track.ts", "../src/core/helpers/cryptoOnchain.ts", "../src/core/helpers/paymentsApiAnswer.ts", "../src/core/helpers/oceanpayment.ts", "../src/core/modules/payment.ts", "../src/core/modules/lazyCommerce.ts", "../src/core/modules/offers.ts", "../src/core/modules/customer.ts", "../src/core/modules/portal/index.ts", "../src/core/modules/catalog.ts", "../src/core/modules/funnel.ts", "../src/core/modules/rx.ts", "../src/core/modules/experiments.ts", "../src/core/client.ts", "../src/core/helpers/autocomplete.ts", "../src/core/helpers/iso3166.ts", "../src/core/helpers/countries.ts", "../src/core/helpers/currency.ts"],
|
|
4
|
-
"sourcesContent": ["export { HeadlessClient, createHeadlessClient } from './client.js';\n\nexport { CheckoutModule } from './modules/checkout.js';\nexport { parseTokensFromUrl } from './modules/checkout.js';\nexport { PaymentModule } from './modules/payment.js';\nexport { OffersModule } from './modules/offers.js';\nexport { CustomerModule } from './modules/customer.js';\nexport { CustomerPortalModule } from './modules/portal/index.js';\nexport type * as PortalTypes from './modules/portal/types.js';\nexport { CatalogModule } from './modules/catalog.js';\nexport { FunnelModule } from './modules/funnel.js';\nexport { RxModule, isQuestionActive, toIntakeAnswers } from './modules/rx.js';\nexport { TrackModule } from './modules/track.js';\nexport type { StepData, EventData, TrackIdentity, TrackHealth } from './modules/track.js';\nexport type {\n RxCaseStatus,\n RxRequiredForProduct,\n RxStorefrontPatient,\n RxIntakeAnswer,\n RxClinicalQuestion,\n RxClinicalQuestionRule,\n RxQuestionAnswers,\n RxIntakeContext,\n RxIntakeIssue,\n RxValidateIntakeInput,\n RxQuestionsForProduct,\n RxSubmitCaseInput,\n RxSubmitCaseResult,\n RxCaseSummary,\n RxIntakeContextResult,\n RxIntakeContextPatient,\n RxActivationStatus,\n RxActivationStepKey,\n RxActivationMissingItem,\n} from './modules/rx.js';\n\nexport { HttpClient } from './http.js';\n\n// On-chain crypto (`crypto_onchain`): paid inline from the page, never through pay-v2\nexport {\n CryptoOnchainCheckout,\n CRYPTO_ONCHAIN_PAYMENT_METHOD,\n CRYPTO_ONCHAIN_STATUS_POLL_MS,\n CRYPTO_ONCHAIN_FINAL_PHASES,\n isCryptoOnchainMethod,\n defaultCryptoOnchainSelection,\n selectCryptoOnchainNetwork,\n cryptoOnchainPhase,\n cryptoOnchainSecondsLeft,\n formatCryptoOnchainCountdown,\n} from './helpers/cryptoOnchain.js';\nexport type { CryptoOnchainApi } from './helpers/cryptoOnchain.js';\n\nexport {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaPaymentError,\n TagadaNetworkError,\n} from './errors.js';\n\n// Helpers: Google Autocomplete, ISO countries/regions, currency formatting\nexport {\n GoogleAutocompleteCore,\n loadGoogleMapsScript,\n ISODataCore,\n AVAILABLE_LANGUAGES,\n CurrencyUtils,\n formatMoney,\n ensureGeoDataLoaded,\n getCountries,\n getStatesForCountry,\n isLanguageLoaded,\n} from './helpers/index.js';\n\nexport type {\n GooglePrediction,\n GooglePlaceDetails,\n ExtractedAddress,\n FormattedAddress,\n SupportedLanguage,\n ISOCountry,\n ISORegion,\n Country,\n State,\n Currency,\n} from './helpers/index.js';\n\nexport type {\n Environment,\n HeadlessConfig,\n HttpRequestOptions,\n LineItem,\n CreateCheckoutSessionOptions,\n CheckoutCustomerMetadata,\n CheckoutSession,\n CheckoutLineItem,\n CheckoutTotals,\n CheckoutCustomer,\n Address,\n ShippingRate,\n PaymentMethodConfig,\n PaymentSetupConfig,\n ExpressMethod,\n ExpressMethods,\n StoreConfig,\n PayResult,\n PayOptions,\n PayDirectOptions,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n OceanPaymentConfig,\n MountOceanPaymentOptions,\n OceanPaymentForm,\n CryptoOnchainAsset,\n CryptoOnchainNetwork,\n CryptoOnchainPayment,\n CryptoOnchainStatus,\n CryptoOnchainOptionsFailureCode,\n CryptoOnchainPaymentFailureCode,\n CryptoOnchainStatusFailureCode,\n CryptoOnchainFailure,\n CryptoOnchainOptionsResult,\n CryptoOnchainPaymentResult,\n CryptoOnchainStatusResult,\n CryptoOnchainPhase,\n CryptoOnchainSelection,\n CryptoOnchainCheckoutState,\n CryptoOnchainCheckoutOptions,\n CreateInstrumentOptions,\n PaymentInstrument,\n ThreedsSession,\n PaymentStatus,\n Offer,\n OfferLineItem,\n OfferPreview,\n OfferPreviewItem,\n OfferPayResult,\n Customer,\n Order,\n OrderItem,\n Subscription,\n CatalogProduct,\n CatalogVariant,\n CatalogPrice,\n CurrencyOption,\n FunnelNavigateInput,\n FunnelNavigateResult,\n} from './types.js';\n\nexport { ExperimentsModule } from './modules/experiments.js';\nexport type { TgdBootstrap, TgdIds } from '../tgd/contract/index.js';\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 * Application error code from the API, when it sends one \u2014 e.g.\n * `MISSING_SHIPPING_ADDRESS` when a cart containing a shippable product is\n * paid with no address (#TAG-1989). Branch on this rather than on the\n * message, which is customer-facing and may be reworded.\n */\n public readonly appCode?: string;\n\n constructor(\n message: string,\n errors: Array<{ field: string; message: string }> = [],\n appCode?: string,\n details?: Record<string, unknown>,\n ) {\n super(message, 'validation_error', 422, { errors, ...details });\n this.name = 'TagadaValidationError';\n this.errors = errors;\n this.appCode = appCode;\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", "/** Identity this package reports to the SDK routes. A test pins it to `package.json`. */\nexport const SDK_NAME = 'headless' as const;\nexport const SDK_VERSION = '1.21.0' as const;\n", "import {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaNetworkError,\n} from './errors.js';\nimport { SDK_VERSION } from './version.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 redirect?: RequestRedirect;\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 private redirect?: RequestRedirect;\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 this.redirect = config.redirect;\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 // Which SDK and version sent the call: the Payments API readiness check counts them per store.\n 'X-Tagada-SDK': `headless-sdk/${SDK_VERSION}`,\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 ...(this.redirect && { redirect: this.redirect }),\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 // Server actions answer `{ code, data }`, where `data` carries the\n // customer-facing message and an application error code \u2014 `Error.message`\n // is non-enumerable, so it cannot travel at the top level (#TAG-1989).\n // Without this the buyer sees \"Request failed: 422 \u2026\" instead of the\n // reason, and the code the storefront should branch on is thrown away.\n // The REST handler sends an object `data` as a JSON string, with an empty `message`.\n const data = parseErrorData(parsed.data);\n\n const msg =\n (parsed.message as string) ||\n (parsed.error as string) ||\n (typeof data.message === 'string' ? data.message : undefined) ||\n (typeof parsed.data === 'string' && Object.keys(data).length === 0 ? (parsed.data as string) : undefined) ||\n `Request failed: ${res.status} ${res.statusText} on ${path}`;\n\n const appCode = typeof data.code === 'string' ? data.code : undefined;\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, appCode, parsed);\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\nfunction parseErrorData(value: unknown): Record<string, unknown> {\n if (value && typeof value === 'object') return value as Record<string, unknown>;\n if (typeof value !== 'string') return {};\n try {\n const parsed: unknown = JSON.parse(value);\n return parsed && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type {\n CheckoutSession,\n LineItem,\n ShippingRate,\n Address,\n CheckoutCustomer,\n CreateCheckoutSessionOptions,\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 * Last session returned by `loadSession()`. Cached so sibling modules\n * (e.g. `FunnelModule`) can read the cart without re-fetching. Cleared\n * intentionally on no events \u2014 call `loadSession()` again to refresh.\n */\n private _currentSession: CheckoutSession | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly onTokenChange?: (token: string) => void,\n /** Tracking hook: the only call that yields a checkout session id. */\n private readonly onSession?: (session: CheckoutSession) => void,\n ) {}\n\n /**\n * Returns the most recently loaded `CheckoutSession`, if any.\n *\n * Populated by `loadSession()`. Returns `undefined` if the SDK has not\n * loaded a session yet. Used by `funnel.navigate()` to source the cart.\n */\n getCurrentSession(): CheckoutSession | undefined {\n return this._currentSession;\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 const session = this.normalizeSession(raw);\n this._currentSession = session;\n try {\n this.onSession?.(session);\n } catch {\n /* tracking must never break a checkout */\n }\n return session;\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(\n opts: CreateCheckoutSessionOptions,\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 ...(i.sellingPlanId !== undefined ? { sellingPlanId: i.sellingPlanId } : {}),\n ...(i.trialDays !== undefined ? { trialDays: i.trialDays } : {}),\n ...(i.trialPrice !== undefined ? { trialPrice: i.trialPrice } : {}),\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 if (opts.funnelSessionId) body.funnelSessionId = opts.funnelSessionId;\n if (opts.discountCodes?.length) body.discountCodes = opts.discountCodes;\n if (opts.metadata && Object.keys(opts.metadata).length > 0) body.metadata = opts.metadata;\n if (opts.customerMetadata && Object.keys(opts.customerMetadata).length > 0) {\n body.customerMetadata = opts.customerMetadata;\n }\n if (opts.customerTags?.length) body.customerTags = opts.customerTags;\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 * Create a session and produce a self-hosted redirect URL.\n *\n * Convenience wrapper around `createSession()`. Builds a URL of the\n * form `${origin}${checkoutPath}?checkoutToken=...&sessionToken=...`\n * that you can navigate to from a Cart page. The receiving page reads\n * the params via {@link CheckoutModule.parseTokensFromUrl} and calls\n * {@link CheckoutModule.loadSession}.\n *\n * For Tagada-hosted checkouts use the `checkoutUrl` returned by\n * `createSession()` directly \u2014 this helper is for **self-hosted**\n * checkout pages.\n *\n * @example\n * ```ts\n * const { url } = await tagada.checkout.createSessionUrl({\n * items: [{ variantId, quantity: 1 }],\n * checkoutPath: '/checkout',\n * });\n * window.location.href = url;\n * ```\n */\n async createSessionUrl(\n opts: CreateCheckoutSessionOptions & {\n /** Path on the current origin for the self-hosted checkout. Default: `/checkout`. */\n checkoutPath?: string;\n /** Origin to use. Defaults to `window.location.origin`. */\n origin?: string;\n },\n ): Promise<{\n url: string;\n checkoutUrl: string;\n checkoutToken: string;\n sessionToken: string;\n customerId: string;\n }> {\n const { checkoutPath = '/checkout', origin: originOverride, ...sessionOpts } = opts;\n const session = await this.createSession(sessionOpts);\n\n const origin =\n originOverride ?? (typeof window !== 'undefined' ? window.location.origin : '');\n const params = new URLSearchParams({\n checkoutToken: session.checkoutToken,\n sessionToken: session.sessionToken,\n });\n const url = `${origin}${checkoutPath}?${params.toString()}`;\n\n return { ...session, url };\n }\n\n /**\n * Read `checkoutToken` and session token from a URL.\n *\n * Recognizes both the SDK convention (`?sessionToken=`) and the\n * Tagada-hosted convention (`?token=`), so the same checkout page\n * works whether the user came from `createSessionUrl()` or directly\n * from a Tagada-hosted redirect.\n *\n * Returns `null` if `checkoutToken` is missing.\n *\n * @example\n * ```ts\n * const tokens = CheckoutModule.parseTokensFromUrl();\n * if (!tokens) {\n * window.location.href = '/cart';\n * return;\n * }\n * const session = await tagada.checkout.loadSession(\n * tokens.checkoutToken,\n * tokens.sessionToken,\n * );\n * ```\n */\n static parseTokensFromUrl(\n url?: string,\n ): { checkoutToken: string; sessionToken: string } | null {\n if (typeof url === 'undefined' && typeof window === 'undefined') return null;\n const href = url ?? window.location.href;\n let parsed: URL;\n try {\n parsed = new URL(href);\n } catch {\n return null;\n }\n const checkoutToken = parsed.searchParams.get('checkoutToken');\n if (!checkoutToken) return null;\n const sessionToken =\n parsed.searchParams.get('sessionToken') ?? parsed.searchParams.get('token') ?? '';\n return { checkoutToken, sessionToken };\n }\n\n /** Instance alias of {@link CheckoutModule.parseTokensFromUrl}. */\n parseTokensFromUrl(url?: string) {\n return CheckoutModule.parseTokensFromUrl(url);\n }\n\n /**\n * Add or update cart items on an existing session (upsert by product).\n *\n * Sends each item as `lineItems` to `POST /checkout-sessions/:id/line-items`.\n * The endpoint UPSERTs by product: it adds new products and updates the\n * variant/quantity of products already in the cart, but it does NOT remove\n * products omitted from `items`, and an empty array is a no-op (it does not\n * clear the cart). Each `quantity` must be >= 1 \u2014 removal is not supported by\n * this endpoint.\n *\n * Returns a server-side mutation summary (counts of created/updated rows).\n * It does NOT return the updated `CheckoutSession` \u2014 the underlying endpoint\n * never has and the previous typing was a lie that quietly assigned\n * `{ success, updated, ... }` 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 const lineItems = items.map((i) => ({\n variantId: i.variantId,\n priceId: i.priceId,\n ...(i.sellingPlanId !== undefined ? { sellingPlanId: i.sellingPlanId } : {}),\n quantity: i.quantity,\n }));\n\n return this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/line-items`,\n { lineItems },\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: Array<Record<string, unknown>> }>(\n `/api/v1/checkout-sessions/${sessionId}/shipping-rates`,\n { token: this.sessionToken },\n );\n return (res.rates ?? []).map((r) => this.normalizeShippingRate(r));\n }\n\n /**\n * Normalize the v1 rates payload (`shippingRateName`, `estimatedDeliveryTime`)\n * to the SDK's `ShippingRate` shape (`name`, `estimatedDays`). Without\n * this the consumer's UI shows blank rate names \u2014 the demo's \"Delivery\"\n * radios were rendering only the price, no label.\n */\n private normalizeShippingRate(r: Record<string, unknown>): ShippingRate {\n return {\n id: r.id as string,\n name: (r.name ?? r.shippingRateName ?? '') as string,\n description: (r.description ?? undefined) as string | undefined,\n amount: (r.amount ?? 0) as number,\n currency: (r.currency ?? 'USD') as string,\n estimatedDays: (r.estimatedDays ?? r.estimatedDeliveryTime ?? undefined) as number | undefined,\n };\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 ...(price?.recurring ? {\n recurring: {\n interval: (price.interval ?? 'month') as string,\n intervalCount: (price.intervalCount ?? 1) as number,\n },\n } : {}),\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 // `totalAdjustedAmount` is what gets charged (subtotal \u2212 discounts + shipping + tax).\n // The raw adjuster summary also carries `totalAmount` = subtotal + shipping only \u2014\n // reading that first showed a pre-discount, pre-tax total (#TAG-2246). The legacy\n // `orderSummaries[0]` shape only has `totalAmount`, already aliased to the adjusted total.\n total: (summary.totalAdjustedAmount ??\n summary.totalAmount ??\n 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 ...(typeof cs.draft === 'boolean' ? { draft: cs.draft } : {}),\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 * Read `checkoutToken` and session token from a URL \u2014 standalone alias of\n * {@link CheckoutModule.parseTokensFromUrl}, importable without the class:\n *\n * ```ts\n * import { parseTokensFromUrl } from '@tagadapay/headless-sdk';\n * const tokens = parseTokensFromUrl(); // null if no checkoutToken in the URL\n * ```\n */\nexport const parseTokensFromUrl = CheckoutModule.parseTokensFromUrl;\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 { Address } from '../types.js';\n\n/**\n * A contact as Apple Pay hands it to `onpaymentauthorized`\n * (`event.payment.billingContact` / `event.payment.shippingContact`).\n *\n * Apple only fills the fields the payment request asked for, so an integration\n * that omits `requiredBillingContactFields` / `requiredShippingContactFields`\n * receives nothing here \u2014 see `applePayContactToAddress`.\n */\nexport interface ApplePayContact {\n givenName?: string;\n familyName?: string;\n addressLines?: string[];\n locality?: string;\n administrativeArea?: string;\n postalCode?: string;\n countryCode?: string;\n emailAddress?: string;\n phoneNumber?: string;\n}\n\n/** A Google Pay address (`paymentData.shippingAddress`, or `billingAddress`). */\nexport interface GooglePayContact {\n name?: string;\n address1?: string;\n address2?: string;\n address3?: string;\n locality?: string;\n administrativeArea?: string;\n postalCode?: string;\n countryCode?: string;\n phoneNumber?: string;\n emailAddress?: string;\n}\n\n/**\n * A contact as Stripe's Express Checkout Element reports it on `confirm`\n * (`event.billingDetails`, `event.shippingAddress`).\n */\nexport interface StripeContact {\n name?: string;\n email?: string;\n phone?: string;\n address?: {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n postal_code?: string;\n country?: string;\n };\n}\n\n/**\n * Map an Apple Pay contact onto an SDK `Address`.\n *\n * Returns `undefined` when the contact has no usable postal address, so a\n * caller can never overwrite a real address with an empty shell \u2014 Apple sends\n * a name-and-email-only contact whenever the payment request did not ask for\n * `postalAddress` (#TAG-1989).\n */\nexport function applePayContactToAddress(contact?: ApplePayContact | null): Address | undefined {\n if (!contact) return undefined;\n\n const address: Address = {\n firstName: contact.givenName,\n lastName: contact.familyName,\n line1: contact.addressLines?.[0],\n line2: contact.addressLines?.[1],\n city: contact.locality,\n state: contact.administrativeArea,\n postalCode: contact.postalCode,\n country: contact.countryCode,\n phone: contact.phoneNumber,\n };\n\n return isUsable(address) ? address : undefined;\n}\n\n/** Map a Google Pay address onto an SDK `Address`. Same contract as above. */\nexport function googlePayContactToAddress(contact?: GooglePayContact | null): Address | undefined {\n if (!contact) return undefined;\n\n const [firstName, ...rest] = (contact.name ?? '').trim().split(/\\s+/);\n\n const address: Address = {\n firstName: firstName || undefined,\n lastName: rest.length ? rest.join(' ') : undefined,\n line1: contact.address1,\n line2: [contact.address2, contact.address3].filter(Boolean).join(' ') || undefined,\n city: contact.locality,\n state: contact.administrativeArea,\n postalCode: contact.postalCode,\n country: contact.countryCode,\n phone: contact.phoneNumber,\n };\n\n return isUsable(address) ? address : undefined;\n}\n\n/**\n * Map a Stripe Express Checkout contact onto an SDK `Address`. Same contract as\n * the wallet mappers above: no street line or no country means `undefined`.\n */\nexport function stripeContactToAddress(contact?: StripeContact | null): Address | undefined {\n if (!contact?.address) return undefined;\n\n const [firstName, ...rest] = (contact.name ?? '').trim().split(/\\s+/);\n\n const address: Address = {\n firstName: firstName || undefined,\n lastName: rest.length ? rest.join(' ') : undefined,\n line1: contact.address.line1,\n line2: contact.address.line2,\n city: contact.address.city,\n state: contact.address.state,\n postalCode: contact.address.postal_code,\n country: contact.address.country,\n phone: contact.phone,\n };\n\n return isUsable(address) ? address : undefined;\n}\n\n/**\n * A street line and a country are the minimum a parcel \u2014 and every carrier\n * integration \u2014 needs. Anything less is a contact, not an address.\n */\nfunction isUsable(address: Address): boolean {\n return Boolean(address.line1?.trim() && address.country?.trim());\n}\n", "/**\n * The `track` capability: the merchant's coded funnel reports its steps and events,\n * and the browser pixels bound on the canvas fire from here.\n *\n * Three rules hold this file together:\n * - the constructor assigns fields and nothing else (the React provider builds the\n * client inside a `useMemo` that also runs during SSR);\n * - every public method returns at once without a `window`;\n * - everything automatic is gated on an opt-in flag that only `step()` writes, so a\n * site that upgrades and never calls `track.step()` makes zero new request.\n */\nimport type { TgdBootstrap, TgdPublicApi } from '../../tgd/contract/index.js';\nimport type { CheckoutLineItem } from '../types.js';\nimport { SDK_NAME, SDK_VERSION } from '../version.js';\nimport type {\n PixelEngine,\n PixelEngineConfig,\n PixelSignal,\n PixelsConfig,\n StandardPixelEvent,\n} from '../../pixels/index.js';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\nexport interface StepData {\n /** Overrides `location.pathname` for display and for the dedup key. */\n path?: string;\n props?: Record<string, JsonValue>;\n}\n\nexport type EventData = Record<string, JsonValue>;\n\nexport interface TrackIdentity {\n email?: string;\n phone?: string;\n customerId?: string;\n}\n\n/** One cart line, as the pixel mappers read it. Amounts stay in MINOR units. */\nexport interface PixelContent {\n id: string;\n quantity: number;\n item_price?: number;\n}\n\nexport interface TrackSignalNote {\n signal: string;\n value: string;\n detail?: Record<string, string>;\n}\n\n/** A local view: what this page loaded and what it could not do. No server call of its own. */\nexport interface TrackHealth {\n enabled: boolean;\n storeId: string;\n funnelKey: string;\n sdk: { name: typeof SDK_NAME; version: typeof SDK_VERSION };\n manifestHash: string | null;\n pixels: { loaded: boolean; providers: string[] };\n signals: TrackSignalNote[];\n}\n\n// ---------------------------------------------------------------------------\n// Wire shapes (contract \u00A76, R4 and R5)\n// ---------------------------------------------------------------------------\n\ntype Provider = 'facebook' | 'tiktok' | 'snapchat' | 'gtm' | 'clarity';\n\ninterface ConfigPixel {\n provider: Provider;\n id: string;\n idKey: 'pixelId' | 'containerId' | 'projectId';\n events: Record<string, boolean>;\n googleAdsConversionId?: string;\n googleAdsConversionLabel?: string;\n}\n\ninterface TrackConfig {\n collect?: { v: 1; url: string };\n experiments?: { v: 1 };\n version: number;\n storeId: string;\n funnelKey: string;\n manifestHash: string;\n pixels: ConfigPixel[];\n steps: Record<string, { type?: string; events: Record<string, Provider[]> }>;\n checkout: { InitiateCheckout: Provider[]; Purchase: Provider[] };\n consent: { required: boolean };\n}\n\ntype TrackRecord =\n | { kind: 'step'; stepId: string; at: number; path?: string }\n | {\n kind: 'event';\n stepId: string;\n name: string;\n at: number;\n eventId: string;\n props?: Record<string, string | number | boolean>;\n }\n | {\n kind: 'signal';\n signal: 'pixel_blocked' | 'pixel_duplicate' | 'wallet_unavailable';\n value: string;\n detail?: Record<string, string>;\n };\n\ninterface PixelsModule {\n createPixelEngine(config: PixelEngineConfig): PixelEngine;\n}\n\n// ---------------------------------------------------------------------------\n// Engine loading: a lazy import on npm, a second CDN file on the bundle\n// ---------------------------------------------------------------------------\n\ndeclare const __TGD_PIXELS_CDN__: string | undefined;\nconst CDN_URL = typeof __TGD_PIXELS_CDN__ === 'undefined' ? '' : __TGD_PIXELS_CDN__;\n\nfunction loadScript(src: string, isReady: () => boolean): Promise<void> {\n if (isReady()) return Promise.resolve();\n return new Promise<void>((resolve, reject) => {\n const script = document.createElement('script');\n script.src = src;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('runtime script failed to load'));\n document.head.appendChild(script);\n });\n}\n\nasync function loadPixels(): Promise<PixelsModule | null> {\n if (typeof window === 'undefined') return null;\n if (CDN_URL) {\n const w = window as unknown as { TagadaPixels?: PixelsModule };\n if (w.TagadaPixels) return w.TagadaPixels;\n await loadScript(CDN_URL, () => Boolean(w.TagadaPixels));\n return w.TagadaPixels ?? null;\n }\n return (await import('../../pixels/index.js')) as unknown as PixelsModule;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst FLAG_KEY = '__tgd_track';\nconst ANON_KEY = '__tgd_aid';\nconst SESSION_KEY = '__tgd_sid';\nconst QUEUE_LIMIT = 50;\nconst FLUSH_MS = 2000;\nconst DEDUP_MS = 1000;\n/** Hard ceiling on the dedup map. A long-lived SPA visiting hundreds of paths must not grow it. */\nconst STEP_MEMORY = 64;\n\n/** Cart lines as the pixel mappers read them. `unitAmount` stays minor; `baseTransform` converts. */\nexport function toContents(items?: CheckoutLineItem[]): PixelContent[] | undefined {\n if (!Array.isArray(items) || items.length === 0) return undefined;\n return items.map((item) => ({ id: item.variantId, quantity: item.quantity, item_price: item.unitAmount }));\n}\n\n/** R5 carries flat scalars only; anything nested is dropped rather than stringified. */\nfunction scalars(data?: Record<string, JsonValue>): Record<string, string | number | boolean> | undefined {\n if (!data) return undefined;\n const out: Record<string, string | number | boolean> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') out[key] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/**\n * Contract \u00A73: the three SDK event names that carry a pixel meaning, and the standard event a\n * canvas binding writes for them. The back end auto-binds `Lead`, not `lead`, so an event sent\n * under its own name would be gated against a key `config.steps[...].events` never holds, and\n * would reach Meta as an unknown custom event. Any other name is a custom event.\n */\nconst STANDARD_EVENTS: Readonly<Record<string, StandardPixelEvent>> = {\n lead: 'Lead',\n product_viewed: 'ViewContent',\n added_to_cart: 'AddToCart',\n};\n\nfunction uuid(): string {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n\n/**\n * R4 answers a flat array (one entry per configured integration); the engine reads the\n * hosted runtime's per-provider map. This is the only place the two shapes meet.\n */\nfunction toPixelsConfig(pixels: ConfigPixel[]): PixelsConfig {\n const out: Record<string, Record<string, unknown>[]> = {};\n for (const pixel of pixels) {\n // R4 builds each entry key by key, so spreading its own answer carries nothing extra.\n const { provider, id, idKey, ...rest } = pixel;\n (out[provider] ??= []).push({ ...rest, enabled: true, [idKey]: id, events: pixel.events ?? {} });\n }\n return out as unknown as PixelsConfig;\n}\n\n// ---------------------------------------------------------------------------\n// The module\n// ---------------------------------------------------------------------------\n\nexport class TrackModule {\n private readonly records: TrackRecord[] = [];\n private readonly lastStep = new Map<string, number>();\n private readonly signals: TrackSignalNote[] = [];\n\n private currentStepId: string | null = null;\n private manifestHash: string | null = null;\n private loadedProviders: string[] = [];\n private configPromise: Promise<TrackConfig | null> | null = null;\n private corePromise: Promise<TgdPublicApi | null> | null = null;\n /** @internal Server assignment passed to the lazy runtime. */\n bootstrap?: TgdBootstrap;\n private enginePromise: Promise<PixelEngine | null> | null = null;\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private listening = false;\n\n constructor(\n private readonly baseUrl: string,\n private readonly storeId: string,\n private readonly funnelKey: string,\n ) {}\n\n // -- opt-in flag ----------------------------------------------------------\n\n /**\n * The flag is `<storeId>:<funnelKey>`. Only the storeId half arms it; the funnel half is DATA,\n * read back by `flagFunnelKey()` so automatic events report the funnel the last `step()` named.\n * A funnel-key mismatch never disarms tracking; only another tenant's storeId reads as disabled.\n */\n private flag(): string[] {\n try {\n return (localStorage.getItem(FLAG_KEY) ?? '').split(':');\n } catch {\n return [];\n }\n }\n\n private enabled(): boolean {\n return this.flag()[0] === this.storeId;\n }\n\n private flagFunnelKey(): string {\n return this.flag()[1] || this.funnelKey;\n }\n\n /** Every automatic path is off under SSR and off without the flag. */\n private off(): boolean {\n return typeof window === 'undefined' || !this.enabled();\n }\n\n private arm(): void {\n try {\n localStorage.setItem(FLAG_KEY, `${this.storeId}:${this.funnelKey}`);\n } catch {\n /* private mode: tracking simply stays off */\n }\n }\n\n // -- public API -----------------------------------------------------------\n\n step(stepId: string, data?: StepData): void {\n if (typeof window === 'undefined') return;\n this.arm();\n const path = data?.path ?? window.location.pathname;\n const key = `${stepId}|${path}`;\n const at = Date.now();\n const previous = this.lastStep.get(key);\n if (previous !== undefined && at - previous < DEDUP_MS) return;\n this.remember(key, at);\n this.currentStepId = stepId;\n this.listen();\n this.push({ kind: 'step', stepId, at, path });\n void this.pixels().then((engine) => engine?.pageView(path, { stepId }));\n void this.core().then((t) => t?.page({ step_id: stepId })).catch(() => undefined);\n }\n\n event(name: string, data?: EventData): void {\n if (this.off()) return;\n const stepId = this.currentStepId;\n // An event before the first `step()` belongs to no step: it reaches neither R5 nor a pixel.\n if (stepId === null) return;\n // One id, both destinations (contract \u00A77.5: `'<PixelEvent>_' + uuid`). The pixel event is the\n // standard name when there is one, so the id Meta receives is the id R5 recorded.\n const standard = STANDARD_EVENTS[name];\n const eventId = `${standard ?? name}_${uuid()}`;\n this.push({ kind: 'event', stepId, name, at: Date.now(), eventId, props: scalars(data) });\n void this.pixels().then((engine) =>\n standard ? engine?.track(standard, data, { stepId, eventId }) : engine?.trackCustom(name, data, { stepId }),\n );\n void this.core().then((t) => t?.track(name, { ...(scalars(data) ?? {}), step_id: stepId, pixel_event_id: eventId })).catch(() => undefined);\n }\n\n /** Keep the dedup map to entries still inside the window, and never past `STEP_MEMORY`. */\n private remember(key: string, at: number): void {\n for (const [seen, when] of this.lastStep) {\n if (at - when >= DEDUP_MS) this.lastStep.delete(seen);\n }\n // Map iterates in insertion order, so the first key is the oldest one still held.\n while (this.lastStep.size >= STEP_MEMORY) {\n const oldest = this.lastStep.keys().next();\n if (oldest.done === true) break;\n this.lastStep.delete(oldest.value);\n }\n this.lastStep.set(key, at);\n }\n\n identify(who: TrackIdentity): void {\n if (this.off()) return;\n // The engine's identity field is `externalId`; the Tagada customer id is what fills it.\n void this.pixels().then((engine) =>\n engine?.identify({ email: who.email, phone: who.phone, externalId: who.customerId }),\n );\n void this.core().then((t) => t?.identify(who.customerId ?? null, { email: who.email, phone: who.phone, customerId: who.customerId })).catch(() => undefined);\n }\n\n consent(state: { marketing: boolean }): void {\n if (this.off()) return;\n void this.pixels().then((engine) => engine?.consent(state));\n }\n\n async health(): Promise<TrackHealth> {\n if (typeof window === 'undefined') return this.snapshot();\n if (this.enabled()) await this.config();\n return this.snapshot();\n }\n\n // -- internal hooks, called by the checkout and payment modules -----------\n\n /** @internal */\n noteCheckout(input: { checkoutSessionId: string; amount?: number; currency?: string; items?: PixelContent[] }): void {\n this.notePixel('InitiateCheckout', input.checkoutSessionId, input);\n }\n\n /** @internal */\n notePaid(input: { orderId: string; amount?: number; currency?: string; items?: PixelContent[] }): void {\n this.notePixel('Purchase', input.orderId, input);\n }\n\n /** The `eventId` formula is the server's `makeMetaEventId`, so Meta and TikTok dedup. */\n private notePixel(\n event: 'InitiateCheckout' | 'Purchase',\n id: string,\n input: { amount?: number; currency?: string; items?: PixelContent[] },\n ): void {\n if (this.off()) return;\n void this.pixels().then((engine) =>\n engine?.track(\n event,\n { value: input.amount, currency: input.currency, contents: input.items, num_items: input.items?.length },\n { eventId: `${event}_${id}` },\n ),\n );\n }\n\n /** @internal */\n noteSignal(signal: 'wallet_unavailable', value: 'applePay' | 'googlePay' | 'express', detail: { reason: string }): void {\n if (this.off()) return;\n this.signals.push({ signal, value, detail });\n this.listen();\n this.push({ kind: 'signal', signal, value, detail });\n }\n\n // -- config, engine -------------------------------------------------------\n\n private snapshot(): TrackHealth {\n return {\n enabled: typeof window === 'undefined' ? false : this.enabled(),\n storeId: this.storeId,\n funnelKey: this.flagFunnelKey(),\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n manifestHash: this.manifestHash,\n pixels: { loaded: this.loadedProviders.length > 0, providers: [...this.loadedProviders] },\n signals: [...this.signals],\n };\n }\n\n /**\n * R4, once per page. Plain `fetch`, no header, no credentials \u2014 never `HttpClient`,\n * which adds `Content-Type` and `x-cms-token` and so preflights against a fixed allow-list.\n */\n private config(): Promise<TrackConfig | null> {\n if (this.configPromise !== null) return this.configPromise;\n const url =\n `${this.baseUrl}/api/public/v1/sdk/config` +\n `?storeId=${encodeURIComponent(this.storeId)}&funnel=${encodeURIComponent(this.flagFunnelKey())}`;\n this.configPromise = (async (): Promise<TrackConfig | null> => {\n try {\n const response = await fetch(url);\n if (!response.ok) return null;\n const config = (await response.json()) as TrackConfig;\n this.manifestHash = config.manifestHash || null;\n return config;\n } catch {\n return null;\n }\n })();\n return this.configPromise;\n }\n\n /** @internal R4 is reused; loading is allowed only when it opts this store in. */\n core(): Promise<TgdPublicApi | null> {\n if (typeof window === 'undefined') return Promise.resolve(null);\n this.corePromise ??= (async () => {\n try {\n const config = await this.config();\n if (!config || (!config.collect && !config.experiments)) return null;\n const base = this.baseUrl.replace(/\\/+$/, '');\n const w = window as unknown as { tgd?: TgdPublicApi };\n if (typeof w.tgd?.init !== 'function') {\n await loadScript(base + '/assets/js/tgd.js', () => typeof w.tgd?.init === 'function');\n }\n if (typeof w.tgd?.init !== 'function') return null;\n w.tgd.init({ storeId: this.storeId, apiHost: config.collect ? new URL(config.collect.url).origin : base,\n bootstrap: this.bootstrap, _source: 'headless', _manualPages: true });\n return w.tgd;\n } catch {\n return null;\n }\n })();\n return this.corePromise;\n }\n\n /** @internal Funnel navigation alone must not opt a site into tracking. */\n noteFunnelSession(funnelSessionId: string): void {\n if (this.off()) return;\n void this.core().then((t) => t?._link(funnelSessionId)).catch(() => undefined);\n }\n\n private pixels(): Promise<PixelEngine | null> {\n if (!this.enabled()) return Promise.resolve(null);\n this.enginePromise ??= this.startEngine();\n return this.enginePromise;\n }\n\n private async startEngine(): Promise<PixelEngine | null> {\n try {\n const config = await this.config();\n if (config === null) return null;\n const module = await loadPixels();\n if (module === null) return null;\n const engine = module.createPixelEngine({\n pixels: toPixelsConfig(config.pixels ?? []),\n steps: config.steps,\n checkout: config.checkout,\n requireConsent: config.consent?.required === true,\n onSignal: (signal: PixelSignal) => this.onPixelSignal(signal),\n });\n await engine.init();\n this.loadedProviders = [...new Set((config.pixels ?? []).map((pixel) => pixel.provider))];\n return engine;\n } catch {\n return null;\n }\n }\n\n private onPixelSignal(signal: PixelSignal): void {\n const detail = signal.detail ?? {};\n this.signals.push({ signal: signal.kind, value: signal.provider, detail });\n this.push({ kind: 'signal', signal: signal.kind, value: signal.provider, detail });\n }\n\n // -- R5 queue -------------------------------------------------------------\n\n private listen(): void {\n if (this.listening || typeof window === 'undefined') return;\n this.listening = true;\n const onLeave = (event: Event): void => {\n if (event.type === 'visibilitychange' && document.visibilityState !== 'hidden') return;\n this.flush();\n };\n window.addEventListener('pagehide', onLeave);\n window.addEventListener('visibilitychange', onLeave);\n }\n\n private push(record: TrackRecord): void {\n if (!this.enabled()) return;\n this.records.push(record);\n if (this.records.length >= QUEUE_LIMIT) {\n this.flush();\n return;\n }\n if (this.flushTimer === null) this.flushTimer = setTimeout(() => this.flush(), FLUSH_MS);\n }\n\n /** `localStorage` is an undeclared identifier in Node, so it is read inside the try. */\n private identifier(scope: 'local' | 'session', key: string): string {\n try {\n const store = scope === 'local' ? localStorage : sessionStorage;\n const existing = store.getItem(key);\n if (existing) return existing;\n const fresh = uuid();\n store.setItem(key, fresh);\n return fresh;\n } catch {\n return uuid();\n }\n }\n\n private flush(): void {\n if (this.flushTimer !== null) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (this.records.length === 0) return;\n const records = this.records.splice(0, QUEUE_LIMIT);\n const payload: Record<string, unknown> = {\n storeId: this.storeId,\n funnelKey: this.flagFunnelKey(),\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n anonymousId: this.identifier('local', ANON_KEY),\n sessionId: this.identifier('session', SESSION_KEY),\n records,\n };\n if (this.manifestHash !== null) payload.manifestHash = this.manifestHash;\n const body = JSON.stringify(payload);\n const url = `${this.baseUrl}/api/public/v1/sdk/events`;\n try {\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n if (navigator.sendBeacon(url, new Blob([body], { type: 'text/plain;charset=UTF-8' }))) return;\n }\n } catch {\n /* swallowed: tracking never surfaces an error */\n }\n try {\n void fetch(url, {\n method: 'POST',\n body,\n keepalive: true,\n headers: { 'content-type': 'text/plain;charset=UTF-8' },\n }).catch(() => undefined);\n } catch {\n /* swallowed */\n }\n }\n}\n", "/**\n * On-chain crypto (`crypto_onchain`): the pure rules of the inline payment and the\n * `CryptoOnchainCheckout` flow. Same behaviour as the hosted (Studio) checkout's crypto panel:\n * default network and coin, status phases, quote countdown, polling until paid.\n */\nimport type {\n CryptoOnchainCheckoutOptions,\n CryptoOnchainCheckoutState,\n CryptoOnchainNetwork,\n CryptoOnchainOptionsResult,\n CryptoOnchainPaymentResult,\n CryptoOnchainPhase,\n CryptoOnchainSelection,\n CryptoOnchainStatus,\n CryptoOnchainStatusResult,\n} from '../types.js';\n\n/** `paymentSetupConfig` key and payment method name of on-chain crypto. */\nexport const CRYPTO_ONCHAIN_PAYMENT_METHOD = 'crypto_onchain';\n\n/** How often the checkout polls the status, in milliseconds. */\nexport const CRYPTO_ONCHAIN_STATUS_POLL_MS = 5000;\n\n/** Phases after which polling stops. */\nexport const CRYPTO_ONCHAIN_FINAL_PHASES: readonly CryptoOnchainPhase[] = ['paid', 'underpaid', 'failed', 'expired'];\n\n/** True for `crypto_onchain` in any spelling a checkout uses (`crypto-onchain`, `crypto_onchain:int_\u2026`). */\nexport function isCryptoOnchainMethod(method: string | null | undefined): boolean {\n if (!method) return false;\n return method.trim().toLowerCase().replace(/-/g, '_').split(':')[0] === CRYPTO_ONCHAIN_PAYMENT_METHOD;\n}\n\n/**\n * The default pick: the first mainnet network (testnets only when nothing else is offered) and its\n * first stablecoin, else its first coin. Null when no network offers a coin.\n */\nexport function defaultCryptoOnchainSelection(networks: CryptoOnchainNetwork[]): CryptoOnchainSelection | null {\n const usable = networks.filter((network) => network.assets.length > 0);\n const network = usable.find((candidate) => !candidate.testnet) ?? usable[0];\n if (!network) return null;\n const asset = network.assets.find((candidate) => candidate.stable) ?? network.assets[0];\n return { chainId: network.chainId, asset: asset.symbol };\n}\n\n/** Switching network keeps the coin when the new network offers it, else takes its default coin. */\nexport function selectCryptoOnchainNetwork(\n networks: CryptoOnchainNetwork[],\n chainId: number,\n currentAsset: string,\n): CryptoOnchainSelection {\n const assets = networks.find((network) => network.chainId === chainId)?.assets ?? [];\n const keep = assets.find((asset) => asset.symbol === currentAsset);\n const fallback = assets.find((asset) => asset.stable) ?? assets[0];\n return { chainId, asset: (keep ?? fallback)?.symbol ?? currentAsset };\n}\n\n/** The phase of the latest status (or of the payment as created, before the first poll). */\nexport function cryptoOnchainPhase(\n status: Pick<CryptoOnchainStatus, 'status' | 'paid' | 'expired'> | null,\n): CryptoOnchainPhase {\n if (!status) return 'waiting';\n if (status.paid) return 'paid';\n switch (status.status) {\n case 'detected':\n case 'overpaid':\n return 'confirming';\n case 'underpaid':\n return 'underpaid';\n case 'failed':\n return 'failed';\n case 'expired':\n return 'expired';\n default:\n return status.expired ? 'expired' : 'waiting';\n }\n}\n\n/** Whole seconds until `expiresAt`, never negative; 0 for a missing or unparsable date. */\nexport function cryptoOnchainSecondsLeft(expiresAt: string | null, nowMs: number): number {\n if (!expiresAt) return 0;\n const end = Date.parse(expiresAt);\n if (Number.isNaN(end)) return 0;\n return Math.max(0, Math.floor((end - nowMs) / 1000));\n}\n\n/** `m:ss` under an hour, `h:mm:ss` above. */\nexport function formatCryptoOnchainCountdown(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const sec = String(s % 60).padStart(2, '0');\n return h > 0 ? `${h}:${String(m).padStart(2, '0')}:${sec}` : `${m}:${sec}`;\n}\n\n/** The three calls the flow needs; `PaymentModule` provides them. */\nexport interface CryptoOnchainApi {\n getCryptoOnchainOptions(checkoutSessionId: string): Promise<CryptoOnchainOptionsResult>;\n createCryptoOnchainPayment(opts: { checkoutSessionId: string; chainId: number; asset: string }): Promise<CryptoOnchainPaymentResult>;\n getCryptoOnchainStatus(opts: { checkoutSessionId: string; cryptoOnchainPaymentId: string }): Promise<CryptoOnchainStatusResult>;\n}\n\nconst UNAVAILABLE = 'Crypto payments are not available right now. Choose another payment method.';\n\n/**\n * The inline crypto payment of one checkout session: load the networks and coins, keep the pick,\n * create (or re-quote) the payment, poll it until crypto-api confirms it and call `onPaid` once.\n * Create it with `tagada.payment.createCryptoOnchainCheckout()`.\n */\nexport class CryptoOnchainCheckout {\n private state: CryptoOnchainCheckoutState = {\n options: 'idle',\n networks: [],\n selection: null,\n payment: null,\n paymentStatus: null,\n isCreating: false,\n error: null,\n };\n\n private readonly listeners = new Set<(state: CryptoOnchainCheckoutState) => void>();\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private stopped = false;\n private paidNotified = false;\n\n constructor(\n private readonly api: CryptoOnchainApi,\n private readonly options: CryptoOnchainCheckoutOptions,\n ) {\n this.subscribe = this.subscribe.bind(this);\n this.getState = this.getState.bind(this);\n }\n\n getState(): CryptoOnchainCheckoutState {\n return this.state;\n }\n\n /** Listens to every state change; returns the unsubscribe function. */\n subscribe(listener: (state: CryptoOnchainCheckoutState) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** What to show: the polled phase, or `expired` once an unpaid quote ran out (renew with `pay()`). */\n getPhase(nowMs: number = Date.now()): CryptoOnchainPhase {\n const { payment, paymentStatus } = this.state;\n const phase = cryptoOnchainPhase(paymentStatus ?? (payment ? { status: payment.status, paid: false, expired: false } : null));\n const quoteOver = payment !== null && phase === 'waiting' && cryptoOnchainSecondsLeft(payment.expiresAt, nowMs) === 0;\n return quoteOver ? 'expired' : phase;\n }\n\n /** Whole seconds left on the current quote. */\n getSecondsLeft(nowMs: number = Date.now()): number {\n return cryptoOnchainSecondsLeft(this.state.payment?.expiresAt ?? null, nowMs);\n }\n\n /** Loads the networks and coins and picks the default network and coin. */\n async loadOptions(): Promise<CryptoOnchainCheckoutState> {\n this.setState({ options: 'loading', error: null });\n try {\n const result = await this.api.getCryptoOnchainOptions(this.options.checkoutSessionId);\n if (!result.ok) {\n this.setState({ options: 'unavailable', networks: [], selection: null, error: result.message || UNAVAILABLE });\n return this.state;\n }\n const selection = this.state.selection ?? defaultCryptoOnchainSelection(result.networks);\n this.setState(\n selection\n ? { options: 'ready', networks: result.networks, selection }\n : { options: 'unavailable', networks: result.networks, selection: null, error: UNAVAILABLE },\n );\n } catch (error: unknown) {\n this.setState({ options: 'unavailable', error: messageOf(error) });\n }\n return this.state;\n }\n\n /** Changes the pick. A new network keeps the coin when it offers it, else takes its default coin. */\n select(next: { chainId?: number; asset?: string }): void {\n const current = this.state.selection;\n if (next.chainId !== undefined && next.chainId !== current?.chainId) {\n this.setState({ selection: selectCryptoOnchainNetwork(this.state.networks, next.chainId, next.asset ?? current?.asset ?? '') });\n return;\n }\n if (next.asset !== undefined && current) this.setState({ selection: { ...current, asset: next.asset } });\n }\n\n /**\n * Creates the payment for the pick (or `selection`), or re-quotes it: another coin, or a quote\n * that expired. Save the customer and address on the session first. Starts polling.\n */\n async pay(selection?: CryptoOnchainSelection): Promise<CryptoOnchainPaymentResult> {\n const target = selection ?? this.state.selection;\n if (!target) return { ok: false, code: 'ASSET_NOT_AVAILABLE', message: 'Choose a network and a coin' };\n if (this.state.isCreating) return { ok: false, code: 'CHECKOUT_FAILED', message: 'A payment is already being created' };\n\n this.setState({ isCreating: true, error: null, selection: target });\n try {\n const result = await this.api.createCryptoOnchainPayment({\n checkoutSessionId: this.options.checkoutSessionId,\n chainId: target.chainId,\n asset: target.asset,\n });\n if (!result.ok) {\n this.setState({ isCreating: false, error: result.message });\n return result;\n }\n this.stopped = false;\n this.setState({ isCreating: false, payment: result.payment, paymentStatus: null });\n this.schedulePoll();\n return result;\n } catch (error: unknown) {\n const message = messageOf(error);\n this.setState({ isCreating: false, error: message });\n return { ok: false, code: 'CHECKOUT_FAILED', message };\n }\n }\n\n /** Polls the status once now (the timer keeps polling until the payment is final). */\n async refreshStatus(): Promise<CryptoOnchainStatus | null> {\n const payment = this.state.payment;\n if (!payment) return null;\n try {\n const result = await this.api.getCryptoOnchainStatus({\n checkoutSessionId: this.options.checkoutSessionId,\n cryptoOnchainPaymentId: payment.cryptoOnchainPaymentId,\n });\n // A newer quote replaced this payment while the call was in flight.\n if (!result.ok || this.state.payment?.cryptoOnchainPaymentId !== payment.cryptoOnchainPaymentId) return null;\n const status: CryptoOnchainStatus = {\n status: result.status,\n paymentId: result.paymentId,\n orderId: result.orderId,\n confirmations: result.confirmations,\n requiredConfirmations: result.requiredConfirmations,\n txHash: result.txHash,\n explorerTxUrl: result.explorerTxUrl,\n paid: result.paid,\n expired: result.expired,\n redirectUrl: result.redirectUrl,\n };\n this.setState({ paymentStatus: status });\n if (status.paid && !this.paidNotified) {\n this.paidNotified = true;\n this.options.onPaid?.(status);\n }\n return status;\n } catch {\n // The next tick retries; the payment still settles server side.\n return null;\n }\n }\n\n /** Polls again after `stop()`, while a payment is open (the customer came back to crypto). */\n resume(): void {\n if (!this.state.payment || CRYPTO_ONCHAIN_FINAL_PHASES.includes(this.getPhase())) return;\n this.stopped = false;\n this.schedulePoll();\n }\n\n /** Stops polling (unmount, or the customer chose another payment method). */\n stop(): void {\n this.stopped = true;\n if (this.pollTimer) clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n\n private schedulePoll(): void {\n if (this.pollTimer) clearTimeout(this.pollTimer);\n this.pollTimer = setTimeout(async () => {\n this.pollTimer = null;\n await this.refreshStatus();\n if (!this.stopped && !CRYPTO_ONCHAIN_FINAL_PHASES.includes(this.getPhase())) this.schedulePoll();\n }, this.options.pollIntervalMs ?? CRYPTO_ONCHAIN_STATUS_POLL_MS);\n }\n\n private setState(patch: Partial<CryptoOnchainCheckoutState>): void {\n this.state = { ...this.state, ...patch };\n this.options.onChange?.(this.state);\n this.listeners.forEach((listener) => listener(this.state));\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error && error.message ? error.message : UNAVAILABLE;\n}\n", "/**\n * The few Payments API (V3, D-29) checks the payment module runs on every answer. Kept apart from\n * `paymentsApi.ts`, which holds the V3 flow and is only imported on a V3 payment.\n */\n\n/** The pay answer of a Payments API store: the payment the page confirms, and no order yet. */\nexport interface StartedPayment {\n paymentId: string;\n clientSecret: string;\n amount?: number;\n currency?: string;\n /** Set when the answer names the session it pays. */\n checkoutSessionId?: string;\n}\n\n/** A V2 answer (it carries `payment` or `order`) is never read as a started payment. */\nexport function readStartedPayment(answer: unknown): StartedPayment | null {\n if (!answer || typeof answer !== 'object' || Array.isArray(answer)) return null;\n const { payment, order, paymentId, clientSecret, amount, currency, checkoutSessionId } = answer as Record<\n string,\n unknown\n >;\n if (payment !== undefined || order !== undefined) return null;\n if (typeof paymentId !== 'string' || !paymentId || typeof clientSecret !== 'string' || !clientSecret)\n return null;\n return {\n paymentId,\n clientSecret,\n ...(typeof amount === 'number' ? { amount } : {}),\n ...(typeof currency === 'string' ? { currency } : {}),\n ...(typeof checkoutSessionId === 'string' ? { checkoutSessionId } : {}),\n };\n}\n\nconst PENDING_KEY = 'tgd_payments_api_return';\nconst PENDING_TTL_MS = 60 * 60_000;\n\n/** Before a redirect: the session the payment pays, so the return page can read its secret again. */\nexport function parkPaymentsApiReturn(paymentId: string, checkoutSessionId: string): void {\n try {\n sessionStorage.setItem(PENDING_KEY, JSON.stringify({ paymentId, checkoutSessionId, at: Date.now() }));\n } catch {\n // Storage unavailable: the return page polls the payment, as on V2.\n }\n}\n\n/** The parked session of `paymentId`, read once; null for any other payment (every V2 payment). */\nexport function takeParkedPaymentsApiReturn(paymentId: string): { checkoutSessionId: string } | null {\n try {\n const raw = sessionStorage.getItem(PENDING_KEY);\n if (!raw) return null;\n const parked = JSON.parse(raw) as { paymentId?: string; checkoutSessionId?: string; at?: number };\n if (parked.paymentId !== paymentId) return null;\n sessionStorage.removeItem(PENDING_KEY);\n if (!parked.checkoutSessionId || !parked.at || Date.now() - parked.at > PENDING_TTL_MS) return null;\n return { checkoutSessionId: parked.checkoutSessionId };\n } catch {\n return null;\n }\n}\n", "/**\n * Browser plumbing for Ocean Payment's inline card form (Oceanpayment\n * Embedded SDK). Mirrors the hosted checkout's OceanPaymentPanel\n * (apps/studio-app/.../PaymentMethodSelector/TakeoverPanels.tsx).\n */\n\nexport interface OceanpaymentGlobal {\n init: (sandbox: boolean, cssUrl: string, language: string, configuration: Record<string, unknown>) => void;\n checkout: (data: Record<string, string>) => void;\n}\n\nexport type OceanWindow = Window & {\n Oceanpayment?: OceanpaymentGlobal;\n /** Ocean's SDK calls this global \u2014 the name is fixed by the SDK. */\n oceanpaymentCallBack?: (data: unknown) => void;\n};\n\nexport const OCEAN_SDK_URL = 'https://secure.oceanpayment.com/pages/js/oceanpayment.js';\n/** Fixed by Ocean's SDK, which looks the container up by this id. */\nexport const OCEAN_CONTAINER_ID = 'oceanpayment-element';\n/** Ocean's iframe answers every checkout(); this only guards a lost message. */\nexport const OCEAN_CALLBACK_TIMEOUT_MS = 120_000;\n\n/**\n * Ocean builds its card fields server-side from `?language=`. An unknown code\n * falls back to English, and `fi` comes back in Polish, so Finnish shoppers\n * get English.\n */\nconst OCEAN_LANGUAGE_OVERRIDES: Record<string, string> = { fi: 'en' };\n\nexport function oceanLanguage(locale: string | undefined): string {\n const primary = locale?.split(/[-_]/)[0]?.toLowerCase();\n if (!primary) return 'en';\n return OCEAN_LANGUAGE_OVERRIDES[primary] ?? primary;\n}\n\nconst OCEAN_SDK_LOAD_TIMEOUT_MS = 30_000;\nlet oceanSdkLoading: Promise<OceanpaymentGlobal> | null = null;\n\n/**\n * Load Ocean's SDK once per page: a second copy would deliver every result\n * twice. A failed or stalled load is forgotten, so the next mount retries.\n */\nexport function loadOceanSdk(): Promise<OceanpaymentGlobal> {\n const w = window as OceanWindow;\n if (w.Oceanpayment) return Promise.resolve(w.Oceanpayment);\n if (oceanSdkLoading) return oceanSdkLoading;\n\n oceanSdkLoading = new Promise<OceanpaymentGlobal>((resolve, reject) => {\n const script = document.createElement('script');\n const fail = (message: string) => {\n clearTimeout(timer);\n script.remove();\n oceanSdkLoading = null;\n reject(new Error(message));\n };\n const timer = setTimeout(() => fail('The Ocean Payment card form took too long to load'), OCEAN_SDK_LOAD_TIMEOUT_MS);\n script.addEventListener('load', () => {\n if (!w.Oceanpayment) return fail('Ocean Payment script loaded without window.Oceanpayment');\n clearTimeout(timer);\n resolve(w.Oceanpayment);\n });\n script.addEventListener('error', () => fail('Failed to load the Ocean Payment card form'));\n script.src = OCEAN_SDK_URL;\n document.head.appendChild(script);\n });\n return oceanSdkLoading;\n}\n\n/**\n * Ocean's inline card form leaves the page only for 3-D Secure, and Ocean\n * returns the shopper to the exact page URL the form was opened on \u2014 without\n * any payment reference in it. The payment id is parked in sessionStorage\n * before leaving; a stale entry (abandoned 3DS) is ignored after 30 minutes.\n */\nconst OCEAN_PENDING_KEY = 'tgd:headless:oceanpayment:pending';\nconst OCEAN_PENDING_TTL_MS = 30 * 60 * 1000;\n\nexport function parkOceanPayment(paymentId: string): void {\n try {\n sessionStorage.setItem(OCEAN_PENDING_KEY, JSON.stringify({ paymentId, at: Date.now() }));\n } catch {\n // Storage unavailable \u2014 Ocean's webhook still settles the order.\n }\n}\n\nfunction takeParkedOceanPayment(): string | undefined {\n try {\n const raw = sessionStorage.getItem(OCEAN_PENDING_KEY);\n if (!raw) return undefined;\n sessionStorage.removeItem(OCEAN_PENDING_KEY);\n const { paymentId, at } = JSON.parse(raw) as { paymentId?: string; at?: number };\n if (!paymentId || !at || Date.now() - at > OCEAN_PENDING_TTL_MS) return undefined;\n return paymentId;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Back from Ocean's 3-D Secure page: turn the parked payment into the\n * `paymentAction` / `paymentActionStatus` / `paymentId` markers that\n * `maybeResumeFromUrl()` and `usePayment()` already resume from.\n */\nexport function restoreOceanPaymentReturn(): void {\n if (typeof window === 'undefined') return;\n const paymentId = takeParkedOceanPayment();\n if (!paymentId) return;\n try {\n const url = new URL(window.location.href);\n if (url.searchParams.get('paymentId')) return;\n url.searchParams.set('paymentId', paymentId);\n url.searchParams.set('paymentAction', 'requireAction');\n url.searchParams.set('paymentActionStatus', 'completed');\n window.history.replaceState(window.history.state, '', url.toString());\n } catch {\n // Best-effort: Ocean's webhook still settles the order.\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport { TagadaNotFoundError } from '../errors.js';\nimport {\n applePayContactToAddress,\n googlePayContactToAddress,\n type ApplePayContact,\n type GooglePayContact,\n} from '../helpers/walletContact.js';\nimport type { CheckoutModule } from './checkout.js';\nimport { toContents } from './track.js';\nimport type { PixelContent } from './track.js';\nimport type {\n Address,\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 OceanPaymentConfig,\n MountOceanPaymentOptions,\n OceanPaymentForm,\n CryptoOnchainCheckoutOptions,\n CryptoOnchainOptionsResult,\n CryptoOnchainPaymentResult,\n CryptoOnchainStatusResult,\n} from '../types.js';\nimport { CryptoOnchainCheckout } from '../helpers/cryptoOnchain.js';\nimport {\n readStartedPayment,\n takeParkedPaymentsApiReturn,\n type StartedPayment,\n} from '../helpers/paymentsApiAnswer.js';\nimport {\n OCEAN_CALLBACK_TIMEOUT_MS,\n OCEAN_CONTAINER_ID,\n loadOceanSdk,\n oceanLanguage,\n parkOceanPayment,\n restoreOceanPaymentReturn,\n type OceanWindow,\n} from '../helpers/oceanpayment.js';\n\n/**\n * The V3 flow, imported on a Payments API payment only: its own chunk on npm, never in the CDN\n * bundle (the define and `external` in build-cdn.js), which cannot load core-js anyway.\n */\ndeclare const __TGD_NO_PAYMENTS_API__: boolean | undefined;\nfunction loadPaymentsApiFlow(): Promise<typeof import('../helpers/paymentsApi.js')> {\n if (typeof __TGD_NO_PAYMENTS_API__ !== 'undefined' && __TGD_NO_PAYMENTS_API__) {\n return Promise.reject(\n new Error(\n 'This store takes payments through the Payments API, which the CDN build does not support yet: ' +\n 'install @tagadapay/headless-sdk and @tagadapay/core-js 3.7.0 or later from npm.',\n ),\n );\n }\n return import('../helpers/paymentsApi.js');\n}\n\n/**\n * Payment statuses that end the payment without money moving. Not `expired`:\n * a crypto payment can still come back from it.\n */\nconst FAILED_PAYMENT_STATUSES = new Set(['failed', 'declined', 'rejected', 'error']);\n\n/**\n * One Ocean card form per page: Ocean's SDK uses a fixed container id and one\n * global callback. Held from the start of a mount; freed by `unmount()`, or\n * once the page has dropped the form's container without calling it.\n */\nlet oceanSlot: { element: HTMLElement; attached: boolean } | null = null;\nconst oceanSlotTaken = () => !!oceanSlot && (!oceanSlot.attached || oceanSlot.element.isConnected);\n\n/** Ocean's iframe never answered `checkout()`. */\nconst OCEAN_TIMED_OUT = Symbol('ocean-timed-out');\n/** The card form was removed while a payment waited on Ocean's iframe. */\nconst OCEAN_UNMOUNTED = Symbol('ocean-unmounted');\n\n/**\n * One row of `GET /api/v1/payment-methods` \u2014 the checkout's payment-method\n * picker list. `type` is `'credit-card'` for the native card form, otherwise\n * the integration provider (`apple_pay`, `google_pay`, `paypal`, `klarna`, \u2026).\n */\ninterface PaymentMethodListEntry {\n id: string;\n type: string;\n title?: string;\n iconUrl?: string;\n default?: boolean;\n settings?: Record<string, unknown> | null;\n metadata?: Record<string, unknown> | null;\n}\n\nconst EXPRESS_METHOD_TYPES = new Set(['apple_pay', 'google_pay', 'paypal', 'klarna', 'klarna_express', 'link']);\n\n/** Map a picker-list row to the `PaymentSetupConfig` entry shape (#TAG-2246). */\nfunction paymentMethodListEntryToConfig(entry: PaymentMethodListEntry): PaymentMethodConfig {\n const isCard = entry.type === 'credit-card';\n const method = isCard ? 'card' : entry.type;\n const settings = (entry.settings ?? {}) as Record<string, unknown>;\n const processors = settings.processors as Array<{ processorId?: string }> | undefined;\n const publishableKey = settings.publishableKey;\n return {\n enabled: true,\n method,\n provider: isCard ? undefined : entry.type,\n type: isCard ? 'card' : entry.type,\n label: entry.title,\n logoUrl: entry.iconUrl,\n express: EXPRESS_METHOD_TYPES.has(method),\n integrationId: isCard ? undefined : entry.id,\n processorId: processors?.[0]?.processorId,\n publishableKey: typeof publishableKey === 'string' ? publishableKey : undefined,\n metadata: entry.metadata ?? undefined,\n };\n}\n\ntype StripeJs = (publishableKey: string) => {\n createRadarSession(): Promise<{\n radarSession?: { id: string; [key: string]: unknown };\n error?: { message?: string };\n }>;\n};\n\n/** Stripe.js from the page, or loaded from Stripe's CDN. */\nfunction loadStripeJs(): Promise<StripeJs> {\n if (typeof window === 'undefined') return Promise.reject(new Error('Stripe Radar needs a browser'));\n const fromPage = (): StripeJs | undefined => (window as unknown as { Stripe?: StripeJs }).Stripe;\n const loaded = fromPage();\n if (loaded) return Promise.resolve(loaded);\n\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://js.stripe.com/v3/';\n script.async = true;\n script.onload = () => {\n const stripe = fromPage();\n if (stripe) resolve(stripe);\n else reject(new Error('Stripe.js loaded without window.Stripe'));\n };\n script.onerror = () => reject(new Error('Failed to load Stripe.js'));\n document.head.appendChild(script);\n });\n}\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 /**\n * Last payment setup seen by `getPaymentSetup` \u2014 lets `processApplePay`\n * resolve the domain's Apple Pay registration (BYOK / platform-integrator)\n * without a second network round-trip inside Apple's authorization window.\n */\n private lastPaymentSetup: PaymentSetupConfig | null = null;\n\n /**\n * Payments API (V3) store: what the pay call knew about each payment it started (the session it\n * pays, the shopper's method), so `finalize()` can confirm it from the bare pay answer.\n */\n private readonly paymentsApiStarts = new Map<string, { checkoutSessionId: string; paymentMethod?: string }>();\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly environment: Environment,\n /** Used to persist wallet contacts onto the session before charging. */\n private readonly checkout?: CheckoutModule,\n /** Tracking hook, fired only on a payment this module sees reach `succeeded`. */\n private readonly onPaid?: (i: {\n orderId: string;\n amount?: number;\n currency?: string;\n items?: PixelContent[];\n }) => void,\n /** Tracking hook for a wallet the browser cannot offer. */\n private readonly onSignal?: (v: 'applePay' | 'googlePay', d: { reason: string }) => void,\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 this.lastPaymentSetup = opts.paymentSetupConfig;\n return opts.paymentSetupConfig;\n }\n\n const injected = this.readInjectedStepConfig();\n if (injected) {\n this.lastPaymentSetup = injected;\n return injected;\n }\n\n // The canonical config for the session \u2014 same builder as the step config\n // injected on Tagada-hosted pages and the partner API-key route\n // (#TAG-2246). Before this route existed the fallback read a `methods`\n // envelope off `/api/v1/payment-methods` (a flat array) and returned `{}`\n // for every self-hosted page.\n try {\n const res = await this.http.get<{ config?: PaymentSetupConfig } | null | undefined>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/payment-setup`,\n );\n const config: PaymentSetupConfig = { ...(res?.config ?? {}) };\n this.lastPaymentSetup = config;\n return config;\n } catch (err) {\n // Backend older than the route: derive the config from the hosted\n // picker list so an upgraded SDK keeps working until the API catches up.\n if (!(err instanceof TagadaNotFoundError)) throw err;\n }\n\n const config = await this.getPaymentSetupFromPickerList(checkoutSessionId);\n this.lastPaymentSetup = config;\n return config;\n }\n\n /**\n * Transitional fallback: `/api/v1/payment-methods` answers with a flat\n * array of `{ id, type, title, iconUrl, default, settings, metadata }`\n * picker rows (`type` = 'credit-card' or the integration provider). Map\n * them to the setup-config shape. Only used when the backend does not\n * serve `/checkout-sessions/:id/payment-setup` yet.\n */\n private async getPaymentSetupFromPickerList(checkoutSessionId: string): Promise<PaymentSetupConfig> {\n const res = await this.http.get<\n PaymentMethodListEntry[] | { methods?: PaymentMethodConfig[] } | null | undefined\n >('/api/v1/payment-methods', { params: { checkoutSessionId } });\n\n const entries: PaymentMethodConfig[] = Array.isArray(res)\n ? res.map(paymentMethodListEntryToConfig)\n : (res?.methods ?? []);\n\n const config: PaymentSetupConfig = {};\n for (const m of entries) {\n const key = m.provider && m.provider !== m.method ? `${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 // `available` stays true for every current caller; only the signal is new.\n if (typeof window !== 'undefined' && !('PaymentRequest' in window)) {\n this.onSignal?.('googlePay', { reason: 'no-payment-request-api' });\n }\n result.googlePay = { ...base, type: 'google_pay' };\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 if (typeof window !== 'undefined' && !('PaymentRequest' in window)) {\n this.onSignal?.('googlePay', { reason: 'no-payment-request-api' });\n }\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 // Tokenize ONCE \u2014 both `tokenizer.tokenizeCard` and\n // `tokenizer.tokenizeCardRaw` internally call BasisTheory's\n // `POST /tokens`. Running them in `Promise.all` charged the\n // customer's network with two identical tokenization requests\n // (visible in the browser as duplicated `tokens/` calls). Get\n // the raw response once, then derive the encoded TagadaToken\n // locally via `createTagadaToken`.\n const rawToken = await tokenizer.tokenizeCardRaw(sanitized);\n const tagadaToken: string = coreJs.createTagadaToken(\n rawToken,\n tokenizer.getProvider().getProviderName(),\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.rememberPaymentsApiStart(await 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 }), opts);\n }\n\n return this.rememberPaymentsApiStart(await 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 returnUrl: opts.returnUrl,\n }), opts);\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.rememberPaymentsApiStart(await 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 returnUrl: opts.returnUrl,\n }), opts);\n }\n\n /**\n * Persist a wallet contact onto the session before the charge.\n *\n * Express wallets are the one checkout where the buyer never fills an address\n * form: they approve one inside the sheet, and it comes back on the\n * authorization event. Studio's `ExpressPaymentWidget` writes it to the\n * session; the headless path used to drop it, which is how a year of orders\n * reached merchants with NULL shipping, billing and customer addresses\n * (#TAG-1989).\n *\n * Never invents data: a contact with no street line or no country maps to\n * `undefined` and the session is left exactly as it was. Failures are NOT\n * swallowed \u2014 if we hold an address and cannot store it, the charge must not\n * proceed, or we are back to the bug this fixes.\n */\n private async syncWalletContact(\n checkoutSessionId: string,\n contact: {\n shippingAddress?: Address;\n billingAddress?: Address;\n email?: string;\n phone?: string;\n firstName?: string;\n lastName?: string;\n },\n ): Promise<void> {\n const { shippingAddress, billingAddress } = contact;\n if (!shippingAddress && !billingAddress) return;\n\n if (!this.checkout) {\n throw new Error(\n 'PaymentModule cannot persist the wallet contact: no CheckoutModule was provided. ' +\n 'Build the SDK through createTagadaClient() rather than constructing PaymentModule directly.',\n );\n }\n\n const customer: Record<string, string> = {};\n if (contact.email) customer.email = contact.email;\n if (contact.phone) customer.phone = contact.phone;\n if (contact.firstName) customer.firstName = contact.firstName;\n if (contact.lastName) customer.lastName = contact.lastName;\n\n await this.checkout.updateCustomerAndAddress(checkoutSessionId, {\n customer,\n shippingAddress,\n billingAddress,\n });\n }\n\n /**\n * Process an Apple Pay payment.\n * Tokenizes the Apple Pay token and processes payment in one call.\n *\n * Pass the contacts from `onpaymentauthorized` \u2014 `event.payment.billingContact`\n * and `event.payment.shippingContact` \u2014 and they are written to the session\n * before the charge, so the address the buyer approved in the wallet sheet\n * lands on the order (#TAG-1989).\n *\n * Apple only returns them when the payment request asked for them, so the\n * `ApplePaySession` request needs:\n *\n * ```js\n * requiredBillingContactFields: ['postalAddress'],\n * requiredShippingContactFields: ['name', 'phone', 'email', 'postalAddress'],\n * ```\n *\n * @example\n * session.onpaymentauthorized = async (event) => {\n * await tagada.payment.processApplePay({\n * checkoutSessionId,\n * applePayToken: event.payment.token,\n * billingContact: event.payment.billingContact,\n * shippingContact: event.payment.shippingContact,\n * });\n * };\n */\n async processApplePay(opts: {\n checkoutSessionId: string;\n applePayToken: unknown;\n billingContact?: ApplePayContact | null;\n shippingContact?: ApplePayContact | null;\n paymentFlowId?: string;\n processorId?: string;\n /**\n * Basis Theory Apple Pay registration the checkout domain is bound to.\n * Required when the domain runs merchant-scoped Apple Pay \u2014 BYOK or the\n * platform-integrator (PPIID) system \u2014 because Apple encrypts the token\n * to that registration's certificate. Resolved automatically from the\n * payment setup (`applePayByok` domain map) when omitted; pass it only to\n * override that resolution.\n */\n merchantRegistrationId?: string;\n }): Promise<PayResult> {\n await this.syncWalletContact(opts.checkoutSessionId, {\n shippingAddress: applePayContactToAddress(opts.shippingContact),\n billingAddress: applePayContactToAddress(opts.billingContact),\n email: opts.shippingContact?.emailAddress ?? opts.billingContact?.emailAddress,\n phone: opts.shippingContact?.phoneNumber ?? opts.billingContact?.phoneNumber,\n firstName: opts.shippingContact?.givenName ?? opts.billingContact?.givenName,\n lastName: opts.shippingContact?.familyName ?? opts.billingContact?.familyName,\n });\n\n const merchantRegistrationId =\n opts.merchantRegistrationId ??\n (await this.resolveApplePayRegistration(opts.checkoutSessionId))?.merchantRegistrationId;\n\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n // The tokenizer returns the normalized Basis Theory response \u2014 it carries\n // no `tagadaToken` field. Wrap it into the standard base64 TagadaToken the\n // pay endpoint expects (destructuring `{ tagadaToken }` here used to yield\n // undefined and silently push the charge down the instrument-less path).\n const rawToken = await tokenizer.tokenizeApplePay(opts.applePayToken, merchantRegistrationId);\n const tagadaToken = btoa(\n JSON.stringify(coreJs.createTagadaDigitalWalletToken(rawToken, 'apple_pay')),\n );\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 * Resolve the Apple Pay registration binding for the domain the page is\n * served from. Both merchant-certificate (BYOK) and platform-integrator\n * (PPIID) Apple Pay attach a domain-keyed `applePayByok` map to the\n * `apple_pay` method's metadata; a hit means every Basis Theory call \u2014\n * merchant session AND tokenization \u2014 must carry that\n * `merchant_registration_id`. A miss (the default) means legacy platform\n * Apple Pay: omit the id and behavior is unchanged.\n *\n * Sources, in order: the Tagada routing injection, the last payment setup\n * seen by `getPaymentSetup`, then one API fetch when a `checkoutSessionId`\n * is given and no setup was ever loaded.\n *\n * Use `displayName` (when present) as the `display_name` of the Basis\n * Theory merchant session.\n */\n async resolveApplePayRegistration(\n checkoutSessionId?: string,\n ): Promise<{ merchantRegistrationId: string; displayName?: string } | null> {\n if (typeof window === 'undefined') return null;\n\n let host = window.location.hostname.toLowerCase().split(':')[0];\n if (host.startsWith('www.')) host = host.slice(4);\n\n const fromConfig = (setup: PaymentSetupConfig | null) => {\n for (const entry of Object.values(setup ?? {})) {\n const map = entry?.metadata?.applePayByok as\n | Record<string, { merchantRegistrationId?: string; displayName?: string }>\n | undefined;\n if (!map || typeof map !== 'object') continue;\n const hit = map[host];\n if (hit?.merchantRegistrationId) {\n return { merchantRegistrationId: hit.merchantRegistrationId, displayName: hit.displayName };\n }\n }\n return null;\n };\n\n const local = fromConfig(this.readInjectedStepConfig()) ?? fromConfig(this.lastPaymentSetup);\n if (local) return local;\n // A setup we already hold that carries no binding is authoritative \u2014 don't\n // burn a network round-trip (inside Apple's authorization window) to\n // re-learn that this is a legacy platform domain.\n if (this.lastPaymentSetup || this.readInjectedStepConfig() || !checkoutSessionId) return null;\n try {\n return fromConfig(await this.getPaymentSetup(checkoutSessionId));\n } catch {\n return null;\n }\n }\n\n /**\n * Process a Google Pay payment.\n * Tokenizes the Google Pay token and processes payment in one call.\n *\n * Pass `paymentData.shippingAddress` / the billing address off\n * `paymentMethodData.info.billingAddress` and they are persisted to the\n * session before the charge (#TAG-1989). Google only returns them when the\n * request sets `shippingAddressRequired` / `billingAddressRequired`.\n */\n async processGooglePay(opts: {\n checkoutSessionId: string;\n googlePayToken: string;\n billingAddress?: GooglePayContact | null;\n shippingAddress?: GooglePayContact | null;\n email?: string;\n paymentFlowId?: string;\n processorId?: string;\n }): Promise<PayResult> {\n await this.syncWalletContact(opts.checkoutSessionId, {\n shippingAddress: googlePayContactToAddress(opts.shippingAddress),\n billingAddress: googlePayContactToAddress(opts.billingAddress),\n email: opts.email ?? opts.shippingAddress?.emailAddress ?? opts.billingAddress?.emailAddress,\n phone: opts.shippingAddress?.phoneNumber ?? opts.billingAddress?.phoneNumber,\n });\n\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n // Same wrapping as Apple Pay above \u2014 the tokenizer's normalized response\n // has no `tagadaToken` field.\n const rawToken = await tokenizer.tokenizeGooglePay(opts.googlePayToken);\n const tagadaToken = btoa(\n JSON.stringify(coreJs.createTagadaDigitalWalletToken(rawToken, 'google_pay')),\n );\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 // On-chain crypto (`crypto_onchain`)\n // ---------------------------------------------------------------------------\n\n /**\n * Networks and coins the store accepts for on-chain crypto on this checkout session. On-chain\n * crypto is paid from your page (address, exact amount, QR) and never through `pay()` /\n * `processApm()`: pay-v2 refuses it with `422 CRYPTO_ONCHAIN_INLINE_ONLY`.\n */\n async getCryptoOnchainOptions(checkoutSessionId: string): Promise<CryptoOnchainOptionsResult> {\n return this.http.get<CryptoOnchainOptionsResult>(\n `/api/v1/checkout-sessions/${encodeURIComponent(checkoutSessionId)}/crypto-onchain/options`,\n );\n }\n\n /**\n * Create the order's on-chain payment for a network and a coin, or re-quote it (another coin,\n * an expired quote): the deposit address, exact amount and wallet URI for the QR code. Save the\n * customer and address on the session first.\n */\n async createCryptoOnchainPayment(opts: {\n checkoutSessionId: string;\n chainId: number;\n asset: string;\n }): Promise<CryptoOnchainPaymentResult> {\n return this.http.post<CryptoOnchainPaymentResult>(\n `/api/v1/checkout-sessions/${encodeURIComponent(opts.checkoutSessionId)}/crypto-onchain/session`,\n { chainId: opts.chainId, asset: opts.asset },\n );\n }\n\n /** The payment's state; poll it every few seconds until `paid` (or underpaid / expired / failed). */\n async getCryptoOnchainStatus(opts: {\n checkoutSessionId: string;\n cryptoOnchainPaymentId: string;\n }): Promise<CryptoOnchainStatusResult> {\n return this.http.get<CryptoOnchainStatusResult>(\n `/api/v1/checkout-sessions/${encodeURIComponent(opts.checkoutSessionId)}/crypto-onchain/status`,\n { params: { cryptoOnchainPaymentId: opts.cryptoOnchainPaymentId } },\n );\n }\n\n /**\n * The whole inline crypto payment of a checkout session, the way the hosted checkout runs it.\n *\n * @example\n * ```ts\n * const crypto = tagada.payment.createCryptoOnchainCheckout({\n * checkoutSessionId: session.id,\n * onPaid: ({ orderId }) => showThankYou(orderId),\n * });\n * crypto.subscribe(render); // networks, selection, payment (address, amount, paymentUri), status\n * await crypto.loadOptions();\n * payButton.onclick = () => crypto.pay(); // after saving the customer and address\n * ```\n */\n createCryptoOnchainCheckout(opts: CryptoOnchainCheckoutOptions): CryptoOnchainCheckout {\n return new CryptoOnchainCheckout(this, opts);\n }\n\n // ---------------------------------------------------------------------------\n // Ocean Payment\n // ---------------------------------------------------------------------------\n\n /** Whether the store's Ocean Payment integration renders its inline card form or redirects. */\n async getOceanPaymentConfig(checkoutSessionId: string): Promise<OceanPaymentConfig> {\n const data = await this.http.post<Partial<OceanPaymentConfig>>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-embedded-config`,\n {},\n );\n return { embedded: !!data?.embedded, sandboxed: !!data?.sandboxed };\n }\n\n /**\n * Set up Ocean Payment for a checkout session, the way the hosted checkout\n * does: Ocean's card fields render inside `container` when the integration\n * has Ocean's public key (`embedded`), otherwise `pay()` sends the shopper\n * to Ocean's page and back to `returnUrl` (`redirect`).\n *\n * @example\n * ```ts\n * const ocean = await tagada.payment.mountOceanPayment({\n * checkoutSessionId: session.id,\n * container: '#ocean-card',\n * });\n * payButton.onclick = async () => {\n * const result = await ocean.pay();\n * if (result.status === 'requires_redirect') window.location.href = result.redirectUrl;\n * else if (result.status === 'succeeded') showThankYou(result.order);\n * else if (result.status === 'failed') showError(result.error);\n * };\n * ```\n */\n async mountOceanPayment(opts: MountOceanPaymentOptions): Promise<OceanPaymentForm> {\n if (typeof window === 'undefined') throw new Error('Ocean Payment needs a browser');\n const { checkoutSessionId, signal } = opts;\n const aborted = () => Object.assign(new Error('Ocean Payment mount aborted'), { name: 'AbortError' });\n if (signal?.aborted) throw aborted();\n\n const host = typeof opts.container === 'string'\n ? document.querySelector<HTMLElement>(opts.container)\n : opts.container;\n if (!host && opts.mode !== 'redirect') {\n throw new Error(`Ocean Payment container not found: ${String(opts.container)}`);\n }\n // Reserve Ocean's single slot before the first await, so a second mount\n // (React StrictMode runs effects twice) fails fast instead of racing.\n if (oceanSlotTaken() || document.getElementById(OCEAN_CONTAINER_ID)) {\n throw new Error('An Ocean Payment card form is already mounted on this page');\n }\n const w = window as OceanWindow;\n const element = document.createElement('div');\n element.id = OCEAN_CONTAINER_ID;\n const slot = { element, attached: false };\n oceanSlot = slot;\n const releaseSlot = () => { if (oceanSlot === slot) oceanSlot = null; };\n\n let mounted = true;\n let pendingCallback: ((data: unknown) => void) | null = null;\n const callback = (data: unknown) => {\n const resolve = pendingCallback;\n pendingCallback = null;\n resolve?.(data);\n };\n const unmount = () => {\n if (!mounted) return;\n mounted = false;\n if (w.oceanpaymentCallBack === callback) delete w.oceanpaymentCallBack;\n element.remove();\n releaseSlot();\n // A payment in flight stops waiting for the iframe and checks its status instead.\n callback(OCEAN_UNMOUNTED);\n };\n signal?.addEventListener('abort', unmount, { once: true });\n\n let config: OceanPaymentConfig;\n let ocean: Awaited<ReturnType<typeof loadOceanSdk>> | undefined;\n try {\n config = opts.mode === 'redirect'\n ? { embedded: false, sandboxed: false }\n : await this.getOceanPaymentConfig(checkoutSessionId);\n if (signal?.aborted) throw aborted();\n if (config.embedded) {\n ocean = await loadOceanSdk();\n if (signal?.aborted) throw aborted();\n }\n } catch (error) {\n unmount();\n throw error;\n }\n\n let submitting = false;\n\n if (!ocean) {\n // Ocean's own page needs no card slot on this one.\n releaseSlot();\n return {\n mode: 'redirect',\n pay: async () => {\n if (!mounted) return { status: 'failed', error: 'The Ocean Payment form was removed' };\n if (submitting) return { status: 'failed', error: 'Payment already in progress' };\n submitting = true;\n try {\n const data = await this.http.post<{ url?: string | null; paymentId?: string | null }>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-link`,\n { returnUrl: opts.returnUrl ?? window.location.href },\n );\n if (!data?.url || !data.paymentId) {\n return { status: 'failed', error: 'Ocean Payment is not available for this store' };\n }\n return { status: 'requires_redirect', redirectUrl: data.url, method: 'GET', paymentId: data.paymentId };\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n } finally {\n submitting = false;\n }\n },\n unmount,\n };\n }\n\n const sdk = ocean;\n host!.appendChild(element);\n slot.attached = true;\n w.oceanpaymentCallBack = callback;\n // Ocean refuses a checkout whose backUrl is not the page it was initialised on.\n const backUrl = window.location.href;\n // No \"Name on Card\" row: Ocean's iframe is a fixed 131px and clips it,\n // and the buyer's name already travels as billing_firstName/lastName.\n sdk.init(config.sandboxed, '', oceanLanguage(opts.locale), { showCardName: false });\n\n const pay = async (): Promise<ProcessPaymentResult> => {\n if (!mounted) return { status: 'failed', error: 'The Ocean Payment card form was removed' };\n if (submitting) return { status: 'failed', error: 'Payment already in progress' };\n submitting = true;\n try {\n // 1. Record the payment server-side and get Ocean's signed fields\n const created = await this.http.post<{ paymentId?: string; params?: Record<string, string> }>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-embedded-payment`,\n { backUrl },\n );\n if (!created?.paymentId || !created.params) {\n return { status: 'failed', error: 'Failed to start the payment' };\n }\n const paymentId = created.paymentId;\n\n // 2. Ocean's iframe charges the card it holds and answers through\n // oceanpaymentCallBack: {code, msg} for a card-entry error, or the\n // signed XML result.\n const answer = await new Promise<unknown>((resolve) => {\n const timer = setTimeout(() => {\n pendingCallback = null;\n resolve(OCEAN_TIMED_OUT);\n }, OCEAN_CALLBACK_TIMEOUT_MS);\n pendingCallback = (data) => { clearTimeout(timer); resolve(data); };\n sdk.checkout(created.params!);\n });\n // No answer from the iframe: the card may still have been charged, so\n // never invite a retry. Ocean's webhook settles the payment either way.\n if (answer === OCEAN_TIMED_OUT || answer === OCEAN_UNMOUNTED) {\n return this.pollUntilDone(paymentId);\n }\n if (answer && typeof answer === 'object' && 'msg' in answer) {\n return { status: 'failed', error: String((answer as { msg?: unknown }).msg || 'Please check your card details.') };\n }\n\n // 3. The server verifies Ocean's signed result: 3DS, success, or decline\n const result = await this.http.post<{ status: string; payUrl?: string; message?: string }>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-embedded-result`,\n { paymentId, response: String(answer) },\n );\n if (result?.status === 'requires_action' && result.payUrl) {\n // Ocean sends the shopper back to this page with nothing in the URL.\n parkOceanPayment(paymentId);\n return { status: 'requires_redirect', redirectUrl: result.payUrl, method: 'GET', paymentId };\n }\n if (result?.status === 'succeeded' || result?.status === 'pending') {\n return this.pollUntilDone(paymentId);\n }\n return { status: 'failed', error: result?.message || 'Payment declined' };\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n } finally {\n submitting = false;\n }\n };\n\n return { mode: 'embedded', pay, unmount };\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 return this.finalize(payResult, { returnUrl: opts.returnUrl });\n }\n\n /**\n * Resolve a raw `PayResult` (from any pay endpoint \u2014 `pay()`, `payDirect()`,\n * `processApplePay()`, `offers.payPreviewedOffer()`, \u2026) into a typed\n * `ProcessPaymentResult` (`succeeded` / `requires_redirect` / `failed`\n * / `pending`).\n *\n * Handles 3DS routing (modal challenge via core-js, or bank redirect)\n * and async polling until the payment reaches a terminal status.\n *\n * This is the same logic `processPayment()` runs after `pay()` \u2014 exposed\n * so callers (and the offers module) that already have a raw `PayResult`\n * don't need to re-pay.\n */\n async finalize(\n input: PayResult,\n opts?: { returnUrl?: string },\n ): Promise<ProcessPaymentResult> {\n const payment = input.payment;\n const returnUrl =\n opts?.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : undefined);\n\n // A Payments API (V3) store answers the payment to confirm, with no `payment`: a V2 answer\n // always carries one, so it never enters this branch.\n if (!payment) {\n const started = readStartedPayment(input);\n if (started) return this.finalizeOnPaymentsApi(started, returnUrl);\n }\n\n if (payment.status === 'succeeded') {\n this.emitPaid(input.order?.id, payment);\n return { status: 'succeeded', payment, order: input.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, { returnUrl } as ProcessPaymentOptions);\n }\n\n // '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 // Only a Payments API payment this page sent to a redirect is parked; every other one polls.\n const parked = takeParkedPaymentsApiReturn(paymentId);\n if (parked) {\n const url = typeof window !== 'undefined' ? window.location.href : undefined;\n return this.onPaymentsApi((flow, host) => flow.resumeOnPaymentsApi(host, paymentId, parked.checkoutSessionId, url));\n }\n return this.pollUntilDone(paymentId);\n }\n\n /**\n * Detect a return from a 3DS / processor redirect by inspecting the\n * current page URL, then poll the payment to completion.\n *\n * The post-3DS URL convention used by Tagada-routed processors is\n * `?paymentAction=requireAction&paymentActionStatus=completed&paymentId=pay_xxx`.\n * If those params are present, this method polls the payment, cleans the\n * URL (so a refresh doesn't re-trigger), and returns the resolved\n * `ProcessPaymentResult`. Otherwise it returns `null`.\n *\n * Use this in vanilla apps as the first thing on page load. The React\n * `usePayment` hook does the same automatically \u2014 don't call this when\n * also using `usePayment`, you'll double-poll.\n *\n * @example\n * ```ts\n * const tagada = createHeadlessClient({ storeId, environment });\n *\n * const resumed = await tagada.payment.maybeResumeFromUrl();\n * if (resumed?.status === 'succeeded') {\n * window.location.href = `/thank-you?orderId=${resumed.order?.id}`;\n * return;\n * }\n * if (resumed?.status === 'failed') {\n * showError(resumed.error);\n * return;\n * }\n * // No 3DS return \u2014 render the normal page.\n * ```\n */\n async maybeResumeFromUrl(opts?: {\n /**\n * URL to inspect (defaults to `window.location.href`). Pass an explicit\n * URL when running outside the browser or when integrating with a\n * router that hasn't navigated yet.\n */\n url?: string;\n /**\n * Whether to clean the redirect query params from the address bar\n * once the payment has been resolved. Defaults to `true`.\n */\n cleanUrl?: boolean;\n }): Promise<ProcessPaymentResult | null> {\n if (typeof window === 'undefined' && !opts?.url) return null;\n if (!opts?.url) restoreOceanPaymentReturn();\n\n const href = opts?.url ?? window.location.href;\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return null;\n }\n\n const action = url.searchParams.get('paymentAction');\n const actionStatus = url.searchParams.get('paymentActionStatus');\n const paymentId = url.searchParams.get('paymentId');\n if (action !== 'requireAction' || actionStatus !== 'completed' || !paymentId) {\n return null;\n }\n\n const result = await this.resumeAfterRedirect(paymentId);\n\n // Strip the redirect params so a refresh doesn't re-trigger.\n if (opts?.cleanUrl !== false && typeof window !== 'undefined' && !opts?.url) {\n const cleanParams = new URLSearchParams(window.location.search);\n [\n 'paymentAction',\n 'paymentActionStatus',\n 'paymentId',\n 'payment_intent',\n 'payment_intent_client_secret',\n 'source_type',\n 'redirect_status',\n 'sessionId',\n ].forEach((k) => cleanParams.delete(k));\n const search = cleanParams.toString();\n try {\n window.history.replaceState(\n {},\n document.title,\n window.location.pathname + (search ? '?' + search : ''),\n );\n } catch {\n // Best-effort.\n }\n }\n\n return result;\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' || FAILED_PAYMENT_STATUSES.has(status.status)) {\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 'stripe_radar':\n return this.handleStripeRadar(payment);\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 * Stripe Radar: the processor holds the charge until the browser sends a Radar\n * session. Create it with Stripe.js, save it, resume the payment, then poll.\n */\n private async handleStripeRadar(payment: PayResult['payment']): Promise<ProcessPaymentResult> {\n const radar = payment.requireActionData?.metadata?.radar as\n | { publishableKey?: string; orderId?: string }\n | undefined;\n if (!radar?.publishableKey) {\n return { status: 'failed', error: 'Stripe Radar configuration missing', payment };\n }\n\n try {\n const Stripe = await loadStripeJs();\n const { radarSession, error } = await Stripe(radar.publishableKey).createRadarSession();\n if (error || !radarSession) {\n throw new Error(error?.message || 'No Radar session returned by Stripe');\n }\n\n await this.http.post('/api/v1/radar-sessions', {\n orderId: radar.orderId,\n paymentId: payment.id,\n stripeRadarSessionId: radarSession.id,\n stripeRadarSessionData: radarSession,\n });\n await this.completeAfter3ds(payment.id);\n return this.pollUntilDone(payment.id);\n } catch (e) {\n return { status: 'failed', error: e instanceof Error ? e.message : 'Stripe Radar failed', payment };\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 // A pre-authorisation that may never be captured is not a purchase (contract \u00A77.4).\n if (status.status === 'succeeded') {\n this.emitPaid(status.order?.id, status as unknown as PayResult['payment']);\n }\n return { status: 'succeeded', payment: status as unknown as PayResult['payment'], order: status.order };\n }\n\n // Ocean writes `rejected` on a decline; `error` never recovers either.\n if (FAILED_PAYMENT_STATUSES.has(status.status)) {\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: Payments API (V3) stores\n // ---------------------------------------------------------------------------\n\n /** Keeps what a V3 pay answer does not say (its session, the method); returns the answer as is. */\n private rememberPaymentsApiStart(\n answer: PayResult,\n opts: { checkoutSessionId: string; paymentMethod?: string },\n ): PayResult {\n const started = answer && !answer.payment ? readStartedPayment(answer) : null;\n if (started) {\n this.paymentsApiStarts.set(started.paymentId, {\n checkoutSessionId: started.checkoutSessionId ?? opts.checkoutSessionId,\n ...(opts.paymentMethod ? { paymentMethod: opts.paymentMethod } : {}),\n });\n }\n return answer;\n }\n\n /** Confirms a started V3 payment with payments-js and runs it to the V2-shaped result. */\n private finalizeOnPaymentsApi(started: StartedPayment, returnUrl: string | undefined): Promise<ProcessPaymentResult> {\n const known = this.paymentsApiStarts.get(started.paymentId);\n this.paymentsApiStarts.delete(started.paymentId);\n return this.onPaymentsApi((flow, host) =>\n flow.finalizeOnPaymentsApi(host, started, {\n checkoutSessionId: known?.checkoutSessionId,\n paymentMethod: known?.paymentMethod,\n returnUrl,\n }),\n );\n }\n\n /** Runs `run` with the lazily imported V3 flow; a flow that cannot load is a failed payment. */\n private async onPaymentsApi(\n run: (\n flow: typeof import('../helpers/paymentsApi.js'),\n host: import('../helpers/paymentsApi.js').PaymentsApiHost,\n ) => Promise<ProcessPaymentResult>,\n ): Promise<ProcessPaymentResult> {\n let flow: typeof import('../helpers/paymentsApi.js');\n try {\n flow = await loadPaymentsApiFlow();\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n }\n return run(flow, {\n http: this.http,\n storeId: this.storeId,\n checkout: this.checkout,\n stepConfig: this.readInjectedStepConfigRaw(),\n onPaid: (orderId, payment) => this.emitPaid(orderId, payment),\n });\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 /** The whole injected step config (Tagada-hosted pages), or null. */\n private readInjectedStepConfigRaw(): unknown {\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 return typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n return null;\n }\n }\n\n /** Tracking hook. Never throws, never awaits: a pixel must not be able to break a payment. */\n private emitPaid(orderId: string | undefined, payment: { amount?: number; currency?: string }): void {\n if (!orderId || !this.onPaid) return;\n try {\n const session = this.checkout?.getCurrentSession();\n this.onPaid({\n orderId,\n amount: payment.amount,\n currency: payment.currency,\n items: toContents(session?.items),\n });\n } catch {\n /* swallowed */\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 (cause) {\n // `lib` is ES2020 here: no two-argument Error constructor, so `cause` is attached by hand.\n const error = new Error(\n 'This method requires @tagadapay/core-js. Install it: npm install @tagadapay/core-js',\n );\n (error as Error & { cause?: unknown }).cause = cause;\n throw error;\n }\n }\n}\n", "import type { CustomerPortalModule } from './portal/index.js';\nimport type { CustomerModule } from './customer.js';\nimport type { OffersModule } from './offers.js';\n\ndeclare const __TGD_COMMERCE_CDN__: string;\ntype Commerce = { CustomerPortalModule: typeof CustomerPortalModule; OffersModule: typeof OffersModule; CustomerModule: typeof CustomerModule };\ndeclare global { interface Window { TagadaHeadlessCommerce?: Commerce } }\nconst script = typeof document === 'undefined' ? null : document.currentScript as HTMLScriptElement | null;\nconst url = script?.src ? new URL('tagada-headless-commerce.min.js', script.src).href : __TGD_COMMERCE_CDN__;\nlet loading: Promise<Commerce> | undefined;\n\nexport function loadCommerce(): Promise<Commerce> {\n if (window.TagadaHeadlessCommerce) return Promise.resolve(window.TagadaHeadlessCommerce);\n if (!loading) loading = new Promise<Commerce>((resolve, reject) => {\n const element = document.createElement('script');\n element.src = url; element.async = true;\n if (script?.nonce) element.nonce = script.nonce;\n element.addEventListener('load', () => window.TagadaHeadlessCommerce ? resolve(window.TagadaHeadlessCommerce) : reject(new Error('Commerce bundle did not initialize')));\n element.addEventListener('error', () => { element.remove(); reject(new Error('Unable to load commerce bundle')); });\n document.head.appendChild(element);\n }).catch(error => { loading = undefined; throw error; });\n return loading;\n}\n", "import {loadCommerce} from './lazyCommerce.js';\n export class OffersModule {\n constructor(...args){this.args=args}\n load(){return this.instance ||= loadCommerce().then(m=>new m.OffersModule(...this.args)).catch(e=>{this.instance=undefined;throw e})}\n }\n for(const method of [\"getOffer\",\"listOffers\",\"previewOffer\",\"enterFunnelStep\",\"payPreviewedOffer\",\"processOfferPayment\",\"toggleOrderBump\",\"listPostPurchaseOffers\",\"acceptPostPurchaseOffer\",\"declinePostPurchaseOffer\"]) OffersModule.prototype[method]=function(...args){return this.load().then(instance=>instance[method](...args))};", "import {loadCommerce} from './lazyCommerce.js';\n export class CustomerModule {\n constructor(...args){this.args=args}\n load(){return this.instance ||= loadCommerce().then(m=>new m.CustomerModule(...this.args)).catch(e=>{this.instance=undefined;throw e})}\n }\n for(const method of [\"getProfile\",\"getByEmail\",\"updateProfile\",\"getOrders\",\"getOrder\",\"getSubscriptions\",\"getSubscription\",\"pauseSubscription\",\"resumeSubscription\",\"skipSubscription\",\"rescheduleSubscription\",\"updateSubscriptionQuantity\",\"changeSubscriptionFrequency\",\"swapSubscriptionProduct\",\"updateSubscriptionPaymentMethod\",\"cancelSubscription\"]) CustomerModule.prototype[method]=function(...args){return this.load().then(instance=>instance[method](...args))};", "import {loadCommerce} from './lazyCommerce.js';\n export class CustomerPortalModule {\n constructor(...args){this.args=args}\n load(){return this.instance ||= loadCommerce().then(m=>new m.CustomerPortalModule(...this.args)).catch(e=>{this.instance=undefined;throw e})}\n }\n for(const method of [\"requestCode\",\"verifyCode\",\"getConfig\",\"getMe\",\"cancelFlow\",\"acceptCancelOffer\",\"switchOption\",\"getOffer\",\"acceptOffer\",\"addToNextOrder\",\"getCredits\",\"redeemCredits\",\"buyCreditPack\",\"requestEmailChangeCode\",\"updateProfile\",\"saveAddress\",\"removeAddress\",\"setDefaultAddress\",\"addCard\",\"removeCard\",\"setDefaultPaymentMethod\",\"retryPayment\",\"buyAgain\",\"joinMembership\",\"buyNow\",\"sendNow\",\"reactivateSubscription\",\"setSubscriptionCard\",\"setSubscriptionAddress\",\"skipDate\",\"unskipDate\"]) CustomerPortalModule.prototype[method]=function(...args){return this.load().then(instance=>instance[method](...args))};", "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 { TagadaError } from '../errors.js';\nimport type { HttpClient } from '../http.js';\nimport type {\n CheckoutSession,\n FunnelNavigateInput,\n FunnelNavigateResult,\n} from '../types.js';\nimport type { CheckoutModule } from './checkout.js';\n\n/**\n * Initialize a funnel session from the SDK's current cart and produce a\n * redirect URL into a funnel step.\n *\n * Mirrors the WooCommerce checkout plugin\n * (`public/assets/php/woocommerce/tagada-checkout-plugin.php`):\n *\n * 1. `POST /api/v1/cms/session/anonymous` \u2014 public, returns a CMS token.\n * 2. `POST /api/v1/cms/session/v2/init` \u2014 uses the token, returns a CMS customer id.\n * 3. `POST /api/v1/funnel/initialize` \u2014 creates the funnel session.\n * 4. `POST /api/v1/funnel/navigate` \u2014 fires an `INIT_CHECKOUT` event and returns `{ url }`.\n *\n * Steps 1\u20133 are cached on the module instance, so repeat `navigate()` calls in\n * the same page only fire step 4.\n *\n * **Prerequisite**: the SDK must have a loaded `CheckoutSession`\n * (`sdk.checkout.loadSession(...)`). The cart is sourced from `session.items`,\n * the currency from `session.currency`, the customer email from\n * `session.customer.email`, and the promotion code from `session.promotionCode`.\n */\nexport class FunnelModule {\n private _cmsToken: string | undefined;\n private _cmsSessionId: string | undefined;\n private _cmsCustomerId: string | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly checkout: CheckoutModule,\n private readonly accountId: string | undefined,\n private readonly onFunnelSession?: (funnelSessionId: string) => void,\n ) {}\n\n async navigate(input: FunnelNavigateInput): Promise<FunnelNavigateResult> {\n const session = this.checkout.getCurrentSession();\n if (!session) {\n throw new TagadaError(\n 'No checkout session loaded. Call sdk.checkout.loadSession(...) before sdk.funnel.navigate(...).',\n 'no_cart_loaded',\n );\n }\n\n const accountId = input.accountId ?? this.accountId;\n if (!accountId) {\n throw new TagadaError(\n 'accountId is required for funnel.navigate(). Set it on createHeadlessClient({ accountId }) or pass it per call.',\n 'missing_account_id',\n );\n }\n\n const currentUrl =\n input.currentUrl ?? (typeof globalThis !== 'undefined' ? globalThis.location?.href : undefined);\n\n await this.ensureCmsSession(session, accountId, input);\n\n const funnelSessionId = await this.initializeFunnel({\n funnelId: input.funnelId,\n stepId: input.stepId,\n accountId,\n currentUrl,\n });\n\n try { this.onFunnelSession?.(funnelSessionId); } catch { /* Tracking cannot interrupt navigation. */ }\n\n const url = await this.runNavigate({\n funnelSessionId,\n stepId: input.stepId,\n session,\n input,\n currentUrl,\n });\n\n return { url, funnelSessionId };\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async ensureCmsSession(\n session: CheckoutSession,\n accountId: string,\n input: FunnelNavigateInput,\n ): Promise<void> {\n if (this._cmsToken && this._cmsSessionId && this._cmsCustomerId) return;\n\n const anon = await this.http.post<{ token: string; sessionId: string }>(\n '/api/v1/cms/session/anonymous',\n { storeId: this.storeId, role: 'anonymous', draft: false },\n );\n this._cmsToken = anon.token;\n this._cmsSessionId = anon.sessionId;\n\n const init = await this.http.post<{ customer: { id: string } }>(\n '/api/v1/cms/session/v2/init',\n {\n storeId: this.storeId,\n accountId,\n customerId: 'anon_placeholder',\n browserLocale: input.customer?.locale ?? defaultLocale(),\n userAgent: defaultUserAgent(),\n queryCurrency: input.customer?.currency ?? session.currency,\n queryLocale: input.customer?.locale,\n },\n { token: this._cmsToken },\n );\n\n this._cmsCustomerId = init.customer.id;\n }\n\n private async initializeFunnel(args: {\n funnelId: string;\n stepId: string;\n accountId: string;\n currentUrl: string | undefined;\n }): Promise<string> {\n const res = await this.http.post<{ context: { sessionId: string } }>(\n '/api/v1/funnel/initialize',\n {\n cmsSession: {\n customerId: this._cmsCustomerId,\n sessionId: this._cmsSessionId,\n storeId: this.storeId,\n accountId: args.accountId,\n },\n funnelId: args.funnelId,\n entryStepId: args.stepId,\n funnelStepId: args.stepId,\n currentUrl: args.currentUrl,\n draft: false,\n },\n { token: this._cmsToken },\n );\n return res.context.sessionId;\n }\n\n private async runNavigate(args: {\n funnelSessionId: string;\n stepId: string;\n session: CheckoutSession;\n input: FunnelNavigateInput;\n currentUrl: string | undefined;\n }): Promise<string> {\n const { funnelSessionId, stepId, session, input, currentUrl } = args;\n\n const lineItems = session.items.map((i) => ({\n variantId: i.variantId,\n priceId: i.priceId,\n quantity: i.quantity,\n }));\n\n const discountCodes =\n input.discountCodes ??\n (session.promotionCode ? [session.promotionCode] : undefined);\n\n const customer = {\n email: input.customer?.email ?? session.customer?.email,\n currency: input.customer?.currency ?? session.currency,\n locale: input.customer?.locale,\n };\n\n const res = await this.http.post<{ result: { url: string } }>(\n '/api/v1/funnel/navigate',\n {\n sessionId: funnelSessionId,\n currentUrl,\n funnelStepId: stepId,\n fireAndForget: false,\n event: {\n type: 'INIT_CHECKOUT',\n data: {\n checkoutInit: {\n cartToken: session.id,\n lineItems,\n customer,\n returnUrl: input.returnUrl,\n storeId: this.storeId,\n metadata: input.metadata,\n discountCodes,\n // Pins the session to this exact shipping amount when the caller's\n // storefront already settled one (#TAG-1785). Left undefined when\n // absent, so it is omitted from the JSON body and the platform\n // auto-selects a rate exactly as before.\n externalShipping: input.externalShipping,\n },\n },\n },\n },\n { token: this._cmsToken },\n );\n\n return res.result.url;\n }\n}\n\nfunction defaultLocale(): string {\n if (typeof navigator !== 'undefined' && navigator.language) return navigator.language;\n return 'en-US';\n}\n\nfunction defaultUserAgent(): string {\n if (typeof navigator !== 'undefined' && navigator.userAgent) return navigator.userAgent;\n return 'tagadapay-headless-sdk';\n}\n", "import type { HttpClient } from '../http.js';\n\n/**\n * Tagada Rx \u2014 storefront module.\n *\n * Drives the post-checkout clinical case flow from the browser:\n * 1. Ask the API whether a product needs an Rx case.\n * 2. After the order is paid, submit the intake (patient + answers)\n * with the `(orderId, checkoutToken)` ownership proof.\n * 3. Poll the case status from the thank-you page.\n *\n * PHI handling: the `patient` and `intakeAnswers` payloads are sent\n * straight to the Tagada API which forwards them to the clinical\n * network (e.g. MDI). Tagada NEVER persists PHI in its database.\n *\n * Auth model: there is no API key. Each route authorizes per-resource\n * (productId is public; case routes require the checkoutToken the\n * storefront already received when it bootstrapped the checkout).\n *\n * Rules: the server enforces the clinical network's contract on every\n * submit (US address and phone, required questions, offered options, MDI\n * demographics). Use `validateIntake` before payment and `isQuestionActive`\n * / `toIntakeAnswers` to render and send the questionnaire the same way.\n *\n * @example\n * ```ts\n * const { required } = await tagada.rx.isRequiredForProduct(productId);\n * if (required) {\n * // Before payment: US address, phone, ZIP, age.\n * const pre = await tagada.rx.validateIntake({ productId, patient });\n * if (!pre.valid) return showErrors(pre.issues);\n * // After payment: render the network questionnaire.\n * const { questions } = await tagada.rx.getQuestionsForProduct(productId, variantId);\n * const ctx = { state: patient.address.state, sexAtBirth: patient.sexAtBirth };\n * const shown = questions.filter((q) => isQuestionActive(q, answers, ctx));\n * // \u2026collect `answers` keyed by externalQuestionId\u2026\n * const res = await tagada.rx.submitCase({\n * orderId, checkoutToken, productId,\n * patient, intakeAnswers: toIntakeAnswers(questions, answers, ctx),\n * });\n * router.push(`/thank-you?rxCase=${res.rxCaseId}`);\n * }\n * ```\n */\nexport type RxCaseStatus =\n | 'requested'\n | 'submitted'\n | 'in_review'\n | 'approved'\n | 'shipped'\n | 'delivered'\n | 'declined'\n | 'cancelled'\n | 'error';\n\nexport interface RxRequiredForProduct {\n required: boolean;\n clinicalNetworkId: string | null;\n externalOfferingId: string | null;\n requiresLabs: boolean;\n requiresIdVerification: boolean;\n isDeaControlled: boolean;\n}\n\nexport interface RxStorefrontPatient {\n firstName: string;\n lastName: string;\n email: string;\n phone?: string | null;\n /** ISO date YYYY-MM-DD. */\n dateOfBirth: string;\n sexAtBirth: 'male' | 'female' | 'unspecified';\n address: {\n line1: string;\n line2?: string;\n city: string;\n state: string;\n zip: string;\n /** ISO 3166-1 alpha-2 country code. */\n country: string;\n };\n /** Patient-level clinical fields (MDI Full API / Judd). */\n weight?: number | string;\n height?: number | string;\n allergies?: string;\n pregnancy?: boolean | string;\n currentMedications?: string;\n medicalConditions?: string;\n specialNecessities?: string;\n driverLicenseId?: string;\n introVideoId?: string;\n}\n\nexport interface RxIntakeAnswer {\n questionId: string;\n value: string | number | boolean | string[];\n comment?: string;\n /** Exact question text shown to the patient (MDI case_questions.question). */\n question?: string;\n /** MDI answer type: string | number | boolean. */\n type?: string;\n important?: boolean;\n isCritical?: boolean;\n displayInPdf?: boolean;\n description?: string;\n label?: string;\n metadata?: string;\n /** Options presented for MCQ questions. */\n displayedOptions?: string[];\n}\n\n/** Display rule copied from the clinical network (see `isQuestionActive`). */\nexport interface RxClinicalQuestionRule {\n op: 'and' | 'or';\n requirements: Array<{\n /** `question`: answer to another question; `state`: shipping state; `other` + `patient_sex`: sex at birth. */\n basedOn: 'question' | 'state' | 'other';\n questionId: string | null;\n answer: string | null;\n }>;\n}\n\nexport interface RxClinicalQuestion {\n externalQuestionId: string;\n title: string;\n description: string | null;\n placeholder: string | null;\n type: string;\n required: boolean;\n order: number;\n options: { value: string; label: string; important?: boolean; critical?: boolean }[];\n /** `false` = clinician-side question: never show it, never ask it. */\n visible?: boolean;\n /** Show the question only when one rule matches (`isQuestionActive`). */\n rules?: RxClinicalQuestionRule[];\n important?: boolean;\n critical?: boolean;\n label?: string | null;\n /** Value the network fills itself for hidden questions; send it as is. */\n defaultValue?: string | null;\n}\n\n/** Answers keyed by `externalQuestionId`, as a storefront collects them. */\nexport type RxQuestionAnswers = Record<string, string | number | boolean | string[] | undefined>;\n\nexport interface RxIntakeContext {\n /** Shipping state, 2-letter code. */\n state?: string;\n sexAtBirth?: 'male' | 'female' | 'unspecified';\n}\n\nconst sameText = (a: unknown, b: string | null): boolean =>\n b !== null && String(a).trim().toLowerCase() === b.trim().toLowerCase();\n\n/**\n * Whether the patient must see (and answer) a question. Same rules the\n * server enforces on `submitCase`: hidden and file questions are never\n * shown; a question with rules shows when one rule matches the answers so\n * far, the shipping state or the patient's sex (e.g. \"Drug Allergies\" only\n * after \"Yes\", pregnancy only for women).\n */\nexport function isQuestionActive(\n question: RxClinicalQuestion,\n answers: RxQuestionAnswers,\n context: RxIntakeContext = {},\n): boolean {\n if (question.visible === false || question.type === 'file') return false;\n const rules = question.rules ?? [];\n if (rules.length === 0) return true;\n return rules.some((rule) => {\n const check = (req: RxClinicalQuestionRule['requirements'][number]) => {\n if (req.basedOn === 'state') return sameText(context.state ?? '', req.answer);\n if (req.basedOn === 'other' && req.questionId === 'patient_sex') return sameText(context.sexAtBirth ?? '', req.answer);\n if (req.basedOn === 'question' && req.questionId) {\n const v = answers[req.questionId];\n if (v === undefined) return false;\n return Array.isArray(v) ? v.some((x) => sameText(x, req.answer)) : sameText(v, req.answer);\n }\n return false;\n };\n return rule.op === 'and' ? rule.requirements.every(check) : rule.requirements.some(check);\n });\n}\n\n/**\n * Turn the answers a storefront collected into the `intakeAnswers` to\n * submit: active questions only, keyed by title (what the clinician\n * reads), with the options that were shown, and the network's default for\n * hidden questions. Plug and play with `submitCase` / `validateIntake`.\n */\nexport function toIntakeAnswers(\n questions: RxClinicalQuestion[],\n answers: RxQuestionAnswers,\n context: RxIntakeContext = {},\n): RxIntakeAnswer[] {\n const out: RxIntakeAnswer[] = [];\n for (const q of questions) {\n if (q.visible === false) {\n if (q.defaultValue) out.push({ questionId: q.title, question: q.title, value: q.defaultValue, type: 'string' });\n continue;\n }\n if (!isQuestionActive(q, answers, context)) continue;\n const value = answers[q.externalQuestionId];\n if (value === undefined || (typeof value === 'string' && value.trim() === '')) continue;\n out.push({\n questionId: q.title,\n question: q.title,\n value,\n type: q.type === 'number' ? 'number' : q.type === 'boolean' ? 'boolean' : 'string',\n ...(q.options.length > 0 ? { displayedOptions: q.options.map((o) => o.label) } : {}),\n });\n }\n return out;\n}\n\nexport interface RxIntakeIssue {\n field: string;\n message: string;\n}\n\nexport interface RxValidateIntakeInput {\n productId: string;\n variantId?: string;\n patient: {\n phone?: string | null;\n dateOfBirth: string;\n sexAtBirth: 'male' | 'female' | 'unspecified';\n address: { state: string; zip: string; country: string };\n };\n intakeAnswers?: RxIntakeAnswer[];\n}\n\nexport interface RxQuestionsForProduct {\n required: boolean;\n externalQuestionnaireId: string | null;\n questions: RxClinicalQuestion[];\n}\n\nexport interface RxSubmitCaseInput {\n orderId: string;\n checkoutToken: string;\n productId: string;\n patient: RxStorefrontPatient;\n intakeAnswers: RxIntakeAnswer[];\n preferredPharmacyId?: string;\n}\n\nexport interface RxSubmitCaseResult {\n rxCaseId: string;\n externalCaseId: string;\n status: 'submitted' | 'error';\n accrualAmountMinor: number;\n accrualCurrency: string;\n}\n\n/** Basics Tagada already holds on the order. Never date of birth or sex at birth. */\nexport interface RxIntakeContextPatient {\n firstName: string | null;\n lastName: string | null;\n email: string | null;\n phone: string | null;\n address: {\n line1: string | null;\n line2: string | null;\n city: string | null;\n state: string | null;\n zip: string | null;\n country: string | null;\n } | null;\n}\n\n/**\n * What a thank-you page needs to resume an unfinished intake, or\n * `{ caseExists: true }` once a case is in (show its status instead).\n */\nexport type RxIntakeContextResult =\n | { caseExists: true }\n | {\n caseExists: false;\n orderId: string;\n storeId: string;\n productId: string;\n variantId: string | null;\n patient: RxIntakeContextPatient;\n };\n\nexport interface RxCaseSummary {\n id: string;\n status: RxCaseStatus;\n externalCaseId: string | null;\n lastShipmentShippedAt: string | null;\n createdAt: string;\n}\n\nexport type RxActivationStepKey =\n | 'application'\n | 'approval'\n | 'payouts'\n | 'statement_descriptor'\n | 'storefront';\n\nexport type RxActivationMissingItem =\n | 'application'\n | 'approval'\n | 'payout_kyc'\n | 'payout_bank_account'\n | 'statement_descriptor'\n | 'statement_descriptor_rejected'\n | 'storefront'\n | 'partner_rx_option';\n\n/**\n * Tagada Rx activation status of a store.\n *\n * `payments` is `'ready'` once the brand's Rx payment account is live and its\n * payment flow is bound; `'setting_up'` before. It is a status, not a step:\n * there is nothing for the brand to do while payments are being set up.\n * The public storefront route leaves out payout verification and partner\n * contract items (`payouts`, `payout_*`, `partner_rx_option`).\n */\nexport interface RxActivationStatus {\n storeId: string;\n state: 'not_requested' | 'pending_review' | 'active';\n steps: { key: RxActivationStepKey; done: boolean }[];\n missing: RxActivationMissingItem[];\n payments: 'setting_up' | 'ready';\n descriptorStatus: 'none' | 'pending' | 'approved' | 'rejected';\n}\n\nexport class RxModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId?: string,\n ) {}\n\n /**\n * Activation status of the store: steps, missing items and whether Rx\n * payments are `setting_up` or `ready`. Storefronts use it to show\n * \"Payments are being set up\" instead of letting a checkout fail.\n *\n * Read-only / public. Defaults to the client's `storeId`.\n */\n async getActivationStatus(storeId?: string): Promise<RxActivationStatus> {\n const id = storeId ?? this.storeId;\n if (!id) throw new Error('rx.getActivationStatus: storeId is required');\n return this.http.get<RxActivationStatus>('/api/public/v1/rx/activation-status', {\n params: { storeId: id },\n });\n }\n\n /**\n * Check whether a product requires an Rx case. Storefronts call this\n * before rendering the intake form so they only ask the patient\n * questions when really necessary.\n *\n * Read-only / public \u2014 does not require any ownership proof.\n */\n async isRequiredForProduct(\n productId: string,\n opts?: { clinicalNetworkId?: string },\n ): Promise<RxRequiredForProduct> {\n return this.http.get<RxRequiredForProduct>('/api/public/v1/rx/required-for-product', {\n params: {\n productId,\n clinicalNetworkId: opts?.clinicalNetworkId,\n },\n });\n }\n\n /**\n * Look up the Rx cases attached to an order. Storefronts poll this\n * on the thank-you page to render \"Your prescription is being\n * reviewed\" \u2192 \"Shipped\" transitions.\n */\n async getCasesForOrder(input: {\n orderId: string;\n checkoutToken: string;\n }): Promise<{ cases: RxCaseSummary[] }> {\n return this.http.post<{ cases: RxCaseSummary[] }>(\n '/api/public/v1/rx/cases/lookup',\n input,\n );\n }\n\n /**\n * Resume an unfinished intake from `(orderId, checkoutToken)` alone: the\n * patient paid (card on hold) but the identity collected at checkout is\n * gone (tab closed, recovery email link, other device). Returns the Rx\n * line (`productId`, `variantId`) and the basics on the order; ask date of\n * birth and sex at birth again, render the questionnaire, then\n * `submitCase`. `{ caseExists: true }` means a case is already in: show\n * `getCasesForOrder`. Fails with 401 on a wrong token, 404 when the order\n * has no Rx line.\n */\n async getIntakeContext(input: { orderId: string; checkoutToken: string }): Promise<RxIntakeContextResult> {\n return this.http.post<RxIntakeContextResult>('/api/public/v1/rx/intake/context', input);\n }\n\n /**\n * Submit a fresh clinical case for a freshly-paid order. PHI is\n * forwarded to the clinical network and never persisted on\n * Tagada-side rows.\n */\n async submitCase(input: RxSubmitCaseInput): Promise<RxSubmitCaseResult> {\n return this.http.post<RxSubmitCaseResult>('/api/public/v1/rx/cases/submit', input);\n }\n\n /**\n * Check the patient (and, once filled, the intake) against the clinical\n * network rules before paying / submitting: US address in the 50 states\n * or DC, US phone, 5 digit ZIP, adult, every active required question\n * answered with an offered option. `submitCase` enforces the same rules\n * and fails with 422 otherwise. Nothing is created.\n */\n async validateIntake(input: RxValidateIntakeInput): Promise<{ valid: boolean; issues: RxIntakeIssue[] }> {\n return this.http.post<{ valid: boolean; issues: RxIntakeIssue[] }>('/api/public/v1/rx/intake/validate', input);\n }\n\n /**\n * Fetch the network-authored intake questions for a product. Render\n * every question for which `isQuestionActive` is true, build the payload\n * with `toIntakeAnswers`. Empty `questions` means the product has no\n * clinical questionnaire: never replace a network questionnaire with your own.\n */\n async getQuestionsForProduct(\n productId: string,\n variantId?: string,\n ): Promise<RxQuestionsForProduct> {\n return this.http.get<RxQuestionsForProduct>('/api/public/v1/rx/questions-for-product', {\n params: variantId ? { productId, variantId } : { productId },\n });\n }\n}\n", "import type { JsonValue, TgdBootstrap, TgdPublicApi } from '../../tgd/contract/index.js';\n\ntype Subscriber = { key: string; cb: (variant: string | null) => void };\n\n/** Lazy facade. Only the shared tgd runtime evaluates assignments and emits exposures. */\nexport class ExperimentsModule {\n private runtime: TgdPublicApi | null = null;\n private loading: Promise<void> | null = null;\n private settled = false;\n private readonly reads = new Set<string>();\n private readonly subscribers: Subscriber[] = [];\n\n constructor(private readonly core: () => Promise<TgdPublicApi | null>, private readonly bootstrap?: TgdBootstrap) {}\n\n private variant(key: string): string | null {\n return this.bootstrap?.experiments[key]?.arm ?? this.bootstrap?.flags[key]?.variant ?? null;\n }\n\n private start(): Promise<void> {\n if (typeof window === 'undefined') return Promise.resolve();\n this.loading ??= (async () => {\n try { this.runtime = await this.core(); } catch { /* Fall back to bootstrap. */ }\n this.settled = true;\n const runtime = this.runtime;\n for (const key of this.reads) {\n try { runtime?.getVariant(key); } catch { /* Runtime failures cannot interrupt the merchant. */ }\n }\n this.reads.clear();\n for (const { key, cb } of this.subscribers.splice(0)) {\n try { if (runtime) runtime.onVariant(key, cb); else cb(this.variant(key)); } catch { /* Isolate subscribers. */ }\n }\n try { await runtime?.ready(); } catch { /* Offline assignment is a settled facade. */ }\n })();\n return this.loading;\n }\n\n private read(key: string): void {\n if (!this.settled) this.reads.add(key);\n void this.start();\n }\n\n getVariant(key: string): string | null {\n if (this.runtime) return this.runtime.getVariant(key);\n this.read(key);\n return this.variant(key);\n }\n\n getPayload(key: string): JsonValue | null {\n if (this.runtime) return this.runtime.getPayload(key);\n this.read(key);\n return this.bootstrap?.experiments[key]?.payload ?? this.bootstrap?.flags[key]?.payload ?? null;\n }\n\n isEnabled(flagKey: string): boolean {\n if (this.runtime) return this.runtime.isEnabled(flagKey);\n this.read(flagKey);\n return this.bootstrap?.flags[flagKey]?.enabled ?? false;\n }\n\n onVariant(key: string, cb: (variant: string | null) => void): void {\n if (this.runtime) { this.runtime.onVariant(key, cb); return; }\n if (this.settled) { cb(this.variant(key)); return; }\n this.subscribers.push({ key, cb });\n void this.start();\n }\n\n ready(): Promise<void> { return this.start(); }\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 { CustomerPortalModule } from './modules/portal/index.js';\nimport { CatalogModule } from './modules/catalog.js';\nimport { FunnelModule } from './modules/funnel.js';\nimport { RxModule } from './modules/rx.js';\nimport { ExperimentsModule } from './modules/experiments.js';\nimport { TrackModule, toContents } from './modules/track.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 /** Customer portal -- login code, portal config, the customer, retention, credits. */\n readonly portal: CustomerPortalModule;\n\n /** Product catalog -- list products, variants, and prices. */\n readonly catalog: CatalogModule;\n\n /**\n * Funnel navigation -- bootstrap an anonymous CMS session and produce a\n * redirect URL into a funnel step using the currently loaded checkout cart.\n * Requires `config.accountId`.\n */\n readonly funnel: FunnelModule;\n\n /**\n * Tagada Rx -- clinical case submission and lookup for telehealth\n * storefronts. Active only on stores whose merchant has paid the\n * Tagada Rx setup fee and configured a clinical network.\n */\n readonly rx: RxModule;\n\n /**\n * Coded-funnel tracking -- report steps and events from your own code, and fire\n * the browser pixels bound to them on the Tagada canvas. Inert until\n * `track.step()` is called once.\n */\n readonly track: TrackModule;\n readonly experiments: ExperimentsModule;\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 this.track = new TrackModule(baseUrl, this.config.storeId, this.config.funnel ?? 'main');\n this.track.bootstrap = this.config.bootstrap;\n this.experiments = new ExperimentsModule(() => this.track.core(), this.config.bootstrap);\n\n const setToken = (token: string) => {\n this._sessionToken = token;\n };\n\n this.checkout = new CheckoutModule(this.http, this.config.storeId, setToken, (s) =>\n this.track.noteCheckout({\n checkoutSessionId: s.id,\n amount: s.totals.total,\n currency: s.totals.currency,\n items: toContents(s.items),\n }),\n );\n // The checkout module is handed to payments so express wallets can persist\n // the contact they collect in the sheet before charging (#TAG-1989).\n this.payment = new PaymentModule(\n this.http,\n this.config.storeId,\n environment,\n this.checkout,\n (p) => this.track.notePaid(p),\n (v, d) => this.track.noteSignal('wallet_unavailable', v, d),\n );\n this.offers = new OffersModule(this.http, this.config.storeId, this.payment);\n this.customer = new CustomerModule(this.http, this.config.storeId);\n this.portal = new CustomerPortalModule(this.http, this.config.storeId, setToken);\n this.catalog = new CatalogModule(this.http, this.config.storeId);\n this.funnel = new FunnelModule(\n this.http,\n this.config.storeId,\n this.checkout,\n this.config.accountId,\n (id) => this.track.noteFunnelSession(id),\n );\n this.rx = new RxModule(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", "/**\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 * 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": ";;;;;w2BAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,yBAAAE,EAAA,gCAAAC,GAAA,kCAAAC,GAAA,kCAAAC,GAAA,kBAAAC,EAAA,mBAAAC,EAAA,0BAAAC,EAAA,kBAAAC,EAAA,mBAAAC,EAAA,yBAAAC,EAAA,sBAAAC,EAAA,iBAAAC,EAAA,2BAAAC,EAAA,mBAAAC,EAAA,eAAAC,EAAA,gBAAAC,GAAA,iBAAAC,EAAA,kBAAAC,EAAA,aAAAC,EAAA,oBAAAC,EAAA,gBAAAC,EAAA,uBAAAC,EAAA,wBAAAC,EAAA,uBAAAC,GAAA,yBAAAC,EAAA,0BAAAC,EAAA,gBAAAC,EAAA,yBAAAC,GAAA,uBAAAC,GAAA,6BAAAC,GAAA,kCAAAC,GAAA,wBAAAC,EAAA,iCAAAC,GAAA,gBAAAC,GAAA,iBAAAC,EAAA,wBAAAC,GAAA,0BAAAC,GAAA,qBAAAC,GAAA,qBAAAC,GAAA,yBAAAC,GAAA,uBAAAC,GAAA,+BAAAC,GAAA,oBAAAC,KCCO,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,EAAN,cAA8BL,CAAY,CAC/C,YAAYC,EAAU,+DAAgE,CACpF,MAAMA,EAAS,aAAc,GAAG,EAChC,KAAK,KAAO,iBACd,CACF,EAGaK,EAAN,cAAoCN,CAAY,CAUrD,YACEC,EACAM,EAAoD,CAAC,EACrDC,EACAJ,EACA,CACA,MAAMH,EAAS,mBAAoB,IAAK,CAAE,OAAAM,EAAQ,GAAGH,CAAQ,CAAC,EAC9D,KAAK,KAAO,wBACZ,KAAK,OAASG,EACd,KAAK,QAAUC,CACjB,CACF,EAGaC,EAAN,cAAkCT,CAAY,CACnD,YAAYU,EAAkBC,EAAY,CACxC,MAAM,GAAGD,CAAQ,KAAKC,CAAE,eAAgB,YAAa,GAAG,EACxD,KAAK,KAAO,qBACd,CACF,EAGaC,EAAN,cAAmCZ,CAAY,CAGpD,YAAYa,EAAe,IAAM,CAC/B,MAAM,6BAA6BA,CAAY,MAAO,aAAc,GAAG,EACvE,KAAK,KAAO,uBACZ,KAAK,aAAeA,CACtB,CACF,EAGaC,GAAN,cAAiCd,CAAY,CAIlD,YACEC,EACAc,EACA,CACA,MAAMd,EAAS,gBAAiB,OAAWc,GAAA,YAAAA,EAAM,OAAO,EACxD,KAAK,KAAO,qBACZ,KAAK,UAAYA,GAAA,YAAAA,EAAM,UACvB,KAAK,cAAgBA,GAAA,YAAAA,EAAM,aAC7B,CACF,EAGaC,EAAN,cAAiChB,CAAY,CAClD,YAAYC,EAAU,iDAAkD,CACtE,MAAMA,EAAS,eAAe,EAC9B,KAAK,KAAO,oBACd,CACF,EC5FO,IAAMgB,GAAW,WACXC,EAAc,SCS3B,IAAMC,GAAyC,CAC7C,WAAY,wBACZ,YAAa,yBACb,MAAO,uBACT,EAcaC,EAAN,KAAiB,CAOtB,YAAYC,EAA0B,CACpC,KAAK,QAAUA,EAAO,QAAQ,QAAQ,MAAO,EAAE,EAC/C,KAAK,QAAUA,EAAO,QACtB,KAAK,OAASA,EAAO,OACrB,KAAK,SAAWA,EAAO,SACvB,KAAK,SAAWA,EAAO,QACzB,CAEA,OAAO,eAAeC,EAA0BC,EAA2B,CACzE,OAAOA,GAAYJ,GAAUG,CAAW,GAAKH,GAAU,UACzD,CAEA,MAAM,QAAqBK,EAAcC,EAA8B,CAAC,EAAe,CAhDzF,IAAAC,EAiDI,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,mBAEhB,eAAgB,gBAAgBC,CAAW,GAC3C,GAAGV,CACL,EAEMW,EAAYT,GAAS,KAAK,UAAUL,EAAA,KAAK,WAAL,YAAAA,EAAA,YACtCc,IACFF,EAAW,aAAa,EAAIE,GAG9B,IAAMC,EAAa,IAAI,gBACjBC,EAAY,WAAW,IAAMD,EAAW,MAAM,EAAG,KAAK,OAAO,EAEnE,GAAI,CACF,IAAME,EAAM,MAAM,MAAMV,EAAK,CAC3B,OAAAN,EACA,QAASW,EACT,KAAMV,GAAQ,KAAO,KAAK,UAAUA,CAAI,EAAI,OAC5C,OAAQI,GAAUS,EAAW,OAC7B,GAAI,KAAK,UAAY,CAAE,SAAU,KAAK,QAAS,CACjD,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,EAAKnB,CAAI,EAClC,IAAIqB,EAAY,mBAAoB,UAAWF,EAAI,MAAM,CACjE,OAASG,EAAK,CAEZ,MADA,aAAaJ,CAAS,EAClBI,aAAeD,EAAmBC,EAClCA,aAAe,cAAgBA,EAAI,OAAS,aACxC,IAAIC,EAAmB,cAAcvB,CAAI,oBAAoB,KAAK,OAAO,KAAK,EAEhF,IAAIuB,EACRD,aAAe,MAAQA,EAAI,QAAU,yBACvC,CACF,CACF,CAEA,IAAiBtB,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,oBAAoBkB,EAAenB,EAA8B,CAC7E,IAAIwB,EAAkC,CAAC,EACvC,GAAI,CACFA,EAAU,MAAML,EAAI,KAAK,CAC3B,MAAQ,CAER,CAQA,IAAMM,EAAOC,GAAeF,EAAO,IAAI,EAEjCG,EACHH,EAAO,SACPA,EAAO,QACP,OAAOC,EAAK,SAAY,SAAWA,EAAK,QAAU,UAClD,OAAOD,EAAO,MAAS,UAAY,OAAO,KAAKC,CAAI,EAAE,SAAW,EAAKD,EAAO,KAAkB,SAC/F,mBAAmBL,EAAI,MAAM,IAAIA,EAAI,UAAU,OAAOnB,CAAI,GAEtD4B,EAAU,OAAOH,EAAK,MAAS,SAAWA,EAAK,KAAO,OAE5D,OAAQN,EAAI,OAAQ,CAClB,IAAK,KACL,IAAK,KACH,MAAM,IAAIU,EAAgBF,CAAG,EAC/B,IAAK,KACH,MAAM,IAAIG,EAAoB9B,EAAM,EAAE,EACxC,IAAK,KAAK,CACR,IAAM+B,EAAc,MAAM,QAAQP,EAAO,MAAM,EAC1CA,EAAO,OACR,CAAC,EACL,MAAM,IAAIQ,EAAsBL,EAAKI,EAAaH,EAASJ,CAAM,CACnE,CACA,IAAK,KAAK,CACR,IAAMS,EAAa,OAAOd,EAAI,QAAQ,IAAI,aAAa,GAAK,GAAG,EAAI,IACnE,MAAM,IAAIe,EAAqBD,CAAU,CAC3C,CACA,QACE,MAAM,IAAIZ,EAAYM,EAAK,YAAaR,EAAI,OAAQK,CAAM,CAC9D,CACF,CACF,EAEA,SAASE,GAAeS,EAAyC,CAC/D,GAAIA,GAAS,OAAOA,GAAU,SAAU,OAAOA,EAC/C,GAAI,OAAOA,GAAU,SAAU,MAAO,CAAC,EACvC,GAAI,CACF,IAAMX,EAAkB,KAAK,MAAMW,CAAK,EACxC,OAAOX,GAAU,OAAOA,GAAW,SAAYA,EAAqC,CAAC,CACvF,MAAQ,CACN,MAAO,CAAC,CACV,CACF,CCzIO,IAAMY,EAAN,MAAMC,CAAe,CAa1B,YACmBC,EACAC,EACAC,EAEAC,EACjB,CALiB,UAAAH,EACA,aAAAC,EACA,mBAAAC,EAEA,eAAAC,CAChB,CAQH,mBAAiD,CAC/C,OAAO,KAAK,eACd,CAcA,MAAM,YACJC,EACAC,EACAC,EAC0B,CA5F9B,IAAAC,EAAAC,EA6FQH,IACF,KAAK,aAAeA,GACpBE,EAAA,KAAK,gBAAL,MAAAA,EAAA,UAAqBF,IAGvB,IAAMI,EAAiC,CAAE,cAAe,OAAQ,EAC5DH,GAAA,MAAAA,EAAM,WACRG,EAAO,SAAWH,EAAK,UAGzB,IAAMI,EAAM,MAAM,KAAK,KAAK,IAC1B,6BAA6BN,CAAa,MAC1C,CACE,OAAAK,EACA,MAAO,KAAK,YACd,CACF,EAEME,EAAU,KAAK,iBAAiBD,CAAG,EACzC,KAAK,gBAAkBC,EACvB,GAAI,EACFH,EAAA,KAAK,YAAL,MAAAA,EAAA,UAAiBG,EACnB,MAAQ,CAER,CACA,OAAOA,CACT,CAQA,MAAM,cACJL,EACmG,CAjIvG,IAAAC,EAAAC,EAAAI,EAkII,IAAMC,EAAYP,EAAK,MAAM,IAAKQ,IAAO,CACvC,UAAWA,EAAE,UACb,QAASA,EAAE,QACX,GAAIA,EAAE,gBAAkB,OAAY,CAAE,cAAeA,EAAE,aAAc,EAAI,CAAC,EAC1E,GAAIA,EAAE,YAAc,OAAY,CAAE,UAAWA,EAAE,SAAU,EAAI,CAAC,EAC9D,GAAIA,EAAE,aAAe,OAAY,CAAE,WAAYA,EAAE,UAAW,EAAI,CAAC,EACjE,SAAUA,EAAE,QACd,EAAE,EAEIC,EAAgC,CACpC,QAAS,KAAK,QACd,UAAAF,CACF,EACIP,EAAK,YAAWS,EAAK,UAAYT,EAAK,WACtCA,EAAK,kBAAiBS,EAAK,gBAAkBT,EAAK,kBAClDC,EAAAD,EAAK,gBAAL,MAAAC,EAAoB,SAAQQ,EAAK,cAAgBT,EAAK,eACtDA,EAAK,UAAY,OAAO,KAAKA,EAAK,QAAQ,EAAE,OAAS,IAAGS,EAAK,SAAWT,EAAK,UAC7EA,EAAK,kBAAoB,OAAO,KAAKA,EAAK,gBAAgB,EAAE,OAAS,IACvES,EAAK,iBAAmBT,EAAK,mBAE3BE,EAAAF,EAAK,eAAL,MAAAE,EAAmB,SAAQO,EAAK,aAAeT,EAAK,cAGxD,IAAMU,EAAwC,CAAC,EAC3CV,EAAK,WAAUU,EAAa,SAAWV,EAAK,UAC5CA,EAAK,gBACPU,EAAa,MAAQV,EAAK,cAC1BU,EAAa,UAAYV,EAAK,kBAC9BU,EAAa,SAAWV,EAAK,kBAE3B,OAAO,KAAKU,CAAY,EAAE,OAAS,IACrCD,EAAK,SAAWC,GAGlB,IAAMC,EAAM,MAAM,KAAK,KAAK,KAIzB,gCAAiCF,CAAI,EAGlCV,EADM,IAAI,IAAIY,EAAI,WAAW,EACV,aAAa,IAAI,OAAO,GAAK,GACtD,YAAK,aAAeZ,EAChBA,KAAcO,EAAA,KAAK,gBAAL,MAAAA,EAAA,UAAqBP,IAEhC,CACL,YAAaY,EAAI,YACjB,cAAeA,EAAI,cACnB,aAAAZ,EACA,WAAYY,EAAI,UAClB,CACF,CAwBA,MAAM,iBACJX,EAYC,CACD,GAAM,CAAE,aAAAY,EAAe,YAAa,OAAQC,EAAgB,GAAGC,CAAY,EAAId,EACzEK,EAAU,MAAM,KAAK,cAAcS,CAAW,EAE9CC,EACJF,IAAmB,OAAO,OAAW,IAAc,OAAO,SAAS,OAAS,IACxEV,EAAS,IAAI,gBAAgB,CACjC,cAAeE,EAAQ,cACvB,aAAcA,EAAQ,YACxB,CAAC,EACKW,EAAM,GAAGD,CAAM,GAAGH,CAAY,IAAIT,EAAO,SAAS,CAAC,GAEzD,MAAO,CAAE,GAAGE,EAAS,IAAAW,CAAI,CAC3B,CAyBA,OAAO,mBACLA,EACwD,CACxD,GAAI,OAAOA,EAAQ,KAAe,OAAO,OAAW,IAAa,OAAO,KACxE,IAAMC,EAAOD,GAAO,OAAO,SAAS,KAChCE,EACJ,GAAI,CACFA,EAAS,IAAI,IAAID,CAAI,CACvB,MAAQ,CACN,OAAO,IACT,CACA,IAAMnB,EAAgBoB,EAAO,aAAa,IAAI,eAAe,EAC7D,GAAI,CAACpB,EAAe,OAAO,KAC3B,IAAMC,EACJmB,EAAO,aAAa,IAAI,cAAc,GAAKA,EAAO,aAAa,IAAI,OAAO,GAAK,GACjF,MAAO,CAAE,cAAApB,EAAe,aAAAC,CAAa,CACvC,CAGA,mBAAmBiB,EAAc,CAC/B,OAAOvB,EAAe,mBAAmBuB,CAAG,CAC9C,CAoBA,MAAM,WAAWG,EAAmBC,EAA8C,CAChF,IAAMb,EAAYa,EAAM,IAAKZ,IAAO,CAClC,UAAWA,EAAE,UACb,QAASA,EAAE,QACX,GAAIA,EAAE,gBAAkB,OAAY,CAAE,cAAeA,EAAE,aAAc,EAAI,CAAC,EAC1E,SAAUA,EAAE,QACd,EAAE,EAEF,OAAO,KAAK,KAAK,KACf,6BAA6BW,CAAS,cACtC,CAAE,UAAAZ,CAAU,EACZ,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAUA,MAAM,eACJY,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,QAJY,MAAM,KAAK,KAAK,IAC1B,6BAA6BA,CAAS,kBACtC,CAAE,MAAO,KAAK,YAAa,CAC7B,GACY,OAAS,CAAC,GAAG,IAAKe,GAAM,KAAK,sBAAsBA,CAAC,CAAC,CACnE,CAQQ,sBAAsBA,EAA0C,CACtE,MAAO,CACL,GAAIA,EAAE,GACN,KAAOA,EAAE,MAAQA,EAAE,kBAAoB,GACvC,YAAcA,EAAE,aAAe,OAC/B,OAASA,EAAE,QAAU,EACrB,SAAWA,EAAE,UAAY,MACzB,cAAgBA,EAAE,eAAiBA,EAAE,uBAAyB,MAChE,CACF,CAMA,MAAM,mBAAmBf,EAAmBgB,EAA+B,CACzE,MAAM,KAAK,KAAK,KACd,6BAA6BhB,CAAS,iBACtC,CAAE,kBAAmBA,EAAW,eAAgBgB,CAAO,EACvD,CAAE,MAAO,KAAK,YAAa,CAC7B,CACF,CAMQ,iBAAiB/B,EAAsE,CAvfjG,IAAAH,EAwfI,IAAMmC,EAAKhC,EAAI,gBACTiC,EAAkBD,EAAG,gBAAkB,CAAC,EACxCE,EAAWlC,EAAI,SAAWgC,EAAG,SAAWC,EAAe,CAAC,GAAK,CAAC,EAC9D9B,EAAa6B,EAAG,kBAAoB,CAAC,EACrCf,EAAWe,EAAG,SACdG,GAAoBtC,EAAAqC,EAAQ,UAAYF,EAAG,8BAAvB,YAAAnC,EAA4E,cAEhGmB,EAAQb,EAAU,IAAKiC,GAAO,CAClC,IAAMC,EAAQD,EAAG,MAOXE,EAAWF,EAAG,UAAWC,GAAA,YAAAA,EAAO,UAAW,CAAC,EAC5CE,EAAWH,EAAG,SAAWE,EAAQ,SAAW,CAAC,EAC7CE,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,UAAYC,EAAQ,UAAY,GACnD,GAAIF,GAAA,MAAAA,EAAO,UAAY,CACrB,UAAW,CACT,SAAWA,EAAM,UAAY,QAC7B,cAAgBA,EAAM,eAAiB,CACzC,CACF,EAAI,CAAC,CACP,CACF,CAAC,EAEKM,EAAgBT,EAAQ,OAAS,CAAC,EAExC,MAAO,CACL,GAAIF,EAAG,GACP,QAASA,EAAG,QACZ,cAAeA,EAAG,cAClB,SAAWG,GAAmB,MAC9B,MAAAnB,EACA,OAAQ,CACN,SAAWkB,EAAQ,gBAAkB,EACrC,SAAWA,EAAQ,sBAAwB,EAC3C,SAAWA,EAAQ,cAAgB,EACnC,IAAMA,EAAQ,gBAAkB,EAKhC,MAAQA,EAAQ,qBACdA,EAAQ,aACRS,EAAa,OAAO,CAACC,EAAWxC,IAA+BwC,GAAMxC,EAAE,QAAU,GAAe,CAAC,EACnG,SAAW+B,GAAmB,KAChC,EACA,SAAUlB,EACN,CACE,GAAIA,EAAS,GACb,MAAOA,EAAS,MAChB,UAAWA,EAAS,UACpB,SAAUA,EAAS,SACnB,MAAOA,EAAS,KAClB,EACA,OACJ,gBAAiB,KAAK,iBAAiBe,EAAG,eAAe,EACzD,eAAgB,KAAK,iBAAiBA,EAAG,cAAc,EACvD,uBAAyBA,EAAG,gBAAkB,KAC9C,SAAUA,EAAG,SACb,GAAI,OAAOA,EAAG,OAAU,UAAY,CAAE,MAAOA,EAAG,KAAM,EAAI,CAAC,CAC7D,CACF,CASQ,iBAAiBhC,EAAmC,CAC1D,GAAI,CAACA,GAAO,OAAOA,GAAQ,SAAU,OACrC,IAAMyB,EAAIzB,EACJ6C,EAAe,CACnB,UAAWpB,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,OAAOoB,CAAG,EAAE,KAAMC,GAAMA,IAAM,QAAaA,IAAM,EAAE,EAAID,EAAM,MAC7E,CACF,EAWaE,GAAqB3D,EAAe,mBAMjD,SAASsC,GAA8CsB,EAAW,CAChE,IAAMC,EAAkC,CAAC,EACzC,OAAW,CAACC,EAAGJ,CAAC,IAAK,OAAO,QAAQE,CAAG,EACdF,GAAM,MAAQA,IAAM,KACzCG,EAAOC,CAAC,EAAIJ,GAGhB,OAAQ,OAAO,KAAKG,CAAM,EAAE,OAAS,EAAIA,EAAS,MACpD,CC7jBO,SAASE,GAAyBC,EAAuD,CA9DhG,IAAAC,EAAAC,EA+DE,GAAI,CAACF,EAAS,OAEd,IAAMG,EAAmB,CACvB,UAAWH,EAAQ,UACnB,SAAUA,EAAQ,WAClB,OAAOC,EAAAD,EAAQ,eAAR,YAAAC,EAAuB,GAC9B,OAAOC,EAAAF,EAAQ,eAAR,YAAAE,EAAuB,GAC9B,KAAMF,EAAQ,SACd,MAAOA,EAAQ,mBACf,WAAYA,EAAQ,WACpB,QAASA,EAAQ,YACjB,MAAOA,EAAQ,WACjB,EAEA,OAAOI,GAASD,CAAO,EAAIA,EAAU,MACvC,CAGO,SAASE,GAA0BL,EAAwD,CAChG,GAAI,CAACA,EAAS,OAEd,GAAM,CAACM,EAAW,GAAGC,CAAI,GAAKP,EAAQ,MAAQ,IAAI,KAAK,EAAE,MAAM,KAAK,EAE9DG,EAAmB,CACvB,UAAWG,GAAa,OACxB,SAAUC,EAAK,OAASA,EAAK,KAAK,GAAG,EAAI,OACzC,MAAOP,EAAQ,SACf,MAAO,CAACA,EAAQ,SAAUA,EAAQ,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAK,OACzE,KAAMA,EAAQ,SACd,MAAOA,EAAQ,mBACf,WAAYA,EAAQ,WACpB,QAASA,EAAQ,YACjB,MAAOA,EAAQ,WACjB,EAEA,OAAOI,GAASD,CAAO,EAAIA,EAAU,MACvC,CA8BA,SAASK,GAASC,EAA2B,CAjI7C,IAAAC,EAAAC,EAkIE,MAAO,IAAQD,EAAAD,EAAQ,QAAR,MAAAC,EAAe,UAAUC,EAAAF,EAAQ,UAAR,MAAAE,EAAiB,QAC3D,CCXA,IAAMC,GAA2D,wFAEjE,SAASC,GAAWC,EAAaC,EAAuC,CACtE,OAAIA,EAAQ,EAAU,QAAQ,QAAQ,EAC/B,IAAI,QAAc,CAACC,EAASC,IAAW,CAC5C,IAAMC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAMJ,EACbI,EAAO,MAAQ,GACfA,EAAO,OAAS,IAAMF,EAAQ,EAC9BE,EAAO,QAAU,IAAMD,EAAO,IAAI,MAAM,+BAA+B,CAAC,EACxE,SAAS,KAAK,YAAYC,CAAM,CAClC,CAAC,CACH,CAEA,eAAeC,IAA2C,CACxD,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,GAAIP,GAAS,CACX,IAAMQ,EAAI,OACV,OAAIA,EAAE,aAAqBA,EAAE,cAC7B,MAAMP,GAAWD,GAAS,IAAM,EAAQQ,EAAE,YAAa,EAChDA,EAAE,cAAgB,KAC3B,CACA,OAAQ,KAAM,QAAO,uBAAuB,CAC9C,CAMA,IAAMC,GAAW,cACXC,GAAW,YACXC,GAAc,YACdC,GAAc,GACdC,GAAW,IACXC,GAAW,IAEXC,GAAc,GAGb,SAASC,GAAWC,EAAwD,CACjF,GAAI,GAAC,MAAM,QAAQA,CAAK,GAAKA,EAAM,SAAW,GAC9C,OAAOA,EAAM,IAAKC,IAAU,CAAE,GAAIA,EAAK,UAAW,SAAUA,EAAK,SAAU,WAAYA,EAAK,UAAW,EAAE,CAC3G,CAGA,SAASC,GAAQC,EAAyF,CACxG,GAAI,CAACA,EAAM,OACX,IAAMC,EAAiD,CAAC,EACxD,OAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQH,CAAI,GACxC,OAAOG,GAAU,UAAY,OAAOA,GAAU,UAAY,OAAOA,GAAU,aAAWF,EAAIC,CAAG,EAAIC,GAEvG,OAAO,OAAO,KAAKF,CAAG,EAAE,OAAS,EAAIA,EAAM,MAC7C,CAQA,IAAMG,GAAgE,CACpE,KAAM,OACN,eAAgB,cAChB,cAAe,WACjB,EAEA,SAASC,IAAe,CACtB,GAAI,CACF,OAAO,OAAO,WAAW,CAC3B,MAAQ,CACN,MAAO,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAG,EAAE,CAAC,EAC9E,CACF,CAMA,SAASC,GAAeC,EAAqC,CAC3D,IAAMN,EAAiD,CAAC,EACxD,QAAWO,KAASD,EAAQ,CAE1B,GAAM,CAAE,SAAAE,EAAU,GAAAC,EAAI,MAAAC,EAAO,GAAGC,CAAK,EAAIJ,GACxCP,EAAAQ,KAAAR,EAAAQ,GAAkB,CAAC,IAAG,KAAK,CAAE,GAAGG,EAAM,QAAS,GAAM,CAACD,CAAK,EAAGD,EAAI,OAAQF,EAAM,QAAU,CAAC,CAAE,CAAC,CACjG,CACA,OAAOP,CACT,CAMO,IAAMY,EAAN,KAAkB,CAgBvB,YACmBC,EACAC,EACAC,EACjB,CAHiB,aAAAF,EACA,aAAAC,EACA,eAAAC,EAlBnB,KAAiB,QAAyB,CAAC,EAC3C,KAAiB,SAAW,IAAI,IAChC,KAAiB,QAA6B,CAAC,EAE/C,KAAQ,cAA+B,KACvC,KAAQ,aAA8B,KACtC,KAAQ,gBAA4B,CAAC,EACrC,KAAQ,cAAoD,KAC5D,KAAQ,YAAmD,KAG3D,KAAQ,cAAoD,KAC5D,KAAQ,WAAmD,KAC3D,KAAQ,UAAY,EAMjB,CASK,MAAiB,CACvB,GAAI,CACF,OAAQ,aAAa,QAAQ3B,EAAQ,GAAK,IAAI,MAAM,GAAG,CACzD,MAAQ,CACN,MAAO,CAAC,CACV,CACF,CAEQ,SAAmB,CACzB,OAAO,KAAK,KAAK,EAAE,CAAC,IAAM,KAAK,OACjC,CAEQ,eAAwB,CAC9B,OAAO,KAAK,KAAK,EAAE,CAAC,GAAK,KAAK,SAChC,CAGQ,KAAe,CACrB,OAAO,OAAO,OAAW,KAAe,CAAC,KAAK,QAAQ,CACxD,CAEQ,KAAY,CAClB,GAAI,CACF,aAAa,QAAQA,GAAU,GAAG,KAAK,OAAO,IAAI,KAAK,SAAS,EAAE,CACpE,MAAQ,CAER,CACF,CAIA,KAAK4B,EAAgBjB,EAAuB,CAC1C,GAAI,OAAO,OAAW,IAAa,OACnC,KAAK,IAAI,EACT,IAAMkB,GAAOlB,GAAA,YAAAA,EAAM,OAAQ,OAAO,SAAS,SACrCE,EAAM,GAAGe,CAAM,IAAIC,CAAI,GACvBC,EAAK,KAAK,IAAI,EACdC,EAAW,KAAK,SAAS,IAAIlB,CAAG,EAClCkB,IAAa,QAAaD,EAAKC,EAAW1B,KAC9C,KAAK,SAASQ,EAAKiB,CAAE,EACrB,KAAK,cAAgBF,EACrB,KAAK,OAAO,EACZ,KAAK,KAAK,CAAE,KAAM,OAAQ,OAAAA,EAAQ,GAAAE,EAAI,KAAAD,CAAK,CAAC,EACvC,KAAK,OAAO,EAAE,KAAMG,GAAWA,GAAA,YAAAA,EAAQ,SAASH,EAAM,CAAE,OAAAD,CAAO,EAAE,EACjE,KAAK,KAAK,EAAE,KAAMK,GAAMA,GAAA,YAAAA,EAAG,KAAK,CAAE,QAASL,CAAO,EAAE,EAAE,MAAM,IAAG,EAAY,EAClF,CAEA,MAAMM,EAAcvB,EAAwB,CAC1C,GAAI,KAAK,IAAI,EAAG,OAChB,IAAMiB,EAAS,KAAK,cAEpB,GAAIA,IAAW,KAAM,OAGrB,IAAMO,EAAWpB,GAAgBmB,CAAI,EAC/BE,EAAU,GAAGD,GAAYD,CAAI,IAAIlB,GAAK,CAAC,GAC7C,KAAK,KAAK,CAAE,KAAM,QAAS,OAAAY,EAAQ,KAAAM,EAAM,GAAI,KAAK,IAAI,EAAG,QAAAE,EAAS,MAAO1B,GAAQC,CAAI,CAAE,CAAC,EACnF,KAAK,OAAO,EAAE,KAAMqB,GACvBG,EAAWH,GAAA,YAAAA,EAAQ,MAAMG,EAAUxB,EAAM,CAAE,OAAAiB,EAAQ,QAAAQ,CAAQ,GAAKJ,GAAA,YAAAA,EAAQ,YAAYE,EAAMvB,EAAM,CAAE,OAAAiB,CAAO,EAC3G,EACK,KAAK,KAAK,EAAE,KAAMK,GAAMA,GAAA,YAAAA,EAAG,MAAMC,EAAM,CAAE,GAAIxB,GAAQC,CAAI,GAAK,CAAC,EAAI,QAASiB,EAAQ,eAAgBQ,CAAQ,EAAE,EAAE,MAAM,IAAG,EAAY,CAC5I,CAGQ,SAASvB,EAAaiB,EAAkB,CAC9C,OAAW,CAACO,EAAMC,CAAI,IAAK,KAAK,SAC1BR,EAAKQ,GAAQjC,IAAU,KAAK,SAAS,OAAOgC,CAAI,EAGtD,KAAO,KAAK,SAAS,MAAQ/B,IAAa,CACxC,IAAMiC,EAAS,KAAK,SAAS,KAAK,EAAE,KAAK,EACzC,GAAIA,EAAO,OAAS,GAAM,MAC1B,KAAK,SAAS,OAAOA,EAAO,KAAK,CACnC,CACA,KAAK,SAAS,IAAI1B,EAAKiB,CAAE,CAC3B,CAEA,SAASU,EAA0B,CAC7B,KAAK,IAAI,IAER,KAAK,OAAO,EAAE,KAAMR,GACvBA,GAAA,YAAAA,EAAQ,SAAS,CAAE,MAAOQ,EAAI,MAAO,MAAOA,EAAI,MAAO,WAAYA,EAAI,UAAW,EACpF,EACK,KAAK,KAAK,EAAE,KAAM,GAAM,iBAAG,SAASA,EAAI,YAAc,KAAM,CAAE,MAAOA,EAAI,MAAO,MAAOA,EAAI,MAAO,WAAYA,EAAI,UAAW,EAAE,EAAE,MAAM,IAAG,EAAY,EAC7J,CAEA,QAAQC,EAAqC,CACvC,KAAK,IAAI,GACR,KAAK,OAAO,EAAE,KAAMT,GAAWA,GAAA,YAAAA,EAAQ,QAAQS,EAAM,CAC5D,CAEA,MAAM,QAA+B,CACnC,OAAI,OAAO,OAAW,IAAoB,KAAK,SAAS,GACpD,KAAK,QAAQ,GAAG,MAAM,KAAK,OAAO,EAC/B,KAAK,SAAS,EACvB,CAKA,aAAaC,EAAwG,CACnH,KAAK,UAAU,mBAAoBA,EAAM,kBAAmBA,CAAK,CACnE,CAGA,SAASA,EAA8F,CACrG,KAAK,UAAU,WAAYA,EAAM,QAASA,CAAK,CACjD,CAGQ,UACNC,EACAtB,EACAqB,EACM,CACF,KAAK,IAAI,GACR,KAAK,OAAO,EAAE,KAAMV,GAAQ,CArWrC,IAAAY,EAsWM,OAAAZ,GAAA,YAAAA,EAAQ,MACNW,EACA,CAAE,MAAOD,EAAM,OAAQ,SAAUA,EAAM,SAAU,SAAUA,EAAM,MAAO,WAAWE,EAAAF,EAAM,QAAN,YAAAE,EAAa,MAAO,EACvG,CAAE,QAAS,GAAGD,CAAK,IAAItB,CAAE,EAAG,GAEhC,CACF,CAGA,WAAWwB,EAA8B/B,EAA6CgC,EAAkC,CAClH,KAAK,IAAI,IACb,KAAK,QAAQ,KAAK,CAAE,OAAAD,EAAQ,MAAA/B,EAAO,OAAAgC,CAAO,CAAC,EAC3C,KAAK,OAAO,EACZ,KAAK,KAAK,CAAE,KAAM,SAAU,OAAAD,EAAQ,MAAA/B,EAAO,OAAAgC,CAAO,CAAC,EACrD,CAIQ,UAAwB,CAC9B,MAAO,CACL,QAAS,OAAO,OAAW,IAAc,GAAQ,KAAK,QAAQ,EAC9D,QAAS,KAAK,QACd,UAAW,KAAK,cAAc,EAC9B,IAAK,CAAE,KAAMC,GAAU,QAASC,CAAY,EAC5C,aAAc,KAAK,aACnB,OAAQ,CAAE,OAAQ,KAAK,gBAAgB,OAAS,EAAG,UAAW,CAAC,GAAG,KAAK,eAAe,CAAE,EACxF,QAAS,CAAC,GAAG,KAAK,OAAO,CAC3B,CACF,CAMQ,QAAsC,CAC5C,GAAI,KAAK,gBAAkB,KAAM,OAAO,KAAK,cAC7C,IAAMC,EACJ,GAAG,KAAK,OAAO,qCACH,mBAAmB,KAAK,OAAO,CAAC,WAAW,mBAAmB,KAAK,cAAc,CAAC,CAAC,GACjG,YAAK,eAAiB,SAAyC,CAC7D,GAAI,CACF,IAAMC,EAAW,MAAM,MAAMD,CAAG,EAChC,GAAI,CAACC,EAAS,GAAI,OAAO,KACzB,IAAMC,EAAU,MAAMD,EAAS,KAAK,EACpC,YAAK,aAAeC,EAAO,cAAgB,KACpCA,CACT,MAAQ,CACN,OAAO,IACT,CACF,GAAG,EACI,KAAK,aACd,CAGA,MAAqC,CACnC,OAAI,OAAO,OAAW,IAAoB,QAAQ,QAAQ,IAAI,GAC9D,KAAK,cAAL,KAAK,aAAiB,SAAY,CA9ZtC,IAAAP,EAAAQ,EA+ZM,GAAI,CACF,IAAMD,EAAS,MAAM,KAAK,OAAO,EACjC,GAAI,CAACA,GAAW,CAACA,EAAO,SAAW,CAACA,EAAO,YAAc,OAAO,KAChE,IAAME,EAAO,KAAK,QAAQ,QAAQ,OAAQ,EAAE,EACtCtD,EAAI,OAIV,OAHI,QAAO6C,EAAA7C,EAAE,MAAF,YAAA6C,EAAO,OAAS,YACzB,MAAMpD,GAAW6D,EAAO,oBAAqB,IAAG,CAra1D,IAAAT,EAqa6D,eAAOA,EAAA7C,EAAE,MAAF,YAAA6C,EAAO,OAAS,WAAU,EAElF,QAAOQ,EAAArD,EAAE,MAAF,YAAAqD,EAAO,OAAS,WAAmB,MAC9CrD,EAAE,IAAI,KAAK,CAAE,QAAS,KAAK,QAAS,QAASoD,EAAO,QAAU,IAAI,IAAIA,EAAO,QAAQ,GAAG,EAAE,OAASE,EACjG,UAAW,KAAK,UAAW,QAAS,WAAY,aAAc,EAAK,CAAC,EAC/DtD,EAAE,IACX,MAAQ,CACN,OAAO,IACT,CACF,GAAG,GACI,KAAK,YACd,CAGA,kBAAkBuD,EAA+B,CAC3C,KAAK,IAAI,GACR,KAAK,KAAK,EAAE,KAAM,GAAM,iBAAG,MAAMA,EAAgB,EAAE,MAAM,IAAG,EAAY,CAC/E,CAEQ,QAAsC,CAC5C,OAAK,KAAK,QAAQ,GAClB,KAAK,gBAAL,KAAK,cAAkB,KAAK,YAAY,GACjC,KAAK,eAFgB,QAAQ,QAAQ,IAAI,CAGlD,CAEA,MAAc,aAA2C,CA9b3D,IAAAV,EA+bI,GAAI,CACF,IAAMO,EAAS,MAAM,KAAK,OAAO,EACjC,GAAIA,IAAW,KAAM,OAAO,KAC5B,IAAMI,EAAS,MAAMzD,GAAW,EAChC,GAAIyD,IAAW,KAAM,OAAO,KAC5B,IAAMvB,EAASuB,EAAO,kBAAkB,CACtC,OAAQtC,GAAekC,EAAO,QAAU,CAAC,CAAC,EAC1C,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,iBAAgBP,EAAAO,EAAO,UAAP,YAAAP,EAAgB,YAAa,GAC7C,SAAWC,GAAwB,KAAK,cAAcA,CAAM,CAC9D,CAAC,EACD,aAAMb,EAAO,KAAK,EAClB,KAAK,gBAAkB,CAAC,GAAG,IAAI,KAAKmB,EAAO,QAAU,CAAC,GAAG,IAAKhC,GAAUA,EAAM,QAAQ,CAAC,CAAC,EACjFa,CACT,MAAQ,CACN,OAAO,IACT,CACF,CAEQ,cAAca,EAA2B,CAC/C,IAAMC,EAASD,EAAO,QAAU,CAAC,EACjC,KAAK,QAAQ,KAAK,CAAE,OAAQA,EAAO,KAAM,MAAOA,EAAO,SAAU,OAAAC,CAAO,CAAC,EACzE,KAAK,KAAK,CAAE,KAAM,SAAU,OAAQD,EAAO,KAAM,MAAOA,EAAO,SAAU,OAAAC,CAAO,CAAC,CACnF,CAIQ,QAAe,CACrB,GAAI,KAAK,WAAa,OAAO,OAAW,IAAa,OACrD,KAAK,UAAY,GACjB,IAAMU,EAAWb,GAAuB,CAClCA,EAAM,OAAS,oBAAsB,SAAS,kBAAoB,UACtE,KAAK,MAAM,CACb,EACA,OAAO,iBAAiB,WAAYa,CAAO,EAC3C,OAAO,iBAAiB,mBAAoBA,CAAO,CACrD,CAEQ,KAAKC,EAA2B,CACtC,GAAK,KAAK,QAAQ,EAElB,IADA,KAAK,QAAQ,KAAKA,CAAM,EACpB,KAAK,QAAQ,QAAUtD,GAAa,CACtC,KAAK,MAAM,EACX,MACF,CACI,KAAK,aAAe,OAAM,KAAK,WAAa,WAAW,IAAM,KAAK,MAAM,EAAGC,EAAQ,GACzF,CAGQ,WAAWsD,EAA4B7C,EAAqB,CAClE,GAAI,CACF,IAAM8C,EAAQD,IAAU,QAAU,aAAe,eAC3CE,EAAWD,EAAM,QAAQ9C,CAAG,EAClC,GAAI+C,EAAU,OAAOA,EACrB,IAAMC,EAAQ7C,GAAK,EACnB,OAAA2C,EAAM,QAAQ9C,EAAKgD,CAAK,EACjBA,CACT,MAAQ,CACN,OAAO7C,GAAK,CACd,CACF,CAEQ,OAAc,CAKpB,GAJI,KAAK,aAAe,OACtB,aAAa,KAAK,UAAU,EAC5B,KAAK,WAAa,MAEhB,KAAK,QAAQ,SAAW,EAAG,OAC/B,IAAM8C,EAAU,KAAK,QAAQ,OAAO,EAAG3D,EAAW,EAC5C4D,EAAmC,CACvC,QAAS,KAAK,QACd,UAAW,KAAK,cAAc,EAC9B,IAAK,CAAE,KAAMhB,GAAU,QAASC,CAAY,EAC5C,YAAa,KAAK,WAAW,QAAS/C,EAAQ,EAC9C,UAAW,KAAK,WAAW,UAAWC,EAAW,EACjD,QAAA4D,CACF,EACI,KAAK,eAAiB,OAAMC,EAAQ,aAAe,KAAK,cAC5D,IAAMC,EAAO,KAAK,UAAUD,CAAO,EAC7Bd,EAAM,GAAG,KAAK,OAAO,4BAC3B,GAAI,CACF,GAAI,OAAO,UAAc,KAAe,OAAO,UAAU,YAAe,YAClE,UAAU,WAAWA,EAAK,IAAI,KAAK,CAACe,CAAI,EAAG,CAAE,KAAM,0BAA2B,CAAC,CAAC,EAAG,MAE3F,MAAQ,CAER,CACA,GAAI,CACG,MAAMf,EAAK,CACd,OAAQ,OACR,KAAAe,EACA,UAAW,GACX,QAAS,CAAE,eAAgB,0BAA2B,CACxD,CAAC,EAAE,MAAM,IAAG,EAAY,CAC1B,MAAQ,CAER,CACF,CACF,EChhBO,IAAMC,GAAgC,iBAGhCC,GAAgC,IAGhCC,GAA6D,CAAC,OAAQ,YAAa,SAAU,SAAS,EAG5G,SAASC,GAAsBC,EAA4C,CAChF,OAAKA,EACEA,EAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,KAAM,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,IAAMJ,GADpD,EAEtB,CAMO,SAASK,GAA8BC,EAAiE,CAC7G,IAAMC,EAASD,EAAS,OAAQE,GAAYA,EAAQ,OAAO,OAAS,CAAC,EAC/DA,EAAUD,EAAO,KAAME,GAAc,CAACA,EAAU,OAAO,GAAKF,EAAO,CAAC,EAC1E,GAAI,CAACC,EAAS,OAAO,KACrB,IAAME,EAAQF,EAAQ,OAAO,KAAMC,GAAcA,EAAU,MAAM,GAAKD,EAAQ,OAAO,CAAC,EACtF,MAAO,CAAE,QAASA,EAAQ,QAAS,MAAOE,EAAM,MAAO,CACzD,CAGO,SAASC,GACdL,EACAM,EACAC,EACwB,CAjD1B,IAAAC,EAAAC,EAkDE,IAAMC,IAASF,EAAAR,EAAS,KAAME,GAAYA,EAAQ,UAAYI,CAAO,IAAtD,YAAAE,EAAyD,SAAU,CAAC,EAC7EG,EAAOD,EAAO,KAAMN,GAAUA,EAAM,SAAWG,CAAY,EAC3DK,EAAWF,EAAO,KAAMN,GAAUA,EAAM,MAAM,GAAKM,EAAO,CAAC,EACjE,MAAO,CAAE,QAAAJ,EAAS,QAAQG,EAAAE,GAAQC,IAAR,YAAAH,EAAmB,SAAUF,CAAa,CACtE,CAGO,SAASM,GACdC,EACoB,CACpB,GAAI,CAACA,EAAQ,MAAO,UACpB,GAAIA,EAAO,KAAM,MAAO,OACxB,OAAQA,EAAO,OAAQ,CACrB,IAAK,WACL,IAAK,WACH,MAAO,aACT,IAAK,YACH,MAAO,YACT,IAAK,SACH,MAAO,SACT,IAAK,UACH,MAAO,UACT,QACE,OAAOA,EAAO,QAAU,UAAY,SACxC,CACF,CAGO,SAASC,GAAyBC,EAA0BC,EAAuB,CACxF,GAAI,CAACD,EAAW,MAAO,GACvB,IAAME,EAAM,KAAK,MAAMF,CAAS,EAChC,OAAI,OAAO,MAAME,CAAG,EAAU,EACvB,KAAK,IAAI,EAAG,KAAK,OAAOA,EAAMD,GAAS,GAAI,CAAC,CACrD,CAGO,SAASE,GAA6BC,EAAyB,CACpE,IAAMC,EAAI,KAAK,IAAI,EAAG,KAAK,MAAMD,CAAO,CAAC,EACnCE,EAAI,KAAK,MAAMD,EAAI,IAAI,EACvBE,EAAI,KAAK,MAAOF,EAAI,KAAQ,EAAE,EAC9BG,EAAM,OAAOH,EAAI,EAAE,EAAE,SAAS,EAAG,GAAG,EAC1C,OAAOC,EAAI,EAAI,GAAGA,CAAC,IAAI,OAAOC,CAAC,EAAE,SAAS,EAAG,GAAG,CAAC,IAAIC,CAAG,GAAK,GAAGD,CAAC,IAAIC,CAAG,EAC1E,CASA,IAAMC,GAAc,8EAOPC,EAAN,KAA4B,CAgBjC,YACmBC,EACAC,EACjB,CAFiB,SAAAD,EACA,aAAAC,EAjBnB,KAAQ,MAAoC,CAC1C,QAAS,OACT,SAAU,CAAC,EACX,UAAW,KACX,QAAS,KACT,cAAe,KACf,WAAY,GACZ,MAAO,IACT,EAEA,KAAiB,UAAY,IAAI,IACjC,KAAQ,UAAkD,KAC1D,KAAQ,QAAU,GAClB,KAAQ,aAAe,GAMrB,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EACzC,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,CACzC,CAEA,UAAuC,CACrC,OAAO,KAAK,KACd,CAGA,UAAUC,EAAmE,CAC3E,YAAK,UAAU,IAAIA,CAAQ,EACpB,IAAM,CACX,KAAK,UAAU,OAAOA,CAAQ,CAChC,CACF,CAGA,SAASZ,EAAgB,KAAK,IAAI,EAAuB,CACvD,GAAM,CAAE,QAAAa,EAAS,cAAAC,CAAc,EAAI,KAAK,MAClCC,EAAQnB,GAAmBkB,IAAkBD,EAAU,CAAE,OAAQA,EAAQ,OAAQ,KAAM,GAAO,QAAS,EAAM,EAAI,KAAK,EAE5H,OADkBA,IAAY,MAAQE,IAAU,WAAajB,GAAyBe,EAAQ,UAAWb,CAAK,IAAM,EACjG,UAAYe,CACjC,CAGA,eAAef,EAAgB,KAAK,IAAI,EAAW,CAzJrD,IAAAT,EA0JI,OAAOO,KAAyBP,EAAA,KAAK,MAAM,UAAX,YAAAA,EAAoB,YAAa,KAAMS,CAAK,CAC9E,CAGA,MAAM,aAAmD,CACvD,KAAK,SAAS,CAAE,QAAS,UAAW,MAAO,IAAK,CAAC,EACjD,GAAI,CACF,IAAMgB,EAAS,MAAM,KAAK,IAAI,wBAAwB,KAAK,QAAQ,iBAAiB,EACpF,GAAI,CAACA,EAAO,GACV,YAAK,SAAS,CAAE,QAAS,cAAe,SAAU,CAAC,EAAG,UAAW,KAAM,MAAOA,EAAO,SAAWR,EAAY,CAAC,EACtG,KAAK,MAEd,IAAMS,EAAY,KAAK,MAAM,WAAanC,GAA8BkC,EAAO,QAAQ,EACvF,KAAK,SACHC,EACI,CAAE,QAAS,QAAS,SAAUD,EAAO,SAAU,UAAAC,CAAU,EACzD,CAAE,QAAS,cAAe,SAAUD,EAAO,SAAU,UAAW,KAAM,MAAOR,EAAY,CAC/F,CACF,OAASU,EAAgB,CACvB,KAAK,SAAS,CAAE,QAAS,cAAe,MAAOC,GAAUD,CAAK,CAAE,CAAC,CACnE,CACA,OAAO,KAAK,KACd,CAGA,OAAOE,EAAkD,CACvD,IAAMC,EAAU,KAAK,MAAM,UAC3B,GAAID,EAAK,UAAY,QAAaA,EAAK,WAAYC,GAAA,YAAAA,EAAS,SAAS,CACnE,KAAK,SAAS,CAAE,UAAWjC,GAA2B,KAAK,MAAM,SAAUgC,EAAK,QAASA,EAAK,QAASC,GAAA,YAAAA,EAAS,QAAS,EAAE,CAAE,CAAC,EAC9H,MACF,CACID,EAAK,QAAU,QAAaC,GAAS,KAAK,SAAS,CAAE,UAAW,CAAE,GAAGA,EAAS,MAAOD,EAAK,KAAM,CAAE,CAAC,CACzG,CAMA,MAAM,IAAIH,EAAyE,CACjF,IAAMK,EAASL,GAAa,KAAK,MAAM,UACvC,GAAI,CAACK,EAAQ,MAAO,CAAE,GAAI,GAAO,KAAM,sBAAuB,QAAS,6BAA8B,EACrG,GAAI,KAAK,MAAM,WAAY,MAAO,CAAE,GAAI,GAAO,KAAM,kBAAmB,QAAS,oCAAqC,EAEtH,KAAK,SAAS,CAAE,WAAY,GAAM,MAAO,KAAM,UAAWA,CAAO,CAAC,EAClE,GAAI,CACF,IAAMN,EAAS,MAAM,KAAK,IAAI,2BAA2B,CACvD,kBAAmB,KAAK,QAAQ,kBAChC,QAASM,EAAO,QAChB,MAAOA,EAAO,KAChB,CAAC,EACD,OAAKN,EAAO,IAIZ,KAAK,QAAU,GACf,KAAK,SAAS,CAAE,WAAY,GAAO,QAASA,EAAO,QAAS,cAAe,IAAK,CAAC,EACjF,KAAK,aAAa,EACXA,IANL,KAAK,SAAS,CAAE,WAAY,GAAO,MAAOA,EAAO,OAAQ,CAAC,EACnDA,EAMX,OAASE,EAAgB,CACvB,IAAMK,EAAUJ,GAAUD,CAAK,EAC/B,YAAK,SAAS,CAAE,WAAY,GAAO,MAAOK,CAAQ,CAAC,EAC5C,CAAE,GAAI,GAAO,KAAM,kBAAmB,QAAAA,CAAQ,CACvD,CACF,CAGA,MAAM,eAAqD,CA5N7D,IAAAhC,EAAAC,EAAAgC,EA6NI,IAAMX,EAAU,KAAK,MAAM,QAC3B,GAAI,CAACA,EAAS,OAAO,KACrB,GAAI,CACF,IAAMG,EAAS,MAAM,KAAK,IAAI,uBAAuB,CACnD,kBAAmB,KAAK,QAAQ,kBAChC,uBAAwBH,EAAQ,sBAClC,CAAC,EAED,GAAI,CAACG,EAAO,MAAMzB,EAAA,KAAK,MAAM,UAAX,YAAAA,EAAoB,0BAA2BsB,EAAQ,uBAAwB,OAAO,KACxG,IAAMhB,EAA8B,CAClC,OAAQmB,EAAO,OACf,UAAWA,EAAO,UAClB,QAASA,EAAO,QAChB,cAAeA,EAAO,cACtB,sBAAuBA,EAAO,sBAC9B,OAAQA,EAAO,OACf,cAAeA,EAAO,cACtB,KAAMA,EAAO,KACb,QAASA,EAAO,QAChB,YAAaA,EAAO,WACtB,EACA,YAAK,SAAS,CAAE,cAAenB,CAAO,CAAC,EACnCA,EAAO,MAAQ,CAAC,KAAK,eACvB,KAAK,aAAe,IACpB2B,GAAAhC,EAAA,KAAK,SAAQ,SAAb,MAAAgC,EAAA,KAAAhC,EAAsBK,IAEjBA,CACT,MAAQ,CAEN,OAAO,IACT,CACF,CAGA,QAAe,CACT,CAAC,KAAK,MAAM,SAAWlB,GAA4B,SAAS,KAAK,SAAS,CAAC,IAC/E,KAAK,QAAU,GACf,KAAK,aAAa,EACpB,CAGA,MAAa,CACX,KAAK,QAAU,GACX,KAAK,WAAW,aAAa,KAAK,SAAS,EAC/C,KAAK,UAAY,IACnB,CAEQ,cAAqB,CACvB,KAAK,WAAW,aAAa,KAAK,SAAS,EAC/C,KAAK,UAAY,WAAW,SAAY,CACtC,KAAK,UAAY,KACjB,MAAM,KAAK,cAAc,EACrB,CAAC,KAAK,SAAW,CAACA,GAA4B,SAAS,KAAK,SAAS,CAAC,GAAG,KAAK,aAAa,CACjG,EAAG,KAAK,QAAQ,gBAAkB,GAA6B,CACjE,CAEQ,SAAS8C,EAAkD,CArRrE,IAAAlC,EAAAC,EAsRI,KAAK,MAAQ,CAAE,GAAG,KAAK,MAAO,GAAGiC,CAAM,GACvCjC,GAAAD,EAAA,KAAK,SAAQ,WAAb,MAAAC,EAAA,KAAAD,EAAwB,KAAK,OAC7B,KAAK,UAAU,QAASqB,GAAaA,EAAS,KAAK,KAAK,CAAC,CAC3D,CACF,EAEA,SAASO,GAAUD,EAAwB,CACzC,OAAOA,aAAiB,OAASA,EAAM,QAAUA,EAAM,QAAUV,EACnE,CC9QO,SAASkB,GAAmBC,EAAwC,CACzE,GAAI,CAACA,GAAU,OAAOA,GAAW,UAAY,MAAM,QAAQA,CAAM,EAAG,OAAO,KAC3E,GAAM,CAAE,QAAAC,EAAS,MAAAC,EAAO,UAAAC,EAAW,aAAAC,EAAc,OAAAC,EAAQ,SAAAC,EAAU,kBAAAC,CAAkB,EAAIP,EAKzF,OADIC,IAAY,QAAaC,IAAU,QACnC,OAAOC,GAAc,UAAY,CAACA,GAAa,OAAOC,GAAiB,UAAY,CAACA,EAC/E,KACF,CACL,UAAAD,EACA,aAAAC,EACA,GAAI,OAAOC,GAAW,SAAW,CAAE,OAAAA,CAAO,EAAI,CAAC,EAC/C,GAAI,OAAOC,GAAa,SAAW,CAAE,SAAAA,CAAS,EAAI,CAAC,EACnD,GAAI,OAAOC,GAAsB,SAAW,CAAE,kBAAAA,CAAkB,EAAI,CAAC,CACvE,CACF,CAEA,IAAMC,GAAc,0BACdC,GAAiB,GAAK,IAYrB,SAASC,GAA4BC,EAAyD,CACnG,GAAI,CACF,IAAMC,EAAM,eAAe,QAAQC,EAAW,EAC9C,GAAI,CAACD,EAAK,OAAO,KACjB,IAAME,EAAS,KAAK,MAAMF,CAAG,EAG7B,OAFIE,EAAO,YAAcH,IACzB,eAAe,WAAWE,EAAW,EACjC,CAACC,EAAO,mBAAqB,CAACA,EAAO,IAAM,KAAK,IAAI,EAAIA,EAAO,GAAKC,IAAuB,KACxF,CAAE,kBAAmBD,EAAO,iBAAkB,CACvD,MAAQ,CACN,OAAO,IACT,CACF,CC1CO,IAAME,GAAgB,2DAEhBC,GAAqB,uBASlC,IAAMC,GAAmD,CAAE,GAAI,IAAK,EAE7D,SAASC,GAAcC,EAAoC,CA9BlE,IAAAC,EA+BE,IAAMC,GAAUD,EAAAD,GAAA,YAAAA,EAAQ,MAAM,QAAQ,KAAtB,YAAAC,EAA0B,cAC1C,OAAKC,EACEJ,GAAyBI,CAAO,GAAKA,EADvB,IAEvB,CAEA,IAAMC,GAA4B,IAC9BC,EAAsD,KAMnD,SAASC,IAA4C,CAC1D,IAAMC,EAAI,OACV,OAAIA,EAAE,aAAqB,QAAQ,QAAQA,EAAE,YAAY,EACrDF,IAEJA,EAAkB,IAAI,QAA4B,CAACG,EAASC,IAAW,CACrE,IAAMC,EAAS,SAAS,cAAc,QAAQ,EACxCC,EAAQC,GAAoB,CAChC,aAAaC,CAAK,EAClBH,EAAO,OAAO,EACdL,EAAkB,KAClBI,EAAO,IAAI,MAAMG,CAAO,CAAC,CAC3B,EACMC,EAAQ,WAAW,IAAMF,EAAK,mDAAmD,EAAGP,EAAyB,EACnHM,EAAO,iBAAiB,OAAQ,IAAM,CACpC,GAAI,CAACH,EAAE,aAAc,OAAOI,EAAK,yDAAyD,EAC1F,aAAaE,CAAK,EAClBL,EAAQD,EAAE,YAAY,CACxB,CAAC,EACDG,EAAO,iBAAiB,QAAS,IAAMC,EAAK,4CAA4C,CAAC,EACzFD,EAAO,IAAMI,GACb,SAAS,KAAK,YAAYJ,CAAM,CAClC,CAAC,EACML,EACT,CAQA,IAAMU,GAAoB,oCACpBC,GAAuB,GAAK,GAAK,IAEhC,SAASC,GAAiBC,EAAyB,CACxD,GAAI,CACF,eAAe,QAAQH,GAAmB,KAAK,UAAU,CAAE,UAAAG,EAAW,GAAI,KAAK,IAAI,CAAE,CAAC,CAAC,CACzF,MAAQ,CAER,CACF,CAEA,SAASC,IAA6C,CACpD,GAAI,CACF,IAAMC,EAAM,eAAe,QAAQL,EAAiB,EACpD,GAAI,CAACK,EAAK,OACV,eAAe,WAAWL,EAAiB,EAC3C,GAAM,CAAE,UAAAG,EAAW,GAAAG,CAAG,EAAI,KAAK,MAAMD,CAAG,EACxC,MAAI,CAACF,GAAa,CAACG,GAAM,KAAK,IAAI,EAAIA,EAAKL,GAAsB,OAC1DE,CACT,MAAQ,CACN,MACF,CACF,CAOO,SAASI,IAAkC,CAChD,GAAI,OAAO,OAAW,IAAa,OACnC,IAAMJ,EAAYC,GAAuB,EACzC,GAAKD,EACL,GAAI,CACF,IAAMK,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EACxC,GAAIA,EAAI,aAAa,IAAI,WAAW,EAAG,OACvCA,EAAI,aAAa,IAAI,YAAaL,CAAS,EAC3CK,EAAI,aAAa,IAAI,gBAAiB,eAAe,EACrDA,EAAI,aAAa,IAAI,sBAAuB,WAAW,EACvD,OAAO,QAAQ,aAAa,OAAO,QAAQ,MAAO,GAAIA,EAAI,SAAS,CAAC,CACtE,MAAQ,CAER,CACF,CC9DA,SAASC,IAA2E,CAEhF,OAAO,QAAQ,OACb,IAAI,MACF,+KAEF,CACF,CAGJ,CAMA,IAAMC,GAA0B,IAAI,IAAI,CAAC,SAAU,WAAY,WAAY,OAAO,CAAC,EAO/EC,EAAgE,KAC9DC,GAAiB,IAAM,CAAC,CAACD,IAAc,CAACA,EAAU,UAAYA,EAAU,QAAQ,aAGhFE,GAAkB,OAAO,iBAAiB,EAE1CC,GAAkB,OAAO,iBAAiB,EAiB1CC,GAAuB,IAAI,IAAI,CAAC,YAAa,aAAc,SAAU,SAAU,iBAAkB,MAAM,CAAC,EAG9G,SAASC,GAA+BC,EAAoD,CAzG5F,IAAAC,EA0GE,IAAMC,EAASF,EAAM,OAAS,cACxBG,EAASD,EAAS,OAASF,EAAM,KACjCI,EAAYJ,EAAM,UAAY,CAAC,EAC/BK,EAAaD,EAAS,WACtBE,EAAiBF,EAAS,eAChC,MAAO,CACL,QAAS,GACT,OAAAD,EACA,SAAUD,EAAS,OAAYF,EAAM,KACrC,KAAME,EAAS,OAASF,EAAM,KAC9B,MAAOA,EAAM,MACb,QAASA,EAAM,QACf,QAASF,GAAqB,IAAIK,CAAM,EACxC,cAAeD,EAAS,OAAYF,EAAM,GAC1C,aAAaC,EAAAI,GAAA,YAAAA,EAAa,KAAb,YAAAJ,EAAiB,YAC9B,eAAgB,OAAOK,GAAmB,SAAWA,EAAiB,OACtE,SAAUN,EAAM,UAAY,MAC9B,CACF,CAUA,SAASO,IAAkC,CACzC,GAAI,OAAO,OAAW,IAAa,OAAO,QAAQ,OAAO,IAAI,MAAM,8BAA8B,CAAC,EAClG,IAAMC,EAAW,IAA6B,OAA4C,OACpFC,EAASD,EAAS,EACxB,OAAIC,EAAe,QAAQ,QAAQA,CAAM,EAElC,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAM,4BACbA,EAAO,MAAQ,GACfA,EAAO,OAAS,IAAM,CACpB,IAAMC,EAASL,EAAS,EACpBK,EAAQH,EAAQG,CAAM,EACrBF,EAAO,IAAI,MAAM,wCAAwC,CAAC,CACjE,EACAC,EAAO,QAAU,IAAMD,EAAO,IAAI,MAAM,0BAA0B,CAAC,EACnE,SAAS,KAAK,YAAYC,CAAM,CAClC,CAAC,CACH,CAwBO,IAAME,EAAN,KAAoB,CAczB,YACmBC,EACAC,EACAC,EAEAC,EAEAC,EAOAC,EACjB,CAdiB,UAAAL,EACA,aAAAC,EACA,iBAAAC,EAEA,cAAAC,EAEA,YAAAC,EAOA,cAAAC,EAtBnB,KAAQ,iBAA8C,KAMtD,KAAiB,kBAAoB,IAAI,GAiBtC,CAgBH,MAAM,gBACJC,EACAC,EAC6B,CAC7B,GAAIA,GAAA,MAAAA,EAAM,mBACR,YAAK,iBAAmBA,EAAK,mBACtBA,EAAK,mBAGd,IAAMC,EAAW,KAAK,uBAAuB,EAC7C,GAAIA,EACF,YAAK,iBAAmBA,EACjBA,EAQT,GAAI,CACF,IAAMC,EAAM,MAAM,KAAK,KAAK,IAC1B,6BAA6BH,CAAiB,gBAChD,EACMI,EAA6B,CAAE,IAAID,GAAA,YAAAA,EAAK,SAAU,CAAC,CAAG,EAC5D,YAAK,iBAAmBC,EACjBA,CACT,OAASC,EAAK,CAGZ,GAAI,EAAEA,aAAeC,GAAsB,MAAMD,CACnD,CAEA,IAAMD,EAAS,MAAM,KAAK,8BAA8BJ,CAAiB,EACzE,YAAK,iBAAmBI,EACjBA,CACT,CASA,MAAc,8BAA8BJ,EAAwD,CAClG,IAAMG,EAAM,MAAM,KAAK,KAAK,IAE1B,0BAA2B,CAAE,OAAQ,CAAE,kBAAAH,CAAkB,CAAE,CAAC,EAExDO,EAAiC,MAAM,QAAQJ,CAAG,EACpDA,EAAI,IAAIzB,EAA8B,GACrCyB,GAAA,YAAAA,EAAK,UAAW,CAAC,EAEhBC,EAA6B,CAAC,EACpC,QAAWI,KAAKD,EAAS,CACvB,IAAME,EAAMD,EAAE,UAAYA,EAAE,WAAaA,EAAE,OAAS,GAAGA,EAAE,MAAM,IAAIA,EAAE,QAAQ,GAAKA,EAAE,OACpFJ,EAAOK,CAAG,EAAID,CAChB,CACA,OAAOJ,CACT,CAMA,MAAM,kBACJJ,EACAC,EACyB,CAlS7B,IAAArB,EAAA8B,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAmSI,IAAMC,EAAQ,MAAM,KAAK,gBAAgBnB,EAAmBC,CAAI,EAC1DmB,EAAyB,CAAC,EAEhC,OAAW,CAACX,EAAKL,CAAM,IAAK,OAAO,QAAQe,CAAK,EAAG,CACjD,GAAI,CAACf,EAAO,QAAS,SAIrB,GAAIK,EAAI,WAAW,mBAAmB,GAAKL,EAAO,QAAS,CACzD,IAAMiB,EAAO,CACX,UAAW,GACX,YAAajB,EAAO,YACpB,eAAgBA,EAAO,eACvB,SAAUA,EAAO,QACnB,EACA,IAAIxB,EAAAwB,EAAO,QAAQ,YAAf,MAAAxB,EAA0B,QAAS,CACrC,IAAM0C,EACJ,OAAO,OAAW,KAClB,oBAAqB,UACpBX,GAAAD,EAAA,OACE,kBADF,YAAAA,EACmB,kBADnB,YAAAC,EAAA,KAAAD,IAEHU,EAAO,SAAW,CAAE,GAAGC,EAAM,KAAM,YAAa,UAAW,CAAC,CAACC,CAAY,CAC3E,EACIV,EAAAR,EAAO,QAAQ,aAAf,MAAAQ,EAA2B,UAEzB,OAAO,OAAW,KAAe,EAAE,mBAAoB,WACzDC,EAAA,KAAK,WAAL,MAAAA,EAAA,UAAgB,YAAa,CAAE,OAAQ,wBAAyB,IAElEO,EAAO,UAAY,CAAE,GAAGC,EAAM,KAAM,YAAa,IAE/CP,EAAAV,EAAO,QAAQ,OAAf,MAAAU,EAAqB,UACvBM,EAAO,KAAO,CAAE,GAAGC,EAAM,KAAM,MAAO,IAEpCN,EAAAX,EAAO,QAAQ,iBAAf,MAAAW,EAA+B,UACjCK,EAAO,OAAS,CAAE,GAAGC,EAAM,KAAM,gBAAiB,GAEpD,QACF,CAEA,GAAI,CAACjB,EAAO,QAAS,SAErB,IAAMtB,EAASsB,EAAO,OAChBiB,EAAO,CACX,KAAMvC,EACN,UAAW,GACX,YAAasB,EAAO,YACpB,eAAgBA,EAAO,eACvB,SAAUA,EAAO,QACnB,EAEA,GAAItB,IAAW,aAAesB,EAAO,OAAS,YAAa,CACzD,IAAMkB,EACJ,OAAO,OAAW,KAClB,oBAAqB,UACpBL,GAAAD,EAAA,OACE,kBADF,YAAAA,EACmB,kBADnB,YAAAC,EAAA,KAAAD,IAEHI,EAAO,SAAW,CAAE,GAAGC,EAAM,UAAW,CAAC,CAACC,CAAY,CACxD,MAAWxC,IAAW,cAAgBsB,EAAO,OAAS,cAChD,OAAO,OAAW,KAAe,EAAE,mBAAoB,WACzDc,EAAA,KAAK,WAAL,MAAAA,EAAA,UAAgB,YAAa,CAAE,OAAQ,wBAAyB,IAElEE,EAAO,UAAYC,GACVvC,IAAW,SACpBsC,EAAO,OAASC,EACPvC,IAAW,UAAYA,IAAW,iBAC3CsC,EAAO,OAASC,EACPvC,IAAW,SACpBsC,EAAO,KAAOC,EAElB,CAEA,OAAOD,CACT,CAKA,MAAM,gBAAuC,CAC3C,IAAMjB,EAAM,MAAM,KAAK,KAAK,IAC1B,0BACA,CAAE,OAAQ,CAAE,QAAS,KAAK,OAAQ,CAAE,CACtC,EACA,OAAOA,EAAI,QAAWA,CACxB,CAKA,MAAM,kBACJH,EACAC,EACmB,CACnB,IAAMkB,EAAQ,MAAM,KAAK,gBAAgBnB,EAAmBC,CAAI,EAChE,OAAO,OAAO,QAAQkB,CAAK,EACxB,OAAO,CAAC,CAAC,CAAEI,CAAC,IAAMA,EAAE,OAAO,EAC3B,IAAI,CAAC,CAACd,CAAG,IAAMA,CAAG,CACvB,CAoBA,MAAM,aAAae,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,gBASzD,IAAMI,EAAW,MAAMF,EAAU,gBAAgBC,CAAS,EAM1D,MAAO,CAAE,YALmBF,EAAO,kBACjCG,EACAF,EAAU,YAAY,EAAE,gBAAgB,CAC1C,EAEsB,SAAAE,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,yBAAyB,MAAM,KAAK,KAAK,KAAgB,iCAAkC,CACrG,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,EAAGA,CAAI,EAGH,KAAK,yBAAyB,MAAM,KAAK,KAAK,KAAgB,iCAAkC,CACrG,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,SACf,UAAWA,EAAK,SAClB,CAAC,EAAGA,CAAI,CACV,CAMA,MAAM,UAAUA,EAA4C,CAC1D,OAAO,KAAK,yBAAyB,MAAM,KAAK,KAAK,KAAgB,iCAAkC,CACrG,kBAAmBA,EAAK,kBACxB,oBAAqBA,EAAK,qBAAuB,GACjD,QAAS,KAAK,QACd,cAAeA,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAeA,EAAK,cACpB,UAAWA,EAAK,UAChB,iBAAkBA,EAAK,iBACvB,UAAWA,EAAK,SAClB,CAAC,EAAGA,CAAI,CACV,CAiBA,MAAc,kBACZD,EACA6B,EAQe,CACf,GAAM,CAAE,gBAAAC,EAAiB,eAAAC,CAAe,EAAIF,EAC5C,GAAI,CAACC,GAAmB,CAACC,EAAgB,OAEzC,GAAI,CAAC,KAAK,SACR,MAAM,IAAI,MACR,8KAEF,EAGF,IAAMC,EAAmC,CAAC,EACtCH,EAAQ,QAAOG,EAAS,MAAQH,EAAQ,OACxCA,EAAQ,QAAOG,EAAS,MAAQH,EAAQ,OACxCA,EAAQ,YAAWG,EAAS,UAAYH,EAAQ,WAChDA,EAAQ,WAAUG,EAAS,SAAWH,EAAQ,UAElD,MAAM,KAAK,SAAS,yBAAyB7B,EAAmB,CAC9D,SAAAgC,EACA,gBAAAF,EACA,eAAAC,CACF,CAAC,CACH,CA6BA,MAAM,gBAAgB9B,EAgBC,CAlnBzB,IAAArB,EAAA8B,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAmnBI,MAAM,KAAK,kBAAkBhB,EAAK,kBAAmB,CACnD,gBAAiBgC,GAAyBhC,EAAK,eAAe,EAC9D,eAAgBgC,GAAyBhC,EAAK,cAAc,EAC5D,QAAOrB,EAAAqB,EAAK,kBAAL,YAAArB,EAAsB,iBAAgB8B,EAAAT,EAAK,iBAAL,YAAAS,EAAqB,cAClE,QAAOC,EAAAV,EAAK,kBAAL,YAAAU,EAAsB,gBAAeC,EAAAX,EAAK,iBAAL,YAAAW,EAAqB,aACjE,YAAWC,EAAAZ,EAAK,kBAAL,YAAAY,EAAsB,cAAaC,EAAAb,EAAK,iBAAL,YAAAa,EAAqB,WACnE,WAAUC,EAAAd,EAAK,kBAAL,YAAAc,EAAsB,eAAcC,EAAAf,EAAK,iBAAL,YAAAe,EAAqB,WACrE,CAAC,EAED,IAAMkB,EACJjC,EAAK,0BACJgB,EAAA,MAAM,KAAK,4BAA4BhB,EAAK,iBAAiB,IAA7D,YAAAgB,EAAiE,wBAE9DQ,EAAS,MAAM,KAAK,WAAW,EAC/BC,EAAY,IAAID,EAAO,UAAU,CAAE,YAAa,KAAK,WAAY,CAAC,EACxE,MAAMC,EAAU,WAAW,EAK3B,IAAME,EAAW,MAAMF,EAAU,iBAAiBzB,EAAK,cAAeiC,CAAsB,EACtFC,EAAc,KAClB,KAAK,UAAUV,EAAO,+BAA+BG,EAAU,WAAW,CAAC,CAC7E,EAEA,OAAO,KAAK,IAAI,CACd,kBAAmB3B,EAAK,kBACxB,YAAAkC,EACA,cAAelC,EAAK,cACpB,YAAaA,EAAK,YAClB,cAAe,YACf,UAAW,EACb,CAAC,CACH,CAkBA,MAAM,4BACJD,EAC0E,CAC1E,GAAI,OAAO,OAAW,IAAa,OAAO,KAE1C,IAAIoC,EAAO,OAAO,SAAS,SAAS,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,EAC1DA,EAAK,WAAW,MAAM,IAAGA,EAAOA,EAAK,MAAM,CAAC,GAEhD,IAAMC,EAAclB,GAAqC,CA9qB7D,IAAAvC,EA+qBM,QAAWD,KAAS,OAAO,OAAOwC,GAAS,CAAC,CAAC,EAAG,CAC9C,IAAMmB,GAAM1D,EAAAD,GAAA,YAAAA,EAAO,WAAP,YAAAC,EAAiB,aAG7B,GAAI,CAAC0D,GAAO,OAAOA,GAAQ,SAAU,SACrC,IAAMC,EAAMD,EAAIF,CAAI,EACpB,GAAIG,GAAA,MAAAA,EAAK,uBACP,MAAO,CAAE,uBAAwBA,EAAI,uBAAwB,YAAaA,EAAI,WAAY,CAE9F,CACA,OAAO,IACT,EAEMC,EAAQH,EAAW,KAAK,uBAAuB,CAAC,GAAKA,EAAW,KAAK,gBAAgB,EAC3F,GAAIG,EAAO,OAAOA,EAIlB,GAAI,KAAK,kBAAoB,KAAK,uBAAuB,GAAK,CAACxC,EAAmB,OAAO,KACzF,GAAI,CACF,OAAOqC,EAAW,MAAM,KAAK,gBAAgBrC,CAAiB,CAAC,CACjE,MAAQ,CACN,OAAO,IACT,CACF,CAWA,MAAM,iBAAiBC,EAQA,CA1tBzB,IAAArB,EAAA8B,EAAAC,EAAAC,EA2tBI,MAAM,KAAK,kBAAkBX,EAAK,kBAAmB,CACnD,gBAAiBwC,GAA0BxC,EAAK,eAAe,EAC/D,eAAgBwC,GAA0BxC,EAAK,cAAc,EAC7D,MAAOA,EAAK,SAASrB,EAAAqB,EAAK,kBAAL,YAAArB,EAAsB,iBAAgB8B,EAAAT,EAAK,iBAAL,YAAAS,EAAqB,cAChF,QAAOC,EAAAV,EAAK,kBAAL,YAAAU,EAAsB,gBAAeC,EAAAX,EAAK,iBAAL,YAAAW,EAAqB,YACnE,CAAC,EAED,IAAMa,EAAS,MAAM,KAAK,WAAW,EAC/BC,EAAY,IAAID,EAAO,UAAU,CAAE,YAAa,KAAK,WAAY,CAAC,EACxE,MAAMC,EAAU,WAAW,EAG3B,IAAME,EAAW,MAAMF,EAAU,kBAAkBzB,EAAK,cAAc,EAChEkC,EAAc,KAClB,KAAK,UAAUV,EAAO,+BAA+BG,EAAU,YAAY,CAAC,CAC9E,EAEA,OAAO,KAAK,IAAI,CACd,kBAAmB3B,EAAK,kBACxB,YAAAkC,EACA,cAAelC,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,CAWA,MAAM,wBAAwBD,EAAgE,CAC5F,OAAO,KAAK,KAAK,IACf,6BAA6B,mBAAmBA,CAAiB,CAAC,yBACpE,CACF,CAOA,MAAM,2BAA2BC,EAIO,CACtC,OAAO,KAAK,KAAK,KACf,6BAA6B,mBAAmBA,EAAK,iBAAiB,CAAC,0BACvE,CAAE,QAASA,EAAK,QAAS,MAAOA,EAAK,KAAM,CAC7C,CACF,CAGA,MAAM,uBAAuBA,EAGU,CACrC,OAAO,KAAK,KAAK,IACf,6BAA6B,mBAAmBA,EAAK,iBAAiB,CAAC,yBACvE,CAAE,OAAQ,CAAE,uBAAwBA,EAAK,sBAAuB,CAAE,CACpE,CACF,CAgBA,4BAA4BA,EAA2D,CACrF,OAAO,IAAIyC,EAAsB,KAAMzC,CAAI,CAC7C,CAOA,MAAM,sBAAsBD,EAAwD,CAClF,IAAM2C,EAAO,MAAM,KAAK,KAAK,KAC3B,6BAA6B3C,CAAiB,gCAC9C,CAAC,CACH,EACA,MAAO,CAAE,SAAU,CAAC,EAAC2C,GAAA,MAAAA,EAAM,UAAU,UAAW,CAAC,EAACA,GAAA,MAAAA,EAAM,UAAU,CACpE,CAsBA,MAAM,kBAAkB1C,EAA2D,CACjF,GAAI,OAAO,OAAW,IAAa,MAAM,IAAI,MAAM,+BAA+B,EAClF,GAAM,CAAE,kBAAAD,EAAmB,OAAA4C,CAAO,EAAI3C,EAChC4C,EAAU,IAAM,OAAO,OAAO,IAAI,MAAM,6BAA6B,EAAG,CAAE,KAAM,YAAa,CAAC,EACpG,GAAID,GAAA,MAAAA,EAAQ,QAAS,MAAMC,EAAQ,EAEnC,IAAMT,EAAO,OAAOnC,EAAK,WAAc,SACnC,SAAS,cAA2BA,EAAK,SAAS,EAClDA,EAAK,UACT,GAAI,CAACmC,GAAQnC,EAAK,OAAS,WACzB,MAAM,IAAI,MAAM,sCAAsC,OAAOA,EAAK,SAAS,CAAC,EAAE,EAIhF,GAAI3B,GAAe,GAAK,SAAS,eAAewE,EAAkB,EAChE,MAAM,IAAI,MAAM,4DAA4D,EAE9E,IAAMC,EAAI,OACJC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,GAAKF,GACb,IAAMG,EAAO,CAAE,QAAAD,EAAS,SAAU,EAAM,EACxC3E,EAAY4E,EACZ,IAAMC,EAAc,IAAM,CAAM7E,IAAc4E,IAAM5E,EAAY,KAAM,EAElE8E,EAAU,GACVC,EAAoD,KAClDC,EAAYV,GAAkB,CAClC,IAAMtD,EAAU+D,EAChBA,EAAkB,KAClB/D,GAAA,MAAAA,EAAUsD,EACZ,EACMW,EAAU,IAAM,CACfH,IACLA,EAAU,GACNJ,EAAE,uBAAyBM,GAAU,OAAON,EAAE,qBAClDC,EAAQ,OAAO,EACfE,EAAY,EAEZG,EAAS7E,EAAe,EAC1B,EACAoE,GAAA,MAAAA,EAAQ,iBAAiB,QAASU,EAAS,CAAE,KAAM,EAAK,GAExD,IAAIlD,EACAmD,EACJ,GAAI,CAKF,GAJAnD,EAASH,EAAK,OAAS,WACnB,CAAE,SAAU,GAAO,UAAW,EAAM,EACpC,MAAM,KAAK,sBAAsBD,CAAiB,EAClD4C,GAAA,MAAAA,EAAQ,SACRxC,EAAO,WACTmD,EAAQ,MAAMC,GAAa,EACvBZ,GAAA,MAAAA,EAAQ,SAAS,MAAMC,EAAQ,CAEvC,OAASY,EAAO,CACd,MAAAH,EAAQ,EACFG,CACR,CAEA,IAAIC,EAAa,GAEjB,GAAI,CAACH,EAEH,OAAAL,EAAY,EACL,CACL,KAAM,WACN,IAAK,SAAY,CACf,GAAI,CAACC,EAAS,MAAO,CAAE,OAAQ,SAAU,MAAO,oCAAqC,EACrF,GAAIO,EAAY,MAAO,CAAE,OAAQ,SAAU,MAAO,6BAA8B,EAChFA,EAAa,GACb,GAAI,CACF,IAAMf,EAAO,MAAM,KAAK,KAAK,KAC3B,6BAA6B3C,CAAiB,qBAC9C,CAAE,UAAWC,EAAK,WAAa,OAAO,SAAS,IAAK,CACtD,EACA,MAAI,EAAC0C,GAAA,MAAAA,EAAM,MAAO,CAACA,EAAK,UACf,CAAE,OAAQ,SAAU,MAAO,+CAAgD,EAE7E,CAAE,OAAQ,oBAAqB,YAAaA,EAAK,IAAK,OAAQ,MAAO,UAAWA,EAAK,SAAU,CACxG,OAASc,EAAO,CACd,MAAO,CAAE,OAAQ,SAAU,MAAOA,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,CAAE,CAC3F,QAAE,CACAC,EAAa,EACf,CACF,EACA,QAAAJ,CACF,EAGF,IAAMK,EAAMJ,EACZnB,EAAM,YAAYY,CAAO,EACzBC,EAAK,SAAW,GAChBF,EAAE,qBAAuBM,EAEzB,IAAMO,EAAU,OAAO,SAAS,KAGhC,OAAAD,EAAI,KAAKvD,EAAO,UAAW,GAAIyD,GAAc5D,EAAK,MAAM,EAAG,CAAE,aAAc,EAAM,CAAC,EA0D3E,CAAE,KAAM,WAAY,IAxDf,SAA2C,CACrD,GAAI,CAACkD,EAAS,MAAO,CAAE,OAAQ,SAAU,MAAO,yCAA0C,EAC1F,GAAIO,EAAY,MAAO,CAAE,OAAQ,SAAU,MAAO,6BAA8B,EAChFA,EAAa,GACb,GAAI,CAEF,IAAMI,EAAU,MAAM,KAAK,KAAK,KAC9B,6BAA6B9D,CAAiB,iCAC9C,CAAE,QAAA4D,CAAQ,CACZ,EACA,GAAI,EAACE,GAAA,MAAAA,EAAS,YAAa,CAACA,EAAQ,OAClC,MAAO,CAAE,OAAQ,SAAU,MAAO,6BAA8B,EAElE,IAAMC,EAAYD,EAAQ,UAKpBE,EAAS,MAAM,IAAI,QAAkB3E,IAAY,CACrD,IAAM4E,GAAQ,WAAW,IAAM,CAC7Bb,EAAkB,KAClB/D,GAAQd,EAAe,CACzB,EAAG,IAAyB,EAC5B6E,EAAmBT,IAAS,CAAE,aAAasB,EAAK,EAAG5E,GAAQsD,EAAI,CAAG,EAClEgB,EAAI,SAASG,EAAQ,MAAO,CAC9B,CAAC,EAGD,GAAIE,IAAWzF,IAAmByF,IAAWxF,GAC3C,OAAO,KAAK,cAAcuF,CAAS,EAErC,GAAIC,GAAU,OAAOA,GAAW,UAAY,QAASA,EACnD,MAAO,CAAE,OAAQ,SAAU,MAAO,OAAQA,EAA6B,KAAO,iCAAiC,CAAE,EAInH,IAAM5C,EAAS,MAAM,KAAK,KAAK,KAC7B,6BAA6BpB,CAAiB,gCAC9C,CAAE,UAAA+D,EAAW,SAAU,OAAOC,CAAM,CAAE,CACxC,EACA,OAAI5C,GAAA,YAAAA,EAAQ,UAAW,mBAAqBA,EAAO,QAEjD8C,GAAiBH,CAAS,EACnB,CAAE,OAAQ,oBAAqB,YAAa3C,EAAO,OAAQ,OAAQ,MAAO,UAAA2C,CAAU,IAEzF3C,GAAA,YAAAA,EAAQ,UAAW,cAAeA,GAAA,YAAAA,EAAQ,UAAW,UAChD,KAAK,cAAc2C,CAAS,EAE9B,CAAE,OAAQ,SAAU,OAAO3C,GAAA,YAAAA,EAAQ,UAAW,kBAAmB,CAC1E,OAASqC,EAAO,CACd,MAAO,CAAE,OAAQ,SAAU,MAAOA,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,CAAE,CAC3F,QAAE,CACAC,EAAa,EACf,CACF,EAEgC,QAAAJ,CAAQ,CAC1C,CAoCA,MAAM,eAAerD,EAA4D,CAC3E,CAACA,EAAK,WAAa,OAAO,OAAW,MACvCA,EAAO,CAAE,GAAGA,EAAM,UAAW,OAAO,SAAS,IAAK,GAEpD,IAAMkE,EAAY,MAAM,KAAK,IAAIlE,CAAI,EACrC,OAAO,KAAK,SAASkE,EAAW,CAAE,UAAWlE,EAAK,SAAU,CAAC,CAC/D,CAeA,MAAM,SACJmE,EACAnE,EAC+B,CAnlCnC,IAAArB,EAAA8B,EAAAC,EAolCI,IAAM0D,EAAUD,EAAM,QAChBE,GACJrE,GAAA,YAAAA,EAAM,aAAc,OAAO,OAAW,IAAc,OAAO,SAAS,KAAO,QAI7E,GAAI,CAACoE,EAAS,CACZ,IAAME,EAAUC,GAAmBJ,CAAK,EACxC,GAAIG,EAAS,OAAO,KAAK,sBAAsBA,EAASD,CAAS,CACnE,CAEA,OAAID,EAAQ,SAAW,aACrB,KAAK,UAASzF,EAAAwF,EAAM,QAAN,YAAAxF,EAAa,GAAIyF,CAAO,EAC/B,CAAE,OAAQ,YAAa,QAAAA,EAAS,MAAOD,EAAM,KAAM,GAGxDC,EAAQ,SAAW,UAAYA,EAAQ,SAAW,WAI7C,CAAE,OAAQ,SAAU,QAHf3D,EAAA2D,EAAQ,oBAAR,YAAA3D,EAA2B,YAClCC,EAAA0D,EAAQ,oBAAR,YAAA1D,EAA2B,YAC3B,WAAW0D,EAAQ,MAAM,GACS,QAAAA,CAAQ,EAG7CA,EAAQ,eAAiBA,EAAQ,gBAAkB,QAAUA,EAAQ,kBAChE,KAAK,oBAAoBA,EAAS,CAAE,UAAAC,CAAU,CAA0B,EAI1E,KAAK,cAAcD,EAAQ,EAAE,CACtC,CAQA,MAAM,oBAAoBN,EAAkD,CAE1E,IAAMU,EAASC,GAA4BX,CAAS,EACpD,GAAIU,EAAQ,CACV,IAAME,EAAM,OAAO,OAAW,IAAc,OAAO,SAAS,KAAO,OACnE,OAAO,KAAK,cAAc,CAACC,EAAMxC,IAASwC,EAAK,oBAAoBxC,EAAM2B,EAAWU,EAAO,kBAAmBE,CAAG,CAAC,CACpH,CACA,OAAO,KAAK,cAAcZ,CAAS,CACrC,CAgCA,MAAM,mBAAmB9D,EAYgB,CACvC,GAAI,OAAO,OAAW,KAAe,EAACA,GAAA,MAAAA,EAAM,KAAK,OAAO,KACnDA,GAAA,MAAAA,EAAM,KAAK4E,GAA0B,EAE1C,IAAMC,GAAO7E,GAAA,YAAAA,EAAM,MAAO,OAAO,SAAS,KACtC0E,EACJ,GAAI,CACFA,EAAM,IAAI,IAAIG,CAAI,CACpB,MAAQ,CACN,OAAO,IACT,CAEA,IAAMC,EAASJ,EAAI,aAAa,IAAI,eAAe,EAC7CK,EAAeL,EAAI,aAAa,IAAI,qBAAqB,EACzDZ,EAAYY,EAAI,aAAa,IAAI,WAAW,EAClD,GAAII,IAAW,iBAAmBC,IAAiB,aAAe,CAACjB,EACjE,OAAO,KAGT,IAAM3C,EAAS,MAAM,KAAK,oBAAoB2C,CAAS,EAGvD,IAAI9D,GAAA,YAAAA,EAAM,YAAa,IAAS,OAAO,OAAW,KAAe,EAACA,GAAA,MAAAA,EAAM,KAAK,CAC3E,IAAMgF,EAAc,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAC9D,CACE,gBACA,sBACA,YACA,iBACA,+BACA,cACA,kBACA,WACF,EAAE,QAASC,GAAMD,EAAY,OAAOC,CAAC,CAAC,EACtC,IAAMC,EAASF,EAAY,SAAS,EACpC,GAAI,CACF,OAAO,QAAQ,aACb,CAAC,EACD,SAAS,MACT,OAAO,SAAS,UAAYE,EAAS,IAAMA,EAAS,GACtD,CACF,MAAQ,CAER,CACF,CAEA,OAAO/D,CACT,CAOA,MAAM,iBAAiB2C,EAA2C,CAChE,OAAO,KAAK,KAAK,IAAmB,oBAAoBA,CAAS,EAAE,CACrE,CAMA,MAAM,kBACJA,EACA9D,EACwB,CACxB,IAAMmF,GAAWnF,GAAA,YAAAA,EAAM,aAAc,KAC/BoF,GAAUpF,GAAA,YAAAA,EAAM,YAAa,IAC7BqF,EAAQ,KAAK,IAAI,EAEvB,KAAO,KAAK,IAAI,EAAIA,EAAQD,GAAS,CACnC,IAAME,EAAS,MAAM,KAAK,iBAAiBxB,CAAS,EACpD,GAAIwB,EAAO,SAAW,aAAenH,GAAwB,IAAImH,EAAO,MAAM,EAC5E,OAAOA,EAET,MAAM,IAAI,QAASC,GAAM,WAAWA,EAAGJ,CAAQ,CAAC,CAClD,CAEA,MAAM,IAAI,MAAM,WAAWrB,CAAS,yCAAyCsB,CAAO,KAAK,CAC3F,CAGA,MAAM,iBAAiBtB,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,oBACZM,EACApE,EAC+B,CAC/B,IAAMwF,EAAapB,EAAQ,kBAM3B,OAJA,MAAM,KAAK,oBAAoBA,EAAQ,EAAE,EAEtBoB,EAAW,KAEV,CAClB,IAAK,eACH,OAAO,KAAK,kBAAkBpB,EAASpE,CAAI,EAE7C,IAAK,iBACL,IAAK,sBACH,OAAO,KAAK,gBAAgBoE,EAASoB,CAAU,EAEjD,IAAK,WACH,OAAO,KAAK,gBAAgBpB,EAASoB,CAAU,EAEjD,IAAK,eACH,OAAO,KAAK,kBAAkBpB,CAAO,EAEvC,IAAK,QACH,MAAO,CACL,OAAQ,SACR,MAAOoB,EAAW,SAAWA,EAAW,WAAa,iBACrD,QAAApB,CACF,EAEF,QAEE,OAAO,KAAK,gBAAgBA,EAASoB,CAAU,CACnD,CACF,CAMQ,gBACNpB,EACAoB,EACsB,CAr0C1B,IAAA7G,EAAA8B,EAs0CI,IAAMgF,GAAW9G,EAAA6G,EAAW,WAAX,YAAA7G,EAAqB,SAChC+F,GAAMe,GAAA,YAAAA,EAAU,cAAeD,EAAW,YAEhD,OAAKd,EAQE,CACL,OAAQ,oBACR,YAAaA,EACb,SAASjE,EAAAgF,GAAA,YAAAA,EAAU,SAAV,YAAAhF,EAAkB,gBAAoC,MAC/D,SAAUgF,GAAA,YAAAA,EAAU,KACpB,UAAWrB,EAAQ,EACrB,EAbS,CACL,OAAQ,SACR,MAAO,4BAA4BoB,EAAW,IAAI,qCAClD,QAAApB,CACF,CAUJ,CAMA,MAAc,kBACZA,EACApE,EAC+B,CAj2CnC,IAAArB,EAAA8B,EAk2CI,IAAMiF,GAAUjF,GAAA9B,EAAAyF,EAAQ,oBAAR,YAAAzF,EAA2B,WAA3B,YAAA8B,EAAqC,eAGrD,GAAI,EAACiF,GAAA,MAAAA,EAAS,mBACZ,OAAO,KAAK,gBAAgBtB,EAASA,EAAQ,iBAAkB,EAIjE,IAAI5C,EACJ,GAAI,CACFA,EAAS,KAAM,QAAO,oBAAoB,CAC5C,MAAQ,CAEN,OAAIkE,EAAQ,gBACH,CACL,OAAQ,oBACR,YAAaA,EAAQ,gBACrB,UAAWtB,EAAQ,EACrB,EAEK,KAAK,gBAAgBA,EAASA,EAAQ,iBAAkB,CACjE,CAGA,GAAI,CACF,IAAMuB,EAAU,IAAInE,EAAO,eAAe,CAAE,SAAU,cAAe,CAAC,EACtE,aAAMmE,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,iBAAiBtB,EAAQ,EAAE,EAC/B,KAAK,cAAcA,EAAQ,EAAE,CACtC,MAAQ,CAEN,OAAIsB,EAAQ,gBACH,CACL,OAAQ,oBACR,YAAaA,EAAQ,gBACrB,UAAWtB,EAAQ,EACrB,EAEK,CACL,OAAQ,SACR,MAAO,kCACP,QAAAA,CACF,CACF,CACF,CAMA,MAAc,kBAAkBA,EAA8D,CA75ChG,IAAAzF,EAAA8B,EA85CI,IAAMmF,GAAQnF,GAAA9B,EAAAyF,EAAQ,oBAAR,YAAAzF,EAA2B,WAA3B,YAAA8B,EAAqC,MAGnD,GAAI,EAACmF,GAAA,MAAAA,EAAO,gBACV,MAAO,CAAE,OAAQ,SAAU,MAAO,qCAAsC,QAAAxB,CAAQ,EAGlF,GAAI,CACF,IAAMyB,EAAS,MAAM5G,GAAa,EAC5B,CAAE,aAAA6G,EAAc,MAAAtC,CAAM,EAAI,MAAMqC,EAAOD,EAAM,cAAc,EAAE,mBAAmB,EACtF,GAAIpC,GAAS,CAACsC,EACZ,MAAM,IAAI,OAAMtC,GAAA,YAAAA,EAAO,UAAW,qCAAqC,EAGzE,aAAM,KAAK,KAAK,KAAK,yBAA0B,CAC7C,QAASoC,EAAM,QACf,UAAWxB,EAAQ,GACnB,qBAAsB0B,EAAa,GACnC,uBAAwBA,CAC1B,CAAC,EACD,MAAM,KAAK,iBAAiB1B,EAAQ,EAAE,EAC/B,KAAK,cAAcA,EAAQ,EAAE,CACtC,OAAS2B,EAAG,CACV,MAAO,CAAE,OAAQ,SAAU,MAAOA,aAAa,MAAQA,EAAE,QAAU,sBAAuB,QAAA3B,CAAQ,CACpG,CACF,CAMA,MAAc,cACZN,EACA9D,EAC+B,CAh8CnC,IAAArB,EAi8CI,IAAMwG,GAAWnF,GAAA,YAAAA,EAAM,aAAc,KAC/BoF,GAAUpF,GAAA,YAAAA,EAAM,YAAa,IAC7BqF,EAAQ,KAAK,IAAI,EACnBW,EAAoB,EAExB,KAAO,KAAK,IAAI,EAAIX,EAAQD,GAAS,CACnC,IAAIE,EACJ,GAAI,CACFA,EAAS,MAAM,KAAK,iBAAiBxB,CAAS,EAC9CkC,EAAoB,CACtB,MAAQ,CAEN,GADAA,IACIA,GAAqB,EACvB,MAAO,CAAE,OAAQ,SAAU,MAAO,mDAAoD,EAExF,MAAM,IAAI,QAAST,GAAM,WAAWA,EAAGJ,CAAQ,CAAC,EAChD,QACF,CAEA,GACEG,EAAO,SAAW,aACjBA,EAAO,SAAW,WAAaA,EAAO,YAAc,aAGrD,OAAIA,EAAO,SAAW,aACpB,KAAK,UAAS3G,EAAA2G,EAAO,QAAP,YAAA3G,EAAc,GAAI2G,CAAyC,EAEpE,CAAE,OAAQ,YAAa,QAASA,EAA2C,MAAOA,EAAO,KAAM,EAIxG,GAAInH,GAAwB,IAAImH,EAAO,MAAM,EAC3C,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,UAAArB,CAAU,CACxC,CAOQ,yBACNC,EACA/D,EACW,CACX,IAAMsE,EAAUP,GAAU,CAACA,EAAO,QAAUQ,GAAmBR,CAAM,EAAI,KACzE,OAAIO,GACF,KAAK,kBAAkB,IAAIA,EAAQ,UAAW,CAC5C,kBAAmBA,EAAQ,mBAAqBtE,EAAK,kBACrD,GAAIA,EAAK,cAAgB,CAAE,cAAeA,EAAK,aAAc,EAAI,CAAC,CACpE,CAAC,EAEI+D,CACT,CAGQ,sBAAsBO,EAAyBD,EAA8D,CACnH,IAAM4B,EAAQ,KAAK,kBAAkB,IAAI3B,EAAQ,SAAS,EAC1D,YAAK,kBAAkB,OAAOA,EAAQ,SAAS,EACxC,KAAK,cAAc,CAACK,EAAMxC,IAC/BwC,EAAK,sBAAsBxC,EAAMmC,EAAS,CACxC,kBAAmB2B,GAAA,YAAAA,EAAO,kBAC1B,cAAeA,GAAA,YAAAA,EAAO,cACtB,UAAA5B,CACF,CAAC,CACH,CACF,CAGA,MAAc,cACZ6B,EAI+B,CAC/B,IAAIvB,EACJ,GAAI,CACFA,EAAO,MAAMzG,GAAoB,CACnC,OAASsF,EAAO,CACd,MAAO,CAAE,OAAQ,SAAU,MAAOA,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,CAAE,CAC3F,CACA,OAAO0C,EAAIvB,EAAM,CACf,KAAM,KAAK,KACX,QAAS,KAAK,QACd,SAAU,KAAK,SACf,WAAY,KAAK,0BAA0B,EAC3C,OAAQ,CAACwB,EAAS/B,IAAY,KAAK,SAAS+B,EAAS/B,CAAO,CAC9D,CAAC,CACH,CAUQ,wBAAoD,CAC1D,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,IAAMgC,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,CAGQ,2BAAqC,CAC3C,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,IAAMD,EAAO,OAA8C,oBAC3D,GAAI,CAACA,EAAK,OAAO,KACjB,GAAI,CACF,OAAO,OAAOA,GAAQ,SAAW,KAAK,MAAMA,CAAG,EAAIA,CACrD,MAAQ,CACN,OAAO,IACT,CACF,CAGQ,SAASD,EAA6B/B,EAAuD,CA9kDvG,IAAAzF,EA+kDI,GAAI,GAACwH,GAAW,CAAC,KAAK,QACtB,GAAI,CACF,IAAMT,GAAU/G,EAAA,KAAK,WAAL,YAAAA,EAAe,oBAC/B,KAAK,OAAO,CACV,QAAAwH,EACA,OAAQ/B,EAAQ,OAChB,SAAUA,EAAQ,SAClB,MAAOkC,GAAWZ,GAAA,YAAAA,EAAS,KAAK,CAClC,CAAC,CACH,MAAQ,CAER,CACF,CAGA,MAAc,YAA2B,CACvC,GAAI,CACF,OAAO,KAAM,QAAO,oBAAoB,CAC1C,OAASa,EAAO,CAEd,IAAM/C,EAAQ,IAAI,MAChB,qFACF,EACA,MAACA,EAAsC,MAAQ+C,EACzC/C,CACR,CACF,CACF,ECnmDA,IAAMgD,EAAS,OAAO,SAAa,IAAc,KAAO,SAAS,cAC3DC,GAAMD,GAAA,MAAAA,EAAQ,IAAM,IAAI,IAAI,kCAAmCA,EAAO,GAAG,EAAE,KAAO,mGACpFE,GAEG,SAASC,GAAkC,CAChD,OAAI,OAAO,uBAA+B,QAAQ,QAAQ,OAAO,sBAAsB,GAClFD,KAASA,GAAU,IAAI,QAAkB,CAACE,EAASC,IAAW,CACjE,IAAMC,EAAU,SAAS,cAAc,QAAQ,EAC/CA,EAAQ,IAAML,GAAKK,EAAQ,MAAQ,GAC/BN,GAAA,MAAAA,EAAQ,QAAOM,EAAQ,MAAQN,EAAO,OAC1CM,EAAQ,iBAAiB,OAAQ,IAAM,OAAO,uBAAyBF,EAAQ,OAAO,sBAAsB,EAAIC,EAAO,IAAI,MAAM,oCAAoC,CAAC,CAAC,EACvKC,EAAQ,iBAAiB,QAAS,IAAM,CAAEA,EAAQ,OAAO,EAAGD,EAAO,IAAI,MAAM,gCAAgC,CAAC,CAAG,CAAC,EAClH,SAAS,KAAK,YAAYC,CAAO,CACnC,CAAC,EAAE,MAAMC,GAAS,CAAE,MAAAL,GAAU,OAAiBK,CAAO,CAAC,GAChDL,GACT,CCrBiB,IAAMM,EAAN,KAAmB,CACxB,eAAeC,EAAK,CAAC,KAAK,KAAKA,CAAI,CACnC,MAAM,CAAC,OAAO,KAAK,WAAL,KAAK,SAAaC,EAAa,EAAE,KAAKC,GAAG,IAAIA,EAAE,aAAa,GAAG,KAAK,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,WAAK,SAAS,OAAgB,CAAC,CAAC,EAAC,CACtI,EACA,QAAUC,IAAU,CAAC,WAAW,aAAa,eAAe,kBAAkB,oBAAoB,sBAAsB,kBAAkB,yBAAyB,0BAA0B,0BAA0B,EAAGJ,EAAa,UAAUI,CAAM,EAAE,YAAYH,EAAK,CAAC,OAAO,KAAK,KAAK,EAAE,KAAKI,GAAUA,EAASD,CAAM,EAAE,GAAGH,CAAI,CAAC,CAAC,ECJhU,IAAMK,EAAN,KAAqB,CAC1B,eAAeC,EAAK,CAAC,KAAK,KAAKA,CAAI,CACnC,MAAM,CAAC,OAAO,KAAK,WAAL,KAAK,SAAaC,EAAa,EAAE,KAAKC,GAAG,IAAIA,EAAE,eAAe,GAAG,KAAK,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,WAAK,SAAS,OAAgB,CAAC,CAAC,EAAC,CACxI,EACA,QAAUC,IAAU,CAAC,aAAa,aAAa,gBAAgB,YAAY,WAAW,mBAAmB,kBAAkB,oBAAoB,qBAAqB,mBAAmB,yBAAyB,6BAA6B,8BAA8B,0BAA0B,kCAAkC,oBAAoB,EAAGJ,EAAe,UAAUI,CAAM,EAAE,YAAYH,EAAK,CAAC,OAAO,KAAK,KAAK,EAAE,KAAKI,GAAUA,EAASD,CAAM,EAAE,GAAGH,CAAI,CAAC,CAAC,ECJtc,IAAMK,EAAN,KAA2B,CAChC,eAAeC,EAAK,CAAC,KAAK,KAAKA,CAAI,CACnC,MAAM,CAAC,OAAO,KAAK,WAAL,KAAK,SAAaC,EAAa,EAAE,KAAKC,GAAG,IAAIA,EAAE,qBAAqB,GAAG,KAAK,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,WAAK,SAAS,OAAgB,CAAC,CAAC,EAAC,CAC9I,EACA,QAAUC,IAAU,CAAC,cAAc,aAAa,YAAY,QAAQ,aAAa,oBAAoB,eAAe,WAAW,cAAc,iBAAiB,aAAa,gBAAgB,gBAAgB,yBAAyB,gBAAgB,cAAc,gBAAgB,oBAAoB,UAAU,aAAa,0BAA0B,eAAe,WAAW,iBAAiB,SAAS,UAAU,yBAAyB,sBAAsB,yBAAyB,WAAW,YAAY,EAAGJ,EAAqB,UAAUI,CAAM,EAAE,YAAYH,EAAK,CAAC,OAAO,KAAK,KAAK,EAAE,KAAKI,GAAUA,EAASD,CAAM,EAAE,GAAGH,CAAI,CAAC,CAAC,ECG/mB,IAAMK,EAAN,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,EClBO,IAAMC,EAAN,KAAmB,CAKxB,YACmBC,EACAC,EACAC,EACAC,EACAC,EACjB,CALiB,UAAAJ,EACA,aAAAC,EACA,cAAAC,EACA,eAAAC,EACA,qBAAAC,CAChB,CAEH,MAAM,SAASC,EAA2D,CA1C5E,IAAAC,EAAAC,EA2CI,IAAMC,EAAU,KAAK,SAAS,kBAAkB,EAChD,GAAI,CAACA,EACH,MAAM,IAAIC,EACR,kGACA,gBACF,EAGF,IAAMN,EAAYE,EAAM,WAAa,KAAK,UAC1C,GAAI,CAACF,EACH,MAAM,IAAIM,EACR,kHACA,oBACF,EAGF,IAAMC,EACJL,EAAM,aAAe,OAAO,WAAe,KAAcC,EAAA,WAAW,WAAX,YAAAA,EAAqB,KAAO,QAEvF,MAAM,KAAK,iBAAiBE,EAASL,EAAWE,CAAK,EAErD,IAAMM,EAAkB,MAAM,KAAK,iBAAiB,CAClD,SAAUN,EAAM,SAChB,OAAQA,EAAM,OACd,UAAAF,EACA,WAAAO,CACF,CAAC,EAED,GAAI,EAAEH,EAAA,KAAK,kBAAL,MAAAA,EAAA,UAAuBI,EAAkB,MAAQ,CAA8C,CAUrG,MAAO,CAAE,IARG,MAAM,KAAK,YAAY,CACjC,gBAAAA,EACA,OAAQN,EAAM,OACd,QAAAG,EACA,MAAAH,EACA,WAAAK,CACF,CAAC,EAEa,gBAAAC,CAAgB,CAChC,CAMA,MAAc,iBACZH,EACAL,EACAE,EACe,CA5FnB,IAAAC,EAAAC,EAAAK,EA6FI,GAAI,KAAK,WAAa,KAAK,eAAiB,KAAK,eAAgB,OAEjE,IAAMC,EAAO,MAAM,KAAK,KAAK,KAC3B,gCACA,CAAE,QAAS,KAAK,QAAS,KAAM,YAAa,MAAO,EAAM,CAC3D,EACA,KAAK,UAAYA,EAAK,MACtB,KAAK,cAAgBA,EAAK,UAE1B,IAAMC,EAAO,MAAM,KAAK,KAAK,KAC3B,8BACA,CACE,QAAS,KAAK,QACd,UAAAX,EACA,WAAY,mBACZ,gBAAeG,EAAAD,EAAM,WAAN,YAAAC,EAAgB,SAAUS,GAAc,EACvD,UAAWC,GAAiB,EAC5B,gBAAeT,EAAAF,EAAM,WAAN,YAAAE,EAAgB,WAAYC,EAAQ,SACnD,aAAaI,EAAAP,EAAM,WAAN,YAAAO,EAAgB,MAC/B,EACA,CAAE,MAAO,KAAK,SAAU,CAC1B,EAEA,KAAK,eAAiBE,EAAK,SAAS,EACtC,CAEA,MAAc,iBAAiBG,EAKX,CAkBlB,OAjBY,MAAM,KAAK,KAAK,KAC1B,4BACA,CACE,WAAY,CACV,WAAY,KAAK,eACjB,UAAW,KAAK,cAChB,QAAS,KAAK,QACd,UAAWA,EAAK,SAClB,EACA,SAAUA,EAAK,SACf,YAAaA,EAAK,OAClB,aAAcA,EAAK,OACnB,WAAYA,EAAK,WACjB,MAAO,EACT,EACA,CAAE,MAAO,KAAK,SAAU,CAC1B,GACW,QAAQ,SACrB,CAEA,MAAc,YAAYA,EAMN,CAvJtB,IAAAX,EAAAC,EAAAK,EAAAM,EAwJI,GAAM,CAAE,gBAAAP,EAAiB,OAAAQ,EAAQ,QAAAX,EAAS,MAAAH,EAAO,WAAAK,CAAW,EAAIO,EAE1DG,EAAYZ,EAAQ,MAAM,IAAKa,IAAO,CAC1C,UAAWA,EAAE,UACb,QAASA,EAAE,QACX,SAAUA,EAAE,QACd,EAAE,EAEIC,EACJjB,EAAM,gBACLG,EAAQ,cAAgB,CAACA,EAAQ,aAAa,EAAI,QAE/Ce,EAAW,CACf,QAAOjB,EAAAD,EAAM,WAAN,YAAAC,EAAgB,UAASC,EAAAC,EAAQ,WAAR,YAAAD,EAAkB,OAClD,WAAUK,EAAAP,EAAM,WAAN,YAAAO,EAAgB,WAAYJ,EAAQ,SAC9C,QAAQU,EAAAb,EAAM,WAAN,YAAAa,EAAgB,MAC1B,EAgCA,OA9BY,MAAM,KAAK,KAAK,KAC1B,0BACA,CACE,UAAWP,EACX,WAAAD,EACA,aAAcS,EACd,cAAe,GACf,MAAO,CACL,KAAM,gBACN,KAAM,CACJ,aAAc,CACZ,UAAWX,EAAQ,GACnB,UAAAY,EACA,SAAAG,EACA,UAAWlB,EAAM,UACjB,QAAS,KAAK,QACd,SAAUA,EAAM,SAChB,cAAAiB,EAKA,iBAAkBjB,EAAM,gBAC1B,CACF,CACF,CACF,EACA,CAAE,MAAO,KAAK,SAAU,CAC1B,GAEW,OAAO,GACpB,CACF,EAEA,SAASU,IAAwB,CAC/B,OAAI,OAAO,UAAc,KAAe,UAAU,SAAiB,UAAU,SACtE,OACT,CAEA,SAASC,IAA2B,CAClC,OAAI,OAAO,UAAc,KAAe,UAAU,UAAkB,UAAU,UACvE,wBACT,CC7DA,IAAMQ,GAAW,CAACC,EAAYC,IAC5BA,IAAM,MAAQ,OAAOD,CAAC,EAAE,KAAK,EAAE,YAAY,IAAMC,EAAE,KAAK,EAAE,YAAY,EASjE,SAASC,GACdC,EACAC,EACAC,EAA2B,CAAC,EACnB,CACT,GAAIF,EAAS,UAAY,IAASA,EAAS,OAAS,OAAQ,MAAO,GACnE,IAAMG,EAAQH,EAAS,OAAS,CAAC,EACjC,OAAIG,EAAM,SAAW,EAAU,GACxBA,EAAM,KAAMC,GAAS,CAC1B,IAAMC,EAASC,GAAwD,CACrE,GAAIA,EAAI,UAAY,QAAS,OAAOV,GAASM,EAAQ,OAAS,GAAII,EAAI,MAAM,EAC5E,GAAIA,EAAI,UAAY,SAAWA,EAAI,aAAe,cAAe,OAAOV,GAASM,EAAQ,YAAc,GAAII,EAAI,MAAM,EACrH,GAAIA,EAAI,UAAY,YAAcA,EAAI,WAAY,CAChD,IAAMC,EAAIN,EAAQK,EAAI,UAAU,EAChC,OAAIC,IAAM,OAAkB,GACrB,MAAM,QAAQA,CAAC,EAAIA,EAAE,KAAMC,GAAMZ,GAASY,EAAGF,EAAI,MAAM,CAAC,EAAIV,GAASW,EAAGD,EAAI,MAAM,CAC3F,CACA,MAAO,EACT,EACA,OAAOF,EAAK,KAAO,MAAQA,EAAK,aAAa,MAAMC,CAAK,EAAID,EAAK,aAAa,KAAKC,CAAK,CAC1F,CAAC,CACH,CAQO,SAASI,GACdC,EACAT,EACAC,EAA2B,CAAC,EACV,CAClB,IAAMS,EAAwB,CAAC,EAC/B,QAAWC,KAAKF,EAAW,CACzB,GAAIE,EAAE,UAAY,GAAO,CACnBA,EAAE,cAAcD,EAAI,KAAK,CAAE,WAAYC,EAAE,MAAO,SAAUA,EAAE,MAAO,MAAOA,EAAE,aAAc,KAAM,QAAS,CAAC,EAC9G,QACF,CACA,GAAI,CAACb,GAAiBa,EAAGX,EAASC,CAAO,EAAG,SAC5C,IAAMW,EAAQZ,EAAQW,EAAE,kBAAkB,EACtCC,IAAU,QAAc,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,IAC1EF,EAAI,KAAK,CACP,WAAYC,EAAE,MACd,SAAUA,EAAE,MACZ,MAAAC,EACA,KAAMD,EAAE,OAAS,SAAW,SAAWA,EAAE,OAAS,UAAY,UAAY,SAC1E,GAAIA,EAAE,QAAQ,OAAS,EAAI,CAAE,iBAAkBA,EAAE,QAAQ,IAAK,GAAM,EAAE,KAAK,CAAE,EAAI,CAAC,CACpF,CAAC,CACH,CACA,OAAOD,CACT,CAoHO,IAAMG,EAAN,KAAe,CACpB,YACmBC,EACAC,EACjB,CAFiB,UAAAD,EACA,aAAAC,CAChB,CASH,MAAM,oBAAoBA,EAA+C,CACvE,IAAMC,EAAKD,GAAW,KAAK,QAC3B,GAAI,CAACC,EAAI,MAAM,IAAI,MAAM,6CAA6C,EACtE,OAAO,KAAK,KAAK,IAAwB,sCAAuC,CAC9E,OAAQ,CAAE,QAASA,CAAG,CACxB,CAAC,CACH,CASA,MAAM,qBACJC,EACAC,EAC+B,CAC/B,OAAO,KAAK,KAAK,IAA0B,yCAA0C,CACnF,OAAQ,CACN,UAAAD,EACA,kBAAmBC,GAAA,YAAAA,EAAM,iBAC3B,CACF,CAAC,CACH,CAOA,MAAM,iBAAiBC,EAGiB,CACtC,OAAO,KAAK,KAAK,KACf,iCACAA,CACF,CACF,CAYA,MAAM,iBAAiBA,EAAmF,CACxG,OAAO,KAAK,KAAK,KAA4B,mCAAoCA,CAAK,CACxF,CAOA,MAAM,WAAWA,EAAuD,CACtE,OAAO,KAAK,KAAK,KAAyB,iCAAkCA,CAAK,CACnF,CASA,MAAM,eAAeA,EAAoF,CACvG,OAAO,KAAK,KAAK,KAAkD,oCAAqCA,CAAK,CAC/G,CAQA,MAAM,uBACJF,EACAG,EACgC,CAChC,OAAO,KAAK,KAAK,IAA2B,0CAA2C,CACrF,OAAQA,EAAY,CAAE,UAAAH,EAAW,UAAAG,CAAU,EAAI,CAAE,UAAAH,CAAU,CAC7D,CAAC,CACH,CACF,EC3aO,IAAMI,EAAN,KAAwB,CAO7B,YAA6BC,EAA2DC,EAA0B,CAArF,UAAAD,EAA2D,eAAAC,EANxF,KAAQ,QAA+B,KACvC,KAAQ,QAAgC,KACxC,KAAQ,QAAU,GAClB,KAAiB,MAAQ,IAAI,IAC7B,KAAiB,YAA4B,CAAC,CAEqE,CAE3G,QAAQC,EAA4B,CAd9C,IAAAC,EAAAC,EAAAC,EAAAC,EAeI,QAAOF,GAAAD,EAAA,KAAK,YAAL,YAAAA,EAAgB,YAAYD,KAA5B,YAAAE,EAAkC,QAAOE,GAAAD,EAAA,KAAK,YAAL,YAAAA,EAAgB,MAAMH,KAAtB,YAAAI,EAA4B,UAAW,IACzF,CAEQ,OAAuB,CAC7B,OAAI,OAAO,OAAW,IAAoB,QAAQ,QAAQ,GAC1D,KAAK,UAAL,KAAK,SAAa,SAAY,CAC5B,GAAI,CAAE,KAAK,QAAU,MAAM,KAAK,KAAK,CAAG,MAAQ,CAAgC,CAChF,KAAK,QAAU,GACf,IAAMC,EAAU,KAAK,QACrB,QAAWL,KAAO,KAAK,MACrB,GAAI,CAAEK,GAAA,MAAAA,EAAS,WAAWL,EAAM,MAAQ,CAAwD,CAElG,KAAK,MAAM,MAAM,EACjB,OAAW,CAAE,IAAAA,EAAK,GAAAM,CAAG,IAAK,KAAK,YAAY,OAAO,CAAC,EACjD,GAAI,CAAMD,EAASA,EAAQ,UAAUL,EAAKM,CAAE,EAAQA,EAAG,KAAK,QAAQN,CAAG,CAAC,CAAG,MAAQ,CAA6B,CAElH,GAAI,CAAE,MAAMK,GAAA,YAAAA,EAAS,QAAS,MAAQ,CAAgD,CACxF,GAAG,GACI,KAAK,QACd,CAEQ,KAAKL,EAAmB,CACzB,KAAK,SAAS,KAAK,MAAM,IAAIA,CAAG,EAChC,KAAK,MAAM,CAClB,CAEA,WAAWA,EAA4B,CACrC,OAAI,KAAK,QAAgB,KAAK,QAAQ,WAAWA,CAAG,GACpD,KAAK,KAAKA,CAAG,EACN,KAAK,QAAQA,CAAG,EACzB,CAEA,WAAWA,EAA+B,CA/C5C,IAAAC,EAAAC,EAAAC,EAAAC,EAgDI,OAAI,KAAK,QAAgB,KAAK,QAAQ,WAAWJ,CAAG,GACpD,KAAK,KAAKA,CAAG,IACNE,GAAAD,EAAA,KAAK,YAAL,YAAAA,EAAgB,YAAYD,KAA5B,YAAAE,EAAkC,YAAWE,GAAAD,EAAA,KAAK,YAAL,YAAAA,EAAgB,MAAMH,KAAtB,YAAAI,EAA4B,UAAW,KAC7F,CAEA,UAAUG,EAA0B,CArDtC,IAAAN,EAAAC,EAsDI,OAAI,KAAK,QAAgB,KAAK,QAAQ,UAAUK,CAAO,GACvD,KAAK,KAAKA,CAAO,IACVL,GAAAD,EAAA,KAAK,YAAL,YAAAA,EAAgB,MAAMM,KAAtB,YAAAL,EAAgC,UAAW,GACpD,CAEA,UAAUF,EAAaM,EAA4C,CACjE,GAAI,KAAK,QAAS,CAAE,KAAK,QAAQ,UAAUN,EAAKM,CAAE,EAAG,MAAQ,CAC7D,GAAI,KAAK,QAAS,CAAEA,EAAG,KAAK,QAAQN,CAAG,CAAC,EAAG,MAAQ,CACnD,KAAK,YAAY,KAAK,CAAE,IAAAA,EAAK,GAAAM,CAAG,CAAC,EAC5B,KAAK,MAAM,CAClB,CAEA,OAAuB,CAAE,OAAO,KAAK,MAAM,CAAG,CAChD,EC1CO,IAAME,EAAN,KAAqB,CAgD1B,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,KAAK,MAAQ,IAAII,EAAYF,EAAS,KAAK,OAAO,QAAS,KAAK,OAAO,QAAU,MAAM,EACvF,KAAK,MAAM,UAAY,KAAK,OAAO,UACnC,KAAK,YAAc,IAAIG,EAAkB,IAAM,KAAK,MAAM,KAAK,EAAG,KAAK,OAAO,SAAS,EAEvF,IAAMC,EAAYC,GAAkB,CAClC,KAAK,cAAgBA,CACvB,EAEA,KAAK,SAAW,IAAIC,EAAe,KAAK,KAAM,KAAK,OAAO,QAASF,EAAWG,GAC5E,KAAK,MAAM,aAAa,CACtB,kBAAmBA,EAAE,GACrB,OAAQA,EAAE,OAAO,MACjB,SAAUA,EAAE,OAAO,SACnB,MAAOC,GAAWD,EAAE,KAAK,CAC3B,CAAC,CACH,EAGA,KAAK,QAAU,IAAIE,EACjB,KAAK,KACL,KAAK,OAAO,QACZV,EACA,KAAK,SACJW,GAAM,KAAK,MAAM,SAASA,CAAC,EAC5B,CAACC,EAAGC,IAAM,KAAK,MAAM,WAAW,qBAAsBD,EAAGC,CAAC,CAC5D,EACA,KAAK,OAAS,IAAIC,EAAa,KAAK,KAAM,KAAK,OAAO,QAAS,KAAK,OAAO,EAC3E,KAAK,SAAW,IAAIC,EAAe,KAAK,KAAM,KAAK,OAAO,OAAO,EACjE,KAAK,OAAS,IAAIC,EAAqB,KAAK,KAAM,KAAK,OAAO,QAASX,CAAQ,EAC/E,KAAK,QAAU,IAAIY,EAAc,KAAK,KAAM,KAAK,OAAO,OAAO,EAC/D,KAAK,OAAS,IAAIC,EAChB,KAAK,KACL,KAAK,OAAO,QACZ,KAAK,SACL,KAAK,OAAO,UACXC,GAAO,KAAK,MAAM,kBAAkBA,CAAE,CACzC,EACA,KAAK,GAAK,IAAIC,EAAS,KAAK,KAAM,KAAK,OAAO,OAAO,CACvD,CAGA,gBAAgBd,EAAe,CAC7B,KAAK,cAAgBA,CACvB,CACF,EAiBO,SAASe,GAAqBtB,EAAwC,CAC3E,OAAO,IAAID,EAAeC,CAAM,CAClC,CC/FA,IAAIuB,GAAiB,GACjBC,GAAc,GACZC,GAAoC,CAAC,EAE3C,SAASC,IAAgB,CACvBF,GAAc,GACd,QAAWG,KAAMF,GAAgBE,EAAG,EACpCF,GAAe,OAAS,CAC1B,CAMO,SAASG,GACdC,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,ECvOA,IAAMC,GAAmB,qEAEZC,EAAsB,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,EAAe,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,GAAiBrB,EAAsC,CACrE,OAAOL,EAAe,IAAIK,CAAQ,CACpC,CC9EO,IAAMsB,GAAN,MAAMC,CAAY,CAEvB,OAAO,aAAaC,EAA8B,KAAqB,CACrE,OAAOC,EAAoBD,CAAQ,CACrC,CAGA,OAAO,aAAaA,EAA8B,KAAkC,CAClF,IAAME,EAAMC,EAAaH,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,EAAaH,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,IAAKS,IAAO,CAAE,MAAOA,EAAE,IAAK,MAAOA,EAAE,IAAK,EAAE,CACnG,CAGA,OAAO,WAAWH,EAAqBI,EAAoBV,EAA8B,KAAwB,CAC/G,OAAOD,EAAY,WAAWO,EAAaN,CAAQ,EAAE,KAAM,GAAM,EAAE,MAAQU,CAAU,GAAK,IAC5F,CAMA,OAAO,eACLC,EACAC,EACAN,EACAN,EAA8B,KACZ,CAClB,IAAMa,EAAUd,EAAY,WAAWO,EAAaN,CAAQ,EAC5D,GAAIa,EAAQ,SAAW,EAAG,OAAO,KAEjC,IAAIC,EAAQD,EAAQ,KAAMJ,GAAMA,EAAE,MAAQE,CAAW,EAOrD,OANIG,IAEJA,EAAQD,EAAQ,KAAMJ,GAAMA,EAAE,KAAK,YAAY,IAAME,EAAY,YAAY,CAAC,EAC1EG,KAEJA,EAAQD,EAAQ,KAAMJ,GAAMA,EAAE,KAAK,YAAY,IAAMG,EAAgB,YAAY,CAAC,EAC9EE,GAAcA,GAElBA,EAAQD,EAAQ,KACbJ,GACCA,EAAE,KAAK,YAAY,EAAE,SAASG,EAAgB,YAAY,CAAC,GAC3DA,EAAgB,YAAY,EAAE,SAASH,EAAE,KAAK,YAAY,CAAC,CAC/D,EAEOK,GAAS,KAClB,CAEA,OAAO,iBAAiBd,EAAsC,CAC5D,OAAOe,GAAiBf,CAAQ,CAClC,CAEA,OAAO,uBAAsD,CAC3D,OAAOgB,CACT,CACF,EC7FA,IAAMC,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",
|
|
6
|
-
"names": ["core_exports", "__export", "AVAILABLE_LANGUAGES", "CRYPTO_ONCHAIN_FINAL_PHASES", "CRYPTO_ONCHAIN_PAYMENT_METHOD", "CRYPTO_ONCHAIN_STATUS_POLL_MS", "CatalogModule", "CheckoutModule", "CryptoOnchainCheckout", "CurrencyUtils", "CustomerModule", "CustomerPortalModule", "ExperimentsModule", "FunnelModule", "GoogleAutocompleteCore", "HeadlessClient", "HttpClient", "ISODataCore", "OffersModule", "PaymentModule", "RxModule", "TagadaAuthError", "TagadaError", "TagadaNetworkError", "TagadaNotFoundError", "TagadaPaymentError", "TagadaRateLimitError", "TagadaValidationError", "TrackModule", "createHeadlessClient", "cryptoOnchainPhase", "cryptoOnchainSecondsLeft", "defaultCryptoOnchainSelection", "ensureGeoDataLoaded", "formatCryptoOnchainCountdown", "formatMoney", "getCountries", "getStatesForCountry", "isCryptoOnchainMethod", "isLanguageLoaded", "isQuestionActive", "loadGoogleMapsScript", "parseTokensFromUrl", "selectCryptoOnchainNetwork", "toIntakeAnswers", "TagadaError", "message", "code", "statusCode", "details", "TagadaAuthError", "TagadaValidationError", "errors", "appCode", "TagadaNotFoundError", "resource", "id", "TagadaRateLimitError", "retryAfterMs", "TagadaPaymentError", "opts", "TagadaNetworkError", "SDK_NAME", "SDK_VERSION", "BASE_URLS", "HttpClient", "config", "environment", "override", "path", "options", "_a", "method", "body", "headers", "params", "token", "signal", "url", "qs", "k", "v", "str", "reqHeaders", "SDK_VERSION", "authToken", "controller", "timeoutId", "res", "text", "TagadaError", "err", "TagadaNetworkError", "parsed", "data", "parseErrorData", "msg", "appCode", "TagadaAuthError", "TagadaNotFoundError", "fieldErrors", "TagadaValidationError", "retryAfter", "TagadaRateLimitError", "value", "CheckoutModule", "_CheckoutModule", "http", "storeId", "onTokenChange", "onSession", "checkoutToken", "sessionToken", "opts", "_a", "_b", "params", "raw", "session", "_c", "lineItems", "i", "body", "customerData", "res", "checkoutPath", "originOverride", "sessionOpts", "origin", "url", "href", "parsed", "sessionId", "items", "customer", "addresses", "shipping", "billing", "effectiveShipping", "effectiveBilling", "differentBilling", "data", "a", "stripEmpty", "code", "promotionId", "promoId", "r", "rateId", "cs", "orderSummaries", "summary", "sessionCurrency", "li", "price", "variant", "product", "currencyOpts", "priceEntry", "amount", "summaryItems", "s", "out", "v", "parseTokensFromUrl", "obj", "result", "k", "applePayContactToAddress", "contact", "_a", "_b", "address", "isUsable", "googlePayContactToAddress", "firstName", "rest", "isUsable", "address", "_a", "_b", "CDN_URL", "loadScript", "src", "isReady", "resolve", "reject", "script", "loadPixels", "w", "FLAG_KEY", "ANON_KEY", "SESSION_KEY", "QUEUE_LIMIT", "FLUSH_MS", "DEDUP_MS", "STEP_MEMORY", "toContents", "items", "item", "scalars", "data", "out", "key", "value", "STANDARD_EVENTS", "uuid", "toPixelsConfig", "pixels", "pixel", "provider", "id", "idKey", "rest", "TrackModule", "baseUrl", "storeId", "funnelKey", "stepId", "path", "at", "previous", "engine", "t", "name", "standard", "eventId", "seen", "when", "oldest", "who", "state", "input", "event", "_a", "signal", "detail", "SDK_NAME", "SDK_VERSION", "url", "response", "config", "_b", "base", "funnelSessionId", "module", "onLeave", "record", "scope", "store", "existing", "fresh", "records", "payload", "body", "CRYPTO_ONCHAIN_PAYMENT_METHOD", "CRYPTO_ONCHAIN_STATUS_POLL_MS", "CRYPTO_ONCHAIN_FINAL_PHASES", "isCryptoOnchainMethod", "method", "defaultCryptoOnchainSelection", "networks", "usable", "network", "candidate", "asset", "selectCryptoOnchainNetwork", "chainId", "currentAsset", "_a", "_b", "assets", "keep", "fallback", "cryptoOnchainPhase", "status", "cryptoOnchainSecondsLeft", "expiresAt", "nowMs", "end", "formatCryptoOnchainCountdown", "seconds", "s", "h", "m", "sec", "UNAVAILABLE", "CryptoOnchainCheckout", "api", "options", "listener", "payment", "paymentStatus", "phase", "result", "selection", "error", "messageOf", "next", "current", "target", "message", "_c", "patch", "readStartedPayment", "answer", "payment", "order", "paymentId", "clientSecret", "amount", "currency", "checkoutSessionId", "PENDING_KEY", "PENDING_TTL_MS", "takeParkedPaymentsApiReturn", "paymentId", "raw", "PENDING_KEY", "parked", "PENDING_TTL_MS", "OCEAN_SDK_URL", "OCEAN_CONTAINER_ID", "OCEAN_LANGUAGE_OVERRIDES", "oceanLanguage", "locale", "_a", "primary", "OCEAN_SDK_LOAD_TIMEOUT_MS", "oceanSdkLoading", "loadOceanSdk", "w", "resolve", "reject", "script", "fail", "message", "timer", "OCEAN_SDK_URL", "OCEAN_PENDING_KEY", "OCEAN_PENDING_TTL_MS", "parkOceanPayment", "paymentId", "takeParkedOceanPayment", "raw", "at", "restoreOceanPaymentReturn", "url", "loadPaymentsApiFlow", "FAILED_PAYMENT_STATUSES", "oceanSlot", "oceanSlotTaken", "OCEAN_TIMED_OUT", "OCEAN_UNMOUNTED", "EXPRESS_METHOD_TYPES", "paymentMethodListEntryToConfig", "entry", "_a", "isCard", "method", "settings", "processors", "publishableKey", "
|
|
3
|
+
"sources": ["../src/core/index.ts", "../src/core/errors.ts", "../src/core/version.ts", "../src/core/http.ts", "../src/core/modules/checkout.ts", "../src/core/helpers/walletContact.ts", "../src/core/modules/track.ts", "../src/core/helpers/cryptoOnchain.ts", "../src/core/helpers/paymentsApiAnswer.ts", "../src/core/helpers/stripeJs.ts", "../src/core/helpers/oceanpayment.ts", "../src/core/modules/payment.ts", "../src/core/modules/lazyCommerce.ts", "../src/core/modules/offers.ts", "../src/core/modules/customer.ts", "../src/core/modules/portal/index.ts", "../src/core/modules/catalog.ts", "../src/core/modules/funnel.ts", "../src/core/modules/rx.ts", "../src/core/modules/experiments.ts", "../src/core/client.ts", "../src/core/helpers/autocomplete.ts", "../src/core/helpers/iso3166.ts", "../src/core/helpers/countries.ts", "../src/core/helpers/currency.ts"],
|
|
4
|
+
"sourcesContent": ["export { HeadlessClient, createHeadlessClient } from './client.js';\n\nexport { CheckoutModule } from './modules/checkout.js';\nexport { parseTokensFromUrl } from './modules/checkout.js';\nexport { PaymentModule } from './modules/payment.js';\nexport { OffersModule } from './modules/offers.js';\nexport { CustomerModule } from './modules/customer.js';\nexport { CustomerPortalModule } from './modules/portal/index.js';\nexport type * as PortalTypes from './modules/portal/types.js';\nexport { CatalogModule } from './modules/catalog.js';\nexport { FunnelModule } from './modules/funnel.js';\nexport { RxModule, isQuestionActive, toIntakeAnswers } from './modules/rx.js';\nexport { TrackModule } from './modules/track.js';\nexport type { StepData, EventData, TrackIdentity, TrackHealth } from './modules/track.js';\nexport type {\n RxCaseStatus,\n RxRequiredForProduct,\n RxStorefrontPatient,\n RxIntakeAnswer,\n RxClinicalQuestion,\n RxClinicalQuestionRule,\n RxQuestionAnswers,\n RxIntakeContext,\n RxIntakeIssue,\n RxValidateIntakeInput,\n RxQuestionsForProduct,\n RxSubmitCaseInput,\n RxSubmitCaseResult,\n RxCaseSummary,\n RxIntakeContextResult,\n RxIntakeContextPatient,\n RxActivationStatus,\n RxActivationStepKey,\n RxActivationMissingItem,\n} from './modules/rx.js';\n\nexport { HttpClient } from './http.js';\n\n// On-chain crypto (`crypto_onchain`): paid inline from the page, never through pay-v2\nexport {\n CryptoOnchainCheckout,\n CRYPTO_ONCHAIN_PAYMENT_METHOD,\n CRYPTO_ONCHAIN_STATUS_POLL_MS,\n CRYPTO_ONCHAIN_FINAL_PHASES,\n isCryptoOnchainMethod,\n defaultCryptoOnchainSelection,\n selectCryptoOnchainNetwork,\n cryptoOnchainPhase,\n cryptoOnchainSecondsLeft,\n formatCryptoOnchainCountdown,\n} from './helpers/cryptoOnchain.js';\nexport type { CryptoOnchainApi } from './helpers/cryptoOnchain.js';\n\nexport {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaPaymentError,\n TagadaNetworkError,\n} from './errors.js';\n\n// Helpers: Google Autocomplete, ISO countries/regions, currency formatting\nexport {\n GoogleAutocompleteCore,\n loadGoogleMapsScript,\n ISODataCore,\n AVAILABLE_LANGUAGES,\n CurrencyUtils,\n formatMoney,\n ensureGeoDataLoaded,\n getCountries,\n getStatesForCountry,\n isLanguageLoaded,\n} from './helpers/index.js';\n\nexport type {\n GooglePrediction,\n GooglePlaceDetails,\n ExtractedAddress,\n FormattedAddress,\n SupportedLanguage,\n ISOCountry,\n ISORegion,\n Country,\n State,\n Currency,\n} from './helpers/index.js';\n\nexport type {\n Environment,\n HeadlessConfig,\n HttpRequestOptions,\n LineItem,\n CreateCheckoutSessionOptions,\n CheckoutCustomerMetadata,\n CheckoutSession,\n CheckoutLineItem,\n CheckoutTotals,\n CheckoutCustomer,\n Address,\n ShippingRate,\n PaymentMethodConfig,\n PaymentSetupConfig,\n ExpressMethod,\n ExpressMethods,\n StoreConfig,\n PayResult,\n PayOptions,\n PayDirectOptions,\n ProcessPaymentOptions,\n ProcessPaymentResult,\n OceanPaymentConfig,\n MountOceanPaymentOptions,\n OceanPaymentForm,\n CryptoOnchainAsset,\n CryptoOnchainNetwork,\n CryptoOnchainPayment,\n CryptoOnchainStatus,\n CryptoOnchainOptionsFailureCode,\n CryptoOnchainPaymentFailureCode,\n CryptoOnchainStatusFailureCode,\n CryptoOnchainFailure,\n CryptoOnchainOptionsResult,\n CryptoOnchainPaymentResult,\n CryptoOnchainStatusResult,\n CryptoOnchainPhase,\n CryptoOnchainSelection,\n CryptoOnchainCheckoutState,\n CryptoOnchainCheckoutOptions,\n CreateInstrumentOptions,\n PaymentInstrument,\n ThreedsSession,\n PaymentStatus,\n Offer,\n OfferLineItem,\n OfferPreview,\n OfferPreviewItem,\n OfferPayResult,\n Customer,\n Order,\n OrderItem,\n Subscription,\n CatalogProduct,\n CatalogVariant,\n CatalogPrice,\n CurrencyOption,\n FunnelNavigateInput,\n FunnelNavigateResult,\n} from './types.js';\n\nexport { ExperimentsModule } from './modules/experiments.js';\nexport type { TgdBootstrap, TgdIds } from '../tgd/contract/index.js';\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 * Application error code from the API, when it sends one \u2014 e.g.\n * `MISSING_SHIPPING_ADDRESS` when a cart containing a shippable product is\n * paid with no address (#TAG-1989). Branch on this rather than on the\n * message, which is customer-facing and may be reworded.\n */\n public readonly appCode?: string;\n\n constructor(\n message: string,\n errors: Array<{ field: string; message: string }> = [],\n appCode?: string,\n details?: Record<string, unknown>,\n ) {\n super(message, 'validation_error', 422, { errors, ...details });\n this.name = 'TagadaValidationError';\n this.errors = errors;\n this.appCode = appCode;\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", "/** Identity this package reports to the SDK routes. A test pins it to `package.json`. */\nexport const SDK_NAME = 'headless' as const;\nexport const SDK_VERSION = '1.23.0' as const;\n", "import {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaNetworkError,\n} from './errors.js';\nimport { SDK_VERSION } from './version.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 redirect?: RequestRedirect;\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 private redirect?: RequestRedirect;\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 this.redirect = config.redirect;\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 // Which SDK and version sent the call: the Payments API readiness check counts them per store.\n 'X-Tagada-SDK': `headless-sdk/${SDK_VERSION}`,\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 ...(this.redirect && { redirect: this.redirect }),\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 // Server actions answer `{ code, data }`, where `data` carries the\n // customer-facing message and an application error code \u2014 `Error.message`\n // is non-enumerable, so it cannot travel at the top level (#TAG-1989).\n // Without this the buyer sees \"Request failed: 422 \u2026\" instead of the\n // reason, and the code the storefront should branch on is thrown away.\n // The REST handler sends an object `data` as a JSON string, with an empty `message`.\n const data = parseErrorData(parsed.data);\n\n const msg =\n (parsed.message as string) ||\n (parsed.error as string) ||\n (typeof data.message === 'string' ? data.message : undefined) ||\n (typeof parsed.data === 'string' && Object.keys(data).length === 0 ? (parsed.data as string) : undefined) ||\n `Request failed: ${res.status} ${res.statusText} on ${path}`;\n\n const appCode = typeof data.code === 'string' ? data.code : undefined;\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, appCode, parsed);\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\nfunction parseErrorData(value: unknown): Record<string, unknown> {\n if (value && typeof value === 'object') return value as Record<string, unknown>;\n if (typeof value !== 'string') return {};\n try {\n const parsed: unknown = JSON.parse(value);\n return parsed && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type {\n CheckoutSession,\n LineItem,\n ShippingRate,\n Address,\n CheckoutCustomer,\n CreateCheckoutSessionOptions,\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 * Last session returned by `loadSession()`. Cached so sibling modules\n * (e.g. `FunnelModule`) can read the cart without re-fetching. Cleared\n * intentionally on no events \u2014 call `loadSession()` again to refresh.\n */\n private _currentSession: CheckoutSession | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly onTokenChange?: (token: string) => void,\n /** Tracking hook: the only call that yields a checkout session id. */\n private readonly onSession?: (session: CheckoutSession) => void,\n ) {}\n\n /**\n * Returns the most recently loaded `CheckoutSession`, if any.\n *\n * Populated by `loadSession()`. Returns `undefined` if the SDK has not\n * loaded a session yet. Used by `funnel.navigate()` to source the cart.\n */\n getCurrentSession(): CheckoutSession | undefined {\n return this._currentSession;\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 const session = this.normalizeSession(raw);\n this._currentSession = session;\n try {\n this.onSession?.(session);\n } catch {\n /* tracking must never break a checkout */\n }\n return session;\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(\n opts: CreateCheckoutSessionOptions,\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 ...(i.sellingPlanId !== undefined ? { sellingPlanId: i.sellingPlanId } : {}),\n ...(i.trialDays !== undefined ? { trialDays: i.trialDays } : {}),\n ...(i.trialPrice !== undefined ? { trialPrice: i.trialPrice } : {}),\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 if (opts.funnelSessionId) body.funnelSessionId = opts.funnelSessionId;\n if (opts.discountCodes?.length) body.discountCodes = opts.discountCodes;\n if (opts.metadata && Object.keys(opts.metadata).length > 0) body.metadata = opts.metadata;\n if (opts.customerMetadata && Object.keys(opts.customerMetadata).length > 0) {\n body.customerMetadata = opts.customerMetadata;\n }\n if (opts.customerTags?.length) body.customerTags = opts.customerTags;\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 * Create a session and produce a self-hosted redirect URL.\n *\n * Convenience wrapper around `createSession()`. Builds a URL of the\n * form `${origin}${checkoutPath}?checkoutToken=...&sessionToken=...`\n * that you can navigate to from a Cart page. The receiving page reads\n * the params via {@link CheckoutModule.parseTokensFromUrl} and calls\n * {@link CheckoutModule.loadSession}.\n *\n * For Tagada-hosted checkouts use the `checkoutUrl` returned by\n * `createSession()` directly \u2014 this helper is for **self-hosted**\n * checkout pages.\n *\n * @example\n * ```ts\n * const { url } = await tagada.checkout.createSessionUrl({\n * items: [{ variantId, quantity: 1 }],\n * checkoutPath: '/checkout',\n * });\n * window.location.href = url;\n * ```\n */\n async createSessionUrl(\n opts: CreateCheckoutSessionOptions & {\n /** Path on the current origin for the self-hosted checkout. Default: `/checkout`. */\n checkoutPath?: string;\n /** Origin to use. Defaults to `window.location.origin`. */\n origin?: string;\n },\n ): Promise<{\n url: string;\n checkoutUrl: string;\n checkoutToken: string;\n sessionToken: string;\n customerId: string;\n }> {\n const { checkoutPath = '/checkout', origin: originOverride, ...sessionOpts } = opts;\n const session = await this.createSession(sessionOpts);\n\n const origin =\n originOverride ?? (typeof window !== 'undefined' ? window.location.origin : '');\n const params = new URLSearchParams({\n checkoutToken: session.checkoutToken,\n sessionToken: session.sessionToken,\n });\n const url = `${origin}${checkoutPath}?${params.toString()}`;\n\n return { ...session, url };\n }\n\n /**\n * Read `checkoutToken` and session token from a URL.\n *\n * Recognizes both the SDK convention (`?sessionToken=`) and the\n * Tagada-hosted convention (`?token=`), so the same checkout page\n * works whether the user came from `createSessionUrl()` or directly\n * from a Tagada-hosted redirect.\n *\n * Returns `null` if `checkoutToken` is missing.\n *\n * @example\n * ```ts\n * const tokens = CheckoutModule.parseTokensFromUrl();\n * if (!tokens) {\n * window.location.href = '/cart';\n * return;\n * }\n * const session = await tagada.checkout.loadSession(\n * tokens.checkoutToken,\n * tokens.sessionToken,\n * );\n * ```\n */\n static parseTokensFromUrl(\n url?: string,\n ): { checkoutToken: string; sessionToken: string } | null {\n if (typeof url === 'undefined' && typeof window === 'undefined') return null;\n const href = url ?? window.location.href;\n let parsed: URL;\n try {\n parsed = new URL(href);\n } catch {\n return null;\n }\n const checkoutToken = parsed.searchParams.get('checkoutToken');\n if (!checkoutToken) return null;\n const sessionToken =\n parsed.searchParams.get('sessionToken') ?? parsed.searchParams.get('token') ?? '';\n return { checkoutToken, sessionToken };\n }\n\n /** Instance alias of {@link CheckoutModule.parseTokensFromUrl}. */\n parseTokensFromUrl(url?: string) {\n return CheckoutModule.parseTokensFromUrl(url);\n }\n\n /**\n * Add or update cart items on an existing session (upsert by product).\n *\n * Sends each item as `lineItems` to `POST /checkout-sessions/:id/line-items`.\n * The endpoint UPSERTs by product: it adds new products and updates the\n * variant/quantity of products already in the cart, but it does NOT remove\n * products omitted from `items`, and an empty array is a no-op (it does not\n * clear the cart). Each `quantity` must be >= 1 \u2014 removal is not supported by\n * this endpoint.\n *\n * Returns a server-side mutation summary (counts of created/updated rows).\n * It does NOT return the updated `CheckoutSession` \u2014 the underlying endpoint\n * never has and the previous typing was a lie that quietly assigned\n * `{ success, updated, ... }` 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 const lineItems = items.map((i) => ({\n variantId: i.variantId,\n priceId: i.priceId,\n ...(i.sellingPlanId !== undefined ? { sellingPlanId: i.sellingPlanId } : {}),\n quantity: i.quantity,\n }));\n\n return this.http.post(\n `/api/v1/checkout-sessions/${sessionId}/line-items`,\n { lineItems },\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: Array<Record<string, unknown>> }>(\n `/api/v1/checkout-sessions/${sessionId}/shipping-rates`,\n { token: this.sessionToken },\n );\n return (res.rates ?? []).map((r) => this.normalizeShippingRate(r));\n }\n\n /**\n * Normalize the v1 rates payload (`shippingRateName`, `estimatedDeliveryTime`)\n * to the SDK's `ShippingRate` shape (`name`, `estimatedDays`). Without\n * this the consumer's UI shows blank rate names \u2014 the demo's \"Delivery\"\n * radios were rendering only the price, no label.\n */\n private normalizeShippingRate(r: Record<string, unknown>): ShippingRate {\n return {\n id: r.id as string,\n name: (r.name ?? r.shippingRateName ?? '') as string,\n description: (r.description ?? undefined) as string | undefined,\n amount: (r.amount ?? 0) as number,\n currency: (r.currency ?? 'USD') as string,\n estimatedDays: (r.estimatedDays ?? r.estimatedDeliveryTime ?? undefined) as number | undefined,\n };\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 ...(price?.recurring ? {\n recurring: {\n interval: (price.interval ?? 'month') as string,\n intervalCount: (price.intervalCount ?? 1) as number,\n },\n } : {}),\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 // `totalAdjustedAmount` is what gets charged (subtotal \u2212 discounts + shipping + tax).\n // The raw adjuster summary also carries `totalAmount` = subtotal + shipping only \u2014\n // reading that first showed a pre-discount, pre-tax total (#TAG-2246). The legacy\n // `orderSummaries[0]` shape only has `totalAmount`, already aliased to the adjusted total.\n total: (summary.totalAdjustedAmount ??\n summary.totalAmount ??\n 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 ...(typeof cs.draft === 'boolean' ? { draft: cs.draft } : {}),\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 * Read `checkoutToken` and session token from a URL \u2014 standalone alias of\n * {@link CheckoutModule.parseTokensFromUrl}, importable without the class:\n *\n * ```ts\n * import { parseTokensFromUrl } from '@tagadapay/headless-sdk';\n * const tokens = parseTokensFromUrl(); // null if no checkoutToken in the URL\n * ```\n */\nexport const parseTokensFromUrl = CheckoutModule.parseTokensFromUrl;\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 { Address } from '../types.js';\n\n/**\n * A contact as Apple Pay hands it to `onpaymentauthorized`\n * (`event.payment.billingContact` / `event.payment.shippingContact`).\n *\n * Apple only fills the fields the payment request asked for, so an integration\n * that omits `requiredBillingContactFields` / `requiredShippingContactFields`\n * receives nothing here \u2014 see `applePayContactToAddress`.\n */\nexport interface ApplePayContact {\n givenName?: string;\n familyName?: string;\n addressLines?: string[];\n locality?: string;\n administrativeArea?: string;\n postalCode?: string;\n countryCode?: string;\n emailAddress?: string;\n phoneNumber?: string;\n}\n\n/** A Google Pay address (`paymentData.shippingAddress`, or `billingAddress`). */\nexport interface GooglePayContact {\n name?: string;\n address1?: string;\n address2?: string;\n address3?: string;\n locality?: string;\n administrativeArea?: string;\n postalCode?: string;\n countryCode?: string;\n phoneNumber?: string;\n emailAddress?: string;\n}\n\n/**\n * A contact as Stripe's Express Checkout Element reports it on `confirm`\n * (`event.billingDetails`, `event.shippingAddress`).\n */\nexport interface StripeContact {\n name?: string;\n email?: string;\n phone?: string;\n address?: {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n postal_code?: string;\n country?: string;\n };\n}\n\n/**\n * Map an Apple Pay contact onto an SDK `Address`.\n *\n * Returns `undefined` when the contact has no usable postal address, so a\n * caller can never overwrite a real address with an empty shell \u2014 Apple sends\n * a name-and-email-only contact whenever the payment request did not ask for\n * `postalAddress` (#TAG-1989).\n */\nexport function applePayContactToAddress(contact?: ApplePayContact | null): Address | undefined {\n if (!contact) return undefined;\n\n const address: Address = {\n firstName: contact.givenName,\n lastName: contact.familyName,\n line1: contact.addressLines?.[0],\n line2: contact.addressLines?.[1],\n city: contact.locality,\n state: contact.administrativeArea,\n postalCode: contact.postalCode,\n country: contact.countryCode,\n phone: contact.phoneNumber,\n };\n\n return isUsable(address) ? address : undefined;\n}\n\n/** Map a Google Pay address onto an SDK `Address`. Same contract as above. */\nexport function googlePayContactToAddress(contact?: GooglePayContact | null): Address | undefined {\n if (!contact) return undefined;\n\n const [firstName, ...rest] = (contact.name ?? '').trim().split(/\\s+/);\n\n const address: Address = {\n firstName: firstName || undefined,\n lastName: rest.length ? rest.join(' ') : undefined,\n line1: contact.address1,\n line2: [contact.address2, contact.address3].filter(Boolean).join(' ') || undefined,\n city: contact.locality,\n state: contact.administrativeArea,\n postalCode: contact.postalCode,\n country: contact.countryCode,\n phone: contact.phoneNumber,\n };\n\n return isUsable(address) ? address : undefined;\n}\n\n/**\n * Map a Stripe Express Checkout contact onto an SDK `Address`. Same contract as\n * the wallet mappers above: no street line or no country means `undefined`.\n */\nexport function stripeContactToAddress(contact?: StripeContact | null): Address | undefined {\n if (!contact?.address) return undefined;\n\n const [firstName, ...rest] = (contact.name ?? '').trim().split(/\\s+/);\n\n const address: Address = {\n firstName: firstName || undefined,\n lastName: rest.length ? rest.join(' ') : undefined,\n line1: contact.address.line1,\n line2: contact.address.line2,\n city: contact.address.city,\n state: contact.address.state,\n postalCode: contact.address.postal_code,\n country: contact.address.country,\n phone: contact.phone,\n };\n\n return isUsable(address) ? address : undefined;\n}\n\n/**\n * A street line and a country are the minimum a parcel \u2014 and every carrier\n * integration \u2014 needs. Anything less is a contact, not an address.\n */\nfunction isUsable(address: Address): boolean {\n return Boolean(address.line1?.trim() && address.country?.trim());\n}\n", "/**\n * The `track` capability: the merchant's coded funnel reports its steps and events,\n * and the browser pixels bound on the canvas fire from here.\n *\n * Three rules hold this file together:\n * - the constructor assigns fields and nothing else (the React provider builds the\n * client inside a `useMemo` that also runs during SSR);\n * - every public method returns at once without a `window`;\n * - everything automatic is gated on an opt-in flag that only `step()` writes, so a\n * site that upgrades and never calls `track.step()` makes zero new request.\n */\nimport type { TgdBootstrap, TgdPublicApi } from '../../tgd/contract/index.js';\nimport type { CheckoutLineItem } from '../types.js';\nimport { SDK_NAME, SDK_VERSION } from '../version.js';\nimport type {\n PixelEngine,\n PixelEngineConfig,\n PixelSignal,\n PixelsConfig,\n StandardPixelEvent,\n} from '../../pixels/index.js';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\nexport interface StepData {\n /** Overrides `location.pathname` for display and for the dedup key. */\n path?: string;\n props?: Record<string, JsonValue>;\n}\n\nexport type EventData = Record<string, JsonValue>;\n\nexport interface TrackIdentity {\n email?: string;\n phone?: string;\n customerId?: string;\n}\n\n/** One cart line, as the pixel mappers read it. Amounts stay in MINOR units. */\nexport interface PixelContent {\n id: string;\n quantity: number;\n item_price?: number;\n}\n\nexport interface TrackSignalNote {\n signal: string;\n value: string;\n detail?: Record<string, string>;\n}\n\n/** A local view: what this page loaded and what it could not do. No server call of its own. */\nexport interface TrackHealth {\n enabled: boolean;\n storeId: string;\n funnelKey: string;\n sdk: { name: typeof SDK_NAME; version: typeof SDK_VERSION };\n manifestHash: string | null;\n pixels: { loaded: boolean; providers: string[] };\n signals: TrackSignalNote[];\n}\n\n// ---------------------------------------------------------------------------\n// Wire shapes (contract \u00A76, R4 and R5)\n// ---------------------------------------------------------------------------\n\ntype Provider = 'facebook' | 'tiktok' | 'snapchat' | 'gtm' | 'clarity' | 'applovin';\n\ninterface ConfigPixel {\n provider: Provider;\n id: string;\n idKey: 'pixelId' | 'containerId' | 'projectId' | 'eventKey';\n events: Record<string, boolean>;\n googleAdsConversionId?: string;\n googleAdsConversionLabel?: string;\n}\n\ninterface TrackConfig {\n collect?: { v: 1; url: string };\n experiments?: { v: 1 };\n version: number;\n storeId: string;\n funnelKey: string;\n manifestHash: string;\n pixels: ConfigPixel[];\n steps: Record<string, { type?: string; events: Record<string, Provider[]> }>;\n checkout: { InitiateCheckout: Provider[]; Purchase: Provider[] };\n consent: { required: boolean };\n}\n\ntype TrackRecord =\n | { kind: 'step'; stepId: string; at: number; path?: string }\n | {\n kind: 'event';\n stepId: string;\n name: string;\n at: number;\n eventId: string;\n props?: Record<string, string | number | boolean>;\n }\n | {\n kind: 'signal';\n signal: 'pixel_blocked' | 'pixel_duplicate' | 'wallet_unavailable';\n value: string;\n detail?: Record<string, string>;\n };\n\ninterface PixelsModule {\n createPixelEngine(config: PixelEngineConfig): PixelEngine;\n}\n\n// ---------------------------------------------------------------------------\n// Engine loading: a lazy import on npm, a second CDN file on the bundle\n// ---------------------------------------------------------------------------\n\ndeclare const __TGD_PIXELS_CDN__: string | undefined;\nconst CDN_URL = typeof __TGD_PIXELS_CDN__ === 'undefined' ? '' : __TGD_PIXELS_CDN__;\n\nfunction loadScript(src: string, isReady: () => boolean): Promise<void> {\n if (isReady()) return Promise.resolve();\n return new Promise<void>((resolve, reject) => {\n const script = document.createElement('script');\n script.src = src;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('runtime script failed to load'));\n document.head.appendChild(script);\n });\n}\n\nasync function loadPixels(): Promise<PixelsModule | null> {\n if (typeof window === 'undefined') return null;\n if (CDN_URL) {\n const w = window as unknown as { TagadaPixels?: PixelsModule };\n if (w.TagadaPixels) return w.TagadaPixels;\n await loadScript(CDN_URL, () => Boolean(w.TagadaPixels));\n return w.TagadaPixels ?? null;\n }\n return (await import('../../pixels/index.js')) as unknown as PixelsModule;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst FLAG_KEY = '__tgd_track';\nconst ANON_KEY = '__tgd_aid';\nconst SESSION_KEY = '__tgd_sid';\nconst QUEUE_LIMIT = 50;\nconst FLUSH_MS = 2000;\nconst DEDUP_MS = 1000;\n/** Hard ceiling on the dedup map. A long-lived SPA visiting hundreds of paths must not grow it. */\nconst STEP_MEMORY = 64;\n\n/** Cart lines as the pixel mappers read them. `unitAmount` stays minor; `baseTransform` converts. */\nexport function toContents(items?: CheckoutLineItem[]): PixelContent[] | undefined {\n if (!Array.isArray(items) || items.length === 0) return undefined;\n return items.map((item) => ({ id: item.variantId, quantity: item.quantity, item_price: item.unitAmount }));\n}\n\n/** R5 carries flat scalars only; anything nested is dropped rather than stringified. */\nfunction scalars(data?: Record<string, JsonValue>): Record<string, string | number | boolean> | undefined {\n if (!data) return undefined;\n const out: Record<string, string | number | boolean> = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') out[key] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\n/**\n * Contract \u00A73: the three SDK event names that carry a pixel meaning, and the standard event a\n * canvas binding writes for them. The back end auto-binds `Lead`, not `lead`, so an event sent\n * under its own name would be gated against a key `config.steps[...].events` never holds, and\n * would reach Meta as an unknown custom event. Any other name is a custom event.\n */\nconst STANDARD_EVENTS: Readonly<Record<string, StandardPixelEvent>> = {\n lead: 'Lead',\n product_viewed: 'ViewContent',\n added_to_cart: 'AddToCart',\n};\n\nfunction uuid(): string {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n }\n}\n\n/**\n * R4 answers a flat array (one entry per configured integration); the engine reads the\n * hosted runtime's per-provider map. This is the only place the two shapes meet.\n */\nfunction toPixelsConfig(pixels: ConfigPixel[]): PixelsConfig {\n const out: Record<string, Record<string, unknown>[]> = {};\n for (const pixel of pixels) {\n // R4 builds each entry key by key, so spreading its own answer carries nothing extra.\n const { provider, id, idKey, ...rest } = pixel;\n (out[provider] ??= []).push({ ...rest, enabled: true, [idKey]: id, events: pixel.events ?? {} });\n }\n return out as unknown as PixelsConfig;\n}\n\n// ---------------------------------------------------------------------------\n// The module\n// ---------------------------------------------------------------------------\n\nexport class TrackModule {\n private readonly records: TrackRecord[] = [];\n private readonly lastStep = new Map<string, number>();\n private readonly signals: TrackSignalNote[] = [];\n\n private currentStepId: string | null = null;\n private manifestHash: string | null = null;\n private loadedProviders: string[] = [];\n private configPromise: Promise<TrackConfig | null> | null = null;\n private corePromise: Promise<TgdPublicApi | null> | null = null;\n /** @internal Server assignment passed to the lazy runtime. */\n bootstrap?: TgdBootstrap;\n private enginePromise: Promise<PixelEngine | null> | null = null;\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private listening = false;\n\n constructor(\n private readonly baseUrl: string,\n private readonly storeId: string,\n private readonly funnelKey: string,\n ) {}\n\n // -- opt-in flag ----------------------------------------------------------\n\n /**\n * The flag is `<storeId>:<funnelKey>`. Only the storeId half arms it; the funnel half is DATA,\n * read back by `flagFunnelKey()` so automatic events report the funnel the last `step()` named.\n * A funnel-key mismatch never disarms tracking; only another tenant's storeId reads as disabled.\n */\n private flag(): string[] {\n try {\n return (localStorage.getItem(FLAG_KEY) ?? '').split(':');\n } catch {\n return [];\n }\n }\n\n private enabled(): boolean {\n return this.flag()[0] === this.storeId;\n }\n\n private flagFunnelKey(): string {\n return this.flag()[1] || this.funnelKey;\n }\n\n /** Every automatic path is off under SSR and off without the flag. */\n private off(): boolean {\n return typeof window === 'undefined' || !this.enabled();\n }\n\n private arm(): void {\n try {\n localStorage.setItem(FLAG_KEY, `${this.storeId}:${this.funnelKey}`);\n } catch {\n /* private mode: tracking simply stays off */\n }\n }\n\n // -- public API -----------------------------------------------------------\n\n step(stepId: string, data?: StepData): void {\n if (typeof window === 'undefined') return;\n this.arm();\n const path = data?.path ?? window.location.pathname;\n const key = `${stepId}|${path}`;\n const at = Date.now();\n const previous = this.lastStep.get(key);\n if (previous !== undefined && at - previous < DEDUP_MS) return;\n this.remember(key, at);\n this.currentStepId = stepId;\n this.listen();\n this.push({ kind: 'step', stepId, at, path });\n void this.pixels().then((engine) => engine?.pageView(path, { stepId }));\n void this.core().then((t) => t?.page({ step_id: stepId })).catch(() => undefined);\n }\n\n event(name: string, data?: EventData): void {\n if (this.off()) return;\n const stepId = this.currentStepId;\n // An event before the first `step()` belongs to no step: it reaches neither R5 nor a pixel.\n if (stepId === null) return;\n // One id, both destinations (contract \u00A77.5: `'<PixelEvent>_' + uuid`). The pixel event is the\n // standard name when there is one, so the id Meta receives is the id R5 recorded.\n const standard = STANDARD_EVENTS[name];\n const eventId = `${standard ?? name}_${uuid()}`;\n this.push({ kind: 'event', stepId, name, at: Date.now(), eventId, props: scalars(data) });\n void this.pixels().then((engine) =>\n standard ? engine?.track(standard, data, { stepId, eventId }) : engine?.trackCustom(name, data, { stepId }),\n );\n void this.core().then((t) => t?.track(name, { ...(scalars(data) ?? {}), step_id: stepId, pixel_event_id: eventId })).catch(() => undefined);\n }\n\n /** Keep the dedup map to entries still inside the window, and never past `STEP_MEMORY`. */\n private remember(key: string, at: number): void {\n for (const [seen, when] of this.lastStep) {\n if (at - when >= DEDUP_MS) this.lastStep.delete(seen);\n }\n // Map iterates in insertion order, so the first key is the oldest one still held.\n while (this.lastStep.size >= STEP_MEMORY) {\n const oldest = this.lastStep.keys().next();\n if (oldest.done === true) break;\n this.lastStep.delete(oldest.value);\n }\n this.lastStep.set(key, at);\n }\n\n identify(who: TrackIdentity): void {\n if (this.off()) return;\n // The engine's identity field is `externalId`; the Tagada customer id is what fills it.\n void this.pixels().then((engine) =>\n engine?.identify({ email: who.email, phone: who.phone, externalId: who.customerId }),\n );\n void this.core().then((t) => t?.identify(who.customerId ?? null, { email: who.email, phone: who.phone, customerId: who.customerId })).catch(() => undefined);\n }\n\n consent(state: { marketing: boolean }): void {\n if (this.off()) return;\n void this.pixels().then((engine) => engine?.consent(state));\n }\n\n async health(): Promise<TrackHealth> {\n if (typeof window === 'undefined') return this.snapshot();\n if (this.enabled()) await this.config();\n return this.snapshot();\n }\n\n // -- internal hooks, called by the checkout and payment modules -----------\n\n /** @internal */\n noteCheckout(input: { checkoutSessionId: string; amount?: number; currency?: string; items?: PixelContent[] }): void {\n this.notePixel('InitiateCheckout', input.checkoutSessionId, input);\n }\n\n /** @internal */\n notePaid(input: { orderId: string; amount?: number; currency?: string; items?: PixelContent[] }): void {\n this.notePixel('Purchase', input.orderId, input);\n }\n\n /** The `eventId` formula is the server's `makeMetaEventId`, so Meta and TikTok dedup. */\n private notePixel(\n event: 'InitiateCheckout' | 'Purchase',\n id: string,\n input: { amount?: number; currency?: string; items?: PixelContent[] },\n ): void {\n if (this.off()) return;\n void this.pixels().then((engine) =>\n engine?.track(\n event,\n {\n value: input.amount,\n currency: input.currency,\n contents: input.items,\n num_items: input.items?.length,\n ...(event === 'Purchase' ? { transaction_id: id } : {}),\n },\n { eventId: `${event}_${id}` },\n ),\n );\n }\n\n /** @internal */\n noteSignal(signal: 'wallet_unavailable', value: 'applePay' | 'googlePay' | 'express', detail: { reason: string }): void {\n if (this.off()) return;\n this.signals.push({ signal, value, detail });\n this.listen();\n this.push({ kind: 'signal', signal, value, detail });\n }\n\n // -- config, engine -------------------------------------------------------\n\n private snapshot(): TrackHealth {\n return {\n enabled: typeof window === 'undefined' ? false : this.enabled(),\n storeId: this.storeId,\n funnelKey: this.flagFunnelKey(),\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n manifestHash: this.manifestHash,\n pixels: { loaded: this.loadedProviders.length > 0, providers: [...this.loadedProviders] },\n signals: [...this.signals],\n };\n }\n\n /**\n * R4, once per page. Plain `fetch`, no header, no credentials \u2014 never `HttpClient`,\n * which adds `Content-Type` and `x-cms-token` and so preflights against a fixed allow-list.\n */\n private config(): Promise<TrackConfig | null> {\n if (this.configPromise !== null) return this.configPromise;\n const url =\n `${this.baseUrl}/api/public/v1/sdk/config` +\n `?storeId=${encodeURIComponent(this.storeId)}&funnel=${encodeURIComponent(this.flagFunnelKey())}`;\n this.configPromise = (async (): Promise<TrackConfig | null> => {\n try {\n const response = await fetch(url);\n if (!response.ok) return null;\n const config = (await response.json()) as TrackConfig;\n this.manifestHash = config.manifestHash || null;\n return config;\n } catch {\n return null;\n }\n })();\n return this.configPromise;\n }\n\n /** @internal R4 is reused; loading is allowed only when it opts this store in. */\n core(): Promise<TgdPublicApi | null> {\n if (typeof window === 'undefined') return Promise.resolve(null);\n this.corePromise ??= (async () => {\n try {\n const config = await this.config();\n if (!config || (!config.collect && !config.experiments)) return null;\n const base = this.baseUrl.replace(/\\/+$/, '');\n const w = window as unknown as { tgd?: TgdPublicApi };\n if (typeof w.tgd?.init !== 'function') {\n await loadScript(base + '/assets/js/tgd.js', () => typeof w.tgd?.init === 'function');\n }\n if (typeof w.tgd?.init !== 'function') return null;\n w.tgd.init({ storeId: this.storeId, apiHost: config.collect ? new URL(config.collect.url).origin : base,\n bootstrap: this.bootstrap, _source: 'headless', _manualPages: true });\n return w.tgd;\n } catch {\n return null;\n }\n })();\n return this.corePromise;\n }\n\n /** @internal Funnel navigation alone must not opt a site into tracking. */\n noteFunnelSession(funnelSessionId: string): void {\n if (this.off()) return;\n void this.core().then((t) => t?._link(funnelSessionId)).catch(() => undefined);\n }\n\n private pixels(): Promise<PixelEngine | null> {\n if (!this.enabled()) return Promise.resolve(null);\n this.enginePromise ??= this.startEngine();\n return this.enginePromise;\n }\n\n private async startEngine(): Promise<PixelEngine | null> {\n try {\n const config = await this.config();\n if (config === null) return null;\n const module = await loadPixels();\n if (module === null) return null;\n const engine = module.createPixelEngine({\n pixels: toPixelsConfig(config.pixels ?? []),\n steps: config.steps,\n checkout: config.checkout,\n requireConsent: config.consent?.required === true,\n onSignal: (signal: PixelSignal) => this.onPixelSignal(signal),\n });\n await engine.init();\n this.loadedProviders = [...new Set((config.pixels ?? []).map((pixel) => pixel.provider))];\n return engine;\n } catch {\n return null;\n }\n }\n\n private onPixelSignal(signal: PixelSignal): void {\n const detail = signal.detail ?? {};\n this.signals.push({ signal: signal.kind, value: signal.provider, detail });\n this.push({ kind: 'signal', signal: signal.kind, value: signal.provider, detail });\n }\n\n // -- R5 queue -------------------------------------------------------------\n\n private listen(): void {\n if (this.listening || typeof window === 'undefined') return;\n this.listening = true;\n const onLeave = (event: Event): void => {\n if (event.type === 'visibilitychange' && document.visibilityState !== 'hidden') return;\n this.flush();\n };\n window.addEventListener('pagehide', onLeave);\n window.addEventListener('visibilitychange', onLeave);\n }\n\n private push(record: TrackRecord): void {\n if (!this.enabled()) return;\n this.records.push(record);\n if (this.records.length >= QUEUE_LIMIT) {\n this.flush();\n return;\n }\n if (this.flushTimer === null) this.flushTimer = setTimeout(() => this.flush(), FLUSH_MS);\n }\n\n /** `localStorage` is an undeclared identifier in Node, so it is read inside the try. */\n private identifier(scope: 'local' | 'session', key: string): string {\n try {\n const store = scope === 'local' ? localStorage : sessionStorage;\n const existing = store.getItem(key);\n if (existing) return existing;\n const fresh = uuid();\n store.setItem(key, fresh);\n return fresh;\n } catch {\n return uuid();\n }\n }\n\n private flush(): void {\n if (this.flushTimer !== null) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (this.records.length === 0) return;\n const records = this.records.splice(0, QUEUE_LIMIT);\n const payload: Record<string, unknown> = {\n storeId: this.storeId,\n funnelKey: this.flagFunnelKey(),\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n anonymousId: this.identifier('local', ANON_KEY),\n sessionId: this.identifier('session', SESSION_KEY),\n records,\n };\n if (this.manifestHash !== null) payload.manifestHash = this.manifestHash;\n const body = JSON.stringify(payload);\n const url = `${this.baseUrl}/api/public/v1/sdk/events`;\n try {\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n if (navigator.sendBeacon(url, new Blob([body], { type: 'text/plain;charset=UTF-8' }))) return;\n }\n } catch {\n /* swallowed: tracking never surfaces an error */\n }\n try {\n void fetch(url, {\n method: 'POST',\n body,\n keepalive: true,\n headers: { 'content-type': 'text/plain;charset=UTF-8' },\n }).catch(() => undefined);\n } catch {\n /* swallowed */\n }\n }\n}\n", "/**\n * On-chain crypto (`crypto_onchain`): the pure rules of the inline payment and the\n * `CryptoOnchainCheckout` flow. Same behaviour as the hosted (Studio) checkout's crypto panel:\n * default network and coin, status phases, quote countdown, polling until paid.\n */\nimport type {\n CryptoOnchainCheckoutOptions,\n CryptoOnchainCheckoutState,\n CryptoOnchainNetwork,\n CryptoOnchainOptionsResult,\n CryptoOnchainPaymentResult,\n CryptoOnchainPhase,\n CryptoOnchainSelection,\n CryptoOnchainStatus,\n CryptoOnchainStatusResult,\n} from '../types.js';\n\n/** `paymentSetupConfig` key and payment method name of on-chain crypto. */\nexport const CRYPTO_ONCHAIN_PAYMENT_METHOD = 'crypto_onchain';\n\n/** How often the checkout polls the status, in milliseconds. */\nexport const CRYPTO_ONCHAIN_STATUS_POLL_MS = 5000;\n\n/** Phases after which polling stops. */\nexport const CRYPTO_ONCHAIN_FINAL_PHASES: readonly CryptoOnchainPhase[] = ['paid', 'underpaid', 'failed', 'expired'];\n\n/** True for `crypto_onchain` in any spelling a checkout uses (`crypto-onchain`, `crypto_onchain:int_\u2026`). */\nexport function isCryptoOnchainMethod(method: string | null | undefined): boolean {\n if (!method) return false;\n return method.trim().toLowerCase().replace(/-/g, '_').split(':')[0] === CRYPTO_ONCHAIN_PAYMENT_METHOD;\n}\n\n/**\n * The default pick: the first mainnet network (testnets only when nothing else is offered) and its\n * first stablecoin, else its first coin. Null when no network offers a coin.\n */\nexport function defaultCryptoOnchainSelection(networks: CryptoOnchainNetwork[]): CryptoOnchainSelection | null {\n const usable = networks.filter((network) => network.assets.length > 0);\n const network = usable.find((candidate) => !candidate.testnet) ?? usable[0];\n if (!network) return null;\n const asset = network.assets.find((candidate) => candidate.stable) ?? network.assets[0];\n return { chainId: network.chainId, asset: asset.symbol };\n}\n\n/** Switching network keeps the coin when the new network offers it, else takes its default coin. */\nexport function selectCryptoOnchainNetwork(\n networks: CryptoOnchainNetwork[],\n chainId: number,\n currentAsset: string,\n): CryptoOnchainSelection {\n const assets = networks.find((network) => network.chainId === chainId)?.assets ?? [];\n const keep = assets.find((asset) => asset.symbol === currentAsset);\n const fallback = assets.find((asset) => asset.stable) ?? assets[0];\n return { chainId, asset: (keep ?? fallback)?.symbol ?? currentAsset };\n}\n\n/** The phase of the latest status (or of the payment as created, before the first poll). */\nexport function cryptoOnchainPhase(\n status: Pick<CryptoOnchainStatus, 'status' | 'paid' | 'expired'> | null,\n): CryptoOnchainPhase {\n if (!status) return 'waiting';\n if (status.paid) return 'paid';\n switch (status.status) {\n case 'detected':\n case 'overpaid':\n return 'confirming';\n case 'underpaid':\n return 'underpaid';\n case 'failed':\n return 'failed';\n case 'expired':\n return 'expired';\n default:\n return status.expired ? 'expired' : 'waiting';\n }\n}\n\n/** Whole seconds until `expiresAt`, never negative; 0 for a missing or unparsable date. */\nexport function cryptoOnchainSecondsLeft(expiresAt: string | null, nowMs: number): number {\n if (!expiresAt) return 0;\n const end = Date.parse(expiresAt);\n if (Number.isNaN(end)) return 0;\n return Math.max(0, Math.floor((end - nowMs) / 1000));\n}\n\n/** `m:ss` under an hour, `h:mm:ss` above. */\nexport function formatCryptoOnchainCountdown(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const sec = String(s % 60).padStart(2, '0');\n return h > 0 ? `${h}:${String(m).padStart(2, '0')}:${sec}` : `${m}:${sec}`;\n}\n\n/** The three calls the flow needs; `PaymentModule` provides them. */\nexport interface CryptoOnchainApi {\n getCryptoOnchainOptions(checkoutSessionId: string): Promise<CryptoOnchainOptionsResult>;\n createCryptoOnchainPayment(opts: { checkoutSessionId: string; chainId: number; asset: string }): Promise<CryptoOnchainPaymentResult>;\n getCryptoOnchainStatus(opts: { checkoutSessionId: string; cryptoOnchainPaymentId: string }): Promise<CryptoOnchainStatusResult>;\n}\n\nconst UNAVAILABLE = 'Crypto payments are not available right now. Choose another payment method.';\n\n/**\n * The inline crypto payment of one checkout session: load the networks and coins, keep the pick,\n * create (or re-quote) the payment, poll it until crypto-api confirms it and call `onPaid` once.\n * Create it with `tagada.payment.createCryptoOnchainCheckout()`.\n */\nexport class CryptoOnchainCheckout {\n private state: CryptoOnchainCheckoutState = {\n options: 'idle',\n networks: [],\n selection: null,\n payment: null,\n paymentStatus: null,\n isCreating: false,\n error: null,\n };\n\n private readonly listeners = new Set<(state: CryptoOnchainCheckoutState) => void>();\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private stopped = false;\n private paidNotified = false;\n\n constructor(\n private readonly api: CryptoOnchainApi,\n private readonly options: CryptoOnchainCheckoutOptions,\n ) {\n this.subscribe = this.subscribe.bind(this);\n this.getState = this.getState.bind(this);\n }\n\n getState(): CryptoOnchainCheckoutState {\n return this.state;\n }\n\n /** Listens to every state change; returns the unsubscribe function. */\n subscribe(listener: (state: CryptoOnchainCheckoutState) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** What to show: the polled phase, or `expired` once an unpaid quote ran out (renew with `pay()`). */\n getPhase(nowMs: number = Date.now()): CryptoOnchainPhase {\n const { payment, paymentStatus } = this.state;\n const phase = cryptoOnchainPhase(paymentStatus ?? (payment ? { status: payment.status, paid: false, expired: false } : null));\n const quoteOver = payment !== null && phase === 'waiting' && cryptoOnchainSecondsLeft(payment.expiresAt, nowMs) === 0;\n return quoteOver ? 'expired' : phase;\n }\n\n /** Whole seconds left on the current quote. */\n getSecondsLeft(nowMs: number = Date.now()): number {\n return cryptoOnchainSecondsLeft(this.state.payment?.expiresAt ?? null, nowMs);\n }\n\n /** Loads the networks and coins and picks the default network and coin. */\n async loadOptions(): Promise<CryptoOnchainCheckoutState> {\n this.setState({ options: 'loading', error: null });\n try {\n const result = await this.api.getCryptoOnchainOptions(this.options.checkoutSessionId);\n if (!result.ok) {\n this.setState({ options: 'unavailable', networks: [], selection: null, error: result.message || UNAVAILABLE });\n return this.state;\n }\n const selection = this.state.selection ?? defaultCryptoOnchainSelection(result.networks);\n this.setState(\n selection\n ? { options: 'ready', networks: result.networks, selection }\n : { options: 'unavailable', networks: result.networks, selection: null, error: UNAVAILABLE },\n );\n } catch (error: unknown) {\n this.setState({ options: 'unavailable', error: messageOf(error) });\n }\n return this.state;\n }\n\n /** Changes the pick. A new network keeps the coin when it offers it, else takes its default coin. */\n select(next: { chainId?: number; asset?: string }): void {\n const current = this.state.selection;\n if (next.chainId !== undefined && next.chainId !== current?.chainId) {\n this.setState({ selection: selectCryptoOnchainNetwork(this.state.networks, next.chainId, next.asset ?? current?.asset ?? '') });\n return;\n }\n if (next.asset !== undefined && current) this.setState({ selection: { ...current, asset: next.asset } });\n }\n\n /**\n * Creates the payment for the pick (or `selection`), or re-quotes it: another coin, or a quote\n * that expired. Save the customer and address on the session first. Starts polling.\n */\n async pay(selection?: CryptoOnchainSelection): Promise<CryptoOnchainPaymentResult> {\n const target = selection ?? this.state.selection;\n if (!target) return { ok: false, code: 'ASSET_NOT_AVAILABLE', message: 'Choose a network and a coin' };\n if (this.state.isCreating) return { ok: false, code: 'CHECKOUT_FAILED', message: 'A payment is already being created' };\n\n this.setState({ isCreating: true, error: null, selection: target });\n try {\n const result = await this.api.createCryptoOnchainPayment({\n checkoutSessionId: this.options.checkoutSessionId,\n chainId: target.chainId,\n asset: target.asset,\n });\n if (!result.ok) {\n this.setState({ isCreating: false, error: result.message });\n return result;\n }\n this.stopped = false;\n this.setState({ isCreating: false, payment: result.payment, paymentStatus: null });\n this.schedulePoll();\n return result;\n } catch (error: unknown) {\n const message = messageOf(error);\n this.setState({ isCreating: false, error: message });\n return { ok: false, code: 'CHECKOUT_FAILED', message };\n }\n }\n\n /** Polls the status once now (the timer keeps polling until the payment is final). */\n async refreshStatus(): Promise<CryptoOnchainStatus | null> {\n const payment = this.state.payment;\n if (!payment) return null;\n try {\n const result = await this.api.getCryptoOnchainStatus({\n checkoutSessionId: this.options.checkoutSessionId,\n cryptoOnchainPaymentId: payment.cryptoOnchainPaymentId,\n });\n // A newer quote replaced this payment while the call was in flight.\n if (!result.ok || this.state.payment?.cryptoOnchainPaymentId !== payment.cryptoOnchainPaymentId) return null;\n const status: CryptoOnchainStatus = {\n status: result.status,\n paymentId: result.paymentId,\n orderId: result.orderId,\n confirmations: result.confirmations,\n requiredConfirmations: result.requiredConfirmations,\n txHash: result.txHash,\n explorerTxUrl: result.explorerTxUrl,\n paid: result.paid,\n expired: result.expired,\n redirectUrl: result.redirectUrl,\n };\n this.setState({ paymentStatus: status });\n if (status.paid && !this.paidNotified) {\n this.paidNotified = true;\n this.options.onPaid?.(status);\n }\n return status;\n } catch {\n // The next tick retries; the payment still settles server side.\n return null;\n }\n }\n\n /** Polls again after `stop()`, while a payment is open (the customer came back to crypto). */\n resume(): void {\n if (!this.state.payment || CRYPTO_ONCHAIN_FINAL_PHASES.includes(this.getPhase())) return;\n this.stopped = false;\n this.schedulePoll();\n }\n\n /** Stops polling (unmount, or the customer chose another payment method). */\n stop(): void {\n this.stopped = true;\n if (this.pollTimer) clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n\n private schedulePoll(): void {\n if (this.pollTimer) clearTimeout(this.pollTimer);\n this.pollTimer = setTimeout(async () => {\n this.pollTimer = null;\n await this.refreshStatus();\n if (!this.stopped && !CRYPTO_ONCHAIN_FINAL_PHASES.includes(this.getPhase())) this.schedulePoll();\n }, this.options.pollIntervalMs ?? CRYPTO_ONCHAIN_STATUS_POLL_MS);\n }\n\n private setState(patch: Partial<CryptoOnchainCheckoutState>): void {\n this.state = { ...this.state, ...patch };\n this.options.onChange?.(this.state);\n this.listeners.forEach((listener) => listener(this.state));\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error && error.message ? error.message : UNAVAILABLE;\n}\n", "/**\n * The few Payments API (V3, D-29) checks the payment module runs on every answer. Kept apart from\n * `paymentsApi.ts`, which holds the V3 flow and is only imported on a V3 payment.\n */\n\n/** The pay answer of a Payments API store: the payment the page confirms, and no order yet. */\nexport interface StartedPayment {\n paymentId: string;\n clientSecret: string;\n amount?: number;\n currency?: string;\n /** Set when the answer names the session it pays. */\n checkoutSessionId?: string;\n /** Set when the page should create the shopper's Stripe Radar session with this key before confirming. */\n radar?: { publishableKey: string };\n}\n\n/** A V2 answer (it carries `payment` or `order`) is never read as a started payment. */\nexport function readStartedPayment(answer: unknown): StartedPayment | null {\n if (!answer || typeof answer !== 'object' || Array.isArray(answer)) return null;\n const { payment, order, paymentId, clientSecret, amount, currency, checkoutSessionId, radar } =\n answer as Record<string, unknown>;\n if (payment !== undefined || order !== undefined) return null;\n if (typeof paymentId !== 'string' || !paymentId || typeof clientSecret !== 'string' || !clientSecret)\n return null;\n return {\n paymentId,\n clientSecret,\n ...(typeof amount === 'number' ? { amount } : {}),\n ...(typeof currency === 'string' ? { currency } : {}),\n ...(typeof checkoutSessionId === 'string' ? { checkoutSessionId } : {}),\n ...(radarKey(radar) ? { radar: { publishableKey: radarKey(radar) as string } } : {}),\n };\n}\n\nfunction radarKey(radar: unknown): string | null {\n const key = radar && typeof radar === 'object' ? (radar as { publishableKey?: unknown }).publishableKey : null;\n return typeof key === 'string' && key.startsWith('pk_') ? key : null;\n}\n\nconst PENDING_KEY = 'tgd_payments_api_return';\nconst PENDING_TTL_MS = 60 * 60_000;\n\n/** Before a redirect: the session the payment pays, so the return page can read its secret again. */\nexport function parkPaymentsApiReturn(paymentId: string, checkoutSessionId: string): void {\n try {\n sessionStorage.setItem(PENDING_KEY, JSON.stringify({ paymentId, checkoutSessionId, at: Date.now() }));\n } catch {\n // Storage unavailable: the return page polls the payment, as on V2.\n }\n}\n\n/** The parked session of `paymentId`, read once; null for any other payment (every V2 payment). */\nexport function takeParkedPaymentsApiReturn(paymentId: string): { checkoutSessionId: string } | null {\n try {\n const raw = sessionStorage.getItem(PENDING_KEY);\n if (!raw) return null;\n const parked = JSON.parse(raw) as { paymentId?: string; checkoutSessionId?: string; at?: number };\n if (parked.paymentId !== paymentId) return null;\n sessionStorage.removeItem(PENDING_KEY);\n if (!parked.checkoutSessionId || !parked.at || Date.now() - parked.at > PENDING_TTL_MS) return null;\n return { checkoutSessionId: parked.checkoutSessionId };\n } catch {\n return null;\n }\n}\n", "/** The part of Stripe.js the SDK uses: a Radar session for the shopper's device. */\nexport type StripeJs = (publishableKey: string) => {\n createRadarSession(): Promise<{\n radarSession?: { id: string; [key: string]: unknown };\n error?: { message?: string };\n }>;\n};\n\n/** Stripe.js from the page, or loaded from Stripe's CDN. */\nexport function loadStripeJs(): Promise<StripeJs> {\n if (typeof window === 'undefined') return Promise.reject(new Error('Stripe Radar needs a browser'));\n const fromPage = (): StripeJs | undefined => (window as unknown as { Stripe?: StripeJs }).Stripe;\n const loaded = fromPage();\n if (loaded) return Promise.resolve(loaded);\n\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://js.stripe.com/v3/';\n script.async = true;\n script.onload = () => {\n const stripe = fromPage();\n if (stripe) resolve(stripe);\n else reject(new Error('Stripe.js loaded without window.Stripe'));\n };\n script.onerror = () => reject(new Error('Failed to load Stripe.js'));\n document.head.appendChild(script);\n });\n}\n", "/**\n * Browser plumbing for Ocean Payment's inline card form (Oceanpayment\n * Embedded SDK). Mirrors the hosted checkout's OceanPaymentPanel\n * (apps/studio-app/.../PaymentMethodSelector/TakeoverPanels.tsx).\n */\n\nexport interface OceanpaymentGlobal {\n init: (sandbox: boolean, cssUrl: string, language: string, configuration: Record<string, unknown>) => void;\n checkout: (data: Record<string, string>) => void;\n}\n\nexport type OceanWindow = Window & {\n Oceanpayment?: OceanpaymentGlobal;\n /** Ocean's SDK calls this global \u2014 the name is fixed by the SDK. */\n oceanpaymentCallBack?: (data: unknown) => void;\n};\n\nexport const OCEAN_SDK_URL = 'https://secure.oceanpayment.com/pages/js/oceanpayment.js';\n/** Fixed by Ocean's SDK, which looks the container up by this id. */\nexport const OCEAN_CONTAINER_ID = 'oceanpayment-element';\n/** Ocean's iframe answers every checkout(); this only guards a lost message. */\nexport const OCEAN_CALLBACK_TIMEOUT_MS = 120_000;\n\n/**\n * Ocean builds its card fields server-side from `?language=`. An unknown code\n * falls back to English, and `fi` comes back in Polish, so Finnish shoppers\n * get English.\n */\nconst OCEAN_LANGUAGE_OVERRIDES: Record<string, string> = { fi: 'en' };\n\nexport function oceanLanguage(locale: string | undefined): string {\n const primary = locale?.split(/[-_]/)[0]?.toLowerCase();\n if (!primary) return 'en';\n return OCEAN_LANGUAGE_OVERRIDES[primary] ?? primary;\n}\n\nconst OCEAN_SDK_LOAD_TIMEOUT_MS = 30_000;\nlet oceanSdkLoading: Promise<OceanpaymentGlobal> | null = null;\n\n/**\n * Load Ocean's SDK once per page: a second copy would deliver every result\n * twice. A failed or stalled load is forgotten, so the next mount retries.\n */\nexport function loadOceanSdk(): Promise<OceanpaymentGlobal> {\n const w = window as OceanWindow;\n if (w.Oceanpayment) return Promise.resolve(w.Oceanpayment);\n if (oceanSdkLoading) return oceanSdkLoading;\n\n oceanSdkLoading = new Promise<OceanpaymentGlobal>((resolve, reject) => {\n const script = document.createElement('script');\n const fail = (message: string) => {\n clearTimeout(timer);\n script.remove();\n oceanSdkLoading = null;\n reject(new Error(message));\n };\n const timer = setTimeout(() => fail('The Ocean Payment card form took too long to load'), OCEAN_SDK_LOAD_TIMEOUT_MS);\n script.addEventListener('load', () => {\n if (!w.Oceanpayment) return fail('Ocean Payment script loaded without window.Oceanpayment');\n clearTimeout(timer);\n resolve(w.Oceanpayment);\n });\n script.addEventListener('error', () => fail('Failed to load the Ocean Payment card form'));\n script.src = OCEAN_SDK_URL;\n document.head.appendChild(script);\n });\n return oceanSdkLoading;\n}\n\n/**\n * Ocean's inline card form leaves the page only for 3-D Secure, and Ocean\n * returns the shopper to the exact page URL the form was opened on \u2014 without\n * any payment reference in it. The payment id is parked in sessionStorage\n * before leaving; a stale entry (abandoned 3DS) is ignored after 30 minutes.\n */\nconst OCEAN_PENDING_KEY = 'tgd:headless:oceanpayment:pending';\nconst OCEAN_PENDING_TTL_MS = 30 * 60 * 1000;\n\nexport function parkOceanPayment(paymentId: string): void {\n try {\n sessionStorage.setItem(OCEAN_PENDING_KEY, JSON.stringify({ paymentId, at: Date.now() }));\n } catch {\n // Storage unavailable \u2014 Ocean's webhook still settles the order.\n }\n}\n\nfunction takeParkedOceanPayment(): string | undefined {\n try {\n const raw = sessionStorage.getItem(OCEAN_PENDING_KEY);\n if (!raw) return undefined;\n sessionStorage.removeItem(OCEAN_PENDING_KEY);\n const { paymentId, at } = JSON.parse(raw) as { paymentId?: string; at?: number };\n if (!paymentId || !at || Date.now() - at > OCEAN_PENDING_TTL_MS) return undefined;\n return paymentId;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Back from Ocean's 3-D Secure page: turn the parked payment into the\n * `paymentAction` / `paymentActionStatus` / `paymentId` markers that\n * `maybeResumeFromUrl()` and `usePayment()` already resume from.\n */\nexport function restoreOceanPaymentReturn(): void {\n if (typeof window === 'undefined') return;\n const paymentId = takeParkedOceanPayment();\n if (!paymentId) return;\n try {\n const url = new URL(window.location.href);\n if (url.searchParams.get('paymentId')) return;\n url.searchParams.set('paymentId', paymentId);\n url.searchParams.set('paymentAction', 'requireAction');\n url.searchParams.set('paymentActionStatus', 'completed');\n window.history.replaceState(window.history.state, '', url.toString());\n } catch {\n // Best-effort: Ocean's webhook still settles the order.\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport { TagadaNotFoundError } from '../errors.js';\nimport {\n applePayContactToAddress,\n googlePayContactToAddress,\n type ApplePayContact,\n type GooglePayContact,\n} from '../helpers/walletContact.js';\nimport type { CheckoutModule } from './checkout.js';\nimport { toContents } from './track.js';\nimport type { PixelContent } from './track.js';\nimport type {\n Address,\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 OceanPaymentConfig,\n MountOceanPaymentOptions,\n OceanPaymentForm,\n CryptoOnchainCheckoutOptions,\n CryptoOnchainOptionsResult,\n CryptoOnchainPaymentResult,\n CryptoOnchainStatusResult,\n} from '../types.js';\nimport { CryptoOnchainCheckout } from '../helpers/cryptoOnchain.js';\nimport {\n readStartedPayment,\n takeParkedPaymentsApiReturn,\n type StartedPayment,\n} from '../helpers/paymentsApiAnswer.js';\nimport { loadStripeJs } from '../helpers/stripeJs.js';\nimport {\n OCEAN_CALLBACK_TIMEOUT_MS,\n OCEAN_CONTAINER_ID,\n loadOceanSdk,\n oceanLanguage,\n parkOceanPayment,\n restoreOceanPaymentReturn,\n type OceanWindow,\n} from '../helpers/oceanpayment.js';\n\n/**\n * The V3 flow, imported on a Payments API payment only: its own chunk on npm, never in the CDN\n * bundle (the define and `external` in build-cdn.js), which cannot load core-js anyway.\n */\ndeclare const __TGD_NO_PAYMENTS_API__: boolean | undefined;\nfunction loadPaymentsApiFlow(): Promise<typeof import('../helpers/paymentsApi.js')> {\n if (typeof __TGD_NO_PAYMENTS_API__ !== 'undefined' && __TGD_NO_PAYMENTS_API__) {\n return Promise.reject(\n new Error(\n 'This store takes payments through the Payments API, which the CDN build does not support yet: ' +\n 'install @tagadapay/headless-sdk and @tagadapay/core-js 3.7.0 or later from npm.',\n ),\n );\n }\n return import('../helpers/paymentsApi.js');\n}\n\n/**\n * Payment statuses that end the payment without money moving. Not `expired`:\n * a crypto payment can still come back from it.\n */\nconst FAILED_PAYMENT_STATUSES = new Set(['failed', 'declined', 'rejected', 'error']);\n\n/**\n * One Ocean card form per page: Ocean's SDK uses a fixed container id and one\n * global callback. Held from the start of a mount; freed by `unmount()`, or\n * once the page has dropped the form's container without calling it.\n */\nlet oceanSlot: { element: HTMLElement; attached: boolean } | null = null;\nconst oceanSlotTaken = () => !!oceanSlot && (!oceanSlot.attached || oceanSlot.element.isConnected);\n\n/** Ocean's iframe never answered `checkout()`. */\nconst OCEAN_TIMED_OUT = Symbol('ocean-timed-out');\n/** The card form was removed while a payment waited on Ocean's iframe. */\nconst OCEAN_UNMOUNTED = Symbol('ocean-unmounted');\n\n/**\n * One row of `GET /api/v1/payment-methods` \u2014 the checkout's payment-method\n * picker list. `type` is `'credit-card'` for the native card form, otherwise\n * the integration provider (`apple_pay`, `google_pay`, `paypal`, `klarna`, \u2026).\n */\ninterface PaymentMethodListEntry {\n id: string;\n type: string;\n title?: string;\n iconUrl?: string;\n default?: boolean;\n settings?: Record<string, unknown> | null;\n metadata?: Record<string, unknown> | null;\n}\n\nconst EXPRESS_METHOD_TYPES = new Set(['apple_pay', 'google_pay', 'paypal', 'klarna', 'klarna_express', 'link']);\n\n/** Map a picker-list row to the `PaymentSetupConfig` entry shape (#TAG-2246). */\nfunction paymentMethodListEntryToConfig(entry: PaymentMethodListEntry): PaymentMethodConfig {\n const isCard = entry.type === 'credit-card';\n const method = isCard ? 'card' : entry.type;\n const settings = (entry.settings ?? {}) as Record<string, unknown>;\n const processors = settings.processors as Array<{ processorId?: string }> | undefined;\n const publishableKey = settings.publishableKey;\n return {\n enabled: true,\n method,\n provider: isCard ? undefined : entry.type,\n type: isCard ? 'card' : entry.type,\n label: entry.title,\n logoUrl: entry.iconUrl,\n express: EXPRESS_METHOD_TYPES.has(method),\n integrationId: isCard ? undefined : entry.id,\n processorId: processors?.[0]?.processorId,\n publishableKey: typeof publishableKey === 'string' ? publishableKey : undefined,\n metadata: entry.metadata ?? undefined,\n };\n}\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 /**\n * Last payment setup seen by `getPaymentSetup` \u2014 lets `processApplePay`\n * resolve the domain's Apple Pay registration (BYOK / platform-integrator)\n * without a second network round-trip inside Apple's authorization window.\n */\n private lastPaymentSetup: PaymentSetupConfig | null = null;\n\n /**\n * Payments API (V3) store: what the pay call knew about each payment it started (the session it\n * pays, the shopper's method), so `finalize()` can confirm it from the bare pay answer.\n */\n private readonly paymentsApiStarts = new Map<string, { checkoutSessionId: string; paymentMethod?: string }>();\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly environment: Environment,\n /** Used to persist wallet contacts onto the session before charging. */\n private readonly checkout?: CheckoutModule,\n /** Tracking hook, fired only on a payment this module sees reach `succeeded`. */\n private readonly onPaid?: (i: {\n orderId: string;\n amount?: number;\n currency?: string;\n items?: PixelContent[];\n }) => void,\n /** Tracking hook for a wallet the browser cannot offer. */\n private readonly onSignal?: (v: 'applePay' | 'googlePay', d: { reason: string }) => void,\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 this.lastPaymentSetup = opts.paymentSetupConfig;\n return opts.paymentSetupConfig;\n }\n\n const injected = this.readInjectedStepConfig();\n if (injected) {\n this.lastPaymentSetup = injected;\n return injected;\n }\n\n // The canonical config for the session \u2014 same builder as the step config\n // injected on Tagada-hosted pages and the partner API-key route\n // (#TAG-2246). Before this route existed the fallback read a `methods`\n // envelope off `/api/v1/payment-methods` (a flat array) and returned `{}`\n // for every self-hosted page.\n try {\n const res = await this.http.get<{ config?: PaymentSetupConfig } | null | undefined>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/payment-setup`,\n );\n const config: PaymentSetupConfig = { ...(res?.config ?? {}) };\n this.lastPaymentSetup = config;\n return config;\n } catch (err) {\n // Backend older than the route: derive the config from the hosted\n // picker list so an upgraded SDK keeps working until the API catches up.\n if (!(err instanceof TagadaNotFoundError)) throw err;\n }\n\n const config = await this.getPaymentSetupFromPickerList(checkoutSessionId);\n this.lastPaymentSetup = config;\n return config;\n }\n\n /**\n * Transitional fallback: `/api/v1/payment-methods` answers with a flat\n * array of `{ id, type, title, iconUrl, default, settings, metadata }`\n * picker rows (`type` = 'credit-card' or the integration provider). Map\n * them to the setup-config shape. Only used when the backend does not\n * serve `/checkout-sessions/:id/payment-setup` yet.\n */\n private async getPaymentSetupFromPickerList(checkoutSessionId: string): Promise<PaymentSetupConfig> {\n const res = await this.http.get<\n PaymentMethodListEntry[] | { methods?: PaymentMethodConfig[] } | null | undefined\n >('/api/v1/payment-methods', { params: { checkoutSessionId } });\n\n const entries: PaymentMethodConfig[] = Array.isArray(res)\n ? res.map(paymentMethodListEntryToConfig)\n : (res?.methods ?? []);\n\n const config: PaymentSetupConfig = {};\n for (const m of entries) {\n const key = m.provider && m.provider !== m.method ? `${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 // `available` stays true for every current caller; only the signal is new.\n if (typeof window !== 'undefined' && !('PaymentRequest' in window)) {\n this.onSignal?.('googlePay', { reason: 'no-payment-request-api' });\n }\n result.googlePay = { ...base, type: 'google_pay' };\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 if (typeof window !== 'undefined' && !('PaymentRequest' in window)) {\n this.onSignal?.('googlePay', { reason: 'no-payment-request-api' });\n }\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 // Tokenize ONCE \u2014 both `tokenizer.tokenizeCard` and\n // `tokenizer.tokenizeCardRaw` internally call BasisTheory's\n // `POST /tokens`. Running them in `Promise.all` charged the\n // customer's network with two identical tokenization requests\n // (visible in the browser as duplicated `tokens/` calls). Get\n // the raw response once, then derive the encoded TagadaToken\n // locally via `createTagadaToken`.\n const rawToken = await tokenizer.tokenizeCardRaw(sanitized);\n const tagadaToken: string = coreJs.createTagadaToken(\n rawToken,\n tokenizer.getProvider().getProviderName(),\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.rememberPaymentsApiStart(await 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 }), opts);\n }\n\n return this.rememberPaymentsApiStart(await 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 returnUrl: opts.returnUrl,\n }), opts);\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.rememberPaymentsApiStart(await 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 returnUrl: opts.returnUrl,\n }), opts);\n }\n\n /**\n * Persist a wallet contact onto the session before the charge.\n *\n * Express wallets are the one checkout where the buyer never fills an address\n * form: they approve one inside the sheet, and it comes back on the\n * authorization event. Studio's `ExpressPaymentWidget` writes it to the\n * session; the headless path used to drop it, which is how a year of orders\n * reached merchants with NULL shipping, billing and customer addresses\n * (#TAG-1989).\n *\n * Never invents data: a contact with no street line or no country maps to\n * `undefined` and the session is left exactly as it was. Failures are NOT\n * swallowed \u2014 if we hold an address and cannot store it, the charge must not\n * proceed, or we are back to the bug this fixes.\n */\n private async syncWalletContact(\n checkoutSessionId: string,\n contact: {\n shippingAddress?: Address;\n billingAddress?: Address;\n email?: string;\n phone?: string;\n firstName?: string;\n lastName?: string;\n },\n ): Promise<void> {\n const { shippingAddress, billingAddress } = contact;\n if (!shippingAddress && !billingAddress) return;\n\n if (!this.checkout) {\n throw new Error(\n 'PaymentModule cannot persist the wallet contact: no CheckoutModule was provided. ' +\n 'Build the SDK through createTagadaClient() rather than constructing PaymentModule directly.',\n );\n }\n\n const customer: Record<string, string> = {};\n if (contact.email) customer.email = contact.email;\n if (contact.phone) customer.phone = contact.phone;\n if (contact.firstName) customer.firstName = contact.firstName;\n if (contact.lastName) customer.lastName = contact.lastName;\n\n await this.checkout.updateCustomerAndAddress(checkoutSessionId, {\n customer,\n shippingAddress,\n billingAddress,\n });\n }\n\n /**\n * Process an Apple Pay payment.\n * Tokenizes the Apple Pay token and processes payment in one call.\n *\n * Pass the contacts from `onpaymentauthorized` \u2014 `event.payment.billingContact`\n * and `event.payment.shippingContact` \u2014 and they are written to the session\n * before the charge, so the address the buyer approved in the wallet sheet\n * lands on the order (#TAG-1989).\n *\n * Apple only returns them when the payment request asked for them, so the\n * `ApplePaySession` request needs:\n *\n * ```js\n * requiredBillingContactFields: ['postalAddress'],\n * requiredShippingContactFields: ['name', 'phone', 'email', 'postalAddress'],\n * ```\n *\n * @example\n * session.onpaymentauthorized = async (event) => {\n * await tagada.payment.processApplePay({\n * checkoutSessionId,\n * applePayToken: event.payment.token,\n * billingContact: event.payment.billingContact,\n * shippingContact: event.payment.shippingContact,\n * });\n * };\n */\n async processApplePay(opts: {\n checkoutSessionId: string;\n applePayToken: unknown;\n billingContact?: ApplePayContact | null;\n shippingContact?: ApplePayContact | null;\n paymentFlowId?: string;\n processorId?: string;\n /**\n * Basis Theory Apple Pay registration the checkout domain is bound to.\n * Required when the domain runs merchant-scoped Apple Pay \u2014 BYOK or the\n * platform-integrator (PPIID) system \u2014 because Apple encrypts the token\n * to that registration's certificate. Resolved automatically from the\n * payment setup (`applePayByok` domain map) when omitted; pass it only to\n * override that resolution.\n */\n merchantRegistrationId?: string;\n }): Promise<PayResult> {\n await this.syncWalletContact(opts.checkoutSessionId, {\n shippingAddress: applePayContactToAddress(opts.shippingContact),\n billingAddress: applePayContactToAddress(opts.billingContact),\n email: opts.shippingContact?.emailAddress ?? opts.billingContact?.emailAddress,\n phone: opts.shippingContact?.phoneNumber ?? opts.billingContact?.phoneNumber,\n firstName: opts.shippingContact?.givenName ?? opts.billingContact?.givenName,\n lastName: opts.shippingContact?.familyName ?? opts.billingContact?.familyName,\n });\n\n const merchantRegistrationId =\n opts.merchantRegistrationId ??\n (await this.resolveApplePayRegistration(opts.checkoutSessionId))?.merchantRegistrationId;\n\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n // The tokenizer returns the normalized Basis Theory response \u2014 it carries\n // no `tagadaToken` field. Wrap it into the standard base64 TagadaToken the\n // pay endpoint expects (destructuring `{ tagadaToken }` here used to yield\n // undefined and silently push the charge down the instrument-less path).\n const rawToken = await tokenizer.tokenizeApplePay(opts.applePayToken, merchantRegistrationId);\n const tagadaToken = btoa(\n JSON.stringify(coreJs.createTagadaDigitalWalletToken(rawToken, 'apple_pay')),\n );\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 * Resolve the Apple Pay registration binding for the domain the page is\n * served from. Both merchant-certificate (BYOK) and platform-integrator\n * (PPIID) Apple Pay attach a domain-keyed `applePayByok` map to the\n * `apple_pay` method's metadata; a hit means every Basis Theory call \u2014\n * merchant session AND tokenization \u2014 must carry that\n * `merchant_registration_id`. A miss (the default) means legacy platform\n * Apple Pay: omit the id and behavior is unchanged.\n *\n * Sources, in order: the Tagada routing injection, the last payment setup\n * seen by `getPaymentSetup`, then one API fetch when a `checkoutSessionId`\n * is given and no setup was ever loaded.\n *\n * Use `displayName` (when present) as the `display_name` of the Basis\n * Theory merchant session.\n */\n async resolveApplePayRegistration(\n checkoutSessionId?: string,\n ): Promise<{ merchantRegistrationId: string; displayName?: string } | null> {\n if (typeof window === 'undefined') return null;\n\n let host = window.location.hostname.toLowerCase().split(':')[0];\n if (host.startsWith('www.')) host = host.slice(4);\n\n const fromConfig = (setup: PaymentSetupConfig | null) => {\n for (const entry of Object.values(setup ?? {})) {\n const map = entry?.metadata?.applePayByok as\n | Record<string, { merchantRegistrationId?: string; displayName?: string }>\n | undefined;\n if (!map || typeof map !== 'object') continue;\n const hit = map[host];\n if (hit?.merchantRegistrationId) {\n return { merchantRegistrationId: hit.merchantRegistrationId, displayName: hit.displayName };\n }\n }\n return null;\n };\n\n const local = fromConfig(this.readInjectedStepConfig()) ?? fromConfig(this.lastPaymentSetup);\n if (local) return local;\n // A setup we already hold that carries no binding is authoritative \u2014 don't\n // burn a network round-trip (inside Apple's authorization window) to\n // re-learn that this is a legacy platform domain.\n if (this.lastPaymentSetup || this.readInjectedStepConfig() || !checkoutSessionId) return null;\n try {\n return fromConfig(await this.getPaymentSetup(checkoutSessionId));\n } catch {\n return null;\n }\n }\n\n /**\n * Process a Google Pay payment.\n * Tokenizes the Google Pay token and processes payment in one call.\n *\n * Pass `paymentData.shippingAddress` / the billing address off\n * `paymentMethodData.info.billingAddress` and they are persisted to the\n * session before the charge (#TAG-1989). Google only returns them when the\n * request sets `shippingAddressRequired` / `billingAddressRequired`.\n */\n async processGooglePay(opts: {\n checkoutSessionId: string;\n googlePayToken: string;\n billingAddress?: GooglePayContact | null;\n shippingAddress?: GooglePayContact | null;\n email?: string;\n paymentFlowId?: string;\n processorId?: string;\n }): Promise<PayResult> {\n await this.syncWalletContact(opts.checkoutSessionId, {\n shippingAddress: googlePayContactToAddress(opts.shippingAddress),\n billingAddress: googlePayContactToAddress(opts.billingAddress),\n email: opts.email ?? opts.shippingAddress?.emailAddress ?? opts.billingAddress?.emailAddress,\n phone: opts.shippingAddress?.phoneNumber ?? opts.billingAddress?.phoneNumber,\n });\n\n const coreJs = await this.loadCoreJs();\n const tokenizer = new coreJs.Tokenizer({ environment: this.environment });\n await tokenizer.initialize();\n // Same wrapping as Apple Pay above \u2014 the tokenizer's normalized response\n // has no `tagadaToken` field.\n const rawToken = await tokenizer.tokenizeGooglePay(opts.googlePayToken);\n const tagadaToken = btoa(\n JSON.stringify(coreJs.createTagadaDigitalWalletToken(rawToken, 'google_pay')),\n );\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 * `returnUrl` is the page that runs `maybeResumeFromUrl()` after the redirect. It defaults to the\n * current page, like `processPayment()`. pay-v2 still prefers the session's checkout page when it\n * has a live one, so this applies to headless pages. Pass the same value to `finalize()`.\n */\n async processApm(opts: {\n checkoutSessionId: string;\n paymentMethod: string;\n processorId: string;\n paymentFlowId?: string;\n returnUrl?: 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 returnUrl: opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : undefined),\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 // On-chain crypto (`crypto_onchain`)\n // ---------------------------------------------------------------------------\n\n /**\n * Networks and coins the store accepts for on-chain crypto on this checkout session. On-chain\n * crypto is paid from your page (address, exact amount, QR) and never through `pay()` /\n * `processApm()`: pay-v2 refuses it with `422 CRYPTO_ONCHAIN_INLINE_ONLY`.\n */\n async getCryptoOnchainOptions(checkoutSessionId: string): Promise<CryptoOnchainOptionsResult> {\n return this.http.get<CryptoOnchainOptionsResult>(\n `/api/v1/checkout-sessions/${encodeURIComponent(checkoutSessionId)}/crypto-onchain/options`,\n );\n }\n\n /**\n * Create the order's on-chain payment for a network and a coin, or re-quote it (another coin,\n * an expired quote): the deposit address, exact amount and wallet URI for the QR code. Save the\n * customer and address on the session first.\n */\n async createCryptoOnchainPayment(opts: {\n checkoutSessionId: string;\n chainId: number;\n asset: string;\n }): Promise<CryptoOnchainPaymentResult> {\n return this.http.post<CryptoOnchainPaymentResult>(\n `/api/v1/checkout-sessions/${encodeURIComponent(opts.checkoutSessionId)}/crypto-onchain/session`,\n { chainId: opts.chainId, asset: opts.asset },\n );\n }\n\n /** The payment's state; poll it every few seconds until `paid` (or underpaid / expired / failed). */\n async getCryptoOnchainStatus(opts: {\n checkoutSessionId: string;\n cryptoOnchainPaymentId: string;\n }): Promise<CryptoOnchainStatusResult> {\n return this.http.get<CryptoOnchainStatusResult>(\n `/api/v1/checkout-sessions/${encodeURIComponent(opts.checkoutSessionId)}/crypto-onchain/status`,\n { params: { cryptoOnchainPaymentId: opts.cryptoOnchainPaymentId } },\n );\n }\n\n /**\n * The whole inline crypto payment of a checkout session, the way the hosted checkout runs it.\n *\n * @example\n * ```ts\n * const crypto = tagada.payment.createCryptoOnchainCheckout({\n * checkoutSessionId: session.id,\n * onPaid: ({ orderId }) => showThankYou(orderId),\n * });\n * crypto.subscribe(render); // networks, selection, payment (address, amount, paymentUri), status\n * await crypto.loadOptions();\n * payButton.onclick = () => crypto.pay(); // after saving the customer and address\n * ```\n */\n createCryptoOnchainCheckout(opts: CryptoOnchainCheckoutOptions): CryptoOnchainCheckout {\n return new CryptoOnchainCheckout(this, opts);\n }\n\n // ---------------------------------------------------------------------------\n // Ocean Payment\n // ---------------------------------------------------------------------------\n\n /** Whether the store's Ocean Payment integration renders its inline card form or redirects. */\n async getOceanPaymentConfig(checkoutSessionId: string): Promise<OceanPaymentConfig> {\n const data = await this.http.post<Partial<OceanPaymentConfig>>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-embedded-config`,\n {},\n );\n return { embedded: !!data?.embedded, sandboxed: !!data?.sandboxed };\n }\n\n /**\n * Set up Ocean Payment for a checkout session, the way the hosted checkout\n * does: Ocean's card fields render inside `container` when the integration\n * has Ocean's public key (`embedded`), otherwise `pay()` sends the shopper\n * to Ocean's page and back to `returnUrl` (`redirect`).\n *\n * @example\n * ```ts\n * const ocean = await tagada.payment.mountOceanPayment({\n * checkoutSessionId: session.id,\n * container: '#ocean-card',\n * });\n * payButton.onclick = async () => {\n * const result = await ocean.pay();\n * if (result.status === 'requires_redirect') window.location.href = result.redirectUrl;\n * else if (result.status === 'succeeded') showThankYou(result.order);\n * else if (result.status === 'failed') showError(result.error);\n * };\n * ```\n */\n async mountOceanPayment(opts: MountOceanPaymentOptions): Promise<OceanPaymentForm> {\n if (typeof window === 'undefined') throw new Error('Ocean Payment needs a browser');\n const { checkoutSessionId, signal } = opts;\n const aborted = () => Object.assign(new Error('Ocean Payment mount aborted'), { name: 'AbortError' });\n if (signal?.aborted) throw aborted();\n\n const host = typeof opts.container === 'string'\n ? document.querySelector<HTMLElement>(opts.container)\n : opts.container;\n if (!host && opts.mode !== 'redirect') {\n throw new Error(`Ocean Payment container not found: ${String(opts.container)}`);\n }\n // Reserve Ocean's single slot before the first await, so a second mount\n // (React StrictMode runs effects twice) fails fast instead of racing.\n if (oceanSlotTaken() || document.getElementById(OCEAN_CONTAINER_ID)) {\n throw new Error('An Ocean Payment card form is already mounted on this page');\n }\n const w = window as OceanWindow;\n const element = document.createElement('div');\n element.id = OCEAN_CONTAINER_ID;\n const slot = { element, attached: false };\n oceanSlot = slot;\n const releaseSlot = () => { if (oceanSlot === slot) oceanSlot = null; };\n\n let mounted = true;\n let pendingCallback: ((data: unknown) => void) | null = null;\n const callback = (data: unknown) => {\n const resolve = pendingCallback;\n pendingCallback = null;\n resolve?.(data);\n };\n const unmount = () => {\n if (!mounted) return;\n mounted = false;\n if (w.oceanpaymentCallBack === callback) delete w.oceanpaymentCallBack;\n element.remove();\n releaseSlot();\n // A payment in flight stops waiting for the iframe and checks its status instead.\n callback(OCEAN_UNMOUNTED);\n };\n signal?.addEventListener('abort', unmount, { once: true });\n\n let config: OceanPaymentConfig;\n let ocean: Awaited<ReturnType<typeof loadOceanSdk>> | undefined;\n try {\n config = opts.mode === 'redirect'\n ? { embedded: false, sandboxed: false }\n : await this.getOceanPaymentConfig(checkoutSessionId);\n if (signal?.aborted) throw aborted();\n if (config.embedded) {\n ocean = await loadOceanSdk();\n if (signal?.aborted) throw aborted();\n }\n } catch (error) {\n unmount();\n throw error;\n }\n\n let submitting = false;\n\n if (!ocean) {\n // Ocean's own page needs no card slot on this one.\n releaseSlot();\n return {\n mode: 'redirect',\n pay: async () => {\n if (!mounted) return { status: 'failed', error: 'The Ocean Payment form was removed' };\n if (submitting) return { status: 'failed', error: 'Payment already in progress' };\n submitting = true;\n try {\n const data = await this.http.post<{ url?: string | null; paymentId?: string | null }>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-link`,\n { returnUrl: opts.returnUrl ?? window.location.href },\n );\n if (!data?.url || !data.paymentId) {\n return { status: 'failed', error: 'Ocean Payment is not available for this store' };\n }\n return { status: 'requires_redirect', redirectUrl: data.url, method: 'GET', paymentId: data.paymentId };\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n } finally {\n submitting = false;\n }\n },\n unmount,\n };\n }\n\n const sdk = ocean;\n host!.appendChild(element);\n slot.attached = true;\n w.oceanpaymentCallBack = callback;\n // Ocean refuses a checkout whose backUrl is not the page it was initialised on.\n const backUrl = window.location.href;\n // No \"Name on Card\" row: Ocean's iframe is a fixed 131px and clips it,\n // and the buyer's name already travels as billing_firstName/lastName.\n sdk.init(config.sandboxed, '', oceanLanguage(opts.locale), { showCardName: false });\n\n const pay = async (): Promise<ProcessPaymentResult> => {\n if (!mounted) return { status: 'failed', error: 'The Ocean Payment card form was removed' };\n if (submitting) return { status: 'failed', error: 'Payment already in progress' };\n submitting = true;\n try {\n // 1. Record the payment server-side and get Ocean's signed fields\n const created = await this.http.post<{ paymentId?: string; params?: Record<string, string> }>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-embedded-payment`,\n { backUrl },\n );\n if (!created?.paymentId || !created.params) {\n return { status: 'failed', error: 'Failed to start the payment' };\n }\n const paymentId = created.paymentId;\n\n // 2. Ocean's iframe charges the card it holds and answers through\n // oceanpaymentCallBack: {code, msg} for a card-entry error, or the\n // signed XML result.\n const answer = await new Promise<unknown>((resolve) => {\n const timer = setTimeout(() => {\n pendingCallback = null;\n resolve(OCEAN_TIMED_OUT);\n }, OCEAN_CALLBACK_TIMEOUT_MS);\n pendingCallback = (data) => { clearTimeout(timer); resolve(data); };\n sdk.checkout(created.params!);\n });\n // No answer from the iframe: the card may still have been charged, so\n // never invite a retry. Ocean's webhook settles the payment either way.\n if (answer === OCEAN_TIMED_OUT || answer === OCEAN_UNMOUNTED) {\n return this.pollUntilDone(paymentId);\n }\n if (answer && typeof answer === 'object' && 'msg' in answer) {\n return { status: 'failed', error: String((answer as { msg?: unknown }).msg || 'Please check your card details.') };\n }\n\n // 3. The server verifies Ocean's signed result: 3DS, success, or decline\n const result = await this.http.post<{ status: string; payUrl?: string; message?: string }>(\n `/api/v1/checkout-sessions/${checkoutSessionId}/oceanpayment-embedded-result`,\n { paymentId, response: String(answer) },\n );\n if (result?.status === 'requires_action' && result.payUrl) {\n // Ocean sends the shopper back to this page with nothing in the URL.\n parkOceanPayment(paymentId);\n return { status: 'requires_redirect', redirectUrl: result.payUrl, method: 'GET', paymentId };\n }\n if (result?.status === 'succeeded' || result?.status === 'pending') {\n return this.pollUntilDone(paymentId);\n }\n return { status: 'failed', error: result?.message || 'Payment declined' };\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n } finally {\n submitting = false;\n }\n };\n\n return { mode: 'embedded', pay, unmount };\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 return this.finalize(payResult, { returnUrl: opts.returnUrl });\n }\n\n /**\n * Resolve a raw `PayResult` (from any pay endpoint \u2014 `pay()`, `payDirect()`,\n * `processApplePay()`, `offers.payPreviewedOffer()`, \u2026) into a typed\n * `ProcessPaymentResult` (`succeeded` / `requires_redirect` / `failed`\n * / `pending`).\n *\n * Handles 3DS routing (modal challenge via core-js, or bank redirect)\n * and async polling until the payment reaches a terminal status.\n *\n * This is the same logic `processPayment()` runs after `pay()` \u2014 exposed\n * so callers (and the offers module) that already have a raw `PayResult`\n * don't need to re-pay.\n */\n async finalize(\n input: PayResult,\n opts?: { returnUrl?: string },\n ): Promise<ProcessPaymentResult> {\n const payment = input.payment;\n const returnUrl =\n opts?.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : undefined);\n\n // A Payments API (V3) store answers the payment to confirm, with no `payment`: a V2 answer\n // always carries one, so it never enters this branch.\n if (!payment) {\n const started = readStartedPayment(input);\n if (started) return this.finalizeOnPaymentsApi(started, returnUrl);\n }\n\n if (payment.status === 'succeeded') {\n this.emitPaid(input.order?.id, payment);\n return { status: 'succeeded', payment, order: input.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, { returnUrl } as ProcessPaymentOptions);\n }\n\n // '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 // Only a Payments API payment this page sent to a redirect is parked; every other one polls.\n const parked = takeParkedPaymentsApiReturn(paymentId);\n if (parked) {\n const url = typeof window !== 'undefined' ? window.location.href : undefined;\n return this.onPaymentsApi((flow, host) => flow.resumeOnPaymentsApi(host, paymentId, parked.checkoutSessionId, url));\n }\n return this.pollUntilDone(paymentId);\n }\n\n /**\n * Detect a return from a 3DS / processor redirect by inspecting the\n * current page URL, then poll the payment to completion.\n *\n * The post-3DS URL convention used by Tagada-routed processors is\n * `?paymentAction=requireAction&paymentActionStatus=completed&paymentId=pay_xxx`.\n * If those params are present, this method polls the payment, cleans the\n * URL (so a refresh doesn't re-trigger), and returns the resolved\n * `ProcessPaymentResult`. Otherwise it returns `null`.\n *\n * Use this in vanilla apps as the first thing on page load. The React\n * `usePayment` hook does the same automatically \u2014 don't call this when\n * also using `usePayment`, you'll double-poll.\n *\n * @example\n * ```ts\n * const tagada = createHeadlessClient({ storeId, environment });\n *\n * const resumed = await tagada.payment.maybeResumeFromUrl();\n * if (resumed?.status === 'succeeded') {\n * window.location.href = `/thank-you?orderId=${resumed.order?.id}`;\n * return;\n * }\n * if (resumed?.status === 'failed') {\n * showError(resumed.error);\n * return;\n * }\n * // No 3DS return \u2014 render the normal page.\n * ```\n */\n async maybeResumeFromUrl(opts?: {\n /**\n * URL to inspect (defaults to `window.location.href`). Pass an explicit\n * URL when running outside the browser or when integrating with a\n * router that hasn't navigated yet.\n */\n url?: string;\n /**\n * Whether to clean the redirect query params from the address bar\n * once the payment has been resolved. Defaults to `true`.\n */\n cleanUrl?: boolean;\n }): Promise<ProcessPaymentResult | null> {\n if (typeof window === 'undefined' && !opts?.url) return null;\n if (!opts?.url) restoreOceanPaymentReturn();\n\n const href = opts?.url ?? window.location.href;\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return null;\n }\n\n const action = url.searchParams.get('paymentAction');\n const actionStatus = url.searchParams.get('paymentActionStatus');\n const paymentId = url.searchParams.get('paymentId');\n if (action !== 'requireAction' || actionStatus !== 'completed' || !paymentId) {\n return null;\n }\n\n const result = await this.resumeAfterRedirect(paymentId);\n\n // Strip the redirect params so a refresh doesn't re-trigger.\n if (opts?.cleanUrl !== false && typeof window !== 'undefined' && !opts?.url) {\n const cleanParams = new URLSearchParams(window.location.search);\n [\n 'paymentAction',\n 'paymentActionStatus',\n 'paymentId',\n 'payment_intent',\n 'payment_intent_client_secret',\n 'source_type',\n 'redirect_status',\n 'sessionId',\n ].forEach((k) => cleanParams.delete(k));\n const search = cleanParams.toString();\n try {\n window.history.replaceState(\n {},\n document.title,\n window.location.pathname + (search ? '?' + search : ''),\n );\n } catch {\n // Best-effort.\n }\n }\n\n return result;\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' || FAILED_PAYMENT_STATUSES.has(status.status)) {\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 'stripe_radar':\n return this.handleStripeRadar(payment);\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 * Stripe Radar: the processor holds the charge until the browser sends a Radar\n * session. Create it with Stripe.js, save it, resume the payment, then poll.\n */\n private async handleStripeRadar(payment: PayResult['payment']): Promise<ProcessPaymentResult> {\n const radar = payment.requireActionData?.metadata?.radar as\n | { publishableKey?: string; orderId?: string }\n | undefined;\n if (!radar?.publishableKey) {\n return { status: 'failed', error: 'Stripe Radar configuration missing', payment };\n }\n\n try {\n const Stripe = await loadStripeJs();\n const { radarSession, error } = await Stripe(radar.publishableKey).createRadarSession();\n if (error || !radarSession) {\n throw new Error(error?.message || 'No Radar session returned by Stripe');\n }\n\n await this.http.post('/api/v1/radar-sessions', {\n orderId: radar.orderId,\n paymentId: payment.id,\n stripeRadarSessionId: radarSession.id,\n stripeRadarSessionData: radarSession,\n });\n await this.completeAfter3ds(payment.id);\n return this.pollUntilDone(payment.id);\n } catch (e) {\n return { status: 'failed', error: e instanceof Error ? e.message : 'Stripe Radar failed', payment };\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 // A pre-authorisation that may never be captured is not a purchase (contract \u00A77.4).\n if (status.status === 'succeeded') {\n this.emitPaid(status.order?.id, status as unknown as PayResult['payment']);\n }\n return { status: 'succeeded', payment: status as unknown as PayResult['payment'], order: status.order };\n }\n\n // Ocean writes `rejected` on a decline; `error` never recovers either.\n if (FAILED_PAYMENT_STATUSES.has(status.status)) {\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: Payments API (V3) stores\n // ---------------------------------------------------------------------------\n\n /** Keeps what a V3 pay answer does not say (its session, the method); returns the answer as is. */\n private rememberPaymentsApiStart(\n answer: PayResult,\n opts: { checkoutSessionId: string; paymentMethod?: string },\n ): PayResult {\n const started = answer && !answer.payment ? readStartedPayment(answer) : null;\n if (started) {\n this.paymentsApiStarts.set(started.paymentId, {\n checkoutSessionId: started.checkoutSessionId ?? opts.checkoutSessionId,\n ...(opts.paymentMethod ? { paymentMethod: opts.paymentMethod } : {}),\n });\n }\n return answer;\n }\n\n /** Confirms a started V3 payment with payments-js and runs it to the V2-shaped result. */\n private finalizeOnPaymentsApi(started: StartedPayment, returnUrl: string | undefined): Promise<ProcessPaymentResult> {\n const known = this.paymentsApiStarts.get(started.paymentId);\n this.paymentsApiStarts.delete(started.paymentId);\n return this.onPaymentsApi((flow, host) =>\n flow.finalizeOnPaymentsApi(host, started, {\n checkoutSessionId: known?.checkoutSessionId,\n paymentMethod: known?.paymentMethod,\n returnUrl,\n }),\n );\n }\n\n /** Runs `run` with the lazily imported V3 flow; a flow that cannot load is a failed payment. */\n private async onPaymentsApi(\n run: (\n flow: typeof import('../helpers/paymentsApi.js'),\n host: import('../helpers/paymentsApi.js').PaymentsApiHost,\n ) => Promise<ProcessPaymentResult>,\n ): Promise<ProcessPaymentResult> {\n let flow: typeof import('../helpers/paymentsApi.js');\n try {\n flow = await loadPaymentsApiFlow();\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n }\n return run(flow, {\n http: this.http,\n storeId: this.storeId,\n checkout: this.checkout,\n stepConfig: this.readInjectedStepConfigRaw(),\n onPaid: (orderId, payment) => this.emitPaid(orderId, payment),\n });\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 /** The whole injected step config (Tagada-hosted pages), or null. */\n private readInjectedStepConfigRaw(): unknown {\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 return typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n return null;\n }\n }\n\n /** Tracking hook. Never throws, never awaits: a pixel must not be able to break a payment. */\n private emitPaid(orderId: string | undefined, payment: { amount?: number; currency?: string }): void {\n if (!orderId || !this.onPaid) return;\n try {\n const session = this.checkout?.getCurrentSession();\n this.onPaid({\n orderId,\n amount: payment.amount,\n currency: payment.currency,\n items: toContents(session?.items),\n });\n } catch {\n /* swallowed */\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 (cause) {\n // `lib` is ES2020 here: no two-argument Error constructor, so `cause` is attached by hand.\n const error = new Error(\n 'This method requires @tagadapay/core-js. Install it: npm install @tagadapay/core-js',\n );\n (error as Error & { cause?: unknown }).cause = cause;\n throw error;\n }\n }\n}\n", "import type { CustomerPortalModule } from './portal/index.js';\nimport type { CustomerModule } from './customer.js';\nimport type { OffersModule } from './offers.js';\n\ndeclare const __TGD_COMMERCE_CDN__: string;\ntype Commerce = { CustomerPortalModule: typeof CustomerPortalModule; OffersModule: typeof OffersModule; CustomerModule: typeof CustomerModule };\ndeclare global { interface Window { TagadaHeadlessCommerce?: Commerce } }\nconst script = typeof document === 'undefined' ? null : document.currentScript as HTMLScriptElement | null;\nconst url = script?.src ? new URL('tagada-headless-commerce.min.js', script.src).href : __TGD_COMMERCE_CDN__;\nlet loading: Promise<Commerce> | undefined;\n\nexport function loadCommerce(): Promise<Commerce> {\n if (window.TagadaHeadlessCommerce) return Promise.resolve(window.TagadaHeadlessCommerce);\n if (!loading) loading = new Promise<Commerce>((resolve, reject) => {\n const element = document.createElement('script');\n element.src = url; element.async = true;\n if (script?.nonce) element.nonce = script.nonce;\n element.addEventListener('load', () => window.TagadaHeadlessCommerce ? resolve(window.TagadaHeadlessCommerce) : reject(new Error('Commerce bundle did not initialize')));\n element.addEventListener('error', () => { element.remove(); reject(new Error('Unable to load commerce bundle')); });\n document.head.appendChild(element);\n }).catch(error => { loading = undefined; throw error; });\n return loading;\n}\n", "import {loadCommerce} from './lazyCommerce.js';\n export class OffersModule {\n constructor(...args){this.args=args}\n load(){return this.instance ||= loadCommerce().then(m=>new m.OffersModule(...this.args)).catch(e=>{this.instance=undefined;throw e})}\n }\n for(const method of [\"getOffer\",\"listOffers\",\"previewOffer\",\"enterFunnelStep\",\"payPreviewedOffer\",\"processOfferPayment\",\"toggleOrderBump\",\"listPostPurchaseOffers\",\"acceptPostPurchaseOffer\",\"declinePostPurchaseOffer\"]) OffersModule.prototype[method]=function(...args){return this.load().then(instance=>instance[method](...args))};", "import {loadCommerce} from './lazyCommerce.js';\n export class CustomerModule {\n constructor(...args){this.args=args}\n load(){return this.instance ||= loadCommerce().then(m=>new m.CustomerModule(...this.args)).catch(e=>{this.instance=undefined;throw e})}\n }\n for(const method of [\"getProfile\",\"getByEmail\",\"updateProfile\",\"getOrders\",\"getOrder\",\"getSubscriptions\",\"getSubscription\",\"pauseSubscription\",\"resumeSubscription\",\"skipSubscription\",\"rescheduleSubscription\",\"updateSubscriptionQuantity\",\"changeSubscriptionFrequency\",\"swapSubscriptionProduct\",\"updateSubscriptionPaymentMethod\",\"cancelSubscription\"]) CustomerModule.prototype[method]=function(...args){return this.load().then(instance=>instance[method](...args))};", "import {loadCommerce} from './lazyCommerce.js';\n export class CustomerPortalModule {\n constructor(...args){this.args=args}\n load(){return this.instance ||= loadCommerce().then(m=>new m.CustomerPortalModule(...this.args)).catch(e=>{this.instance=undefined;throw e})}\n }\n for(const method of [\"requestCode\",\"verifyCode\",\"getConfig\",\"getMe\",\"cancelFlow\",\"acceptCancelOffer\",\"switchOption\",\"getOffer\",\"acceptOffer\",\"addToNextOrder\",\"getCredits\",\"redeemCredits\",\"buyCreditPack\",\"requestEmailChangeCode\",\"updateProfile\",\"saveAddress\",\"removeAddress\",\"setDefaultAddress\",\"addCard\",\"removeCard\",\"setDefaultPaymentMethod\",\"retryPayment\",\"buyAgain\",\"joinMembership\",\"buyNow\",\"sendNow\",\"reactivateSubscription\",\"setSubscriptionCard\",\"setSubscriptionAddress\",\"skipDate\",\"unskipDate\"]) CustomerPortalModule.prototype[method]=function(...args){return this.load().then(instance=>instance[method](...args))};", "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 { TagadaError } from '../errors.js';\nimport type { HttpClient } from '../http.js';\nimport type {\n CheckoutSession,\n FunnelNavigateInput,\n FunnelNavigateResult,\n} from '../types.js';\nimport type { CheckoutModule } from './checkout.js';\n\n/**\n * Initialize a funnel session from the SDK's current cart and produce a\n * redirect URL into a funnel step.\n *\n * Mirrors the WooCommerce checkout plugin\n * (`public/assets/php/woocommerce/tagada-checkout-plugin.php`):\n *\n * 1. `POST /api/v1/cms/session/anonymous` \u2014 public, returns a CMS token.\n * 2. `POST /api/v1/cms/session/v2/init` \u2014 uses the token, returns a CMS customer id.\n * 3. `POST /api/v1/funnel/initialize` \u2014 creates the funnel session.\n * 4. `POST /api/v1/funnel/navigate` \u2014 fires an `INIT_CHECKOUT` event and returns `{ url }`.\n *\n * Steps 1\u20133 are cached on the module instance, so repeat `navigate()` calls in\n * the same page only fire step 4.\n *\n * **Prerequisite**: the SDK must have a loaded `CheckoutSession`\n * (`sdk.checkout.loadSession(...)`). The cart is sourced from `session.items`,\n * the currency from `session.currency`, the customer email from\n * `session.customer.email`, and the promotion code from `session.promotionCode`.\n */\nexport class FunnelModule {\n private _cmsToken: string | undefined;\n private _cmsSessionId: string | undefined;\n private _cmsCustomerId: string | undefined;\n\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly checkout: CheckoutModule,\n private readonly accountId: string | undefined,\n private readonly onFunnelSession?: (funnelSessionId: string) => void,\n ) {}\n\n async navigate(input: FunnelNavigateInput): Promise<FunnelNavigateResult> {\n const session = this.checkout.getCurrentSession();\n if (!session) {\n throw new TagadaError(\n 'No checkout session loaded. Call sdk.checkout.loadSession(...) before sdk.funnel.navigate(...).',\n 'no_cart_loaded',\n );\n }\n\n const accountId = input.accountId ?? this.accountId;\n if (!accountId) {\n throw new TagadaError(\n 'accountId is required for funnel.navigate(). Set it on createHeadlessClient({ accountId }) or pass it per call.',\n 'missing_account_id',\n );\n }\n\n const currentUrl =\n input.currentUrl ?? (typeof globalThis !== 'undefined' ? globalThis.location?.href : undefined);\n\n await this.ensureCmsSession(session, accountId, input);\n\n const funnelSessionId = await this.initializeFunnel({\n funnelId: input.funnelId,\n stepId: input.stepId,\n accountId,\n currentUrl,\n });\n\n try { this.onFunnelSession?.(funnelSessionId); } catch { /* Tracking cannot interrupt navigation. */ }\n\n const url = await this.runNavigate({\n funnelSessionId,\n stepId: input.stepId,\n session,\n input,\n currentUrl,\n });\n\n return { url, funnelSessionId };\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async ensureCmsSession(\n session: CheckoutSession,\n accountId: string,\n input: FunnelNavigateInput,\n ): Promise<void> {\n if (this._cmsToken && this._cmsSessionId && this._cmsCustomerId) return;\n\n const anon = await this.http.post<{ token: string; sessionId: string }>(\n '/api/v1/cms/session/anonymous',\n { storeId: this.storeId, role: 'anonymous', draft: false },\n );\n this._cmsToken = anon.token;\n this._cmsSessionId = anon.sessionId;\n\n const init = await this.http.post<{ customer: { id: string } }>(\n '/api/v1/cms/session/v2/init',\n {\n storeId: this.storeId,\n accountId,\n customerId: 'anon_placeholder',\n browserLocale: input.customer?.locale ?? defaultLocale(),\n userAgent: defaultUserAgent(),\n queryCurrency: input.customer?.currency ?? session.currency,\n queryLocale: input.customer?.locale,\n },\n { token: this._cmsToken },\n );\n\n this._cmsCustomerId = init.customer.id;\n }\n\n private async initializeFunnel(args: {\n funnelId: string;\n stepId: string;\n accountId: string;\n currentUrl: string | undefined;\n }): Promise<string> {\n const res = await this.http.post<{ context: { sessionId: string } }>(\n '/api/v1/funnel/initialize',\n {\n cmsSession: {\n customerId: this._cmsCustomerId,\n sessionId: this._cmsSessionId,\n storeId: this.storeId,\n accountId: args.accountId,\n },\n funnelId: args.funnelId,\n entryStepId: args.stepId,\n funnelStepId: args.stepId,\n currentUrl: args.currentUrl,\n draft: false,\n },\n { token: this._cmsToken },\n );\n return res.context.sessionId;\n }\n\n private async runNavigate(args: {\n funnelSessionId: string;\n stepId: string;\n session: CheckoutSession;\n input: FunnelNavigateInput;\n currentUrl: string | undefined;\n }): Promise<string> {\n const { funnelSessionId, stepId, session, input, currentUrl } = args;\n\n const lineItems = session.items.map((i) => ({\n variantId: i.variantId,\n priceId: i.priceId,\n quantity: i.quantity,\n }));\n\n const discountCodes =\n input.discountCodes ??\n (session.promotionCode ? [session.promotionCode] : undefined);\n\n const customer = {\n email: input.customer?.email ?? session.customer?.email,\n currency: input.customer?.currency ?? session.currency,\n locale: input.customer?.locale,\n };\n\n const res = await this.http.post<{ result: { url: string } }>(\n '/api/v1/funnel/navigate',\n {\n sessionId: funnelSessionId,\n currentUrl,\n funnelStepId: stepId,\n fireAndForget: false,\n event: {\n type: 'INIT_CHECKOUT',\n data: {\n checkoutInit: {\n cartToken: session.id,\n lineItems,\n customer,\n returnUrl: input.returnUrl,\n storeId: this.storeId,\n metadata: input.metadata,\n discountCodes,\n // Pins the session to this exact shipping amount when the caller's\n // storefront already settled one (#TAG-1785). Left undefined when\n // absent, so it is omitted from the JSON body and the platform\n // auto-selects a rate exactly as before.\n externalShipping: input.externalShipping,\n },\n },\n },\n },\n { token: this._cmsToken },\n );\n\n return res.result.url;\n }\n}\n\nfunction defaultLocale(): string {\n if (typeof navigator !== 'undefined' && navigator.language) return navigator.language;\n return 'en-US';\n}\n\nfunction defaultUserAgent(): string {\n if (typeof navigator !== 'undefined' && navigator.userAgent) return navigator.userAgent;\n return 'tagadapay-headless-sdk';\n}\n", "import type { HttpClient } from '../http.js';\n\n/**\n * Tagada Rx \u2014 storefront module.\n *\n * Drives the post-checkout clinical case flow from the browser:\n * 1. Ask the API whether a product needs an Rx case.\n * 2. After the order is paid, submit the intake (patient + answers)\n * with the `(orderId, checkoutToken)` ownership proof.\n * 3. Poll the case status from the thank-you page.\n *\n * PHI handling: the `patient` and `intakeAnswers` payloads are sent\n * straight to the Tagada API which forwards them to the clinical\n * network (e.g. MDI). Tagada NEVER persists PHI in its database.\n *\n * Auth model: there is no API key. Each route authorizes per-resource\n * (productId is public; case routes require the checkoutToken the\n * storefront already received when it bootstrapped the checkout).\n *\n * Rules: the server enforces the clinical network's contract on every\n * submit (US address and phone, required questions, offered options, MDI\n * demographics). Use `validateIntake` before payment and `isQuestionActive`\n * / `toIntakeAnswers` to render and send the questionnaire the same way.\n *\n * @example\n * ```ts\n * const { required } = await tagada.rx.isRequiredForProduct(productId);\n * if (required) {\n * // Before payment: US address, phone, ZIP, age.\n * const pre = await tagada.rx.validateIntake({ productId, patient });\n * if (!pre.valid) return showErrors(pre.issues);\n * // After payment: render the network questionnaire.\n * const { questions } = await tagada.rx.getQuestionsForProduct(productId, variantId);\n * const ctx = { state: patient.address.state, sexAtBirth: patient.sexAtBirth };\n * const shown = questions.filter((q) => isQuestionActive(q, answers, ctx));\n * // \u2026collect `answers` keyed by externalQuestionId\u2026\n * const res = await tagada.rx.submitCase({\n * orderId, checkoutToken, productId,\n * patient, intakeAnswers: toIntakeAnswers(questions, answers, ctx),\n * });\n * router.push(`/thank-you?rxCase=${res.rxCaseId}`);\n * }\n * ```\n */\nexport type RxCaseStatus =\n | 'requested'\n | 'submitted'\n | 'in_review'\n | 'approved'\n | 'shipped'\n | 'delivered'\n | 'declined'\n | 'cancelled'\n | 'error';\n\nexport interface RxRequiredForProduct {\n required: boolean;\n clinicalNetworkId: string | null;\n externalOfferingId: string | null;\n requiresLabs: boolean;\n requiresIdVerification: boolean;\n isDeaControlled: boolean;\n}\n\nexport interface RxStorefrontPatient {\n firstName: string;\n lastName: string;\n email: string;\n phone?: string | null;\n /** ISO date YYYY-MM-DD. */\n dateOfBirth: string;\n sexAtBirth: 'male' | 'female' | 'unspecified';\n address: {\n line1: string;\n line2?: string;\n city: string;\n state: string;\n zip: string;\n /** ISO 3166-1 alpha-2 country code. */\n country: string;\n };\n /** Patient-level clinical fields (MDI Full API / Judd). */\n weight?: number | string;\n height?: number | string;\n allergies?: string;\n pregnancy?: boolean | string;\n currentMedications?: string;\n medicalConditions?: string;\n specialNecessities?: string;\n driverLicenseId?: string;\n introVideoId?: string;\n}\n\nexport interface RxIntakeAnswer {\n questionId: string;\n value: string | number | boolean | string[];\n comment?: string;\n /** Exact question text shown to the patient (MDI case_questions.question). */\n question?: string;\n /** MDI answer type: string | number | boolean. */\n type?: string;\n important?: boolean;\n isCritical?: boolean;\n displayInPdf?: boolean;\n description?: string;\n label?: string;\n metadata?: string;\n /** Options presented for MCQ questions. */\n displayedOptions?: string[];\n}\n\n/** Display rule copied from the clinical network (see `isQuestionActive`). */\nexport interface RxClinicalQuestionRule {\n op: 'and' | 'or';\n requirements: Array<{\n /** `question`: answer to another question; `state`: shipping state; `other` + `patient_sex`: sex at birth. */\n basedOn: 'question' | 'state' | 'other';\n questionId: string | null;\n answer: string | null;\n }>;\n}\n\nexport interface RxClinicalQuestion {\n externalQuestionId: string;\n title: string;\n description: string | null;\n placeholder: string | null;\n type: string;\n required: boolean;\n order: number;\n options: { value: string; label: string; important?: boolean; critical?: boolean }[];\n /** `false` = clinician-side question: never show it, never ask it. */\n visible?: boolean;\n /** Show the question only when one rule matches (`isQuestionActive`). */\n rules?: RxClinicalQuestionRule[];\n important?: boolean;\n critical?: boolean;\n label?: string | null;\n /** Value the network fills itself for hidden questions; send it as is. */\n defaultValue?: string | null;\n}\n\n/** Answers keyed by `externalQuestionId`, as a storefront collects them. */\nexport type RxQuestionAnswers = Record<string, string | number | boolean | string[] | undefined>;\n\nexport interface RxIntakeContext {\n /** Shipping state, 2-letter code. */\n state?: string;\n sexAtBirth?: 'male' | 'female' | 'unspecified';\n}\n\nconst sameText = (a: unknown, b: string | null): boolean =>\n b !== null && String(a).trim().toLowerCase() === b.trim().toLowerCase();\n\n/**\n * Whether the patient must see (and answer) a question. Same rules the\n * server enforces on `submitCase`: hidden and file questions are never\n * shown; a question with rules shows when one rule matches the answers so\n * far, the shipping state or the patient's sex (e.g. \"Drug Allergies\" only\n * after \"Yes\", pregnancy only for women).\n */\nexport function isQuestionActive(\n question: RxClinicalQuestion,\n answers: RxQuestionAnswers,\n context: RxIntakeContext = {},\n): boolean {\n if (question.visible === false || question.type === 'file') return false;\n const rules = question.rules ?? [];\n if (rules.length === 0) return true;\n return rules.some((rule) => {\n const check = (req: RxClinicalQuestionRule['requirements'][number]) => {\n if (req.basedOn === 'state') return sameText(context.state ?? '', req.answer);\n if (req.basedOn === 'other' && req.questionId === 'patient_sex') return sameText(context.sexAtBirth ?? '', req.answer);\n if (req.basedOn === 'question' && req.questionId) {\n const v = answers[req.questionId];\n if (v === undefined) return false;\n return Array.isArray(v) ? v.some((x) => sameText(x, req.answer)) : sameText(v, req.answer);\n }\n return false;\n };\n return rule.op === 'and' ? rule.requirements.every(check) : rule.requirements.some(check);\n });\n}\n\n/**\n * Turn the answers a storefront collected into the `intakeAnswers` to\n * submit: active questions only, keyed by title (what the clinician\n * reads), with the options that were shown, and the network's default for\n * hidden questions. Plug and play with `submitCase` / `validateIntake`.\n */\nexport function toIntakeAnswers(\n questions: RxClinicalQuestion[],\n answers: RxQuestionAnswers,\n context: RxIntakeContext = {},\n): RxIntakeAnswer[] {\n const out: RxIntakeAnswer[] = [];\n for (const q of questions) {\n if (q.visible === false) {\n if (q.defaultValue) out.push({ questionId: q.title, question: q.title, value: q.defaultValue, type: 'string' });\n continue;\n }\n if (!isQuestionActive(q, answers, context)) continue;\n const value = answers[q.externalQuestionId];\n if (value === undefined || (typeof value === 'string' && value.trim() === '')) continue;\n out.push({\n questionId: q.title,\n question: q.title,\n value,\n type: q.type === 'number' ? 'number' : q.type === 'boolean' ? 'boolean' : 'string',\n ...(q.options.length > 0 ? { displayedOptions: q.options.map((o) => o.label) } : {}),\n });\n }\n return out;\n}\n\nexport interface RxIntakeIssue {\n field: string;\n message: string;\n}\n\nexport interface RxValidateIntakeInput {\n productId: string;\n variantId?: string;\n patient: {\n phone?: string | null;\n dateOfBirth: string;\n sexAtBirth: 'male' | 'female' | 'unspecified';\n address: { state: string; zip: string; country: string };\n };\n intakeAnswers?: RxIntakeAnswer[];\n}\n\nexport interface RxQuestionsForProduct {\n required: boolean;\n externalQuestionnaireId: string | null;\n questions: RxClinicalQuestion[];\n}\n\nexport interface RxSubmitCaseInput {\n orderId: string;\n checkoutToken: string;\n productId: string;\n patient: RxStorefrontPatient;\n intakeAnswers: RxIntakeAnswer[];\n preferredPharmacyId?: string;\n}\n\nexport interface RxSubmitCaseResult {\n rxCaseId: string;\n externalCaseId: string;\n status: 'submitted' | 'error';\n accrualAmountMinor: number;\n accrualCurrency: string;\n}\n\n/** Basics Tagada already holds on the order. Never date of birth or sex at birth. */\nexport interface RxIntakeContextPatient {\n firstName: string | null;\n lastName: string | null;\n email: string | null;\n phone: string | null;\n address: {\n line1: string | null;\n line2: string | null;\n city: string | null;\n state: string | null;\n zip: string | null;\n country: string | null;\n } | null;\n}\n\n/**\n * What a thank-you page needs to resume an unfinished intake, or\n * `{ caseExists: true }` once a case is in (show its status instead).\n */\nexport type RxIntakeContextResult =\n | { caseExists: true }\n | {\n caseExists: false;\n orderId: string;\n storeId: string;\n productId: string;\n variantId: string | null;\n patient: RxIntakeContextPatient;\n };\n\nexport interface RxCaseSummary {\n id: string;\n status: RxCaseStatus;\n externalCaseId: string | null;\n lastShipmentShippedAt: string | null;\n createdAt: string;\n}\n\nexport type RxActivationStepKey =\n | 'application'\n | 'approval'\n | 'payouts'\n | 'statement_descriptor'\n | 'storefront';\n\nexport type RxActivationMissingItem =\n | 'application'\n | 'approval'\n | 'payout_kyc'\n | 'payout_bank_account'\n | 'statement_descriptor'\n | 'statement_descriptor_rejected'\n | 'storefront'\n | 'partner_rx_option';\n\n/**\n * Tagada Rx activation status of a store.\n *\n * `payments` is `'ready'` once the brand's Rx payment account is live and its\n * payment flow is bound; `'setting_up'` before. It is a status, not a step:\n * there is nothing for the brand to do while payments are being set up.\n * The public storefront route leaves out payout verification and partner\n * contract items (`payouts`, `payout_*`, `partner_rx_option`).\n */\nexport interface RxActivationStatus {\n storeId: string;\n state: 'not_requested' | 'pending_review' | 'active';\n steps: { key: RxActivationStepKey; done: boolean }[];\n missing: RxActivationMissingItem[];\n payments: 'setting_up' | 'ready';\n descriptorStatus: 'none' | 'pending' | 'approved' | 'rejected';\n}\n\nexport class RxModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId?: string,\n ) {}\n\n /**\n * Activation status of the store: steps, missing items and whether Rx\n * payments are `setting_up` or `ready`. Storefronts use it to show\n * \"Payments are being set up\" instead of letting a checkout fail.\n *\n * Read-only / public. Defaults to the client's `storeId`.\n */\n async getActivationStatus(storeId?: string): Promise<RxActivationStatus> {\n const id = storeId ?? this.storeId;\n if (!id) throw new Error('rx.getActivationStatus: storeId is required');\n return this.http.get<RxActivationStatus>('/api/public/v1/rx/activation-status', {\n params: { storeId: id },\n });\n }\n\n /**\n * Check whether a product requires an Rx case. Storefronts call this\n * before rendering the intake form so they only ask the patient\n * questions when really necessary.\n *\n * Read-only / public \u2014 does not require any ownership proof.\n */\n async isRequiredForProduct(\n productId: string,\n opts?: { clinicalNetworkId?: string },\n ): Promise<RxRequiredForProduct> {\n return this.http.get<RxRequiredForProduct>('/api/public/v1/rx/required-for-product', {\n params: {\n productId,\n clinicalNetworkId: opts?.clinicalNetworkId,\n },\n });\n }\n\n /**\n * Look up the Rx cases attached to an order. Storefronts poll this\n * on the thank-you page to render \"Your prescription is being\n * reviewed\" \u2192 \"Shipped\" transitions.\n */\n async getCasesForOrder(input: {\n orderId: string;\n checkoutToken: string;\n }): Promise<{ cases: RxCaseSummary[] }> {\n return this.http.post<{ cases: RxCaseSummary[] }>(\n '/api/public/v1/rx/cases/lookup',\n input,\n );\n }\n\n /**\n * Resume an unfinished intake from `(orderId, checkoutToken)` alone: the\n * patient paid (card on hold) but the identity collected at checkout is\n * gone (tab closed, recovery email link, other device). Returns the Rx\n * line (`productId`, `variantId`) and the basics on the order; ask date of\n * birth and sex at birth again, render the questionnaire, then\n * `submitCase`. `{ caseExists: true }` means a case is already in: show\n * `getCasesForOrder`. Fails with 401 on a wrong token, 404 when the order\n * has no Rx line.\n */\n async getIntakeContext(input: { orderId: string; checkoutToken: string }): Promise<RxIntakeContextResult> {\n return this.http.post<RxIntakeContextResult>('/api/public/v1/rx/intake/context', input);\n }\n\n /**\n * Submit a fresh clinical case for a freshly-paid order. PHI is\n * forwarded to the clinical network and never persisted on\n * Tagada-side rows.\n */\n async submitCase(input: RxSubmitCaseInput): Promise<RxSubmitCaseResult> {\n return this.http.post<RxSubmitCaseResult>('/api/public/v1/rx/cases/submit', input);\n }\n\n /**\n * Check the patient (and, once filled, the intake) against the clinical\n * network rules before paying / submitting: US address in the 50 states\n * or DC, US phone, 5 digit ZIP, adult, every active required question\n * answered with an offered option. `submitCase` enforces the same rules\n * and fails with 422 otherwise. Nothing is created.\n */\n async validateIntake(input: RxValidateIntakeInput): Promise<{ valid: boolean; issues: RxIntakeIssue[] }> {\n return this.http.post<{ valid: boolean; issues: RxIntakeIssue[] }>('/api/public/v1/rx/intake/validate', input);\n }\n\n /**\n * Fetch the network-authored intake questions for a product. Render\n * every question for which `isQuestionActive` is true, build the payload\n * with `toIntakeAnswers`. Empty `questions` means the product has no\n * clinical questionnaire: never replace a network questionnaire with your own.\n */\n async getQuestionsForProduct(\n productId: string,\n variantId?: string,\n ): Promise<RxQuestionsForProduct> {\n return this.http.get<RxQuestionsForProduct>('/api/public/v1/rx/questions-for-product', {\n params: variantId ? { productId, variantId } : { productId },\n });\n }\n}\n", "import type { JsonValue, TgdBootstrap, TgdPublicApi } from '../../tgd/contract/index.js';\n\ntype Subscriber = { key: string; cb: (variant: string | null) => void };\n\n/** Lazy facade. Only the shared tgd runtime evaluates assignments and emits exposures. */\nexport class ExperimentsModule {\n private runtime: TgdPublicApi | null = null;\n private loading: Promise<void> | null = null;\n private settled = false;\n private readonly reads = new Set<string>();\n private readonly subscribers: Subscriber[] = [];\n\n constructor(private readonly core: () => Promise<TgdPublicApi | null>, private readonly bootstrap?: TgdBootstrap) {}\n\n private variant(key: string): string | null {\n return this.bootstrap?.experiments[key]?.arm ?? this.bootstrap?.flags[key]?.variant ?? null;\n }\n\n private start(): Promise<void> {\n if (typeof window === 'undefined') return Promise.resolve();\n this.loading ??= (async () => {\n try { this.runtime = await this.core(); } catch { /* Fall back to bootstrap. */ }\n this.settled = true;\n const runtime = this.runtime;\n for (const key of this.reads) {\n try { runtime?.getVariant(key); } catch { /* Runtime failures cannot interrupt the merchant. */ }\n }\n this.reads.clear();\n for (const { key, cb } of this.subscribers.splice(0)) {\n try { if (runtime) runtime.onVariant(key, cb); else cb(this.variant(key)); } catch { /* Isolate subscribers. */ }\n }\n try { await runtime?.ready(); } catch { /* Offline assignment is a settled facade. */ }\n })();\n return this.loading;\n }\n\n private read(key: string): void {\n if (!this.settled) this.reads.add(key);\n void this.start();\n }\n\n getVariant(key: string): string | null {\n if (this.runtime) return this.runtime.getVariant(key);\n this.read(key);\n return this.variant(key);\n }\n\n getPayload(key: string): JsonValue | null {\n if (this.runtime) return this.runtime.getPayload(key);\n this.read(key);\n return this.bootstrap?.experiments[key]?.payload ?? this.bootstrap?.flags[key]?.payload ?? null;\n }\n\n isEnabled(flagKey: string): boolean {\n if (this.runtime) return this.runtime.isEnabled(flagKey);\n this.read(flagKey);\n return this.bootstrap?.flags[flagKey]?.enabled ?? false;\n }\n\n onVariant(key: string, cb: (variant: string | null) => void): void {\n if (this.runtime) { this.runtime.onVariant(key, cb); return; }\n if (this.settled) { cb(this.variant(key)); return; }\n this.subscribers.push({ key, cb });\n void this.start();\n }\n\n ready(): Promise<void> { return this.start(); }\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 { CustomerPortalModule } from './modules/portal/index.js';\nimport { CatalogModule } from './modules/catalog.js';\nimport { FunnelModule } from './modules/funnel.js';\nimport { RxModule } from './modules/rx.js';\nimport { ExperimentsModule } from './modules/experiments.js';\nimport { TrackModule, toContents } from './modules/track.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 /** Customer portal -- login code, portal config, the customer, retention, credits. */\n readonly portal: CustomerPortalModule;\n\n /** Product catalog -- list products, variants, and prices. */\n readonly catalog: CatalogModule;\n\n /**\n * Funnel navigation -- bootstrap an anonymous CMS session and produce a\n * redirect URL into a funnel step using the currently loaded checkout cart.\n * Requires `config.accountId`.\n */\n readonly funnel: FunnelModule;\n\n /**\n * Tagada Rx -- clinical case submission and lookup for telehealth\n * storefronts. Active only on stores whose merchant has paid the\n * Tagada Rx setup fee and configured a clinical network.\n */\n readonly rx: RxModule;\n\n /**\n * Coded-funnel tracking -- report steps and events from your own code, and fire\n * the browser pixels bound to them on the Tagada canvas. Inert until\n * `track.step()` is called once.\n */\n readonly track: TrackModule;\n readonly experiments: ExperimentsModule;\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 this.track = new TrackModule(baseUrl, this.config.storeId, this.config.funnel ?? 'main');\n this.track.bootstrap = this.config.bootstrap;\n this.experiments = new ExperimentsModule(() => this.track.core(), this.config.bootstrap);\n\n const setToken = (token: string) => {\n this._sessionToken = token;\n };\n\n this.checkout = new CheckoutModule(this.http, this.config.storeId, setToken, (s) =>\n this.track.noteCheckout({\n checkoutSessionId: s.id,\n amount: s.totals.total,\n currency: s.totals.currency,\n items: toContents(s.items),\n }),\n );\n // The checkout module is handed to payments so express wallets can persist\n // the contact they collect in the sheet before charging (#TAG-1989).\n this.payment = new PaymentModule(\n this.http,\n this.config.storeId,\n environment,\n this.checkout,\n (p) => this.track.notePaid(p),\n (v, d) => this.track.noteSignal('wallet_unavailable', v, d),\n );\n this.offers = new OffersModule(this.http, this.config.storeId, this.payment);\n this.customer = new CustomerModule(this.http, this.config.storeId);\n this.portal = new CustomerPortalModule(this.http, this.config.storeId, setToken);\n this.catalog = new CatalogModule(this.http, this.config.storeId);\n this.funnel = new FunnelModule(\n this.http,\n this.config.storeId,\n this.checkout,\n this.config.accountId,\n (id) => this.track.noteFunnelSession(id),\n );\n this.rx = new RxModule(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", "/**\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 * 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
|
+
"names": ["core_exports", "__export", "AVAILABLE_LANGUAGES", "CRYPTO_ONCHAIN_FINAL_PHASES", "CRYPTO_ONCHAIN_PAYMENT_METHOD", "CRYPTO_ONCHAIN_STATUS_POLL_MS", "CatalogModule", "CheckoutModule", "CryptoOnchainCheckout", "CurrencyUtils", "CustomerModule", "CustomerPortalModule", "ExperimentsModule", "FunnelModule", "GoogleAutocompleteCore", "HeadlessClient", "HttpClient", "ISODataCore", "OffersModule", "PaymentModule", "RxModule", "TagadaAuthError", "TagadaError", "TagadaNetworkError", "TagadaNotFoundError", "TagadaPaymentError", "TagadaRateLimitError", "TagadaValidationError", "TrackModule", "createHeadlessClient", "cryptoOnchainPhase", "cryptoOnchainSecondsLeft", "defaultCryptoOnchainSelection", "ensureGeoDataLoaded", "formatCryptoOnchainCountdown", "formatMoney", "getCountries", "getStatesForCountry", "isCryptoOnchainMethod", "isLanguageLoaded", "isQuestionActive", "loadGoogleMapsScript", "parseTokensFromUrl", "selectCryptoOnchainNetwork", "toIntakeAnswers", "TagadaError", "message", "code", "statusCode", "details", "TagadaAuthError", "TagadaValidationError", "errors", "appCode", "TagadaNotFoundError", "resource", "id", "TagadaRateLimitError", "retryAfterMs", "TagadaPaymentError", "opts", "TagadaNetworkError", "SDK_NAME", "SDK_VERSION", "BASE_URLS", "HttpClient", "config", "environment", "override", "path", "options", "_a", "method", "body", "headers", "params", "token", "signal", "url", "qs", "k", "v", "str", "reqHeaders", "SDK_VERSION", "authToken", "controller", "timeoutId", "res", "text", "TagadaError", "err", "TagadaNetworkError", "parsed", "data", "parseErrorData", "msg", "appCode", "TagadaAuthError", "TagadaNotFoundError", "fieldErrors", "TagadaValidationError", "retryAfter", "TagadaRateLimitError", "value", "CheckoutModule", "_CheckoutModule", "http", "storeId", "onTokenChange", "onSession", "checkoutToken", "sessionToken", "opts", "_a", "_b", "params", "raw", "session", "_c", "lineItems", "i", "body", "customerData", "res", "checkoutPath", "originOverride", "sessionOpts", "origin", "url", "href", "parsed", "sessionId", "items", "customer", "addresses", "shipping", "billing", "effectiveShipping", "effectiveBilling", "differentBilling", "data", "a", "stripEmpty", "code", "promotionId", "promoId", "r", "rateId", "cs", "orderSummaries", "summary", "sessionCurrency", "li", "price", "variant", "product", "currencyOpts", "priceEntry", "amount", "summaryItems", "s", "out", "v", "parseTokensFromUrl", "obj", "result", "k", "applePayContactToAddress", "contact", "_a", "_b", "address", "isUsable", "googlePayContactToAddress", "firstName", "rest", "isUsable", "address", "_a", "_b", "CDN_URL", "loadScript", "src", "isReady", "resolve", "reject", "script", "loadPixels", "w", "FLAG_KEY", "ANON_KEY", "SESSION_KEY", "QUEUE_LIMIT", "FLUSH_MS", "DEDUP_MS", "STEP_MEMORY", "toContents", "items", "item", "scalars", "data", "out", "key", "value", "STANDARD_EVENTS", "uuid", "toPixelsConfig", "pixels", "pixel", "provider", "id", "idKey", "rest", "TrackModule", "baseUrl", "storeId", "funnelKey", "stepId", "path", "at", "previous", "engine", "t", "name", "standard", "eventId", "seen", "when", "oldest", "who", "state", "input", "event", "_a", "signal", "detail", "SDK_NAME", "SDK_VERSION", "url", "response", "config", "_b", "base", "funnelSessionId", "module", "onLeave", "record", "scope", "store", "existing", "fresh", "records", "payload", "body", "CRYPTO_ONCHAIN_PAYMENT_METHOD", "CRYPTO_ONCHAIN_STATUS_POLL_MS", "CRYPTO_ONCHAIN_FINAL_PHASES", "isCryptoOnchainMethod", "method", "defaultCryptoOnchainSelection", "networks", "usable", "network", "candidate", "asset", "selectCryptoOnchainNetwork", "chainId", "currentAsset", "_a", "_b", "assets", "keep", "fallback", "cryptoOnchainPhase", "status", "cryptoOnchainSecondsLeft", "expiresAt", "nowMs", "end", "formatCryptoOnchainCountdown", "seconds", "s", "h", "m", "sec", "UNAVAILABLE", "CryptoOnchainCheckout", "api", "options", "listener", "payment", "paymentStatus", "phase", "result", "selection", "error", "messageOf", "next", "current", "target", "message", "_c", "patch", "readStartedPayment", "answer", "payment", "order", "paymentId", "clientSecret", "amount", "currency", "checkoutSessionId", "radar", "radarKey", "key", "PENDING_KEY", "PENDING_TTL_MS", "takeParkedPaymentsApiReturn", "paymentId", "raw", "PENDING_KEY", "parked", "PENDING_TTL_MS", "loadStripeJs", "fromPage", "loaded", "resolve", "reject", "script", "stripe", "OCEAN_SDK_URL", "OCEAN_CONTAINER_ID", "OCEAN_LANGUAGE_OVERRIDES", "oceanLanguage", "locale", "_a", "primary", "OCEAN_SDK_LOAD_TIMEOUT_MS", "oceanSdkLoading", "loadOceanSdk", "w", "resolve", "reject", "script", "fail", "message", "timer", "OCEAN_SDK_URL", "OCEAN_PENDING_KEY", "OCEAN_PENDING_TTL_MS", "parkOceanPayment", "paymentId", "takeParkedOceanPayment", "raw", "at", "restoreOceanPaymentReturn", "url", "loadPaymentsApiFlow", "FAILED_PAYMENT_STATUSES", "oceanSlot", "oceanSlotTaken", "OCEAN_TIMED_OUT", "OCEAN_UNMOUNTED", "EXPRESS_METHOD_TYPES", "paymentMethodListEntryToConfig", "entry", "_a", "isCard", "method", "settings", "processors", "publishableKey", "PaymentModule", "http", "storeId", "environment", "checkout", "onPaid", "onSignal", "checkoutSessionId", "opts", "injected", "res", "config", "err", "TagadaNotFoundError", "entries", "m", "key", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "setup", "result", "base", "hasApplePay", "c", "card", "coreJs", "tokenizer", "sanitized", "rawToken", "contact", "shippingAddress", "billingAddress", "customer", "applePayContactToAddress", "merchantRegistrationId", "tagadaToken", "host", "fromConfig", "map", "hit", "local", "googlePayContactToAddress", "CryptoOnchainCheckout", "data", "signal", "aborted", "OCEAN_CONTAINER_ID", "w", "element", "slot", "releaseSlot", "mounted", "pendingCallback", "callback", "resolve", "unmount", "ocean", "loadOceanSdk", "error", "submitting", "sdk", "backUrl", "oceanLanguage", "created", "paymentId", "answer", "timer", "parkOceanPayment", "payResult", "input", "payment", "returnUrl", "started", "readStartedPayment", "parked", "takeParkedPaymentsApiReturn", "url", "flow", "restoreOceanPaymentReturn", "href", "action", "actionStatus", "cleanParams", "k", "search", "interval", "timeout", "start", "status", "r", "actionData", "redirect", "session", "manager", "radar", "Stripe", "loadStripeJs", "radarSession", "e", "consecutiveErrors", "known", "run", "orderId", "raw", "parsed", "toContents", "cause", "script", "url", "loading", "loadCommerce", "resolve", "reject", "element", "error", "OffersModule", "args", "loadCommerce", "m", "method", "instance", "CustomerModule", "args", "loadCommerce", "m", "method", "instance", "CustomerPortalModule", "args", "loadCommerce", "m", "method", "instance", "CatalogModule", "http", "storeId", "opts", "_a", "_b", "body", "productId", "FunnelModule", "http", "storeId", "checkout", "accountId", "onFunnelSession", "input", "_a", "_b", "session", "TagadaError", "currentUrl", "funnelSessionId", "_c", "anon", "init", "defaultLocale", "defaultUserAgent", "args", "_d", "stepId", "lineItems", "i", "discountCodes", "customer", "sameText", "a", "b", "isQuestionActive", "question", "answers", "context", "rules", "rule", "check", "req", "v", "x", "toIntakeAnswers", "questions", "out", "q", "value", "RxModule", "http", "storeId", "id", "productId", "opts", "input", "variantId", "ExperimentsModule", "core", "bootstrap", "key", "_a", "_b", "_c", "_d", "runtime", "cb", "flagKey", "HeadlessClient", "config", "environment", "baseUrl", "HttpClient", "TrackModule", "ExperimentsModule", "setToken", "token", "CheckoutModule", "s", "toContents", "PaymentModule", "p", "v", "d", "OffersModule", "CustomerModule", "CustomerPortalModule", "CatalogModule", "FunnelModule", "id", "RxModule", "createHeadlessClient", "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", "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", "r", "regionCode", "googleState", "googleStateLong", "regions", "match", "isLanguageLoaded", "AVAILABLE_LANGUAGES", "SYMBOLS", "NAMES", "ZERO_DECIMAL", "CurrencyUtils", "_CurrencyUtils", "code", "formatMoney", "amountMinorUnits", "currencyCode", "locale", "decimals", "value"]
|
|
7
7
|
}
|