@pluve/logger-sdk 0.0.1 → 0.0.3

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 (44) hide show
  1. package/README.md +195 -76
  2. package/dist/index.js +9 -0
  3. package/dist/loggerSDK.d.ts +36 -0
  4. package/dist/{esm/dbQueue.js → loggerSDK.js} +195 -161
  5. package/dist/transportAdapter.d.ts +51 -0
  6. package/dist/{esm/transportAdapter.js → transportAdapter.js} +260 -111
  7. package/dist/types.d.ts +46 -0
  8. package/dist/utils.d.ts +30 -0
  9. package/dist/utils.js +229 -0
  10. package/lib/dbQueue.js +133 -0
  11. package/{dist/esm → lib}/index.js +1 -1
  12. package/lib/loggerSDK.js +571 -0
  13. package/lib/storeAdapter.js +99 -0
  14. package/lib/transportAdapter.d.ts +66 -0
  15. package/lib/transportAdapter.js +406 -0
  16. package/lib/types.js +1 -0
  17. package/lib/utils.js +50 -0
  18. package/package.json +8 -2
  19. package/dist/cjs/dbQueue.js +0 -88
  20. package/dist/cjs/index.js +0 -29
  21. package/dist/cjs/loggerSDK.js +0 -426
  22. package/dist/cjs/storeAdapter.js +0 -64
  23. package/dist/cjs/transportAdapter.d.ts +0 -5
  24. package/dist/cjs/transportAdapter.js +0 -109
  25. package/dist/cjs/types.js +0 -17
  26. package/dist/cjs/utils.js +0 -69
  27. package/dist/esm/dbQueue.d.ts +0 -10
  28. package/dist/esm/loggerSDK.d.ts +0 -29
  29. package/dist/esm/loggerSDK.js +0 -761
  30. package/dist/esm/storeAdapter.d.ts +0 -7
  31. package/dist/esm/storeAdapter.js +0 -139
  32. package/dist/esm/transportAdapter.d.ts +0 -5
  33. package/dist/esm/types.d.ts +0 -35
  34. package/dist/esm/utils.d.ts +0 -5
  35. package/dist/esm/utils.js +0 -53
  36. package/dist/umd/logger-sdk.min.js +0 -1
  37. /package/dist/{cjs/index.d.ts → index.d.ts} +0 -0
  38. /package/dist/{esm/types.js → types.js} +0 -0
  39. /package/{dist/cjs → lib}/dbQueue.d.ts +0 -0
  40. /package/{dist/esm → lib}/index.d.ts +0 -0
  41. /package/{dist/cjs → lib}/loggerSDK.d.ts +0 -0
  42. /package/{dist/cjs → lib}/storeAdapter.d.ts +0 -0
  43. /package/{dist/cjs → lib}/types.d.ts +0 -0
  44. /package/{dist/cjs → lib}/utils.d.ts +0 -0
@@ -0,0 +1,571 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
23
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
50
+ if (ar || !(i in from)) {
51
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
52
+ ar[i] = from[i];
53
+ }
54
+ }
55
+ return to.concat(ar || Array.prototype.slice.call(from));
56
+ };
57
+ import IDBQueue from './dbQueue';
58
+ import { defaultTransport } from './transportAdapter';
59
+ import { isBrowser, isIndexedDBAvailable, isWeChatMiniProgram, now, safeStringify } from './utils';
60
+ import { browserStorage, wechatStorage } from './storeAdapter';
61
+ var LoggerSDK = /** @class */ (function () {
62
+ function LoggerSDK(options) {
63
+ var _this = this;
64
+ this.inMemoryQueue = [];
65
+ this.seq = 0;
66
+ this.timerId = null;
67
+ this.storage = null;
68
+ this.closed = false;
69
+ this.idbQueue = null;
70
+ this.flushing = false;
71
+ var defaults = {
72
+ endpoints: options.endpoints || {},
73
+ appId: options.appId || '',
74
+ env: options.env ||
75
+ (function () {
76
+ if (isWeChatMiniProgram())
77
+ return 'wechat';
78
+ if (isBrowser())
79
+ return 'h5';
80
+ return 'unknown';
81
+ })(),
82
+ batchSize: options.batchSize || 10,
83
+ flushInterval: options.flushInterval || 5000,
84
+ retryCount: options.retryCount || 3,
85
+ retryBase: options.retryBase || 300,
86
+ storageKey: options.storageKey || 'logger_sdk_cache_v2',
87
+ maxCacheSize: options.maxCacheSize || 2000,
88
+ timeout: options.timeout || 10000,
89
+ debug: !!options.debug,
90
+ transport: options.transport || defaultTransport,
91
+ globalHeaders: options.globalHeaders || {},
92
+ enableAutoPV: options.enableAutoPV !== false,
93
+ enablePerf: options.enablePerf !== false,
94
+ usePixel: options.usePixel || false,
95
+ pixelParam: options.pixelParam || 'data',
96
+ maxPixelUrlLen: options.maxPixelUrlLen || 1900,
97
+ };
98
+ this.opts = Object.assign(defaults, options);
99
+ this.env = this.opts.env;
100
+ // choose storage
101
+ if (this.env === 'wechat')
102
+ this.storage = wechatStorage(this.opts.storageKey);
103
+ else if (this.env === 'h5')
104
+ this.storage = browserStorage(this.opts.storageKey);
105
+ else
106
+ this.storage = null;
107
+ // idb queue
108
+ if (isBrowser() && isIndexedDBAvailable()) {
109
+ this.idbQueue = new IDBQueue('logger_sdk_db', 'queue');
110
+ this.idbQueue.open().catch(function () {
111
+ _this.idbQueue = null;
112
+ });
113
+ }
114
+ // load existing persisted items (localStorage)
115
+ this.loadFromStorage().then(function () {
116
+ if (_this.opts.flushInterval > 0)
117
+ _this.startTimer();
118
+ });
119
+ // attach error handlers
120
+ this.attachGlobalHandlers();
121
+ // auto PV
122
+ if (this.opts.enableAutoPV && this.env === 'h5')
123
+ this.installAutoPV();
124
+ // collect perf once on load
125
+ if (this.opts.enablePerf && this.env === 'h5') {
126
+ if (document.readyState === 'complete')
127
+ this.collectPerf();
128
+ else
129
+ window.addEventListener('load', function () { return _this.collectPerf(); });
130
+ }
131
+ }
132
+ LoggerSDK.prototype.logDebug = function () {
133
+ var args = [];
134
+ for (var _i = 0; _i < arguments.length; _i++) {
135
+ args[_i] = arguments[_i];
136
+ }
137
+ if (this.opts.debug)
138
+ console.debug.apply(console, __spreadArray(['[LoggerSDK]'], args, false));
139
+ };
140
+ LoggerSDK.prototype.loadFromStorage = function () {
141
+ return __awaiter(this, void 0, void 0, function () {
142
+ var raw, arr, e_1;
143
+ return __generator(this, function (_a) {
144
+ switch (_a.label) {
145
+ case 0:
146
+ if (!this.storage)
147
+ return [2 /*return*/];
148
+ _a.label = 1;
149
+ case 1:
150
+ _a.trys.push([1, 3, , 4]);
151
+ return [4 /*yield*/, this.storage.get()];
152
+ case 2:
153
+ raw = _a.sent();
154
+ if (raw) {
155
+ arr = JSON.parse(raw);
156
+ this.inMemoryQueue = arr.concat(this.inMemoryQueue).slice(-this.opts.maxCacheSize);
157
+ this.logDebug('loaded persisted queue', this.inMemoryQueue.length);
158
+ }
159
+ return [3 /*break*/, 4];
160
+ case 3:
161
+ e_1 = _a.sent();
162
+ this.logDebug('load persisted fail', e_1);
163
+ return [3 /*break*/, 4];
164
+ case 4: return [2 /*return*/];
165
+ }
166
+ });
167
+ });
168
+ };
169
+ LoggerSDK.prototype.persistToStorage = function () {
170
+ return __awaiter(this, void 0, void 0, function () {
171
+ var e_2;
172
+ return __generator(this, function (_a) {
173
+ switch (_a.label) {
174
+ case 0:
175
+ if (!this.storage)
176
+ return [2 /*return*/];
177
+ _a.label = 1;
178
+ case 1:
179
+ _a.trys.push([1, 3, , 4]);
180
+ return [4 /*yield*/, this.storage.set(safeStringify(this.inMemoryQueue))];
181
+ case 2:
182
+ _a.sent();
183
+ this.logDebug('persisted queue', this.inMemoryQueue.length);
184
+ return [3 /*break*/, 4];
185
+ case 3:
186
+ e_2 = _a.sent();
187
+ this.logDebug('persist fail', e_2);
188
+ return [3 /*break*/, 4];
189
+ case 4: return [2 /*return*/];
190
+ }
191
+ });
192
+ });
193
+ };
194
+ LoggerSDK.prototype.startTimer = function () {
195
+ var _this = this;
196
+ if (this.timerId)
197
+ return;
198
+ this.timerId = setInterval(function () { return _this.flush().catch(function () { }); }, this.opts.flushInterval);
199
+ };
200
+ LoggerSDK.prototype.stopTimer = function () {
201
+ if (!this.timerId)
202
+ return;
203
+ clearInterval(this.timerId);
204
+ this.timerId = null;
205
+ };
206
+ // 将事件入队(先到内存,再持久化)
207
+ LoggerSDK.prototype.track = function (event, headers) {
208
+ return __awaiter(this, void 0, void 0, function () {
209
+ var e, err_1;
210
+ return __generator(this, function (_a) {
211
+ switch (_a.label) {
212
+ case 0:
213
+ if (this.closed)
214
+ return [2 /*return*/];
215
+ this.seq += 1;
216
+ e = {
217
+ type: event.type || 'custom',
218
+ time: event.time || now(),
219
+ user: event.user || undefined,
220
+ ctx: event.ctx || {},
221
+ level: event.level || 'info',
222
+ seq: this.seq,
223
+ };
224
+ this.inMemoryQueue.push(e);
225
+ this.logDebug('enqueue', e);
226
+ // persist to local storage
227
+ return [4 /*yield*/, this.persistToStorage()];
228
+ case 1:
229
+ // persist to local storage
230
+ _a.sent();
231
+ if (!this.idbQueue) return [3 /*break*/, 5];
232
+ _a.label = 2;
233
+ case 2:
234
+ _a.trys.push([2, 4, , 5]);
235
+ return [4 /*yield*/, this.idbQueue.add(e)];
236
+ case 3:
237
+ _a.sent();
238
+ return [3 /*break*/, 5];
239
+ case 4:
240
+ err_1 = _a.sent();
241
+ this.logDebug('idb add fail', err_1);
242
+ return [3 /*break*/, 5];
243
+ case 5:
244
+ if (!(this.inMemoryQueue.length >= this.opts.batchSize)) return [3 /*break*/, 7];
245
+ return [4 /*yield*/, this.flush(headers).catch(function () { })];
246
+ case 6:
247
+ _a.sent();
248
+ _a.label = 7;
249
+ case 7: return [2 /*return*/];
250
+ }
251
+ });
252
+ });
253
+ };
254
+ // flush:从队列中取一批发送(按 level 分 endpoint,支持部分成功剔除)
255
+ LoggerSDK.prototype.flush = function (extraHeaders) {
256
+ return __awaiter(this, void 0, void 0, function () {
257
+ var batch, groups_1, delay_1, sendGroup_1, results, successLevels_1, allOk, removeSeq_1, e_3;
258
+ var _this = this;
259
+ return __generator(this, function (_a) {
260
+ switch (_a.label) {
261
+ case 0:
262
+ if (this.closed)
263
+ return [2 /*return*/];
264
+ if (this.inMemoryQueue.length === 0)
265
+ return [2 /*return*/];
266
+ if (this.flushing)
267
+ return [2 /*return*/];
268
+ this.flushing = true;
269
+ _a.label = 1;
270
+ case 1:
271
+ _a.trys.push([1, , 8, 9]);
272
+ batch = this.inMemoryQueue.slice(0, this.opts.batchSize);
273
+ groups_1 = {};
274
+ batch.forEach(function (ev) {
275
+ var level = (ev.level || 'info');
276
+ (groups_1[level] = groups_1[level] || []).push(ev);
277
+ });
278
+ delay_1 = function (ms) { return new Promise(function (r) { return setTimeout(r, ms); }); };
279
+ sendGroup_1 = function (level, events) {
280
+ var endpoint = _this.opts.endpoints[level] || _this.opts.endpoints.default;
281
+ var payload = { appId: _this.opts.appId, env: _this.env, ts: now(), level: level, events: events };
282
+ var maxTry = _this.opts.retryCount;
283
+ var attemptOnce = function (attempt) {
284
+ var transportOpts = __assign(__assign({}, _this.opts), { endpoint: endpoint, headers: __assign(__assign({}, (_this.opts.globalHeaders || {})), (extraHeaders || {})) });
285
+ return _this.opts.transport(payload, transportOpts)
286
+ .then(function () { return true; })
287
+ .catch(function (err) { return __awaiter(_this, void 0, void 0, function () {
288
+ var next, wait;
289
+ return __generator(this, function (_a) {
290
+ switch (_a.label) {
291
+ case 0:
292
+ next = attempt + 1;
293
+ this.logDebug('send fail', level, next, err);
294
+ if (next > maxTry)
295
+ return [2 /*return*/, false];
296
+ wait = (this.opts.retryBase || 300) * Math.pow(2, (next - 1));
297
+ return [4 /*yield*/, delay_1(wait)];
298
+ case 1:
299
+ _a.sent();
300
+ return [2 /*return*/, attemptOnce(next)];
301
+ }
302
+ });
303
+ }); });
304
+ };
305
+ return attemptOnce(0).then(function (ok) { return ({ ok: ok, level: level, events: events }); });
306
+ };
307
+ return [4 /*yield*/, Promise.all(Object.keys(groups_1).map(function (level) { return sendGroup_1(level, groups_1[level]); }))];
308
+ case 2:
309
+ results = _a.sent();
310
+ successLevels_1 = new Set(results.filter(function (r) { return r.ok; }).map(function (r) { return r.level; }));
311
+ allOk = results.length > 0 && results.every(function (r) { return r.ok; });
312
+ if (!allOk && successLevels_1.size === 0) {
313
+ // 全部失败:保留队列,等待下次重试
314
+ this.logDebug('batch send failed, keep batch in queue');
315
+ return [2 /*return*/];
316
+ }
317
+ removeSeq_1 = new Set(batch.filter(function (e) { return successLevels_1.has((e.level || 'info')); }).map(function (e) { return e.seq; }));
318
+ this.inMemoryQueue = this.inMemoryQueue.filter(function (x) { return !removeSeq_1.has(x.seq); });
319
+ return [4 /*yield*/, this.persistToStorage()];
320
+ case 3:
321
+ _a.sent();
322
+ if (!(allOk && this.idbQueue)) return [3 /*break*/, 7];
323
+ _a.label = 4;
324
+ case 4:
325
+ _a.trys.push([4, 6, , 7]);
326
+ return [4 /*yield*/, this.idbQueue.clear()];
327
+ case 5:
328
+ _a.sent();
329
+ return [3 /*break*/, 7];
330
+ case 6:
331
+ e_3 = _a.sent();
332
+ this.logDebug('idb clear fail', e_3);
333
+ return [3 /*break*/, 7];
334
+ case 7: return [3 /*break*/, 9];
335
+ case 8:
336
+ this.flushing = false;
337
+ return [7 /*endfinally*/];
338
+ case 9: return [2 /*return*/];
339
+ }
340
+ });
341
+ });
342
+ };
343
+ // 将队列尽力全部发送(分批轮询 + 安全阈值)
344
+ LoggerSDK.prototype.flushAll = function () {
345
+ return __awaiter(this, void 0, void 0, function () {
346
+ var safety;
347
+ var _this = this;
348
+ return __generator(this, function (_a) {
349
+ safety = 0;
350
+ return [2 /*return*/, new Promise(function (resolve) {
351
+ var tick = function () { return __awaiter(_this, void 0, void 0, function () {
352
+ var _a;
353
+ return __generator(this, function (_b) {
354
+ switch (_b.label) {
355
+ case 0:
356
+ // 安全阈值,避免异常情况下无限循环
357
+ safety += 1;
358
+ if (this.inMemoryQueue.length === 0 || safety >= 200)
359
+ return [2 /*return*/, resolve()];
360
+ if (!!this.flushing) return [3 /*break*/, 4];
361
+ _b.label = 1;
362
+ case 1:
363
+ _b.trys.push([1, 3, , 4]);
364
+ return [4 /*yield*/, this.flush()];
365
+ case 2:
366
+ _b.sent();
367
+ return [3 /*break*/, 4];
368
+ case 3:
369
+ _a = _b.sent();
370
+ return [3 /*break*/, 4];
371
+ case 4:
372
+ setTimeout(tick, 50);
373
+ return [2 /*return*/];
374
+ }
375
+ });
376
+ }); };
377
+ tick();
378
+ })];
379
+ });
380
+ });
381
+ };
382
+ LoggerSDK.prototype.identify = function (user) {
383
+ return __awaiter(this, void 0, void 0, function () {
384
+ return __generator(this, function (_a) {
385
+ this.opts.appId = (user && user.appId) || this.opts.appId;
386
+ this.logDebug('identify', user);
387
+ return [2 /*return*/];
388
+ });
389
+ });
390
+ };
391
+ LoggerSDK.prototype.setCommon = function (params) {
392
+ return __awaiter(this, void 0, void 0, function () {
393
+ return __generator(this, function (_a) {
394
+ Object.assign(this.opts, params);
395
+ this.logDebug('setCommon', params);
396
+ return [2 /*return*/];
397
+ });
398
+ });
399
+ };
400
+ LoggerSDK.prototype.destroy = function () {
401
+ this.stopTimer();
402
+ this.closed = true;
403
+ };
404
+ // ========== 自动采集与错误处理 ===========
405
+ LoggerSDK.prototype.attachGlobalHandlers = function () {
406
+ var _this = this;
407
+ if (this.env === 'h5' && typeof window !== 'undefined') {
408
+ var win = window;
409
+ // JS 错误
410
+ win.addEventListener &&
411
+ win.addEventListener('error', function (ev) {
412
+ try {
413
+ _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 } });
414
+ }
415
+ catch (_a) {
416
+ //
417
+ }
418
+ });
419
+ // Promise 未捕获
420
+ win.addEventListener &&
421
+ win.addEventListener('unhandledrejection', function (ev) {
422
+ try {
423
+ _this.track({ type: 'error', level: 'error', ctx: { reason: ev.reason && (ev.reason.stack || ev.reason) } });
424
+ }
425
+ catch (_a) {
426
+ //
427
+ }
428
+ });
429
+ // Resource 加载错误(img/script/link)
430
+ win.addEventListener &&
431
+ win.addEventListener('error', function (ev) {
432
+ if (ev.target && (ev.target.src || ev.target.href)) {
433
+ try {
434
+ _this.track({ type: 'error', level: 'warn', ctx: { resource: ev.target.src || ev.target.href, tag: ev.target.tagName } });
435
+ }
436
+ catch (_a) {
437
+ //
438
+ }
439
+ }
440
+ }, true);
441
+ document.addEventListener &&
442
+ document.addEventListener('visibilitychange', function () {
443
+ try {
444
+ if (document.visibilityState === 'hidden')
445
+ _this.flushBeacon();
446
+ }
447
+ catch (_a) {
448
+ //
449
+ }
450
+ });
451
+ win.addEventListener &&
452
+ win.addEventListener('pagehide', function () {
453
+ try {
454
+ _this.flushBeacon();
455
+ }
456
+ catch (_a) {
457
+ //
458
+ }
459
+ });
460
+ win.addEventListener &&
461
+ win.addEventListener('beforeunload', function () {
462
+ try {
463
+ _this.flushBeacon();
464
+ }
465
+ catch (_a) {
466
+ //
467
+ }
468
+ });
469
+ }
470
+ };
471
+ // 自动 PV(single-page 支持简单的 history 池监听)
472
+ LoggerSDK.prototype.installAutoPV = function () {
473
+ var _this = this;
474
+ // 仅在浏览器环境安装 PV 监听,避免 SSR/Node 触发 window 访问错误
475
+ if (!isBrowser())
476
+ return;
477
+ var history = window.history, location = window.location;
478
+ var pushState = history.pushState;
479
+ var replaceState = history.replaceState;
480
+ var onUrlChange = function () {
481
+ try {
482
+ _this.track({ type: 'pageview', level: 'info', ctx: { path: location.pathname + location.search, title: document.title } });
483
+ }
484
+ catch (_a) {
485
+ //
486
+ }
487
+ };
488
+ // 包装原生 history 方法,正确转发所有参数并派发自定义事件
489
+ history.pushState = function () {
490
+ var args = [];
491
+ for (var _i = 0; _i < arguments.length; _i++) {
492
+ args[_i] = arguments[_i];
493
+ }
494
+ // @ts-ignore
495
+ pushState.apply(this, args);
496
+ window.dispatchEvent(new Event('locationchange'));
497
+ };
498
+ history.replaceState = function () {
499
+ var args = [];
500
+ for (var _i = 0; _i < arguments.length; _i++) {
501
+ args[_i] = arguments[_i];
502
+ }
503
+ // @ts-ignore
504
+ replaceState.apply(this, args);
505
+ window.dispatchEvent(new Event('locationchange'));
506
+ };
507
+ window.addEventListener('popstate', function () { return window.dispatchEvent(new Event('locationchange')); });
508
+ window.addEventListener('locationchange', onUrlChange);
509
+ // 首次 PV
510
+ onUrlChange();
511
+ };
512
+ // 性能采集(Navigation timing + Paint)
513
+ LoggerSDK.prototype.collectPerf = function () {
514
+ if (!isBrowser() || !('performance' in window))
515
+ return;
516
+ try {
517
+ var perf = window.performance;
518
+ var nav = perf.getEntriesByType && perf.getEntriesByType('navigation') && perf.getEntriesByType('navigation')[0];
519
+ var paints = perf.getEntriesByType ? perf.getEntriesByType('paint') : [];
520
+ var data_1 = {};
521
+ if (nav) {
522
+ data_1.ttfb = nav.responseStart - nav.requestStart;
523
+ data_1.domContentLoaded = nav.domContentLoadedEventEnd - nav.startTime;
524
+ data_1.load = nav.loadEventEnd - nav.startTime;
525
+ }
526
+ else if (perf.timing) {
527
+ var t = perf.timing;
528
+ data_1.ttfb = t.responseStart - t.requestStart;
529
+ data_1.domContentLoaded = t.domContentLoadedEventEnd - t.navigationStart;
530
+ data_1.load = t.loadEventEnd - t.navigationStart;
531
+ }
532
+ if (paints && paints.length) {
533
+ paints.forEach(function (p) {
534
+ data_1[p.name] = p.startTime;
535
+ });
536
+ }
537
+ this.track({ type: 'perf', level: 'info', ctx: data_1 });
538
+ }
539
+ catch (e) {
540
+ this.logDebug('collect perf fail', e);
541
+ }
542
+ };
543
+ LoggerSDK.prototype.flushBeacon = function () {
544
+ var _this = this;
545
+ if (!isBrowser())
546
+ return;
547
+ if (this.inMemoryQueue.length === 0)
548
+ return;
549
+ var groups = {};
550
+ this.inMemoryQueue.forEach(function (ev) {
551
+ var level = (ev.level || 'info');
552
+ (groups[level] = groups[level] || []).push(ev);
553
+ });
554
+ Object.keys(groups).forEach(function (level) {
555
+ var events = groups[level];
556
+ var endpoint = _this.opts.endpoints[level] || _this.opts.endpoints.default;
557
+ var payload = { appId: _this.opts.appId, env: _this.env, ts: now(), level: level, events: events };
558
+ var transportOpts = __assign(__assign({}, _this.opts), { endpoint: endpoint, headers: __assign({}, (_this.opts.globalHeaders || {})), useBeacon: true, usePixel: _this.opts.usePixel, pixelParam: _this.opts.pixelParam, maxPixelUrlLen: _this.opts.maxPixelUrlLen });
559
+ try {
560
+ _this.opts.transport(payload, transportOpts);
561
+ }
562
+ catch (_a) {
563
+ //
564
+ }
565
+ });
566
+ };
567
+ return LoggerSDK;
568
+ }());
569
+ export { LoggerSDK };
570
+ // 兼容导出(UMD/ESM)
571
+ export default LoggerSDK;
@@ -0,0 +1,99 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ // 浏览器环境:使用 localStorage 简单持久化
38
+ export function browserStorage(key) {
39
+ return {
40
+ get: function () {
41
+ return __awaiter(this, void 0, void 0, function () {
42
+ return __generator(this, function (_a) {
43
+ return [2 /*return*/, Promise.resolve(localStorage.getItem(key))];
44
+ });
45
+ });
46
+ },
47
+ set: function (val) {
48
+ return __awaiter(this, void 0, void 0, function () {
49
+ return __generator(this, function (_a) {
50
+ localStorage.setItem(key, val);
51
+ return [2 /*return*/, Promise.resolve()];
52
+ });
53
+ });
54
+ },
55
+ remove: function () {
56
+ return __awaiter(this, void 0, void 0, function () {
57
+ return __generator(this, function (_a) {
58
+ localStorage.removeItem(key);
59
+ return [2 /*return*/, Promise.resolve()];
60
+ });
61
+ });
62
+ },
63
+ };
64
+ }
65
+ // 微信小程序环境:封装 wx.*Storage API
66
+ export function wechatStorage(key) {
67
+ return {
68
+ get: function () {
69
+ return __awaiter(this, void 0, void 0, function () {
70
+ return __generator(this, function (_a) {
71
+ return [2 /*return*/, new Promise(function (res) {
72
+ // @ts-ignore
73
+ wx.getStorage({ key: key, success: function (r) { return res(r.data); }, fail: function () { return res(null); } });
74
+ })];
75
+ });
76
+ });
77
+ },
78
+ set: function (val) {
79
+ return __awaiter(this, void 0, void 0, function () {
80
+ return __generator(this, function (_a) {
81
+ return [2 /*return*/, new Promise(function (res) {
82
+ // @ts-ignore
83
+ wx.setStorage({ key: key, data: val, success: function () { return res(undefined); }, fail: function () { return res(undefined); } });
84
+ })];
85
+ });
86
+ });
87
+ },
88
+ remove: function () {
89
+ return __awaiter(this, void 0, void 0, function () {
90
+ return __generator(this, function (_a) {
91
+ return [2 /*return*/, new Promise(function (res) {
92
+ // @ts-ignore
93
+ wx.removeStorage({ key: key, success: function () { return res(undefined); }, fail: function () { return res(undefined); } });
94
+ })];
95
+ });
96
+ });
97
+ },
98
+ };
99
+ }