@tagadapay/headless-sdk 1.16.0 → 1.17.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.
Files changed (150) hide show
  1. package/dist/core/client.d.ts +5 -0
  2. package/dist/core/client.d.ts.map +1 -1
  3. package/dist/core/client.js +6 -1
  4. package/dist/core/client.js.map +1 -1
  5. package/dist/core/http.d.ts +2 -0
  6. package/dist/core/http.d.ts.map +1 -1
  7. package/dist/core/http.js +21 -5
  8. package/dist/core/http.js.map +1 -1
  9. package/dist/core/index.d.ts +4 -0
  10. package/dist/core/index.d.ts.map +1 -1
  11. package/dist/core/index.js +2 -0
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/core/modules/checkout.d.ts.map +1 -1
  14. package/dist/core/modules/checkout.js +12 -0
  15. package/dist/core/modules/checkout.js.map +1 -1
  16. package/dist/core/modules/commerce.d.ts +4 -0
  17. package/dist/core/modules/commerce.d.ts.map +1 -0
  18. package/dist/core/modules/commerce.js +5 -0
  19. package/dist/core/modules/commerce.js.map +1 -0
  20. package/dist/core/modules/customer.d.ts +47 -1
  21. package/dist/core/modules/customer.d.ts.map +1 -1
  22. package/dist/core/modules/customer.js +60 -3
  23. package/dist/core/modules/customer.js.map +1 -1
  24. package/dist/core/modules/experiments.d.ts +21 -0
  25. package/dist/core/modules/experiments.d.ts.map +1 -0
  26. package/dist/core/modules/experiments.js +85 -0
  27. package/dist/core/modules/experiments.js.map +1 -0
  28. package/dist/core/modules/funnel.d.ts +2 -1
  29. package/dist/core/modules/funnel.d.ts.map +1 -1
  30. package/dist/core/modules/funnel.js +6 -1
  31. package/dist/core/modules/funnel.js.map +1 -1
  32. package/dist/core/modules/lazyCommerce.d.ts +16 -0
  33. package/dist/core/modules/lazyCommerce.d.ts.map +1 -0
  34. package/dist/core/modules/lazyCommerce.js +20 -0
  35. package/dist/core/modules/lazyCommerce.js.map +1 -0
  36. package/dist/core/modules/offers.d.ts +30 -5
  37. package/dist/core/modules/offers.d.ts.map +1 -1
  38. package/dist/core/modules/offers.js +66 -7
  39. package/dist/core/modules/offers.js.map +1 -1
  40. package/dist/core/modules/portal/index.d.ts +102 -0
  41. package/dist/core/modules/portal/index.d.ts.map +1 -0
  42. package/dist/core/modules/portal/index.js +166 -0
  43. package/dist/core/modules/portal/index.js.map +1 -0
  44. package/dist/core/modules/portal/types.d.ts +617 -0
  45. package/dist/core/modules/portal/types.d.ts.map +1 -0
  46. package/dist/core/modules/portal/types.js +11 -0
  47. package/dist/core/modules/portal/types.js.map +1 -0
  48. package/dist/core/modules/track.d.ts +8 -0
  49. package/dist/core/modules/track.d.ts.map +1 -1
  50. package/dist/core/modules/track.js +49 -8
  51. package/dist/core/modules/track.js.map +1 -1
  52. package/dist/core/types.d.ts +11 -0
  53. package/dist/core/types.d.ts.map +1 -1
  54. package/dist/core/types.js +0 -3
  55. package/dist/core/types.js.map +1 -1
  56. package/dist/core/version.d.ts +1 -1
  57. package/dist/core/version.js +1 -1
  58. package/dist/pixels/pixelTracker.d.ts.map +1 -1
  59. package/dist/pixels/pixelTracker.js +4 -2
  60. package/dist/pixels/pixelTracker.js.map +1 -1
  61. package/dist/tagada-headless-commerce.min.js +8 -0
  62. package/dist/tagada-headless-commerce.min.js.map +7 -0
  63. package/dist/tagada-headless-react.min.js +2 -2
  64. package/dist/tagada-headless-react.min.js.map +4 -4
  65. package/dist/tagada-headless.js +299 -288
  66. package/dist/tagada-headless.min.js +2 -2
  67. package/dist/tagada-headless.min.js.map +4 -4
  68. package/dist/tagada-pixels.min.js +2 -2
  69. package/dist/tagada-pixels.min.js.map +3 -3
  70. package/dist/tgd/contract/attribution.d.ts +28 -0
  71. package/dist/tgd/contract/attribution.d.ts.map +1 -0
  72. package/dist/tgd/contract/attribution.js +44 -0
  73. package/dist/tgd/contract/attribution.js.map +1 -0
  74. package/dist/tgd/contract/browser-api.d.ts +57 -0
  75. package/dist/tgd/contract/browser-api.d.ts.map +1 -0
  76. package/dist/tgd/contract/browser-api.js +2 -0
  77. package/dist/tgd/contract/browser-api.js.map +1 -0
  78. package/dist/tgd/contract/canvas.d.ts +120 -0
  79. package/dist/tgd/contract/canvas.d.ts.map +1 -0
  80. package/dist/tgd/contract/canvas.js +12 -0
  81. package/dist/tgd/contract/canvas.js.map +1 -0
  82. package/dist/tgd/contract/dedup-keys.d.ts +24 -0
  83. package/dist/tgd/contract/dedup-keys.d.ts.map +1 -0
  84. package/dist/tgd/contract/dedup-keys.js +23 -0
  85. package/dist/tgd/contract/dedup-keys.js.map +1 -0
  86. package/dist/tgd/contract/destination-names.d.ts +4 -0
  87. package/dist/tgd/contract/destination-names.d.ts.map +1 -0
  88. package/dist/tgd/contract/destination-names.js +66 -0
  89. package/dist/tgd/contract/destination-names.js.map +1 -0
  90. package/dist/tgd/contract/destinations.d.ts +124 -0
  91. package/dist/tgd/contract/destinations.d.ts.map +1 -0
  92. package/dist/tgd/contract/destinations.js +63 -0
  93. package/dist/tgd/contract/destinations.js.map +1 -0
  94. package/dist/tgd/contract/envelope.d.ts +203 -0
  95. package/dist/tgd/contract/envelope.d.ts.map +1 -0
  96. package/dist/tgd/contract/envelope.js +103 -0
  97. package/dist/tgd/contract/envelope.js.map +1 -0
  98. package/dist/tgd/contract/experiments.d.ts +87 -0
  99. package/dist/tgd/contract/experiments.d.ts.map +1 -0
  100. package/dist/tgd/contract/experiments.js +2 -0
  101. package/dist/tgd/contract/experiments.js.map +1 -0
  102. package/dist/tgd/contract/index.d.ts +20 -0
  103. package/dist/tgd/contract/index.d.ts.map +1 -0
  104. package/dist/tgd/contract/index.js +20 -0
  105. package/dist/tgd/contract/index.js.map +1 -0
  106. package/dist/tgd/contract/is-test.d.ts +2 -0
  107. package/dist/tgd/contract/is-test.d.ts.map +1 -0
  108. package/dist/tgd/contract/is-test.js +3 -0
  109. package/dist/tgd/contract/is-test.js.map +1 -0
  110. package/dist/tgd/contract/junk-ids.d.ts +4 -0
  111. package/dist/tgd/contract/junk-ids.d.ts.map +1 -0
  112. package/dist/tgd/contract/junk-ids.js +7 -0
  113. package/dist/tgd/contract/junk-ids.js.map +1 -0
  114. package/dist/tgd/contract/limits.d.ts +19 -0
  115. package/dist/tgd/contract/limits.d.ts.map +1 -0
  116. package/dist/tgd/contract/limits.js +20 -0
  117. package/dist/tgd/contract/limits.js.map +1 -0
  118. package/dist/tgd/contract/names.d.ts +13 -0
  119. package/dist/tgd/contract/names.d.ts.map +1 -0
  120. package/dist/tgd/contract/names.js +15 -0
  121. package/dist/tgd/contract/names.js.map +1 -0
  122. package/dist/tgd/contract/registry.d.ts +116 -0
  123. package/dist/tgd/contract/registry.d.ts.map +1 -0
  124. package/dist/tgd/contract/registry.js +59 -0
  125. package/dist/tgd/contract/registry.js.map +1 -0
  126. package/dist/tgd/contract/signed-ids.d.ts +33 -0
  127. package/dist/tgd/contract/signed-ids.d.ts.map +1 -0
  128. package/dist/tgd/contract/signed-ids.js +26 -0
  129. package/dist/tgd/contract/signed-ids.js.map +1 -0
  130. package/dist/tgd/contract/snapshots.d.ts +69 -0
  131. package/dist/tgd/contract/snapshots.d.ts.map +1 -0
  132. package/dist/tgd/contract/snapshots.js +2 -0
  133. package/dist/tgd/contract/snapshots.js.map +1 -0
  134. package/dist/tgd/contract/time.d.ts +9 -0
  135. package/dist/tgd/contract/time.d.ts.map +1 -0
  136. package/dist/tgd/contract/time.js +9 -0
  137. package/dist/tgd/contract/time.js.map +1 -0
  138. package/dist/tgd/contract/unions.d.ts +21 -0
  139. package/dist/tgd/contract/unions.d.ts.map +1 -0
  140. package/dist/tgd/contract/unions.js +17 -0
  141. package/dist/tgd/contract/unions.js.map +1 -0
  142. package/dist/tgd/contract/unit.d.ts +12 -0
  143. package/dist/tgd/contract/unit.d.ts.map +1 -0
  144. package/dist/tgd/contract/unit.js +18 -0
  145. package/dist/tgd/contract/unit.js.map +1 -0
  146. package/dist/tgd/contract/wire.d.ts +59 -0
  147. package/dist/tgd/contract/wire.d.ts.map +1 -0
  148. package/dist/tgd/contract/wire.js +2 -0
  149. package/dist/tgd/contract/wire.js.map +1 -0
  150. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/core/index.ts", "../src/core/errors.ts", "../src/core/http.ts", "../src/core/modules/checkout.ts", "../src/core/helpers/walletContact.ts", "../src/core/version.ts", "../src/core/modules/track.ts", "../src/core/modules/payment.ts", "../src/core/modules/offers.ts", "../src/core/modules/customer.ts", "../src/core/modules/catalog.ts", "../src/core/modules/funnel.ts", "../src/core/modules/rx.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 { CatalogModule } from './modules/catalog.js';\nexport { FunnelModule } from './modules/funnel.js';\nexport { RxModule } 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 RxQuestionsForProduct,\n RxSubmitCaseInput,\n RxSubmitCaseResult,\n RxCaseSummary,\n RxActivationStatus,\n RxActivationStepKey,\n RxActivationMissingItem,\n} from './modules/rx.js';\n\nexport { HttpClient } from './http.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 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", "/** 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", "import {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaNetworkError,\n} from './errors.js';\nimport type { Environment, HttpRequestOptions } from './types.js';\n\nconst BASE_URLS: Record<Environment, string> = {\n production: 'https://api.tagada.io',\n development: 'https://api.tagada.dev',\n local: 'http://localhost:3000',\n};\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n apiKey?: string;\n getToken?: () => string | undefined;\n}\n\n/**\n * Lightweight HTTP client built on native fetch.\n * Zero dependencies -- works in browser, edge runtimes, and Node 18+.\n */\nexport class HttpClient {\n readonly baseUrl: string;\n private timeout: number;\n private apiKey?: string;\n private getToken?: () => string | undefined;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.timeout = config.timeout;\n this.apiKey = config.apiKey;\n this.getToken = config.getToken;\n }\n\n static resolveBaseUrl(environment: Environment, override?: string): string {\n return override ?? BASE_URLS[environment] ?? BASE_URLS.production;\n }\n\n async request<T = unknown>(path: string, options: HttpRequestOptions = {}): Promise<T> {\n const { method = 'GET', body, headers = {}, params, token, signal } = options;\n\n let url = `${this.baseUrl}${path}`;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined) qs.set(k, String(v));\n }\n const str = qs.toString();\n if (str) url += `?${str}`;\n }\n\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...headers,\n };\n\n const authToken = token ?? this.apiKey ?? this.getToken?.();\n if (authToken) {\n reqHeaders['x-cms-token'] = authToken;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, {\n method,\n headers: reqHeaders,\n body: body != null ? JSON.stringify(body) : undefined,\n signal: signal ?? controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (res.ok) {\n const text = await res.text();\n return text ? (JSON.parse(text) as T) : ({} as T);\n }\n\n await this.handleErrorResponse(res, path);\n throw new TagadaError('Unexpected error', 'unknown', res.status);\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof TagadaError) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw new TagadaNetworkError(`Request to ${path} timed out after ${this.timeout}ms.`);\n }\n throw new TagadaNetworkError(\n err instanceof Error ? err.message : 'Network request failed.',\n );\n }\n }\n\n get<T = unknown>(path: string, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'GET' });\n }\n\n post<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'POST', body });\n }\n\n patch<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'PATCH', body });\n }\n\n put<T = unknown>(path: string, body?: unknown, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'PUT', body });\n }\n\n delete<T = unknown>(path: string, options?: HttpRequestOptions): Promise<T> {\n return this.request<T>(path, { ...options, method: 'DELETE' });\n }\n\n private async handleErrorResponse(res: Response, path: string): Promise<never> {\n let parsed: Record<string, unknown> = {};\n try {\n parsed = (await res.json()) as Record<string, unknown>;\n } catch {\n // response isn't JSON\n }\n\n // 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 const data = (parsed.data ?? {}) as Record<string, unknown>;\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' ? (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", "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 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.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 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 };\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 };\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", "/** 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.16.0' as const;\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 { 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 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\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 new Promise<void>((resolve, reject) => {\n const s = document.createElement('script');\n s.src = CDN_URL;\n s.async = true;\n s.onload = () => resolve();\n s.onerror = () => reject(new Error('pixel bundle failed to load'));\n document.head.appendChild(s);\n });\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 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 }\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 }\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 }\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 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", "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} from '../types.js';\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 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.http.post<PayResult>('/api/v1/payment/pay-with-token', {\n tagadaToken: opts.tagadaToken,\n checkoutSessionId: opts.checkoutSessionId,\n returnUrl: opts.returnUrl,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n });\n }\n\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId,\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n threedsSessionId: opts.threedsSessionId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n returnUrl: opts.returnUrl,\n });\n }\n\n /**\n * Low-level pay: process payment with an existing instrument or for APM/express flows\n * where no instrument is needed (redirect-based methods).\n */\n async payDirect(opts: PayDirectOptions): Promise<PayResult> {\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId ?? '',\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n threedsSessionId: opts.threedsSessionId,\n returnUrl: opts.returnUrl,\n });\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 // 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 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 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\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' || status.status === 'failed' || status.status === 'declined') {\n return status;\n }\n await new Promise((r) => setTimeout(r, interval));\n }\n\n throw new Error(`Payment ${paymentId} did not reach terminal status within ${timeout}ms.`);\n }\n\n /** Finalize a payment after a 3DS challenge completes. */\n async completeAfter3ds(paymentId: string): Promise<PaymentStatus> {\n return this.http.post<PaymentStatus>('/api/v1/payments/complete-after-3ds', {\n paymentId,\n });\n }\n\n /** Tell the server this action has been seen / is being processed. */\n async markActionProcessed(paymentId: string): Promise<void> {\n try {\n await this.http.post('/api/v1/payments/require-action/processed', {\n paymentId,\n });\n } catch {\n // Best-effort \u2014 don't block the payment flow if this fails\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal: action routing\n // ---------------------------------------------------------------------------\n\n /**\n * Route a payment action to the appropriate handler.\n * Returns `requires_redirect` for browser-level redirects,\n * or attempts 3DS inline and polls to completion.\n */\n private async handlePaymentAction(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const actionData = payment.requireActionData!;\n\n await this.markActionProcessed(payment.id);\n\n const actionType = actionData.type;\n\n switch (actionType) {\n case 'threeds_auth':\n return this.handleThreedsAuth(payment, opts);\n\n case 'processor_auth':\n case 'redirect_to_payment':\n return this.extractRedirect(payment, actionData);\n\n case 'redirect':\n return this.extractRedirect(payment, actionData);\n\n case 'error':\n return {\n status: 'failed',\n error: actionData.message || actionData.errorCode || 'Payment failed',\n payment,\n };\n\n default:\n // Unknown action type \u2014 try to extract a redirect URL (forward-compatible)\n return this.extractRedirect(payment, actionData);\n }\n }\n\n /**\n * Extract redirect info from actionData.\n * Works for processor_auth (GET or POST), redirect, and any unknown type with a URL.\n */\n private extractRedirect(\n payment: PayResult['payment'],\n actionData: NonNullable<PayResult['payment']['requireActionData']>,\n ): ProcessPaymentResult {\n const redirect = actionData.metadata?.redirect;\n const url = redirect?.redirectUrl || actionData.redirectUrl;\n\n if (!url) {\n return {\n status: 'failed',\n error: `Payment requires action (${actionData.type}) but no redirect URL was provided`,\n payment,\n };\n }\n\n return {\n status: 'requires_redirect',\n redirectUrl: url,\n method: (redirect?.method?.toUpperCase() as 'GET' | 'POST') || 'GET',\n postData: redirect?.data,\n paymentId: payment.id,\n };\n }\n\n /**\n * Run a 3DS challenge using @tagadapay/core-js.\n * If core-js is not installed, falls back to redirect.\n */\n private async handleThreedsAuth(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const session = payment.requireActionData?.metadata?.threedsSession;\n\n // If no 3DS session data, fall back to redirect (acsChallengeUrl)\n if (!session?.externalSessionId) {\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Try to run the challenge inline via core-js\n let coreJs: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n try {\n coreJs = await import('@tagadapay/core-js');\n } catch {\n // core-js not installed \u2014 fall back to redirect if possible\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Run BasisTheory 3DS challenge in a modal iframe\n try {\n const manager = new coreJs.ThreedsManager({ provider: 'basis_theory' });\n await manager.initialize({ apiKey: undefined });\n\n await manager.startChallenge({\n sessionId: session.externalSessionId,\n acsChallengeUrl: session.acsChallengeUrl,\n acsTransactionId: session.acsTransID,\n threeDSVersion: session.messageVersion,\n });\n\n // Challenge done \u2014 tell backend and poll\n await this.completeAfter3ds(payment.id);\n return this.pollUntilDone(payment.id);\n } catch {\n // 3DS challenge failed \u2014 fall back to redirect\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return {\n status: 'failed',\n error: '3D Secure authentication failed',\n payment,\n };\n }\n }\n\n /**\n * Poll until the payment reaches a terminal status, then return a ProcessPaymentResult.\n * Also handles new requireAction that may appear during polling.\n */\n private async pollUntilDone(\n paymentId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<ProcessPaymentResult> {\n const interval = opts?.intervalMs ?? 1500;\n const timeout = opts?.timeoutMs ?? 60_000;\n const start = Date.now();\n let consecutiveErrors = 0;\n\n while (Date.now() - start < timeout) {\n let status: PaymentStatus;\n try {\n status = await this.getPaymentStatus(paymentId);\n consecutiveErrors = 0;\n } catch {\n consecutiveErrors++;\n if (consecutiveErrors >= 3) {\n return { status: 'failed', error: 'Payment verification failed due to network errors' };\n }\n await new Promise((r) => setTimeout(r, interval));\n continue;\n }\n\n if (\n status.status === 'succeeded' ||\n (status.status === 'pending' && status.subStatus === 'authorized')\n ) {\n // 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 if (status.status === 'failed' || status.status === 'declined') {\n return { status: 'failed', error: status.status, payment: status as unknown as PayResult['payment'] };\n }\n\n // New unprocessed action appeared during polling\n if (\n status.requireAction &&\n status.requireAction !== 'none' &&\n status.requireActionData &&\n !status.requireActionData.processed\n ) {\n return this.handlePaymentAction(\n status as unknown as PayResult['payment'],\n {} as ProcessPaymentOptions,\n );\n }\n\n await new Promise((r) => setTimeout(r, interval));\n }\n\n return { status: 'pending', paymentId };\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Read paymentSetupConfig from the Tagada routing injection.\n * Only available when running on Tagada infra (not on external hosting like Vercel).\n */\n private readInjectedStepConfig(): PaymentSetupConfig | null {\n if (typeof window === 'undefined') return null;\n const raw = (window as unknown as Record<string, unknown>).__TGD_STEP_CONFIG__;\n if (!raw) return null;\n try {\n const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;\n return (parsed as Record<string, unknown>)?.paymentSetupConfig as PaymentSetupConfig ?? null;\n } catch {\n return null;\n }\n }\n\n /** 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 { HttpClient } from '../http.js';\nimport type {\n Offer,\n OfferPreview,\n OfferPayResult,\n ProcessPaymentResult,\n} from '../types.js';\nimport type { PaymentModule } from './payment.js';\n\n/**\n * Offers \u2014 upsells, downsells, order bumps, and post-purchase offers.\n *\n * Endpoints align with the plugin-sdk patterns:\n * GET /api/v1/offers/:id \u2014 single offer\n * GET /api/v1/stores/:storeId/offers \u2014 list store offers\n * POST /api/v1/offers/:offerId/preview \u2014 preview pricing\n * POST /api/v1/offers/:offerId/pay-preview \u2014 pay a previewed offer (one-click)\n * POST /api/v1/checkout-sessions/:id/toggle-order-bump \u2014 toggle order bump\n * GET /api/v1/post-purchase/:orderId/offers \u2014 post-purchase offers for an order\n * POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/accept \u2014 accept\n * POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/decline \u2014 decline\n */\nexport class OffersModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n private readonly payment?: PaymentModule,\n ) {}\n\n // ---------------------------------------------------------------------------\n // Offer loading\n // ---------------------------------------------------------------------------\n\n /** Get a single offer by ID. */\n async getOffer(offerId: string): Promise<Offer> {\n return this.http.get<Offer>(`/api/v1/offers/${offerId}`);\n }\n\n /** List offers for the current store. Optionally filter by type or a set of IDs. */\n async listOffers(opts?: {\n type?: 'upsell' | 'orderbump';\n ids?: string[];\n }): Promise<Offer[]> {\n let url = `/api/v1/stores/${this.storeId}/offers`;\n\n const queryParts: string[] = [];\n if (opts?.type) queryParts.push(`type=${encodeURIComponent(opts.type)}`);\n if (opts?.ids?.length) {\n for (const id of opts.ids) queryParts.push(`ids=${encodeURIComponent(id)}`);\n }\n if (queryParts.length) url += `?${queryParts.join('&')}`;\n\n const res = await this.http.get<{ offers: Offer[] }>(url);\n return res.offers ?? [];\n }\n\n // ---------------------------------------------------------------------------\n // Preview & pay (one-click upsell flow from plugin-sdk)\n // ---------------------------------------------------------------------------\n\n /** Preview offer pricing. Returns line items with amounts and totals. */\n async previewOffer(opts: {\n offerId: string;\n currency?: string;\n lineItems?: Array<{ lineItemId?: string; productId?: string; variantId: string; quantity: number }>;\n }): Promise<OfferPreview> {\n return this.http.post<OfferPreview>(`/api/v1/offers/${opts.offerId}/preview`, {\n offerId: opts.offerId,\n currency: opts.currency ?? '',\n lineItems: opts.lineItems,\n });\n }\n\n /**\n * Pay a previously previewed offer (one-click charge).\n * Used after a main order so the stored payment instrument is reused.\n *\n * **Low-level API.** Returns the raw `OfferPayResult` \u2014 `requireAction`,\n * polling, and 3DS redirects are NOT handled. For most cases, use\n * {@link processOfferPayment} which orchestrates the full lifecycle.\n */\n async payPreviewedOffer(opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{ lineItemId?: string; productId?: string; variantId: string; quantity: number }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }): Promise<OfferPayResult> {\n return this.http.post<OfferPayResult>(`/api/v1/offers/${opts.offerId}/pay-preview`, {\n offerId: opts.offerId,\n currency: opts.currency ?? '',\n lineItems: opts.lineItems,\n returnUrl: opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),\n mainOrderId: opts.mainOrderId,\n paymentInstrumentId: opts.paymentInstrumentId,\n });\n }\n\n /**\n * One-click upsell with full lifecycle handling.\n *\n * Like `payment.processPayment()` but for previewed offers: charges the\n * stored instrument from `mainOrderId`, runs any 3DS challenge or bank\n * redirect, polls until terminal, and returns a typed\n * `ProcessPaymentResult` (`succeeded` / `requires_redirect` /\n * `failed` / `pending`).\n *\n * Use this instead of the lower-level `payPreviewedOffer()` whenever you\n * don't need to inspect the raw `OfferPayResult` shape \u2014 which is most\n * of the time.\n *\n * @example\n * ```ts\n * const result = await tagada.offers.processOfferPayment({\n * offerId: 'offer_xxx',\n * mainOrderId: order.id,\n * returnUrl: window.location.href,\n * });\n *\n * switch (result.status) {\n * case 'succeeded':\n * window.location.href = '/upsell-2';\n * break;\n * case 'requires_redirect':\n * window.location.href = result.redirectUrl;\n * break;\n * case 'failed':\n * showError(result.error);\n * break;\n * }\n * ```\n */\n async processOfferPayment(opts: {\n offerId: string;\n mainOrderId: string;\n currency?: string;\n lineItems?: Array<{\n lineItemId?: string;\n productId?: string;\n variantId: string;\n quantity: number;\n }>;\n returnUrl?: string;\n paymentInstrumentId?: string;\n }): Promise<ProcessPaymentResult> {\n if (!this.payment) {\n throw new Error(\n 'OffersModule: no PaymentModule injected. ' +\n 'Use createHeadlessClient() instead of constructing OffersModule directly.',\n );\n }\n const returnUrl =\n opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : undefined);\n const payResult = await this.payPreviewedOffer({ ...opts, returnUrl });\n return this.payment.finalize(\n { payment: payResult.payment, order: payResult.order },\n { returnUrl },\n );\n }\n\n // ---------------------------------------------------------------------------\n // Order bumps (checkout-session scoped)\n // ---------------------------------------------------------------------------\n\n /** Toggle an order bump on/off within a checkout session. */\n async toggleOrderBump(opts: {\n checkoutSessionId: string;\n orderBumpOfferId: string;\n selected: boolean;\n }): Promise<unknown> {\n return this.http.post(\n `/api/v1/checkout-sessions/${opts.checkoutSessionId}/toggle-order-bump`,\n {\n orderBumpOfferId: opts.orderBumpOfferId,\n selected: opts.selected,\n },\n );\n }\n\n // ---------------------------------------------------------------------------\n // Post-purchase offers (order-scoped)\n // ---------------------------------------------------------------------------\n\n /** List post-purchase offers for an order. */\n async listPostPurchaseOffers(orderId: string): Promise<Offer[]> {\n const res = await this.http.get<Offer[]>(`/api/v1/post-purchase/${orderId}/offers`);\n return Array.isArray(res) ? res : [];\n }\n\n /** Accept a post-purchase offer. */\n async acceptPostPurchaseOffer(opts: {\n orderId: string;\n offerId: string;\n items?: Array<{ variantId: string; quantity: number }>;\n }): Promise<{ success: boolean; error?: string }> {\n return this.http.post(\n `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/accept`,\n { items: opts.items ?? [] },\n );\n }\n\n /** Decline a post-purchase offer. */\n async declinePostPurchaseOffer(opts: {\n orderId: string;\n offerId: string;\n }): Promise<{ success: boolean; error?: string }> {\n return this.http.post(\n `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/decline`,\n );\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { Customer, Order, Subscription } from '../types.js';\n\n/**\n * Customer data -- profile, orders, subscriptions.\n *\n * Requires either an API key or a session token for authentication.\n */\nexport class CustomerModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n /** Get customer profile by ID. */\n async getProfile(customerId: string): Promise<Customer> {\n const res = await this.http.get<{ customer: Customer }>(\n `/api/v1/customers/${customerId}`,\n { params: { storeId: this.storeId } },\n );\n return res.customer;\n }\n\n /** Get customer profile by email. */\n async getByEmail(email: string): Promise<Customer | null> {\n try {\n const res = await this.http.get<{ customer: Customer }>(\n '/api/v1/customers/by-email',\n { params: { email, storeId: this.storeId } },\n );\n return res.customer;\n } catch {\n return null;\n }\n }\n\n /** Update customer profile fields. */\n async updateProfile(\n customerId: string,\n data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone' | 'metadata'>>,\n ): Promise<Customer> {\n const res = await this.http.patch<{ customer: Customer }>(\n `/api/v1/customers/${customerId}`,\n { storeId: this.storeId, ...data },\n );\n return res.customer;\n }\n\n /** List orders for a customer. */\n async getOrders(\n customerId: string,\n opts?: { limit?: number; offset?: number },\n ): Promise<{ orders: Order[]; total: number }> {\n return this.http.get<{ orders: Order[]; total: number }>(\n `/api/v1/customers/${customerId}/orders`,\n { params: { storeId: this.storeId, limit: opts?.limit, offset: opts?.offset } },\n );\n }\n\n /**\n * Get a single order by ID.\n *\n * **Thank-you pages:** accepted one-click upsells create *child orders*\n * (`metadata.mainOrderId` = this order's id) that land asynchronously \u2014\n * the first fetch right after an accept usually misses them. Pass\n * `waitForRelatedOrders: true` to poll until `order.relatedOrders` is\n * non-empty or the timeout elapses. On timeout the latest snapshot is\n * returned (never throws), so an order with no accepted upsell simply\n * comes back with an empty `relatedOrders` after `timeoutMs`.\n *\n * @example\n * ```ts\n * // Thank-you page: show the main order AND the upsells\n * const order = await tagada.customer.getOrder(orderId, {\n * waitForRelatedOrders: true,\n * });\n * renderOrders([order, ...(order.relatedOrders ?? [])]);\n * ```\n */\n async getOrder(\n orderId: string,\n opts?: {\n /** Poll until `relatedOrders` is non-empty (or `timeoutMs` elapses). */\n waitForRelatedOrders?: boolean;\n /** Max total wait in ms. Default: 8000. */\n timeoutMs?: number;\n /** Delay between polls in ms. Default: 2000. */\n intervalMs?: number;\n },\n ): Promise<Order> {\n const fetchOrder = async (): Promise<Order> => {\n const res = await this.http.get<{ order: Order }>(`/api/v1/orders/${orderId}`, {\n params: { storeId: this.storeId },\n });\n return res.order;\n };\n\n let order = await fetchOrder();\n if (!opts?.waitForRelatedOrders || order.relatedOrders?.length) return order;\n\n const timeoutMs = opts.timeoutMs ?? 8000;\n const intervalMs = opts.intervalMs ?? 2000;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, Math.min(intervalMs, Math.max(0, deadline - Date.now()))));\n order = await fetchOrder();\n if (order.relatedOrders?.length) return order;\n }\n return order;\n }\n\n /** List subscriptions for a customer. */\n async getSubscriptions(customerId: string): Promise<Subscription[]> {\n const res = await this.http.get<{ subscriptions: Subscription[] }>(\n `/api/v1/customers/${customerId}/subscriptions`,\n { params: { storeId: this.storeId } },\n );\n return res.subscriptions;\n }\n\n /** Get a single subscription by ID. */\n async getSubscription(subscriptionId: string): Promise<Subscription> {\n const res = await this.http.get<{ subscription: Subscription }>(\n `/api/v1/subscriptions/${subscriptionId}`,\n { params: { storeId: this.storeId } },\n );\n return res.subscription;\n }\n}\n", "import type { HttpClient } from '../http.js';\nimport type { CatalogProduct } from '../types.js';\n\n/**\n * Fetches the product catalog for a store.\n *\n * Uses the public `/api/v1/products` endpoint (no auth required).\n */\nexport class CatalogModule {\n constructor(\n private readonly http: HttpClient,\n private readonly storeId: string,\n ) {}\n\n /**\n * List all active products for the store, including variants and prices.\n *\n * @param opts.productIds Optional filter to specific product IDs.\n * @param opts.variantIds Optional filter to products containing these variant IDs.\n */\n async getProducts(opts?: {\n productIds?: string[];\n variantIds?: string[];\n }): Promise<CatalogProduct[]> {\n const body: Record<string, unknown> = {\n storeId: this.storeId,\n includeVariants: true,\n includePrices: true,\n };\n if (opts?.productIds?.length) body.productIds = opts.productIds;\n if (opts?.variantIds?.length) body.variantIds = opts.variantIds;\n\n const res = await this.http.post<{ items: CatalogProduct[] }>(\n '/api/v1/products',\n body,\n );\n\n return res.items ?? [];\n }\n\n /**\n * Get a single product by ID.\n */\n async getProduct(productId: string): Promise<CatalogProduct | null> {\n const items = await this.getProducts({ productIds: [productId] });\n return items[0] ?? null;\n }\n}\n", "import { 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 ) {}\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 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 * @example\n * ```ts\n * const { required } = await tagada.rx.isRequiredForProduct(productId);\n * if (required) {\n * const intake = await collectIntakeFromUser();\n * const res = await tagada.rx.submitCase({\n * orderId, checkoutToken, productId,\n * patient, intakeAnswers: intake,\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\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 }[];\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\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 * 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 * Fetch the network-authored intake questions for a product.\n * Empty `questions` means the storefront should use its local quiz.\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 { HttpClient } from './http.js';\nimport { CheckoutModule } from './modules/checkout.js';\nimport { PaymentModule } from './modules/payment.js';\nimport { OffersModule } from './modules/offers.js';\nimport { CustomerModule } from './modules/customer.js';\nimport { CatalogModule } from './modules/catalog.js';\nimport { FunnelModule } from './modules/funnel.js';\nimport { RxModule } from './modules/rx.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 /** 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\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\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.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 );\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", "CatalogModule", "CheckoutModule", "CurrencyUtils", "CustomerModule", "FunnelModule", "GoogleAutocompleteCore", "HeadlessClient", "HttpClient", "ISODataCore", "OffersModule", "PaymentModule", "RxModule", "TagadaAuthError", "TagadaError", "TagadaNetworkError", "TagadaNotFoundError", "TagadaPaymentError", "TagadaRateLimitError", "TagadaValidationError", "TrackModule", "createHeadlessClient", "ensureGeoDataLoaded", "formatMoney", "getCountries", "getStatesForCountry", "isLanguageLoaded", "loadGoogleMapsScript", "parseTokensFromUrl", "TagadaError", "message", "code", "statusCode", "details", "TagadaAuthError", "TagadaValidationError", "errors", "appCode", "TagadaNotFoundError", "resource", "id", "TagadaRateLimitError", "retryAfterMs", "TagadaPaymentError", "opts", "TagadaNetworkError", "BASE_URLS", "HttpClient", "config", "environment", "override", "path", "options", "_a", "method", "body", "headers", "params", "token", "signal", "url", "qs", "k", "str", "reqHeaders", "authToken", "controller", "timeoutId", "res", "text", "TagadaError", "err", "TagadaNetworkError", "parsed", "data", "msg", "appCode", "TagadaAuthError", "TagadaNotFoundError", "fieldErrors", "TagadaValidationError", "retryAfter", "TagadaRateLimitError", "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", "SDK_NAME", "SDK_VERSION", "CDN_URL", "loadPixels", "w", "resolve", "reject", "s", "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", "name", "standard", "eventId", "seen", "when", "oldest", "who", "state", "input", "event", "_a", "signal", "detail", "SDK_NAME", "SDK_VERSION", "url", "response", "config", "module", "onLeave", "record", "scope", "store", "existing", "fresh", "records", "payload", "body", "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", "payResult", "input", "payment", "returnUrl", "paymentId", "href", "url", "action", "actionStatus", "cleanParams", "k", "search", "interval", "timeout", "start", "status", "r", "actionData", "redirect", "session", "manager", "consecutiveErrors", "raw", "parsed", "orderId", "toContents", "cause", "error", "OffersModule", "http", "storeId", "payment", "offerId", "opts", "_a", "url", "queryParts", "id", "returnUrl", "payResult", "orderId", "res", "CustomerModule", "http", "storeId", "customerId", "email", "data", "opts", "orderId", "_a", "_b", "fetchOrder", "order", "timeoutMs", "intervalMs", "deadline", "resolve", "subscriptionId", "CatalogModule", "http", "storeId", "opts", "_a", "_b", "body", "productId", "FunnelModule", "http", "storeId", "checkout", "accountId", "input", "_a", "session", "TagadaError", "currentUrl", "funnelSessionId", "_b", "_c", "anon", "init", "defaultLocale", "defaultUserAgent", "args", "_d", "stepId", "lineItems", "i", "discountCodes", "customer", "RxModule", "http", "storeId", "id", "productId", "opts", "input", "variantId", "HeadlessClient", "config", "environment", "baseUrl", "HttpClient", "TrackModule", "setToken", "token", "CheckoutModule", "toContents", "PaymentModule", "p", "v", "d", "OffersModule", "CustomerModule", "CatalogModule", "FunnelModule", "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"]
3
+ "sources": ["../src/core/index.ts", "../src/core/errors.ts", "../src/core/http.ts", "../src/core/modules/checkout.ts", "../src/core/helpers/walletContact.ts", "../src/core/version.ts", "../src/core/modules/track.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 } 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 RxQuestionsForProduct,\n RxSubmitCaseInput,\n RxSubmitCaseResult,\n RxCaseSummary,\n RxActivationStatus,\n RxActivationStepKey,\n RxActivationMissingItem,\n} from './modules/rx.js';\n\nexport { HttpClient } from './http.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 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", "import {\n TagadaError,\n TagadaAuthError,\n TagadaValidationError,\n TagadaNotFoundError,\n TagadaRateLimitError,\n TagadaNetworkError,\n} from './errors.js';\nimport type { Environment, HttpRequestOptions } from './types.js';\n\nconst BASE_URLS: Record<Environment, string> = {\n production: 'https://api.tagada.io',\n development: 'https://api.tagada.dev',\n local: 'http://localhost:3000',\n};\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n apiKey?: string;\n getToken?: () => string | undefined;\n 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 ...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 };\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", "/** 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.17.0' as const;\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", "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} from '../types.js';\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 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.http.post<PayResult>('/api/v1/payment/pay-with-token', {\n tagadaToken: opts.tagadaToken,\n checkoutSessionId: opts.checkoutSessionId,\n returnUrl: opts.returnUrl,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n });\n }\n\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId,\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n threedsSessionId: opts.threedsSessionId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n metadata: opts.metadata,\n returnUrl: opts.returnUrl,\n });\n }\n\n /**\n * Low-level pay: process payment with an existing instrument or for APM/express flows\n * where no instrument is needed (redirect-based methods).\n */\n async payDirect(opts: PayDirectOptions): Promise<PayResult> {\n return this.http.post<PayResult>('/api/public/v1/checkout/pay-v2', {\n checkoutSessionId: opts.checkoutSessionId,\n paymentInstrumentId: opts.paymentInstrumentId ?? '',\n storeId: this.storeId,\n paymentFlowId: opts.paymentFlowId,\n processorId: opts.processorId,\n paymentMethod: opts.paymentMethod,\n isExpress: opts.isExpress,\n threedsSessionId: opts.threedsSessionId,\n returnUrl: opts.returnUrl,\n });\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 // 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 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 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\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' || status.status === 'failed' || status.status === 'declined') {\n return status;\n }\n await new Promise((r) => setTimeout(r, interval));\n }\n\n throw new Error(`Payment ${paymentId} did not reach terminal status within ${timeout}ms.`);\n }\n\n /** Finalize a payment after a 3DS challenge completes. */\n async completeAfter3ds(paymentId: string): Promise<PaymentStatus> {\n return this.http.post<PaymentStatus>('/api/v1/payments/complete-after-3ds', {\n paymentId,\n });\n }\n\n /** Tell the server this action has been seen / is being processed. */\n async markActionProcessed(paymentId: string): Promise<void> {\n try {\n await this.http.post('/api/v1/payments/require-action/processed', {\n paymentId,\n });\n } catch {\n // Best-effort \u2014 don't block the payment flow if this fails\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal: action routing\n // ---------------------------------------------------------------------------\n\n /**\n * Route a payment action to the appropriate handler.\n * Returns `requires_redirect` for browser-level redirects,\n * or attempts 3DS inline and polls to completion.\n */\n private async handlePaymentAction(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const actionData = payment.requireActionData!;\n\n await this.markActionProcessed(payment.id);\n\n const actionType = actionData.type;\n\n switch (actionType) {\n case 'threeds_auth':\n return this.handleThreedsAuth(payment, opts);\n\n case 'processor_auth':\n case 'redirect_to_payment':\n return this.extractRedirect(payment, actionData);\n\n case 'redirect':\n return this.extractRedirect(payment, actionData);\n\n case 'error':\n return {\n status: 'failed',\n error: actionData.message || actionData.errorCode || 'Payment failed',\n payment,\n };\n\n default:\n // Unknown action type \u2014 try to extract a redirect URL (forward-compatible)\n return this.extractRedirect(payment, actionData);\n }\n }\n\n /**\n * Extract redirect info from actionData.\n * Works for processor_auth (GET or POST), redirect, and any unknown type with a URL.\n */\n private extractRedirect(\n payment: PayResult['payment'],\n actionData: NonNullable<PayResult['payment']['requireActionData']>,\n ): ProcessPaymentResult {\n const redirect = actionData.metadata?.redirect;\n const url = redirect?.redirectUrl || actionData.redirectUrl;\n\n if (!url) {\n return {\n status: 'failed',\n error: `Payment requires action (${actionData.type}) but no redirect URL was provided`,\n payment,\n };\n }\n\n return {\n status: 'requires_redirect',\n redirectUrl: url,\n method: (redirect?.method?.toUpperCase() as 'GET' | 'POST') || 'GET',\n postData: redirect?.data,\n paymentId: payment.id,\n };\n }\n\n /**\n * Run a 3DS challenge using @tagadapay/core-js.\n * If core-js is not installed, falls back to redirect.\n */\n private async handleThreedsAuth(\n payment: PayResult['payment'],\n opts: ProcessPaymentOptions,\n ): Promise<ProcessPaymentResult> {\n const session = payment.requireActionData?.metadata?.threedsSession;\n\n // If no 3DS session data, fall back to redirect (acsChallengeUrl)\n if (!session?.externalSessionId) {\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Try to run the challenge inline via core-js\n let coreJs: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n try {\n coreJs = await import('@tagadapay/core-js');\n } catch {\n // core-js not installed \u2014 fall back to redirect if possible\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return this.extractRedirect(payment, payment.requireActionData!);\n }\n\n // Run BasisTheory 3DS challenge in a modal iframe\n try {\n const manager = new coreJs.ThreedsManager({ provider: 'basis_theory' });\n await manager.initialize({ apiKey: undefined });\n\n await manager.startChallenge({\n sessionId: session.externalSessionId,\n acsChallengeUrl: session.acsChallengeUrl,\n acsTransactionId: session.acsTransID,\n threeDSVersion: session.messageVersion,\n });\n\n // Challenge done \u2014 tell backend and poll\n await this.completeAfter3ds(payment.id);\n return this.pollUntilDone(payment.id);\n } catch {\n // 3DS challenge failed \u2014 fall back to redirect\n if (session.acsChallengeUrl) {\n return {\n status: 'requires_redirect',\n redirectUrl: session.acsChallengeUrl,\n paymentId: payment.id,\n };\n }\n return {\n status: 'failed',\n error: '3D Secure authentication failed',\n payment,\n };\n }\n }\n\n /**\n * Poll until the payment reaches a terminal status, then return a ProcessPaymentResult.\n * Also handles new requireAction that may appear during polling.\n */\n private async pollUntilDone(\n paymentId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<ProcessPaymentResult> {\n const interval = opts?.intervalMs ?? 1500;\n const timeout = opts?.timeoutMs ?? 60_000;\n const start = Date.now();\n let consecutiveErrors = 0;\n\n while (Date.now() - start < timeout) {\n let status: PaymentStatus;\n try {\n status = await this.getPaymentStatus(paymentId);\n consecutiveErrors = 0;\n } catch {\n consecutiveErrors++;\n if (consecutiveErrors >= 3) {\n return { status: 'failed', error: 'Payment verification failed due to network errors' };\n }\n await new Promise((r) => setTimeout(r, interval));\n continue;\n }\n\n if (\n status.status === 'succeeded' ||\n (status.status === 'pending' && status.subStatus === 'authorized')\n ) {\n // 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 if (status.status === 'failed' || status.status === 'declined') {\n return { status: 'failed', error: status.status, payment: status as unknown as PayResult['payment'] };\n }\n\n // New unprocessed action appeared during polling\n if (\n status.requireAction &&\n status.requireAction !== 'none' &&\n status.requireActionData &&\n !status.requireActionData.processed\n ) {\n return this.handlePaymentAction(\n status as unknown as PayResult['payment'],\n {} as ProcessPaymentOptions,\n );\n }\n\n await new Promise((r) => setTimeout(r, interval));\n }\n\n return { status: 'pending', paymentId };\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Read paymentSetupConfig from the Tagada routing injection.\n * Only available when running on Tagada infra (not on external hosting like Vercel).\n */\n private readInjectedStepConfig(): PaymentSetupConfig | null {\n if (typeof window === 'undefined') return null;\n const raw = (window as unknown as Record<string, unknown>).__TGD_STEP_CONFIG__;\n if (!raw) return null;\n try {\n const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;\n return (parsed as Record<string, unknown>)?.paymentSetupConfig as PaymentSetupConfig ?? null;\n } catch {\n return null;\n }\n }\n\n /** 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 * @example\n * ```ts\n * const { required } = await tagada.rx.isRequiredForProduct(productId);\n * if (required) {\n * const intake = await collectIntakeFromUser();\n * const res = await tagada.rx.submitCase({\n * orderId, checkoutToken, productId,\n * patient, intakeAnswers: intake,\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\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 }[];\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\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 * 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 * Fetch the network-authored intake questions for a product.\n * Empty `questions` means the storefront should use its local quiz.\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", "CatalogModule", "CheckoutModule", "CurrencyUtils", "CustomerModule", "CustomerPortalModule", "ExperimentsModule", "FunnelModule", "GoogleAutocompleteCore", "HeadlessClient", "HttpClient", "ISODataCore", "OffersModule", "PaymentModule", "RxModule", "TagadaAuthError", "TagadaError", "TagadaNetworkError", "TagadaNotFoundError", "TagadaPaymentError", "TagadaRateLimitError", "TagadaValidationError", "TrackModule", "createHeadlessClient", "ensureGeoDataLoaded", "formatMoney", "getCountries", "getStatesForCountry", "isLanguageLoaded", "loadGoogleMapsScript", "parseTokensFromUrl", "TagadaError", "message", "code", "statusCode", "details", "TagadaAuthError", "TagadaValidationError", "errors", "appCode", "TagadaNotFoundError", "resource", "id", "TagadaRateLimitError", "retryAfterMs", "TagadaPaymentError", "opts", "TagadaNetworkError", "BASE_URLS", "HttpClient", "config", "environment", "override", "path", "options", "_a", "method", "body", "headers", "params", "token", "signal", "url", "qs", "k", "str", "reqHeaders", "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", "SDK_NAME", "SDK_VERSION", "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", "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", "payResult", "input", "payment", "returnUrl", "paymentId", "href", "url", "action", "actionStatus", "cleanParams", "k", "search", "interval", "timeout", "start", "status", "r", "actionData", "redirect", "session", "manager", "consecutiveErrors", "raw", "parsed", "orderId", "toContents", "cause", "error", "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", "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", "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
  }