@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,66 @@
1
+ import { SDKOptions } from './types';
2
+ /** 传输选项接口 */
3
+ export interface TransportOptions extends SDKOptions {
4
+ endpoint?: string;
5
+ headers?: Record<string, string>;
6
+ }
7
+ /** 传输适配器接口 */
8
+ export interface TransportAdapter {
9
+ /** 适配器名称 */
10
+ name: string;
11
+ /** 是否支持当前环境 */
12
+ isSupported(opts?: TransportOptions): boolean;
13
+ /** 发送数据 */
14
+ send(payload: any, opts?: TransportOptions): Promise<void>;
15
+ }
16
+ /**
17
+ * Fetch 传输适配器
18
+ * - 兼容性:现代浏览器(Chrome 42+, Firefox 39+, Safari 10.1+, Edge 14+)
19
+ * - 健壮性:支持超时控制、AbortController、keepalive
20
+ * - 适用场景:所有需要可靠传输的场景,包括页面卸载(keepalive)
21
+ */
22
+ export declare const fetchTransport: TransportAdapter;
23
+ /**
24
+ * XMLHttpRequest 传输适配器
25
+ * - 兼容性:几乎所有浏览器(IE7+)
26
+ * - 健壮性:支持超时控制、完善的错误处理
27
+ * - 适用场景:需要兼容老旧浏览器的场景
28
+ */
29
+ export declare const xhrTransport: TransportAdapter;
30
+ /**
31
+ * 微信小程序传输适配器
32
+ * - 兼容性:微信小程序环境
33
+ * - 健壮性:支持超时控制、完善的错误处理、防止重复回调
34
+ * - 适用场景:微信小程序专用
35
+ */
36
+ export declare const wechatTransport: TransportAdapter;
37
+ /**
38
+ * Image 像素上报适配器
39
+ * - 兼容性:所有浏览器
40
+ * - 健壮性:轻量级、无跨域限制、支持超时控制
41
+ * - 适用场景:数据量小的快速上报、跨域场景
42
+ * - 限制:URL 长度限制(默认 1900 字符)
43
+ */
44
+ export declare const imageTransport: TransportAdapter;
45
+ /**
46
+ * Beacon 传输适配器
47
+ * - 兼容性:现代浏览器(Chrome 39+, Firefox 31+, Edge 14+)
48
+ * - 健壮性:页面卸载时可靠传输、不阻塞页面卸载
49
+ * - 适用场景:页面关闭、visibilitychange、pagehide、beforeunload 事件
50
+ * - 限制:无法获取响应、队列有大小限制(通常 64KB)
51
+ */
52
+ export declare const beaconTransport: TransportAdapter;
53
+ /**
54
+ * 默认传输函数 - 自动选择最佳传输方式
55
+ */
56
+ export declare function defaultTransport(payload: any, opts?: TransportOptions): Promise<void>;
57
+ /**
58
+ * 导出所有适配器,方便自定义使用
59
+ */
60
+ export declare const TransportAdapters: {
61
+ fetch: TransportAdapter;
62
+ xhr: TransportAdapter;
63
+ wechat: TransportAdapter;
64
+ image: TransportAdapter;
65
+ beacon: TransportAdapter;
66
+ };
@@ -0,0 +1,406 @@
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
+ import { isWeChatMiniProgram, safeStringify, isBrowser, now } from './utils';
49
+ // ==================== 辅助函数 ====================
50
+ /** 获取端点 URL */
51
+ function getEndpoint(opts) {
52
+ var _a;
53
+ return (opts === null || opts === void 0 ? void 0 : opts.endpoint) || ((_a = opts === null || opts === void 0 ? void 0 : opts.endpoints) === null || _a === void 0 ? void 0 : _a.default) || '';
54
+ }
55
+ /** 构建请求头 */
56
+ function buildHeaders(opts) {
57
+ return __assign(__assign({ 'Content-Type': 'application/json' }, ((opts === null || opts === void 0 ? void 0 : opts.globalHeaders) || {})), ((opts === null || opts === void 0 ? void 0 : opts.headers) || {}));
58
+ }
59
+ // ==================== 1. Fetch 传输适配器(兼容性最高、功能最完善)====================
60
+ /**
61
+ * Fetch 传输适配器
62
+ * - 兼容性:现代浏览器(Chrome 42+, Firefox 39+, Safari 10.1+, Edge 14+)
63
+ * - 健壮性:支持超时控制、AbortController、keepalive
64
+ * - 适用场景:所有需要可靠传输的场景,包括页面卸载(keepalive)
65
+ */
66
+ export var fetchTransport = {
67
+ name: 'fetch',
68
+ isSupported: function () {
69
+ return typeof fetch === 'function';
70
+ },
71
+ send: function (payload, opts) {
72
+ return __awaiter(this, void 0, void 0, function () {
73
+ var body, timeout, endpoint, headers, controller, timeoutId, response, error_1;
74
+ return __generator(this, function (_a) {
75
+ switch (_a.label) {
76
+ case 0:
77
+ body = typeof payload === 'string' ? payload : safeStringify(payload);
78
+ timeout = (opts === null || opts === void 0 ? void 0 : opts.timeout) || 10000;
79
+ endpoint = getEndpoint(opts);
80
+ headers = buildHeaders(opts);
81
+ controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
82
+ timeoutId = controller ? setTimeout(function () { return controller.abort(); }, timeout) : null;
83
+ _a.label = 1;
84
+ case 1:
85
+ _a.trys.push([1, 3, , 4]);
86
+ return [4 /*yield*/, fetch(endpoint, {
87
+ method: 'POST',
88
+ headers: headers,
89
+ body: body,
90
+ // keepalive 确保页面卸载时仍能发送(Chrome/Edge 支持)
91
+ // @ts-ignore
92
+ keepalive: (opts === null || opts === void 0 ? void 0 : opts.useBeacon) ? true : undefined,
93
+ signal: controller === null || controller === void 0 ? void 0 : controller.signal,
94
+ })];
95
+ case 2:
96
+ response = _a.sent();
97
+ if (timeoutId)
98
+ clearTimeout(timeoutId);
99
+ if (!response.ok) {
100
+ throw new Error("HTTP ".concat(response.status, ": ").concat(response.statusText));
101
+ }
102
+ return [3 /*break*/, 4];
103
+ case 3:
104
+ error_1 = _a.sent();
105
+ if (timeoutId)
106
+ clearTimeout(timeoutId);
107
+ // 区分不同错误类型,提供更好的错误信息
108
+ if (error_1.name === 'AbortError') {
109
+ throw new Error("Fetch timeout after ".concat(timeout, "ms"));
110
+ }
111
+ throw error_1;
112
+ case 4: return [2 /*return*/];
113
+ }
114
+ });
115
+ });
116
+ },
117
+ };
118
+ // ==================== 2. XMLHttpRequest 传输适配器(兼容性高、功能完善)====================
119
+ /**
120
+ * XMLHttpRequest 传输适配器
121
+ * - 兼容性:几乎所有浏览器(IE7+)
122
+ * - 健壮性:支持超时控制、完善的错误处理
123
+ * - 适用场景:需要兼容老旧浏览器的场景
124
+ */
125
+ export var xhrTransport = {
126
+ name: 'xhr',
127
+ isSupported: function () {
128
+ return isBrowser() && typeof XMLHttpRequest !== 'undefined';
129
+ },
130
+ send: function (payload, opts) {
131
+ return __awaiter(this, void 0, void 0, function () {
132
+ var body, timeout, endpoint, headers;
133
+ return __generator(this, function (_a) {
134
+ body = typeof payload === 'string' ? payload : safeStringify(payload);
135
+ timeout = (opts === null || opts === void 0 ? void 0 : opts.timeout) || 10000;
136
+ endpoint = getEndpoint(opts);
137
+ headers = buildHeaders(opts);
138
+ return [2 /*return*/, new Promise(function (resolve, reject) {
139
+ var xhr = new XMLHttpRequest();
140
+ var timeoutId = null;
141
+ // 超时处理
142
+ timeoutId = setTimeout(function () {
143
+ xhr.abort();
144
+ reject(new Error("XHR timeout after ".concat(timeout, "ms")));
145
+ }, timeout);
146
+ xhr.onreadystatechange = function () {
147
+ if (xhr.readyState === 4) {
148
+ if (timeoutId)
149
+ clearTimeout(timeoutId);
150
+ if (xhr.status >= 200 && xhr.status < 300) {
151
+ resolve();
152
+ }
153
+ else {
154
+ reject(new Error("HTTP ".concat(xhr.status, ": ").concat(xhr.statusText)));
155
+ }
156
+ }
157
+ };
158
+ xhr.onerror = function () {
159
+ if (timeoutId)
160
+ clearTimeout(timeoutId);
161
+ reject(new Error('XHR network error'));
162
+ };
163
+ xhr.onabort = function () {
164
+ if (timeoutId)
165
+ clearTimeout(timeoutId);
166
+ reject(new Error('XHR aborted'));
167
+ };
168
+ try {
169
+ xhr.open('POST', endpoint, true);
170
+ // 设置请求头
171
+ Object.keys(headers).forEach(function (key) {
172
+ xhr.setRequestHeader(key, headers[key]);
173
+ });
174
+ xhr.send(body);
175
+ }
176
+ catch (error) {
177
+ if (timeoutId)
178
+ clearTimeout(timeoutId);
179
+ reject(error);
180
+ }
181
+ })];
182
+ });
183
+ });
184
+ },
185
+ };
186
+ // ==================== 3. 微信小程序传输适配器(微信环境专用)====================
187
+ /**
188
+ * 微信小程序传输适配器
189
+ * - 兼容性:微信小程序环境
190
+ * - 健壮性:支持超时控制、完善的错误处理、防止重复回调
191
+ * - 适用场景:微信小程序专用
192
+ */
193
+ export var wechatTransport = {
194
+ name: 'wechat',
195
+ isSupported: function () {
196
+ return isWeChatMiniProgram();
197
+ },
198
+ send: function (payload, opts) {
199
+ return __awaiter(this, void 0, void 0, function () {
200
+ var body, timeout, endpoint, headers;
201
+ return __generator(this, function (_a) {
202
+ body = typeof payload === 'string' ? payload : safeStringify(payload);
203
+ timeout = (opts === null || opts === void 0 ? void 0 : opts.timeout) || 10000;
204
+ endpoint = getEndpoint(opts);
205
+ headers = buildHeaders(opts);
206
+ return [2 /*return*/, new Promise(function (resolve, reject) {
207
+ var timeoutId = null;
208
+ var settled = false;
209
+ // 超时处理
210
+ timeoutId = setTimeout(function () {
211
+ if (!settled) {
212
+ settled = true;
213
+ reject(new Error("WeChat request timeout after ".concat(timeout, "ms")));
214
+ }
215
+ }, timeout);
216
+ // @ts-ignore
217
+ wx.request({
218
+ url: endpoint,
219
+ method: 'POST',
220
+ data: body,
221
+ header: headers,
222
+ success: function (res) {
223
+ if (timeoutId)
224
+ clearTimeout(timeoutId);
225
+ if (!settled) {
226
+ settled = true;
227
+ // 微信小程序的 statusCode 判断
228
+ if (res.statusCode >= 200 && res.statusCode < 300) {
229
+ resolve();
230
+ }
231
+ else {
232
+ reject(new Error("HTTP ".concat(res.statusCode)));
233
+ }
234
+ }
235
+ },
236
+ fail: function (err) {
237
+ if (timeoutId)
238
+ clearTimeout(timeoutId);
239
+ if (!settled) {
240
+ settled = true;
241
+ reject(new Error("WeChat request failed: ".concat(err.errMsg || 'unknown error')));
242
+ }
243
+ },
244
+ });
245
+ })];
246
+ });
247
+ });
248
+ },
249
+ };
250
+ // ==================== 4. Image 像素上报适配器(轻量级、适合 GET 请求)====================
251
+ /**
252
+ * Image 像素上报适配器
253
+ * - 兼容性:所有浏览器
254
+ * - 健壮性:轻量级、无跨域限制、支持超时控制
255
+ * - 适用场景:数据量小的快速上报、跨域场景
256
+ * - 限制:URL 长度限制(默认 1900 字符)
257
+ */
258
+ export var imageTransport = {
259
+ name: 'image',
260
+ isSupported: function (opts) {
261
+ // 只在浏览器环境且明确启用时支持
262
+ return isBrowser() && typeof Image !== 'undefined' && !!(opts === null || opts === void 0 ? void 0 : opts.usePixel);
263
+ },
264
+ send: function (payload, opts) {
265
+ return __awaiter(this, void 0, void 0, function () {
266
+ var body, timeout, endpoint, param, maxLen, cacheBuster, qs, url;
267
+ return __generator(this, function (_a) {
268
+ body = typeof payload === 'string' ? payload : safeStringify(payload);
269
+ timeout = (opts === null || opts === void 0 ? void 0 : opts.timeout) || 10000;
270
+ endpoint = getEndpoint(opts);
271
+ param = (opts === null || opts === void 0 ? void 0 : opts.pixelParam) || 'data';
272
+ maxLen = (opts === null || opts === void 0 ? void 0 : opts.maxPixelUrlLen) || 1900;
273
+ cacheBuster = "_=".concat(now());
274
+ qs = "".concat(param, "=").concat(encodeURIComponent(body), "&").concat(cacheBuster);
275
+ url = endpoint.includes('?') ? "".concat(endpoint, "&").concat(qs) : "".concat(endpoint, "?").concat(qs);
276
+ // URL 长度检查
277
+ if (url.length > maxLen) {
278
+ throw new Error("URL too long (".concat(url.length, " > ").concat(maxLen, "), fallback to POST required"));
279
+ }
280
+ return [2 /*return*/, new Promise(function (resolve, reject) {
281
+ var img = new Image();
282
+ var timeoutId = null;
283
+ var settled = false;
284
+ // 超时处理
285
+ timeoutId = setTimeout(function () {
286
+ if (!settled) {
287
+ settled = true;
288
+ img.src = ''; // 取消请求
289
+ reject(new Error("Image request timeout after ".concat(timeout, "ms")));
290
+ }
291
+ }, timeout);
292
+ img.onload = function () {
293
+ if (timeoutId)
294
+ clearTimeout(timeoutId);
295
+ if (!settled) {
296
+ settled = true;
297
+ resolve();
298
+ }
299
+ };
300
+ img.onerror = function () {
301
+ if (timeoutId)
302
+ clearTimeout(timeoutId);
303
+ if (!settled) {
304
+ settled = true;
305
+ reject(new Error('Image request failed'));
306
+ }
307
+ };
308
+ // 发起请求
309
+ img.src = url;
310
+ })];
311
+ });
312
+ });
313
+ },
314
+ };
315
+ // ==================== 5. Beacon 传输适配器(页面卸载场景专用)====================
316
+ /**
317
+ * Beacon 传输适配器
318
+ * - 兼容性:现代浏览器(Chrome 39+, Firefox 31+, Edge 14+)
319
+ * - 健壮性:页面卸载时可靠传输、不阻塞页面卸载
320
+ * - 适用场景:页面关闭、visibilitychange、pagehide、beforeunload 事件
321
+ * - 限制:无法获取响应、队列有大小限制(通常 64KB)
322
+ */
323
+ export var beaconTransport = {
324
+ name: 'beacon',
325
+ isSupported: function (opts) {
326
+ // 只在浏览器环境且明确启用时支持
327
+ return isBrowser() && typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function' && !!(opts === null || opts === void 0 ? void 0 : opts.useBeacon);
328
+ },
329
+ send: function (payload, opts) {
330
+ return __awaiter(this, void 0, void 0, function () {
331
+ var body, endpoint, blob, success;
332
+ return __generator(this, function (_a) {
333
+ body = typeof payload === 'string' ? payload : safeStringify(payload);
334
+ endpoint = getEndpoint(opts);
335
+ blob = new Blob([body], { type: 'application/json' });
336
+ success = navigator.sendBeacon(endpoint, blob);
337
+ if (!success) {
338
+ throw new Error('sendBeacon failed (queue full or other error)');
339
+ }
340
+ return [2 /*return*/];
341
+ });
342
+ });
343
+ },
344
+ };
345
+ // ==================== 默认传输策略:按兼容性和健壮性排序 ====================
346
+ /**
347
+ * 获取可用的传输适配器列表(按优先级排序)
348
+ * 普通场景优先级:Fetch > XHR > WeChat > Image
349
+ */
350
+ function getNormalTransports() {
351
+ return [fetchTransport, xhrTransport, wechatTransport, imageTransport];
352
+ }
353
+ /**
354
+ * 获取页面卸载场景的传输适配器列表
355
+ * 卸载场景优先级:Beacon > Fetch(keepalive) > Image > XHR
356
+ */
357
+ function getUnloadTransports() {
358
+ return [beaconTransport, fetchTransport, imageTransport, xhrTransport];
359
+ }
360
+ /**
361
+ * 默认传输函数 - 自动选择最佳传输方式
362
+ */
363
+ export function defaultTransport(payload, opts) {
364
+ return __awaiter(this, void 0, void 0, function () {
365
+ var isUnloadScenario, transports, adapter, error_2, fallbackAdapter;
366
+ return __generator(this, function (_a) {
367
+ switch (_a.label) {
368
+ case 0:
369
+ isUnloadScenario = opts === null || opts === void 0 ? void 0 : opts.useBeacon;
370
+ transports = isUnloadScenario ? getUnloadTransports() : getNormalTransports();
371
+ adapter = transports.find(function (t) { return t.isSupported(opts); });
372
+ if (!adapter) {
373
+ throw new Error('No supported transport adapter available');
374
+ }
375
+ _a.label = 1;
376
+ case 1:
377
+ _a.trys.push([1, 3, , 6]);
378
+ return [4 /*yield*/, adapter.send(payload, opts)];
379
+ case 2:
380
+ _a.sent();
381
+ return [3 /*break*/, 6];
382
+ case 3:
383
+ error_2 = _a.sent();
384
+ if (!(adapter.name === 'image' && error_2.message.includes('URL too long'))) return [3 /*break*/, 5];
385
+ fallbackAdapter = transports.find(function (t) { return (t.name === 'fetch' || t.name === 'xhr') && t.isSupported(opts); });
386
+ if (!fallbackAdapter) return [3 /*break*/, 5];
387
+ return [4 /*yield*/, fallbackAdapter.send(payload, opts)];
388
+ case 4:
389
+ _a.sent();
390
+ return [2 /*return*/];
391
+ case 5: throw error_2;
392
+ case 6: return [2 /*return*/];
393
+ }
394
+ });
395
+ });
396
+ }
397
+ /**
398
+ * 导出所有适配器,方便自定义使用
399
+ */
400
+ export var TransportAdapters = {
401
+ fetch: fetchTransport,
402
+ xhr: xhrTransport,
403
+ wechat: wechatTransport,
404
+ image: imageTransport,
405
+ beacon: beaconTransport,
406
+ };
package/lib/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/lib/utils.js ADDED
@@ -0,0 +1,50 @@
1
+ /*
2
+ * @Author : 黄震 huangzhen@yfpharmacy.com
3
+ * @Date : 2025-11-21 14:31:33
4
+ * @LastEditors : 黄震 huangzhen@yfpharmacy.com
5
+ * @LastEditTime : 2025-12-02 15:31:27
6
+ * @Description : utils 工具函数
7
+ * Copyright (c) 2025 by 益丰大药房连锁股份有限公司, All Rights Reserved.
8
+ */
9
+ // 当前时间戳(毫秒)
10
+ export var now = function () { return Date.now(); };
11
+ // 判断是否在微信小程序环境
12
+ export function isWeChatMiniProgram() {
13
+ try {
14
+ // @ts-ignore
15
+ return typeof wx !== 'undefined' && typeof wx.request === 'function';
16
+ }
17
+ catch (e) {
18
+ return false;
19
+ }
20
+ }
21
+ // 判断是否在浏览器环境
22
+ export function isBrowser() {
23
+ try {
24
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
25
+ }
26
+ catch (e) {
27
+ return false;
28
+ }
29
+ }
30
+ // 安全 JSON 序列化:处理循环引用
31
+ export function safeStringify(obj) {
32
+ var seen = new WeakSet();
33
+ return JSON.stringify(obj, function (_k, v) {
34
+ if (v && typeof v === 'object') {
35
+ if (seen.has(v))
36
+ return '[Circular]';
37
+ seen.add(v);
38
+ }
39
+ return v;
40
+ });
41
+ }
42
+ // 判断 IndexedDB 能力是否可用
43
+ export function isIndexedDBAvailable() {
44
+ try {
45
+ return typeof indexedDB !== 'undefined';
46
+ }
47
+ catch (e) {
48
+ return false;
49
+ }
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluve/logger-sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "logger sdk",
5
5
  "keywords": [
6
6
  "logger"
@@ -30,8 +30,14 @@
30
30
  "init-install": "npm i",
31
31
  "build-types": "tsc",
32
32
  "build": "father build",
33
+ "test": "vitest run",
34
+ "test:watch": "vitest",
35
+ "test:coverage": "vitest run --coverage",
33
36
  "clear-types": "rm -rf lib",
34
37
  "clear-build": "rm -rf dist",
35
38
  "clear-node_modules": "rm -rf node_modules"
39
+ },
40
+ "devDependencies": {
41
+ "vitest": "^4.0.15"
36
42
  }
37
- }
43
+ }
@@ -1,88 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
-
19
- // src/dbQueue.ts
20
- var dbQueue_exports = {};
21
- __export(dbQueue_exports, {
22
- default: () => IDBQueue
23
- });
24
- module.exports = __toCommonJS(dbQueue_exports);
25
- var import_utils = require("./utils");
26
- var IDBQueue = class {
27
- constructor(dbName = "logger_sdk_db", storeName = "queue") {
28
- this.db = null;
29
- this.dbName = dbName;
30
- this.storeName = storeName;
31
- }
32
- // 打开数据库并初始化对象仓库
33
- async open() {
34
- if (!(0, import_utils.isBrowser)() || !(0, import_utils.isIndexedDBAvailable)())
35
- return;
36
- if (this.db)
37
- return;
38
- return new Promise((resolve, reject) => {
39
- const req = indexedDB.open(this.dbName, 1);
40
- req.onupgradeneeded = () => {
41
- const db = req.result;
42
- if (!db.objectStoreNames.contains(this.storeName))
43
- db.createObjectStore(this.storeName, { autoIncrement: true });
44
- };
45
- req.onsuccess = () => {
46
- this.db = req.result;
47
- resolve();
48
- };
49
- req.onerror = () => reject(req.error);
50
- });
51
- }
52
- // 入队:追加一条记录
53
- async add(item) {
54
- if (!this.db)
55
- return;
56
- return new Promise((res, rej) => {
57
- const tx = this.db.transaction(this.storeName, "readwrite");
58
- const st = tx.objectStore(this.storeName);
59
- const r = st.add(item);
60
- r.onsuccess = () => res();
61
- r.onerror = () => rej(r.error);
62
- });
63
- }
64
- // 读取全部记录(调试/回溯用)
65
- async getAll() {
66
- if (!this.db)
67
- return [];
68
- return new Promise((res, rej) => {
69
- const tx = this.db.transaction(this.storeName, "readonly");
70
- const st = tx.objectStore(this.storeName);
71
- const req = st.getAll();
72
- req.onsuccess = () => res(req.result || []);
73
- req.onerror = () => rej(req.error);
74
- });
75
- }
76
- // 清空队列:发送成功后用于兜底清理
77
- async clear() {
78
- if (!this.db)
79
- return;
80
- return new Promise((res, rej) => {
81
- const tx = this.db.transaction(this.storeName, "readwrite");
82
- const st = tx.objectStore(this.storeName);
83
- const req = st.clear();
84
- req.onsuccess = () => res(void 0);
85
- req.onerror = () => rej(req.error);
86
- });
87
- }
88
- };
package/dist/cjs/index.js DELETED
@@ -1,29 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
-
19
- // src/index.ts
20
- var src_exports = {};
21
- __export(src_exports, {
22
- LoggerSDK: () => import_loggerSDK.LoggerSDK
23
- });
24
- module.exports = __toCommonJS(src_exports);
25
- var import_loggerSDK = require("./loggerSDK");
26
- // Annotate the CommonJS export names for ESM import in node:
27
- 0 && (module.exports = {
28
- LoggerSDK
29
- });