import type { EnvContext, LinkedData, ScopeContext } from './types'; import type { Reporter } from './Reporter'; const STORAGE_AID_KEY = '__ml::aid'; /** 环境桥接器 * @desc 用于提取和传递环境相关的上下文信息给 Reporter,包括 envInfo 和部分 scopeInfo * * 关于 linkedData: * - linkedData 并不需要持久存储,它仅仅是用于在不同上下文间进行同步的临时数据 * - 在同 contextId 下从 A 上下文延伸到 B 上下文时(如页面跳转),用 `linkedData` 或者 `serializeLinkedData` 从 scopeInfo 中提取出需要传递到下一上下文的数据 * - 在从某来源到达一个上下文时,用 `readLinkedData` 将协议约定的上下文字段写入到本地 scopeInfo 中 */ export abstract class Adapter, R extends Reporter> { /** 环境上下文 */ envInfo: EnvContext = {}; protected reporter?: R; /** 当前环境的本地存储机制 */ abstract storage: { /** 是否支持同步读写 */ supportSync: boolean; setItem: (key: string, value: any) => void; getItem: (key: string, defaultValue?: any) => any; removeItem: (key: string) => void; }; init(reporter: R) { this.reporter = reporter; this.initEnvInfo(); this.readLinkedData(); this.updateScopeInfo(); } /** 获取 aid */ getAid() { return this.storage.getItem(STORAGE_AID_KEY, undefined); } /** 存储 aid */ saveAid(aid?: string) { if (!aid) return; this.storage.setItem(STORAGE_AID_KEY, aid); } /** 更新 scopeInfo 中某个 key 的值 */ protected updateScopeInfoField(key: K, value: ScopeContext[K]) { if (!this.reporter) return; if (this.reporter.scopeInfo[key] !== value) { this.reporter.scopeInfo[key] = value; } } private initEnvInfo() { if (!this.reporter) return; this.envInfo = this.getEnvInfo(); } abstract settle(): void; /** 更新环境相关的局部上下文信息字段 */ abstract updateScopeInfo(): void; /** 读取 linkedData 并写入 scopeInfo */ abstract readLinkedData(): void; abstract get linkedData(): LinkedData; /** 序列化 linkedData,用于传递给其他需要串联上下文的地方 */ abstract serializeLinkedData(extra?: LinkedData): string; /** 相对保险的 HTTP 请求方式,允许优先使用 beacon */ abstract httpPost( url: string, data: string, options: { contentType: string; }, ): void | Promise; /** 提取环境相关上下文信息 */ protected abstract getEnvInfo(): EnvContext; }