{"version":3,"sources":["../../src/track/index.ts"],"sourcesContent":["import { TokenBucket, fetch } from '@shware/utils';\nimport type { CreateTrackEventDTO } from '../schema/index';\nimport { cache, config } from '../setup/index';\nimport { session } from '../setup/session';\nimport { IGNORED_EVENTS } from '../third-parties/ignored-events';\nimport { getVisitor } from '../visitor/index';\nimport type { EventName, TrackEventResponse, TrackName, TrackProperties } from './types';\n\nexport interface TrackOptions {\n  enableThirdPartyTracking?: boolean;\n  onSucceed?: (response?: TrackEventResponse[number]) => void;\n  onError?: (error: unknown) => void;\n}\n\nconst defaultOptions: TrackOptions = { enableThirdPartyTracking: true };\nconst tokenBucket = new TokenBucket({ rate: 1, capacity: 20, requested: 2 });\n\ntype Item = {\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  name: TrackName<any>;\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  properties: TrackProperties<any>;\n  timestamp: string;\n  options: TrackOptions;\n};\n\nasync function sendEvents(events: Item[]) {\n  try {\n    if (events.length === 0) return;\n\n    if (session.isExpired()) {\n      session.refresh();\n      events.unshift({\n        name: 'session_start',\n        properties: {},\n        options: { enableThirdPartyTracking: false },\n        timestamp: new Date().toISOString(),\n      });\n    } else {\n      session.updateLastActiveTime();\n    }\n\n    await tokenBucket.removeTokens();\n\n    const tags = await config.getTags();\n    const visitor_id = (await getVisitor()).id;\n\n    const dto: CreateTrackEventDTO = events.map((event) => ({\n      name: event.name,\n      properties: event.properties,\n      tags,\n      visitor_id,\n      session_id: session.getId(),\n      platform: config.platform,\n      environment: config.environment,\n      timestamp: event.timestamp,\n    }));\n\n    const response = await fetch(`${config.endpoint}/events`, {\n      method: 'POST',\n      credentials: 'include',\n      headers: await config.getHeaders(),\n      body: JSON.stringify(dto),\n    });\n\n    if (!response.ok) {\n      throw new Error(`Failed to send track event: ${response.status} ${await response.text()}`);\n    }\n\n    const data = (await response.json()) as TrackEventResponse;\n\n    let index = 0;\n    while (events.length > 0) {\n      const event = events.shift();\n      if (!event) {\n        index++;\n        continue;\n      }\n      const { options, name, properties } = event;\n      const eventId = data[index].id;\n      options.onSucceed?.({ id: eventId });\n      index++;\n      if (\n        !config.thirdPartyTrackers ||\n        !options.enableThirdPartyTracking ||\n        IGNORED_EVENTS.includes(name)\n      ) {\n        continue;\n      }\n      config.thirdPartyTrackers.forEach((tracker) => tracker(name, properties, eventId));\n    }\n  } catch (e: unknown) {\n    if (e instanceof Error) console.log(e.message);\n    events.forEach((event) => event.options.onError?.(e));\n  }\n}\n\nconst batch = 10;\nconst delay = 2000;\nconst list: Item[] = [];\nlet timer: ReturnType<typeof setTimeout> | null = null;\n\nexport function track<T extends EventName = EventName>(\n  name: TrackName<T>,\n  properties?: TrackProperties<T>,\n  options: TrackOptions = defaultOptions\n) {\n  list.push({ name, properties, options, timestamp: new Date().toISOString() });\n  if (list.length >= batch) {\n    const copy = [...list];\n    list.length = 0;\n    sendEvents(copy);\n    return;\n  }\n  if (timer) clearTimeout(timer);\n  timer = setTimeout(() => {\n    timer = null;\n    const copy = [...list];\n    list.length = 0;\n    sendEvents(copy);\n  }, delay);\n}\n\nexport async function trackAsync<T extends EventName = EventName>(\n  name: TrackName<T>,\n  properties?: TrackProperties<T>,\n  options: TrackOptions = defaultOptions\n) {\n  await sendEvents([{ name, properties, options, timestamp: new Date().toISOString() }]);\n}\n\nexport function sendBeacon<T extends EventName = EventName>(\n  name: TrackName<T>,\n  properties?: TrackProperties<T>\n) {\n  if (!cache.tags || !cache.visitor) return;\n  session.updateLastActiveTime();\n\n  const dto: CreateTrackEventDTO = [\n    {\n      name,\n      properties,\n      tags: cache.tags,\n      visitor_id: cache.visitor.id,\n      session_id: session.getId(),\n      platform: config.platform,\n      environment: config.environment,\n      timestamp: new Date().toISOString(),\n    },\n  ];\n  const blob = new Blob([JSON.stringify(dto)], { type: 'application/json' });\n  const success = navigator.sendBeacon(`${config.endpoint}/events`, blob);\n  if (success) return;\n  console.warn('Failed to send beacon', name, properties);\n}\n"],"mappings":";AAAA,SAAS,aAAa,aAAa;AAEnC,SAAS,OAAO,cAAc;AAC9B,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAS3B,IAAM,iBAA+B,EAAE,0BAA0B,KAAK;AACtE,IAAM,cAAc,IAAI,YAAY,EAAE,MAAM,GAAG,UAAU,IAAI,WAAW,EAAE,CAAC;AAW3E,eAAe,WAAW,QAAgB;AA1B1C;AA2BE,MAAI;AACF,QAAI,OAAO,WAAW,EAAG;AAEzB,QAAI,QAAQ,UAAU,GAAG;AACvB,cAAQ,QAAQ;AAChB,aAAO,QAAQ;AAAA,QACb,MAAM;AAAA,QACN,YAAY,CAAC;AAAA,QACb,SAAS,EAAE,0BAA0B,MAAM;AAAA,QAC3C,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,qBAAqB;AAAA,IAC/B;AAEA,UAAM,YAAY,aAAa;AAE/B,UAAM,OAAO,MAAM,OAAO,QAAQ;AAClC,UAAM,cAAc,MAAM,WAAW,GAAG;AAExC,UAAM,MAA2B,OAAO,IAAI,CAAC,WAAW;AAAA,MACtD,MAAM,MAAM;AAAA,MACZ,YAAY,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA,YAAY,QAAQ,MAAM;AAAA,MAC1B,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,WAAW,MAAM;AAAA,IACnB,EAAE;AAEF,UAAM,WAAW,MAAM,MAAM,GAAG,OAAO,QAAQ,WAAW;AAAA,MACxD,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,SAAS,MAAM,OAAO,WAAW;AAAA,MACjC,MAAM,KAAK,UAAU,GAAG;AAAA,IAC1B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,+BAA+B,SAAS,MAAM,IAAI,MAAM,SAAS,KAAK,CAAC,EAAE;AAAA,IAC3F;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,QAAI,QAAQ;AACZ,WAAO,OAAO,SAAS,GAAG;AACxB,YAAM,QAAQ,OAAO,MAAM;AAC3B,UAAI,CAAC,OAAO;AACV;AACA;AAAA,MACF;AACA,YAAM,EAAE,SAAS,MAAM,WAAW,IAAI;AACtC,YAAM,UAAU,KAAK,KAAK,EAAE;AAC5B,oBAAQ,cAAR,iCAAoB,EAAE,IAAI,QAAQ;AAClC;AACA,UACE,CAAC,OAAO,sBACR,CAAC,QAAQ,4BACT,eAAe,SAAS,IAAI,GAC5B;AACA;AAAA,MACF;AACA,aAAO,mBAAmB,QAAQ,CAAC,YAAY,QAAQ,MAAM,YAAY,OAAO,CAAC;AAAA,IACnF;AAAA,EACF,SAAS,GAAY;AACnB,QAAI,aAAa,MAAO,SAAQ,IAAI,EAAE,OAAO;AAC7C,WAAO,QAAQ,CAAC,UAAO;AA7F3B,UAAAA,KAAA;AA6F8B,oBAAAA,MAAA,MAAM,SAAQ,YAAd,wBAAAA,KAAwB;AAAA,KAAE;AAAA,EACtD;AACF;AAEA,IAAM,QAAQ;AACd,IAAM,QAAQ;AACd,IAAM,OAAe,CAAC;AACtB,IAAI,QAA8C;AAE3C,SAAS,MACd,MACA,YACA,UAAwB,gBACxB;AACA,OAAK,KAAK,EAAE,MAAM,YAAY,SAAS,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAC5E,MAAI,KAAK,UAAU,OAAO;AACxB,UAAM,OAAO,CAAC,GAAG,IAAI;AACrB,SAAK,SAAS;AACd,eAAW,IAAI;AACf;AAAA,EACF;AACA,MAAI,MAAO,cAAa,KAAK;AAC7B,UAAQ,WAAW,MAAM;AACvB,YAAQ;AACR,UAAM,OAAO,CAAC,GAAG,IAAI;AACrB,SAAK,SAAS;AACd,eAAW,IAAI;AAAA,EACjB,GAAG,KAAK;AACV;AAEA,eAAsB,WACpB,MACA,YACA,UAAwB,gBACxB;AACA,QAAM,WAAW,CAAC,EAAE,MAAM,YAAY,SAAS,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC,CAAC;AACvF;AAEO,SAAS,WACd,MACA,YACA;AACA,MAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,QAAS;AACnC,UAAQ,qBAAqB;AAE7B,QAAM,MAA2B;AAAA,IAC/B;AAAA,MACE;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,YAAY,MAAM,QAAQ;AAAA,MAC1B,YAAY,QAAQ,MAAM;AAAA,MAC1B,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,EACF;AACA,QAAM,OAAO,IAAI,KAAK,CAAC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACzE,QAAM,UAAU,UAAU,WAAW,GAAG,OAAO,QAAQ,WAAW,IAAI;AACtE,MAAI,QAAS;AACb,UAAQ,KAAK,yBAAyB,MAAM,UAAU;AACxD;","names":["_a"]}