@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.
- package/README.md +195 -76
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +14 -2
- package/dist/cjs/loggerSDK.d.ts +27 -20
- package/dist/cjs/loggerSDK.js +86 -354
- package/dist/cjs/transportAdapter.d.ts +51 -5
- package/dist/cjs/transportAdapter.js +133 -60
- package/dist/cjs/types.d.ts +37 -26
- package/dist/cjs/utils.d.ts +27 -2
- package/dist/cjs/utils.js +151 -12
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +4 -2
- package/dist/esm/loggerSDK.d.ts +27 -20
- package/dist/esm/loggerSDK.js +141 -674
- package/dist/esm/transportAdapter.d.ts +51 -5
- package/dist/esm/transportAdapter.js +260 -111
- package/dist/esm/types.d.ts +37 -26
- package/dist/esm/utils.d.ts +27 -2
- package/dist/esm/utils.js +190 -14
- package/dist/umd/logger-sdk.min.js +1 -1
- package/lib/dbQueue.js +133 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +9 -0
- package/lib/loggerSDK.d.ts +29 -0
- package/lib/loggerSDK.js +571 -0
- package/lib/storeAdapter.js +99 -0
- package/lib/transportAdapter.d.ts +66 -0
- package/lib/transportAdapter.js +406 -0
- package/lib/types.d.ts +35 -0
- package/lib/types.js +1 -0
- package/lib/utils.d.ts +5 -0
- package/lib/utils.js +50 -0
- package/package.json +8 -2
- package/dist/cjs/dbQueue.js +0 -88
- package/dist/cjs/storeAdapter.js +0 -64
- package/dist/esm/dbQueue.d.ts +0 -10
- package/dist/esm/dbQueue.js +0 -194
- package/dist/esm/storeAdapter.d.ts +0 -7
- package/dist/esm/storeAdapter.js +0 -139
- /package/{dist/cjs → lib}/dbQueue.d.ts +0 -0
- /package/{dist/cjs → lib}/storeAdapter.d.ts +0 -0
|
@@ -1,5 +1,51 @@
|
|
|
1
|
-
import { SDKOptions } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
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
|
+
};
|
|
@@ -1,142 +1,291 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
2
|
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
3
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
|
-
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
7
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
8
3
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
9
4
|
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
10
5
|
/*
|
|
11
6
|
* @Author : 黄震 huangzhen@yfpharmacy.com
|
|
12
7
|
* @Date : 2025-11-21 14:35:48
|
|
13
8
|
* @LastEditors : 黄震 huangzhen@yfpharmacy.com
|
|
14
|
-
* @LastEditTime : 2025-12-
|
|
15
|
-
* @Description :
|
|
9
|
+
* @LastEditTime : 2025-12-04 14:30:00
|
|
10
|
+
* @Description : 传输适配器 - Beacon、像素图和微信小程序方式
|
|
16
11
|
* Copyright (c) 2025 by 益丰大药房连锁股份有限公司, All Rights Reserved.
|
|
17
12
|
*/
|
|
18
13
|
|
|
19
|
-
import {
|
|
14
|
+
import { safeStringify, isBrowser, isWeChatMiniProgram, now } from "./utils";
|
|
15
|
+
|
|
16
|
+
/** 传输选项接口 */
|
|
17
|
+
|
|
18
|
+
/** 传输适配器接口 */
|
|
19
|
+
|
|
20
|
+
// ==================== 辅助函数 ====================
|
|
21
|
+
|
|
22
|
+
/** 获取端点 URL */
|
|
23
|
+
function getEndpoint(opts) {
|
|
24
|
+
return (opts === null || opts === void 0 ? void 0 : opts.endpoint) || '';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ==================== 1. Beacon 传输适配器(页面卸载场景首选)====================
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Beacon 传输适配器
|
|
31
|
+
* - 兼容性:现代浏览器(Chrome 39+, Firefox 31+, Edge 14+)
|
|
32
|
+
* - 健壮性:页面卸载时可靠传输、不阻塞页面卸载
|
|
33
|
+
* - 适用场景:页面关闭、visibilitychange、pagehide、beforeunload 事件
|
|
34
|
+
* - 限制:无法获取响应、队列有大小限制(通常 64KB)
|
|
35
|
+
*/
|
|
36
|
+
export var beaconTransport = {
|
|
37
|
+
name: 'beacon',
|
|
38
|
+
isSupported: function isSupported() {
|
|
39
|
+
return isBrowser() && typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';
|
|
40
|
+
},
|
|
41
|
+
send: function send(payload, opts) {
|
|
42
|
+
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
43
|
+
var body, endpoint, blob, success;
|
|
44
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
45
|
+
while (1) switch (_context.prev = _context.next) {
|
|
46
|
+
case 0:
|
|
47
|
+
body = typeof payload === 'string' ? payload : safeStringify(payload);
|
|
48
|
+
endpoint = getEndpoint(opts); // sendBeacon 使用 Blob 确保正确的 Content-Type
|
|
49
|
+
blob = new Blob([body], {
|
|
50
|
+
type: 'application/json'
|
|
51
|
+
});
|
|
52
|
+
success = navigator.sendBeacon(endpoint, blob);
|
|
53
|
+
if (success) {
|
|
54
|
+
_context.next = 6;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
throw new Error('sendBeacon failed (queue full or other error)');
|
|
58
|
+
case 6:
|
|
59
|
+
case "end":
|
|
60
|
+
return _context.stop();
|
|
61
|
+
}
|
|
62
|
+
}, _callee);
|
|
63
|
+
}))();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// ==================== 2. 微信小程序传输适配器(微信环境专用)====================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 微信小程序传输适配器
|
|
71
|
+
* - 兼容性:微信小程序环境
|
|
72
|
+
* - 健壮性:支持超时控制、完善的错误处理
|
|
73
|
+
* - 适用场景:微信小程序环境下的日志上报
|
|
74
|
+
*/
|
|
75
|
+
export var wechatTransport = {
|
|
76
|
+
name: 'wechat',
|
|
77
|
+
isSupported: function isSupported() {
|
|
78
|
+
return isWeChatMiniProgram();
|
|
79
|
+
},
|
|
80
|
+
send: function send(payload, opts) {
|
|
81
|
+
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
|
|
82
|
+
var body, endpoint, timeout;
|
|
83
|
+
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
84
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
85
|
+
case 0:
|
|
86
|
+
body = typeof payload === 'string' ? payload : safeStringify(payload);
|
|
87
|
+
endpoint = getEndpoint(opts);
|
|
88
|
+
timeout = 10000; // 10秒超时
|
|
89
|
+
return _context2.abrupt("return", new Promise(function (resolve, reject) {
|
|
90
|
+
var timeoutId = null;
|
|
91
|
+
var settled = false;
|
|
92
|
+
|
|
93
|
+
// 超时处理
|
|
94
|
+
timeoutId = setTimeout(function () {
|
|
95
|
+
if (!settled) {
|
|
96
|
+
settled = true;
|
|
97
|
+
reject(new Error("WeChat request timeout after ".concat(timeout, "ms")));
|
|
98
|
+
}
|
|
99
|
+
}, timeout);
|
|
100
|
+
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
wx.request({
|
|
103
|
+
url: endpoint,
|
|
104
|
+
method: 'POST',
|
|
105
|
+
data: body,
|
|
106
|
+
header: {
|
|
107
|
+
'Content-Type': 'application/json'
|
|
108
|
+
},
|
|
109
|
+
success: function success(res) {
|
|
110
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
111
|
+
if (!settled) {
|
|
112
|
+
settled = true;
|
|
113
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
114
|
+
resolve();
|
|
115
|
+
} else {
|
|
116
|
+
reject(new Error("HTTP ".concat(res.statusCode)));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
fail: function fail(err) {
|
|
121
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
122
|
+
if (!settled) {
|
|
123
|
+
settled = true;
|
|
124
|
+
reject(new Error("WeChat request failed: ".concat(err.errMsg || 'unknown error')));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}));
|
|
129
|
+
case 4:
|
|
130
|
+
case "end":
|
|
131
|
+
return _context2.stop();
|
|
132
|
+
}
|
|
133
|
+
}, _callee2);
|
|
134
|
+
}))();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// ==================== 3. Image 像素上报适配器(兼容性最好)====================
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Image 像素上报适配器
|
|
142
|
+
* - 兼容性:所有浏览器
|
|
143
|
+
* - 健壮性:轻量级、无跨域限制、支持超时控制
|
|
144
|
+
* - 适用场景:数据量小的快速上报、跨域场景、降级方案
|
|
145
|
+
* - 限制:URL 长度限制(默认 1900 字符)
|
|
146
|
+
*/
|
|
147
|
+
export var imageTransport = {
|
|
148
|
+
name: 'image',
|
|
149
|
+
isSupported: function isSupported() {
|
|
150
|
+
return isBrowser() && typeof Image !== 'undefined';
|
|
151
|
+
},
|
|
152
|
+
send: function send(payload, opts) {
|
|
153
|
+
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
|
|
154
|
+
var body, endpoint, param, maxLen, cacheBuster, qs, url;
|
|
155
|
+
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
156
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
157
|
+
case 0:
|
|
158
|
+
body = typeof payload === 'string' ? payload : safeStringify(payload);
|
|
159
|
+
endpoint = getEndpoint(opts);
|
|
160
|
+
param = (opts === null || opts === void 0 ? void 0 : opts.pixelParam) || 'data';
|
|
161
|
+
maxLen = (opts === null || opts === void 0 ? void 0 : opts.maxPixelUrlLen) || 1900; // 构建 URL
|
|
162
|
+
cacheBuster = "_=".concat(now());
|
|
163
|
+
qs = "".concat(param, "=").concat(encodeURIComponent(body), "&").concat(cacheBuster);
|
|
164
|
+
url = endpoint.includes('?') ? "".concat(endpoint, "&").concat(qs) : "".concat(endpoint, "?").concat(qs); // URL 长度检查
|
|
165
|
+
if (!(url.length > maxLen)) {
|
|
166
|
+
_context3.next = 9;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
throw new Error("URL too long (".concat(url.length, " > ").concat(maxLen, ")"));
|
|
170
|
+
case 9:
|
|
171
|
+
return _context3.abrupt("return", new Promise(function (resolve, reject) {
|
|
172
|
+
var img = new Image();
|
|
173
|
+
var timeoutId = null;
|
|
174
|
+
var settled = false;
|
|
175
|
+
|
|
176
|
+
// 超时处理(5秒)
|
|
177
|
+
timeoutId = setTimeout(function () {
|
|
178
|
+
if (!settled) {
|
|
179
|
+
settled = true;
|
|
180
|
+
img.src = ''; // 取消请求
|
|
181
|
+
reject(new Error('Image request timeout after 5000ms'));
|
|
182
|
+
}
|
|
183
|
+
}, 5000);
|
|
184
|
+
img.onload = function () {
|
|
185
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
186
|
+
if (!settled) {
|
|
187
|
+
settled = true;
|
|
188
|
+
resolve();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
img.onerror = function () {
|
|
192
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
193
|
+
if (!settled) {
|
|
194
|
+
settled = true;
|
|
195
|
+
reject(new Error('Image request failed'));
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// 发起请求
|
|
200
|
+
img.src = url;
|
|
201
|
+
}));
|
|
202
|
+
case 10:
|
|
203
|
+
case "end":
|
|
204
|
+
return _context3.stop();
|
|
205
|
+
}
|
|
206
|
+
}, _callee3);
|
|
207
|
+
}))();
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// ==================== 默认传输策略 ====================
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 默认传输函数 - 按环境选择最佳传输方式
|
|
215
|
+
* 浏览器策略:Beacon(可靠) > Image(兼容)
|
|
216
|
+
* 微信小程序策略:WeChat Request
|
|
217
|
+
*/
|
|
20
218
|
export function defaultTransport(_x, _x2) {
|
|
21
219
|
return _defaultTransport.apply(this, arguments);
|
|
22
220
|
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 导出所有适配器,方便自定义使用
|
|
224
|
+
*/
|
|
23
225
|
function _defaultTransport() {
|
|
24
|
-
_defaultTransport = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function
|
|
25
|
-
var
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
while (1) switch (_context.prev = _context.next) {
|
|
226
|
+
_defaultTransport = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(payload, opts) {
|
|
227
|
+
var transports, adapter;
|
|
228
|
+
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
229
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
29
230
|
case 0:
|
|
30
|
-
body = typeof payload === 'string' ? payload : safeStringify(payload);
|
|
31
|
-
timeout = (opts === null || opts === void 0 ? void 0 : opts.timeout) || 10000;
|
|
32
|
-
endpoint = opts && opts.endpoint ? opts.endpoint : ((_endpoints = opts.endpoints) === null || _endpoints === void 0 ? void 0 : _endpoints.default) || '';
|
|
33
|
-
if (!(isBrowser() && typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function' && opts !== null && opts !== void 0 && opts.useBeacon)) {
|
|
34
|
-
_context.next = 9;
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
blob = new Blob([body], {
|
|
38
|
-
type: 'application/json'
|
|
39
|
-
});
|
|
40
|
-
ok = navigator.sendBeacon(endpoint || '', blob);
|
|
41
|
-
if (!ok) {
|
|
42
|
-
_context.next = 8;
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
return _context.abrupt("return", Promise.resolve());
|
|
46
|
-
case 8:
|
|
47
|
-
return _context.abrupt("return", Promise.reject(new Error('sendBeacon failed')));
|
|
48
|
-
case 9:
|
|
49
231
|
if (!isWeChatMiniProgram()) {
|
|
50
|
-
|
|
232
|
+
_context4.next = 5;
|
|
51
233
|
break;
|
|
52
234
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
wx.request({
|
|
57
|
-
url: endpoint || '',
|
|
58
|
-
method: 'POST',
|
|
59
|
-
data: body,
|
|
60
|
-
header: _objectSpread({
|
|
61
|
-
'Content-Type': 'application/json'
|
|
62
|
-
}, opts && opts.globalHeaders ? opts.globalHeaders : {}),
|
|
63
|
-
success: function success() {
|
|
64
|
-
if (timer) clearTimeout(timer);
|
|
65
|
-
resolve();
|
|
66
|
-
},
|
|
67
|
-
fail: function fail(err) {
|
|
68
|
-
if (timer) clearTimeout(timer);
|
|
69
|
-
reject(err);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
timer = setTimeout(function () {
|
|
73
|
-
return reject(new Error('timeout'));
|
|
74
|
-
}, timeout);
|
|
75
|
-
}));
|
|
76
|
-
case 11:
|
|
77
|
-
if (!(isBrowser() && opts !== null && opts !== void 0 && opts.usePixel)) {
|
|
78
|
-
_context.next = 23;
|
|
235
|
+
if (!wechatTransport.isSupported(opts)) {
|
|
236
|
+
_context4.next = 5;
|
|
79
237
|
break;
|
|
80
238
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
239
|
+
_context4.next = 4;
|
|
240
|
+
return wechatTransport.send(payload, opts);
|
|
241
|
+
case 4:
|
|
242
|
+
return _context4.abrupt("return");
|
|
243
|
+
case 5:
|
|
244
|
+
// 浏览器环境使用 Beacon 或 Image
|
|
245
|
+
transports = [beaconTransport, imageTransport]; // 尝试找到第一个支持的适配器
|
|
246
|
+
adapter = transports.find(function (t) {
|
|
247
|
+
return t.isSupported(opts);
|
|
248
|
+
});
|
|
249
|
+
if (adapter) {
|
|
250
|
+
_context4.next = 9;
|
|
89
251
|
break;
|
|
90
252
|
}
|
|
91
|
-
|
|
253
|
+
throw new Error('No supported transport adapter available');
|
|
254
|
+
case 9:
|
|
255
|
+
_context4.prev = 9;
|
|
256
|
+
_context4.next = 12;
|
|
257
|
+
return adapter.send(payload, opts);
|
|
258
|
+
case 12:
|
|
259
|
+
_context4.next = 27;
|
|
92
260
|
break;
|
|
93
|
-
case
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
img.onload = function () {
|
|
99
|
-
if (timer) clearTimeout(timer);
|
|
100
|
-
resolve();
|
|
101
|
-
};
|
|
102
|
-
img.onerror = function () {
|
|
103
|
-
if (timer) clearTimeout(timer);
|
|
104
|
-
reject(new Error('pixel error'));
|
|
105
|
-
};
|
|
106
|
-
timer = setTimeout(function () {
|
|
107
|
-
return reject(new Error('timeout'));
|
|
108
|
-
}, timeout);
|
|
109
|
-
img.src = url;
|
|
110
|
-
}));
|
|
111
|
-
case 23:
|
|
112
|
-
if (!(typeof fetch === 'function')) {
|
|
113
|
-
_context.next = 27;
|
|
261
|
+
case 14:
|
|
262
|
+
_context4.prev = 14;
|
|
263
|
+
_context4.t0 = _context4["catch"](9);
|
|
264
|
+
if (!(adapter.name === 'beacon' && imageTransport.isSupported(opts))) {
|
|
265
|
+
_context4.next = 26;
|
|
114
266
|
break;
|
|
115
267
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
// @ts-ignore
|
|
128
|
-
keepalive: opts !== null && opts !== void 0 && opts.useBeacon ? true : undefined,
|
|
129
|
-
signal: controller ? controller.signal : undefined
|
|
130
|
-
}).then(function (res) {
|
|
131
|
-
if (!res.ok) throw new Error('network response not ok');
|
|
132
|
-
}));
|
|
268
|
+
_context4.prev = 17;
|
|
269
|
+
_context4.next = 20;
|
|
270
|
+
return imageTransport.send(payload, opts);
|
|
271
|
+
case 20:
|
|
272
|
+
return _context4.abrupt("return");
|
|
273
|
+
case 23:
|
|
274
|
+
_context4.prev = 23;
|
|
275
|
+
_context4.t1 = _context4["catch"](17);
|
|
276
|
+
throw _context4.t0;
|
|
277
|
+
case 26:
|
|
278
|
+
throw _context4.t0;
|
|
133
279
|
case 27:
|
|
134
|
-
return _context.abrupt("return", Promise.reject(new Error('no transport available')));
|
|
135
|
-
case 28:
|
|
136
280
|
case "end":
|
|
137
|
-
return
|
|
281
|
+
return _context4.stop();
|
|
138
282
|
}
|
|
139
|
-
},
|
|
283
|
+
}, _callee4, null, [[9, 14], [17, 23]]);
|
|
140
284
|
}));
|
|
141
285
|
return _defaultTransport.apply(this, arguments);
|
|
142
|
-
}
|
|
286
|
+
}
|
|
287
|
+
export var TransportAdapters = {
|
|
288
|
+
beacon: beaconTransport,
|
|
289
|
+
wechat: wechatTransport,
|
|
290
|
+
image: imageTransport
|
|
291
|
+
};
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,35 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
export type
|
|
3
|
-
|
|
1
|
+
/** 环境类型 */
|
|
2
|
+
export type Env = 'prod' | 'stage' | 'dev';
|
|
3
|
+
/** 事件类型 */
|
|
4
|
+
export type LogEventType = 'error' | 'crash' | 'pageview' | 'custom';
|
|
5
|
+
/** 日志级别 */
|
|
6
|
+
export type LogEventLevel = 'info' | 'warn' | 'error' | 'fatal';
|
|
7
|
+
/** SDK 配置选项 */
|
|
4
8
|
export interface SDKOptions {
|
|
5
|
-
|
|
9
|
+
/** 上报端点 URL */
|
|
10
|
+
endpoint: string;
|
|
11
|
+
/** 应用 ID */
|
|
6
12
|
appId?: string;
|
|
13
|
+
/** 环境标识 */
|
|
7
14
|
env?: Env;
|
|
8
|
-
|
|
9
|
-
flushInterval?: number;
|
|
10
|
-
retryCount?: number;
|
|
11
|
-
retryBase?: number;
|
|
12
|
-
storageKey?: string;
|
|
13
|
-
maxCacheSize?: number;
|
|
14
|
-
timeout?: number;
|
|
15
|
+
/** 是否开启调试模式 */
|
|
15
16
|
debug?: boolean;
|
|
16
|
-
|
|
17
|
-
endpoint?: string;
|
|
18
|
-
headers?: Record<string, string>;
|
|
19
|
-
}) => Promise<void>;
|
|
20
|
-
globalHeaders?: Record<string, string>;
|
|
21
|
-
enableAutoPV?: boolean;
|
|
22
|
-
enablePerf?: boolean;
|
|
23
|
-
useBeacon?: boolean;
|
|
24
|
-
usePixel?: boolean;
|
|
17
|
+
/** 像素上报参数名,默认 'data' */
|
|
25
18
|
pixelParam?: string;
|
|
19
|
+
/** 像素上报 URL 最大长度,默认 1900 */
|
|
26
20
|
maxPixelUrlLen?: number;
|
|
27
21
|
}
|
|
22
|
+
/** 标准化日志上报格式 */
|
|
28
23
|
export interface LogEvent {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
/** 事件类型:error/crash/pageview/custom */
|
|
25
|
+
eventType: LogEventType;
|
|
26
|
+
/** 毫秒时间戳 */
|
|
27
|
+
ts: number;
|
|
28
|
+
/** 应用标识 */
|
|
29
|
+
appId: string;
|
|
30
|
+
/** 环境标识:prod/stage/dev */
|
|
31
|
+
env: Env;
|
|
32
|
+
/** 日志级别:info/warn/error/fatal */
|
|
33
|
+
level: LogEventLevel;
|
|
34
|
+
/** 摘要信息 */
|
|
35
|
+
message: string;
|
|
36
|
+
/** 可选:堆栈信息(长字符串) */
|
|
37
|
+
stack?: string;
|
|
38
|
+
/** 发生页面 URL */
|
|
39
|
+
url: string;
|
|
40
|
+
/** 可选:用户 ID(脱敏) */
|
|
41
|
+
userId?: string;
|
|
42
|
+
/** 会话标识 */
|
|
43
|
+
sessionId: string;
|
|
44
|
+
/** 可选的结构化额外信息 */
|
|
45
|
+
tags?: Record<string, any>;
|
|
35
46
|
}
|
package/dist/esm/utils.d.ts
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
export declare const now: () => number;
|
|
2
|
-
export declare function isWeChatMiniProgram(): boolean;
|
|
3
2
|
export declare function isBrowser(): boolean;
|
|
3
|
+
export declare function isWeChatMiniProgram(): boolean;
|
|
4
4
|
export declare function safeStringify(obj: any): string;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function getSessionId(): string;
|
|
6
|
+
export declare function getCurrentUrl(): string;
|
|
7
|
+
/** 平台类型 */
|
|
8
|
+
export type PlatformType = 'browser' | 'wechat' | 'unknown';
|
|
9
|
+
/** 环境信息 */
|
|
10
|
+
export interface EnvironmentInfo {
|
|
11
|
+
platform: PlatformType;
|
|
12
|
+
userAgent?: string;
|
|
13
|
+
screenWidth?: number;
|
|
14
|
+
screenHeight?: number;
|
|
15
|
+
language?: string;
|
|
16
|
+
systemInfo?: any;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 获取环境信息
|
|
20
|
+
*/
|
|
21
|
+
export declare function getEnvironmentInfo(): EnvironmentInfo;
|
|
22
|
+
/**
|
|
23
|
+
* 解析浏览器信息
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseBrowserInfo(userAgent: string): {
|
|
26
|
+
browser: string;
|
|
27
|
+
browserVersion: string;
|
|
28
|
+
os: string;
|
|
29
|
+
osVersion: string;
|
|
30
|
+
};
|