@tracelog/lib 2.8.4 → 2.8.5-rc.106.6

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
+ var TraceLogShopifyPixel=function(t){"use strict";function e(t,e){if(!Array.isArray(t))return null;for(const n of t)if(n&&n.key===e&&"string"==typeof n.value&&n.value.length>0)return n.value;return null}function n(t){return"number"==typeof t&&Number.isFinite(t)?t:void 0}function i(t){return"string"==typeof t&&t.length>0?t:void 0}function o(t,e,n){void 0!==n&&(t[e]=n)}function c(t,e){const c=t.data?.checkout,d=t.data?.cart,l={};o(l,"shopify_client_id",i(t.clientId));const _=i(c?.token);if(_&&(l.checkout_token=_),"checkout_completed"===e){o(l,"value",n(c?.totalPrice?.amount??c?.subtotalPrice?.amount)),o(l,"currency",i(c?.currencyCode??c?.totalPrice?.currencyCode));const t=c?.order?.id;null!=t&&(l.orderId=String(t));const e=c?.lineItems??[],r=function(t){if(!t||0===t.length)return[];const e=t.slice(0,100);return e.map(t=>{const e={};return o(e,"id",i(void 0!==t.variant?.id?String(t.variant.id):void 0)),o(e,"title",s(i(t.title??t.variant?.product?.title),u)),o(e,"quantity",n(t.quantity)),o(e,"price",n(t.variant?.price?.amount??t.finalLinePrice?.amount)),o(e,"sku",s(i(t.variant?.sku??void 0),a)),o(e,"vendor",s(i(t.variant?.product?.vendor),u)),e})}(e);r.length>0&&(l.items=r,e.length>100&&(l.items_truncated=!0))}else if("cart_viewed"===e){o(l,"cart_total",n(d?.cost?.totalAmount?.amount??d?.totalAmount?.amount));o(l,"item_count",r(d?.lines??d?.lineItems))}else if("checkout_started"===e){o(l,"cart_total",n(c?.totalPrice?.amount??c?.subtotalPrice?.amount)),o(l,"currency",i(c?.currencyCode??c?.totalPrice?.currencyCode));o(l,"item_count",r(c?.lineItems)??r(t.data?.checkoutLineItems))}else{o(l,"currency",i(c?.currencyCode??c?.totalPrice?.currencyCode));const t=c?.totalPrice?.amount;o(l,"cart_total",n(t))}return l}function r(t){if(!t||0===t.length)return;let e=0;for(const i of t){e+=n(i?.quantity)??0}return e>0?e:t.length}const u=255,a=128;function s(t,e){if(void 0!==t)return t.length>e?t.slice(0,e):t}function d(t){const e=i(t.context?.window?.location?.href)??i(t.context?.document?.location?.href);return e?function(t){const e=t.indexOf("?"),n=t.indexOf("#");let i=t.length;return-1!==e&&(i=e),-1!==n&&n<i&&(i=n),t.slice(0,i)}(e):"unknown"}function l(t,n){if(!t)return null;const o=t.data?.checkout?.attributes,r=t.data?.cart?.attributes,u=e(o,"tracelog_session_id")??e(r,"tracelog_session_id"),a=e(o,"tracelog_user_id")??e(r,"tracelog_user_id");if(!u||!a)return null;const s=function(t){if("string"!=typeof t||0===t.length)return Date.now();const e=Date.parse(t);return Number.isFinite(e)?e:Date.now()}(t.timestamp),l=function(t,e){return`${e}-001-${i(t.id)?.slice(-6)??Math.random().toString(36).slice(2,8)}`}(t,s),_=c(t,n);return{user_id:a,session_id:u,device:{type:"unknown",os:"unknown",browser:"unknown"},events:[{id:l,type:"custom",page_url:d(t),timestamp:s,custom_event:{name:`shopify_${n}`,metadata:_}}],_metadata:{client_version:"shopify-web-pixel-1",timestamp:s}}}function _(t,e){if(!t.projectId)return;const n=`https://ingest.tracelog.io/p/${encodeURIComponent(t.projectId)}/collect`;try{fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},keepalive:!0,body:JSON.stringify(e)}).catch(()=>{})}catch{}}return t.SHOPIFY_EVENTS=["cart_viewed","checkout_started","checkout_contact_info_submitted","checkout_address_info_submitted","checkout_shipping_info_submitted","payment_info_submitted","checkout_completed"],t.mapEventToBody=l,t.registerShopifyPixel=function(t,e){const n=(t,n)=>{const i=l(n,t);i&&_(e,i)};t.analytics.subscribe("cart_viewed",t=>{n("cart_viewed",t)}),t.analytics.subscribe("checkout_started",t=>{n("checkout_started",t)}),t.analytics.subscribe("checkout_contact_info_submitted",t=>{n("checkout_contact_info_submitted",t)}),t.analytics.subscribe("checkout_address_info_submitted",t=>{n("checkout_address_info_submitted",t)}),t.analytics.subscribe("checkout_shipping_info_submitted",t=>{n("checkout_shipping_info_submitted",t)}),t.analytics.subscribe("payment_info_submitted",t=>{n("payment_info_submitted",t)}),t.analytics.subscribe("checkout_completed",t=>{n("checkout_completed",t)})},t.sendBatch=_,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),t}({});
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracelog-shopify-pixel.iife.js","sources":["../../src/pixel/event-mapper.ts","../../src/pixel/pixel-sender.ts","../../src/pixel/shopify-pixel.ts"],"sourcesContent":["import type { PixelEventBody } from './pixel-sender';\n\nconst PIXEL_CLIENT_VERSION = 'shopify-web-pixel-1';\n\nconst MAX_LINE_ITEMS = 100;\n\nexport const SHOPIFY_EVENTS = [\n 'cart_viewed',\n 'checkout_started',\n 'checkout_contact_info_submitted',\n 'checkout_address_info_submitted',\n 'checkout_shipping_info_submitted',\n 'payment_info_submitted',\n 'checkout_completed',\n] as const;\n\nexport type ShopifyEventName = (typeof SHOPIFY_EVENTS)[number];\n\n/**\n * Spike-confirmed shape ([04-spike-report.md](../../docs/tasks/shopify-hybrid-capture/04-spike-report.md)):\n * `event.data.{cart,checkout}.attributes` is `Array<{key, value, __typename?}>`,\n * NOT a plain object. `__typename: 'NoteAttribute'` is added on `checkout_completed`\n * only — harmless because we lookup by `key`.\n */\ninterface ShopifyAttribute {\n key?: string;\n value?: string;\n __typename?: string;\n}\n\ninterface ShopifyMoney {\n amount?: number;\n currencyCode?: string;\n}\n\ninterface ShopifyLineItemVariantProduct {\n id?: string | number;\n title?: string;\n vendor?: string;\n}\n\ninterface ShopifyLineItemVariant {\n id?: string | number;\n sku?: string | null;\n price?: ShopifyMoney;\n product?: ShopifyLineItemVariantProduct;\n}\n\ninterface ShopifyLineItem {\n id?: string | number;\n title?: string;\n quantity?: number;\n variant?: ShopifyLineItemVariant;\n finalLinePrice?: ShopifyMoney;\n}\n\ninterface ShopifyCheckout {\n token?: string;\n currencyCode?: string;\n totalPrice?: ShopifyMoney;\n subtotalPrice?: ShopifyMoney;\n attributes?: ShopifyAttribute[];\n lineItems?: ShopifyLineItem[];\n order?: { id?: string | number };\n}\n\ninterface ShopifyCart {\n attributes?: ShopifyAttribute[];\n totalAmount?: ShopifyMoney;\n cost?: { totalAmount?: ShopifyMoney };\n lines?: ShopifyLineItem[];\n lineItems?: ShopifyLineItem[];\n}\n\ninterface ShopifyCheckoutLineItem {\n quantity?: number;\n}\n\ninterface ShopifyEvent {\n id?: string;\n timestamp?: string;\n clientId?: string;\n data?: {\n checkout?: ShopifyCheckout;\n cart?: ShopifyCart;\n checkoutLineItems?: ShopifyCheckoutLineItem[];\n };\n context?: {\n window?: { location?: { href?: string } };\n document?: { location?: { href?: string } };\n };\n}\n\nfunction attrLookup(attrs: ShopifyAttribute[] | undefined, key: string): string | null {\n if (!Array.isArray(attrs)) return null;\n for (const a of attrs) {\n if (a && a.key === key && typeof a.value === 'string' && a.value.length > 0) return a.value;\n }\n return null;\n}\n\nfunction safeNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction safeString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction setIfDefined<T>(target: Record<string, unknown>, key: string, value: T | undefined): void {\n if (value !== undefined) target[key] = value;\n}\n\nfunction buildMetadata(event: ShopifyEvent, name: ShopifyEventName): Record<string, unknown> {\n const checkout = event.data?.checkout;\n const cart = event.data?.cart;\n const meta: Record<string, unknown> = {};\n\n setIfDefined(meta, 'shopify_client_id', safeString(event.clientId));\n\n const checkoutToken = safeString(checkout?.token);\n if (checkoutToken) meta['checkout_token'] = checkoutToken;\n\n if (name === 'checkout_completed') {\n const total = checkout?.totalPrice?.amount ?? checkout?.subtotalPrice?.amount;\n setIfDefined(meta, 'value', safeNumber(total));\n setIfDefined(meta, 'currency', safeString(checkout?.currencyCode ?? checkout?.totalPrice?.currencyCode));\n const orderId = checkout?.order?.id;\n if (orderId !== undefined && orderId !== null) meta['orderId'] = String(orderId);\n const rawItems = checkout?.lineItems ?? [];\n const items = mapLineItems(rawItems);\n if (items.length > 0) {\n meta['items'] = items;\n if (rawItems.length > MAX_LINE_ITEMS) meta['items_truncated'] = true;\n }\n } else if (name === 'cart_viewed') {\n const cartTotal = cart?.cost?.totalAmount?.amount ?? cart?.totalAmount?.amount;\n setIfDefined(meta, 'cart_total', safeNumber(cartTotal));\n const itemCount = countLineItems(cart?.lines ?? cart?.lineItems);\n setIfDefined(meta, 'item_count', itemCount);\n } else if (name === 'checkout_started') {\n const total = checkout?.totalPrice?.amount ?? checkout?.subtotalPrice?.amount;\n setIfDefined(meta, 'cart_total', safeNumber(total));\n setIfDefined(meta, 'currency', safeString(checkout?.currencyCode ?? checkout?.totalPrice?.currencyCode));\n const itemCount = countLineItems(checkout?.lineItems) ?? countLineItems(event.data?.checkoutLineItems);\n setIfDefined(meta, 'item_count', itemCount);\n } else {\n setIfDefined(meta, 'currency', safeString(checkout?.currencyCode ?? checkout?.totalPrice?.currencyCode));\n const total = checkout?.totalPrice?.amount;\n setIfDefined(meta, 'cart_total', safeNumber(total));\n }\n\n return meta;\n}\n\nfunction countLineItems(items: { quantity?: number }[] | undefined): number | undefined {\n if (!items || items.length === 0) return undefined;\n let count = 0;\n for (const item of items) {\n const q = safeNumber(item?.quantity);\n count += q ?? 0;\n }\n // Fallback to row count when every line is missing a numeric quantity.\n return count > 0 ? count : items.length;\n}\n\n// Caps merchant-controlled free-text to keep payloads under the API's per-string DTO limit.\n// IDs, tokens, and currency codes are naturally bounded by Shopify and skip capping.\nconst MAX_TEXT_LEN = 255;\nconst MAX_SKU_LEN = 128;\n\nfunction cap(value: string | undefined, max: number): string | undefined {\n if (value === undefined) return undefined;\n return value.length > max ? value.slice(0, max) : value;\n}\n\nfunction mapLineItems(items: ShopifyLineItem[] | undefined): Record<string, unknown>[] {\n if (!items || items.length === 0) return [];\n const capped = items.slice(0, MAX_LINE_ITEMS);\n return capped.map((item) => {\n const out: Record<string, unknown> = {};\n setIfDefined(out, 'id', safeString(item.variant?.id !== undefined ? String(item.variant.id) : undefined));\n setIfDefined(out, 'title', cap(safeString(item.title ?? item.variant?.product?.title), MAX_TEXT_LEN));\n setIfDefined(out, 'quantity', safeNumber(item.quantity));\n setIfDefined(out, 'price', safeNumber(item.variant?.price?.amount ?? item.finalLinePrice?.amount));\n setIfDefined(out, 'sku', cap(safeString(item.variant?.sku ?? undefined), MAX_SKU_LEN));\n setIfDefined(out, 'vendor', cap(safeString(item.variant?.product?.vendor), MAX_TEXT_LEN));\n return out;\n });\n}\n\nfunction generateEventId(event: ShopifyEvent, ts: number): string {\n const suffix = safeString(event.id)?.slice(-6) ?? Math.random().toString(36).slice(2, 8);\n return `${ts}-001-${suffix}`;\n}\n\nfunction resolveTimestamp(value: string | undefined): number {\n if (typeof value !== 'string' || value.length === 0) return Date.now();\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : Date.now();\n}\n\nfunction stripUrlParams(href: string): string {\n // Pixel runs in the checkout sandbox where href can carry recovery tokens\n // (`?recovery=...`, `?key=...`). Path alone identifies the funnel stage; drop\n // query and hash to keep tokens out of telemetry. Mirrors the policy in\n // `src/utils/network/url.utils.ts` (which is too heavy to import into the\n // sub-5KB pixel bundle).\n const queryIdx = href.indexOf('?');\n const hashIdx = href.indexOf('#');\n let cutoff = href.length;\n if (queryIdx !== -1) cutoff = queryIdx;\n if (hashIdx !== -1 && hashIdx < cutoff) cutoff = hashIdx;\n return href.slice(0, cutoff);\n}\n\nfunction resolvePageUrl(event: ShopifyEvent): string {\n const href = safeString(event.context?.window?.location?.href) ?? safeString(event.context?.document?.location?.href);\n return href ? stripUrlParams(href) : 'unknown';\n}\n\nexport function mapEventToBody(\n shopifyEvent: ShopifyEvent | null | undefined,\n shopifyEventName: ShopifyEventName,\n): PixelEventBody | null {\n if (!shopifyEvent) return null;\n\n const checkoutAttrs = shopifyEvent.data?.checkout?.attributes;\n const cartAttrs = shopifyEvent.data?.cart?.attributes;\n\n const sessionId = attrLookup(checkoutAttrs, 'tracelog_session_id') ?? attrLookup(cartAttrs, 'tracelog_session_id');\n const userId = attrLookup(checkoutAttrs, 'tracelog_user_id') ?? attrLookup(cartAttrs, 'tracelog_user_id');\n\n if (!sessionId || !userId) return null;\n\n const ts = resolveTimestamp(shopifyEvent.timestamp);\n const eventId = generateEventId(shopifyEvent, ts);\n const metadata = buildMetadata(shopifyEvent, shopifyEventName);\n\n return {\n user_id: userId,\n session_id: sessionId,\n device: { type: 'unknown', os: 'unknown', browser: 'unknown' },\n events: [\n {\n id: eventId,\n type: 'custom',\n page_url: resolvePageUrl(shopifyEvent),\n timestamp: ts,\n custom_event: {\n name: `shopify_${shopifyEventName}`,\n metadata,\n },\n },\n ],\n _metadata: {\n client_version: PIXEL_CLIENT_VERSION,\n timestamp: ts,\n },\n };\n}\n","/**\n * Standalone HTTP sender for the Shopify Web Pixel Extension bundle.\n *\n * Posts to the path-based ingress (`ingest.tracelog.io/p/<id>/collect`) — NOT\n * `api.tracelog.io/events/collect` — because the middleware has the only CORS\n * handler that accepts `Origin: null` from sandboxed iframes.\n *\n * Best-effort: failures are silently swallowed. The webhook (Task 03) carries\n * the revenue contract; pixel events are funnel-only and accept ~5-30% loss.\n */\n\nconst INGEST_HOST = 'https://ingest.tracelog.io';\n\nexport interface PixelSenderSettings {\n /** TraceLog project identifier (e.g. `t756edc0pnn17ha7`). Provided by Shopify init payload. */\n projectId: string;\n}\n\nexport interface PixelEventBody {\n user_id: string;\n session_id: string;\n device: { type: string; os: string; browser: string };\n events: Array<{\n id: string;\n type: 'custom';\n page_url: string;\n timestamp: number;\n custom_event: { name: string; metadata: Record<string, unknown> };\n }>;\n _metadata: { client_version: string; timestamp: number };\n}\n\nexport function sendBatch(settings: PixelSenderSettings, body: PixelEventBody): void {\n // Trust boundary is the Shopify extension settings form, but a misconfigured\n // (empty) projectId would yield `https://ingest.tracelog.io/p//collect` and\n // 404 every event. Drop silently so it can be diagnosed via Shopify pixel logs.\n if (!settings.projectId) return;\n\n // Encode in case the merchant pastes whitespace, slashes, or other unsafe\n // characters into the Shopify extension settings form.\n const url = `${INGEST_HOST}/p/${encodeURIComponent(settings.projectId)}/collect`;\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n keepalive: true,\n body: JSON.stringify(body),\n }).catch(() => {});\n } catch {\n // Pixel runs inside Shopify's strict sandbox; fetch() may be unavailable\n // or throw synchronously. Funnel events are best-effort — drop silently.\n }\n}\n","import { mapEventToBody, type ShopifyEventName } from './event-mapper';\nimport { sendBatch, type PixelSenderSettings } from './pixel-sender';\n\ninterface ShopifyAnalyticsApi {\n subscribe: (event: ShopifyEventName, callback: (event: unknown) => void) => void;\n}\n\ninterface ShopifyPixelApi {\n analytics: ShopifyAnalyticsApi;\n}\n\n/**\n * Registers the TraceLog Shopify Web Pixel: subscribes to the 7 standard\n * Customer Events and forwards each one to `ingest.tracelog.io/p/<id>/collect`.\n *\n * Each subscription is declared explicitly because Shopify's static analyzer\n * inspects the bundle for `analytics.subscribe('event_name', ...)` calls;\n * loop-based subscriptions are flagged and the pixel is treated as inactive.\n */\nexport function registerShopifyPixel(api: ShopifyPixelApi, settings: PixelSenderSettings): void {\n const handle = (eventName: ShopifyEventName, payload: unknown): void => {\n const body = mapEventToBody(payload as Parameters<typeof mapEventToBody>[0], eventName);\n if (!body) return;\n sendBatch(settings, body);\n };\n\n api.analytics.subscribe('cart_viewed', (event) => {\n handle('cart_viewed', event);\n });\n api.analytics.subscribe('checkout_started', (event) => {\n handle('checkout_started', event);\n });\n api.analytics.subscribe('checkout_contact_info_submitted', (event) => {\n handle('checkout_contact_info_submitted', event);\n });\n api.analytics.subscribe('checkout_address_info_submitted', (event) => {\n handle('checkout_address_info_submitted', event);\n });\n api.analytics.subscribe('checkout_shipping_info_submitted', (event) => {\n handle('checkout_shipping_info_submitted', event);\n });\n api.analytics.subscribe('payment_info_submitted', (event) => {\n handle('payment_info_submitted', event);\n });\n api.analytics.subscribe('checkout_completed', (event) => {\n handle('checkout_completed', event);\n });\n}\n"],"names":["attrLookup","attrs","key","Array","isArray","a","value","length","safeNumber","Number","isFinite","safeString","setIfDefined","target","buildMetadata","event","name","checkout","data","cart","meta","clientId","checkoutToken","token","totalPrice","amount","subtotalPrice","currencyCode","orderId","order","id","String","rawItems","lineItems","items","capped","slice","map","item","out","variant","cap","title","product","MAX_TEXT_LEN","quantity","price","finalLinePrice","sku","MAX_SKU_LEN","vendor","mapLineItems","cost","totalAmount","countLineItems","lines","checkoutLineItems","total","count","max","resolvePageUrl","href","context","window","location","document","queryIdx","indexOf","hashIdx","cutoff","stripUrlParams","mapEventToBody","shopifyEvent","shopifyEventName","checkoutAttrs","attributes","cartAttrs","sessionId","userId","ts","Date","now","parsed","parse","resolveTimestamp","timestamp","eventId","Math","random","toString","generateEventId","metadata","user_id","session_id","device","type","os","browser","events","page_url","custom_event","_metadata","client_version","sendBatch","settings","body","projectId","url","encodeURIComponent","fetch","method","headers","keepalive","JSON","stringify","catch","api","handle","eventName","payload","analytics","subscribe"],"mappings":"kDA6FA,SAASA,EAAWC,EAAuCC,GACzD,IAAKC,MAAMC,QAAQH,GAAQ,OAAO,KAClC,IAAA,MAAWI,KAAKJ,EACd,GAAII,GAAKA,EAAEH,MAAQA,GAA0B,iBAAZG,EAAEC,OAAsBD,EAAEC,MAAMC,OAAS,SAAUF,EAAEC,MAExF,OAAO,IACT,CAEA,SAASE,EAAWF,GAClB,MAAwB,iBAAVA,GAAsBG,OAAOC,SAASJ,GAASA,OAAQ,CACvE,CAEA,SAASK,EAAWL,GAClB,MAAwB,iBAAVA,GAAsBA,EAAMC,OAAS,EAAID,OAAQ,CACjE,CAEA,SAASM,EAAgBC,EAAiCX,EAAaI,QACvD,IAAVA,IAAqBO,EAAOX,GAAOI,EACzC,CAEA,SAASQ,EAAcC,EAAqBC,GAC1C,MAAMC,EAAWF,EAAMG,MAAMD,SACvBE,EAAOJ,EAAMG,MAAMC,KACnBC,EAAgC,CAAA,EAEtCR,EAAaQ,EAAM,oBAAqBT,EAAWI,EAAMM,WAEzD,MAAMC,EAAgBX,EAAWM,GAAUM,OAG3C,GAFID,IAAeF,EAAqB,eAAIE,GAE/B,uBAATN,EAA+B,CAEjCJ,EAAaQ,EAAM,QAASZ,EADdS,GAAUO,YAAYC,QAAUR,GAAUS,eAAeD,SAEvEb,EAAaQ,EAAM,WAAYT,EAAWM,GAAUU,cAAgBV,GAAUO,YAAYG,eAC1F,MAAMC,EAAUX,GAAUY,OAAOC,GAC7BF,YAAyD,QAAIG,OAAOH,IACxE,MAAMI,EAAWf,GAAUgB,WAAa,GAClCC,EA8CV,SAAsBA,GACpB,IAAKA,GAA0B,IAAjBA,EAAM3B,aAAqB,GACzC,MAAM4B,EAASD,EAAME,MAAM,EA9KN,KA+KrB,OAAOD,EAAOE,IAAKC,IACjB,MAAMC,EAA+B,CAAA,EAOrC,OANA3B,EAAa2B,EAAK,KAAM5B,OAAgC,IAArB2B,EAAKE,SAASV,GAAmBC,OAAOO,EAAKE,QAAQV,SAAM,IAC9FlB,EAAa2B,EAAK,QAASE,EAAI9B,EAAW2B,EAAKI,OAASJ,EAAKE,SAASG,SAASD,OAAQE,IACvFhC,EAAa2B,EAAK,WAAY/B,EAAW8B,EAAKO,WAC9CjC,EAAa2B,EAAK,QAAS/B,EAAW8B,EAAKE,SAASM,OAAOrB,QAAUa,EAAKS,gBAAgBtB,SAC1Fb,EAAa2B,EAAK,MAAOE,EAAI9B,EAAW2B,EAAKE,SAASQ,UAAO,GAAYC,IACzErC,EAAa2B,EAAK,SAAUE,EAAI9B,EAAW2B,EAAKE,SAASG,SAASO,QAASN,IACpEL,GAEX,CA3DkBY,CAAanB,GACvBE,EAAM3B,OAAS,IACjBa,EAAY,MAAIc,EACZF,EAASzB,OAjII,MAiIqBa,EAAsB,iBAAI,GAEpE,MAAA,GAAoB,gBAATJ,EAAwB,CAEjCJ,EAAaQ,EAAM,aAAcZ,EADfW,GAAMiC,MAAMC,aAAa5B,QAAUN,GAAMkC,aAAa5B,SAGxEb,EAAaQ,EAAM,aADDkC,EAAenC,GAAMoC,OAASpC,GAAMc,WAExD,MAAA,GAAoB,qBAATjB,EAA6B,CAEtCJ,EAAaQ,EAAM,aAAcZ,EADnBS,GAAUO,YAAYC,QAAUR,GAAUS,eAAeD,SAEvEb,EAAaQ,EAAM,WAAYT,EAAWM,GAAUU,cAAgBV,GAAUO,YAAYG,eAE1Ff,EAAaQ,EAAM,aADDkC,EAAerC,GAAUgB,YAAcqB,EAAevC,EAAMG,MAAMsC,mBAEtF,KAAO,CACL5C,EAAaQ,EAAM,WAAYT,EAAWM,GAAUU,cAAgBV,GAAUO,YAAYG,eAC1F,MAAM8B,EAAQxC,GAAUO,YAAYC,OACpCb,EAAaQ,EAAM,aAAcZ,EAAWiD,GAC9C,CAEA,OAAOrC,CACT,CAEA,SAASkC,EAAepB,GACtB,IAAKA,GAA0B,IAAjBA,EAAM3B,OAAc,OAClC,IAAImD,EAAQ,EACZ,IAAA,MAAWpB,KAAQJ,EAAO,CAExBwB,GADUlD,EAAW8B,GAAMO,WACb,CAChB,CAEA,OAAOa,EAAQ,EAAIA,EAAQxB,EAAM3B,MACnC,CAIA,MAAMqC,EAAe,IACfK,EAAc,IAEpB,SAASR,EAAInC,EAA2BqD,GACtC,QAAc,IAAVrD,EACJ,OAAOA,EAAMC,OAASoD,EAAMrD,EAAM8B,MAAM,EAAGuB,GAAOrD,CACpD,CA0CA,SAASsD,EAAe7C,GACtB,MAAM8C,EAAOlD,EAAWI,EAAM+C,SAASC,QAAQC,UAAUH,OAASlD,EAAWI,EAAM+C,SAASG,UAAUD,UAAUH,MAChH,OAAOA,EAhBT,SAAwBA,GAMtB,MAAMK,EAAWL,EAAKM,QAAQ,KACxBC,EAAUP,EAAKM,QAAQ,KAC7B,IAAIE,EAASR,EAAKtD,OAGlB,WAFI2D,IAAiBG,EAASH,IACd,IAAZE,GAAkBA,EAAUC,IAAQA,EAASD,GAC1CP,EAAKzB,MAAM,EAAGiC,EACvB,CAIgBC,CAAeT,GAAQ,SACvC,CAEO,SAASU,EACdC,EACAC,GAEA,IAAKD,EAAc,OAAO,KAE1B,MAAME,EAAgBF,EAAatD,MAAMD,UAAU0D,WAC7CC,EAAYJ,EAAatD,MAAMC,MAAMwD,WAErCE,EAAY7E,EAAW0E,EAAe,wBAA0B1E,EAAW4E,EAAW,uBACtFE,EAAS9E,EAAW0E,EAAe,qBAAuB1E,EAAW4E,EAAW,oBAEtF,IAAKC,IAAcC,EAAQ,OAAO,KAElC,MAAMC,EAvCR,SAA0BzE,GACxB,GAAqB,iBAAVA,GAAuC,IAAjBA,EAAMC,OAAc,OAAOyE,KAAKC,MACjE,MAAMC,EAASF,KAAKG,MAAM7E,GAC1B,OAAOG,OAAOC,SAASwE,GAAUA,EAASF,KAAKC,KACjD,CAmCaG,CAAiBZ,EAAaa,WACnCC,EA7CR,SAAyBvE,EAAqBgE,GAE5C,MAAO,GAAGA,SADKpE,EAAWI,EAAMe,KAAKM,OAAM,IAAOmD,KAAKC,SAASC,SAAS,IAAIrD,MAAM,EAAG,IAExF,CA0CkBsD,CAAgBlB,EAAcO,GACxCY,EAAW7E,EAAc0D,EAAcC,GAE7C,MAAO,CACLmB,QAASd,EACTe,WAAYhB,EACZiB,OAAQ,CAAEC,KAAM,UAAWC,GAAI,UAAWC,QAAS,WACnDC,OAAQ,CACN,CACEpE,GAAIwD,EACJS,KAAM,SACNI,SAAUvC,EAAeY,GACzBa,UAAWN,EACXqB,aAAc,CACZpF,KAAM,WAAWyD,IACjBkB,cAINU,UAAW,CACTC,eA9PuB,sBA+PvBjB,UAAWN,GAGjB,CCpOO,SAASwB,EAAUC,EAA+BC,GAIvD,IAAKD,EAASE,UAAW,OAIzB,MAAMC,EAAM,gCAAoBC,mBAAmBJ,EAASE,qBAC5D,IACOG,MAAMF,EAAK,CACdG,OAAQ,OACRC,QAAS,CAAE,eAAgB,oBAC3BC,WAAW,EACXP,KAAMQ,KAAKC,UAAUT,KACpBU,MAAM,OACX,CAAA,MAGA,CACF,yBD9C8B,CAC5B,cACA,mBACA,kCACA,kCACA,mCACA,yBACA,gEEMK,SAA8BC,EAAsBZ,GACzD,MAAMa,EAAS,CAACC,EAA6BC,KAC3C,MAAMd,EAAOlC,EAAegD,EAAiDD,GACxEb,GACLF,EAAUC,EAAUC,IAGtBW,EAAII,UAAUC,UAAU,cAAgB1G,IACtCsG,EAAO,cAAetG,KAExBqG,EAAII,UAAUC,UAAU,mBAAqB1G,IAC3CsG,EAAO,mBAAoBtG,KAE7BqG,EAAII,UAAUC,UAAU,kCAAoC1G,IAC1DsG,EAAO,kCAAmCtG,KAE5CqG,EAAII,UAAUC,UAAU,kCAAoC1G,IAC1DsG,EAAO,kCAAmCtG,KAE5CqG,EAAII,UAAUC,UAAU,mCAAqC1G,IAC3DsG,EAAO,mCAAoCtG,KAE7CqG,EAAII,UAAUC,UAAU,yBAA2B1G,IACjDsG,EAAO,yBAA0BtG,KAEnCqG,EAAII,UAAUC,UAAU,qBAAuB1G,IAC7CsG,EAAO,qBAAsBtG,IAEjC"}