@tabcommerceio/buy-together-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/uuid.ts","../src/commerce.ts","../src/events.ts","../src/flush.ts","../src/observer.ts","../src/resolve.ts","../src/client.ts","../src/pdp-sequencer.ts","../src/quote-fence.ts"],"sourcesContent":["/** Single UUID helper shared by every Bundle SDK module to prevent drift. */\nexport const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\nexport const NIL_UUID = '00000000-0000-0000-0000-000000000000'\n\nexport function isUUID(value: string): boolean {\n return UUID_PATTERN.test(value)\n}\n\n/** Match the customer API's canonical, non-nil UUID boundary. */\nexport function isCanonicalUUID(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value !== NIL_UUID &&\n value === value.toLowerCase() &&\n isUUID(value)\n )\n}\n\nexport function createUUID(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (character) => {\n const random = (Math.random() * 16) | 0\n const nibble = character === 'x' ? random : (random & 0x3) | 0x8\n return nibble.toString(16)\n })\n}\n","import type {\n BundleCartOffer,\n BundleComponent,\n BundleTrackInput,\n CartLineLike,\n FetchLike,\n} from './types'\n\nimport { createUUID, isCanonicalUUID } from './uuid'\n\nconst VARIANT_GID = /^gid:\\/\\/shopify\\/ProductVariant\\/([1-9]\\d*)$/\nconst PRODUCT_GID = /^gid:\\/\\/shopify\\/Product\\/([1-9]\\d*)$/\n\n/**\n * `failed` is a proven clean no-op: a successful fresh cart read showed that\n * nothing of this instance reached the cart, so no compensation ran.\n * `compensated` means partially written lines were zeroed.\n * `recoverable_error` covers every unproven outcome: instance lines whose\n * cart/update.js compensation failed, and double network failures where the\n * add may have been accepted but the cart read could not prove either way.\n * Callers must not blind-retry a `recoverable_error` as if it were `failed`.\n */\nexport type BundleAddResult =\n | { status: 'added' }\n | { status: 'failed' }\n | { status: 'compensated' }\n | { status: 'recoverable_error' }\n\nexport type AddBundleToCartOptions = {\n offer: BundleCartOffer\n fetchImpl?: FetchLike\n track: (input: BundleTrackInput) => void\n /** Injectable for deterministic tests; defaults to crypto.randomUUID(). */\n createId?: () => string\n /** Shopify.routes.root, e.g. `/` or `/fr/`. */\n routeRoot?: string\n onAdded?: () => void | Promise<void>\n\t/** Injectable epoch milliseconds for quote-expiry tests. */\n\tnow?: () => number\n}\n\ntype RequiredLine = {\n component: BundleComponent\n variantNumericID: string\n properties: Record<string, string>\n}\n\nfunction routeURL(routeRoot: string | undefined, path: string): string {\n let root = typeof routeRoot === 'string' && routeRoot ? routeRoot : '/'\n if (!root.endsWith('/')) root += '/'\n return `${root}${path}`\n}\n\nfunction componentsAreExact(components: BundleComponent[]): boolean {\n if (components.length < 2 || components.length > 4) return false\n\n const componentIDs = new Set<string>()\n const products = new Set<string>()\n const variants = new Set<string>()\n for (const component of components) {\n if (\n !component ||\n !isCanonicalUUID(component.component_id) ||\n !PRODUCT_GID.test(component.product_id) ||\n !VARIANT_GID.test(component.variant_id)\n ) {\n return false\n }\n\n if (\n componentIDs.has(component.component_id) ||\n products.has(component.product_id) ||\n variants.has(component.variant_id)\n ) return false\n componentIDs.add(component.component_id)\n products.add(component.product_id)\n variants.add(component.variant_id)\n }\n return true\n}\n\nfunction requiredLines(\n offer: BundleCartOffer,\n instanceID: string,\n requestID: string,\n): RequiredLine[] | null {\n if (\n !isCanonicalUUID(offer.offer_id) ||\n !offer.tracking_token.trim() ||\n !isCanonicalUUID(offer.bundle_instance_id) ||\n !isCanonicalUUID(requestID) ||\n !componentsAreExact(offer.components)\n ) {\n return null\n }\n const lines: RequiredLine[] = []\n for (const component of offer.components) {\n const match = component.variant_id.match(VARIANT_GID)\n if (!match) return null\n lines.push({\n component,\n variantNumericID: match[1]!,\n properties: {\n _tab_bundle_instance_id: instanceID,\n _tab_bundle_tracking_token: offer.tracking_token,\n _tab_bundle_offer_id: offer.offer_id,\n _tab_bundle_component_id: component.component_id,\n _tab_bundle_request_id: requestID,\n },\n })\n }\n return lines\n}\n\nfunction cartLinesFrom(body: unknown): CartLineLike[] {\n if (!body || typeof body !== 'object') return []\n const items = (body as { items?: unknown }).items\n return Array.isArray(items) ? (items as CartLineLike[]) : []\n}\n\nfunction lineMatches(line: CartLineLike, wanted: RequiredLine): boolean {\n if (String(line.id ?? '') !== wanted.variantNumericID || Number(line.quantity ?? 0) < 1) return false\n const properties = line.properties\n if (!properties || typeof properties !== 'object') return false\n return Object.entries(wanted.properties).every(([key, value]) => properties[key] === value)\n}\n\nfunction provesAll(lines: CartLineLike[], expected: RequiredLine[]): boolean {\n return expected.every((wanted) => lines.some((line) => lineMatches(line, wanted)))\n}\n\nfunction hasExpectedLine(lines: CartLineLike[], expected: RequiredLine[]): boolean {\n return expected.some((wanted) => lines.some((line) => lineMatches(line, wanted)))\n}\n\nfunction matchingKeys(lines: CartLineLike[], expected: RequiredLine[]): string[] {\n const keys = new Set<string>()\n for (const line of lines) {\n if (typeof line.key !== 'string' || !line.key) continue\n if (expected.some((wanted) => lineMatches(line, wanted))) keys.add(line.key)\n }\n return [...keys]\n}\n\nasync function safeJSON(response: Awaited<ReturnType<FetchLike>>): Promise<unknown> {\n try {\n return await response.json()\n } catch {\n return null\n }\n}\n\nasync function compensate(\n fetchImpl: FetchLike,\n routeRoot: string | undefined,\n keys: string[],\n provedAbsence: boolean,\n expected: RequiredLine[],\n): Promise<BundleAddResult> {\n // Zero instance lines is a clean failure only when a successful cart read\n // proved the absence. Without that proof the add may have landed, so the\n // outcome must stay recoverable rather than inviting a duplicate retry.\n if (keys.length === 0) {\n return provedAbsence ? { status: 'failed' } : { status: 'recoverable_error' }\n }\n try {\n const response = await fetchImpl(routeURL(routeRoot, 'cart/update.js'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ updates: Object.fromEntries(keys.map((key) => [key, 0])) }),\n credentials: 'same-origin',\n })\n if (!response.ok) return { status: 'recoverable_error' }\n\n // A successful update response only means Shopify accepted the requested\n // keys. Keys can change after discounts or concurrent cart updates, so\n // confirm that no exact instance/token line remains before reporting a\n // completed compensation to the caller.\n const cartResponse = await fetchImpl(routeURL(routeRoot, 'cart.js'), {\n method: 'GET',\n credentials: 'same-origin',\n })\n if (!cartResponse.ok) return { status: 'recoverable_error' }\n const body = await safeJSON(cartResponse)\n const items = body && typeof body === 'object' ? (body as { items?: unknown }).items : null\n if (!Array.isArray(items)) return { status: 'recoverable_error' }\n return hasExpectedLine(items as CartLineLike[], expected)\n ? { status: 'recoverable_error' }\n : { status: 'compensated' }\n } catch {\n return { status: 'recoverable_error' }\n }\n}\n\n/**\n * Adds every exact signed component in one Shopify Ajax Cart request. It does\n * not optimistically track success: the add response *and* a fresh cart read\n * must both prove each exact Variant/private-property tuple.\n */\nexport async function addBundleToCart(options: AddBundleToCartOptions): Promise<BundleAddResult> {\n\tconst quoteExpiry = Date.parse(options.offer.quote_expires_at)\n\tif (!Number.isFinite(quoteExpiry) || quoteExpiry <= (options.now ?? Date.now)()) return { status: 'failed' }\n const createId = options.createId ?? createUUID\n // This exact value was supplied by the client at token issuance and then\n // echoed by the renderer. Never generate a replacement after token minting.\n const instanceID = options.offer.bundle_instance_id\n const requestID = createId()\n const expected = requiredLines(options.offer, instanceID, requestID)\n if (!expected) return { status: 'failed' }\n\n const fetchImpl = options.fetchImpl ?? (globalThis.fetch as unknown as FetchLike)\n let addLines: CartLineLike[] = []\n let addProved = false\n try {\n const addResponse = await fetchImpl(routeURL(options.routeRoot, 'cart/add.js'), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n items: expected.map((wanted) => ({\n id: Number(wanted.variantNumericID),\n quantity: 1,\n properties: wanted.properties,\n })),\n }),\n credentials: 'same-origin',\n })\n if (addResponse.ok) {\n addLines = cartLinesFrom(await safeJSON(addResponse))\n addProved = provesAll(addLines, expected)\n }\n } catch {\n // Shopify can accept some units before an add request becomes uncertain or\n // rejects another component. Always reconcile the current cart before\n // deciding whether instance-scoped compensation is required.\n }\n\n let cartLines: CartLineLike[] = []\n let cartProved = false\n let cartReadOK = false\n try {\n const cartResponse = await fetchImpl(routeURL(options.routeRoot, 'cart.js'), {\n method: 'GET',\n credentials: 'same-origin',\n })\n if (cartResponse.ok) {\n const body = await safeJSON(cartResponse)\n const items = body && typeof body === 'object' ? (body as { items?: unknown }).items : null\n if (Array.isArray(items)) {\n cartReadOK = true\n cartLines = items as CartLineLike[]\n cartProved = provesAll(cartLines, expected)\n }\n }\n } catch {\n // A failed proof is not a successful Add all. Continue only to safe\n // instance/token-scoped compensation below.\n }\n\n if (addProved && cartProved) {\n try {\n options.track({\n event_type: 'add_to_cart',\n offer_id: options.offer.offer_id,\n request_id: requestID,\n tracking_token: options.offer.tracking_token,\n })\n } catch {\n // Analytics must never turn a fully proven cart mutation into a failed\n // shopper action. The caller can safely trust the cart proof below.\n }\n try {\n await options.onAdded?.()\n } catch {\n // Theme synchronization is best-effort after the cart proof succeeds.\n }\n return { status: 'added' }\n }\n\n // Shopify line item keys are not stable: discount application or concurrent\n // cart changes can rewrite them between the add response and the cart read.\n // When the fresh cart read succeeded it is the only source of live keys;\n // add-response keys are just the fallback when the cart is unreadable.\n const keys = cartReadOK ? matchingKeys(cartLines, expected) : matchingKeys(addLines, expected)\n return compensate(fetchImpl, options.routeRoot, keys, cartReadOK, expected)\n}\n","import type { BundleStorefrontEvent, BundleTrackInput, FetchLike } from './types'\nimport { createUUID } from './uuid'\n\nexport const MAX_BUNDLE_EVENTS_BATCH = 100\nexport const MAX_PENDING_BUNDLE_EVENTS = 100\nexport const RETRY_BACKOFF_BASE_MS = 2_000\nexport const RETRY_BACKOFF_MAX_MS = 60_000\n/**\n * The Fetch spec caps the total in-flight keepalive body budget at 64 KiB and\n * rejects an over-budget request synchronously, which would deadlock retries\n * forever. Bundle tokens run up to 1 KiB each, so a full 100-event batch can\n * exceed the cap; keep each request comfortably below it.\n */\nexport const MAX_BUNDLE_EVENTS_BATCH_BYTES = 56 * 1024\n\nexport type BundleEventQueueOptions = {\n proxyBase?: string\n fetchImpl?: FetchLike\n createEventId?: () => string\n now?: () => number\n onEnqueued?: (count: number) => void\n}\n\nfunction normalizeProxyBase(proxyBase: string): string {\n return proxyBase.replace(/\\/+$/, '')\n}\n\nfunction utf8Length(value: string): number {\n if (typeof TextEncoder !== 'undefined') return new TextEncoder().encode(value).length\n return value.length\n}\n\nconst BATCH_ENVELOPE_BYTES = utf8Length('{\"items\":[]}')\n\ntype NextBatch = { batch: BundleStorefrontEvent[]; overBudget: boolean }\n\n/**\n * Takes head-of-queue events while both the count cap and the keepalive byte\n * budget hold. A single event that alone exceeds the budget still ships as a\n * one-event batch, flagged so the caller can drop keepalive for it.\n */\nfunction nextBatch(pending: BundleStorefrontEvent[], remaining: number): NextBatch {\n const batch: BundleStorefrontEvent[] = []\n let bytes = BATCH_ENVELOPE_BYTES\n const max = Math.min(MAX_BUNDLE_EVENTS_BATCH, remaining, pending.length)\n for (let index = 0; index < max; index += 1) {\n const eventBytes = utf8Length(JSON.stringify(pending[index]!)) + (batch.length > 0 ? 1 : 0)\n if (batch.length > 0 && bytes + eventBytes > MAX_BUNDLE_EVENTS_BATCH_BYTES) break\n batch.push(pending[index]!)\n bytes += eventBytes\n }\n return { batch, overBudget: bytes > MAX_BUNDLE_EVENTS_BATCH_BYTES }\n}\n\n/**\n * Deliberately separate from the Cross Sell queue: Bundle event payloads carry\n * Offer identity and are delivered only to the Bundle event route.\n */\nexport function createBundleEventQueue(options: BundleEventQueueOptions = {}) {\n const pending: BundleStorefrontEvent[] = []\n const createEventId = options.createEventId ?? createUUID\n const now = options.now ?? (() => Date.now())\n let backoffMs = 0\n let nextAttemptAt = 0\n\n function enqueue(event: BundleStorefrontEvent): void {\n if (pending.length >= MAX_PENDING_BUNDLE_EVENTS) pending.shift()\n pending.push(event)\n options.onEnqueued?.(pending.length)\n }\n\n function track(input: BundleTrackInput): BundleStorefrontEvent {\n const event: BundleStorefrontEvent = {\n event_id: input.event_id ?? createEventId(),\n occurred_at: input.occurred_at ?? new Date(now()).toISOString(),\n event_type: input.event_type,\n tracking_token: input.tracking_token,\n offer_id: input.offer_id,\n request_id: input.request_id,\n attrs: input.attrs,\n }\n enqueue(event)\n return event\n }\n\n function scheduleRetry(): void {\n backoffMs = Math.min(\n backoffMs > 0 ? backoffMs * 2 : RETRY_BACKOFF_BASE_MS,\n RETRY_BACKOFF_MAX_MS,\n )\n nextAttemptAt = now() + backoffMs\n }\n\n async function flush(): Promise<void> {\n if (pending.length === 0) return\n if (!options.proxyBase) throw new Error('proxyBase is required to flush Bundle events')\n if (now() < nextAttemptAt) return\n const fetchImpl = options.fetchImpl ?? (globalThis.fetch as unknown as FetchLike)\n const countAtStart = pending.length\n let processed = 0\n while (processed < countAtStart) {\n const { batch, overBudget } = nextBatch(pending, countAtStart - processed)\n if (batch.length === 0) return\n let response: Awaited<ReturnType<FetchLike>>\n try {\n response = await fetchImpl(`${normalizeProxyBase(options.proxyBase)}/bundle-offers/events`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ items: batch }),\n // An over-budget single event would be rejected synchronously with\n // keepalive; deliver it as an ordinary request instead.\n keepalive: !overBudget,\n credentials: 'same-origin',\n })\n } catch {\n scheduleRetry()\n return\n }\n // The Bundle ingest route uses 429 for its per-shop token bucket. That\n // is an explicit temporary refusal, so retain stable event identities\n // and retry it with the same backoff as a server failure. Other 4xx\n // responses are malformed/invalid requests and remain terminal.\n if (!response.ok && (response.status === 429 || response.status >= 500)) {\n scheduleRetry()\n return\n }\n // 2xx accepts and/or rejects final per-item results; a 4xx request cannot\n // succeed through retry. In both cases drop only the sent event IDs.\n backoffMs = 0\n nextAttemptAt = 0\n const delivered = new Set(batch.map((event) => event.event_id))\n for (let index = pending.length - 1; index >= 0; index -= 1) {\n if (delivered.has(pending[index]!.event_id)) pending.splice(index, 1)\n }\n processed += batch.length\n }\n }\n\n return { track, enqueue, flush, pending: () => pending.slice() }\n}\n\nexport type BundleEventQueue = ReturnType<typeof createBundleEventQueue>\n","export type BundleFlushControllerOptions = {\n flush: () => Promise<void>\n intervalMs?: number\n threshold?: number\n setIntervalImpl?: (callback: () => void, intervalMs: number) => number | ReturnType<typeof setInterval>\n clearIntervalImpl?: (handle: number | ReturnType<typeof setInterval>) => void\n documentRef?: Document\n windowRef?: Window\n}\n\n/** Page-lifecycle delivery coordinator owned solely by the Bundle event queue. */\nexport function createBundleFlushController(options: BundleFlushControllerOptions) {\n const intervalMs = options.intervalMs ?? 2_000\n const threshold = options.threshold ?? 10\n const setIntervalImpl = options.setIntervalImpl ?? setInterval\n const clearIntervalImpl = options.clearIntervalImpl ?? clearInterval\n let timer: number | ReturnType<typeof setInterval> | null = null\n let flushing = false\n let flushAgain = false\n\n async function flushNow(): Promise<void> {\n if (flushing) {\n flushAgain = true\n return\n }\n flushing = true\n try {\n do {\n flushAgain = false\n await options.flush()\n } while (flushAgain)\n } finally {\n flushing = false\n }\n }\n\n const onLifecycle = () => {\n void flushNow().catch(() => {})\n }\n\n function start(): void {\n if (timer !== null) return\n timer = setIntervalImpl(onLifecycle, intervalMs)\n options.documentRef?.addEventListener('visibilitychange', onLifecycle)\n options.windowRef?.addEventListener('pagehide', onLifecycle)\n }\n\n function stop(): void {\n if (timer !== null) {\n clearIntervalImpl(timer)\n timer = null\n }\n options.documentRef?.removeEventListener('visibilitychange', onLifecycle)\n options.windowRef?.removeEventListener('pagehide', onLifecycle)\n }\n\n return {\n start,\n stop,\n flushNow,\n notifyEnqueued(count: number) {\n if (count >= threshold) void flushNow().catch(() => {})\n },\n }\n}\n\nexport type BundleFlushController = ReturnType<typeof createBundleFlushController>\n","import type { ObserveTarget, VisibilityEvidence } from './types'\n\nexport const BUNDLE_IMPRESSION_MIN_RATIO = 0.5\nexport const BUNDLE_IMPRESSION_MIN_DURATION_MS = 500\nconst RATIO_EPSILON = 1e-4\n\nexport type BundleImpressionPayload = {\n tracking_token: string\n offer_id: string\n request_id: string\n attrs: { visibility: VisibilityEvidence }\n}\n\nexport type BundleImpressionObserverOptions = {\n onImpression: (payload: BundleImpressionPayload) => void\n IntersectionObserverImpl?: typeof IntersectionObserver\n now?: () => number\n setTimeoutImpl?: (callback: () => void, delayMs: number) => number | ReturnType<typeof setTimeout>\n clearTimeoutImpl?: (handle: number | ReturnType<typeof setTimeout>) => void\n documentRef?: Document\n}\n\ntype Pending = {\n target: ObserveTarget\n ratio: number\n startedAt: number\n timer: number | ReturnType<typeof setTimeout> | null\n}\n\n/** Independent 50%/500ms Bundle observer, never shared with Cross Sell. */\nexport function createBundleImpressionObserver(options: BundleImpressionObserverOptions) {\n const now = options.now ?? (() => Date.now())\n const setTimeoutImpl = options.setTimeoutImpl ?? setTimeout\n const clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout\n const Observer = options.IntersectionObserverImpl ?? globalThis.IntersectionObserver\n const seen = new Set<string>()\n const targets = new WeakMap<Element, ObserveTarget>()\n const pending = new Map<string, Pending>()\n\n function hidden(): boolean {\n return options.documentRef?.hidden === true\n }\n\n function emitAfterThreshold(item: Pending): void {\n if (item.timer !== null || hidden()) return\n item.startedAt = now()\n item.timer = setTimeoutImpl(() => {\n const current = pending.get(item.target.tracking_token)\n if (!current || seen.has(current.target.tracking_token) || hidden()) return\n current.timer = null\n seen.add(current.target.tracking_token)\n pending.delete(current.target.tracking_token)\n options.onImpression({\n tracking_token: current.target.tracking_token,\n offer_id: current.target.offer_id,\n request_id: current.target.request_id,\n attrs: {\n visibility: { ratio: current.ratio, duration_ms: now() - current.startedAt },\n },\n })\n }, BUNDLE_IMPRESSION_MIN_DURATION_MS)\n }\n\n const onVisibilityChange = () => {\n for (const item of pending.values()) {\n if (hidden()) {\n if (item.timer !== null) clearTimeoutImpl(item.timer)\n item.timer = null\n } else {\n emitAfterThreshold(item)\n }\n }\n }\n\n if (!Observer) {\n return {\n observe: (_items: ObserveTarget[]) => {},\n disconnect: () => {},\n seenTokens: () => new Set(seen),\n }\n }\n\n const observer = new Observer(\n (entries) => {\n for (const entry of entries) {\n const target = targets.get(entry.target)\n if (!target || seen.has(target.tracking_token)) continue\n const qualifies =\n entry.isIntersecting && entry.intersectionRatio >= BUNDLE_IMPRESSION_MIN_RATIO - RATIO_EPSILON\n const current = pending.get(target.tracking_token)\n if (!qualifies) {\n if (current?.timer !== null && current?.timer !== undefined) clearTimeoutImpl(current.timer)\n pending.delete(target.tracking_token)\n continue\n }\n if (current) {\n current.ratio = entry.intersectionRatio\n current.target = target\n emitAfterThreshold(current)\n continue\n }\n const item: Pending = {\n target,\n ratio: entry.intersectionRatio,\n startedAt: now(),\n timer: null,\n }\n pending.set(target.tracking_token, item)\n emitAfterThreshold(item)\n }\n },\n { threshold: [0, BUNDLE_IMPRESSION_MIN_RATIO, 1] },\n )\n\n options.documentRef?.addEventListener('visibilitychange', onVisibilityChange)\n return {\n observe(items: ObserveTarget[]) {\n for (const item of items) {\n targets.set(item.element, item)\n observer.observe(item.element)\n }\n },\n disconnect() {\n for (const item of pending.values()) {\n if (item.timer !== null) clearTimeoutImpl(item.timer)\n }\n pending.clear()\n observer.disconnect()\n options.documentRef?.removeEventListener('visibilitychange', onVisibilityChange)\n },\n seenTokens: () => new Set(seen),\n }\n}\n\nexport type BundleImpressionObserver = ReturnType<typeof createBundleImpressionObserver>\n","import type {\n BundleOffer,\n BundlePDPRenderedRequest,\n BundleQuoteRequest,\n BundleQuoteResponse,\n BundleRenderedResponse,\n BundleResolveRequest,\n BundleResolveResponse,\n FetchLike,\n} from './types'\nimport { isCanonicalUUID } from './uuid'\n\nconst SLOT_KEY = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\nconst PRODUCT_GID = /^gid:\\/\\/shopify\\/Product\\/[1-9]\\d{0,19}$/\nconst VARIANT_GID = /^gid:\\/\\/shopify\\/ProductVariant\\/[1-9]\\d{0,19}$/\nconst MONEY_AMOUNT = /^(?:0|[1-9]\\d*)(?:\\.\\d+)?$/\nconst DEFAULT_RESOLVE_LIMIT = 10\nconst MAX_POSITION = 2_147_483_647\n\nexport type ResolveOptions = {\n /** App Proxy base, e.g. `/apps/tab-cross-sell-dev`. */\n proxyBase: string\n fetchImpl?: FetchLike\n signal?: AbortSignal\n}\n\nfunction normalizeProxyBase(proxyBase: string): string {\n return proxyBase.replace(/\\/+$/, '')\n}\n\nfunction validContext(request: { context: { country: string }; cart: { currency: string } }): boolean {\n return Boolean(request.context?.country?.trim() && request.cart?.currency?.trim())\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isNonBlankString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction isPositiveInteger(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value > 0\n}\n\nfunction isPosition(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= MAX_POSITION\n}\n\nfunction hasPositiveMoney(value: unknown, currency: string): boolean {\n if (!isRecord(value)) return false\n const amount = value.amount\n return (\n typeof amount === 'string' &&\n amount === amount.trim() &&\n MONEY_AMOUNT.test(amount) &&\n /[1-9]/.test(amount) &&\n value.currency === currency\n )\n}\n\nfunction hasExactComponents(value: unknown, currency: string): boolean {\n if (!Array.isArray(value) || value.length < 2 || value.length > 4) return false\n const componentIDs = new Set<string>()\n const products = new Set<string>()\n const variants = new Set<string>()\n let previousProductID: string | null = null\n return value.every((candidate) => {\n if (!isRecord(candidate)) return false\n const componentID = candidate.component_id\n const productID = candidate.product_id\n const variantID = candidate.variant_id\n\t\tconst options = candidate.options\n\t\tconst eligibleVariants = candidate.variants\n if (\n !isCanonicalUUID(componentID) ||\n typeof productID !== 'string' ||\n !PRODUCT_GID.test(productID) ||\n typeof variantID !== 'string' ||\n !VARIANT_GID.test(variantID) ||\n !isNonBlankString(candidate.product_title) ||\n\t\t\t!Array.isArray(options) || !options.every(isNonBlankString) ||\n\t\t\t!Array.isArray(eligibleVariants) || eligibleVariants.length < 1 ||\n\t\t\t!eligibleVariants.every((variant) => hasEligibleVariant(variant, currency)) ||\n\t\t\t!eligibleVariants.some((variant) => isRecord(variant) && variant.variant_id === variantID && variant.available === true) ||\n ('image_url' in candidate && !isNonBlankString(candidate.image_url)) ||\n componentIDs.has(componentID) ||\n products.has(productID) ||\n variants.has(variantID) ||\n (previousProductID !== null && previousProductID >= productID)\n ) {\n return false\n }\n componentIDs.add(componentID)\n products.add(productID)\n variants.add(variantID)\n previousProductID = productID\n return true\n })\n}\n\nfunction hasEligibleVariant(value: unknown, currency: string): boolean {\n\tif (!isRecord(value)) return false\n\treturn typeof value.variant_id === 'string' && VARIANT_GID.test(value.variant_id) &&\n\t\tisNonBlankString(value.title) && Array.isArray(value.option_values) && value.option_values.every(isNonBlankString) &&\n\t\tvalue.available === true && hasPositiveMoney(value.price, currency)\n}\n\nfunction hasFutureQuoteExpiry(value: unknown): value is string {\n\tif (typeof value !== 'string') return false\n\tconst timestamp = Date.parse(value)\n\treturn Number.isFinite(timestamp) && timestamp > Date.now()\n}\n\nfunction hasValidOfferSurface(offer: Record<string, unknown>, request: BundleResolveRequest, expectedSurface?: BundleOffer['surface'], expectedSlot?: string): boolean {\n\tif (expectedSurface) {\n\t\treturn offer.surface === expectedSurface && (expectedSurface === 'api_slot' ? offer.slot_key === expectedSlot : offer.slot_key === undefined)\n\t}\n if (typeof request.slot_key === 'string') {\n return (\n offer.surface === 'api_slot' &&\n offer.slot_key === request.slot_key &&\n request.slot_key.length <= 64 &&\n SLOT_KEY.test(request.slot_key)\n )\n }\n return (\n offer.surface === 'api_offer_ids' &&\n offer.slot_key === undefined\n )\n}\n\nfunction hasContractBundleOffer(\n value: unknown,\n requestID: string,\n request: BundleResolveRequest,\n\texpectedSurface?: BundleOffer['surface'],\n\texpectedSlot?: string,\n): boolean {\n if (!isRecord(value)) return false\n const trackingToken = value.tracking_token\n return (\n isCanonicalUUID(value.campaign_id) &&\n isCanonicalUUID(value.offer_id) &&\n isCanonicalUUID(value.publish_version_id) &&\n isPositiveInteger(value.campaign_version) &&\n isPositiveInteger(value.revision) &&\n isPosition(value.position) &&\n isNonBlankString(value.name) &&\n isNonBlankString(value.message) &&\n\t\thasExactComponents(value.components, request.cart.currency) &&\n hasPositiveMoney(value.regular_total, request.cart.currency) &&\n hasPositiveMoney(value.offer_total, request.cart.currency) &&\n hasPositiveMoney(value.savings, request.cart.currency) &&\n typeof trackingToken === 'string' &&\n trackingToken === trackingToken.trim() &&\n trackingToken.length > 0 &&\n isCanonicalUUID(value.bundle_instance_id) &&\n\t\thasFutureQuoteExpiry(value.quote_expires_at) &&\n value.request_id === requestID &&\n hasValidOfferSurface(value, request, expectedSurface, expectedSlot)\n )\n}\n\nfunction isValidQuoteRequest(request: BundleQuoteRequest): boolean {\n\tif (!validContext(request) || !isNonBlankString(request.tracking_token) || request.tracking_token !== request.tracking_token.trim() || request.tracking_token.length > 1024 ||\n\t\t!Array.isArray(request.selections) || request.selections.length < 2 || request.selections.length > 4) return false\n\tconst components = new Set<string>()\n\tconst products = new Set<string>()\n\tconst variants = new Set<string>()\n\treturn request.selections.every((selected) => {\n\t\tif (!isCanonicalUUID(selected.component_id) || !PRODUCT_GID.test(selected.product_id) || !VARIANT_GID.test(selected.variant_id) ||\n\t\t\tcomponents.has(selected.component_id) || products.has(selected.product_id) || variants.has(selected.variant_id)) return false\n\t\tcomponents.add(selected.component_id); products.add(selected.product_id); variants.add(selected.variant_id)\n\t\treturn true\n\t})\n}\n\nfunction hasContractQuoteResponse(value: unknown, request: BundleQuoteRequest): value is BundleQuoteResponse {\n\tif (!isRecord(value) || !isCanonicalUUID(value.request_id) || typeof value.eligible !== 'boolean') return false\n\tif (!value.eligible) return value.offer === undefined && ['stale_offer', 'invalid_selection', 'temporarily_unavailable'].includes(String(value.reason))\n\tif (value.reason !== undefined || !isRecord(value.offer)) return false\n\tconst offer = value.offer\n\tif (offer.request_id !== value.request_id || !['pdp', 'api_slot', 'api_offer_ids'].includes(String(offer.surface))) return false\n\tconst selected = new Map(request.selections.map((item) => [item.component_id, item]))\n\tif (!Array.isArray(offer.components) || offer.components.length !== request.selections.length || offer.components.some((item) => !isRecord(item) ||\n\t\tselected.get(String(item.component_id))?.product_id !== item.product_id ||\n\t\tselected.get(String(item.component_id))?.variant_id !== item.variant_id)) return false\n\tconst surface = offer.surface as BundleOffer['surface']\n\tconst slot = surface === 'api_slot' && typeof offer.slot_key === 'string' ? offer.slot_key : undefined\n\tconst resolveRequest: BundleResolveRequest = surface === 'api_slot'\n\t\t? { slot_key: slot ?? '', context: request.context, cart: request.cart }\n\t\t: { offer_ids: [String(offer.offer_id)], context: request.context, cart: request.cart }\n\treturn hasContractBundleOffer(offer, value.request_id, resolveRequest, surface, slot)\n}\n\nfunction hasContractResolveResponse(\n value: unknown,\n request: BundleResolveRequest,\n): value is BundleResolveResponse {\n if (!isRecord(value) || !isCanonicalUUID(value.request_id) || !Array.isArray(value.offers)) return false\n const requestID = value.request_id\n const limit = request.limit ?? DEFAULT_RESOLVE_LIMIT\n if (value.offers.length > limit) return false\n const offerIDs = new Set<string>()\n const instanceIDs = new Set<string>()\n let previousRequestedIndex = -1\n return value.offers.every((offer) => {\n if (!hasContractBundleOffer(offer, requestID, request)) return false\n const identity = offer as Record<string, unknown>\n const offerID = identity.offer_id as string\n const instanceID = identity.bundle_instance_id as string\n if (offerIDs.has(offerID) || instanceIDs.has(instanceID)) return false\n offerIDs.add(offerID)\n instanceIDs.add(instanceID)\n if (!Array.isArray(request.offer_ids)) return true\n const requestedIndex = request.offer_ids.indexOf(offerID)\n if (requestedIndex < 0 || requestedIndex <= previousRequestedIndex) return false\n previousRequestedIndex = requestedIndex\n return true\n })\n}\n\n/**\n * Reject malformed selector requests before they cross the App Proxy. This is\n * defense-in-depth; customer-api repeats all selector validation authoritatively.\n */\nexport function isValidBundleResolveRequest(request: BundleResolveRequest): boolean {\n if (!validContext(request)) return false\n if (request.limit !== undefined && (!Number.isInteger(request.limit) || request.limit < 1 || request.limit > 20)) {\n return false\n }\n const hasSlot = typeof request.slot_key === 'string'\n const hasOffers = Array.isArray(request.offer_ids)\n if (hasSlot === hasOffers) return false\n if (hasSlot) return request.slot_key.length <= 64 && SLOT_KEY.test(request.slot_key)\n if (!hasOffers || request.offer_ids.length < 1 || request.offer_ids.length > 20) return false\n const ids = new Set<string>()\n return request.offer_ids.every((id) => {\n if (!isCanonicalUUID(id) || ids.has(id)) return false\n ids.add(id)\n return true\n })\n}\n\nfunction isValidPDPRequest(request: BundlePDPRenderedRequest): boolean {\n return Boolean(\n validContext(request) &&\n PRODUCT_GID.test(request.source_product_id) &&\n VARIANT_GID.test(request.source_variant_id) &&\n isCanonicalUUID(request.bundle_instance_id),\n )\n}\n\nasync function readData(response: Awaited<ReturnType<FetchLike>>): Promise<unknown> {\n try {\n const body = (await response.json()) as { data?: unknown }\n return body?.data\n } catch {\n return null\n }\n}\n\n/** Agency SDK resolve; failed/invalid response remains an empty integration. */\nexport async function resolveBundleOffers(\n request: BundleResolveRequest,\n options: ResolveOptions,\n): Promise<BundleResolveResponse | null> {\n if (!isValidBundleResolveRequest(request)) return null\n const fetchImpl = options.fetchImpl ?? (globalThis.fetch as unknown as FetchLike)\n try {\n const response = await fetchImpl(`${normalizeProxyBase(options.proxyBase)}/bundle-offers/resolve`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n signal: options.signal,\n credentials: 'same-origin',\n })\n if (!response.ok) return null\n const data = await readData(response)\n if (!hasContractResolveResponse(data, request)) return null\n return { request_id: data.request_id, offers: data.offers }\n } catch {\n return null\n }\n}\n\n/** Official PDP-only rendered resolve. It does not accept slots or explicit IDs. */\nexport async function resolveBundlePDP(\n request: BundlePDPRenderedRequest,\n options: ResolveOptions,\n): Promise<BundleRenderedResponse | null> {\n if (!isValidPDPRequest(request)) return null\n const fetchImpl = options.fetchImpl ?? (globalThis.fetch as unknown as FetchLike)\n try {\n const response = await fetchImpl(\n `${normalizeProxyBase(options.proxyBase)}/bundle-offers/pdp/rendered`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n signal: options.signal,\n credentials: 'same-origin',\n },\n )\n if (!response.ok) return null\n const data = await readData(response)\n if (!data || typeof data !== 'object') return null\n const value = data as Partial<BundleRenderedResponse>\n if (typeof value.html !== 'string' || !isCanonicalUUID(value.request_id)) return null\n return { html: value.html, request_id: value.request_id }\n } catch {\n return null\n }\n}\n\n/** Re-quotes one exact selection; malformed/stale responses never become addable. */\nexport async function quoteBundleOffer(request: BundleQuoteRequest, options: ResolveOptions): Promise<BundleQuoteResponse | null> {\n\tif (!isValidQuoteRequest(request)) return null\n\tconst fetchImpl = options.fetchImpl ?? (globalThis.fetch as unknown as FetchLike)\n\ttry {\n\t\tconst response = await fetchImpl(`${normalizeProxyBase(options.proxyBase)}/bundle-offers/quote`, {\n\t\t\tmethod: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(request),\n\t\t\tsignal: options.signal, credentials: 'same-origin',\n\t\t})\n\t\tif (!response.ok) return null\n\t\tconst data = await readData(response)\n\t\treturn hasContractQuoteResponse(data, request) ? data : null\n\t} catch {\n\t\treturn null\n\t}\n}\n","import { addBundleToCart, type AddBundleToCartOptions, type BundleAddResult } from './commerce'\nimport { createBundleEventQueue } from './events'\nimport { createBundleFlushController } from './flush'\nimport { createBundleImpressionObserver } from './observer'\nimport { quoteBundleOffer, resolveBundleOffers, resolveBundlePDP } from './resolve'\nimport type {\n BundleCartOffer,\n BundlePDPRenderedRequest,\n BundleQuoteRequest,\n BundleQuoteResponse,\n BundleRenderedResponse,\n BundleResolveRequest,\n BundleResolveResponse,\n BundleTrackInput,\n FetchLike,\n ObserveTarget,\n} from './types'\n\nexport type BuyTogetherInitOptions = {\n proxyBase: string\n fetchImpl?: FetchLike\n flushIntervalMs?: number\n flushThreshold?: number\n createEventId?: () => string\n now?: () => number\n documentRef?: Document\n windowRef?: Window\n IntersectionObserverImpl?: typeof IntersectionObserver\n}\n\nexport type BundleMountPDPOptions = {\n root: Element\n request: BundlePDPRenderedRequest\n signal?: AbortSignal\n}\n\nexport type BuyTogetherClient = {\n resolve: (request: BundleResolveRequest, signal?: AbortSignal) => Promise<BundleResolveResponse | null>\n resolvePDP: (\n request: BundlePDPRenderedRequest,\n signal?: AbortSignal,\n ) => Promise<BundleRenderedResponse | null>\n\tquote: (request: BundleQuoteRequest, signal?: AbortSignal) => Promise<BundleQuoteResponse | null>\n mountPDP: (options: BundleMountPDPOptions) => Promise<() => void>\n addAll: (\n offer: BundleCartOffer,\n options?: Omit<AddBundleToCartOptions, 'offer' | 'track' | 'fetchImpl'>,\n ) => Promise<BundleAddResult>\n track: (input: BundleTrackInput) => void\n flush: () => Promise<void>\n destroy: () => void\n}\n\nfunction textAttribute(element: Element, name: string): string {\n return String(element.getAttribute(name) || '').trim()\n}\n\n/**\n * The Bundle renderer has independent data attributes. Do not make a card\n * trackable from Cross Sell provenance or from generic product markup.\n */\nexport function collectBundleObserveTargets(root: Element): ObserveTarget[] {\n return Array.from(root.querySelectorAll('[data-tab-buy-together-offer]')).map((element) => ({\n element,\n tracking_token: textAttribute(element, 'data-tab-buy-together-tracking-token'),\n offer_id: textAttribute(element, 'data-tab-buy-together-offer-id'),\n request_id: textAttribute(element, 'data-tab-buy-together-request-id'),\n }))\n}\n\nfunction isTrackable(target: ObserveTarget): boolean {\n return Boolean(target.tracking_token && target.offer_id && target.request_id)\n}\n\nexport function init(options: BuyTogetherInitOptions): BuyTogetherClient {\n // npm consumers rarely pass these refs; default to the browser globals so\n // hidden-tab time stays excluded from impressions and pagehide still\n // flushes. Non-browser callers simply run without lifecycle hooks.\n const documentRef =\n options.documentRef ?? (typeof document !== 'undefined' ? document : undefined)\n const windowRef = options.windowRef ?? (typeof window !== 'undefined' ? window : undefined)\n const observers = new Set<{ disconnect: () => void }>()\n type PDPInstance = { controller: AbortController; unmount: () => void }\n const mountedPDP = new WeakMap<Element, PDPInstance>()\n const activePDP = new Set<PDPInstance>()\n let notifyEnqueued: (count: number) => void = () => {}\n const queue = createBundleEventQueue({\n proxyBase: options.proxyBase,\n fetchImpl: options.fetchImpl,\n createEventId: options.createEventId,\n now: options.now,\n onEnqueued: (count) => notifyEnqueued(count),\n })\n const flushController = createBundleFlushController({\n flush: () => queue.flush(),\n intervalMs: options.flushIntervalMs,\n threshold: options.flushThreshold,\n documentRef,\n windowRef,\n })\n notifyEnqueued = (count) => flushController.notifyEnqueued(count)\n flushController.start()\n\n function track(input: BundleTrackInput): void {\n queue.track(input)\n }\n\n function resolve(request: BundleResolveRequest, signal?: AbortSignal) {\n return resolveBundleOffers(request, {\n proxyBase: options.proxyBase,\n fetchImpl: options.fetchImpl,\n signal,\n })\n }\n\n function resolvePDP(request: BundlePDPRenderedRequest, signal?: AbortSignal) {\n return resolveBundlePDP(request, {\n proxyBase: options.proxyBase,\n fetchImpl: options.fetchImpl,\n signal,\n })\n }\n\n\tfunction quote(request: BundleQuoteRequest, signal?: AbortSignal) {\n\t\treturn quoteBundleOffer(request, { proxyBase: options.proxyBase, fetchImpl: options.fetchImpl, signal })\n\t}\n\n async function mountPDP(mountOptions: BundleMountPDPOptions): Promise<() => void> {\n const prior = mountedPDP.get(mountOptions.root)\n prior?.controller.abort()\n prior?.unmount()\n if (prior) activePDP.delete(prior)\n const controller = new AbortController()\n const mounted: PDPInstance = { controller, unmount: () => {} }\n mountedPDP.set(mountOptions.root, mounted)\n activePDP.add(mounted)\n // Required current-variant behavior: stale markup vanishes before the\n // next request, rather than remaining purchasable while it is pending.\n mountOptions.root.innerHTML = ''\n const abortExternal = () => controller.abort()\n mountOptions.signal?.addEventListener('abort', abortExternal, { once: true })\n if (mountOptions.signal?.aborted) controller.abort()\n const rendered = await resolvePDP(mountOptions.request, controller.signal)\n mountOptions.signal?.removeEventListener('abort', abortExternal)\n if (mountedPDP.get(mountOptions.root) !== mounted || controller.signal.aborted) {\n activePDP.delete(mounted)\n return () => {}\n }\n if (!rendered || !rendered.html.trim()) {\n return () => {}\n }\n mountOptions.root.innerHTML = rendered.html\n const targets = collectBundleObserveTargets(mountOptions.root).filter(isTrackable)\n if (targets.length === 0) return () => {}\n const observer = createBundleImpressionObserver({\n IntersectionObserverImpl: options.IntersectionObserverImpl,\n documentRef,\n now: options.now,\n onImpression: (payload) => {\n track({\n event_type: 'impression',\n tracking_token: payload.tracking_token,\n offer_id: payload.offer_id,\n request_id: payload.request_id,\n attrs: payload.attrs,\n })\n },\n })\n observer.observe(targets)\n observers.add(observer)\n mounted.unmount = () => {\n observer.disconnect()\n observers.delete(observer)\n }\n return () => {\n if (mountedPDP.get(mountOptions.root) === mounted) {\n mounted.unmount()\n mountedPDP.delete(mountOptions.root)\n activePDP.delete(mounted)\n }\n }\n }\n\n function addAll(\n offer: BundleCartOffer,\n addOptions: Omit<AddBundleToCartOptions, 'offer' | 'track' | 'fetchImpl'> = {},\n ) {\n return addBundleToCart({\n ...addOptions,\n offer,\n fetchImpl: options.fetchImpl,\n track,\n })\n }\n\n function destroy(): void {\n for (const mounted of activePDP) {\n mounted.controller.abort()\n mounted.unmount()\n }\n activePDP.clear()\n for (const observer of observers) observer.disconnect()\n observers.clear()\n flushController.stop()\n void flushController.flushNow().catch(() => {})\n }\n\n return {\n resolve,\n resolvePDP,\n\t\tquote,\n mountPDP,\n addAll,\n track,\n flush: () => flushController.flushNow().catch(() => {}),\n destroy,\n }\n}\n","export type PDPRequestSequencerOptions<Request, Result> = {\n resolve: (request: Request, signal: AbortSignal) => Promise<Result | null>\n /** Called synchronously for every source-variant change. */\n onClear: () => void\n /** Only receives results that still belong to the current request. */\n onResult: (result: Result) => void\n}\n\n/**\n * Keeps PDP output tied to the currently selected variant. A variation switch\n * immediately removes stale bundle content, aborts the old fetch, and fences\n * late responses by monotonically increasing request generation.\n */\nexport function createPDPRequestSequencer<Request, Result>(\n options: PDPRequestSequencerOptions<Request, Result>,\n) {\n let generation = 0\n let controller: AbortController | null = null\n\n async function run(request: Request): Promise<Result | null> {\n generation += 1\n const currentGeneration = generation\n controller?.abort()\n controller = new AbortController()\n options.onClear()\n try {\n const result = await options.resolve(request, controller.signal)\n if (currentGeneration !== generation || controller.signal.aborted || result === null) return null\n options.onResult(result)\n return result\n } catch {\n return null\n }\n }\n\n function cancel(): void {\n generation += 1\n controller?.abort()\n controller = null\n }\n\n return { run, cancel }\n}\n\nexport type PDPRequestSequencer<Request, Result> = ReturnType<\n typeof createPDPRequestSequencer<Request, Result>\n>\n","export type QuoteAttempt = { revision: number; signal: AbortSignal }\n\n/** One-lane quote fence: every new selection aborts and invalidates its predecessor. */\nexport function createQuoteRequestFence() {\n let revision = 0\n let controller: AbortController | null = null\n return {\n begin(): QuoteAttempt {\n controller?.abort()\n controller = new AbortController()\n return { revision: ++revision, signal: controller.signal }\n },\n isCurrent(attempt: QuoteAttempt): boolean {\n return attempt.revision === revision && !attempt.signal.aborted\n },\n cancel(): void {\n revision += 1\n controller?.abort()\n controller = null\n },\n }\n}\n"],"mappings":"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","names":["PRODUCT_GID","VARIANT_GID","normalizeProxyBase"]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@tabcommerceio/buy-together-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Storefront JavaScript SDK for Product Bundle offers, exact Variant quotes, Add bundle, and isolated Bundle event delivery.",
5
+ "license": "MIT",
6
+ "author": "tab commerce technologies llc",
7
+ "homepage": "https://tabcommerce.io/docs/tab-cross-sell/buy-together-javascript-sdk",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/tabcommerce/tab-cross-sell.git",
11
+ "directory": "packages/web/buy-together-sdk"
12
+ },
13
+ "bugs": {
14
+ "url": "https://tabcommerce.io/contact"
15
+ },
16
+ "keywords": [
17
+ "shopify",
18
+ "buy-together",
19
+ "bundle",
20
+ "storefront",
21
+ "tab-commerce"
22
+ ],
23
+ "type": "module",
24
+ "sideEffects": false,
25
+ "main": "./dist/index.js",
26
+ "module": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "build": "tsup && node ./scripts/emit-theme-asset.mjs",
45
+ "test": "pnpm typecheck && vitest run",
46
+ "typecheck": "tsc --noEmit",
47
+ "prepublishOnly": "pnpm run test && pnpm run build && node ./scripts/check-publish-artifacts.mjs"
48
+ },
49
+ "devDependencies": {
50
+ "tsup": "^8.5.0",
51
+ "typescript": "^5.9.0",
52
+ "vitest": "^3.2.0"
53
+ }
54
+ }