npm package: @swiftcrab/tracker
Description: 埋点上报
Latest version: 0.0.2

## 使用示例

```bash
安装: pnpm add @swiftcrab/tracker @swiftcrab/spm
```

#### 使用

```typescript
import { trackerManager, type ITracker } from '@swiftcrab/tracker'

interface ClickTrackerOption {
  /** 默认：spm-only */
  mode?: "spm-only" | "all-clickable"
  /** 自定义spm属性名，默认 data-spm-click */
  spmAttr?: string
  /** 捕获阶段监听，默认 true */
  capture?: boolean
  /** 去重窗口（ms），默认 300ms */
  dedupeWindowMs?: number
  /** 忽略规则：返回 true 则不记录 */
  ignore?: (host: HTMLElement, e: MouseEvent) => boolean
  /** 入队前最后加工；返回 null/undefined 则不入队, 方便做字段补充、过滤、脱敏等 */
  beforeSend?: (payload: Record<string, any>, host: HTMLElement, e: MouseEvent) => Record<string, any> | null | undefined
}

nterface PageTrackerOptions {
  /** 防重复安装 key */
  installFlagKey?: string
  /**
   * 去重口径：
   * - 'href'：path+query+hash（默认）
   * - 'path+query'：忽略 hash
   * - 'path'：仅 path
   * - 自定义函数：返回用于去重的 key
   */
  dedupeBy?: 'href' | 'path+query' | 'path' | ((loc: Location) => string)
  /**
   * 首次 PV 触发时机：
   * - 'immediate'：立刻触发（默认）
   * - 'domcontentloaded'：等 DOMContentLoaded
   */
  firstFire?: 'immediate' | 'domcontentloaded'
  /** 是否上报 hashchange（Hash Router 场景建议 true），默认 true */
  trackHashChange?: boolean
  /** 上报前加工/丢弃；返回 null 表示丢弃 */
  beforeSend?: (payload: ITracker) => ITracker | null | undefined | void
}

interface HttpTrackerOptions {
  /** 过滤不需要监控的请求 URL，防止上报心跳、健康检查、静态资源等无意义请求 */
  filterUrls?: UrlFilter[]
  /** 限制错误信息的最大长度 */
  maxErrorLength?: number
  /** 对请求URL进行脱敏或简化，常用于移除敏感参数 */
  sanitizeUrl?: (url: string) => string
  /** 对错误内容进行脱敏或结构化处理 */
  sanitizeError?: (errorText: string, ctx: Omit<ITracker, "httpError">) => string
  /** 防止重复安装（多次调用 httpTracker() 不会重复劫持 fetch/XMLHttpRequest） */
  installFlagKey?: string
  /** 同一错误去重窗口(ms) */
  dedupeWindowMs?: number
  /** 单页最多上报条数，防止风暴 */
  maxReportsPerPage?: number
  /** 采样率 0~1 */
  sampleRate?: number
  /** 是否读取并上报响应体（仅对 !ok / status>=400） */
  captureResponseBody?: boolean
  /** 响应体最大长度（字符） */
  maxResponseBodyLength?: number
  /** 强制忽略 tracker 自己的上报请求（默认 true） */
  ignoreSelfRequests?: boolean
  /** 自定义判断是否为“自家上报请求”，用于 enqueue 内部也是 fetch/xhr 时避免循环 */
  isSelfRequest?: (url: string) => boolean
  /** 上报前加工/丢弃 */
  beforeSend?: (payload: ITracker) => ITracker | null | undefined | void
}

interface JsErrorTrackerOptions {
  /** 过滤不需要上报的错误 */
  filterErrors?: (string | RegExp | ((message: string, stack?: string) => boolean))[]
  /** 最大堆栈长度（默认 2000） */
  maxStackLength?: number
  /** 防重复安装 key */
  installFlagKey?: string
  /** 同一错误去重窗口(ms) */
  dedupeWindowMs?: number
  /** 单页最多上报条数，防止风暴 */
  maxReportsPerPage?: number
  /** 资源加载失败是否按 js_error 事件上报（会映射到 jsMessage/jsSource） */
  reportResourceError?: boolean
  /** unhandledrejection 是否上报 */
  reportUnhandledRejection?: boolean
  /** 采样率 0~1 */
  sampleRate?: number
  /** 上报前可做脱敏/清洗；返回 null 表示丢弃 */
  beforeSend?: (payload: ITracker) => ITracker | null | undefined | void
  /** 对 URL query 做脱敏（默认原样） */
  sanitizeUrl?: (url: string) => string
}

interface TrackerManagerOptions {
  /** localStorage 缓存键名 */
  storageKey?: string
  /** 最大缓存事件数（防内存/存储爆炸） */
  maxCacheSize?: number
  /** 批量上报间隔（毫秒） */
  batchInterval?: number
  /** 最大失败重试次数，默认 5 */
  maxRetryAttempts?: number
  /** 在达到最大重试次数后是否放弃，默认 true */
  dropOnMaxRetry?: boolean
  /** 上报失败后的重试延迟（毫秒） */
  retryDelay?: number
  /** 是否启用 localStorage 持久化（默认 true） */
  enableStorage?: boolean
  /** 采样率：0.0 ~ 1.0，1.0 表示 100% 上报 */
  sampleRate?: number
}

interface ITracker {
  /** 事件类型 */
  event: TEvent
  /** 页面URL */
  url: string
  /** 页面路径 */
  path: string
  /** 点击事件文本 */
  text?: string
  /** 点击事件spm */
  spm?: string
  /** 页面浏览量来源 */
  from?: TPageFrom
  /** 页面查询参数 */
  query?: string
  /** 页面hash值 */
  hash?: string
  /** HTTP请求方法 */
  method?: string
  /** HTTP请求URL */
  httpUrl?: string
  /** HTTP请求状态码 */
  httpStatus?: number
  /** HTTP请求错误信息 */
  httpError?: string
  /** HTTP请求耗时 */
  httpDuration?: number
  /** 设备名称 */
  deviceName?: string
  /** 设备版本 */
  deviceVersion?: string
  /** 操作系统 */
  deviceOs?: string
  /** 设备类型 */
  deviceType?: string
  /** jsError错误的核心描述信息，通常是错误对象的 message 属性 */
  jsMessage?: string
  /** jsError完整的调用栈 */
  jsStack?: string
  /** jsError发生错误的脚本文件 URL */
  jsSource?: string
  /** jsError错误发生的行号 */
  jsLine?: number
  /** jsError错误发生的列号 */
  jsColumn?: number
  /** 用户信息 */
  user?: {
    userId?: string
    userName?: string
    [key: string]: any
  }
}

interface IOption {
  clickTrackerOption?: ClickTrackerOption
  httpTrackerOptions?: HttpTrackerOptions
  trackerManagerOptions?: TrackerManagerOptions
  jsErrorTrackerOptions?: JsErrorTrackerOptions
  pageTrackerOptions?: PageTrackerOptions
}

trackerManager(async (batch: ITracker[]) => {
  /** 上报接口逻辑 */
}, {
  clickTrackerOption: {},
  httpTrackerOptions: {},
  trackerManagerOptions: {},
  jsErrorTrackerOptions: {},
  pageTrackerOptions: {},
})
```