cope-sdk 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/cope-cart.ts"],"names":["CopeError","message","CopeApiError","status","errors","requestId","retryAfter","first","CopeNetworkError","CopeCartExpiredError","state","CHECKOUT_EMBED_ERROR_CODES","CHECKOUT_EMBED_TERMINAL_STATUSES","TERMINAL_STATES","DEFAULT_BASE_URL","STORAGE_KEY","REQUEST_TIMEOUT_MS","RETRY_INITIAL_DELAY_MS","RETRY_MAX_DELAY_MS","CHECKOUT_MESSAGE_SOURCE","CHECKOUT_MESSAGE_VERSION","CHECKOUT_MOUNT_MESSAGE_TYPE","CHECKOUT_MOUNT_MESSAGE_VERSION","CHECKOUT_MOUNT_RETRY_INTERVAL_MS","CHECKOUT_MOUNT_MAX_ATTEMPTS","CHECKOUT_READY_TIMEOUT_MS","SUPPORTED_ONE_CLICK_CHARGE_TERMS_VERSIONS","seg","id","isRecord","value","originOnly","url","EDGE_ERROR_MESSAGES","parseErrorBody","body","isApiErrorEntry","parseRetryAfter","at","bodyRequestId","normalizeOneClickChargeConsent","termsVersion","normalizeCart","cart","CHECKOUT_EMBED_ERROR_CODE_SET","CHECKOUT_EMBED_TERMINAL_STATUS_SET","isCheckoutEmbedErrorCode","isCheckoutEmbedTerminalStatus","isPostPurchaseOfferStepKind","isPostPurchaseDecisionStatus","isPostPurchaseChargeStatus","isPostPurchaseTerminalStatus","currentWindowOrigin","location","host","normalizeCheckoutUrls","absoluteUrl","checkoutUrl","embedCheckoutUrl","embedMatch","checkoutMatch","checkoutEmbedToken","match","checkoutEmbedOrigin","raw","embed","parseCheckoutEmbedEvent","data","metadata","height","code","retryable","offerRef","stepKind","title","priceGrossMinorUnits","currency","chargeStatus","CopeCart","options","baseOrigin","payload","productUuid","cartId","lineId","input","lines","line","checkout","checkoutId","checkoutOrTarget","optionsOrCheckout","maybeOptions","allowedOrigin","fallbackUrl","target","iframe","checkoutOrigin","mountMessage","parentOrigin","destroyed","ready","mountAttempts","mountRetry","readyTimeout","clearMountRetry","clearReadyTimeout","cleanup","handleMessage","handleIframeLoad","postMountMessage","startMountHandshake","event","error","opts","created","urls","method","path","headers","idempotencyKey","maxAttempts","replaySafe","lastError","attempt","delay","timeoutController","timeout","signal","response","errorBody","msg","exponential","ms","resolve","externalReference","digest","byte","label","origin","element","parsed"],"mappings":"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","file":"index.js","sourcesContent":["// ---------------------------------------------------------------------------\n// Error classes\n// ---------------------------------------------------------------------------\n\nexport class CopeError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CopeError'\n }\n}\n\nexport class CopeApiError extends CopeError {\n readonly code: ApiErrorCode\n readonly status: number\n readonly field?: string\n readonly requestId: string | null\n /** Seconds the server asked the caller to wait (`Retry-After`), or null. */\n readonly retryAfter: number | null\n readonly errors: ReadonlyArray<{ readonly code: string; readonly message: string; readonly field?: string }>\n\n constructor(\n status: number,\n errors: Array<{ code: string; message: string; field?: string }>,\n requestId?: string | null,\n retryAfter?: number | null,\n ) {\n const first = errors[0]\n super(first?.message ?? `API error ${status}`)\n this.name = 'CopeApiError'\n this.status = status\n this.code = (first?.code ?? 'unknown') as ApiErrorCode\n this.field = first?.field\n this.requestId = requestId ?? null\n this.retryAfter = retryAfter ?? null\n this.errors = errors\n }\n}\n\nexport class CopeNetworkError extends CopeError {\n constructor(message: string) {\n super(message)\n this.name = 'CopeNetworkError'\n }\n}\n\nexport class CopeCartExpiredError extends CopeError {\n readonly state: CartState\n\n constructor(state: CartState) {\n super(`Cart is ${state} and cannot be used`)\n this.name = 'CopeCartExpiredError'\n this.state = state\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error codes — known codes + string escape hatch\n// ---------------------------------------------------------------------------\n\nexport type ApiErrorCode =\n | 'rate_limited'\n | 'cart_not_active'\n | 'duplicate_line'\n | 'not_saleable'\n | 'empty_cart'\n | 'incomplete_buyer_identity'\n | 'incomplete_shipping_address'\n | 'missing_consent'\n | 'below_minimum_charge'\n | 'invalid_redirect_url'\n | 'checkout_expired'\n | 'checkout_not_open'\n | 'checkout_not_cancellable'\n // A refused promo code (422), PromoCodes::Validate's reasons. `not_found` here\n // means no such code; it shares the name of the 404 code below.\n | 'inactive'\n | 'not_started'\n | 'expired'\n | 'exhausted'\n | 'no_applicable_items'\n | 'currency_not_supported'\n | 'promo_not_supported_for_recurring'\n | 'missing_code'\n | 'missing_tax_location'\n | 'tax_service_unavailable'\n | 'payment_provider_error'\n | 'unauthorized'\n | 'not_found'\n | 'validation_error'\n | 'cart_id_mismatch'\n // Answered by cope-edge itself, in its `{error, request_id}` envelope.\n | 'payload_too_large'\n | 'upstream_unavailable'\n | 'gateway_timeout'\n | (string & {}) // escape hatch for unknown codes\n\n// ---------------------------------------------------------------------------\n// Cart\n// ---------------------------------------------------------------------------\n\nexport type CartState =\n | 'active'\n | 'checkout_in_progress'\n | 'ordered'\n | 'expired'\n | 'abandoned'\n | 'merged'\n\nexport interface OneClickChargeConsentApplicability {\n readonly applicable: boolean\n readonly terms_version: string | null\n}\n\nexport interface Cart {\n readonly id: string\n readonly state: CartState\n readonly version: number\n readonly currency: string\n readonly charge_currency: string\n /** Present only in the `createCart()` response. The SDK persists it to localStorage automatically. */\n readonly cart_secret?: string\n readonly lines: readonly CartLine[]\n /**\n * Absent where cope-core does not report it — the reprice and promo-code\n * responses — which is not the same as `null` (no buyer recorded yet).\n */\n readonly buyer_identity?: BuyerIdentity | null\n readonly totals: CartTotals | null\n readonly locale: string\n readonly applied_promo_code: AppliedPromoCode | null\n /** Backend-owned OTO candidate; absent while older backends roll forward. */\n readonly one_click_charge_consent?: OneClickChargeConsentApplicability | null\n}\n\n// ---------------------------------------------------------------------------\n// Cart Line\n// ---------------------------------------------------------------------------\n\nexport interface CartLine {\n readonly id: string\n readonly cart_id: string\n readonly product_id: number\n readonly plan_id: number | null\n readonly quantity: number\n readonly price_snapshot: PriceSnapshot | null\n /** The product's name, present before the line is repriced (`price_snapshot` is null until then). */\n readonly product_name?: string | null\n readonly product_uuid: string\n readonly stale?: boolean\n readonly requires_shipping?: boolean\n readonly trial_days?: number\n readonly payment_methods: readonly string[]\n readonly plan_type: string | null\n}\n\nexport interface PriceSnapshot {\n readonly unit_price_minor_units: number\n readonly currency: string\n readonly charge_currency: string\n readonly product_name: string\n readonly plan_name: string | null\n readonly captured_at: string\n}\n\n// ---------------------------------------------------------------------------\n// Buyer Identity\n// ---------------------------------------------------------------------------\n\nexport interface Address {\n readonly line1: string\n readonly line2: string | null\n readonly city: string\n readonly region?: string | null\n readonly postal_code: string\n readonly country: string\n}\n\n/** The promo code on the cart and what it takes off (apps/cope-core CartBlueprint `applied_promo_code`). */\nexport interface AppliedPromoCode {\n readonly id: number\n readonly code: string\n readonly discount_total_minor_units: number\n /** True when the discount was trimmed to keep the order above the minimum charge. */\n readonly capped_to_minimum_charge: boolean\n}\n\nexport interface BuyerIdentity {\n readonly email: string\n readonly country: string\n readonly postal_code: string | null\n readonly company: string | null\n readonly buyer_type: 'b2b' | 'b2c' | null\n readonly billing_address: Address | null\n readonly shipping_address: Address | null\n readonly consents: readonly Consent[]\n}\n\nexport interface Consent {\n readonly type: string\n readonly granted_at: string\n readonly ip: string\n}\n\n// ---------------------------------------------------------------------------\n// Totals\n// ---------------------------------------------------------------------------\n\nexport type TotalsFinality = 'estimate' | 'final'\n\nexport interface CartTotals {\n readonly subtotal_minor_units: number\n readonly tax_minor_units: number\n readonly shipping_minor_units: number\n readonly discount_minor_units: number\n readonly total_minor_units: number\n /** Currency the *_minor_units are denominated in. Always equals `charge_currency`. */\n readonly currency: string\n /** Currency that will be billed (Stripe PaymentIntent.currency). */\n readonly charge_currency: string\n readonly finality: TotalsFinality\n /** Buyer's selected presentment currency, when different from `charge_currency`.\n * Paired with `presentment_exchange_rate`; both present or both absent.\n * To display amounts in presentment, multiply each `*_minor_units` by `presentment_exchange_rate`. */\n readonly presentment_currency?: string\n readonly presentment_exchange_rate?: number\n}\n\n// ---------------------------------------------------------------------------\n// Product (read-only, for getProduct)\n// ---------------------------------------------------------------------------\n\nexport interface SdkProduct {\n readonly uuid: string\n readonly name: string\n readonly headline: string | null\n readonly product_type: string\n readonly currency: string\n readonly payment_methods: readonly string[]\n readonly images: readonly SdkProductImage[]\n readonly payment_plans: readonly SdkPaymentPlan[]\n}\n\nexport interface SdkProductImage {\n readonly id: number\n readonly image_url: string\n}\n\nexport interface SdkPaymentPlan {\n readonly id: number\n readonly plan_type: 'one_time' | 'subscription' | 'installment'\n readonly position: number\n readonly currency: string\n readonly display_name: string | null\n /** Price as a decimal string, e.g. \"24.99\" (dollars, not cents despite the field name) */\n readonly first_payment_amount_cents: string\n readonly next_payments_amount_cents: string | null\n readonly next_payments_count: number | null\n readonly shipping_price_cents: string\n readonly charge_shipping_once: boolean\n readonly shipping_depend_on_quantity: boolean\n readonly interval: 'day' | 'week' | 'month' | 'year' | null\n readonly interval_count: number | null\n readonly second_payment_in: number | null\n readonly vanity_prices: readonly SdkVanityPrice[]\n}\n\nexport interface SdkVanityPrice {\n readonly id: number\n readonly currency: string\n readonly first_payment_amount_cents: string\n readonly next_payments_amount_cents: string | null\n}\n\n// ---------------------------------------------------------------------------\n// Checkout\n// ---------------------------------------------------------------------------\n\nexport type CheckoutStatus = 'open' | 'completed' | 'expired' | 'cancelled'\n\nexport interface CheckoutCreateEmbedPolicy {\n readonly allowed: true\n readonly parent_origin: string\n}\n\nexport interface CheckoutCreateResponse {\n readonly checkout_id: string\n readonly checkout_url: string\n readonly embed?: CheckoutCreateEmbedPolicy\n readonly status: CheckoutStatus\n readonly expires_at: string\n readonly totals: CartTotals\n readonly cart_version: number\n}\n\n// ---------------------------------------------------------------------------\n// SDK Options & Payloads\n// ---------------------------------------------------------------------------\n\nexport interface CopeCartOptions {\n readonly publishableKey: string\n readonly baseUrl?: string\n readonly checkoutBaseUrl?: string\n /**\n * Where the active cart's id and secret are kept between page loads.\n * `'localStorage'` (default) is right for one buyer in one browser. Use `'none'`\n * on a server, where one process serves many buyers: a process-wide store would\n * hand one buyer's cart secret to the next client. A client also holds its cart\n * secret in memory and sends it on every request, so a server needs one client\n * per buyer (or per request with `cart`), never one shared client.\n */\n readonly persistence?: 'localStorage' | 'none'\n /**\n * Act on an existing cart whose credentials the caller already holds. Implies\n * `persistence: 'none'`: such a client never reads, writes or clears stored carts.\n */\n readonly cart?: { readonly id: string; readonly secret: string }\n}\n\nexport interface CheckoutOptions {\n /**\n * Sent as the Idempotency-Key. The cart API replays its stored answer to a\n * repeated key and identical body, so a caller that may re-send the same\n * checkout (an agent retrying a tool call) gets the same checkout back instead\n * of `cart_not_active` from a cart the first call already locked. While the first\n * call is still being processed, a repeat gets 409 `idempotency_conflict`; wait\n * briefly and repeat again.\n */\n readonly idempotencyKey?: string\n}\n\nexport interface CreateCartPayload {\n readonly currency: string\n readonly locale?: string\n readonly attribution?: CartAttribution\n readonly metadata?: CartMetadata\n}\n\nexport interface CartAttribution {\n readonly affiliate_id?: string\n readonly promo_code?: string\n readonly utm_source?: string\n readonly utm_medium?: string\n readonly utm_campaign?: string\n readonly utm_content?: string\n readonly utm_term?: string\n readonly landing_url?: string\n readonly referrer?: string\n readonly captured_at?: string\n}\n\nexport type CartMetadataValue =\n | string\n | number\n | boolean\n | null\n | readonly CartMetadataValue[]\n | { readonly [key: string]: CartMetadataValue }\n\nexport interface CartMetadata {\n readonly [key: string]: CartMetadataValue\n}\n\nexport interface AddLinePayload {\n /** Product UUID string — resolved to integer FK in API response (CartLine.product_id) */\n readonly product_id: string\n /** Optional payment plan ID. Omit it to let the API select the product's default plan. */\n readonly plan_id?: number\n readonly quantity?: number\n}\n\nexport interface UpdateLinePayload {\n readonly quantity?: number\n readonly plan_id?: number\n}\n\nexport interface UpdateBuyerIdentityPayload {\n readonly email?: string\n readonly first_name?: string\n readonly last_name?: string\n readonly country?: string\n readonly postal_code?: string\n readonly company?: string\n readonly buyer_type?: 'b2b' | 'b2c'\n readonly vat_id?: string\n readonly billing_address?: Partial<Address>\n readonly shipping_address?: Partial<Address>\n readonly consents?: ReadonlyArray<{ readonly type: string }>\n}\n\nexport interface CheckoutPayload {\n readonly success_url?: string\n readonly cancel_url?: string\n readonly embed_origin?: string\n readonly consents: ReadonlyArray<{ readonly type: string; readonly version?: string }>\n}\n\n/**\n * The minimum a checkout has to expose to be mounted in an iframe.\n *\n * `mountCheckout` reads exactly three things: `embedCheckoutUrl` (the frame's\n * src, and the source of the handshake token), `embedOrigin` (checked against\n * the hosting page), and `checkoutUrl` — the last only for `fallback:\n * 'redirect'`, which refuses to run without it rather than deriving one. It\n * never reads `checkoutId`, `totals`, `status` or `expiresAt`.\n *\n * Asking for a whole `CheckoutResult` therefore asked for four fields it does\n * not use, which shut out the caller that has no CheckoutResult to give: an\n * offer is created server-side and its API answers with `embed_url` +\n * `embed_origin`, no cart and no totals in sight. Integrators were left\n * inventing a `checkoutId` to satisfy a type, or hand-rolling the postMessage\n * handshake the SDK exists to own.\n *\n * `mountCheckout` accepts `CheckoutResult | MountableCheckout` rather than this\n * type alone, and the union is load-bearing: TypeScript excess-property-checks\n * an object LITERAL against its parameter type, so narrowing the parameter to\n * this interface would have rejected the seven-field literal integrators write\n * inline today — a compile break dressed up as a widening. Keeping\n * `CheckoutResult` in the union gives that literal an arm to match.\n */\nexport interface MountableCheckout {\n readonly embedCheckoutUrl: string\n /** Required: `mountCheckout` refuses to mount without it. */\n readonly embedOrigin: string\n /** Required only by `fallback: 'redirect'`; for an offer, pass `public_url`. */\n readonly checkoutUrl?: string\n}\n\nexport interface CheckoutResult {\n readonly checkoutId: string\n readonly checkoutUrl: string\n readonly embedCheckoutUrl: string\n readonly embedOrigin?: string\n readonly status: CheckoutStatus\n readonly expiresAt: string\n readonly totals: CartTotals\n}\n\nexport interface PrefilledCheckoutLineInput {\n readonly productId: string\n /** Optional payment plan ID. Omit it to let the API select the product's default plan. */\n readonly planId?: number\n readonly quantity?: number\n}\n\ninterface PrefilledCheckoutBaseInput {\n /**\n * Stable caller-side reference, e.g. an event sales session ID. The SDK uses\n * it for the backend Idempotency-Key and stores it as cart metadata. Distinct\n * references always get distinct keys: up to 120 characters of\n * `[A-Za-z0-9._:-]` are used as is, anything else is SHA-256'd whole. A replay\n * returns the stored handoff only for the cart API's 24-hour idempotency TTL;\n * after that the same reference creates a new cart and checkout.\n */\n readonly externalReference: string\n readonly currency: string\n readonly locale?: string\n readonly attribution?: CartAttribution\n /**\n * Non-sensitive reconciliation metadata. `external_reference` and\n * `intended_payment_method` are reserved metadata keys populated from the\n * matching top-level SDK fields.\n */\n readonly metadata?: CartMetadata\n readonly intendedPaymentMethod?: string\n readonly buyerIdentity: UpdateBuyerIdentityPayload\n readonly checkout: CheckoutPayload\n}\n\nexport type PrefilledCheckoutInput = PrefilledCheckoutBaseInput & (\n | {\n readonly line: PrefilledCheckoutLineInput\n readonly lines?: never\n }\n | {\n readonly line?: never\n readonly lines: readonly [PrefilledCheckoutLineInput, ...PrefilledCheckoutLineInput[]]\n }\n)\n\nexport interface PrefilledCheckoutResult {\n /**\n * Cart ID for logging and reconciliation only. The prefilled handoff response\n * intentionally excludes `cart_secret`, so this SDK instance cannot use this\n * cart ID for follow-up mutations such as `addLine`, `reprice`, or `checkout`.\n */\n readonly cartId: string\n readonly cartVersion: number\n readonly checkoutId: string\n readonly checkoutToken: string\n readonly checkoutUrl: string\n readonly embedCheckoutUrl: string\n readonly embedOrigin?: string\n readonly status: CheckoutStatus\n readonly expiresAt: string\n readonly totals: CartTotals\n readonly intendedPaymentMethod?: string\n}\n\n// ---------------------------------------------------------------------------\n// Checkout embed postMessage protocol — consumer half of a two-package contract\n// ---------------------------------------------------------------------------\n//\n// The producer is the hosted checkout embed bridge\n// (`apps/frontend/lib/checkout/embed-protocol.ts` +\n// `apps/frontend/app/checkout/embed/[token]/HostedCheckoutEmbedBridge.tsx`).\n// A status the bridge emits but this list omits is silently dropped by\n// `parseCheckoutEmbedEvent` — the parent frame then sees nothing at all, not\n// even an error. The two lists are asserted equal by\n// `tests/checkout-embed-protocol-contract.test.ts` (and by its mirror in the\n// frontend suite, so either package's CI lane catches a divergence).\n//\n// Do not add a value here without adding a producer on the bridge side, and do\n// not add one there without adding it here.\n\nexport const CHECKOUT_EMBED_ERROR_CODES = [\n 'not_found',\n 'load_failed',\n 'embed_not_allowed',\n 'confirm_failed',\n] as const\n\nexport type CheckoutEmbedErrorCode = (typeof CHECKOUT_EMBED_ERROR_CODES)[number]\nexport type CheckoutEmbedFallbackMode = 'redirect' | 'error'\n\n/**\n * Terminal states the mounted checkout can report.\n *\n * - `completed` — the order was placed in this session (live payment success).\n * - `already_completed` — the token resolved to a checkout that was paid\n * *before* this iframe mounted (refresh after success, bookmark, re-opened\n * offer link). The parent must not re-run fulfilment, so it does NOT fire\n * `onSuccess`.\n * - `processing` — an asynchronous rail (Klarna/iDEAL/BNPL/SEPA) accepted the\n * payment but Cart's authoritative order state is still `processing`. Not a\n * success: the parent should wait for its own server-side signal.\n * - `expired` / `cancelled` — the checkout or its offer is no longer payable.\n */\nexport const CHECKOUT_EMBED_TERMINAL_STATUSES = [\n 'expired',\n 'completed',\n 'already_completed',\n 'cancelled',\n 'processing',\n] as const\n\nexport type CheckoutEmbedTerminalStatus = (typeof CHECKOUT_EMBED_TERMINAL_STATUSES)[number]\n\nexport interface CheckoutEmbedErrorPayload {\n readonly code: CheckoutEmbedErrorCode\n readonly retryable: boolean\n}\n\nexport interface CheckoutEmbedTerminalPayload {\n readonly status: CheckoutEmbedTerminalStatus\n}\n\nexport interface CheckoutEmbedResizePayload {\n readonly height: number\n}\n\nexport interface CheckoutEmbedEventMetadata {\n readonly messageId?: string\n readonly timestamp?: string\n}\n\n// ---------------------------------------------------------------------------\n// Post-Purchase Offer (OTO) — native post-purchase upsell/downsell flow\n// ---------------------------------------------------------------------------\n//\n// These types mirror the backend post-purchase offer/decision contract for\n// typed consumption by SDK integrators. The SDK never fetches OTO state\n// directly — it only relays sanitized lifecycle events emitted by the\n// mounted checkout iframe (see `post_purchase_offer` / `post_purchase_decision`\n// / `post_purchase_terminal` in CheckoutEmbedEvent below). `offerRef` is an\n// opaque reference — no product/plan identifiers, checkout tokens, cart\n// secrets, payment client secrets, or buyer PII are ever included. The 3DS\n// step-up authentication for an accepted offer happens entirely inside the\n// COPE-owned iframe; the parent only ever learns `requires_action` as a status.\n\nexport type PostPurchaseOfferStepKind = 'upsell' | 'downsell'\n\n/**\n * Buyer's response to a presented offer. `requires_action` means a 3DS\n * step-up is in progress inside the COPE iframe — the payment client secret\n * never leaves that surface.\n */\nexport type PostPurchaseDecisionStatus = 'accepted' | 'declined' | 'failed_not_charged' | 'requires_action'\n\n/** Payment outcome for an accepted offer, tracked separately from the buyer-facing decision status. */\nexport type PostPurchaseChargeStatus = 'not_charged' | 'charged' | 'requires_action' | 'failed'\n\n/** Final state of the overall post-purchase offer flow. */\nexport type PostPurchaseTerminalStatus = 'completed' | 'declined' | 'expired' | 'unavailable'\n\n/** Sanitized offer display fields — no product/plan IDs, only an opaque `offerRef`. */\nexport interface PostPurchaseOffer {\n readonly offerRef: string\n readonly stepKind: PostPurchaseOfferStepKind\n readonly title: string\n readonly priceGrossMinorUnits: number\n readonly currency: string\n}\n\n/** Sanitized decision outcome for a single offer. */\nexport interface PostPurchaseOutcome {\n readonly offerRef: string\n readonly status: PostPurchaseDecisionStatus\n readonly chargeStatus: PostPurchaseChargeStatus\n}\n\nexport type PostPurchaseOfferPayload = PostPurchaseOffer\nexport type PostPurchaseDecisionPayload = PostPurchaseOutcome\n\nexport interface PostPurchaseTerminalPayload {\n readonly status: PostPurchaseTerminalStatus\n}\n\nexport type CheckoutEmbedEvent =\n | ({ readonly type: 'ready' } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'error'; readonly payload: CheckoutEmbedErrorPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'terminal'; readonly payload: CheckoutEmbedTerminalPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'resize'; readonly payload: CheckoutEmbedResizePayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'post_purchase_offer'; readonly payload: PostPurchaseOfferPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'post_purchase_decision'; readonly payload: PostPurchaseDecisionPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'post_purchase_terminal'; readonly payload: PostPurchaseTerminalPayload } & CheckoutEmbedEventMetadata)\n\nexport interface CheckoutMountMessage {\n readonly type: 'copecart.checkout.mount'\n readonly version: 1\n readonly token: string\n}\n\nexport interface MountCheckoutOptions {\n readonly target: HTMLElement | string\n readonly title?: string\n readonly className?: string\n /**\n * What to do when the iframe never completes the trusted ready handshake.\n * Defaults to `error`; set `redirect` for a buyer-safe hosted checkout fallback.\n */\n readonly fallback?: CheckoutEmbedFallbackMode\n readonly readyTimeoutMs?: number\n /**\n * Called after a trusted `cope.checkout` ready message from the mounted checkout iframe.\n * `mountCheckout()` intentionally does not expose checkout tokens, cart secrets,\n * payment client secrets, or buyer PII through any callback payload.\n */\n readonly onReady?: () => void\n readonly onResize?: (payload: CheckoutEmbedResizePayload) => void\n readonly onError?: (payload: CheckoutEmbedErrorPayload) => void\n readonly onTerminal?: (payload: CheckoutEmbedTerminalPayload) => void\n readonly onSuccess?: () => void\n readonly onCancel?: () => void\n readonly onFallbackRedirect?: () => void\n /**\n * Called when the mounted checkout iframe presents a post-purchase offer\n * (native OTO upsell/downsell). The payload is sanitized: display fields\n * and an opaque `offerRef` only — never a product/plan ID, checkout token,\n * cart secret, payment client secret, or buyer PII.\n */\n readonly onPostPurchaseOffer?: (payload: PostPurchaseOfferPayload) => void\n /**\n * Called when the buyer decides on a post-purchase offer. `requires_action`\n * means a 3DS step-up is happening inside the COPE iframe — the payment\n * client secret is never forwarded here.\n */\n readonly onPostPurchaseDecision?: (payload: PostPurchaseDecisionPayload) => void\n /** Called when the overall post-purchase offer flow reaches a final state. */\n readonly onPostPurchaseTerminal?: (payload: PostPurchaseTerminalPayload) => void\n readonly onMessage?: (event: CheckoutEmbedEvent) => void\n}\n\nexport type MountCheckoutCallbacks = Omit<MountCheckoutOptions, 'target'>\n\nexport interface MountedCheckout {\n /**\n * Hosted checkout iframe. The SDK sets `allow=\"payment *\"` and\n * `referrerPolicy=\"no-referrer\"`.\n *\n * The SDK intentionally omits a `sandbox` attribute: no sandbox token set has\n * been proven compatible with all required wallet, redirect, and payment\n * provider flows yet. Embedding is instead constrained by the registered\n * `embed_origin` contract plus strict postMessage origin/source checks.\n */\n readonly iframe: HTMLIFrameElement\n destroy(): void\n}\n","import type {\n AddLinePayload,\n Cart,\n CheckoutCreateResponse,\n CheckoutEmbedErrorCode,\n CheckoutEmbedEvent,\n CheckoutEmbedTerminalPayload,\n CheckoutMountMessage,\n CheckoutPayload,\n CheckoutOptions,\n CheckoutResult,\n CopeCartOptions,\n CreateCartPayload,\n MountedCheckout,\n MountCheckoutCallbacks,\n MountCheckoutOptions,\n MountableCheckout,\n OneClickChargeConsentApplicability,\n PostPurchaseChargeStatus,\n PostPurchaseDecisionStatus,\n PostPurchaseOfferStepKind,\n PostPurchaseTerminalStatus,\n PrefilledCheckoutInput,\n PrefilledCheckoutLineInput,\n PrefilledCheckoutResult,\n SdkProduct,\n UpdateBuyerIdentityPayload,\n UpdateLinePayload,\n} from './types.js'\nimport {\n CHECKOUT_EMBED_ERROR_CODES,\n CHECKOUT_EMBED_TERMINAL_STATUSES,\n CopeApiError,\n CopeCartExpiredError,\n CopeError,\n CopeNetworkError,\n} from './types.js'\nimport type { CartState } from './types.js'\n\nconst TERMINAL_STATES: ReadonlySet<CartState> = new Set(['ordered', 'expired', 'abandoned', 'merged'])\n// The app host: requests go to `${baseUrl}/api/cart/v1/...`, which cope-edge's\n// checkout block serves there, and the hosted checkout's origin (derived from\n// this URL when checkoutBaseUrl is unset) is the same host.\nconst DEFAULT_BASE_URL = 'https://app.cope.com'\nconst STORAGE_KEY = 'cope_sdk_cart'\nconst REQUEST_TIMEOUT_MS = 8_000\nconst RETRY_INITIAL_DELAY_MS = 500\nconst RETRY_MAX_DELAY_MS = 5_000\nconst CHECKOUT_MESSAGE_SOURCE = 'cope.checkout'\nconst CHECKOUT_MESSAGE_VERSION = 1\nconst CHECKOUT_MOUNT_MESSAGE_TYPE = 'copecart.checkout.mount'\nconst CHECKOUT_MOUNT_MESSAGE_VERSION = 1\nconst CHECKOUT_MOUNT_RETRY_INTERVAL_MS = 250\nconst CHECKOUT_MOUNT_MAX_ATTEMPTS = 20\nconst CHECKOUT_READY_TIMEOUT_MS = 8_000\nconst SUPPORTED_ONE_CLICK_CHARGE_TERMS_VERSIONS: ReadonlySet<string> = new Set(['oto-v1'])\n\ntype HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE'\ntype MountCleanup = () => void\ntype RequestOptions = {\n readonly skipAuth?: boolean\n readonly idempotencyKey?: string\n}\ntype PrefilledCheckoutCreateResponse = CheckoutCreateResponse & {\n readonly cart_id: string\n readonly checkout_token?: string\n}\n\n// One path segment. Ids arrive from callers (and, through cope-sdk/mcp, from AI\n// agents); unencoded, `../buyer-identity` or a `?` would aim a request carrying\n// the cart secret at another route.\nfunction seg(id: string): string {\n return encodeURIComponent(id)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\ntype ApiErrorEntry = { code: string; message: string; field?: string }\n\n// The normalized origin of a URL that is nothing but an origin — no path, query,\n// fragment or credentials — or null. `https://App.Cope.com:443/` is accepted and\n// becomes `https://app.cope.com`.\nfunction originOnly(value: string): string | null {\n try {\n const url = new URL(value)\n const bare = url.pathname === '/' && !url.search && !url.hash && !url.username && !url.password\n return bare ? url.origin : null\n } catch {\n return null\n }\n}\n\nconst EDGE_ERROR_MESSAGES: Readonly<Record<string, string>> = {\n payload_too_large: 'Request body is too large',\n rate_limited: 'Too many requests',\n upstream_unavailable: 'The checkout service is unavailable',\n gateway_timeout: 'The checkout service did not answer in time',\n not_found: 'Not found',\n}\n\n// Two envelopes reach the SDK: cope-core's `{errors: [{code, message}]}`, and\n// the `{error: \"<code>\", request_id}` cope-edge answers itself on the checkout\n// block — rate limit, body cap, unreachable upstream, deadline\n// (svcs/cope-edge/docs/errors.md). Plan 30 W2-47.\nfunction parseErrorBody(body: unknown): ApiErrorEntry[] | null {\n if (!isRecord(body)) return null\n if (Array.isArray(body.errors) && body.errors.length > 0 && body.errors.every(isApiErrorEntry)) return body.errors\n if (typeof body.error === 'string' && body.error.length > 0) {\n // Edge's `error` is a snake_case code; anything else is prose some other\n // upstream put there, which must not masquerade as a code callers switch on.\n return /^[a-z][a-z0-9_]*$/.test(body.error)\n ? [{ code: body.error, message: EDGE_ERROR_MESSAGES[body.error] ?? body.error }]\n : [{ code: 'unknown', message: body.error }]\n }\n return null\n}\n\nfunction isApiErrorEntry(value: unknown): value is ApiErrorEntry {\n return isRecord(value) && typeof value.code === 'string' && typeof value.message === 'string'\n}\n\n// `Retry-After` is either delta-seconds or an HTTP-date (RFC 9110 §10.2.3).\nfunction parseRetryAfter(value: string | null): number | null {\n if (value === null || value.trim() === '') return null\n if (/^\\d+$/.test(value.trim())) return Number(value.trim())\n const at = Date.parse(value)\n return Number.isNaN(at) ? null : Math.max(0, Math.ceil((at - Date.now()) / 1000))\n}\n\nfunction bodyRequestId(body: unknown): string | null {\n return isRecord(body) && typeof body.request_id === 'string' ? body.request_id : null\n}\n\nfunction normalizeOneClickChargeConsent(value: unknown): OneClickChargeConsentApplicability {\n if (!isRecord(value)) {\n return { applicable: false, terms_version: null }\n }\n\n const termsVersion = value.terms_version\n if (\n value.applicable !== true\n || typeof termsVersion !== 'string'\n || !SUPPORTED_ONE_CLICK_CHARGE_TERMS_VERSIONS.has(termsVersion)\n ) {\n return { applicable: false, terms_version: null }\n }\n\n return { applicable: true, terms_version: termsVersion }\n}\n\nfunction normalizeCart(cart: Cart): Cart {\n return {\n ...cart,\n one_click_charge_consent: normalizeOneClickChargeConsent(cart.one_click_charge_consent),\n }\n}\n\n// Both guards read the exported protocol lists rather than repeating the\n// union: a second hand-maintained copy is exactly how `already_completed`\n// came to be emitted by the bridge and dropped here.\nconst CHECKOUT_EMBED_ERROR_CODE_SET: ReadonlySet<string> = new Set(CHECKOUT_EMBED_ERROR_CODES)\nconst CHECKOUT_EMBED_TERMINAL_STATUS_SET: ReadonlySet<string> = new Set(CHECKOUT_EMBED_TERMINAL_STATUSES)\n\nfunction isCheckoutEmbedErrorCode(value: string): value is CheckoutEmbedErrorCode {\n return CHECKOUT_EMBED_ERROR_CODE_SET.has(value)\n}\n\nfunction isCheckoutEmbedTerminalStatus(value: string): value is CheckoutEmbedTerminalPayload['status'] {\n return CHECKOUT_EMBED_TERMINAL_STATUS_SET.has(value)\n}\n\nfunction isPostPurchaseOfferStepKind(value: string): value is PostPurchaseOfferStepKind {\n return value === 'upsell' || value === 'downsell'\n}\n\nfunction isPostPurchaseDecisionStatus(value: string): value is PostPurchaseDecisionStatus {\n return (\n value === 'accepted'\n || value === 'declined'\n || value === 'failed_not_charged'\n || value === 'requires_action'\n )\n}\n\nfunction isPostPurchaseChargeStatus(value: string): value is PostPurchaseChargeStatus {\n return (\n value === 'not_charged'\n || value === 'charged'\n || value === 'requires_action'\n || value === 'failed'\n )\n}\n\nfunction isPostPurchaseTerminalStatus(value: string): value is PostPurchaseTerminalStatus {\n return (\n value === 'completed'\n || value === 'declined'\n || value === 'expired'\n || value === 'unavailable'\n )\n}\n\nfunction currentWindowOrigin(): string {\n const location = window.location\n if (location.origin) return location.origin\n\n const host = location.host || [location.hostname, location.port].filter(Boolean).join(':')\n return new URL(`${location.protocol}//${host}`).origin\n}\n\nfunction normalizeCheckoutUrls(absoluteUrl: string): { checkoutUrl: string; embedCheckoutUrl: string } {\n const checkoutUrl = new URL(absoluteUrl)\n const embedCheckoutUrl = new URL(absoluteUrl)\n const embedMatch = checkoutUrl.pathname.match(/^\\/checkout\\/embed\\/([^/]+)$/)\n const checkoutMatch = checkoutUrl.pathname.match(/^\\/checkout\\/([^/]+)$/)\n\n if (embedMatch) {\n checkoutUrl.pathname = `/checkout/${embedMatch[1]}`\n embedCheckoutUrl.pathname = `/checkout/embed/${embedMatch[1]}`\n return {\n checkoutUrl: checkoutUrl.toString(),\n embedCheckoutUrl: embedCheckoutUrl.toString(),\n }\n }\n\n if (checkoutMatch) {\n checkoutUrl.pathname = `/checkout/${checkoutMatch[1]}`\n embedCheckoutUrl.pathname = `/checkout/embed/${checkoutMatch[1]}`\n return {\n checkoutUrl: checkoutUrl.toString(),\n embedCheckoutUrl: embedCheckoutUrl.toString(),\n }\n }\n\n throw new CopeError('Checkout URL path cannot be mapped to COPE checkout routes')\n}\n\nfunction checkoutEmbedToken(embedCheckoutUrl: string): string {\n const url = new URL(embedCheckoutUrl)\n const match = url.pathname.match(/^\\/checkout\\/embed\\/([^/]+)$/)\n if (!match) {\n throw new CopeError('Checkout embed URL path cannot be mapped to COPE checkout embed route')\n }\n\n return decodeURIComponent(match[1])\n}\n\nfunction checkoutEmbedOrigin(raw: CheckoutCreateResponse): string | undefined {\n const embed = raw.embed\n if (!isRecord(embed)) return undefined\n if (embed.allowed !== true) return undefined\n if (typeof embed.parent_origin !== 'string') return undefined\n\n try {\n const origin = new URL(embed.parent_origin).origin\n return origin === embed.parent_origin ? embed.parent_origin : undefined\n } catch {\n return undefined\n }\n}\n\nfunction parseCheckoutEmbedEvent(data: unknown): CheckoutEmbedEvent | null {\n if (!isRecord(data)) return null\n if (data.source !== CHECKOUT_MESSAGE_SOURCE) return null\n if (data.version !== CHECKOUT_MESSAGE_VERSION) return null\n\n const metadata = {\n ...(typeof data.messageId === 'string' ? { messageId: data.messageId } : {}),\n ...(typeof data.timestamp === 'string' ? { timestamp: data.timestamp } : {}),\n }\n\n if (data.type === 'ready') {\n return { type: 'ready', ...metadata }\n }\n\n if (data.type === 'resize') {\n if (!isRecord(data.payload)) return null\n const { height } = data.payload\n if (typeof height !== 'number' || !Number.isFinite(height) || height <= 0) return null\n return {\n type: 'resize',\n payload: { height: Math.ceil(height) },\n ...metadata,\n }\n }\n\n if (data.type === 'error') {\n if (!isRecord(data.payload)) return null\n const { code, retryable } = data.payload\n if (typeof code !== 'string' || !isCheckoutEmbedErrorCode(code)) return null\n if (typeof retryable !== 'boolean') return null\n return {\n type: 'error',\n payload: { code, retryable },\n ...metadata,\n }\n }\n\n if (data.type === 'terminal') {\n if (!isRecord(data.payload)) return null\n const { status } = data.payload\n if (typeof status !== 'string' || !isCheckoutEmbedTerminalStatus(status)) return null\n return {\n type: 'terminal',\n payload: { status },\n ...metadata,\n }\n }\n\n // Only recognized fields are ever read off `data.payload` below — this is what\n // keeps the sanitization guarantee: any extra keys the iframe message might\n // carry (token, cart_secret, client_secret, email, ...) are never copied into\n // the object handed to callbacks.\n if (data.type === 'post_purchase_offer') {\n if (!isRecord(data.payload)) return null\n const { offerRef, stepKind, title, priceGrossMinorUnits, currency } = data.payload\n if (typeof offerRef !== 'string' || !offerRef) return null\n if (typeof stepKind !== 'string' || !isPostPurchaseOfferStepKind(stepKind)) return null\n if (typeof title !== 'string' || !title) return null\n if (typeof priceGrossMinorUnits !== 'number' || !Number.isFinite(priceGrossMinorUnits) || priceGrossMinorUnits < 0) return null\n if (typeof currency !== 'string' || !currency) return null\n return {\n type: 'post_purchase_offer',\n payload: { offerRef, stepKind, title, priceGrossMinorUnits, currency },\n ...metadata,\n }\n }\n\n if (data.type === 'post_purchase_decision') {\n if (!isRecord(data.payload)) return null\n const { offerRef, status, chargeStatus } = data.payload\n if (typeof offerRef !== 'string' || !offerRef) return null\n if (typeof status !== 'string' || !isPostPurchaseDecisionStatus(status)) return null\n if (typeof chargeStatus !== 'string' || !isPostPurchaseChargeStatus(chargeStatus)) return null\n return {\n type: 'post_purchase_decision',\n payload: { offerRef, status, chargeStatus },\n ...metadata,\n }\n }\n\n if (data.type === 'post_purchase_terminal') {\n if (!isRecord(data.payload)) return null\n const { status } = data.payload\n if (typeof status !== 'string' || !isPostPurchaseTerminalStatus(status)) return null\n return {\n type: 'post_purchase_terminal',\n payload: { status },\n ...metadata,\n }\n }\n\n return null\n}\n\n/**\n * COPE SDK — browser client for the checkout API cope-edge serves under `/api/cart/v1`.\n *\n * Usage:\n * ```ts\n * const cope = new CopeCart({ publishableKey: 'cope_pk_...' })\n * const cart = await cope.createCart({ currency: 'EUR' })\n * await cope.addLine(cart.id, { product_id: 'uuid-123' })\n * await cope.reprice(cart.id)\n * const checkout = await cope.checkout(cart.id, { success_url: '...', cancel_url: '...', consents: [{ type: 'buyer_tos' }] })\n * cope.redirectToCheckout(checkout)\n * ```\n */\nexport class CopeCart {\n private readonly publishableKey: string\n private readonly baseUrl: string\n private readonly checkoutBaseUrl: string\n private readonly persistence: 'localStorage' | 'none'\n private readonly abortController: AbortController\n private readonly mountCleanups = new Set<MountCleanup>()\n private cachedSecret: string | null = null\n private cachedCartId: string | null = null\n\n /** The active cart ID from localStorage, or null if no cart exists. */\n get currentCartId(): string | null {\n return this.cachedCartId\n }\n\n constructor(options: CopeCartOptions) {\n if (!options.publishableKey?.startsWith('cope_pk_')) {\n throw new CopeError('Invalid publishableKey. Must start with \"cope_pk_\".')\n }\n\n if (typeof window !== 'undefined' && window.location?.protocol === 'http:' && window.location.hostname !== 'localhost') {\n throw new CopeError('CopeCart SDK requires HTTPS. Refusing to operate on an insecure page.')\n }\n\n this.publishableKey = options.publishableKey\n // An origin only. @copecart/sdk's docs told integrators to pass\n // `.../gateway/cart_api`; carried over, it would 404 on every call rather\n // than fail here where the cause is visible.\n const baseOrigin = originOnly(options.baseUrl ?? DEFAULT_BASE_URL)\n if (baseOrigin === null) {\n throw new CopeError('Invalid baseUrl. Pass an origin such as \"https://app.cope.com\"; the SDK adds /api/cart/v1 itself.')\n }\n this.baseUrl = baseOrigin\n this.checkoutBaseUrl = options.checkoutBaseUrl\n ? options.checkoutBaseUrl.replace(/\\/+$/, '')\n : new URL(this.baseUrl).origin\n this.abortController = new AbortController()\n // A client handed a cart acts on that cart only: it must not read, overwrite or\n // clear the page's stored cart, which belongs to whichever client created it.\n this.persistence = options.cart ? 'none' : (options.persistence ?? 'localStorage')\n\n if (options.cart) {\n this.cachedCartId = options.cart.id\n this.cachedSecret = options.cart.secret\n } else {\n this.hydrateFromStorage()\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n async createCart(payload: CreateCartPayload): Promise<Cart> {\n return this.createCartRequest(payload, { skipAuth: true })\n }\n\n async getProduct(productUuid: string): Promise<SdkProduct> {\n return this.get<SdkProduct>(`/products/${seg(productUuid)}`, { skipAuth: true })\n }\n\n async getCart(cartId: string): Promise<Cart> {\n const cart = normalizeCart(await this.get<Cart>(`/carts/${seg(cartId)}`))\n if (TERMINAL_STATES.has(cart.state)) {\n this.clearStorage()\n throw new CopeCartExpiredError(cart.state)\n }\n return cart\n }\n\n async addLine(cartId: string, payload: AddLinePayload): Promise<Cart> {\n return normalizeCart(await this.post<Cart>(`/carts/${seg(cartId)}/lines`, payload))\n }\n\n async updateLine(cartId: string, lineId: string, payload: UpdateLinePayload): Promise<Cart> {\n return normalizeCart(await this.patch<Cart>(`/carts/${seg(cartId)}/lines/${seg(lineId)}`, payload))\n }\n\n async removeLine(cartId: string, lineId: string): Promise<Cart> {\n return normalizeCart(await this.del<Cart>(`/carts/${seg(cartId)}/lines/${seg(lineId)}`))\n }\n\n async setBuyerIdentity(cartId: string, payload: UpdateBuyerIdentityPayload): Promise<Cart> {\n return normalizeCart(await this.patch<Cart>(`/carts/${seg(cartId)}/buyer-identity`, payload))\n }\n\n async reprice(cartId: string): Promise<Cart> {\n return normalizeCart(await this.post<Cart>(`/carts/${seg(cartId)}/reprice`, {}))\n }\n\n async applyPromoCode(cartId: string, code: string): Promise<Cart> {\n return normalizeCart(await this.post<Cart>(`/carts/${seg(cartId)}/promo_code`, { code }))\n }\n\n async removePromoCode(cartId: string): Promise<Cart> {\n return normalizeCart(await this.del<Cart>(`/carts/${seg(cartId)}/promo_code`))\n }\n\n async checkout(cartId: string, payload: CheckoutPayload, options: CheckoutOptions = {}): Promise<CheckoutResult> {\n return this.createCheckoutResult(cartId, payload,\n options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : undefined)\n }\n\n async createPrefilledCheckout(input: PrefilledCheckoutInput): Promise<PrefilledCheckoutResult> {\n const lines = this.normalizePrefilledLines(input)\n const raw = await this.post<PrefilledCheckoutCreateResponse>('/prefilled-checkouts', {\n external_reference: input.externalReference,\n currency: input.currency,\n ...(input.locale != null ? { locale: input.locale } : {}),\n ...(input.attribution ? { attribution: input.attribution } : {}),\n ...(input.intendedPaymentMethod != null ? { intended_payment_method: input.intendedPaymentMethod } : {}),\n ...(input.metadata ? { metadata: input.metadata } : {}),\n lines: lines.map((line) => ({\n product_id: line.productId,\n ...(line.planId !== undefined ? { plan_id: line.planId } : {}),\n ...(line.quantity !== undefined ? { quantity: line.quantity } : {}),\n })),\n buyer_identity: input.buyerIdentity,\n checkout: input.checkout,\n }, {\n skipAuth: true,\n idempotencyKey: await this.prefilledIdempotencyKey(input.externalReference),\n })\n const checkout = this.normalizeCheckoutResult(raw)\n\n return {\n cartId: raw.cart_id,\n cartVersion: raw.cart_version,\n checkoutId: checkout.checkoutId,\n checkoutToken: raw.checkout_token ?? checkoutEmbedToken(checkout.embedCheckoutUrl),\n checkoutUrl: checkout.checkoutUrl,\n embedCheckoutUrl: checkout.embedCheckoutUrl,\n ...(checkout.embedOrigin ? { embedOrigin: checkout.embedOrigin } : {}),\n status: checkout.status,\n expiresAt: checkout.expiresAt,\n totals: checkout.totals,\n ...(input.intendedPaymentMethod != null ? { intendedPaymentMethod: input.intendedPaymentMethod } : {}),\n }\n }\n\n async cancelCheckout(checkoutId: string): Promise<void> {\n await this.requestVoid('POST', `/checkouts/${seg(checkoutId)}/cancel`)\n }\n\n redirectToCheckout(checkout: CheckoutResult): void {\n if (this.abortController.signal.aborted) return\n if (typeof window !== 'undefined') {\n window.location.href = checkout.checkoutUrl\n }\n }\n\n mountCheckout(checkout: CheckoutResult | MountableCheckout, options: MountCheckoutOptions): MountedCheckout\n mountCheckout(target: HTMLElement | string, checkout: CheckoutResult | MountableCheckout, options?: MountCheckoutCallbacks): MountedCheckout\n mountCheckout(\n checkoutOrTarget: CheckoutResult | MountableCheckout | HTMLElement | string,\n optionsOrCheckout: MountCheckoutOptions | CheckoutResult | MountableCheckout,\n maybeOptions: MountCheckoutCallbacks = {},\n ): MountedCheckout {\n if (this.abortController.signal.aborted) {\n throw new CopeError('SDK destroyed')\n }\n\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new CopeError('mountCheckout requires a browser environment')\n }\n\n const { checkout, options } = this.normalizeMountCheckoutArgs(\n checkoutOrTarget,\n optionsOrCheckout,\n maybeOptions,\n )\n // Validation first: every check below reads caller-supplied input, and until\n // this method accepted a bare embed URL that input was origin-proven by\n // construction — it could only have come from normalizeCheckoutResult, which\n // refuses a foreign origin. Accepting `embed_url` straight out of an API\n // response removes that proof, so the two URLs are re-checked here before any\n // DOM is touched or any token is parsed.\n const allowedOrigin = this.checkoutOrigin()\n this.assertCopeOrigin(checkout.embedCheckoutUrl, allowedOrigin, 'Checkout embed URL')\n\n if (!checkout.embedOrigin) {\n throw new CopeError(\n 'mountCheckout requires checkout.embedOrigin — send embed_origin on checkout() or on '\n + 'create-offer, and register the origin in dashboard Settings',\n )\n }\n\n // The `checkoutUrl` sink is strictly worse than the frame's: `fallback:\n // 'redirect'` navigates the buyer's TOP window, so an unvalidated value would\n // hand the whole page to another origin mid-checkout.\n //\n // It is also deliberately NOT derived from the embed URL. For an offer the\n // recovery page is `public_url` (/offers/:uuid), which renders the offer's\n // state; the hosted checkout route would refuse in exactly the cases the\n // fallback exists for, and it carries the payment-capable access token into the\n // address bar and browser history. Refuse at mount rather than at the buyer's\n // eight-second timeout, so this is an integration error, never a runtime one.\n let fallbackUrl: string | undefined\n if (options.fallback === 'redirect') {\n if (!checkout.checkoutUrl) {\n throw new CopeError(\n \"mountCheckout with fallback: 'redirect' requires checkout.checkoutUrl — for an offer, \"\n + 'pass its public_url',\n )\n }\n this.assertCopeOrigin(checkout.checkoutUrl, allowedOrigin, 'Checkout URL')\n fallbackUrl = checkout.checkoutUrl\n }\n\n const target = this.resolveMountTarget(options.target)\n const iframe = document.createElement('iframe')\n const checkoutOrigin = new URL(checkout.embedCheckoutUrl).origin\n const mountMessage: CheckoutMountMessage = {\n type: CHECKOUT_MOUNT_MESSAGE_TYPE,\n version: CHECKOUT_MOUNT_MESSAGE_VERSION,\n token: checkoutEmbedToken(checkout.embedCheckoutUrl),\n }\n const parentOrigin = currentWindowOrigin()\n let destroyed = false\n let ready = false\n let mountAttempts = 0\n // The DOM timer id. Not ReturnType<typeof window.setInterval>: that picks\n // the last overload, which is Node's Timeout once @types/node is loaded.\n let mountRetry: number | undefined\n let readyTimeout: number | undefined\n\n if (checkout.embedOrigin !== parentOrigin) {\n throw new CopeError(`Checkout embed origin ${checkout.embedOrigin} does not match current origin ${parentOrigin}`)\n }\n\n iframe.src = checkout.embedCheckoutUrl\n iframe.title = options.title ?? 'COPE checkout'\n iframe.setAttribute('allow', 'payment *')\n iframe.referrerPolicy = 'no-referrer'\n iframe.style.border = '0'\n iframe.style.width = '100%'\n iframe.style.minHeight = '720px'\n if (options.className) {\n iframe.className = options.className\n }\n\n const clearMountRetry = () => {\n if (mountRetry !== undefined) {\n window.clearInterval(mountRetry)\n mountRetry = undefined\n }\n }\n\n const clearReadyTimeout = () => {\n if (readyTimeout !== undefined) {\n window.clearTimeout(readyTimeout)\n readyTimeout = undefined\n }\n }\n\n const cleanup = () => {\n if (destroyed) return\n destroyed = true\n clearMountRetry()\n clearReadyTimeout()\n window.removeEventListener('message', handleMessage)\n iframe.removeEventListener('load', handleIframeLoad)\n iframe.remove()\n this.mountCleanups.delete(cleanup)\n }\n\n const postMountMessage = () => {\n if (destroyed || ready) return\n if (mountAttempts >= CHECKOUT_MOUNT_MAX_ATTEMPTS) {\n clearMountRetry()\n return\n }\n\n mountAttempts += 1\n iframe.contentWindow?.postMessage(mountMessage, checkoutOrigin)\n }\n\n const startMountHandshake = () => {\n if (destroyed) return\n mountAttempts = 0\n clearMountRetry()\n postMountMessage()\n mountRetry = window.setInterval(postMountMessage, CHECKOUT_MOUNT_RETRY_INTERVAL_MS)\n }\n\n /**\n * Re-arm the handshake on every completed navigation inside the frame.\n *\n * A redirect payment method (Klarna / iDEAL / other BNPL) navigates the\n * iframe away to the provider and back to `/checkout/embed/<token>`. The\n * returning document is a brand-new bridge sitting in `awaiting-mount`, and\n * it will not proceed until the parent proves it knows the token again.\n * Without this the embed hangs forever after any redirect payment.\n *\n * `load` fires on the parent for cross-origin navigations too, so this also\n * runs while the frame is on the provider's page. That is safe: the mount\n * message is posted with `targetOrigin = checkoutOrigin`, so the browser\n * drops it rather than leaking the checkout token to the provider.\n *\n * The ready timeout is deliberately NOT re-armed. It is a one-shot\n * \"the embed never loaded\" guard for the initial mount. Re-arming it would\n * fire `onError({ code: 'load_failed' })` — or, under\n * `fallback: 'redirect'`, navigate the vendor's top window away — eight\n * seconds after the buyer lands on the provider's page, mid-payment. The\n * parent cannot tell those two loads apart: a cross-origin frame exposes\n * neither its location nor whether a `postMessage` was delivered.\n *\n * So the returning document owns reporting its own failure instead: the\n * bridge posts `error` even when it blocks before it has a validated\n * policy, which is why the parent can drop the timer here without going\n * silent after a redirect payment. The one case neither side covers is a\n * return the browser refuses to render at all (the embed origin was\n * disabled while the buyer was at the provider, so the response carries\n * `frame-ancestors 'none'`): no document runs, and nothing can report.\n */\n const handleIframeLoad = () => {\n if (destroyed) return\n ready = false\n startMountHandshake()\n }\n\n const handleMessage = (event: MessageEvent<unknown>) => {\n if (destroyed) return\n if (event.origin !== checkoutOrigin) return\n if (event.source !== iframe.contentWindow) return\n\n const message = parseCheckoutEmbedEvent(event.data)\n if (!message) return\n\n options.onMessage?.(message)\n if (message.type === 'ready') {\n ready = true\n clearMountRetry()\n clearReadyTimeout()\n options.onReady?.()\n } else if (message.type === 'resize') {\n iframe.style.height = `${message.payload.height}px`\n options.onResize?.(message.payload)\n } else if (message.type === 'error') {\n // A bridge that reports an error has already accepted the handshake, so\n // there is nothing left to retry and no missing load to time out. Both\n // timers must stop here or the ready timeout still fires eight seconds\n // later with a bogus `load_failed` (or a top-window fallback redirect).\n clearMountRetry()\n clearReadyTimeout()\n options.onError?.(message.payload)\n } else if (message.type === 'terminal') {\n clearMountRetry()\n clearReadyTimeout()\n options.onTerminal?.(message.payload)\n // Only a live `completed` is a success. `already_completed` means the\n // buyer paid before this mount, so re-running vendor fulfilment would\n // double-grant; `processing` is an asynchronous rail that has not\n // settled yet.\n if (message.payload.status === 'completed') {\n options.onSuccess?.()\n } else if (message.payload.status === 'cancelled') {\n options.onCancel?.()\n }\n } else if (message.type === 'post_purchase_offer') {\n options.onPostPurchaseOffer?.(message.payload)\n } else if (message.type === 'post_purchase_decision') {\n options.onPostPurchaseDecision?.(message.payload)\n } else if (message.type === 'post_purchase_terminal') {\n options.onPostPurchaseTerminal?.(message.payload)\n }\n }\n\n window.addEventListener('message', handleMessage)\n iframe.addEventListener('load', handleIframeLoad)\n this.mountCleanups.add(cleanup)\n\n try {\n target.appendChild(iframe)\n startMountHandshake()\n readyTimeout = window.setTimeout(() => {\n if (destroyed || ready) return\n if (options.fallback === 'redirect') {\n options.onFallbackRedirect?.()\n window.location.href = fallbackUrl as string\n return\n }\n\n options.onError?.({ code: 'load_failed', retryable: true })\n }, options.readyTimeoutMs ?? CHECKOUT_READY_TIMEOUT_MS)\n } catch (error) {\n cleanup()\n throw error\n }\n\n return { iframe, destroy: cleanup }\n }\n\n destroy(): void {\n for (const cleanup of Array.from(this.mountCleanups)) {\n cleanup()\n }\n this.abortController.abort()\n this.clearStorage()\n }\n\n // ---------------------------------------------------------------------------\n // HTTP methods\n // ---------------------------------------------------------------------------\n\n private async createCartRequest(payload: CreateCartPayload, opts?: RequestOptions): Promise<Cart> {\n // POST /carts renders the cart without `lines` or `buyer_identity`\n // (apps/cope-core carts_controller.rb `create`: CartBlueprint's default view,\n // unmasked). A new cart has neither, and the payload cannot supply them.\n const created = await this.post<Cart>('/carts', payload, opts)\n const cart = normalizeCart({ ...created, lines: created.lines ?? [], buyer_identity: created.buyer_identity ?? null })\n if (cart.cart_secret) {\n this.cachedCartId = cart.id\n this.cachedSecret = cart.cart_secret\n this.persistToStorage()\n }\n return cart\n }\n\n private async createCheckoutResult(cartId: string, payload: CheckoutPayload, opts?: RequestOptions): Promise<CheckoutResult> {\n const raw = await this.post<CheckoutCreateResponse>(`/carts/${seg(cartId)}/checkout`, payload, opts)\n return this.normalizeCheckoutResult(raw)\n }\n\n private normalizeCheckoutResult(raw: CheckoutCreateResponse): CheckoutResult {\n const absoluteUrl = raw.checkout_url.startsWith('http')\n ? raw.checkout_url\n : `${this.checkoutBaseUrl}${raw.checkout_url}`\n\n // Validate redirect URL belongs to expected origin\n this.assertCopeOrigin(absoluteUrl, this.checkoutOrigin(), 'Checkout URL')\n\n const urls = normalizeCheckoutUrls(absoluteUrl)\n\n return {\n checkoutId: raw.checkout_id,\n checkoutUrl: urls.checkoutUrl,\n embedCheckoutUrl: urls.embedCheckoutUrl,\n embedOrigin: checkoutEmbedOrigin(raw),\n status: raw.status,\n expiresAt: raw.expires_at,\n totals: raw.totals,\n }\n }\n\n private async requestVoid(method: HttpMethod, path: string, body?: unknown): Promise<void> {\n await this.request<unknown>(method, path, body)\n }\n\n private async get<T>(path: string, opts?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, undefined, opts)\n }\n\n private async post<T>(path: string, body: unknown, opts?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, body, opts)\n }\n\n private async patch<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>('PATCH', path, body)\n }\n\n private async del<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path)\n }\n\n private async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n opts?: RequestOptions,\n ): Promise<T> {\n if (this.abortController.signal.aborted) {\n throw new CopeError('SDK destroyed')\n }\n\n const url = `${this.baseUrl}/api/cart/v1${path}`\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'X-Cope-Key': this.publishableKey,\n }\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json'\n }\n\n if (!opts?.skipAuth && this.cachedSecret) {\n headers['Authorization'] = `CartSecret ${this.cachedSecret}`\n }\n\n // Idempotency key for POST — same key across retries\n const idempotencyKey = method === 'POST' ? (opts?.idempotencyKey ?? crypto.randomUUID()) : undefined\n if (idempotencyKey) {\n headers['Idempotency-Key'] = idempotencyKey\n }\n\n const maxAttempts = (method === 'GET' || (method === 'POST' && this.isRetryablePath(path))) ? 2 : 1\n // A retry after an ambiguous failure (5xx, timeout, network) may re-run a write the\n // server already committed; only a GET, or a POST cope-core deduplicates by\n // Idempotency-Key, survives that. A 429 is refused before processing, so it is safe.\n const replaySafe = this.isReplaySafe(method, path)\n let lastError: unknown\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (attempt > 0) {\n const delay = this.calculateRetryDelay(attempt - 1)\n await this.sleep(delay)\n }\n\n const timeoutController = new AbortController()\n const timeout = setTimeout(() => timeoutController.abort(), REQUEST_TIMEOUT_MS)\n const signal = AbortSignal.any([this.abortController.signal, timeoutController.signal])\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal,\n })\n\n if (response.ok) {\n if (response.status === 204) return undefined as T\n return (await response.json()) as T\n }\n\n // Parse error body\n const errorBody: unknown = await response.json().catch(() => null)\n const errors = parseErrorBody(errorBody) ?? [{ code: 'unknown', message: response.statusText }]\n const requestId = response.headers.get('X-Request-Id') ?? bodyRequestId(errorBody)\n const retryAfter = parseRetryAfter(response.headers.get('Retry-After'))\n\n // Retry on 5xx / 429\n if (this.shouldRetry(response.status) && attempt < maxAttempts - 1 && (replaySafe || response.status === 429)) {\n lastError = new CopeApiError(response.status, errors, requestId, retryAfter)\n continue\n }\n\n throw new CopeApiError(response.status, errors, requestId, retryAfter)\n } catch (error) {\n if (error instanceof CopeApiError) throw error\n if (error instanceof CopeCartExpiredError) throw error\n\n // AbortError from SDK destroy\n if (this.abortController.signal.aborted) {\n throw new CopeError('SDK destroyed')\n }\n\n // Network or timeout error — retry only where a replay cannot duplicate a write\n if (attempt < maxAttempts - 1 && replaySafe) {\n lastError = error\n continue\n }\n\n const msg = error instanceof Error ? error.message : 'Network error'\n throw new CopeNetworkError(msg)\n } finally {\n clearTimeout(timeout)\n }\n }\n\n // Should not reach here, but just in case\n throw lastError instanceof Error ? lastError : new CopeNetworkError('Request failed')\n }\n\n private shouldRetry(status: number): boolean {\n return status === 429 || status >= 500\n }\n\n private isRetryablePath(path: string): boolean {\n return !path.includes('/checkout')\n }\n\n // The SDK POSTs cope-core's IdempotencyMiddleware deduplicates\n // (CART_POST_ROUTES, apps/cope-core/app/middleware/idempotency_middleware.rb).\n // Checkout creation is deduplicated too, but isRetryablePath keeps it single-shot.\n private isReplaySafe(method: string, path: string): boolean {\n return method === 'GET' || (method === 'POST' && path === '/prefilled-checkouts')\n }\n\n private calculateRetryDelay(attempt: number): number {\n const exponential = RETRY_INITIAL_DELAY_MS * Math.pow(2, attempt)\n const capped = Math.min(exponential, RETRY_MAX_DELAY_MS)\n return capped * (0.5 + Math.random() * 0.5)\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n\n private normalizePrefilledLines(input: PrefilledCheckoutInput): readonly PrefilledCheckoutLineInput[] {\n if (!isRecord(input)) {\n throw new CopeError('createPrefilledCheckout requires an input object')\n }\n\n if (!input.externalReference) {\n throw new CopeError('createPrefilledCheckout requires externalReference for backend idempotency')\n }\n\n if (input.line != null && input.lines != null) {\n throw new CopeError('Use either line or lines for createPrefilledCheckout, not both')\n }\n\n if (input.line != null) {\n return [input.line]\n }\n\n if (input.lines == null || input.lines.length === 0) {\n throw new CopeError('createPrefilledCheckout requires at least one line')\n }\n\n return input.lines\n }\n\n // Injective in the reference: two different references never share a key.\n // A reference that is already header-safe and short keeps the readable\n // `prefilled:<reference>:cart`; any other is SHA-256'd whole, under a `#`\n // prefix no readable key can contain, instead of being rewritten or cut —\n // `INV/2026/1` and `INV-2026-1` used to share a key, and the second checkout\n // got 422 idempotency_body_mismatch for the replay TTL.\n private async prefilledIdempotencyKey(externalReference: string): Promise<string> {\n if (/^[A-Za-z0-9._:-]{1,120}$/.test(externalReference)) return `prefilled:${externalReference}:cart`\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(externalReference))\n const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('')\n return `prefilled#${hex}:cart`\n }\n\n // One definition of \"an origin this SDK is configured to talk to\", used by the\n // mount guards and by normalizeCheckoutResult, so the two cannot drift.\n private checkoutOrigin(): string {\n return new URL(this.checkoutBaseUrl).origin\n }\n\n private assertCopeOrigin(url: string, allowedOrigin: string, label: string): void {\n const origin = new URL(url).origin\n if (origin !== allowedOrigin) {\n throw new CopeError(`${label} origin ${origin} does not match expected ${allowedOrigin}`)\n }\n }\n\n private resolveMountTarget(target: HTMLElement | string): HTMLElement {\n // The IIFE bundle ships to untyped JS, where the checkout-first form can be\n // called with the callbacks object alone. Without this the mount got as far as\n // `undefined.appendChild` and surfaced a raw DOM TypeError instead of saying\n // what was missing.\n if (target == null) {\n throw new CopeError('mountCheckout requires options.target')\n }\n if (typeof target !== 'string') return target\n\n const element = document.querySelector(target)\n if (element instanceof HTMLElement) return element\n\n throw new CopeError(`mountCheckout target \"${target}\" was not found`)\n }\n\n private normalizeMountCheckoutArgs(\n checkoutOrTarget: CheckoutResult | MountableCheckout | HTMLElement | string,\n optionsOrCheckout: MountCheckoutOptions | CheckoutResult | MountableCheckout,\n maybeOptions: MountCheckoutCallbacks,\n ): { checkout: CheckoutResult | MountableCheckout; options: MountCheckoutOptions } {\n if (this.isMountableCheckout(checkoutOrTarget)) {\n return {\n checkout: checkoutOrTarget,\n options: optionsOrCheckout as MountCheckoutOptions,\n }\n }\n\n if (!this.isMountableCheckout(optionsOrCheckout)) {\n throw new CopeError('mountCheckout requires a checkout with embedCheckoutUrl')\n }\n\n return {\n checkout: optionsOrCheckout,\n options: { ...maybeOptions, target: checkoutOrTarget },\n }\n }\n\n // Also the overload discriminator: the target-first form passes an element or\n // a selector string, neither of which carries an embedCheckoutUrl.\n private isMountableCheckout(value: unknown): value is CheckoutResult | MountableCheckout {\n if (!isRecord(value)) return false\n return typeof value.embedCheckoutUrl === 'string'\n }\n\n // ---------------------------------------------------------------------------\n // localStorage persistence\n // ---------------------------------------------------------------------------\n\n private get storageEnabled(): boolean {\n return this.persistence === 'localStorage' && typeof localStorage !== 'undefined'\n }\n\n private hydrateFromStorage(): void {\n if (!this.storageEnabled) return\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n if (raw) {\n const parsed = JSON.parse(raw) as { cartId?: string; secret?: string }\n this.cachedCartId = parsed.cartId ?? null\n this.cachedSecret = parsed.secret ?? null\n }\n } catch {\n // Corrupted or unavailable storage — ignore\n }\n }\n\n private persistToStorage(): void {\n if (!this.storageEnabled) return\n try {\n localStorage.setItem(\n STORAGE_KEY,\n JSON.stringify({ cartId: this.cachedCartId, secret: this.cachedSecret }),\n )\n } catch {\n // Storage full or unavailable — SDK still works via in-memory cache\n }\n }\n\n private clearStorage(): void {\n this.cachedCartId = null\n this.cachedSecret = null\n if (!this.storageEnabled) return\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Ignore\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/cope-cart.ts"],"names":["CopeError","message","CopeApiError","status","errors","requestId","retryAfter","first","CopeNetworkError","CopeCartExpiredError","state","CHECKOUT_EMBED_ERROR_CODES","CHECKOUT_EMBED_TERMINAL_STATUSES","TERMINAL_STATES","DEFAULT_BASE_URL","STORAGE_KEY","REQUEST_TIMEOUT_MS","RETRY_INITIAL_DELAY_MS","RETRY_MAX_DELAY_MS","CHECKOUT_MESSAGE_SOURCE","CHECKOUT_MESSAGE_VERSION","CHECKOUT_MOUNT_MESSAGE_TYPE","CHECKOUT_MOUNT_MESSAGE_VERSION","CHECKOUT_MOUNT_RETRY_INTERVAL_MS","CHECKOUT_MOUNT_MAX_ATTEMPTS","CHECKOUT_READY_TIMEOUT_MS","SUPPORTED_ONE_CLICK_CHARGE_TERMS_VERSIONS","seg","id","isRecord","value","originOnly","url","EDGE_ERROR_MESSAGES","parseErrorBody","body","isApiErrorEntry","MONTHS","ASCTIME","asctimeToUtc","monthName","day","hh","mm","ss","year","fields","at","back","i","parseRetryAfter","trimmed","asctime","bodyRequestId","normalizeOneClickChargeConsent","termsVersion","normalizeCart","cart","CHECKOUT_EMBED_ERROR_CODE_SET","CHECKOUT_EMBED_TERMINAL_STATUS_SET","isCheckoutEmbedErrorCode","isCheckoutEmbedTerminalStatus","isPostPurchaseOfferStepKind","isPostPurchaseDecisionStatus","isPostPurchaseChargeStatus","isPostPurchaseTerminalStatus","currentWindowOrigin","location","host","normalizeCheckoutUrls","absoluteUrl","checkoutUrl","embedCheckoutUrl","embedMatch","checkoutMatch","checkoutEmbedToken","match","checkoutEmbedOrigin","raw","embed","parseCheckoutEmbedEvent","data","metadata","height","code","retryable","offerRef","stepKind","title","priceGrossMinorUnits","currency","chargeStatus","Cope","options","baseOrigin","payload","productUuid","cartId","lineId","input","lines","line","checkout","checkoutId","checkoutOrTarget","optionsOrCheckout","maybeOptions","allowedOrigin","fallbackUrl","target","iframe","checkoutOrigin","mountMessage","parentOrigin","destroyed","ready","mountAttempts","mountRetry","readyTimeout","clearMountRetry","clearReadyTimeout","cleanup","handleMessage","handleIframeLoad","postMountMessage","startMountHandshake","event","error","opts","created","urls","method","path","headers","idempotencyKey","maxAttempts","replaySafe","lastError","attempt","delay","timeoutController","timeout","signal","response","errorBody","msg","exponential","ms","resolve","externalReference","digest","byte","label","origin","element","parsed","CopeCart"],"mappings":"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","file":"index.js","sourcesContent":["// ---------------------------------------------------------------------------\n// Error classes\n// ---------------------------------------------------------------------------\n\nexport class CopeError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CopeError'\n }\n}\n\nexport class CopeApiError extends CopeError {\n readonly code: ApiErrorCode\n readonly status: number\n readonly field?: string\n readonly requestId: string | null\n /** Seconds the server asked the caller to wait (`Retry-After`), or null. */\n readonly retryAfter: number | null\n readonly errors: ReadonlyArray<{ readonly code: string; readonly message: string; readonly field?: string }>\n\n constructor(\n status: number,\n errors: Array<{ code: string; message: string; field?: string }>,\n requestId?: string | null,\n retryAfter?: number | null,\n ) {\n const first = errors[0]\n super(first?.message ?? `API error ${status}`)\n this.name = 'CopeApiError'\n this.status = status\n this.code = (first?.code ?? 'unknown') as ApiErrorCode\n this.field = first?.field\n this.requestId = requestId ?? null\n this.retryAfter = retryAfter ?? null\n this.errors = errors\n }\n}\n\nexport class CopeNetworkError extends CopeError {\n constructor(message: string) {\n super(message)\n this.name = 'CopeNetworkError'\n }\n}\n\nexport class CopeCartExpiredError extends CopeError {\n readonly state: CartState\n\n constructor(state: CartState) {\n super(`Cart is ${state} and cannot be used`)\n this.name = 'CopeCartExpiredError'\n this.state = state\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error codes — known codes + string escape hatch\n// ---------------------------------------------------------------------------\n\nexport type ApiErrorCode =\n // The codes the cart-API endpoints this SDK calls can answer.\n // tests/error-codes-agreement.test.ts holds this list to the literal codes in a\n // listed set of cope-core sources, in both directions; a code built at runtime\n // or emitted outside that set is not seen.\n | 'unauthorized'\n | 'invalid_sdk_key'\n | 'cart_id_mismatch'\n | 'not_found'\n | 'validation_error'\n | 'forbidden_field'\n | 'business_checkout_hold'\n | 'cart_not_active'\n | 'unsupported_currency'\n | 'unsupported_checkout_locale'\n | 'checkout_locale_not_allowed'\n | 'duplicate_line'\n | 'not_saleable'\n | 'product_unavailable'\n | 'insufficient_stock'\n | 'mixed_seller_cart'\n | 'mixed_vat_mode_cart'\n | 'empty_cart'\n | 'below_minimum_charge'\n | 'above_maximum_charge'\n | 'missing_tax_location'\n | 'cart_not_repriceable'\n | 'tax_address_invalid'\n | 'tax_request_rejected'\n | 'tax_service_unavailable'\n | 'invalid_redirect_url'\n | 'embed_origin_not_allowed'\n | 'price_changed'\n | 'checkout_expired'\n | 'checkout_not_cancellable'\n | 'checkout_payment_in_flight'\n | 'idempotency_conflict'\n | 'idempotency_body_mismatch'\n // A refused promo code (422), PromoCodes::Validate's reasons. `not_found` here\n // means no such code; it shares the name of the 404 code above.\n | 'inactive'\n | 'not_started'\n | 'expired'\n | 'exhausted'\n | 'no_applicable_items'\n | 'currency_not_supported'\n | 'promo_not_supported_for_recurring'\n | 'offer_sourced_no_promo'\n | 'promo_locked_during_payment'\n // Answered by cope-edge itself, in its `{error, request_id}` envelope.\n | 'payload_too_large'\n | 'rate_limited'\n | 'upstream_unavailable'\n | 'gateway_timeout'\n // Answered when the buyer's payment session is created on COPE's hosted\n // checkout page — an endpoint this SDK does not call. Kept for code that\n // switches on them; no SDK method returns them.\n | 'incomplete_buyer_identity'\n | 'incomplete_shipping_address'\n | 'missing_consent'\n | 'missing_withdrawal_waiver'\n | 'checkout_not_open'\n | 'payment_provider_error'\n | (string & {}) // escape hatch for unknown codes\n\n// ---------------------------------------------------------------------------\n// Cart\n// ---------------------------------------------------------------------------\n\nexport type CartState =\n | 'active'\n | 'checkout_in_progress'\n | 'ordered'\n | 'expired'\n | 'abandoned'\n | 'merged'\n\nexport interface OneClickChargeConsentApplicability {\n readonly applicable: boolean\n readonly terms_version: string | null\n}\n\nexport interface Cart {\n readonly id: string\n readonly state: CartState\n readonly version: number\n readonly currency: string\n readonly charge_currency: string\n /** Present only in the `createCart()` response. The SDK persists it to localStorage automatically. */\n readonly cart_secret?: string\n readonly lines: readonly CartLine[]\n /** Present only on a `setBuyerIdentity()` response that dropped a field, e.g. a malformed phone. */\n readonly field_errors?: readonly FieldError[]\n /**\n * `getCart()` masks the email (`j***n@example.com`); the `setBuyerIdentity()`\n * response carries it as saved.\n *\n * Absent where cope-core does not report it — the reprice and promo-code\n * responses — which is not the same as `null` (no buyer recorded yet).\n */\n readonly buyer_identity?: BuyerIdentity | null\n readonly totals: CartTotals | null\n readonly locale: string\n readonly applied_promo_code: AppliedPromoCode | null\n /** Backend-owned OTO candidate; absent while older backends roll forward. */\n readonly one_click_charge_consent?: OneClickChargeConsentApplicability | null\n}\n\n// ---------------------------------------------------------------------------\n// Cart Line\n// ---------------------------------------------------------------------------\n\nexport interface CartLine {\n /** The line's id: an integer (the cart API renders `cart_lines.id`, a bigint). */\n readonly id: number\n readonly cart_id: string\n readonly product_id: number\n readonly plan_id: number | null\n readonly quantity: number\n readonly price_snapshot: PriceSnapshot | null\n /** The product's name, present before the line is repriced (`price_snapshot` is null until then). */\n readonly product_name?: string | null\n readonly product_uuid: string\n readonly stale?: boolean\n readonly requires_shipping?: boolean\n readonly trial_days?: number\n readonly payment_methods: readonly string[]\n readonly plan_type: string | null\n}\n\nexport interface PriceSnapshot {\n readonly unit_price_minor_units: number\n readonly currency: string\n readonly charge_currency: string\n readonly product_name: string\n readonly plan_name: string | null\n readonly captured_at: string\n}\n\n// ---------------------------------------------------------------------------\n// Buyer Identity\n// ---------------------------------------------------------------------------\n\nexport interface Address {\n readonly line1: string\n readonly line2: string | null\n readonly city: string\n readonly region?: string | null\n readonly postal_code: string\n readonly country: string\n}\n\n/** The promo code on the cart and what it takes off (apps/cope-core CartBlueprint `applied_promo_code`). */\nexport interface AppliedPromoCode {\n readonly id: number\n readonly code: string\n readonly discount_total_minor_units: number\n /** True when the discount was trimmed to keep the order above the minimum charge. */\n readonly capped_to_minimum_charge: boolean\n}\n\nexport interface BuyerIdentity {\n readonly email: string\n readonly country: string\n readonly postal_code: string | null\n readonly company: string | null\n readonly buyer_type: 'b2b' | 'b2c' | null\n readonly billing_address: Address | null\n readonly shipping_address: Address | null\n readonly consents: readonly Consent[]\n}\n\nexport interface Consent {\n readonly type: string\n readonly granted_at: string\n readonly ip: string\n}\n\n// ---------------------------------------------------------------------------\n// Totals\n// ---------------------------------------------------------------------------\n\nexport type TotalsFinality = 'estimate' | 'final'\n\nexport interface CartTotals {\n readonly subtotal_minor_units: number\n readonly tax_minor_units: number\n readonly shipping_minor_units: number\n readonly discount_minor_units: number\n readonly total_minor_units: number\n /** Currency the *_minor_units are denominated in. Always equals `charge_currency`. */\n readonly currency: string\n /** Currency that will be billed (Stripe PaymentIntent.currency). */\n readonly charge_currency: string\n readonly finality: TotalsFinality\n /** Buyer's selected presentment currency, when different from `charge_currency`.\n * Paired with `presentment_exchange_rate`; both present or both absent.\n * To display amounts in presentment, multiply each `*_minor_units` by `presentment_exchange_rate`. */\n readonly presentment_currency?: string\n readonly presentment_exchange_rate?: number\n}\n\n// ---------------------------------------------------------------------------\n// Product (read-only, for getProduct)\n// ---------------------------------------------------------------------------\n\nexport interface SdkProduct {\n readonly uuid: string\n readonly name: string\n readonly headline: string | null\n readonly product_type: string\n readonly currency: string\n readonly payment_methods: readonly string[]\n readonly images: readonly SdkProductImage[]\n readonly payment_plans: readonly SdkPaymentPlan[]\n}\n\nexport interface SdkProductImage {\n readonly id: number\n readonly image_url: string\n}\n\nexport interface SdkPaymentPlan {\n readonly id: number\n readonly plan_type: 'one_time' | 'subscription' | 'installment'\n readonly position: number\n readonly currency: string\n readonly display_name: string | null\n /** Price as a decimal string, e.g. \"24.99\" (dollars, not cents despite the field name) */\n readonly first_payment_amount_cents: string\n readonly next_payments_amount_cents: string | null\n readonly next_payments_count: number | null\n readonly shipping_price_cents: string\n readonly charge_shipping_once: boolean\n readonly shipping_depend_on_quantity: boolean\n readonly interval: 'day' | 'week' | 'month' | 'year' | null\n readonly interval_count: number | null\n readonly second_payment_in: number | null\n readonly vanity_prices: readonly SdkVanityPrice[]\n}\n\nexport interface SdkVanityPrice {\n readonly id: number\n readonly currency: string\n readonly first_payment_amount_cents: string\n readonly next_payments_amount_cents: string | null\n}\n\n// ---------------------------------------------------------------------------\n// Checkout\n// ---------------------------------------------------------------------------\n\nexport type CheckoutStatus = 'open' | 'completed' | 'expired' | 'cancelled'\n\nexport interface CheckoutCreateEmbedPolicy {\n readonly allowed: true\n readonly parent_origin: string\n}\n\nexport interface CheckoutCreateResponse {\n readonly checkout_id: string\n readonly checkout_url: string\n readonly embed?: CheckoutCreateEmbedPolicy\n readonly status: CheckoutStatus\n readonly expires_at: string\n readonly totals: CartTotals\n readonly cart_version: number\n}\n\n// ---------------------------------------------------------------------------\n// SDK Options & Payloads\n// ---------------------------------------------------------------------------\n\nexport interface CopeOptions {\n readonly publishableKey: string\n readonly baseUrl?: string\n readonly checkoutBaseUrl?: string\n /**\n * Where the active cart's id and secret are kept between page loads.\n * `'localStorage'` (default) is right for one buyer in one browser. Use `'none'`\n * on a server, where one process serves many buyers: a process-wide store would\n * hand one buyer's cart secret to the next client. A client also holds its cart\n * secret in memory and sends it on every request, so a server needs one client\n * per buyer (or per request with `cart`), never one shared client.\n */\n readonly persistence?: 'localStorage' | 'none'\n /**\n * Act on an existing cart whose credentials the caller already holds. Implies\n * `persistence: 'none'`: such a client never reads, writes or clears stored carts.\n */\n readonly cart?: { readonly id: string; readonly secret: string }\n}\n\n/** @deprecated Use `CopeOptions`. */\nexport type CopeCartOptions = CopeOptions\n\nexport interface CheckoutOptions {\n /**\n * Sent as the Idempotency-Key. The cart API replays its stored answer to a\n * repeated key and identical body, so a caller that may re-send the same\n * checkout (an agent retrying a tool call) gets the same checkout back instead\n * of `cart_not_active` from a cart the first call already locked. While the first\n * call is still being processed, a repeat gets 409 `idempotency_conflict`; wait\n * briefly and repeat again.\n */\n readonly idempotencyKey?: string\n}\n\nexport interface CreateCartPayload {\n readonly currency: string\n readonly locale?: string\n readonly attribution?: CartAttribution\n readonly metadata?: CartMetadata\n}\n\nexport interface CartAttribution {\n readonly affiliate_id?: string\n readonly promo_code?: string\n readonly utm_source?: string\n readonly utm_medium?: string\n readonly utm_campaign?: string\n readonly utm_content?: string\n readonly utm_term?: string\n readonly landing_url?: string\n readonly referrer?: string\n readonly captured_at?: string\n}\n\nexport type CartMetadataValue =\n | string\n | number\n | boolean\n | null\n | readonly CartMetadataValue[]\n | { readonly [key: string]: CartMetadataValue }\n\nexport interface CartMetadata {\n readonly [key: string]: CartMetadataValue\n}\n\nexport interface AddLinePayload {\n /** Product UUID string — resolved to integer FK in API response (CartLine.product_id) */\n readonly product_id: string\n /** Optional payment plan ID. Omit it to let the API select the product's default plan. */\n readonly plan_id?: number\n readonly quantity?: number\n}\n\nexport interface UpdateLinePayload {\n readonly quantity?: number\n readonly plan_id?: number\n}\n\nexport interface UpdateBuyerIdentityPayload {\n readonly email?: string\n readonly first_name?: string\n readonly last_name?: string\n readonly country?: string\n readonly postal_code?: string\n readonly company?: string\n readonly buyer_type?: 'b2b' | 'b2c'\n readonly vat_id?: string\n readonly billing_address?: Partial<Address>\n readonly shipping_address?: Partial<Address>\n /**\n * Not blocking: a malformed phone is dropped and the rest of the identity is\n * saved, and the response says so in `field_errors`.\n */\n readonly phone?: string\n /** The buyer's checkout language; a locale the business has not enabled is ignored. */\n readonly locale?: string\n readonly consents?: ReadonlyArray<{ readonly type: string }>\n}\n\nexport interface CheckoutPayload {\n readonly success_url?: string\n readonly cancel_url?: string\n readonly embed_origin?: string\n /**\n * Recorded on the checkout when sent; not required to create it. When the\n * buyer's payment session is created, `buyer_tos` is required, and so is\n * `withdrawal_waiver` for a cart holding a product that does not ship (a digital\n * product). The hosted checkout page asks the buyer for both; send them here\n * only when the buyer has already given them on your page.\n */\n readonly consents?: ReadonlyArray<{ readonly type: string; readonly version?: string }>\n}\n\n/**\n * The minimum a checkout has to expose to be mounted in an iframe.\n *\n * `mountCheckout` reads exactly three things: `embedCheckoutUrl` (the frame's\n * src, and the source of the handshake token), `embedOrigin` (checked against\n * the hosting page), and `checkoutUrl` — the last only for `fallback:\n * 'redirect'`, which refuses to run without it rather than deriving one. It\n * never reads `checkoutId`, `totals`, `status` or `expiresAt`.\n *\n * Asking for a whole `CheckoutResult` therefore asked for four fields it does\n * not use, which shut out the caller that has no CheckoutResult to give: an\n * offer is created server-side and its API answers with `embed_url` +\n * `embed_origin`, no cart and no totals in sight. Integrators were left\n * inventing a `checkoutId` to satisfy a type, or hand-rolling the postMessage\n * handshake the SDK exists to own.\n *\n * `mountCheckout` accepts `CheckoutResult | MountableCheckout` rather than this\n * type alone, and the union is load-bearing: TypeScript excess-property-checks\n * an object LITERAL against its parameter type, so narrowing the parameter to\n * this interface would have rejected the seven-field literal integrators write\n * inline today — a compile break dressed up as a widening. Keeping\n * `CheckoutResult` in the union gives that literal an arm to match.\n */\nexport interface MountableCheckout {\n readonly embedCheckoutUrl: string\n /** Required: `mountCheckout` refuses to mount without it. */\n readonly embedOrigin: string\n /** Required only by `fallback: 'redirect'`; for an offer, pass `public_url`. */\n readonly checkoutUrl?: string\n}\n\nexport interface CheckoutResult {\n readonly checkoutId: string\n readonly checkoutUrl: string\n readonly embedCheckoutUrl: string\n readonly embedOrigin?: string\n readonly status: CheckoutStatus\n readonly expiresAt: string\n readonly totals: CartTotals\n}\n\nexport interface PrefilledCheckoutLineInput {\n readonly productId: string\n /** Optional payment plan ID. Omit it to let the API select the product's default plan. */\n readonly planId?: number\n readonly quantity?: number\n}\n\ninterface PrefilledCheckoutBaseInput {\n /**\n * Stable caller-side reference, e.g. an event sales session ID. The SDK uses\n * it for the backend Idempotency-Key and stores it as cart metadata. Distinct\n * references always get distinct keys: up to 120 characters of\n * `[A-Za-z0-9._:-]` are used as is, anything else is SHA-256'd whole. A replay\n * returns the stored handoff only for the cart API's 24-hour idempotency TTL;\n * after that the same reference creates a new cart and checkout.\n */\n readonly externalReference: string\n readonly currency: string\n readonly locale?: string\n readonly attribution?: CartAttribution\n /**\n * Non-sensitive reconciliation metadata. `external_reference` and\n * `intended_payment_method` are reserved metadata keys populated from the\n * matching top-level SDK fields.\n */\n readonly metadata?: CartMetadata\n readonly intendedPaymentMethod?: string\n /**\n * Let the hosted checkout page collect the buyer's email, country and postal\n * code instead of requiring them in `buyerIdentity`. Only with\n * `intendedPaymentMethod: 'hosted'`; the API refuses it otherwise.\n */\n readonly collectBuyerIdentityAtCheckout?: boolean\n readonly buyerIdentity: UpdateBuyerIdentityPayload\n readonly checkout: CheckoutPayload\n}\n\nexport type PrefilledCheckoutInput = PrefilledCheckoutBaseInput & (\n | {\n readonly line: PrefilledCheckoutLineInput\n readonly lines?: never\n }\n | {\n readonly line?: never\n readonly lines: readonly [PrefilledCheckoutLineInput, ...PrefilledCheckoutLineInput[]]\n }\n)\n\nexport interface PrefilledCheckoutResult {\n /**\n * Cart ID for logging and reconciliation only. The prefilled handoff response\n * intentionally excludes `cart_secret`, so this SDK instance cannot use this\n * cart ID for follow-up mutations such as `addLine`, `reprice`, or `checkout`.\n */\n readonly cartId: string\n readonly cartVersion: number\n readonly checkoutId: string\n readonly checkoutToken: string\n readonly checkoutUrl: string\n readonly embedCheckoutUrl: string\n readonly embedOrigin?: string\n readonly status: CheckoutStatus\n readonly expiresAt: string\n readonly totals: CartTotals\n readonly intendedPaymentMethod?: string\n /** Non-blocking notices, e.g. a malformed phone that was dropped. Absent when there are none. */\n readonly fieldErrors?: readonly FieldError[]\n}\n\n/** A non-blocking notice the API attaches to a successful response. */\nexport interface FieldError {\n readonly code: string\n readonly message: string\n readonly field: string\n}\n\n// ---------------------------------------------------------------------------\n// Checkout embed postMessage protocol — consumer half of a two-package contract\n// ---------------------------------------------------------------------------\n//\n// The producer is the hosted checkout embed bridge\n// (`apps/cope-frontend/lib/checkout/embed-protocol.ts` +\n// `apps/cope-frontend/app/checkout/embed/[token]/HostedCheckoutEmbedBridge.tsx`).\n// A status the bridge emits but this list omits is silently dropped by\n// `parseCheckoutEmbedEvent` — the parent frame then sees nothing at all, not\n// even an error. The two lists are asserted equal by\n// `tests/checkout-embed-protocol-contract.test.ts` (and by its mirror in the\n// frontend suite, so either package's CI lane catches a divergence).\n//\n// Do not add a value here without adding a producer on the bridge side, and do\n// not add one there without adding it here.\n\nexport const CHECKOUT_EMBED_ERROR_CODES = [\n 'not_found',\n 'load_failed',\n 'embed_not_allowed',\n 'confirm_failed',\n] as const\n\nexport type CheckoutEmbedErrorCode = (typeof CHECKOUT_EMBED_ERROR_CODES)[number]\nexport type CheckoutEmbedFallbackMode = 'redirect' | 'error'\n\n/**\n * Terminal states the mounted checkout can report.\n *\n * - `completed` — the order was placed in this session (live payment success).\n * - `already_completed` — the token resolved to a checkout that was paid\n * *before* this iframe mounted (refresh after success, bookmark, re-opened\n * offer link). The parent must not re-run fulfilment, so it does NOT fire\n * `onSuccess`.\n * - `processing` — an asynchronous rail (Klarna/iDEAL/BNPL/SEPA) accepted the\n * payment but Cart's authoritative order state is still `processing`. Not a\n * success: the parent should wait for its own server-side signal.\n * - `expired` / `cancelled` — the checkout or its offer is no longer payable.\n */\nexport const CHECKOUT_EMBED_TERMINAL_STATUSES = [\n 'expired',\n 'completed',\n 'already_completed',\n 'cancelled',\n 'processing',\n] as const\n\nexport type CheckoutEmbedTerminalStatus = (typeof CHECKOUT_EMBED_TERMINAL_STATUSES)[number]\n\nexport interface CheckoutEmbedErrorPayload {\n readonly code: CheckoutEmbedErrorCode\n readonly retryable: boolean\n}\n\nexport interface CheckoutEmbedTerminalPayload {\n readonly status: CheckoutEmbedTerminalStatus\n}\n\nexport interface CheckoutEmbedResizePayload {\n readonly height: number\n}\n\nexport interface CheckoutEmbedEventMetadata {\n readonly messageId?: string\n readonly timestamp?: string\n}\n\n// ---------------------------------------------------------------------------\n// Post-Purchase Offer (OTO) — native post-purchase upsell/downsell flow\n// ---------------------------------------------------------------------------\n//\n// These types mirror the backend post-purchase offer/decision contract for\n// typed consumption by SDK integrators. The SDK never fetches OTO state\n// directly — it only relays sanitized lifecycle events emitted by the\n// mounted checkout iframe (see `post_purchase_offer` / `post_purchase_decision`\n// / `post_purchase_terminal` in CheckoutEmbedEvent below). `offerRef` is an\n// opaque reference — no product/plan identifiers, checkout tokens, cart\n// secrets, payment client secrets, or buyer PII are ever included. The 3DS\n// step-up authentication for an accepted offer happens entirely inside the\n// COPE-owned iframe; the parent only ever learns `requires_action` as a status.\n\nexport type PostPurchaseOfferStepKind = 'upsell' | 'downsell'\n\n/**\n * Buyer's response to a presented offer. `requires_action` means a 3DS\n * step-up is in progress inside the COPE iframe — the payment client secret\n * never leaves that surface.\n */\nexport type PostPurchaseDecisionStatus = 'accepted' | 'declined' | 'failed_not_charged' | 'requires_action'\n\n/** Payment outcome for an accepted offer, tracked separately from the buyer-facing decision status. */\nexport type PostPurchaseChargeStatus = 'not_charged' | 'charged' | 'requires_action' | 'failed'\n\n/** Final state of the overall post-purchase offer flow. */\nexport type PostPurchaseTerminalStatus = 'completed' | 'declined' | 'expired' | 'unavailable'\n\n/** Sanitized offer display fields — no product/plan IDs, only an opaque `offerRef`. */\nexport interface PostPurchaseOffer {\n readonly offerRef: string\n readonly stepKind: PostPurchaseOfferStepKind\n readonly title: string\n readonly priceGrossMinorUnits: number\n readonly currency: string\n}\n\n/** Sanitized decision outcome for a single offer. */\nexport interface PostPurchaseOutcome {\n readonly offerRef: string\n readonly status: PostPurchaseDecisionStatus\n readonly chargeStatus: PostPurchaseChargeStatus\n}\n\nexport type PostPurchaseOfferPayload = PostPurchaseOffer\nexport type PostPurchaseDecisionPayload = PostPurchaseOutcome\n\nexport interface PostPurchaseTerminalPayload {\n readonly status: PostPurchaseTerminalStatus\n}\n\nexport type CheckoutEmbedEvent =\n | ({ readonly type: 'ready' } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'error'; readonly payload: CheckoutEmbedErrorPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'terminal'; readonly payload: CheckoutEmbedTerminalPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'resize'; readonly payload: CheckoutEmbedResizePayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'post_purchase_offer'; readonly payload: PostPurchaseOfferPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'post_purchase_decision'; readonly payload: PostPurchaseDecisionPayload } & CheckoutEmbedEventMetadata)\n | ({ readonly type: 'post_purchase_terminal'; readonly payload: PostPurchaseTerminalPayload } & CheckoutEmbedEventMetadata)\n\nexport interface CheckoutMountMessage {\n readonly type: 'copecart.checkout.mount'\n readonly version: 1\n readonly token: string\n}\n\nexport interface MountCheckoutOptions {\n readonly target: HTMLElement | string\n readonly title?: string\n readonly className?: string\n /**\n * What to do when the iframe never completes the trusted ready handshake.\n * Defaults to `error`; set `redirect` for a buyer-safe hosted checkout fallback.\n */\n readonly fallback?: CheckoutEmbedFallbackMode\n readonly readyTimeoutMs?: number\n /**\n * Called after a trusted `cope.checkout` ready message from the mounted checkout iframe.\n * `mountCheckout()` intentionally does not expose checkout tokens, cart secrets,\n * payment client secrets, or buyer PII through any callback payload.\n */\n readonly onReady?: () => void\n readonly onResize?: (payload: CheckoutEmbedResizePayload) => void\n readonly onError?: (payload: CheckoutEmbedErrorPayload) => void\n readonly onTerminal?: (payload: CheckoutEmbedTerminalPayload) => void\n readonly onSuccess?: () => void\n readonly onCancel?: () => void\n readonly onFallbackRedirect?: () => void\n /**\n * Called when the mounted checkout iframe presents a post-purchase offer\n * (native OTO upsell/downsell). The payload is sanitized: display fields\n * and an opaque `offerRef` only — never a product/plan ID, checkout token,\n * cart secret, payment client secret, or buyer PII.\n */\n readonly onPostPurchaseOffer?: (payload: PostPurchaseOfferPayload) => void\n /**\n * Called when the buyer decides on a post-purchase offer. `requires_action`\n * means a 3DS step-up is happening inside the COPE iframe — the payment\n * client secret is never forwarded here.\n */\n readonly onPostPurchaseDecision?: (payload: PostPurchaseDecisionPayload) => void\n /** Called when the overall post-purchase offer flow reaches a final state. */\n readonly onPostPurchaseTerminal?: (payload: PostPurchaseTerminalPayload) => void\n readonly onMessage?: (event: CheckoutEmbedEvent) => void\n}\n\nexport type MountCheckoutCallbacks = Omit<MountCheckoutOptions, 'target'>\n\nexport interface MountedCheckout {\n /**\n * Hosted checkout iframe. The SDK sets `allow=\"payment *\"` and\n * `referrerPolicy=\"no-referrer\"`.\n *\n * The SDK intentionally omits a `sandbox` attribute: no sandbox token set has\n * been proven compatible with all required wallet, redirect, and payment\n * provider flows yet. Embedding is instead constrained by the registered\n * `embed_origin` contract plus strict postMessage origin/source checks.\n */\n readonly iframe: HTMLIFrameElement\n destroy(): void\n}\n","import type {\n AddLinePayload,\n Cart,\n CheckoutCreateResponse,\n CheckoutEmbedErrorCode,\n CheckoutEmbedEvent,\n CheckoutEmbedTerminalPayload,\n CheckoutMountMessage,\n CheckoutPayload,\n CheckoutOptions,\n CheckoutResult,\n CopeOptions,\n CreateCartPayload,\n FieldError,\n MountedCheckout,\n MountCheckoutCallbacks,\n MountCheckoutOptions,\n MountableCheckout,\n OneClickChargeConsentApplicability,\n PostPurchaseChargeStatus,\n PostPurchaseDecisionStatus,\n PostPurchaseOfferStepKind,\n PostPurchaseTerminalStatus,\n PrefilledCheckoutInput,\n PrefilledCheckoutLineInput,\n PrefilledCheckoutResult,\n SdkProduct,\n UpdateBuyerIdentityPayload,\n UpdateLinePayload,\n} from './types.js'\nimport {\n CHECKOUT_EMBED_ERROR_CODES,\n CHECKOUT_EMBED_TERMINAL_STATUSES,\n CopeApiError,\n CopeCartExpiredError,\n CopeError,\n CopeNetworkError,\n} from './types.js'\nimport type { CartState } from './types.js'\n\nconst TERMINAL_STATES: ReadonlySet<CartState> = new Set(['ordered', 'expired', 'abandoned', 'merged'])\n// The app host: requests go to `${baseUrl}/api/cart/v1/...`, which cope-edge's\n// checkout block serves there, and the hosted checkout's origin (derived from\n// this URL when checkoutBaseUrl is unset) is the same host.\nconst DEFAULT_BASE_URL = 'https://app.cope.com'\nconst STORAGE_KEY = 'cope_sdk_cart'\nconst REQUEST_TIMEOUT_MS = 8_000\nconst RETRY_INITIAL_DELAY_MS = 500\nconst RETRY_MAX_DELAY_MS = 5_000\nconst CHECKOUT_MESSAGE_SOURCE = 'cope.checkout'\nconst CHECKOUT_MESSAGE_VERSION = 1\nconst CHECKOUT_MOUNT_MESSAGE_TYPE = 'copecart.checkout.mount'\nconst CHECKOUT_MOUNT_MESSAGE_VERSION = 1\nconst CHECKOUT_MOUNT_RETRY_INTERVAL_MS = 250\nconst CHECKOUT_MOUNT_MAX_ATTEMPTS = 20\nconst CHECKOUT_READY_TIMEOUT_MS = 8_000\nconst SUPPORTED_ONE_CLICK_CHARGE_TERMS_VERSIONS: ReadonlySet<string> = new Set(['oto-v1'])\n\ntype HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE'\ntype MountCleanup = () => void\ntype RequestOptions = {\n readonly skipAuth?: boolean\n readonly idempotencyKey?: string\n}\ntype PrefilledCheckoutCreateResponse = CheckoutCreateResponse & {\n readonly cart_id: string\n readonly checkout_token?: string\n readonly field_errors?: readonly FieldError[]\n}\n\n// One path segment. Ids arrive from callers (and, through cope-sdk/mcp, from AI\n// agents); unencoded, `../buyer-identity` or a `?` would aim a request carrying\n// the cart secret at another route.\nfunction seg(id: string | number): string {\n return encodeURIComponent(String(id))\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\ntype ApiErrorEntry = { code: string; message: string; field?: string }\n\n// The normalized origin of a URL that is nothing but an origin — no path, query,\n// fragment or credentials — or null. `https://App.Cope.com:443/` is accepted and\n// becomes `https://app.cope.com`.\nfunction originOnly(value: string): string | null {\n try {\n const url = new URL(value)\n const bare = url.pathname === '/' && !url.search && !url.hash && !url.username && !url.password\n return bare ? url.origin : null\n } catch {\n return null\n }\n}\n\nconst EDGE_ERROR_MESSAGES: Readonly<Record<string, string>> = {\n payload_too_large: 'Request body is too large',\n rate_limited: 'Too many requests',\n upstream_unavailable: 'The checkout service is unavailable',\n gateway_timeout: 'The checkout service did not answer in time',\n not_found: 'Not found',\n}\n\n// Two envelopes reach the SDK: cope-core's `{errors: [{code, message}]}`, and\n// the `{error: \"<code>\", request_id}` cope-edge answers itself on the checkout\n// block — rate limit, body cap, unreachable upstream, deadline\n// (svcs/cope-edge/docs/errors.md). Plan 30 W2-47.\nfunction parseErrorBody(body: unknown): ApiErrorEntry[] | null {\n if (!isRecord(body)) return null\n if (Array.isArray(body.errors) && body.errors.length > 0 && body.errors.every(isApiErrorEntry)) return body.errors\n if (typeof body.error === 'string' && body.error.length > 0) {\n // Edge's `error` is a snake_case code; anything else is prose some other\n // upstream put there, which must not masquerade as a code callers switch on.\n return /^[a-z][a-z0-9_]*$/.test(body.error)\n ? [{ code: body.error, message: EDGE_ERROR_MESSAGES[body.error] ?? body.error }]\n : [{ code: 'unknown', message: body.error }]\n }\n return null\n}\n\nfunction isApiErrorEntry(value: unknown): value is ApiErrorEntry {\n return isRecord(value) && typeof value.code === 'string' && typeof value.message === 'string'\n}\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n// asctime, the one HTTP-date form that names no zone: `Sun Nov 6 08:49:37 1994`.\nconst ASCTIME = /^[A-Z][a-z]{2} ([A-Z][a-z]{2}) ([ \\d]\\d) (\\d{2}):(\\d{2}):(\\d{2}) (\\d{4})$/\n\n// NaN for a date that does not exist: Date.UTC rolls an unknown month (-1), day 39\n// or hour 99 over into a real instant, so the fields must survive a round trip.\nfunction asctimeToUtc([, monthName, day, hh, mm, ss, year]: RegExpExecArray): number {\n const fields = [Number(year), MONTHS.indexOf(monthName ?? ''), Number((day ?? '').trim()), Number(hh), Number(mm), Number(ss)]\n const at = Date.UTC(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5])\n const back = new Date(at)\n const roundTrip = [back.getUTCFullYear(), back.getUTCMonth(), back.getUTCDate(), back.getUTCHours(),\n back.getUTCMinutes(), back.getUTCSeconds()]\n return roundTrip.every((value, i) => value === fields[i]) ? at : Number.NaN\n}\n\n// `Retry-After` is either delta-seconds or an HTTP-date (RFC 9110 §10.2.3), and\n// every HTTP-date is GMT. `Date.parse` reads the asctime form in the HOST's zone,\n// so that form is read by hand; the other two say `GMT`, which Date.parse honours.\n// Anything else is ignored rather than guessed at.\nfunction parseRetryAfter(value: string | null): number | null {\n if (value === null) return null\n const trimmed = value.trim()\n if (/^\\d+$/.test(trimmed)) return Number(trimmed)\n const asctime = ASCTIME.exec(trimmed)\n const at = asctime ? asctimeToUtc(asctime) : / GMT$/.test(trimmed) ? Date.parse(trimmed) : Number.NaN\n return Number.isNaN(at) ? null : Math.max(0, Math.ceil((at - Date.now()) / 1000))\n}\n\nfunction bodyRequestId(body: unknown): string | null {\n return isRecord(body) && typeof body.request_id === 'string' ? body.request_id : null\n}\n\nfunction normalizeOneClickChargeConsent(value: unknown): OneClickChargeConsentApplicability {\n if (!isRecord(value)) {\n return { applicable: false, terms_version: null }\n }\n\n const termsVersion = value.terms_version\n if (\n value.applicable !== true\n || typeof termsVersion !== 'string'\n || !SUPPORTED_ONE_CLICK_CHARGE_TERMS_VERSIONS.has(termsVersion)\n ) {\n return { applicable: false, terms_version: null }\n }\n\n return { applicable: true, terms_version: termsVersion }\n}\n\nfunction normalizeCart(cart: Cart): Cart {\n return {\n ...cart,\n one_click_charge_consent: normalizeOneClickChargeConsent(cart.one_click_charge_consent),\n }\n}\n\n// Both guards read the exported protocol lists rather than repeating the\n// union: a second hand-maintained copy is exactly how `already_completed`\n// came to be emitted by the bridge and dropped here.\nconst CHECKOUT_EMBED_ERROR_CODE_SET: ReadonlySet<string> = new Set(CHECKOUT_EMBED_ERROR_CODES)\nconst CHECKOUT_EMBED_TERMINAL_STATUS_SET: ReadonlySet<string> = new Set(CHECKOUT_EMBED_TERMINAL_STATUSES)\n\nfunction isCheckoutEmbedErrorCode(value: string): value is CheckoutEmbedErrorCode {\n return CHECKOUT_EMBED_ERROR_CODE_SET.has(value)\n}\n\nfunction isCheckoutEmbedTerminalStatus(value: string): value is CheckoutEmbedTerminalPayload['status'] {\n return CHECKOUT_EMBED_TERMINAL_STATUS_SET.has(value)\n}\n\nfunction isPostPurchaseOfferStepKind(value: string): value is PostPurchaseOfferStepKind {\n return value === 'upsell' || value === 'downsell'\n}\n\nfunction isPostPurchaseDecisionStatus(value: string): value is PostPurchaseDecisionStatus {\n return (\n value === 'accepted'\n || value === 'declined'\n || value === 'failed_not_charged'\n || value === 'requires_action'\n )\n}\n\nfunction isPostPurchaseChargeStatus(value: string): value is PostPurchaseChargeStatus {\n return (\n value === 'not_charged'\n || value === 'charged'\n || value === 'requires_action'\n || value === 'failed'\n )\n}\n\nfunction isPostPurchaseTerminalStatus(value: string): value is PostPurchaseTerminalStatus {\n return (\n value === 'completed'\n || value === 'declined'\n || value === 'expired'\n || value === 'unavailable'\n )\n}\n\nfunction currentWindowOrigin(): string {\n const location = window.location\n if (location.origin) return location.origin\n\n const host = location.host || [location.hostname, location.port].filter(Boolean).join(':')\n return new URL(`${location.protocol}//${host}`).origin\n}\n\nfunction normalizeCheckoutUrls(absoluteUrl: string): { checkoutUrl: string; embedCheckoutUrl: string } {\n const checkoutUrl = new URL(absoluteUrl)\n const embedCheckoutUrl = new URL(absoluteUrl)\n const embedMatch = checkoutUrl.pathname.match(/^\\/checkout\\/embed\\/([^/]+)$/)\n const checkoutMatch = checkoutUrl.pathname.match(/^\\/checkout\\/([^/]+)$/)\n\n if (embedMatch) {\n checkoutUrl.pathname = `/checkout/${embedMatch[1]}`\n embedCheckoutUrl.pathname = `/checkout/embed/${embedMatch[1]}`\n return {\n checkoutUrl: checkoutUrl.toString(),\n embedCheckoutUrl: embedCheckoutUrl.toString(),\n }\n }\n\n if (checkoutMatch) {\n checkoutUrl.pathname = `/checkout/${checkoutMatch[1]}`\n embedCheckoutUrl.pathname = `/checkout/embed/${checkoutMatch[1]}`\n return {\n checkoutUrl: checkoutUrl.toString(),\n embedCheckoutUrl: embedCheckoutUrl.toString(),\n }\n }\n\n throw new CopeError('Checkout URL path cannot be mapped to COPE checkout routes')\n}\n\nfunction checkoutEmbedToken(embedCheckoutUrl: string): string {\n const url = new URL(embedCheckoutUrl)\n const match = url.pathname.match(/^\\/checkout\\/embed\\/([^/]+)$/)\n if (!match) {\n throw new CopeError('Checkout embed URL path cannot be mapped to COPE checkout embed route')\n }\n\n return decodeURIComponent(match[1])\n}\n\nfunction checkoutEmbedOrigin(raw: CheckoutCreateResponse): string | undefined {\n const embed = raw.embed\n if (!isRecord(embed)) return undefined\n if (embed.allowed !== true) return undefined\n if (typeof embed.parent_origin !== 'string') return undefined\n\n try {\n const origin = new URL(embed.parent_origin).origin\n return origin === embed.parent_origin ? embed.parent_origin : undefined\n } catch {\n return undefined\n }\n}\n\nfunction parseCheckoutEmbedEvent(data: unknown): CheckoutEmbedEvent | null {\n if (!isRecord(data)) return null\n if (data.source !== CHECKOUT_MESSAGE_SOURCE) return null\n if (data.version !== CHECKOUT_MESSAGE_VERSION) return null\n\n const metadata = {\n ...(typeof data.messageId === 'string' ? { messageId: data.messageId } : {}),\n ...(typeof data.timestamp === 'string' ? { timestamp: data.timestamp } : {}),\n }\n\n if (data.type === 'ready') {\n return { type: 'ready', ...metadata }\n }\n\n if (data.type === 'resize') {\n if (!isRecord(data.payload)) return null\n const { height } = data.payload\n if (typeof height !== 'number' || !Number.isFinite(height) || height <= 0) return null\n return {\n type: 'resize',\n payload: { height: Math.ceil(height) },\n ...metadata,\n }\n }\n\n if (data.type === 'error') {\n if (!isRecord(data.payload)) return null\n const { code, retryable } = data.payload\n if (typeof code !== 'string' || !isCheckoutEmbedErrorCode(code)) return null\n if (typeof retryable !== 'boolean') return null\n return {\n type: 'error',\n payload: { code, retryable },\n ...metadata,\n }\n }\n\n if (data.type === 'terminal') {\n if (!isRecord(data.payload)) return null\n const { status } = data.payload\n if (typeof status !== 'string' || !isCheckoutEmbedTerminalStatus(status)) return null\n return {\n type: 'terminal',\n payload: { status },\n ...metadata,\n }\n }\n\n // Only recognized fields are ever read off `data.payload` below — this is what\n // keeps the sanitization guarantee: any extra keys the iframe message might\n // carry (token, cart_secret, client_secret, email, ...) are never copied into\n // the object handed to callbacks.\n if (data.type === 'post_purchase_offer') {\n if (!isRecord(data.payload)) return null\n const { offerRef, stepKind, title, priceGrossMinorUnits, currency } = data.payload\n if (typeof offerRef !== 'string' || !offerRef) return null\n if (typeof stepKind !== 'string' || !isPostPurchaseOfferStepKind(stepKind)) return null\n if (typeof title !== 'string' || !title) return null\n if (typeof priceGrossMinorUnits !== 'number' || !Number.isFinite(priceGrossMinorUnits) || priceGrossMinorUnits < 0) return null\n if (typeof currency !== 'string' || !currency) return null\n return {\n type: 'post_purchase_offer',\n payload: { offerRef, stepKind, title, priceGrossMinorUnits, currency },\n ...metadata,\n }\n }\n\n if (data.type === 'post_purchase_decision') {\n if (!isRecord(data.payload)) return null\n const { offerRef, status, chargeStatus } = data.payload\n if (typeof offerRef !== 'string' || !offerRef) return null\n if (typeof status !== 'string' || !isPostPurchaseDecisionStatus(status)) return null\n if (typeof chargeStatus !== 'string' || !isPostPurchaseChargeStatus(chargeStatus)) return null\n return {\n type: 'post_purchase_decision',\n payload: { offerRef, status, chargeStatus },\n ...metadata,\n }\n }\n\n if (data.type === 'post_purchase_terminal') {\n if (!isRecord(data.payload)) return null\n const { status } = data.payload\n if (typeof status !== 'string' || !isPostPurchaseTerminalStatus(status)) return null\n return {\n type: 'post_purchase_terminal',\n payload: { status },\n ...metadata,\n }\n }\n\n return null\n}\n\n/**\n * COPE SDK — browser client for the checkout API cope-edge serves under `/api/cart/v1`.\n *\n * Usage:\n * ```ts\n * const cope = new Cope({ publishableKey: 'cope_pk_...' })\n * const cart = await cope.createCart({ currency: 'EUR' })\n * await cope.addLine(cart.id, { product_id: 'uuid-123' })\n * await cope.reprice(cart.id)\n * const checkout = await cope.checkout(cart.id, { success_url: '...', cancel_url: '...', consents: [{ type: 'buyer_tos' }] })\n * cope.redirectToCheckout(checkout)\n * ```\n */\nexport class Cope {\n private readonly publishableKey: string\n private readonly baseUrl: string\n private readonly checkoutBaseUrl: string\n private readonly persistence: 'localStorage' | 'none'\n private readonly abortController: AbortController\n private readonly mountCleanups = new Set<MountCleanup>()\n private cachedSecret: string | null = null\n private cachedCartId: string | null = null\n\n /** The active cart ID from localStorage, or null if no cart exists. */\n get currentCartId(): string | null {\n return this.cachedCartId\n }\n\n constructor(options: CopeOptions) {\n if (!options.publishableKey?.startsWith('cope_pk_')) {\n throw new CopeError('Invalid publishableKey. Must start with \"cope_pk_\".')\n }\n\n if (typeof window !== 'undefined' && window.location?.protocol === 'http:' && window.location.hostname !== 'localhost') {\n throw new CopeError('COPE SDK requires HTTPS. Refusing to operate on an insecure page.')\n }\n\n this.publishableKey = options.publishableKey\n // An origin only. @copecart/sdk's docs told integrators to pass\n // `.../gateway/cart_api`; carried over, it would 404 on every call rather\n // than fail here where the cause is visible.\n const baseOrigin = originOnly(options.baseUrl ?? DEFAULT_BASE_URL)\n if (baseOrigin === null) {\n throw new CopeError('Invalid baseUrl. Pass an origin such as \"https://app.cope.com\"; the SDK adds /api/cart/v1 itself.')\n }\n this.baseUrl = baseOrigin\n this.checkoutBaseUrl = options.checkoutBaseUrl\n ? options.checkoutBaseUrl.replace(/\\/+$/, '')\n : new URL(this.baseUrl).origin\n this.abortController = new AbortController()\n // A client handed a cart acts on that cart only: it must not read, overwrite or\n // clear the page's stored cart, which belongs to whichever client created it.\n this.persistence = options.cart ? 'none' : (options.persistence ?? 'localStorage')\n\n if (options.cart) {\n this.cachedCartId = options.cart.id\n this.cachedSecret = options.cart.secret\n } else {\n this.hydrateFromStorage()\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n async createCart(payload: CreateCartPayload): Promise<Cart> {\n return this.createCartRequest(payload, { skipAuth: true })\n }\n\n async getProduct(productUuid: string): Promise<SdkProduct> {\n return this.get<SdkProduct>(`/products/${seg(productUuid)}`, { skipAuth: true })\n }\n\n async getCart(cartId: string): Promise<Cart> {\n const cart = normalizeCart(await this.get<Cart>(`/carts/${seg(cartId)}`))\n if (TERMINAL_STATES.has(cart.state)) {\n this.clearStorage()\n throw new CopeCartExpiredError(cart.state)\n }\n return cart\n }\n\n async addLine(cartId: string, payload: AddLinePayload): Promise<Cart> {\n return normalizeCart(await this.post<Cart>(`/carts/${seg(cartId)}/lines`, payload))\n }\n\n /** `lineId` is the line's `id`, an integer; a string of its digits is accepted too. */\n async updateLine(cartId: string, lineId: number | string, payload: UpdateLinePayload): Promise<Cart> {\n return normalizeCart(await this.patch<Cart>(`/carts/${seg(cartId)}/lines/${seg(lineId)}`, payload))\n }\n\n /** `lineId` is the line's `id`, an integer; a string of its digits is accepted too. */\n async removeLine(cartId: string, lineId: number | string): Promise<Cart> {\n return normalizeCart(await this.del<Cart>(`/carts/${seg(cartId)}/lines/${seg(lineId)}`))\n }\n\n async setBuyerIdentity(cartId: string, payload: UpdateBuyerIdentityPayload): Promise<Cart> {\n return normalizeCart(await this.patch<Cart>(`/carts/${seg(cartId)}/buyer-identity`, payload))\n }\n\n async reprice(cartId: string): Promise<Cart> {\n return normalizeCart(await this.post<Cart>(`/carts/${seg(cartId)}/reprice`, {}))\n }\n\n async applyPromoCode(cartId: string, code: string): Promise<Cart> {\n return normalizeCart(await this.post<Cart>(`/carts/${seg(cartId)}/promo_code`, { code }))\n }\n\n async removePromoCode(cartId: string): Promise<Cart> {\n return normalizeCart(await this.del<Cart>(`/carts/${seg(cartId)}/promo_code`))\n }\n\n async checkout(cartId: string, payload: CheckoutPayload, options: CheckoutOptions = {}): Promise<CheckoutResult> {\n return this.createCheckoutResult(cartId, payload,\n options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : undefined)\n }\n\n async createPrefilledCheckout(input: PrefilledCheckoutInput): Promise<PrefilledCheckoutResult> {\n const lines = this.normalizePrefilledLines(input)\n const raw = await this.post<PrefilledCheckoutCreateResponse>('/prefilled-checkouts', {\n external_reference: input.externalReference,\n currency: input.currency,\n ...(input.locale != null ? { locale: input.locale } : {}),\n ...(input.attribution ? { attribution: input.attribution } : {}),\n ...(input.intendedPaymentMethod != null ? { intended_payment_method: input.intendedPaymentMethod } : {}),\n ...(input.metadata ? { metadata: input.metadata } : {}),\n ...(input.collectBuyerIdentityAtCheckout != null\n ? { collect_buyer_identity_at_checkout: input.collectBuyerIdentityAtCheckout }\n : {}),\n lines: lines.map((line) => ({\n product_id: line.productId,\n ...(line.planId !== undefined ? { plan_id: line.planId } : {}),\n ...(line.quantity !== undefined ? { quantity: line.quantity } : {}),\n })),\n buyer_identity: input.buyerIdentity,\n checkout: input.checkout,\n }, {\n skipAuth: true,\n idempotencyKey: await this.prefilledIdempotencyKey(input.externalReference),\n })\n const checkout = this.normalizeCheckoutResult(raw)\n\n return {\n cartId: raw.cart_id,\n cartVersion: raw.cart_version,\n checkoutId: checkout.checkoutId,\n checkoutToken: raw.checkout_token ?? checkoutEmbedToken(checkout.embedCheckoutUrl),\n checkoutUrl: checkout.checkoutUrl,\n embedCheckoutUrl: checkout.embedCheckoutUrl,\n ...(checkout.embedOrigin ? { embedOrigin: checkout.embedOrigin } : {}),\n status: checkout.status,\n expiresAt: checkout.expiresAt,\n totals: checkout.totals,\n ...(input.intendedPaymentMethod != null ? { intendedPaymentMethod: input.intendedPaymentMethod } : {}),\n ...(raw.field_errors?.length ? { fieldErrors: raw.field_errors } : {}),\n }\n }\n\n async cancelCheckout(checkoutId: string): Promise<void> {\n await this.requestVoid('POST', `/checkouts/${seg(checkoutId)}/cancel`)\n }\n\n redirectToCheckout(checkout: CheckoutResult): void {\n if (this.abortController.signal.aborted) return\n if (typeof window !== 'undefined') {\n window.location.href = checkout.checkoutUrl\n }\n }\n\n mountCheckout(checkout: CheckoutResult | MountableCheckout, options: MountCheckoutOptions): MountedCheckout\n mountCheckout(target: HTMLElement | string, checkout: CheckoutResult | MountableCheckout, options?: MountCheckoutCallbacks): MountedCheckout\n mountCheckout(\n checkoutOrTarget: CheckoutResult | MountableCheckout | HTMLElement | string,\n optionsOrCheckout: MountCheckoutOptions | CheckoutResult | MountableCheckout,\n maybeOptions: MountCheckoutCallbacks = {},\n ): MountedCheckout {\n if (this.abortController.signal.aborted) {\n throw new CopeError('SDK destroyed')\n }\n\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new CopeError('mountCheckout requires a browser environment')\n }\n\n const { checkout, options } = this.normalizeMountCheckoutArgs(\n checkoutOrTarget,\n optionsOrCheckout,\n maybeOptions,\n )\n // Validation first: every check below reads caller-supplied input, and until\n // this method accepted a bare embed URL that input was origin-proven by\n // construction — it could only have come from normalizeCheckoutResult, which\n // refuses a foreign origin. Accepting `embed_url` straight out of an API\n // response removes that proof, so the two URLs are re-checked here before any\n // DOM is touched or any token is parsed.\n const allowedOrigin = this.checkoutOrigin()\n this.assertCopeOrigin(checkout.embedCheckoutUrl, allowedOrigin, 'Checkout embed URL')\n\n if (!checkout.embedOrigin) {\n throw new CopeError(\n 'mountCheckout requires checkout.embedOrigin — send embed_origin on checkout() or on '\n + 'create-offer, and register the origin in dashboard Settings',\n )\n }\n\n // The `checkoutUrl` sink is strictly worse than the frame's: `fallback:\n // 'redirect'` navigates the buyer's TOP window, so an unvalidated value would\n // hand the whole page to another origin mid-checkout.\n //\n // It is also deliberately NOT derived from the embed URL. For an offer the\n // recovery page is `public_url` (/offers/:uuid), which renders the offer's\n // state; the hosted checkout route would refuse in exactly the cases the\n // fallback exists for, and it carries the payment-capable access token into the\n // address bar and browser history. Refuse at mount rather than at the buyer's\n // eight-second timeout, so this is an integration error, never a runtime one.\n let fallbackUrl: string | undefined\n if (options.fallback === 'redirect') {\n if (!checkout.checkoutUrl) {\n throw new CopeError(\n \"mountCheckout with fallback: 'redirect' requires checkout.checkoutUrl — for an offer, \"\n + 'pass its public_url',\n )\n }\n this.assertCopeOrigin(checkout.checkoutUrl, allowedOrigin, 'Checkout URL')\n fallbackUrl = checkout.checkoutUrl\n }\n\n const target = this.resolveMountTarget(options.target)\n const iframe = document.createElement('iframe')\n const checkoutOrigin = new URL(checkout.embedCheckoutUrl).origin\n const mountMessage: CheckoutMountMessage = {\n type: CHECKOUT_MOUNT_MESSAGE_TYPE,\n version: CHECKOUT_MOUNT_MESSAGE_VERSION,\n token: checkoutEmbedToken(checkout.embedCheckoutUrl),\n }\n const parentOrigin = currentWindowOrigin()\n let destroyed = false\n let ready = false\n let mountAttempts = 0\n // The DOM timer id. Not ReturnType<typeof window.setInterval>: that picks\n // the last overload, which is Node's Timeout once @types/node is loaded.\n let mountRetry: number | undefined\n let readyTimeout: number | undefined\n\n if (checkout.embedOrigin !== parentOrigin) {\n throw new CopeError(`Checkout embed origin ${checkout.embedOrigin} does not match current origin ${parentOrigin}`)\n }\n\n iframe.src = checkout.embedCheckoutUrl\n iframe.title = options.title ?? 'COPE checkout'\n iframe.setAttribute('allow', 'payment *')\n iframe.referrerPolicy = 'no-referrer'\n iframe.style.border = '0'\n iframe.style.width = '100%'\n iframe.style.minHeight = '720px'\n if (options.className) {\n iframe.className = options.className\n }\n\n const clearMountRetry = () => {\n if (mountRetry !== undefined) {\n window.clearInterval(mountRetry)\n mountRetry = undefined\n }\n }\n\n const clearReadyTimeout = () => {\n if (readyTimeout !== undefined) {\n window.clearTimeout(readyTimeout)\n readyTimeout = undefined\n }\n }\n\n const cleanup = () => {\n if (destroyed) return\n destroyed = true\n clearMountRetry()\n clearReadyTimeout()\n window.removeEventListener('message', handleMessage)\n iframe.removeEventListener('load', handleIframeLoad)\n iframe.remove()\n this.mountCleanups.delete(cleanup)\n }\n\n const postMountMessage = () => {\n if (destroyed || ready) return\n if (mountAttempts >= CHECKOUT_MOUNT_MAX_ATTEMPTS) {\n clearMountRetry()\n return\n }\n\n mountAttempts += 1\n iframe.contentWindow?.postMessage(mountMessage, checkoutOrigin)\n }\n\n const startMountHandshake = () => {\n if (destroyed) return\n mountAttempts = 0\n clearMountRetry()\n postMountMessage()\n mountRetry = window.setInterval(postMountMessage, CHECKOUT_MOUNT_RETRY_INTERVAL_MS)\n }\n\n /**\n * Re-arm the handshake on every completed navigation inside the frame.\n *\n * A redirect payment method (Klarna / iDEAL / other BNPL) navigates the\n * iframe away to the provider and back to `/checkout/embed/<token>`. The\n * returning document is a brand-new bridge sitting in `awaiting-mount`, and\n * it will not proceed until the parent proves it knows the token again.\n * Without this the embed hangs forever after any redirect payment.\n *\n * `load` fires on the parent for cross-origin navigations too, so this also\n * runs while the frame is on the provider's page. That is safe: the mount\n * message is posted with `targetOrigin = checkoutOrigin`, so the browser\n * drops it rather than leaking the checkout token to the provider.\n *\n * The ready timeout is deliberately NOT re-armed. It is a one-shot\n * \"the embed never loaded\" guard for the initial mount. Re-arming it would\n * fire `onError({ code: 'load_failed' })` — or, under\n * `fallback: 'redirect'`, navigate the vendor's top window away — eight\n * seconds after the buyer lands on the provider's page, mid-payment. The\n * parent cannot tell those two loads apart: a cross-origin frame exposes\n * neither its location nor whether a `postMessage` was delivered.\n *\n * So the returning document owns reporting its own failure instead: the\n * bridge posts `error` even when it blocks before it has a validated\n * policy, which is why the parent can drop the timer here without going\n * silent after a redirect payment. The one case neither side covers is a\n * return the browser refuses to render at all (the embed origin was\n * disabled while the buyer was at the provider, so the response carries\n * `frame-ancestors 'none'`): no document runs, and nothing can report.\n */\n const handleIframeLoad = () => {\n if (destroyed) return\n ready = false\n startMountHandshake()\n }\n\n const handleMessage = (event: MessageEvent<unknown>) => {\n if (destroyed) return\n if (event.origin !== checkoutOrigin) return\n if (event.source !== iframe.contentWindow) return\n\n const message = parseCheckoutEmbedEvent(event.data)\n if (!message) return\n\n options.onMessage?.(message)\n if (message.type === 'ready') {\n ready = true\n clearMountRetry()\n clearReadyTimeout()\n options.onReady?.()\n } else if (message.type === 'resize') {\n iframe.style.height = `${message.payload.height}px`\n options.onResize?.(message.payload)\n } else if (message.type === 'error') {\n // A bridge that reports an error has already accepted the handshake, so\n // there is nothing left to retry and no missing load to time out. Both\n // timers must stop here or the ready timeout still fires eight seconds\n // later with a bogus `load_failed` (or a top-window fallback redirect).\n clearMountRetry()\n clearReadyTimeout()\n options.onError?.(message.payload)\n } else if (message.type === 'terminal') {\n clearMountRetry()\n clearReadyTimeout()\n options.onTerminal?.(message.payload)\n // Only a live `completed` is a success. `already_completed` means the\n // buyer paid before this mount, so re-running vendor fulfilment would\n // double-grant; `processing` is an asynchronous rail that has not\n // settled yet.\n if (message.payload.status === 'completed') {\n options.onSuccess?.()\n } else if (message.payload.status === 'cancelled') {\n options.onCancel?.()\n }\n } else if (message.type === 'post_purchase_offer') {\n options.onPostPurchaseOffer?.(message.payload)\n } else if (message.type === 'post_purchase_decision') {\n options.onPostPurchaseDecision?.(message.payload)\n } else if (message.type === 'post_purchase_terminal') {\n options.onPostPurchaseTerminal?.(message.payload)\n }\n }\n\n window.addEventListener('message', handleMessage)\n iframe.addEventListener('load', handleIframeLoad)\n this.mountCleanups.add(cleanup)\n\n try {\n target.appendChild(iframe)\n startMountHandshake()\n readyTimeout = window.setTimeout(() => {\n if (destroyed || ready) return\n if (options.fallback === 'redirect') {\n options.onFallbackRedirect?.()\n window.location.href = fallbackUrl as string\n return\n }\n\n options.onError?.({ code: 'load_failed', retryable: true })\n }, options.readyTimeoutMs ?? CHECKOUT_READY_TIMEOUT_MS)\n } catch (error) {\n cleanup()\n throw error\n }\n\n return { iframe, destroy: cleanup }\n }\n\n destroy(): void {\n for (const cleanup of Array.from(this.mountCleanups)) {\n cleanup()\n }\n this.abortController.abort()\n this.clearStorage()\n }\n\n // ---------------------------------------------------------------------------\n // HTTP methods\n // ---------------------------------------------------------------------------\n\n private async createCartRequest(payload: CreateCartPayload, opts?: RequestOptions): Promise<Cart> {\n // POST /carts renders the cart without `lines` or `buyer_identity`\n // (apps/cope-core carts_controller.rb `create`: CartBlueprint's default view,\n // unmasked). A new cart has neither, and the payload cannot supply them.\n const created = await this.post<Cart>('/carts', payload, opts)\n const cart = normalizeCart({ ...created, lines: created.lines ?? [], buyer_identity: created.buyer_identity ?? null })\n if (cart.cart_secret) {\n this.cachedCartId = cart.id\n this.cachedSecret = cart.cart_secret\n this.persistToStorage()\n }\n return cart\n }\n\n private async createCheckoutResult(cartId: string, payload: CheckoutPayload, opts?: RequestOptions): Promise<CheckoutResult> {\n const raw = await this.post<CheckoutCreateResponse>(`/carts/${seg(cartId)}/checkout`, payload, opts)\n return this.normalizeCheckoutResult(raw)\n }\n\n private normalizeCheckoutResult(raw: CheckoutCreateResponse): CheckoutResult {\n const absoluteUrl = raw.checkout_url.startsWith('http')\n ? raw.checkout_url\n : `${this.checkoutBaseUrl}${raw.checkout_url}`\n\n // Validate redirect URL belongs to expected origin\n this.assertCopeOrigin(absoluteUrl, this.checkoutOrigin(), 'Checkout URL')\n\n const urls = normalizeCheckoutUrls(absoluteUrl)\n\n return {\n checkoutId: raw.checkout_id,\n checkoutUrl: urls.checkoutUrl,\n embedCheckoutUrl: urls.embedCheckoutUrl,\n embedOrigin: checkoutEmbedOrigin(raw),\n status: raw.status,\n expiresAt: raw.expires_at,\n totals: raw.totals,\n }\n }\n\n private async requestVoid(method: HttpMethod, path: string, body?: unknown): Promise<void> {\n await this.request<unknown>(method, path, body)\n }\n\n private async get<T>(path: string, opts?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, undefined, opts)\n }\n\n private async post<T>(path: string, body: unknown, opts?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, body, opts)\n }\n\n private async patch<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>('PATCH', path, body)\n }\n\n private async del<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path)\n }\n\n private async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n opts?: RequestOptions,\n ): Promise<T> {\n if (this.abortController.signal.aborted) {\n throw new CopeError('SDK destroyed')\n }\n\n const url = `${this.baseUrl}/api/cart/v1${path}`\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'X-Cope-Key': this.publishableKey,\n }\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json'\n }\n\n if (!opts?.skipAuth && this.cachedSecret) {\n headers['Authorization'] = `CartSecret ${this.cachedSecret}`\n }\n\n // Idempotency key for POST — same key across retries\n const idempotencyKey = method === 'POST' ? (opts?.idempotencyKey ?? crypto.randomUUID()) : undefined\n if (idempotencyKey) {\n headers['Idempotency-Key'] = idempotencyKey\n }\n\n const maxAttempts = (method === 'GET' || (method === 'POST' && this.isRetryablePath(path))) ? 2 : 1\n // A retry after an ambiguous failure (5xx, timeout, network) may re-run a write the\n // server already committed; only a GET, or a POST cope-core deduplicates by\n // Idempotency-Key, survives that. A 429 is refused before processing, so it is safe.\n const replaySafe = this.isReplaySafe(method, path)\n let lastError: unknown\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (attempt > 0) {\n const delay = this.calculateRetryDelay(attempt - 1)\n await this.sleep(delay)\n }\n\n const timeoutController = new AbortController()\n const timeout = setTimeout(() => timeoutController.abort(), REQUEST_TIMEOUT_MS)\n const signal = AbortSignal.any([this.abortController.signal, timeoutController.signal])\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal,\n })\n\n if (response.ok) {\n if (response.status === 204) return undefined as T\n return (await response.json()) as T\n }\n\n // Parse error body\n const errorBody: unknown = await response.json().catch(() => null)\n const errors = parseErrorBody(errorBody) ?? [{ code: 'unknown', message: response.statusText }]\n const requestId = response.headers.get('X-Request-Id') ?? bodyRequestId(errorBody)\n const retryAfter = parseRetryAfter(response.headers.get('Retry-After'))\n\n // Retry on 5xx / 429\n if (this.shouldRetry(response.status) && attempt < maxAttempts - 1 && (replaySafe || response.status === 429)) {\n lastError = new CopeApiError(response.status, errors, requestId, retryAfter)\n continue\n }\n\n throw new CopeApiError(response.status, errors, requestId, retryAfter)\n } catch (error) {\n if (error instanceof CopeApiError) throw error\n if (error instanceof CopeCartExpiredError) throw error\n\n // AbortError from SDK destroy\n if (this.abortController.signal.aborted) {\n throw new CopeError('SDK destroyed')\n }\n\n // Network or timeout error — retry only where a replay cannot duplicate a write\n if (attempt < maxAttempts - 1 && replaySafe) {\n lastError = error\n continue\n }\n\n const msg = error instanceof Error ? error.message : 'Network error'\n throw new CopeNetworkError(msg)\n } finally {\n clearTimeout(timeout)\n }\n }\n\n // Should not reach here, but just in case\n throw lastError instanceof Error ? lastError : new CopeNetworkError('Request failed')\n }\n\n private shouldRetry(status: number): boolean {\n return status === 429 || status >= 500\n }\n\n private isRetryablePath(path: string): boolean {\n return !path.includes('/checkout')\n }\n\n // The SDK POSTs cope-core's IdempotencyMiddleware deduplicates\n // (CART_POST_ROUTES, apps/cope-core/app/middleware/idempotency_middleware.rb).\n // Checkout creation is deduplicated too, but isRetryablePath keeps it single-shot.\n private isReplaySafe(method: string, path: string): boolean {\n return method === 'GET' || (method === 'POST' && path === '/prefilled-checkouts')\n }\n\n private calculateRetryDelay(attempt: number): number {\n const exponential = RETRY_INITIAL_DELAY_MS * Math.pow(2, attempt)\n const capped = Math.min(exponential, RETRY_MAX_DELAY_MS)\n return capped * (0.5 + Math.random() * 0.5)\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n\n private normalizePrefilledLines(input: PrefilledCheckoutInput): readonly PrefilledCheckoutLineInput[] {\n if (!isRecord(input)) {\n throw new CopeError('createPrefilledCheckout requires an input object')\n }\n\n if (!input.externalReference) {\n throw new CopeError('createPrefilledCheckout requires externalReference for backend idempotency')\n }\n\n if (input.line != null && input.lines != null) {\n throw new CopeError('Use either line or lines for createPrefilledCheckout, not both')\n }\n\n if (input.line != null) {\n return [input.line]\n }\n\n if (input.lines == null || input.lines.length === 0) {\n throw new CopeError('createPrefilledCheckout requires at least one line')\n }\n\n return input.lines\n }\n\n // Injective in the reference: two different references never share a key.\n // A reference that is already header-safe and short keeps the readable\n // `prefilled:<reference>:cart`; any other is SHA-256'd whole, under a `#`\n // prefix no readable key can contain, instead of being rewritten or cut —\n // `INV/2026/1` and `INV-2026-1` used to share a key, and the second checkout\n // got 422 idempotency_body_mismatch for the replay TTL.\n private async prefilledIdempotencyKey(externalReference: string): Promise<string> {\n if (/^[A-Za-z0-9._:-]{1,120}$/.test(externalReference)) return `prefilled:${externalReference}:cart`\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(externalReference))\n const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('')\n return `prefilled#${hex}:cart`\n }\n\n // One definition of \"an origin this SDK is configured to talk to\", used by the\n // mount guards and by normalizeCheckoutResult, so the two cannot drift.\n private checkoutOrigin(): string {\n return new URL(this.checkoutBaseUrl).origin\n }\n\n private assertCopeOrigin(url: string, allowedOrigin: string, label: string): void {\n const origin = new URL(url).origin\n if (origin !== allowedOrigin) {\n throw new CopeError(`${label} origin ${origin} does not match expected ${allowedOrigin}`)\n }\n }\n\n private resolveMountTarget(target: HTMLElement | string): HTMLElement {\n // The IIFE bundle ships to untyped JS, where the checkout-first form can be\n // called with the callbacks object alone. Without this the mount got as far as\n // `undefined.appendChild` and surfaced a raw DOM TypeError instead of saying\n // what was missing.\n if (target == null) {\n throw new CopeError('mountCheckout requires options.target')\n }\n if (typeof target !== 'string') return target\n\n const element = document.querySelector(target)\n if (element instanceof HTMLElement) return element\n\n throw new CopeError(`mountCheckout target \"${target}\" was not found`)\n }\n\n private normalizeMountCheckoutArgs(\n checkoutOrTarget: CheckoutResult | MountableCheckout | HTMLElement | string,\n optionsOrCheckout: MountCheckoutOptions | CheckoutResult | MountableCheckout,\n maybeOptions: MountCheckoutCallbacks,\n ): { checkout: CheckoutResult | MountableCheckout; options: MountCheckoutOptions } {\n if (this.isMountableCheckout(checkoutOrTarget)) {\n return {\n checkout: checkoutOrTarget,\n options: optionsOrCheckout as MountCheckoutOptions,\n }\n }\n\n if (!this.isMountableCheckout(optionsOrCheckout)) {\n throw new CopeError('mountCheckout requires a checkout with embedCheckoutUrl')\n }\n\n return {\n checkout: optionsOrCheckout,\n options: { ...maybeOptions, target: checkoutOrTarget },\n }\n }\n\n // Also the overload discriminator: the target-first form passes an element or\n // a selector string, neither of which carries an embedCheckoutUrl.\n private isMountableCheckout(value: unknown): value is CheckoutResult | MountableCheckout {\n if (!isRecord(value)) return false\n return typeof value.embedCheckoutUrl === 'string'\n }\n\n // ---------------------------------------------------------------------------\n // localStorage persistence\n // ---------------------------------------------------------------------------\n\n private get storageEnabled(): boolean {\n return this.persistence === 'localStorage' && typeof localStorage !== 'undefined'\n }\n\n private hydrateFromStorage(): void {\n if (!this.storageEnabled) return\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n if (raw) {\n const parsed = JSON.parse(raw) as { cartId?: string; secret?: string }\n this.cachedCartId = parsed.cartId ?? null\n this.cachedSecret = parsed.secret ?? null\n }\n } catch {\n // Corrupted or unavailable storage — ignore\n }\n }\n\n private persistToStorage(): void {\n if (!this.storageEnabled) return\n try {\n localStorage.setItem(\n STORAGE_KEY,\n JSON.stringify({ cartId: this.cachedCartId, secret: this.cachedSecret }),\n )\n } catch {\n // Storage full or unavailable — SDK still works via in-memory cache\n }\n }\n\n private clearStorage(): void {\n this.cachedCartId = null\n this.cachedSecret = null\n if (!this.storageEnabled) return\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Ignore\n }\n }\n}\n\n/**\n * The 0.1.0 name of {@link Cope}: the same class, so `instanceof` agrees across both names.\n * @deprecated Use `Cope`. `CopeCart` stays exported for code written against 0.1.0.\n */\nexport const CopeCart = Cope\n/** @deprecated Use `Cope`. */\nexport type CopeCart = Cope\n"]}