@pluve/logger-sdk 0.0.1 → 0.0.2

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.
Files changed (41) hide show
  1. package/README.md +195 -76
  2. package/dist/cjs/index.d.ts +5 -0
  3. package/dist/cjs/index.js +14 -2
  4. package/dist/cjs/loggerSDK.d.ts +27 -20
  5. package/dist/cjs/loggerSDK.js +86 -354
  6. package/dist/cjs/transportAdapter.d.ts +51 -5
  7. package/dist/cjs/transportAdapter.js +133 -60
  8. package/dist/cjs/types.d.ts +37 -26
  9. package/dist/cjs/utils.d.ts +27 -2
  10. package/dist/cjs/utils.js +151 -12
  11. package/dist/esm/index.d.ts +5 -0
  12. package/dist/esm/index.js +4 -2
  13. package/dist/esm/loggerSDK.d.ts +27 -20
  14. package/dist/esm/loggerSDK.js +141 -674
  15. package/dist/esm/transportAdapter.d.ts +51 -5
  16. package/dist/esm/transportAdapter.js +260 -111
  17. package/dist/esm/types.d.ts +37 -26
  18. package/dist/esm/utils.d.ts +27 -2
  19. package/dist/esm/utils.js +190 -14
  20. package/dist/umd/logger-sdk.min.js +1 -1
  21. package/lib/dbQueue.js +133 -0
  22. package/lib/index.d.ts +1 -0
  23. package/lib/index.js +9 -0
  24. package/lib/loggerSDK.d.ts +29 -0
  25. package/lib/loggerSDK.js +571 -0
  26. package/lib/storeAdapter.js +99 -0
  27. package/lib/transportAdapter.d.ts +66 -0
  28. package/lib/transportAdapter.js +406 -0
  29. package/lib/types.d.ts +35 -0
  30. package/lib/types.js +1 -0
  31. package/lib/utils.d.ts +5 -0
  32. package/lib/utils.js +50 -0
  33. package/package.json +8 -2
  34. package/dist/cjs/dbQueue.js +0 -88
  35. package/dist/cjs/storeAdapter.js +0 -64
  36. package/dist/esm/dbQueue.d.ts +0 -10
  37. package/dist/esm/dbQueue.js +0 -194
  38. package/dist/esm/storeAdapter.d.ts +0 -7
  39. package/dist/esm/storeAdapter.js +0 -139
  40. /package/{dist/cjs → lib}/dbQueue.d.ts +0 -0
  41. /package/{dist/cjs → lib}/storeAdapter.d.ts +0 -0
@@ -1,8 +1,6 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __export = (target, all) => {
8
6
  for (var name in all)
@@ -16,14 +14,6 @@ var __copyProps = (to, from, except, desc) => {
16
14
  }
17
15
  return to;
18
16
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
18
 
29
19
  // src/loggerSDK.ts
@@ -33,391 +23,133 @@ __export(loggerSDK_exports, {
33
23
  default: () => loggerSDK_default
34
24
  });
35
25
  module.exports = __toCommonJS(loggerSDK_exports);
36
- var import_dbQueue = __toESM(require("./dbQueue"));
37
26
  var import_transportAdapter = require("./transportAdapter");
38
27
  var import_utils = require("./utils");
39
- var import_storeAdapter = require("./storeAdapter");
40
28
  var LoggerSDK = class {
41
29
  constructor(options) {
42
- this.inMemoryQueue = [];
43
30
  this.seq = 0;
44
- this.timerId = null;
45
- this.storage = null;
46
31
  this.closed = false;
47
- this.idbQueue = null;
48
- this.flushing = false;
49
- const defaults = {
50
- endpoints: options.endpoints || {},
51
- appId: options.appId || "",
52
- env: options.env || (() => {
53
- if ((0, import_utils.isWeChatMiniProgram)())
54
- return "wechat";
55
- if ((0, import_utils.isBrowser)())
56
- return "h5";
57
- return "unknown";
58
- })(),
59
- batchSize: options.batchSize || 10,
60
- flushInterval: options.flushInterval || 5e3,
61
- retryCount: options.retryCount || 3,
62
- retryBase: options.retryBase || 300,
63
- storageKey: options.storageKey || "logger_sdk_cache_v2",
64
- maxCacheSize: options.maxCacheSize || 2e3,
65
- timeout: options.timeout || 1e4,
32
+ this.opts = {
33
+ endpoint: options.endpoint,
34
+ appId: options.appId || "unknown",
35
+ env: options.env || "dev",
66
36
  debug: !!options.debug,
67
- transport: options.transport || import_transportAdapter.defaultTransport,
68
- globalHeaders: options.globalHeaders || {},
69
- enableAutoPV: options.enableAutoPV !== false,
70
- enablePerf: options.enablePerf !== false,
71
- usePixel: options.usePixel || false,
72
37
  pixelParam: options.pixelParam || "data",
73
38
  maxPixelUrlLen: options.maxPixelUrlLen || 1900
74
39
  };
75
- this.opts = Object.assign(defaults, options);
76
- this.env = this.opts.env;
77
- if (this.env === "wechat")
78
- this.storage = (0, import_storeAdapter.wechatStorage)(this.opts.storageKey);
79
- else if (this.env === "h5")
80
- this.storage = (0, import_storeAdapter.browserStorage)(this.opts.storageKey);
81
- else
82
- this.storage = null;
83
- if ((0, import_utils.isBrowser)() && (0, import_utils.isIndexedDBAvailable)()) {
84
- this.idbQueue = new import_dbQueue.default("logger_sdk_db", "queue");
85
- this.idbQueue.open().catch(() => {
86
- this.idbQueue = null;
87
- });
88
- }
89
- this.loadFromStorage().then(() => {
90
- if (this.opts.flushInterval > 0)
91
- this.startTimer();
92
- });
93
- this.attachGlobalHandlers();
94
- if (this.opts.enableAutoPV && this.env === "h5")
95
- this.installAutoPV();
96
- if (this.opts.enablePerf && this.env === "h5") {
97
- if (document.readyState === "complete")
98
- this.collectPerf();
99
- else
100
- window.addEventListener("load", () => this.collectPerf());
101
- }
40
+ this.envTags = this.collectEnvironmentTags();
41
+ this.attachUnloadHandlers();
102
42
  }
103
43
  logDebug(...args) {
104
44
  if (this.opts.debug)
105
45
  console.debug("[LoggerSDK]", ...args);
106
46
  }
107
- async loadFromStorage() {
108
- if (!this.storage)
109
- return;
110
- try {
111
- const raw = await this.storage.get();
112
- if (raw) {
113
- const arr = JSON.parse(raw);
114
- this.inMemoryQueue = arr.concat(this.inMemoryQueue).slice(-this.opts.maxCacheSize);
115
- this.logDebug("loaded persisted queue", this.inMemoryQueue.length);
116
- }
117
- } catch (e) {
118
- this.logDebug("load persisted fail", e);
119
- }
120
- }
121
- async persistToStorage() {
122
- if (!this.storage)
123
- return;
124
- try {
125
- await this.storage.set((0, import_utils.safeStringify)(this.inMemoryQueue));
126
- this.logDebug("persisted queue", this.inMemoryQueue.length);
127
- } catch (e) {
128
- this.logDebug("persist fail", e);
47
+ /**
48
+ * 收集环境信息并生成 tags(仅在初始化时执行一次)
49
+ */
50
+ collectEnvironmentTags() {
51
+ const envInfo = (0, import_utils.getEnvironmentInfo)();
52
+ const tags = {
53
+ platform: envInfo.platform
54
+ };
55
+ if (envInfo.platform === "browser" && envInfo.userAgent) {
56
+ const browserInfo = (0, import_utils.parseBrowserInfo)(envInfo.userAgent);
57
+ tags.browser = browserInfo.browser;
58
+ tags.browserVersion = browserInfo.browserVersion;
59
+ tags.os = browserInfo.os;
60
+ tags.osVersion = browserInfo.osVersion;
61
+ tags.screenWidth = envInfo.screenWidth;
62
+ tags.screenHeight = envInfo.screenHeight;
63
+ tags.language = envInfo.language;
64
+ } else if (envInfo.platform === "wechat" && envInfo.systemInfo) {
65
+ tags.brand = envInfo.systemInfo.brand;
66
+ tags.model = envInfo.systemInfo.model;
67
+ tags.system = envInfo.systemInfo.system;
68
+ tags.wechatVersion = envInfo.systemInfo.version;
69
+ tags.SDKVersion = envInfo.systemInfo.SDKVersion;
70
+ tags.screenWidth = envInfo.screenWidth;
71
+ tags.screenHeight = envInfo.screenHeight;
72
+ tags.language = envInfo.language;
129
73
  }
74
+ this.logDebug("Environment tags collected:", tags);
75
+ return tags;
130
76
  }
131
- startTimer() {
132
- if (this.timerId)
133
- return;
134
- this.timerId = setInterval(() => this.flush().catch(() => {
135
- }), this.opts.flushInterval);
136
- }
137
- stopTimer() {
138
- if (!this.timerId)
139
- return;
140
- clearInterval(this.timerId);
141
- this.timerId = null;
142
- }
143
- // 将事件入队(先到内存,再持久化)
144
- async track(event, headers) {
77
+ /**
78
+ * 记录事件
79
+ */
80
+ async track(eventType, message, options) {
145
81
  if (this.closed)
146
82
  return;
147
83
  this.seq += 1;
148
- const e = {
149
- type: event.type || "custom",
150
- time: event.time || (0, import_utils.now)(),
151
- user: event.user || void 0,
152
- ctx: event.ctx || {},
153
- level: event.level || "info",
154
- seq: this.seq
155
- };
156
- this.inMemoryQueue.push(e);
157
- this.logDebug("enqueue", e);
158
- await this.persistToStorage();
159
- if (this.idbQueue) {
160
- try {
161
- await this.idbQueue.add(e);
162
- } catch (err) {
163
- this.logDebug("idb add fail", err);
84
+ const logEvent = {
85
+ eventType,
86
+ ts: (0, import_utils.now)(),
87
+ appId: this.opts.appId || "unknown",
88
+ env: this.opts.env || "dev",
89
+ level: (options == null ? void 0 : options.level) || "info",
90
+ message,
91
+ stack: options == null ? void 0 : options.stack,
92
+ url: (0, import_utils.getCurrentUrl)(),
93
+ userId: options == null ? void 0 : options.userId,
94
+ sessionId: (0, import_utils.getSessionId)(),
95
+ // 合并预收集的环境 tags 和用户自定义 tags
96
+ tags: {
97
+ ...this.envTags,
98
+ ...(options == null ? void 0 : options.tags) || {}
164
99
  }
165
- }
166
- if (this.inMemoryQueue.length >= this.opts.batchSize) {
167
- await this.flush(headers).catch(() => {
168
- });
169
- }
170
- }
171
- // flush:从队列中取一批发送(按 level 分 endpoint,支持部分成功剔除)
172
- async flush(extraHeaders) {
173
- if (this.closed)
174
- return;
175
- if (this.inMemoryQueue.length === 0)
176
- return;
177
- if (this.flushing)
178
- return;
179
- this.flushing = true;
100
+ };
101
+ this.logDebug("track", logEvent);
180
102
  try {
181
- const batch = this.inMemoryQueue.slice(0, this.opts.batchSize);
182
- const groups = {};
183
- batch.forEach((ev) => {
184
- const level = ev.level || "info";
185
- (groups[level] = groups[level] || []).push(ev);
186
- });
187
- const delay = (ms) => new Promise((r) => setTimeout(r, ms));
188
- const sendGroup = (level, events) => {
189
- const endpoint = this.opts.endpoints[level] || this.opts.endpoints.default;
190
- const payload = { appId: this.opts.appId, env: this.env, ts: (0, import_utils.now)(), level, events };
191
- const maxTry = this.opts.retryCount;
192
- const attemptOnce = (attempt) => {
193
- const transportOpts = { ...this.opts, endpoint, headers: { ...this.opts.globalHeaders || {}, ...extraHeaders || {} } };
194
- return this.opts.transport(payload, transportOpts).then(() => true).catch(async (err) => {
195
- const next = attempt + 1;
196
- this.logDebug("send fail", level, next, err);
197
- if (next > maxTry)
198
- return false;
199
- const wait = (this.opts.retryBase || 300) * 2 ** (next - 1);
200
- await delay(wait);
201
- return attemptOnce(next);
202
- });
203
- };
204
- return attemptOnce(0).then((ok) => ({ ok, level, events }));
205
- };
206
- const results = await Promise.all(Object.keys(groups).map((level) => sendGroup(level, groups[level])));
207
- const successLevels = new Set(results.filter((r) => r.ok).map((r) => r.level));
208
- const allOk = results.length > 0 && results.every((r) => r.ok);
209
- if (!allOk && successLevels.size === 0) {
210
- this.logDebug("batch send failed, keep batch in queue");
211
- return;
212
- }
213
- const removeSeq = new Set(batch.filter((e) => successLevels.has(e.level || "info")).map((e) => e.seq));
214
- this.inMemoryQueue = this.inMemoryQueue.filter((x) => !removeSeq.has(x.seq));
215
- await this.persistToStorage();
216
- if (allOk && this.idbQueue) {
217
- try {
218
- await this.idbQueue.clear();
219
- } catch (e) {
220
- this.logDebug("idb clear fail", e);
221
- }
222
- }
223
- } finally {
224
- this.flushing = false;
103
+ await (0, import_transportAdapter.defaultTransport)(logEvent, this.opts);
104
+ } catch (error) {
105
+ this.logDebug("track failed", error);
225
106
  }
226
107
  }
227
- // 将队列尽力全部发送(分批轮询 + 安全阈值)
228
- async flushAll() {
229
- let safety = 0;
230
- return new Promise((resolve) => {
231
- const tick = async () => {
232
- safety += 1;
233
- if (this.inMemoryQueue.length === 0 || safety >= 200)
234
- return resolve();
235
- if (!this.flushing) {
236
- try {
237
- await this.flush();
238
- } catch {
239
- }
240
- }
241
- setTimeout(tick, 50);
242
- };
243
- tick();
244
- });
245
- }
246
- async identify(user) {
247
- this.opts.appId = user && user.appId || this.opts.appId;
248
- this.logDebug("identify", user);
249
- }
250
- async setCommon(params) {
251
- Object.assign(this.opts, params);
252
- this.logDebug("setCommon", params);
108
+ /**
109
+ * 设置用户信息
110
+ */
111
+ identify(userId) {
112
+ this.logDebug("identify", userId);
253
113
  }
114
+ /**
115
+ * 销毁实例
116
+ */
254
117
  destroy() {
255
- this.stopTimer();
256
118
  this.closed = true;
257
119
  }
258
- // ========== 自动采集与错误处理 ===========
259
- attachGlobalHandlers() {
260
- if (this.env === "h5" && typeof window !== "undefined") {
261
- const win = window;
262
- win.addEventListener && win.addEventListener("error", (ev) => {
263
- try {
264
- this.track({ type: "error", level: "error", ctx: { message: ev.message, filename: ev.filename, lineno: ev.lineno, colno: ev.colno, stack: ev.error && ev.error.stack } });
265
- } catch {
266
- }
267
- });
268
- win.addEventListener && win.addEventListener("unhandledrejection", (ev) => {
269
- try {
270
- this.track({ type: "error", level: "error", ctx: { reason: ev.reason && (ev.reason.stack || ev.reason) } });
271
- } catch {
272
- }
273
- });
274
- win.addEventListener && win.addEventListener(
275
- "error",
276
- (ev) => {
277
- if (ev.target && (ev.target.src || ev.target.href)) {
278
- try {
279
- this.track({ type: "error", level: "warn", ctx: { resource: ev.target.src || ev.target.href, tag: ev.target.tagName } });
280
- } catch {
281
- }
282
- }
283
- },
284
- true
285
- );
286
- document.addEventListener && document.addEventListener("visibilitychange", () => {
287
- try {
288
- if (document.visibilityState === "hidden")
289
- this.flushBeacon();
290
- } catch {
291
- }
292
- });
293
- win.addEventListener && win.addEventListener("pagehide", () => {
294
- try {
295
- this.flushBeacon();
296
- } catch {
297
- }
298
- });
299
- win.addEventListener && win.addEventListener("beforeunload", () => {
300
- try {
301
- this.flushBeacon();
302
- } catch {
303
- }
304
- });
120
+ // ========== 自动采集 ===========
121
+ /**
122
+ * 监听页面卸载事件
123
+ */
124
+ attachUnloadHandlers() {
125
+ if ((0, import_utils.isWeChatMiniProgram)()) {
126
+ this.logDebug("WeChat MiniProgram environment detected");
127
+ return;
305
128
  }
306
- }
307
- // 自动 PV(single-page 支持简单的 history 池监听)
308
- installAutoPV() {
309
129
  if (!(0, import_utils.isBrowser)())
310
130
  return;
311
- const { history, location } = window;
312
- const { pushState } = history;
313
- const { replaceState } = history;
314
- const onUrlChange = () => {
131
+ const win = window;
132
+ document.addEventListener && document.addEventListener("visibilitychange", () => {
315
133
  try {
316
- this.track({ type: "pageview", level: "info", ctx: { path: location.pathname + location.search, title: document.title } });
134
+ if (document.visibilityState === "hidden") {
135
+ console.log("Page hidden");
136
+ }
317
137
  } catch {
318
138
  }
319
- };
320
- history.pushState = function(...args) {
321
- pushState.apply(this, args);
322
- window.dispatchEvent(new Event("locationchange"));
323
- };
324
- history.replaceState = function(...args) {
325
- replaceState.apply(this, args);
326
- window.dispatchEvent(new Event("locationchange"));
327
- };
328
- window.addEventListener("popstate", () => window.dispatchEvent(new Event("locationchange")));
329
- window.addEventListener("locationchange", onUrlChange);
330
- onUrlChange();
331
- }
332
- // 性能采集(Navigation timing + Paint)
333
- collectPerf() {
334
- if (!(0, import_utils.isBrowser)() || !("performance" in window))
335
- return;
336
- try {
337
- const perf = window.performance;
338
- const nav = perf.getEntriesByType && perf.getEntriesByType("navigation") && perf.getEntriesByType("navigation")[0];
339
- const paints = perf.getEntriesByType ? perf.getEntriesByType("paint") : [];
340
- const data = {};
341
- if (nav) {
342
- data.ttfb = nav.responseStart - nav.requestStart;
343
- data.domContentLoaded = nav.domContentLoadedEventEnd - nav.startTime;
344
- data.load = nav.loadEventEnd - nav.startTime;
345
- } else if (perf.timing) {
346
- const t = perf.timing;
347
- data.ttfb = t.responseStart - t.requestStart;
348
- data.domContentLoaded = t.domContentLoadedEventEnd - t.navigationStart;
349
- data.load = t.loadEventEnd - t.navigationStart;
350
- }
351
- if (paints && paints.length) {
352
- paints.forEach((p) => {
353
- data[p.name] = p.startTime;
354
- });
139
+ });
140
+ win.addEventListener && win.addEventListener("pagehide", () => {
141
+ try {
142
+ console.log("Page hide");
143
+ } catch {
355
144
  }
356
- this.track({ type: "perf", level: "info", ctx: data });
357
- } catch (e) {
358
- this.logDebug("collect perf fail", e);
359
- }
360
- }
361
- flushBeacon() {
362
- if (!(0, import_utils.isBrowser)())
363
- return;
364
- if (this.inMemoryQueue.length === 0)
365
- return;
366
- const groups = {};
367
- this.inMemoryQueue.forEach((ev) => {
368
- const level = ev.level || "info";
369
- (groups[level] = groups[level] || []).push(ev);
370
145
  });
371
- Object.keys(groups).forEach((level) => {
372
- const events = groups[level];
373
- const endpoint = this.opts.endpoints[level] || this.opts.endpoints.default;
374
- const payload = { appId: this.opts.appId, env: this.env, ts: (0, import_utils.now)(), level, events };
375
- const transportOpts = {
376
- ...this.opts,
377
- endpoint,
378
- headers: { ...this.opts.globalHeaders || {} },
379
- useBeacon: true,
380
- usePixel: this.opts.usePixel,
381
- pixelParam: this.opts.pixelParam,
382
- maxPixelUrlLen: this.opts.maxPixelUrlLen
383
- };
146
+ win.addEventListener && win.addEventListener("beforeunload", () => {
384
147
  try {
385
- this.opts.transport(payload, transportOpts);
148
+ console.log("Page unload");
386
149
  } catch {
387
150
  }
388
151
  });
389
152
  }
390
- // 生成简单 Demo 页面(HTML 字符串),方便生成 demo 文档站点
391
- // public generateDemoHtml(opts?: { scriptUrl?: string }) {
392
- // const scriptUrl = (opts && opts.scriptUrl) || 'dist/index.umd.js';
393
- // const html = ```
394
- // <!doctype html>
395
- // <html>
396
- // <head>
397
- // <meta charset="utf-8" />
398
- // <title>LoggerSDK Demo</title>
399
- // </head>
400
- // <body>
401
- // <h1>LoggerSDK Demo</h1>
402
- // <script src="${scriptUrl}"></script>
403
- // <script>
404
- // // 通过 UMD 全局 MyLogger 使用
405
- // const sdk = new MyLogger.LoggerSDK({
406
- // endpoints: { default: '/api/collect', info: '/api/collect/info', error: '/api/collect/error' },
407
- // appId: 'demo-app',
408
- // debug: true,
409
- // enableAutoPV: true,
410
- // enablePerf: true
411
- // });
412
- // // 手动埋点
413
- // sdk.track({ type: 'custom', level: 'info', ctx: { action: 'click_demo' } });
414
- // // 模拟错误
415
- // setTimeout(() => { throw new Error('demo error'); }, 2000);
416
- // </script>
417
- // </body>
418
- // </html>```;
419
- // return html;
420
- // }
421
153
  };
422
154
  var loggerSDK_default = LoggerSDK;
423
155
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,5 +1,51 @@
1
- import { SDKOptions } from "./types";
2
- export declare function defaultTransport(payload: any, opts?: SDKOptions & {
3
- endpoint?: string;
4
- headers?: Record<string, string>;
5
- }): Promise<void>;
1
+ import { SDKOptions } from './types';
2
+ /** 传输选项接口 */
3
+ export interface TransportOptions extends Omit<SDKOptions, 'endpoint'> {
4
+ endpoint: string;
5
+ }
6
+ /** 传输适配器接口 */
7
+ export interface TransportAdapter {
8
+ /** 适配器名称 */
9
+ name: string;
10
+ /** 是否支持当前环境 */
11
+ isSupported(opts?: TransportOptions): boolean;
12
+ /** 发送数据 */
13
+ send(payload: any, opts?: TransportOptions): Promise<void>;
14
+ }
15
+ /**
16
+ * Beacon 传输适配器
17
+ * - 兼容性:现代浏览器(Chrome 39+, Firefox 31+, Edge 14+)
18
+ * - 健壮性:页面卸载时可靠传输、不阻塞页面卸载
19
+ * - 适用场景:页面关闭、visibilitychange、pagehide、beforeunload 事件
20
+ * - 限制:无法获取响应、队列有大小限制(通常 64KB)
21
+ */
22
+ export declare const beaconTransport: TransportAdapter;
23
+ /**
24
+ * 微信小程序传输适配器
25
+ * - 兼容性:微信小程序环境
26
+ * - 健壮性:支持超时控制、完善的错误处理
27
+ * - 适用场景:微信小程序环境下的日志上报
28
+ */
29
+ export declare const wechatTransport: TransportAdapter;
30
+ /**
31
+ * Image 像素上报适配器
32
+ * - 兼容性:所有浏览器
33
+ * - 健壮性:轻量级、无跨域限制、支持超时控制
34
+ * - 适用场景:数据量小的快速上报、跨域场景、降级方案
35
+ * - 限制:URL 长度限制(默认 1900 字符)
36
+ */
37
+ export declare const imageTransport: TransportAdapter;
38
+ /**
39
+ * 默认传输函数 - 按环境选择最佳传输方式
40
+ * 浏览器策略:Beacon(可靠) > Image(兼容)
41
+ * 微信小程序策略:WeChat Request
42
+ */
43
+ export declare function defaultTransport(payload: any, opts?: TransportOptions): Promise<void>;
44
+ /**
45
+ * 导出所有适配器,方便自定义使用
46
+ */
47
+ export declare const TransportAdapters: {
48
+ beacon: TransportAdapter;
49
+ wechat: TransportAdapter;
50
+ image: TransportAdapter;
51
+ };