lee_web_track_sdk 0.0.8 → 0.0.9

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/esm/index.js CHANGED
@@ -362,6 +362,7 @@ var request = function(url, data) {
362
362
  return [
363
363
  2,
364
364
  new Promise(function(resolve, reject) {
365
+ console.trace("Current call stack:");
365
366
  if ("sendBeacon" in navigator) {
366
367
  var jsonData = JSON.stringify(data);
367
368
  var formData = new FormData();
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/esm/index.js","../../src/index.ts","../../src/core/track/cache.ts","../../src/config/constant.ts","../../src/utils/utils.ts","../../src/utils/validator.ts","../../src/core/report/clean.ts","../../src/core/report/aggregation.ts","../../src/core/report/index.ts","../../src/utils/uuid.ts","../../src/utils/browser.ts"],"names":["localForage","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","getVariableType","variable","typeString","Object","prototype","toString","call","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","type","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","error","console","warn","offset","Date","getTimezoneOffset","validateEventType","eventType","includes","validateEventKey","params","keys","key","cleanData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","data","errReason","message","aggregationData","item","i","is_aggregation","currentDate","setHours","resultItem","find","push","customData","custom_data","count","length","request","url","Promise","resolve","reject","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","send","onReportFail","clearCacheKey","retryCount","reportErrorData","reportDataRequest","getItem","setItem","reportData","Array","isArray","removeItem","reportCacheData","cacheData","cleanInfo","result","getCacheData","setCacheData","maxLen","errMsg","localForage2","getUserId","track_uuid","localStorage","uuid","Browser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","parse","browser","os","platform","name","version","getDeviceResolution","screen","width","height","FrTrack","options","option","project_name","report_url","app_version","auto_pv","maxCacheSize","maxCacheTime","userId","routeMode","timer","uvTimer","browserInfo","assign","reportPrevData","res1","err","localForage3","loopReport","setInterval","onBrowserClose","addEventListener","clearInterval","document","visibilityState","init","frUserView","pushState","replaceState","frAutoPageView","track","trackParams","user_id","device_type","user_agent","screen_resolution","user_timezone","now","singleTrack","baseParams","setUser","setRouteMode","mode","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","methodsList","forEach","method","href","location","page_url","page_name","frPageView","interval","frPageDestroy","frReport","index_default","default"],"mappings":"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","sourcesContent":["// src/index.ts\nimport * as localForage3 from \"localforage\";\n\n// src/core/track/cache.ts\nimport * as localForage2 from \"localforage\";\n\n// src/config/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\", \"module_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn(\"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\", error);\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n console.warn(\"[Fr-track warning]: Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/report/clean.ts\nvar cleanData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn(\"[Fr-track warning]: error event type\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n console.warn(\"[Fr-track warning]: cleanData error\", error);\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/report/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn(\"[Fr-track warn]: \\u805A\\u5408\\u5931\\u8D25\", error);\n return rawData;\n }\n};\n\n// src/core/report/index.ts\nimport * as localForage from \"localforage\";\nvar request = async (url, data) => {\n return new Promise((resolve, reject) => {\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\nvar onReportFail = async (url, data, clearCacheKey, retryCount) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n let reportErrorData = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\nvar reportDataRequest = async (url, data, clearCacheKey = \"\", retryCount = 1) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\nvar reportCacheData = async (url) => {\n try {\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== \"success\") {\n console.warn(\"[Fr-track warn]:\", cleanInfo.errReason);\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error(\"[Fr-track error]:\", error);\n }\n};\n\n// src/core/track/cache.ts\nvar setCacheData = async (data, url, maxLen, retryCount = 1) => {\n try {\n let cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage2.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n const errMsg = retryCount > 3 ? error : \"Retrying...\";\n if (retryCount <= 3) {\n console.warn(\"[Fr-track warning]:\" + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error(\"[Fr-track error]:\" + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\nvar getCacheData = async () => {\n try {\n const cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error(\"[Fr-track error]:\" + error);\n return [];\n }\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n};\n\n// src/utils/browser.ts\nimport Browser from \"bowser\";\nvar getBrowserAndDeviceInfo = () => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } catch (error) {\n return defRes;\n }\n};\nvar getDeviceResolution = () => {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\n// src/index.ts\nvar FrTrack = class {\n constructor(options) {\n this.option = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 3e5\n };\n this.userId = getUserId();\n this.routeMode = \"history\";\n this.timer = null;\n this.uvTimer = null;\n this.browserInfo = null;\n const {\n project_name,\n report_url,\n app_version = \"unknown\",\n auto_pv = false,\n maxCacheTime = 3e5,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n async reportPrevData() {\n try {\n const res = await localForage3.getItem(CACHE_DATA_NAME);\n const res1 = await localForage3.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn(\"[Fr-track warn]: \\u68C0\\u9A8C\\u5386\\u53F2\\u6570\\u636E\\u5931\\u8D25\");\n }\n }\n loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n init() {\n this.browserInfo = getBrowserAndDeviceInfo();\n this.reportPrevData();\n this.loopReport();\n this.onBrowserClose();\n this.frUserView();\n if (this.option.auto_pv) {\n if (this.routeMode === \"history\") {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n }\n this.frAutoPageView();\n }\n }\n track(params) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n setCacheData(trackParams, report_url, maxCacheSize);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n }\n /**\n * @method 自定义路由方式\n */\n setRouteMode(mode) {\n this.routeMode = mode;\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === \"hash\") {\n methodsList.push(\"hashchange\");\n } else {\n methodsList.push(...[\"popstate\", \"pushState\", \"replaceState\"]);\n }\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n const href = window.location.href || \"\";\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n });\n });\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n const currentDate = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n reportCacheData(this.option.report_url);\n }\n};\nvar index_default = FrTrack;\nexport {\n index_default as default\n};\n","import * as localForage from 'localforage';\nimport { trackEvent } from './core/track';\nimport { reportCacheData, reportDataRequest } from './core/report';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from './config/constant';\nimport { getUserId } from './utils/uuid';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from './utils/browser';\nimport { overrideHistoryMethods, getUserTimeZone } from './utils/utils';\nimport type {\n EventsType,\n BrowserInfoType,\n TrackEventItem,\n Options,\n CustomOptions,\n CustomData,\n TrackParams\n} from './types';\n\nclass FrTrack {\n public option: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 300000\n };\n\n private userId = getUserId();\n private routeMode: 'hash' | 'history' = 'history';\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private browserInfo: BrowserInfoType | null = null;\n public constructor(options: CustomOptions) {\n const {\n project_name,\n report_url,\n app_version = 'unknown',\n auto_pv = false,\n maxCacheTime = 300000,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n\n private async reportPrevData() {\n /**\n * 检测上次上报遗漏数据\n */\n try {\n const res: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n const res1: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn('[Fr-track warn]: 检验历史数据失败');\n }\n }\n\n private loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n // 重启定时器\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n\n public init() {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo();\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n /**\n * 4. 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n /**\n * 5. 统计uv\n */\n this.frUserView();\n /**\n * 6. 判断是否监听pv事件\n */\n if (this.option.auto_pv) {\n if (this.routeMode === 'history') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n }\n this.frAutoPageView();\n }\n }\n\n private track(params: TrackParams) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n trackEvent(trackParams, report_url, maxCacheSize);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n }\n\n /**\n * @method 自定义路由方式\n */\n public setRouteMode(mode: 'history' | 'hash') {\n this.routeMode = mode;\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === 'hash') {\n methodsList.push('hashchange');\n } else {\n methodsList.push(...['popstate', 'pushState', 'replaceState']);\n }\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n const href = window.location.href || '';\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n });\n });\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n const currentDate = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n // 超过24小时,再次上报uv\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n reportCacheData(this.option.report_url);\n }\n}\n\nexport default FrTrack;\n","import * as localForage from 'localforage';\nimport { reportCacheData, reportDataRequest } from '../report';\nimport { CACHE_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * set缓存数据\n * @param { object } data - 待缓存的数据\n * @param { string } url = 上报路径\n * @param { number } maxLen - 最大的缓存阈值\n * @param { number } retryCount - 重试次数\n */\nconst setCacheData = async (\n data: TrackEventItem,\n url: string,\n maxLen: number,\n retryCount = 1\n): Promise<void> => {\n // 优先采用indexedDB缓存,针对旧浏览器采用localstorage降级方案处理\n try {\n let cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n // 重试\n const errMsg = retryCount > 3 ? error : 'Retrying...';\n if (retryCount <= 3) {\n console.warn('[Fr-track warning]:' + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error('[Fr-track error]:' + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\n\n/**\n * get缓存的数据\n */\nconst getCacheData = async () => {\n try {\n const cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error('[Fr-track error]:' + error);\n return [];\n }\n};\n\nexport { setCacheData, getCacheData };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view', 'module_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn('无法获取时区名称,使用偏移量推算:', error);\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\nexport { getVariableType, generateUserId, overrideHistoryMethods, getUserTimeZone };\n","import { EVENT_TYPES, EVENT_KEYS } from '../config/constant';\nimport { getVariableType } from './utils';\nimport type { EventsType } from '../types/';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n console.warn('[Fr-track warning]: Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../../utils/validator';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn('[Fr-track warning]: error event type');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n console.warn('[Fr-track warning]: cleanData error', error);\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanData };\n","import { CAN_AGGREGATION_TYPES } from '../../config/constant';\nimport { TrackEventItem } from '../../types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn('[Fr-track warn]: 聚合失败', error);\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { getCacheData } from '../track/cache';\nimport { cleanData } from './clean';\nimport { aggregationData } from './aggregation';\nimport * as localForage from 'localforage';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 上报数据网络请求\n * @param { string } url 上报路径\n * @param { array } data 要上报的数据\n */\nconst request = async (url: string, data: TrackEventItem[]) => {\n return new Promise((resolve, reject) => {\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\n\n/**\n * 上报数据失败兜底处理\n * @param { string } url 上报路径\n * @param { number } retryCount 重试次数\n * @param { string } clearCacheKey 上报成功是否清除的缓存key值\n * @param { array | object } data 上报失败的数据\n */\nconst onReportFail = async (\n url: string,\n data: TrackEventItem[],\n clearCacheKey: string,\n retryCount: number\n) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n // 将上报失败的数据存入缓存\n let reportErrorData: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\n\n/**\n * 自定义上报数据\n * @param { string } url 上报路径\n * @param { array | object } data 待上报数据\n * @param { string } clearCacheKey 上报成功清除缓存的key\n * @param { number } retryCount 调用次数\n */\nconst reportDataRequest = async (\n url: string,\n data: TrackEventItem[] | TrackEventItem,\n clearCacheKey = '',\n retryCount = 1\n) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\n\n/**\n * 上报缓存中所有数据\n * @param { string } url 上报地址\n */\nconst reportCacheData = async (url: string) => {\n try {\n // 获取缓存数据\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== 'success') {\n console.warn('[Fr-track warn]:', cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n // 聚合\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n // 上报\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error('[Fr-track error]:', error);\n }\n};\n\nexport { reportCacheData, reportDataRequest };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport type { BrowserInfoType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } catch (error) {\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (): string => {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n"]}
1
+ {"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/esm/index.js","../../src/index.ts","../../src/core/track/cache.ts","../../src/config/constant.ts","../../src/utils/utils.ts","../../src/utils/validator.ts","../../src/core/report/clean.ts","../../src/core/report/aggregation.ts","../../src/core/report/index.ts","../../src/utils/uuid.ts","../../src/utils/browser.ts"],"names":["localForage","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","getVariableType","variable","typeString","Object","prototype","toString","call","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","type","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","error","console","warn","offset","Date","getTimezoneOffset","validateEventType","eventType","includes","validateEventKey","params","keys","key","cleanData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","data","errReason","message","aggregationData","item","i","is_aggregation","currentDate","setHours","resultItem","find","push","customData","custom_data","count","length","request","url","Promise","resolve","reject","trace","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","send","onReportFail","clearCacheKey","retryCount","reportErrorData","reportDataRequest","getItem","setItem","reportData","Array","isArray","removeItem","reportCacheData","cacheData","cleanInfo","result","getCacheData","setCacheData","maxLen","errMsg","localForage2","getUserId","track_uuid","localStorage","uuid","Browser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","parse","browser","os","platform","name","version","getDeviceResolution","screen","width","height","FrTrack","options","option","project_name","report_url","app_version","auto_pv","maxCacheSize","maxCacheTime","userId","routeMode","timer","uvTimer","browserInfo","assign","reportPrevData","res1","err","localForage3","loopReport","setInterval","onBrowserClose","addEventListener","clearInterval","document","visibilityState","init","frUserView","pushState","replaceState","frAutoPageView","track","trackParams","user_id","device_type","user_agent","screen_resolution","user_timezone","now","singleTrack","baseParams","setUser","setRouteMode","mode","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","methodsList","forEach","method","href","location","page_url","page_name","frPageView","interval","frPageDestroy","frReport","index_default","default"],"mappings":"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","sourcesContent":["// src/index.ts\nimport * as localForage3 from \"localforage\";\n\n// src/core/track/cache.ts\nimport * as localForage2 from \"localforage\";\n\n// src/config/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\", \"module_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn(\"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\", error);\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n console.warn(\"[Fr-track warning]: Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/report/clean.ts\nvar cleanData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn(\"[Fr-track warning]: error event type\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n console.warn(\"[Fr-track warning]: cleanData error\", error);\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/report/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn(\"[Fr-track warn]: \\u805A\\u5408\\u5931\\u8D25\", error);\n return rawData;\n }\n};\n\n// src/core/report/index.ts\nimport * as localForage from \"localforage\";\nvar request = async (url, data) => {\n return new Promise((resolve, reject) => {\n console.trace(\"Current call stack:\");\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\nvar onReportFail = async (url, data, clearCacheKey, retryCount) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n let reportErrorData = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\nvar reportDataRequest = async (url, data, clearCacheKey = \"\", retryCount = 1) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\nvar reportCacheData = async (url) => {\n try {\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== \"success\") {\n console.warn(\"[Fr-track warn]:\", cleanInfo.errReason);\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error(\"[Fr-track error]:\", error);\n }\n};\n\n// src/core/track/cache.ts\nvar setCacheData = async (data, url, maxLen, retryCount = 1) => {\n try {\n let cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage2.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n const errMsg = retryCount > 3 ? error : \"Retrying...\";\n if (retryCount <= 3) {\n console.warn(\"[Fr-track warning]:\" + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error(\"[Fr-track error]:\" + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\nvar getCacheData = async () => {\n try {\n const cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error(\"[Fr-track error]:\" + error);\n return [];\n }\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n};\n\n// src/utils/browser.ts\nimport Browser from \"bowser\";\nvar getBrowserAndDeviceInfo = () => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } catch (error) {\n return defRes;\n }\n};\nvar getDeviceResolution = () => {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\n// src/index.ts\nvar FrTrack = class {\n constructor(options) {\n this.option = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 3e5\n };\n this.userId = getUserId();\n this.routeMode = \"history\";\n this.timer = null;\n this.uvTimer = null;\n this.browserInfo = null;\n const {\n project_name,\n report_url,\n app_version = \"unknown\",\n auto_pv = false,\n maxCacheTime = 3e5,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n async reportPrevData() {\n try {\n const res = await localForage3.getItem(CACHE_DATA_NAME);\n const res1 = await localForage3.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn(\"[Fr-track warn]: \\u68C0\\u9A8C\\u5386\\u53F2\\u6570\\u636E\\u5931\\u8D25\");\n }\n }\n loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n init() {\n this.browserInfo = getBrowserAndDeviceInfo();\n this.reportPrevData();\n this.loopReport();\n this.onBrowserClose();\n this.frUserView();\n if (this.option.auto_pv) {\n if (this.routeMode === \"history\") {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n }\n this.frAutoPageView();\n }\n }\n track(params) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n setCacheData(trackParams, report_url, maxCacheSize);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n }\n /**\n * @method 自定义路由方式\n */\n setRouteMode(mode) {\n this.routeMode = mode;\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === \"hash\") {\n methodsList.push(\"hashchange\");\n } else {\n methodsList.push(...[\"popstate\", \"pushState\", \"replaceState\"]);\n }\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n const href = window.location.href || \"\";\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n });\n });\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n const currentDate = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n reportCacheData(this.option.report_url);\n }\n};\nvar index_default = FrTrack;\nexport {\n index_default as default\n};\n","import * as localForage from 'localforage';\nimport { trackEvent } from './core/track';\nimport { reportCacheData, reportDataRequest } from './core/report';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from './config/constant';\nimport { getUserId } from './utils/uuid';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from './utils/browser';\nimport { overrideHistoryMethods, getUserTimeZone } from './utils/utils';\nimport type {\n EventsType,\n BrowserInfoType,\n TrackEventItem,\n Options,\n CustomOptions,\n CustomData,\n TrackParams\n} from './types';\n\nclass FrTrack {\n public option: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 300000\n };\n\n private userId = getUserId();\n private routeMode: 'hash' | 'history' = 'history';\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private browserInfo: BrowserInfoType | null = null;\n public constructor(options: CustomOptions) {\n const {\n project_name,\n report_url,\n app_version = 'unknown',\n auto_pv = false,\n maxCacheTime = 300000,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n\n private async reportPrevData() {\n /**\n * 检测上次上报遗漏数据\n */\n try {\n const res: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n const res1: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn('[Fr-track warn]: 检验历史数据失败');\n }\n }\n\n private loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n // 重启定时器\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n\n public init() {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo();\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n /**\n * 4. 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n /**\n * 5. 统计uv\n */\n this.frUserView();\n /**\n * 6. 判断是否监听pv事件\n */\n if (this.option.auto_pv) {\n if (this.routeMode === 'history') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n }\n this.frAutoPageView();\n }\n }\n\n private track(params: TrackParams) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n trackEvent(trackParams, report_url, maxCacheSize);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n }\n\n /**\n * @method 自定义路由方式\n */\n public setRouteMode(mode: 'history' | 'hash') {\n this.routeMode = mode;\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === 'hash') {\n methodsList.push('hashchange');\n } else {\n methodsList.push(...['popstate', 'pushState', 'replaceState']);\n }\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n const href = window.location.href || '';\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n });\n });\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n const currentDate = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n // 超过24小时,再次上报uv\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n reportCacheData(this.option.report_url);\n }\n}\n\nexport default FrTrack;\n","import * as localForage from 'localforage';\nimport { reportCacheData, reportDataRequest } from '../report';\nimport { CACHE_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * set缓存数据\n * @param { object } data - 待缓存的数据\n * @param { string } url = 上报路径\n * @param { number } maxLen - 最大的缓存阈值\n * @param { number } retryCount - 重试次数\n */\nconst setCacheData = async (\n data: TrackEventItem,\n url: string,\n maxLen: number,\n retryCount = 1\n): Promise<void> => {\n // 优先采用indexedDB缓存,针对旧浏览器采用localstorage降级方案处理\n try {\n let cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n // 重试\n const errMsg = retryCount > 3 ? error : 'Retrying...';\n if (retryCount <= 3) {\n console.warn('[Fr-track warning]:' + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error('[Fr-track error]:' + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\n\n/**\n * get缓存的数据\n */\nconst getCacheData = async () => {\n try {\n const cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error('[Fr-track error]:' + error);\n return [];\n }\n};\n\nexport { setCacheData, getCacheData };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view', 'module_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn('无法获取时区名称,使用偏移量推算:', error);\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\nexport { getVariableType, generateUserId, overrideHistoryMethods, getUserTimeZone };\n","import { EVENT_TYPES, EVENT_KEYS } from '../config/constant';\nimport { getVariableType } from './utils';\nimport type { EventsType } from '../types/';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n console.warn('[Fr-track warning]: Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../../utils/validator';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn('[Fr-track warning]: error event type');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n console.warn('[Fr-track warning]: cleanData error', error);\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanData };\n","import { CAN_AGGREGATION_TYPES } from '../../config/constant';\nimport { TrackEventItem } from '../../types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn('[Fr-track warn]: 聚合失败', error);\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { getCacheData } from '../track/cache';\nimport { cleanData } from './clean';\nimport { aggregationData } from './aggregation';\nimport * as localForage from 'localforage';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 上报数据网络请求\n * @param { string } url 上报路径\n * @param { array } data 要上报的数据\n */\nconst request = async (url: string, data: TrackEventItem[]) => {\n return new Promise((resolve, reject) => {\n console.trace('Current call stack:');\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\n\n/**\n * 上报数据失败兜底处理\n * @param { string } url 上报路径\n * @param { number } retryCount 重试次数\n * @param { string } clearCacheKey 上报成功是否清除的缓存key值\n * @param { array | object } data 上报失败的数据\n */\nconst onReportFail = async (\n url: string,\n data: TrackEventItem[],\n clearCacheKey: string,\n retryCount: number\n) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n // 将上报失败的数据存入缓存\n let reportErrorData: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\n\n/**\n * 自定义上报数据\n * @param { string } url 上报路径\n * @param { array | object } data 待上报数据\n * @param { string } clearCacheKey 上报成功清除缓存的key\n * @param { number } retryCount 调用次数\n */\nconst reportDataRequest = async (\n url: string,\n data: TrackEventItem[] | TrackEventItem,\n clearCacheKey = '',\n retryCount = 1\n) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\n\n/**\n * 上报缓存中所有数据\n * @param { string } url 上报地址\n */\nconst reportCacheData = async (url: string) => {\n try {\n // 获取缓存数据\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== 'success') {\n console.warn('[Fr-track warn]:', cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n // 聚合\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n // 上报\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error('[Fr-track error]:', error);\n }\n};\n\nexport { reportCacheData, reportDataRequest };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport type { BrowserInfoType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } catch (error) {\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (): string => {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n"]}
package/dist/index.js CHANGED
@@ -432,6 +432,7 @@ var request = function(url, data) {
432
432
  return [
433
433
  2,
434
434
  new Promise(function(resolve, reject) {
435
+ console.trace("Current call stack:");
435
436
  if ("sendBeacon" in navigator) {
436
437
  var jsonData = JSON.stringify(data);
437
438
  var formData = new FormData();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/index.js","../src/index.ts","../src/core/track/cache.ts","../src/config/constant.ts","../src/utils/utils.ts","../src/utils/validator.ts","../src/core/report/clean.ts","../src/core/report/aggregation.ts","../src/core/report/index.ts","../src/utils/uuid.ts","../src/utils/browser.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","index_exports","default","index_default","module","exports","localForage","require","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","getVariableType","variable","typeString","toString","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","type","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","error","console","warn","offset","Date","getTimezoneOffset","validateEventType","eventType","includes","validateEventKey","params","keys","cleanData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","data","errReason","message","aggregationData","item","i","is_aggregation","currentDate","setHours","resultItem","find","push","customData","custom_data","count","length","request","url","Promise","resolve","reject","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","send","onReportFail","clearCacheKey","retryCount","reportErrorData","reportDataRequest","getItem","setItem","reportData","Array","isArray","removeItem","reportCacheData","cacheData","cleanInfo","result","getCacheData","setCacheData","maxLen","errMsg","localForage2","getUserId","track_uuid","localStorage","uuid","import_bowser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","Browser","parse","browser","os","platform","version","getDeviceResolution","screen","width","height","FrTrack","options","option","project_name","report_url","app_version","auto_pv","maxCacheSize","maxCacheTime","userId","routeMode","timer","uvTimer","browserInfo","assign","reportPrevData","res1","err","localForage3","loopReport","setInterval","onBrowserClose","addEventListener","clearInterval","document","visibilityState","init","frUserView","pushState","replaceState","frAutoPageView","track","trackParams","user_id","device_type","user_agent","screen_resolution","user_timezone","now","singleTrack","baseParams","setUser","setRouteMode","mode","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","methodsList","forEach","method","href","location","page_url","page_name","frPageView","interval","frPageDestroy","frReport"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/index.ts\nvar index_exports = {};\n__export(index_exports, {\n default: () => index_default\n});\nmodule.exports = __toCommonJS(index_exports);\nvar localForage3 = __toESM(require(\"localforage\"), 1);\n\n// src/core/track/cache.ts\nvar localForage2 = __toESM(require(\"localforage\"), 1);\n\n// src/config/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\", \"module_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn(\"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\", error);\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n console.warn(\"[Fr-track warning]: Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/report/clean.ts\nvar cleanData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn(\"[Fr-track warning]: error event type\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n console.warn(\"[Fr-track warning]: cleanData error\", error);\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/report/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn(\"[Fr-track warn]: \\u805A\\u5408\\u5931\\u8D25\", error);\n return rawData;\n }\n};\n\n// src/core/report/index.ts\nvar localForage = __toESM(require(\"localforage\"), 1);\nvar request = async (url, data) => {\n return new Promise((resolve, reject) => {\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\nvar onReportFail = async (url, data, clearCacheKey, retryCount) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n let reportErrorData = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\nvar reportDataRequest = async (url, data, clearCacheKey = \"\", retryCount = 1) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\nvar reportCacheData = async (url) => {\n try {\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== \"success\") {\n console.warn(\"[Fr-track warn]:\", cleanInfo.errReason);\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error(\"[Fr-track error]:\", error);\n }\n};\n\n// src/core/track/cache.ts\nvar setCacheData = async (data, url, maxLen, retryCount = 1) => {\n try {\n let cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage2.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n const errMsg = retryCount > 3 ? error : \"Retrying...\";\n if (retryCount <= 3) {\n console.warn(\"[Fr-track warning]:\" + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error(\"[Fr-track error]:\" + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\nvar getCacheData = async () => {\n try {\n const cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error(\"[Fr-track error]:\" + error);\n return [];\n }\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n};\n\n// src/utils/browser.ts\nvar import_bowser = __toESM(require(\"bowser\"), 1);\nvar getBrowserAndDeviceInfo = () => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = import_bowser.default.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } catch (error) {\n return defRes;\n }\n};\nvar getDeviceResolution = () => {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\n// src/index.ts\nvar FrTrack = class {\n constructor(options) {\n this.option = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 3e5\n };\n this.userId = getUserId();\n this.routeMode = \"history\";\n this.timer = null;\n this.uvTimer = null;\n this.browserInfo = null;\n const {\n project_name,\n report_url,\n app_version = \"unknown\",\n auto_pv = false,\n maxCacheTime = 3e5,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n async reportPrevData() {\n try {\n const res = await localForage3.getItem(CACHE_DATA_NAME);\n const res1 = await localForage3.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn(\"[Fr-track warn]: \\u68C0\\u9A8C\\u5386\\u53F2\\u6570\\u636E\\u5931\\u8D25\");\n }\n }\n loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n init() {\n this.browserInfo = getBrowserAndDeviceInfo();\n this.reportPrevData();\n this.loopReport();\n this.onBrowserClose();\n this.frUserView();\n if (this.option.auto_pv) {\n if (this.routeMode === \"history\") {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n }\n this.frAutoPageView();\n }\n }\n track(params) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n setCacheData(trackParams, report_url, maxCacheSize);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n }\n /**\n * @method 自定义路由方式\n */\n setRouteMode(mode) {\n this.routeMode = mode;\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === \"hash\") {\n methodsList.push(\"hashchange\");\n } else {\n methodsList.push(...[\"popstate\", \"pushState\", \"replaceState\"]);\n }\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n const href = window.location.href || \"\";\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n });\n });\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n const currentDate = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n reportCacheData(this.option.report_url);\n }\n};\nvar index_default = FrTrack;\n","import * as localForage from 'localforage';\nimport { trackEvent } from './core/track';\nimport { reportCacheData, reportDataRequest } from './core/report';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from './config/constant';\nimport { getUserId } from './utils/uuid';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from './utils/browser';\nimport { overrideHistoryMethods, getUserTimeZone } from './utils/utils';\nimport type {\n EventsType,\n BrowserInfoType,\n TrackEventItem,\n Options,\n CustomOptions,\n CustomData,\n TrackParams\n} from './types';\n\nclass FrTrack {\n public option: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 300000\n };\n\n private userId = getUserId();\n private routeMode: 'hash' | 'history' = 'history';\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private browserInfo: BrowserInfoType | null = null;\n public constructor(options: CustomOptions) {\n const {\n project_name,\n report_url,\n app_version = 'unknown',\n auto_pv = false,\n maxCacheTime = 300000,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n\n private async reportPrevData() {\n /**\n * 检测上次上报遗漏数据\n */\n try {\n const res: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n const res1: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn('[Fr-track warn]: 检验历史数据失败');\n }\n }\n\n private loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n // 重启定时器\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n\n public init() {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo();\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n /**\n * 4. 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n /**\n * 5. 统计uv\n */\n this.frUserView();\n /**\n * 6. 判断是否监听pv事件\n */\n if (this.option.auto_pv) {\n if (this.routeMode === 'history') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n }\n this.frAutoPageView();\n }\n }\n\n private track(params: TrackParams) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n trackEvent(trackParams, report_url, maxCacheSize);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n }\n\n /**\n * @method 自定义路由方式\n */\n public setRouteMode(mode: 'history' | 'hash') {\n this.routeMode = mode;\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === 'hash') {\n methodsList.push('hashchange');\n } else {\n methodsList.push(...['popstate', 'pushState', 'replaceState']);\n }\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n const href = window.location.href || '';\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n });\n });\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n const currentDate = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n // 超过24小时,再次上报uv\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n reportCacheData(this.option.report_url);\n }\n}\n\nexport default FrTrack;\n","import * as localForage from 'localforage';\nimport { reportCacheData, reportDataRequest } from '../report';\nimport { CACHE_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * set缓存数据\n * @param { object } data - 待缓存的数据\n * @param { string } url = 上报路径\n * @param { number } maxLen - 最大的缓存阈值\n * @param { number } retryCount - 重试次数\n */\nconst setCacheData = async (\n data: TrackEventItem,\n url: string,\n maxLen: number,\n retryCount = 1\n): Promise<void> => {\n // 优先采用indexedDB缓存,针对旧浏览器采用localstorage降级方案处理\n try {\n let cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n // 重试\n const errMsg = retryCount > 3 ? error : 'Retrying...';\n if (retryCount <= 3) {\n console.warn('[Fr-track warning]:' + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error('[Fr-track error]:' + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\n\n/**\n * get缓存的数据\n */\nconst getCacheData = async () => {\n try {\n const cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error('[Fr-track error]:' + error);\n return [];\n }\n};\n\nexport { setCacheData, getCacheData };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view', 'module_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn('无法获取时区名称,使用偏移量推算:', error);\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\nexport { getVariableType, generateUserId, overrideHistoryMethods, getUserTimeZone };\n","import { EVENT_TYPES, EVENT_KEYS } from '../config/constant';\nimport { getVariableType } from './utils';\nimport type { EventsType } from '../types/';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n console.warn('[Fr-track warning]: Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../../utils/validator';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn('[Fr-track warning]: error event type');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n console.warn('[Fr-track warning]: cleanData error', error);\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanData };\n","import { CAN_AGGREGATION_TYPES } from '../../config/constant';\nimport { TrackEventItem } from '../../types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn('[Fr-track warn]: 聚合失败', error);\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { getCacheData } from '../track/cache';\nimport { cleanData } from './clean';\nimport { aggregationData } from './aggregation';\nimport * as localForage from 'localforage';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 上报数据网络请求\n * @param { string } url 上报路径\n * @param { array } data 要上报的数据\n */\nconst request = async (url: string, data: TrackEventItem[]) => {\n return new Promise((resolve, reject) => {\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\n\n/**\n * 上报数据失败兜底处理\n * @param { string } url 上报路径\n * @param { number } retryCount 重试次数\n * @param { string } clearCacheKey 上报成功是否清除的缓存key值\n * @param { array | object } data 上报失败的数据\n */\nconst onReportFail = async (\n url: string,\n data: TrackEventItem[],\n clearCacheKey: string,\n retryCount: number\n) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n // 将上报失败的数据存入缓存\n let reportErrorData: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\n\n/**\n * 自定义上报数据\n * @param { string } url 上报路径\n * @param { array | object } data 待上报数据\n * @param { string } clearCacheKey 上报成功清除缓存的key\n * @param { number } retryCount 调用次数\n */\nconst reportDataRequest = async (\n url: string,\n data: TrackEventItem[] | TrackEventItem,\n clearCacheKey = '',\n retryCount = 1\n) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\n\n/**\n * 上报缓存中所有数据\n * @param { string } url 上报地址\n */\nconst reportCacheData = async (url: string) => {\n try {\n // 获取缓存数据\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== 'success') {\n console.warn('[Fr-track warn]:', cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n // 聚合\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n // 上报\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error('[Fr-track error]:', error);\n }\n};\n\nexport { reportCacheData, reportDataRequest };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport type { BrowserInfoType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } catch (error) {\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (): string => {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n"]}
1
+ {"version":3,"sources":["/Users/hl/Desktop/project/track-sdk/dist/index.js","../src/index.ts","../src/core/track/cache.ts","../src/config/constant.ts","../src/utils/utils.ts","../src/utils/validator.ts","../src/core/report/clean.ts","../src/core/report/aggregation.ts","../src/core/report/index.ts","../src/utils/uuid.ts","../src/utils/browser.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","index_exports","default","index_default","module","exports","localForage","require","EVENT_TYPES","CAN_AGGREGATION_TYPES","EVENT_KEYS","CACHE_DATA_NAME","CACHE_ERR_DATA_NAME","getVariableType","variable","typeString","toString","slice","toLowerCase","generateFallbackUUID","replace","c","r","Math","random","v","generateUserId","crypto","randomUUID","overrideHistoryMethods","type","originalMethod","history","args","res","apply","e","Event","window","dispatchEvent","getUserTimeZone","Intl","DateTimeFormat","resolvedOptions","timeZone","error","console","warn","offset","Date","getTimezoneOffset","validateEventType","eventType","includes","validateEventKey","params","keys","cleanData","rawData","tempIds","Set","resultData","filter","rawItem","eventKeyResult","eventTypeResult","event_type","eventTime","event_time","minDateTime","getTime","id","event_name","has","add","data","errReason","message","aggregationData","item","i","is_aggregation","currentDate","setHours","resultItem","find","push","customData","custom_data","count","length","request","url","Promise","resolve","reject","trace","navigator","jsonData","JSON","stringify","formData","FormData","append","status","sendBeacon","xhr","XMLHttpRequest","open","setRequestHeader","onload","response","onerror","send","onReportFail","clearCacheKey","retryCount","reportErrorData","reportDataRequest","getItem","setItem","reportData","Array","isArray","removeItem","reportCacheData","cacheData","cleanInfo","result","getCacheData","setCacheData","maxLen","errMsg","localForage2","getUserId","track_uuid","localStorage","uuid","import_bowser","getBrowserAndDeviceInfo","defRes","browserName","browserVersion","osName","osVersion","platformName","ua","userAgent","info","Browser","parse","browser","os","platform","version","getDeviceResolution","screen","width","height","FrTrack","options","option","project_name","report_url","app_version","auto_pv","maxCacheSize","maxCacheTime","userId","routeMode","timer","uvTimer","browserInfo","assign","reportPrevData","res1","err","localForage3","loopReport","setInterval","onBrowserClose","addEventListener","clearInterval","document","visibilityState","init","frUserView","pushState","replaceState","frAutoPageView","track","trackParams","user_id","device_type","user_agent","screen_resolution","user_timezone","now","singleTrack","baseParams","setUser","setRouteMode","mode","frModuleView","frModuleClick","frLoginEvent","frOrderEvent","frCustomEvent","frLogEvent","frClickEvent","methodsList","forEach","method","href","location","page_url","page_name","frPageView","interval","frPageDestroy","frReport"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/index.ts\nvar index_exports = {};\n__export(index_exports, {\n default: () => index_default\n});\nmodule.exports = __toCommonJS(index_exports);\nvar localForage3 = __toESM(require(\"localforage\"), 1);\n\n// src/core/track/cache.ts\nvar localForage2 = __toESM(require(\"localforage\"), 1);\n\n// src/config/constant.ts\nvar EVENT_TYPES = [\n \"page_view\",\n \"user_view\",\n \"page_destroy\",\n \"click_event\",\n \"module_click\",\n \"module_view\",\n \"login_event\",\n \"order_event\",\n \"custom_event\",\n \"log_event\"\n];\nvar CAN_AGGREGATION_TYPES = [\"page_view\", \"user_view\", \"module_view\"];\nvar EVENT_KEYS = [\n \"project_name\",\n \"event_type\",\n \"event_name\",\n \"event_time\",\n \"user_id\",\n \"app_version\",\n \"user_timezone\",\n \"device_type\",\n \"user_agent\",\n \"screen_resolution\",\n \"custom_data\",\n \"is_aggregation\"\n];\nvar CACHE_DATA_NAME = \"fr-track-cache-data\";\nvar CACHE_ERR_DATA_NAME = \"fr-track-cache-err-data\";\n\n// src/utils/utils.ts\nvar getVariableType = (variable) => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\nvar generateFallbackUUID = () => {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function(c) {\n const r = Math.random() * 16 | 0;\n const v = c === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n};\nvar generateUserId = () => {\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return generateFallbackUUID();\n};\nvar overrideHistoryMethods = (type) => {\n const originalMethod = history[type];\n return function(...args) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\nvar getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn(\"\\u65E0\\u6CD5\\u83B7\\u53D6\\u65F6\\u533A\\u540D\\u79F0\\uFF0C\\u4F7F\\u7528\\u504F\\u79FB\\u91CF\\u63A8\\u7B97:\", error);\n const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();\n if (offset >= 0) {\n return `\\u897F${offset / 60}\\u533A`;\n } else {\n return `\\u4E1C${-offset / 60}\\u533A`;\n }\n }\n};\n\n// src/utils/validator.ts\nfunction validateEventType(eventType) {\n return typeof eventType === \"string\" && EVENT_TYPES.includes(eventType);\n}\nfunction validateEventKey(params) {\n const type = getVariableType(params);\n if (!params || type !== \"object\") {\n console.warn(\"[Fr-track warning]: Event params must be an object\");\n return false;\n }\n const keys = Object.keys(params);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key)) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n\n// src/core/report/clean.ts\nvar cleanData = (rawData) => {\n try {\n const tempIds = /* @__PURE__ */ new Set();\n const resultData = rawData.filter((rawItem) => {\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn(\"[Fr-track warning]: error event type\");\n return false;\n }\n const eventTime = rawItem.event_time;\n const minDateTime = (/* @__PURE__ */ new Date(\"2025-12-01\")).getTime();\n if (!eventTime || typeof eventTime !== \"number\" || eventTime < minDateTime) {\n return false;\n }\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: \"success\",\n data: resultData\n };\n } catch (error) {\n console.warn(\"[Fr-track warning]: cleanData error\", error);\n const errReason = error.message || \"Unknown error\";\n return {\n type: \"fail\",\n errReason,\n data: rawData\n };\n }\n};\n\n// src/core/report/aggregation.ts\nvar aggregationData = (rawData) => {\n try {\n const resultData = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n if (CAN_AGGREGATION_TYPES.includes(item.event_type) || item.is_aggregation) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n (r) => r.event_time === currentDate && r.event_type === item.event_type && r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn(\"[Fr-track warn]: \\u805A\\u5408\\u5931\\u8D25\", error);\n return rawData;\n }\n};\n\n// src/core/report/index.ts\nvar localForage = __toESM(require(\"localforage\"), 1);\nvar request = async (url, data) => {\n return new Promise((resolve, reject) => {\n console.trace(\"Current call stack:\");\n if (\"sendBeacon\" in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append(\"data\", jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\nvar onReportFail = async (url, data, clearCacheKey, retryCount) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n let reportErrorData = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\nvar reportDataRequest = async (url, data, clearCacheKey = \"\", retryCount = 1) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\nvar reportCacheData = async (url) => {\n try {\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== \"success\") {\n console.warn(\"[Fr-track warn]:\", cleanInfo.errReason);\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error(\"[Fr-track error]:\", error);\n }\n};\n\n// src/core/track/cache.ts\nvar setCacheData = async (data, url, maxLen, retryCount = 1) => {\n try {\n let cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage2.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n const errMsg = retryCount > 3 ? error : \"Retrying...\";\n if (retryCount <= 3) {\n console.warn(\"[Fr-track warning]:\" + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error(\"[Fr-track error]:\" + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\nvar getCacheData = async () => {\n try {\n const cacheData = await localForage2.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error(\"[Fr-track error]:\" + error);\n return [];\n }\n};\n\n// src/utils/uuid.ts\nvar getUserId = () => {\n const track_uuid = localStorage.getItem(\"track_uuid\");\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem(\"track_uuid\", uuid);\n return uuid;\n};\n\n// src/utils/browser.ts\nvar import_bowser = __toESM(require(\"bowser\"), 1);\nvar getBrowserAndDeviceInfo = () => {\n const defRes = {\n browserName: \"unknown\",\n browserVersion: \"unknown\",\n osName: \"unknown\",\n osVersion: \"unknown\",\n platformName: \"unknown\"\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = import_bowser.default.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || \"unknown\",\n browserVersion: browser.version || \"unknown\",\n osName: os.name || \"unknown\",\n osVersion: os.version || \"unknown\",\n platformName: platform.type || \"unknown\"\n };\n } catch (error) {\n return defRes;\n }\n};\nvar getDeviceResolution = () => {\n if (!window) return \"unknown\";\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\n// src/index.ts\nvar FrTrack = class {\n constructor(options) {\n this.option = {\n project_name: \"\",\n report_url: \"\",\n app_version: \"\",\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 3e5\n };\n this.userId = getUserId();\n this.routeMode = \"history\";\n this.timer = null;\n this.uvTimer = null;\n this.browserInfo = null;\n const {\n project_name,\n report_url,\n app_version = \"unknown\",\n auto_pv = false,\n maxCacheTime = 3e5,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n async reportPrevData() {\n try {\n const res = await localForage3.getItem(CACHE_DATA_NAME);\n const res1 = await localForage3.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn(\"[Fr-track warn]: \\u68C0\\u9A8C\\u5386\\u53F2\\u6570\\u636E\\u5931\\u8D25\");\n }\n }\n loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n onBrowserClose() {\n window.addEventListener(\"beforeunload\", () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState !== \"visible\") {\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n init() {\n this.browserInfo = getBrowserAndDeviceInfo();\n this.reportPrevData();\n this.loopReport();\n this.onBrowserClose();\n this.frUserView();\n if (this.option.auto_pv) {\n if (this.routeMode === \"history\") {\n window.history.pushState = overrideHistoryMethods(\"pushState\");\n window.history.replaceState = overrideHistoryMethods(\"replaceState\");\n }\n this.frAutoPageView();\n }\n }\n track(params) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n setCacheData(trackParams, report_url, maxCacheSize);\n }\n singleTrack(eventType, params) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n /**\n * @method 自定义用户id\n */\n setUser(id) {\n this.userId = id;\n }\n /**\n * @method 自定义路由方式\n */\n setRouteMode(mode) {\n this.routeMode = mode;\n }\n /**\n * @method 模块view\n */\n frModuleView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"module_view\", params);\n }\n /**\n * @method 模块click\n */\n frModuleClick(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"module_click\", params);\n }\n /**\n * @method 登录事件\n */\n frLoginEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"login_event\", params);\n }\n /**\n * @method 生单事件\n */\n frOrderEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"order_event\", params);\n }\n /**\n * @method 自定义事件\n */\n frCustomEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"custom_event\", params);\n }\n /**\n * @method 日志事件\n */\n frLogEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"log_event\", params);\n }\n /**\n * @method 点击事件\n */\n frClickEvent(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"click_event\", params);\n }\n /**\n * @method 自动收集pv事件\n */\n frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === \"hash\") {\n methodsList.push(\"hashchange\");\n } else {\n methodsList.push(...[\"popstate\", \"pushState\", \"replaceState\"]);\n }\n methodsList.forEach((method) => {\n window.addEventListener(method, () => {\n const href = window.location.href || \"\";\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: \"unknown\",\n count: 1\n }\n };\n this.singleTrack(\"page_view\", params);\n });\n });\n }\n /**\n * @method pv事件\n */\n frPageView(event_name, custom_data) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack(\"page_view\", params);\n }\n /**\n * @method uv事件\n */\n frUserView() {\n const currentDate = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n const interval = 60 * 60 * 1e3;\n const params = {\n event_name: \"user_view\"\n };\n this.singleTrack(\"user_view\", params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n this.singleTrack(\"user_view\", params);\n }\n }, interval);\n }\n /**\n * @method 页面销毁事件\n */\n frPageDestroy(event_name, custom_data, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack(\"page_destroy\", params);\n }\n /**\n * @method 手动立即上报缓存的数据\n */\n frReport() {\n reportCacheData(this.option.report_url);\n }\n};\nvar index_default = FrTrack;\n","import * as localForage from 'localforage';\nimport { trackEvent } from './core/track';\nimport { reportCacheData, reportDataRequest } from './core/report';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from './config/constant';\nimport { getUserId } from './utils/uuid';\nimport { getBrowserAndDeviceInfo, getDeviceResolution } from './utils/browser';\nimport { overrideHistoryMethods, getUserTimeZone } from './utils/utils';\nimport type {\n EventsType,\n BrowserInfoType,\n TrackEventItem,\n Options,\n CustomOptions,\n CustomData,\n TrackParams\n} from './types';\n\nclass FrTrack {\n public option: Options = {\n project_name: '',\n report_url: '',\n app_version: '',\n auto_pv: false,\n maxCacheSize: 15,\n maxCacheTime: 300000\n };\n\n private userId = getUserId();\n private routeMode: 'hash' | 'history' = 'history';\n private timer: number | null = null;\n private uvTimer: number | null = null;\n private browserInfo: BrowserInfoType | null = null;\n public constructor(options: CustomOptions) {\n const {\n project_name,\n report_url,\n app_version = 'unknown',\n auto_pv = false,\n maxCacheTime = 300000,\n maxCacheSize = 15\n } = options;\n Object.assign(this.option, {\n project_name,\n report_url,\n auto_pv,\n maxCacheTime,\n maxCacheSize,\n app_version\n });\n }\n\n private async reportPrevData() {\n /**\n * 检测上次上报遗漏数据\n */\n try {\n const res: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n const res1: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (res && res.length) {\n reportCacheData(this.option.report_url);\n }\n if (res1 && res1.length) {\n reportDataRequest(this.option.report_url, res1, CACHE_ERR_DATA_NAME);\n }\n } catch (err) {\n console.warn('[Fr-track warn]: 检验历史数据失败');\n }\n }\n\n private loopReport() {\n this.timer = setInterval(() => {\n reportCacheData(this.option.report_url);\n }, this.option.maxCacheTime);\n }\n\n private onBrowserClose() {\n /**\n * 浏览器环境\n */\n window.addEventListener('beforeunload', () => {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n reportCacheData(this.option.report_url);\n });\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState !== 'visible') {\n // 重启定时器\n this.loopReport();\n } else {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n reportCacheData(this.option.report_url);\n }\n });\n }\n\n public init() {\n /**\n * 获取浏览器信息\n */\n this.browserInfo = getBrowserAndDeviceInfo();\n\n /**\n * 1. 判断缓存是否有没有传输的数据\n * 2. 判断上次是否有失败的数据存储在缓存中\n */\n this.reportPrevData();\n /**\n * 3. 开启定时器轮询,达到时间阈值进行上报\n */\n this.loopReport();\n /**\n * 4. 监听浏览器关闭事件,进行上报\n */\n this.onBrowserClose();\n /**\n * 5. 统计uv\n */\n this.frUserView();\n /**\n * 6. 判断是否监听pv事件\n */\n if (this.option.auto_pv) {\n if (this.routeMode === 'history') {\n window.history.pushState = overrideHistoryMethods('pushState');\n window.history.replaceState = overrideHistoryMethods('replaceState');\n }\n this.frAutoPageView();\n }\n }\n\n private track(params: TrackParams) {\n const { project_name, app_version, maxCacheSize, report_url } = this.option;\n const { osName, osVersion, browserName, browserVersion, platformName } = this.browserInfo!;\n const trackParams = Object.assign(\n {\n project_name,\n app_version,\n user_id: this.userId,\n device_type: platformName,\n user_agent: `os: ${osName}--v${osVersion}, browser: ${browserName}--v${browserVersion}`,\n screen_resolution: getDeviceResolution(),\n user_timezone: getUserTimeZone(),\n event_time: Date.now(),\n custom_data: null\n },\n params\n );\n trackEvent(trackParams, report_url, maxCacheSize);\n }\n\n private singleTrack<T extends Omit<TrackParams, 'event_type'>>(\n eventType: EventsType,\n params: T & (keyof T extends keyof Omit<TrackParams, 'event_type'> ? T : never)\n ) {\n const baseParams = {\n event_type: eventType\n };\n const trackParams = Object.assign(baseParams, params);\n this.track(trackParams);\n }\n\n /**\n * @method 自定义用户id\n */\n public setUser(id: string) {\n this.userId = id;\n }\n\n /**\n * @method 自定义路由方式\n */\n public setRouteMode(mode: 'history' | 'hash') {\n this.routeMode = mode;\n }\n\n /**\n * @method 模块view\n */\n public frModuleView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('module_view', params);\n }\n\n /**\n * @method 模块click\n */\n public frModuleClick(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('module_click', params);\n }\n\n /**\n * @method 登录事件\n */\n public frLoginEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('login_event', params);\n }\n\n /**\n * @method 生单事件\n */\n public frOrderEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('order_event', params);\n }\n\n /**\n * @method 自定义事件\n */\n public frCustomEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('custom_event', params);\n }\n\n /**\n * @method 日志事件\n */\n public frLogEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('log_event', params);\n }\n\n /**\n * @method 点击事件\n */\n public frClickEvent(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('click_event', params);\n }\n\n /**\n * @method 自动收集pv事件\n */\n private frAutoPageView() {\n const methodsList = [];\n if (this.routeMode === 'hash') {\n methodsList.push('hashchange');\n } else {\n methodsList.push(...['popstate', 'pushState', 'replaceState']);\n }\n methodsList.forEach(method => {\n window.addEventListener(method, () => {\n const href = window.location.href || '';\n const params = {\n event_name: href,\n custom_data: {\n page_url: href,\n page_name: 'unknown',\n count: 1\n }\n };\n this.singleTrack('page_view', params);\n });\n });\n }\n\n /**\n * @method pv事件\n */\n public frPageView(event_name: string, custom_data: CustomData) {\n const params = {\n event_name,\n custom_data\n };\n this.singleTrack('page_view', params);\n }\n\n /**\n * @method uv事件\n */\n public frUserView() {\n const currentDate = new Date().setHours(0, 0, 0, 0);\n // 一小时检查一次\n const interval = 60 * 60 * 1000;\n const params = {\n event_name: 'user_view'\n };\n this.singleTrack('user_view', params);\n if (this.uvTimer) {\n clearInterval(this.uvTimer);\n this.uvTimer = null;\n }\n this.uvTimer = setInterval(() => {\n const now = new Date().setHours(0, 0, 0, 0);\n if (now > currentDate + 24 * interval) {\n // 超过24小时,再次上报uv\n this.singleTrack('user_view', params);\n }\n }, interval);\n }\n\n /**\n * @method 页面销毁事件\n */\n public frPageDestroy(event_name: string, custom_data: CustomData, is_aggregation = false) {\n const params = {\n event_name,\n custom_data,\n is_aggregation\n };\n this.singleTrack('page_destroy', params);\n }\n\n /**\n * @method 手动立即上报缓存的数据\n */\n public frReport() {\n reportCacheData(this.option.report_url);\n }\n}\n\nexport default FrTrack;\n","import * as localForage from 'localforage';\nimport { reportCacheData, reportDataRequest } from '../report';\nimport { CACHE_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * set缓存数据\n * @param { object } data - 待缓存的数据\n * @param { string } url = 上报路径\n * @param { number } maxLen - 最大的缓存阈值\n * @param { number } retryCount - 重试次数\n */\nconst setCacheData = async (\n data: TrackEventItem,\n url: string,\n maxLen: number,\n retryCount = 1\n): Promise<void> => {\n // 优先采用indexedDB缓存,针对旧浏览器采用localstorage降级方案处理\n try {\n let cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n if (cacheData) {\n cacheData.push(data);\n cacheData.length >= maxLen && reportCacheData(url);\n } else {\n cacheData = [data];\n }\n await localForage.setItem(CACHE_DATA_NAME, cacheData);\n } catch (error) {\n // 重试\n const errMsg = retryCount > 3 ? error : 'Retrying...';\n if (retryCount <= 3) {\n console.warn('[Fr-track warning]:' + errMsg);\n setCacheData(data, url, retryCount + 1);\n } else {\n console.error('[Fr-track error]:' + errMsg);\n reportDataRequest(url, data);\n }\n }\n};\n\n/**\n * get缓存的数据\n */\nconst getCacheData = async () => {\n try {\n const cacheData: TrackEventItem[] | null = await localForage.getItem(CACHE_DATA_NAME);\n return cacheData || [];\n } catch (error) {\n console.error('[Fr-track error]:' + error);\n return [];\n }\n};\n\nexport { setCacheData, getCacheData };\n","const EVENT_TYPES = [\n 'page_view',\n 'user_view',\n 'page_destroy',\n 'click_event',\n 'module_click',\n 'module_view',\n 'login_event',\n 'order_event',\n 'custom_event',\n 'log_event'\n] as const;\n\nconst CAN_AGGREGATION_TYPES = ['page_view', 'user_view', 'module_view'] as const;\n\nconst EVENT_KEYS = [\n 'project_name',\n 'event_type',\n 'event_name',\n 'event_time',\n 'user_id',\n 'app_version',\n 'user_timezone',\n 'device_type',\n 'user_agent',\n 'screen_resolution',\n 'custom_data',\n 'is_aggregation'\n] as const;\n\nconst CACHE_DATA_NAME = 'fr-track-cache-data';\nconst CACHE_ERR_DATA_NAME = 'fr-track-cache-err-data';\n\nexport { EVENT_TYPES, EVENT_KEYS, CAN_AGGREGATION_TYPES, CACHE_DATA_NAME, CACHE_ERR_DATA_NAME };\n","/**\n * 获取变量类型\n * @param { unknown } variable 变量\n * @return { string } 类型字符串\n */\nconst getVariableType = (variable: unknown): string => {\n const typeString = Object.prototype.toString.call(variable);\n return typeString.slice(8, -1).toLowerCase();\n};\n\n/**\n * 手动实现 UUID v4\n * @returns { string } uuid\n */\nconst generateFallbackUUID = (): string => {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * 生成uuid\n * @returns { string } uuid\n */\nconst generateUserId = (): string => {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // 降级方案\n return generateFallbackUUID();\n};\n\n/**\n * 重写history的pushState和replaceState\n */\nconst overrideHistoryMethods = <T extends keyof History>(type: T): any => {\n const originalMethod = history[type];\n\n return function (this: any, ...args: any) {\n const res = originalMethod.apply(this, args);\n var e = new Event(type);\n window.dispatchEvent(e);\n return res;\n };\n};\n\n/**\n * 获取用户时区\n */\nconst getUserTimeZone = () => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch (error) {\n console.warn('无法获取时区名称,使用偏移量推算:', error);\n const offset = new Date().getTimezoneOffset();\n if (offset >= 0) {\n return `西${offset / 60}区`;\n } else {\n return `东${-offset / 60}区`;\n }\n }\n};\n\nexport { getVariableType, generateUserId, overrideHistoryMethods, getUserTimeZone };\n","import { EVENT_TYPES, EVENT_KEYS } from '../config/constant';\nimport { getVariableType } from './utils';\nimport type { EventsType } from '../types/';\n\n/**\n * @method 校验事件类型\n */\nexport function validateEventType(eventType?: unknown): boolean {\n return typeof eventType === 'string' && EVENT_TYPES.includes(eventType as EventsType);\n}\n\n/**\n * @method 校验字段\n */\nexport function validateEventKey(params?: unknown): boolean {\n const type = getVariableType(params);\n if (!params || type !== 'object') {\n console.warn('[Fr-track warning]: Event params must be an object');\n return false;\n }\n const keys = Object.keys(params as Record<string, unknown>);\n for (const key of keys) {\n if (!EVENT_KEYS.includes(key as (typeof EVENT_KEYS)[number])) {\n console.warn(`[Fr-track warning]: Invalid event key: ${key}`);\n return false;\n }\n }\n return true;\n}\n","import { validateEventType, validateEventKey } from '../../utils/validator';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 清洗上报数据\n * @param { array } rawData 待清洗的原数据\n * @returns { array } 清洗后的数据\n */\nconst cleanData = (\n rawData: TrackEventItem[]\n): {\n type: 'success' | 'fail';\n errReason?: string;\n data: TrackEventItem[];\n} => {\n try {\n // 过滤非法的事件类型、非法的时间日期\n const tempIds = new Set();\n const resultData = rawData.filter(rawItem => {\n // 缺失必要字段\n const eventKeyResult = validateEventKey(rawItem);\n if (!eventKeyResult) {\n return false;\n }\n\n // event_type校验不通过\n const eventTypeResult = validateEventType(rawItem.event_type);\n if (!eventTypeResult) {\n console.warn('[Fr-track warning]: error event type');\n return false;\n }\n\n // event_time校验不通过\n const eventTime = rawItem.event_time;\n const minDateTime = new Date('2025-12-01').getTime();\n if (!eventTime || typeof eventTime !== 'number' || eventTime < minDateTime) {\n return false;\n }\n\n // 相同时间戳相同事件已存在\n const id = `${rawItem.event_type}-${rawItem.event_name}-${rawItem.event_time}`;\n if (tempIds.has(id)) {\n return false;\n } else {\n tempIds.add(id);\n }\n return true;\n });\n return {\n type: 'success',\n data: resultData\n };\n } catch (error) {\n console.warn('[Fr-track warning]: cleanData error', error);\n const errReason = (error as Error).message || 'Unknown error';\n return {\n type: 'fail',\n errReason: errReason,\n data: rawData\n };\n }\n};\n\nexport { cleanData };\n","import { CAN_AGGREGATION_TYPES } from '../../config/constant';\nimport { TrackEventItem } from '../../types';\n\n/**\n * 聚合数据\n * @param { array } rawData 需要聚合的原数据\n * @returns { array } 聚合后的数据\n */\nconst aggregationData = (rawData: TrackEventItem[]): TrackEventItem[] => {\n try {\n const resultData: TrackEventItem[] = [];\n for (let i = 0; i < rawData.length; i++) {\n const item = rawData[i];\n /**\n * 以\"天\"为维度,将以下事件进行聚合\n * pv、uv、自定义指定需要聚合的数据\n */\n if (\n CAN_AGGREGATION_TYPES.includes(item.event_type as (typeof CAN_AGGREGATION_TYPES)[number]) ||\n item.is_aggregation\n ) {\n delete item.is_aggregation;\n const currentDate = new Date(item.event_time as number).setHours(0, 0, 0, 0);\n const resultItem = resultData.find(\n r =>\n r.event_time === currentDate &&\n r.event_type === item.event_type &&\n r.event_name === item.event_name\n );\n if (!resultItem) {\n item.event_time = currentDate;\n resultData.push(item);\n } else {\n const customData = resultItem.custom_data;\n if (customData && customData.count) {\n customData.count += 1;\n resultItem.custom_data = customData;\n }\n }\n } else {\n delete item.is_aggregation;\n resultData.push(item);\n }\n }\n return resultData;\n } catch (error) {\n console.warn('[Fr-track warn]: 聚合失败', error);\n // 聚合失败则直接上报原数据\n return rawData;\n }\n};\n\nexport { aggregationData };\n","import { getCacheData } from '../track/cache';\nimport { cleanData } from './clean';\nimport { aggregationData } from './aggregation';\nimport * as localForage from 'localforage';\nimport { CACHE_DATA_NAME, CACHE_ERR_DATA_NAME } from '../../config/constant';\nimport type { TrackEventItem } from '../../types';\n\n/**\n * 上报数据网络请求\n * @param { string } url 上报路径\n * @param { array } data 要上报的数据\n */\nconst request = async (url: string, data: TrackEventItem[]) => {\n return new Promise((resolve, reject) => {\n console.trace('Current call stack:');\n if ('sendBeacon' in navigator) {\n const jsonData = JSON.stringify(data);\n const formData = new FormData();\n formData.append('data', jsonData);\n const status = navigator.sendBeacon(url, formData);\n if (status) {\n resolve(true);\n } else {\n reject();\n }\n } else {\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = () => {\n if (xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject();\n }\n };\n xhr.onerror = () => {\n reject();\n };\n xhr.send(JSON.stringify(data));\n }\n });\n};\n\n/**\n * 上报数据失败兜底处理\n * @param { string } url 上报路径\n * @param { number } retryCount 重试次数\n * @param { string } clearCacheKey 上报成功是否清除的缓存key值\n * @param { array | object } data 上报失败的数据\n */\nconst onReportFail = async (\n url: string,\n data: TrackEventItem[],\n clearCacheKey: string,\n retryCount: number\n) => {\n if (retryCount < 3) {\n await reportDataRequest(url, data, clearCacheKey, retryCount);\n } else {\n // 将上报失败的数据存入缓存\n let reportErrorData: TrackEventItem[] | null = await localForage.getItem(CACHE_ERR_DATA_NAME);\n if (reportErrorData) {\n reportErrorData.push(...data);\n } else {\n reportErrorData = data;\n }\n await localForage.setItem(CACHE_ERR_DATA_NAME, reportErrorData);\n }\n};\n\n/**\n * 自定义上报数据\n * @param { string } url 上报路径\n * @param { array | object } data 待上报数据\n * @param { string } clearCacheKey 上报成功清除缓存的key\n * @param { number } retryCount 调用次数\n */\nconst reportDataRequest = async (\n url: string,\n data: TrackEventItem[] | TrackEventItem,\n clearCacheKey = '',\n retryCount = 1\n) => {\n const reportData = Array.isArray(data) ? data : [data];\n try {\n await request(url, reportData);\n if (clearCacheKey) {\n await localForage.removeItem(clearCacheKey);\n }\n } catch (error) {\n onReportFail(url, reportData, clearCacheKey, retryCount + 1);\n }\n};\n\n/**\n * 上报缓存中所有数据\n * @param { string } url 上报地址\n */\nconst reportCacheData = async (url: string) => {\n try {\n // 获取缓存数据\n const cacheData = await getCacheData();\n if (!cacheData?.length) return;\n // 清洗\n const cleanInfo = cleanData(cacheData);\n if (cleanInfo.type !== 'success') {\n console.warn('[Fr-track warn]:', cleanInfo.errReason);\n // TODO: 上报失败原因及数据 清空缓存\n await localForage.removeItem(CACHE_DATA_NAME);\n return;\n }\n // 聚合\n const result = aggregationData(cleanInfo.data);\n if (result && result.length) {\n // 上报\n await reportDataRequest(url, result, CACHE_DATA_NAME);\n }\n } catch (error) {\n console.error('[Fr-track error]:', error);\n }\n};\n\nexport { reportCacheData, reportDataRequest };\n","import { generateUserId } from '../utils/utils';\n\n/**\n * 获取user_id\n */\nconst getUserId = (): string => {\n // 查看缓存是否有已生成的uuid\n const track_uuid = localStorage.getItem('track_uuid');\n if (track_uuid) {\n return track_uuid;\n }\n const uuid = generateUserId();\n localStorage.setItem('track_uuid', uuid);\n return uuid;\n};\n\nexport { getUserId };\n","import Browser from 'bowser';\nimport type { BrowserInfoType } from '../types';\n\n/**\n * 获取浏览器及设备信息\n * @returns { object | null }\n */\nconst getBrowserAndDeviceInfo = (): BrowserInfoType => {\n const defRes = {\n browserName: 'unknown',\n browserVersion: 'unknown',\n osName: 'unknown',\n osVersion: 'unknown',\n platformName: 'unknown'\n };\n try {\n const ua = window.navigator.userAgent;\n if (!ua) return defRes;\n const info = Browser.parse(ua);\n const { browser, os, platform } = info;\n return {\n browserName: browser.name || 'unknown',\n browserVersion: browser.version || 'unknown',\n osName: os.name || 'unknown',\n osVersion: os.version || 'unknown',\n platformName: platform.type || 'unknown'\n };\n } catch (error) {\n return defRes;\n }\n};\n\n/**\n * 获取设备分辨率\n * @return { string } 分辨率信息\n */\nconst getDeviceResolution = (): string => {\n if (!window) return 'unknown';\n const { screen } = window;\n return `${screen.width}x${screen.height}`;\n};\n\nexport { getBrowserAndDeviceInfo, getDeviceResolution };\n"]}
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "files": [
11
11
  "dist"
12
12
  ],
13
- "version": "0.0.8",
13
+ "version": "0.0.9",
14
14
  "scripts": {
15
15
  "dev": "tsup --watch",
16
16
  "build": "tsup"