@antglobal/rlog-sdk 0.0.1755855517-dev.8 → 1.0.0
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 +192 -432
- package/dist/esm/index.d.ts +14 -41
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +92 -76
- package/dist/esm/lib/api.d.ts +10 -0
- package/dist/esm/lib/api.d.ts.map +1 -1
- package/dist/esm/lib/api.js +58 -35
- package/dist/esm/lib/config.d.ts +14 -16
- package/dist/esm/lib/config.d.ts.map +1 -1
- package/dist/esm/lib/config.js +61 -33
- package/dist/esm/lib/constants.d.ts +89 -0
- package/dist/esm/lib/constants.d.ts.map +1 -0
- package/dist/esm/lib/constants.js +145 -0
- package/dist/esm/lib/drive/indexeddb-adapt.d.ts +12 -0
- package/dist/esm/lib/drive/indexeddb-adapt.d.ts.map +1 -1
- package/dist/esm/lib/drive/indexeddb-adapt.js +190 -20
- package/dist/esm/lib/drive/localstorage-adapt.d.ts +12 -0
- package/dist/esm/lib/drive/localstorage-adapt.d.ts.map +1 -1
- package/dist/esm/lib/drive/localstorage-adapt.js +179 -36
- package/dist/esm/lib/drive/memory-adapt.d.ts +10 -2
- package/dist/esm/lib/drive/memory-adapt.d.ts.map +1 -1
- package/dist/esm/lib/drive/memory-adapt.js +118 -26
- package/dist/esm/lib/drive/safe-storage.d.ts +24 -0
- package/dist/esm/lib/drive/safe-storage.d.ts.map +1 -0
- package/dist/esm/lib/drive/safe-storage.js +96 -0
- package/dist/esm/lib/drive/storage-interface.d.ts +20 -0
- package/dist/esm/lib/drive/storage-interface.d.ts.map +1 -1
- package/dist/esm/lib/error-trigger.d.ts +73 -0
- package/dist/esm/lib/error-trigger.d.ts.map +1 -0
- package/dist/esm/lib/error-trigger.js +162 -0
- package/dist/esm/lib/error.d.ts +9 -0
- package/dist/esm/lib/error.d.ts.map +1 -1
- package/dist/esm/lib/error.js +70 -118
- package/dist/esm/lib/init.d.ts +0 -4
- package/dist/esm/lib/init.d.ts.map +1 -1
- package/dist/esm/lib/init.js +148 -47
- package/dist/esm/lib/logger.d.ts +27 -0
- package/dist/esm/lib/logger.d.ts.map +1 -0
- package/dist/esm/lib/logger.js +79 -0
- package/dist/esm/lib/net.d.ts +11 -0
- package/dist/esm/lib/net.d.ts.map +1 -1
- package/dist/esm/lib/net.js +264 -116
- package/dist/esm/lib/request.d.ts.map +1 -1
- package/dist/esm/lib/request.js +2 -2
- package/dist/esm/lib/router-monitor.d.ts.map +1 -1
- package/dist/esm/lib/router-monitor.js +135 -49
- package/dist/esm/lib/rrweb.d.ts.map +1 -1
- package/dist/esm/lib/rrweb.js +31 -24
- package/dist/esm/lib/storage-manager.d.ts +12 -0
- package/dist/esm/lib/storage-manager.d.ts.map +1 -1
- package/dist/esm/lib/storage-manager.js +129 -46
- package/dist/esm/lib/upload-worker-manager.d.ts +47 -0
- package/dist/esm/lib/upload-worker-manager.d.ts.map +1 -0
- package/dist/esm/lib/upload-worker-manager.js +559 -0
- package/dist/esm/lib/upload-worker.d.ts +58 -0
- package/dist/esm/lib/upload-worker.d.ts.map +1 -0
- package/dist/esm/lib/upload-worker.js +28 -0
- package/dist/esm/lib/uploader.d.ts +43 -0
- package/dist/esm/lib/uploader.d.ts.map +1 -1
- package/dist/esm/lib/uploader.js +464 -102
- package/dist/esm/lib/utils.d.ts +75 -0
- package/dist/esm/lib/utils.d.ts.map +1 -1
- package/dist/esm/lib/utils.js +268 -5
- package/dist/lib/index.d.ts +14 -41
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +81 -63
- package/dist/lib/lib/api.d.ts +10 -0
- package/dist/lib/lib/api.d.ts.map +1 -1
- package/dist/lib/lib/api.js +59 -35
- package/dist/lib/lib/config.d.ts +14 -16
- package/dist/lib/lib/config.d.ts.map +1 -1
- package/dist/lib/lib/config.js +63 -33
- package/dist/lib/lib/constants.d.ts +89 -0
- package/dist/lib/lib/constants.d.ts.map +1 -0
- package/dist/lib/lib/constants.js +151 -0
- package/dist/lib/lib/drive/indexeddb-adapt.d.ts +12 -0
- package/dist/lib/lib/drive/indexeddb-adapt.d.ts.map +1 -1
- package/dist/lib/lib/drive/indexeddb-adapt.js +191 -19
- package/dist/lib/lib/drive/localstorage-adapt.d.ts +12 -0
- package/dist/lib/lib/drive/localstorage-adapt.d.ts.map +1 -1
- package/dist/lib/lib/drive/localstorage-adapt.js +179 -36
- package/dist/lib/lib/drive/memory-adapt.d.ts +10 -2
- package/dist/lib/lib/drive/memory-adapt.d.ts.map +1 -1
- package/dist/lib/lib/drive/memory-adapt.js +117 -26
- package/dist/lib/lib/drive/safe-storage.d.ts +24 -0
- package/dist/lib/lib/drive/safe-storage.d.ts.map +1 -0
- package/dist/lib/lib/drive/safe-storage.js +102 -0
- package/dist/lib/lib/drive/storage-interface.d.ts +20 -0
- package/dist/lib/lib/drive/storage-interface.d.ts.map +1 -1
- package/dist/lib/lib/error-trigger.d.ts +73 -0
- package/dist/lib/lib/error-trigger.d.ts.map +1 -0
- package/dist/lib/lib/error-trigger.js +167 -0
- package/dist/lib/lib/error.d.ts +9 -0
- package/dist/lib/lib/error.d.ts.map +1 -1
- package/dist/lib/lib/error.js +73 -118
- package/dist/lib/lib/init.d.ts +0 -4
- package/dist/lib/lib/init.d.ts.map +1 -1
- package/dist/lib/lib/init.js +144 -43
- package/dist/lib/lib/logger.d.ts +27 -0
- package/dist/lib/lib/logger.d.ts.map +1 -0
- package/dist/lib/lib/logger.js +84 -0
- package/dist/lib/lib/net.d.ts +11 -0
- package/dist/lib/lib/net.d.ts.map +1 -1
- package/dist/lib/lib/net.js +268 -117
- package/dist/lib/lib/request.d.ts.map +1 -1
- package/dist/lib/lib/request.js +3 -3
- package/dist/lib/lib/router-monitor.d.ts.map +1 -1
- package/dist/lib/lib/router-monitor.js +136 -49
- package/dist/lib/lib/rrweb.d.ts.map +1 -1
- package/dist/lib/lib/rrweb.js +31 -23
- package/dist/lib/lib/storage-manager.d.ts +12 -0
- package/dist/lib/lib/storage-manager.d.ts.map +1 -1
- package/dist/lib/lib/storage-manager.js +130 -46
- package/dist/lib/lib/upload-worker-manager.d.ts +47 -0
- package/dist/lib/lib/upload-worker-manager.d.ts.map +1 -0
- package/dist/lib/lib/upload-worker-manager.js +570 -0
- package/dist/lib/lib/upload-worker.d.ts +58 -0
- package/dist/lib/lib/upload-worker.d.ts.map +1 -0
- package/dist/lib/lib/upload-worker.js +33 -0
- package/dist/lib/lib/uploader.d.ts +43 -0
- package/dist/lib/lib/uploader.d.ts.map +1 -1
- package/dist/lib/lib/uploader.js +468 -101
- package/dist/lib/lib/utils.d.ts +75 -0
- package/dist/lib/lib/utils.d.ts.map +1 -1
- package/dist/lib/lib/utils.js +276 -6
- package/dist/rlog-sdk.min.js +1 -1
- package/package.json +3 -2
package/dist/esm/lib/utils.d.ts
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
1
|
export declare const generateUUIDCompat: () => string;
|
|
2
2
|
export declare const getDeviceId: () => string;
|
|
3
|
+
/**
|
|
4
|
+
* session 过期时间(1小时)
|
|
5
|
+
* 超过此时间的 session 数据将在下次 SDK 初始化时被清理
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 获取当前标签页的 sessionId
|
|
9
|
+
* 首次调用时自动生成并注册
|
|
10
|
+
*/
|
|
11
|
+
export declare const getSessionId: () => string;
|
|
12
|
+
/**
|
|
13
|
+
* 获取存储用的复合键(deviceId_sessionId)
|
|
14
|
+
* 用于替代原来单独使用 deviceId 作为存储分区键
|
|
15
|
+
* 确保多标签页的录制数据互相隔离
|
|
16
|
+
*/
|
|
17
|
+
export declare const getStorageKey: () => string;
|
|
18
|
+
/**
|
|
19
|
+
* 从注册表中移除指定 sessionId
|
|
20
|
+
*/
|
|
21
|
+
export declare function unregisterSession(sessionId: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* 清理过期的 session 数据
|
|
24
|
+
* 在 SDK 初始化时调用,扫描注册表中超过 SESSION_MAX_AGE 的 session,
|
|
25
|
+
* 删除其对应的存储数据和锁,并从注册表中移除
|
|
26
|
+
*/
|
|
27
|
+
export declare function cleanupStaleSessions(): void;
|
|
28
|
+
/**
|
|
29
|
+
* 孤儿 session 数据的最大有效时间跨度(默认 2 分钟)
|
|
30
|
+
* 只有数据时间跨度在此范围内的才被视为"上传周期内的残留数据",
|
|
31
|
+
* 超过此范围的可能是其他无关项目或异常数据,不予上传
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* 孤儿 session 数据的最大年龄(默认 5 分钟)
|
|
35
|
+
* 只有 session 注册时间在此范围内的才被视为"近期的残留数据",
|
|
36
|
+
* 超过此范围的可能是长时间未清理的旧数据
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* 孤儿 session 信息
|
|
40
|
+
*/
|
|
41
|
+
export interface OrphanSessionInfo {
|
|
42
|
+
sessionId: string;
|
|
43
|
+
storageKey: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 获取所有孤儿 session(注册表中存在但不属于当前标签页的 session)
|
|
47
|
+
* 仅返回近期的、可能包含残留数据的 session
|
|
48
|
+
*
|
|
49
|
+
* 判断条件:
|
|
50
|
+
* 1. 不是当前标签页的 sessionId
|
|
51
|
+
* 2. session 注册时间在 ORPHAN_SESSION_MAX_AGE 范围内(排除过老的数据)
|
|
52
|
+
* 3. 对应的 localStorage 中确实存在数据
|
|
53
|
+
*/
|
|
54
|
+
export declare function getOrphanSessions(): OrphanSessionInfo[];
|
|
55
|
+
/**
|
|
56
|
+
* 检查孤儿 session 的数据是否在合理的时间跨度内
|
|
57
|
+
* 用于过滤掉可能是其他无关项目或异常的数据
|
|
58
|
+
*
|
|
59
|
+
* @param events 事件数组
|
|
60
|
+
* @returns 是否在合理范围内
|
|
61
|
+
*/
|
|
62
|
+
export declare function isOrphanDataValid(events: any[]): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* 清理指定孤儿 session 的数据和注册信息
|
|
65
|
+
*/
|
|
66
|
+
export declare function cleanupOrphanSession(sessionId: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* 检查值是否为纯对象(非数组、非null)
|
|
69
|
+
*/
|
|
70
|
+
export declare const isPlainObject: (value: any) => value is Record<string, any>;
|
|
71
|
+
/**
|
|
72
|
+
* 深度合并配置对象
|
|
73
|
+
* @param target 目标配置(默认配置)
|
|
74
|
+
* @param source 源配置(新配置)
|
|
75
|
+
* @returns 合并后的配置
|
|
76
|
+
*/
|
|
77
|
+
export declare const deepMergeConfig: <T extends Record<string, any>>(target: T, source: Partial<T>) => T;
|
|
3
78
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,kBAAkB,cAM9B,CAAC;AAEF,eAAO,MAAM,WAAW,cAYvB,CAAC;AAgBF;;;GAGG;AAGH;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,MAM/B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAO,MAEhC,CAAC;AAeF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CA0B3C;AAID;;;;GAIG;AAGH;;;;GAIG;AAGH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,EAAE,CAkCvD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CA0BxD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAW5D;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,UAAW,GAAG,iCAEvC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,0CAClB,CAAC,UACD,QAAQ,CAAC,CAAC,KACjB,CAsBF,CAAC"}
|
package/dist/esm/lib/utils.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
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; }
|
|
2
|
+
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; }
|
|
3
|
+
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; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
5
|
+
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); }
|
|
6
|
+
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); }
|
|
7
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
8
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
9
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
10
|
+
import { safeStorage } from "./drive/safe-storage";
|
|
11
|
+
import { STORAGE_KEY_DEVICE_ID, STORAGE_KEY_UTOKEN, STORAGE_KEY_IWP_DEVICE_TAG, STORAGE_KEY_SESSION_REGISTRY, STORAGE_KEY_DATA_PREFIX, STORAGE_KEY_LOCK_PREFIX, SESSION_MAX_AGE, ORPHAN_DATA_MAX_SPAN, ORPHAN_SESSION_MAX_AGE } from "./constants";
|
|
1
12
|
export var generateUUIDCompat = function generateUUIDCompat() {
|
|
2
13
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
3
14
|
var r = Math.random() * 16 | 0;
|
|
@@ -6,11 +17,263 @@ export var generateUUIDCompat = function generateUUIDCompat() {
|
|
|
6
17
|
});
|
|
7
18
|
};
|
|
8
19
|
export var getDeviceId = function getDeviceId() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return localStorage.getItem('rlog-deviceId');
|
|
20
|
+
if (safeStorage.getItem(STORAGE_KEY_DEVICE_ID)) {
|
|
21
|
+
return safeStorage.getItem(STORAGE_KEY_DEVICE_ID);
|
|
12
22
|
}
|
|
13
|
-
var newId =
|
|
14
|
-
|
|
23
|
+
var newId = safeStorage.getItem(STORAGE_KEY_UTOKEN) || safeStorage.getItem(STORAGE_KEY_IWP_DEVICE_TAG) || generateUUIDCompat();
|
|
24
|
+
safeStorage.setItem(STORAGE_KEY_DEVICE_ID, newId);
|
|
15
25
|
return newId;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ==================== Session 隔离 ====================
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 当前标签页的 sessionId(内存中,每次页面加载生成新的)
|
|
32
|
+
* 用于隔离同域下多个标签页的录制数据
|
|
33
|
+
*/
|
|
34
|
+
var currentSessionId = null;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* session 注册表的存储 key
|
|
38
|
+
* 注册表结构: { [sessionId]: timestamp }
|
|
39
|
+
*/
|
|
40
|
+
var SESSION_REGISTRY_KEY = STORAGE_KEY_SESSION_REGISTRY;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* session 过期时间(1小时)
|
|
44
|
+
* 超过此时间的 session 数据将在下次 SDK 初始化时被清理
|
|
45
|
+
*/
|
|
46
|
+
// SESSION_MAX_AGE 已从 constants.ts 导入
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 获取当前标签页的 sessionId
|
|
50
|
+
* 首次调用时自动生成并注册
|
|
51
|
+
*/
|
|
52
|
+
export var getSessionId = function getSessionId() {
|
|
53
|
+
if (!currentSessionId) {
|
|
54
|
+
currentSessionId = generateUUIDCompat();
|
|
55
|
+
registerSession(currentSessionId);
|
|
56
|
+
}
|
|
57
|
+
return currentSessionId;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 获取存储用的复合键(deviceId_sessionId)
|
|
62
|
+
* 用于替代原来单独使用 deviceId 作为存储分区键
|
|
63
|
+
* 确保多标签页的录制数据互相隔离
|
|
64
|
+
*/
|
|
65
|
+
export var getStorageKey = function getStorageKey() {
|
|
66
|
+
return "".concat(getDeviceId(), "_").concat(getSessionId());
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 将 sessionId 注册到注册表中
|
|
71
|
+
*/
|
|
72
|
+
function registerSession(sessionId) {
|
|
73
|
+
try {
|
|
74
|
+
var registry = JSON.parse(safeStorage.getItem(SESSION_REGISTRY_KEY) || '{}');
|
|
75
|
+
registry[sessionId] = Date.now();
|
|
76
|
+
safeStorage.setItem(SESSION_REGISTRY_KEY, JSON.stringify(registry));
|
|
77
|
+
} catch (e) {
|
|
78
|
+
// 解析失败时静默忽略
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 从注册表中移除指定 sessionId
|
|
84
|
+
*/
|
|
85
|
+
export function unregisterSession(sessionId) {
|
|
86
|
+
try {
|
|
87
|
+
var registry = JSON.parse(safeStorage.getItem(SESSION_REGISTRY_KEY) || '{}');
|
|
88
|
+
delete registry[sessionId];
|
|
89
|
+
safeStorage.setItem(SESSION_REGISTRY_KEY, JSON.stringify(registry));
|
|
90
|
+
} catch (e) {
|
|
91
|
+
// 解析失败时静默忽略
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 清理过期的 session 数据
|
|
97
|
+
* 在 SDK 初始化时调用,扫描注册表中超过 SESSION_MAX_AGE 的 session,
|
|
98
|
+
* 删除其对应的存储数据和锁,并从注册表中移除
|
|
99
|
+
*/
|
|
100
|
+
export function cleanupStaleSessions() {
|
|
101
|
+
try {
|
|
102
|
+
var registry = JSON.parse(safeStorage.getItem(SESSION_REGISTRY_KEY) || '{}');
|
|
103
|
+
var now = Date.now();
|
|
104
|
+
var deviceId = getDeviceId();
|
|
105
|
+
var changed = false;
|
|
106
|
+
for (var _i = 0, _Object$keys = Object.keys(registry); _i < _Object$keys.length; _i++) {
|
|
107
|
+
var sessionId = _Object$keys[_i];
|
|
108
|
+
var createdAt = registry[sessionId];
|
|
109
|
+
if (now - createdAt > SESSION_MAX_AGE) {
|
|
110
|
+
// 清理该 session 对应的存储数据和锁
|
|
111
|
+
var storageKey = "".concat(STORAGE_KEY_DATA_PREFIX).concat(deviceId, "_").concat(sessionId);
|
|
112
|
+
var lockKey = "".concat(STORAGE_KEY_LOCK_PREFIX).concat(deviceId, "_").concat(sessionId);
|
|
113
|
+
safeStorage.removeItem(storageKey);
|
|
114
|
+
safeStorage.removeItem(lockKey);
|
|
115
|
+
delete registry[sessionId];
|
|
116
|
+
changed = true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (changed) {
|
|
120
|
+
safeStorage.setItem(SESSION_REGISTRY_KEY, JSON.stringify(registry));
|
|
121
|
+
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
// 解析失败时静默忽略
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ==================== 孤儿 Session 残留数据扫描 ====================
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 孤儿 session 数据的最大有效时间跨度(默认 2 分钟)
|
|
131
|
+
* 只有数据时间跨度在此范围内的才被视为"上传周期内的残留数据",
|
|
132
|
+
* 超过此范围的可能是其他无关项目或异常数据,不予上传
|
|
133
|
+
*/
|
|
134
|
+
// ORPHAN_DATA_MAX_SPAN 已从 constants.ts 导入
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 孤儿 session 数据的最大年龄(默认 5 分钟)
|
|
138
|
+
* 只有 session 注册时间在此范围内的才被视为"近期的残留数据",
|
|
139
|
+
* 超过此范围的可能是长时间未清理的旧数据
|
|
140
|
+
*/
|
|
141
|
+
// ORPHAN_SESSION_MAX_AGE 已从 constants.ts 导入
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 孤儿 session 信息
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 获取所有孤儿 session(注册表中存在但不属于当前标签页的 session)
|
|
149
|
+
* 仅返回近期的、可能包含残留数据的 session
|
|
150
|
+
*
|
|
151
|
+
* 判断条件:
|
|
152
|
+
* 1. 不是当前标签页的 sessionId
|
|
153
|
+
* 2. session 注册时间在 ORPHAN_SESSION_MAX_AGE 范围内(排除过老的数据)
|
|
154
|
+
* 3. 对应的 localStorage 中确实存在数据
|
|
155
|
+
*/
|
|
156
|
+
export function getOrphanSessions() {
|
|
157
|
+
try {
|
|
158
|
+
var registry = JSON.parse(safeStorage.getItem(SESSION_REGISTRY_KEY) || '{}');
|
|
159
|
+
var now = Date.now();
|
|
160
|
+
var deviceId = getDeviceId();
|
|
161
|
+
var mySessionId = getSessionId();
|
|
162
|
+
var orphans = [];
|
|
163
|
+
for (var _i2 = 0, _Object$keys2 = Object.keys(registry); _i2 < _Object$keys2.length; _i2++) {
|
|
164
|
+
var sessionId = _Object$keys2[_i2];
|
|
165
|
+
// 跳过当前标签页的 session
|
|
166
|
+
if (sessionId === mySessionId) continue;
|
|
167
|
+
var createdAt = registry[sessionId];
|
|
168
|
+
|
|
169
|
+
// 跳过过期的 session(由 cleanupStaleSessions 处理)
|
|
170
|
+
if (now - createdAt > SESSION_MAX_AGE) continue;
|
|
171
|
+
|
|
172
|
+
// 只处理近期的 session(ORPHAN_SESSION_MAX_AGE 范围内)
|
|
173
|
+
if (now - createdAt > ORPHAN_SESSION_MAX_AGE) continue;
|
|
174
|
+
var storageKey = "".concat(deviceId, "_").concat(sessionId);
|
|
175
|
+
var dataKey = "".concat(STORAGE_KEY_DATA_PREFIX).concat(storageKey);
|
|
176
|
+
|
|
177
|
+
// 检查是否有残留数据
|
|
178
|
+
var rawData = safeStorage.getItem(dataKey);
|
|
179
|
+
if (!rawData || rawData === '[]') continue;
|
|
180
|
+
orphans.push({
|
|
181
|
+
sessionId: sessionId,
|
|
182
|
+
storageKey: storageKey
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return orphans;
|
|
186
|
+
} catch (e) {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 检查孤儿 session 的数据是否在合理的时间跨度内
|
|
193
|
+
* 用于过滤掉可能是其他无关项目或异常的数据
|
|
194
|
+
*
|
|
195
|
+
* @param events 事件数组
|
|
196
|
+
* @returns 是否在合理范围内
|
|
197
|
+
*/
|
|
198
|
+
export function isOrphanDataValid(events) {
|
|
199
|
+
if (!events || events.length === 0) return false;
|
|
200
|
+
|
|
201
|
+
// 找到最早和最晚的事件时间戳
|
|
202
|
+
var minTime = Infinity;
|
|
203
|
+
var maxTime = -Infinity;
|
|
204
|
+
var _iterator = _createForOfIteratorHelper(events),
|
|
205
|
+
_step;
|
|
206
|
+
try {
|
|
207
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
208
|
+
var event = _step.value;
|
|
209
|
+
if (event && typeof event.timestamp === 'number') {
|
|
210
|
+
if (event.timestamp < minTime) minTime = event.timestamp;
|
|
211
|
+
if (event.timestamp > maxTime) maxTime = event.timestamp;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 如果没有有效的时间戳,不上传
|
|
216
|
+
} catch (err) {
|
|
217
|
+
_iterator.e(err);
|
|
218
|
+
} finally {
|
|
219
|
+
_iterator.f();
|
|
220
|
+
}
|
|
221
|
+
if (minTime === Infinity || maxTime === -Infinity) return false;
|
|
222
|
+
|
|
223
|
+
// 检查数据时间跨度是否在合理范围内
|
|
224
|
+
var span = maxTime - minTime;
|
|
225
|
+
if (span > ORPHAN_DATA_MAX_SPAN) return false;
|
|
226
|
+
|
|
227
|
+
// 检查数据是否太旧(最新事件距今超过 ORPHAN_SESSION_MAX_AGE)
|
|
228
|
+
var now = Date.now();
|
|
229
|
+
if (now - maxTime > ORPHAN_SESSION_MAX_AGE) return false;
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* 清理指定孤儿 session 的数据和注册信息
|
|
235
|
+
*/
|
|
236
|
+
export function cleanupOrphanSession(sessionId) {
|
|
237
|
+
try {
|
|
238
|
+
var deviceId = getDeviceId();
|
|
239
|
+
var storageKey = "".concat(STORAGE_KEY_DATA_PREFIX).concat(deviceId, "_").concat(sessionId);
|
|
240
|
+
var lockKey = "".concat(STORAGE_KEY_LOCK_PREFIX).concat(deviceId, "_").concat(sessionId);
|
|
241
|
+
safeStorage.removeItem(storageKey);
|
|
242
|
+
safeStorage.removeItem(lockKey);
|
|
243
|
+
unregisterSession(sessionId);
|
|
244
|
+
} catch (e) {
|
|
245
|
+
// 静默忽略
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 检查值是否为纯对象(非数组、非null)
|
|
251
|
+
*/
|
|
252
|
+
export var isPlainObject = function isPlainObject(value) {
|
|
253
|
+
return value !== null && _typeof(value) === 'object' && !Array.isArray(value);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 深度合并配置对象
|
|
258
|
+
* @param target 目标配置(默认配置)
|
|
259
|
+
* @param source 源配置(新配置)
|
|
260
|
+
* @returns 合并后的配置
|
|
261
|
+
*/
|
|
262
|
+
export var deepMergeConfig = function deepMergeConfig(target, source) {
|
|
263
|
+
var result = _objectSpread({}, target);
|
|
264
|
+
for (var key in source) {
|
|
265
|
+
if (source.hasOwnProperty(key)) {
|
|
266
|
+
var sourceValue = source[key];
|
|
267
|
+
var targetValue = target[key];
|
|
268
|
+
|
|
269
|
+
// 如果两个值都是纯对象,则递归合并
|
|
270
|
+
if (isPlainObject(sourceValue) && isPlainObject(targetValue)) {
|
|
271
|
+
result[key] = deepMergeConfig(targetValue, sourceValue);
|
|
272
|
+
} else if (sourceValue !== undefined) {
|
|
273
|
+
// 其他情况(包括数组、基本类型、null)直接覆盖
|
|
274
|
+
result[key] = sourceValue;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
16
279
|
};
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,65 +1,38 @@
|
|
|
1
|
-
import { setCustomHeaders, setWhiteListUrls, setBlackListUrls, getBlackListUrls, getSdkLogEndpoint, getWhiteListUrls, shouldRecordUrl } from './lib/net';
|
|
1
|
+
import { setCustomHeaders, getCustomHeaders, setWhiteListUrls, setBlackListUrls, getBlackListUrls, getSdkLogEndpoint, getWhiteListUrls, shouldRecordUrl } from './lib/net';
|
|
2
2
|
import { forceResetUploadState } from './lib/uploader';
|
|
3
3
|
import { updateRouterConfig, getCurrentRouteInfo, manualRouteChange, stopRouterMonitor } from './lib/router-monitor';
|
|
4
|
+
import { getConfig } from './lib/config';
|
|
4
5
|
import { cleanupErrorHandler } from './lib/error';
|
|
5
6
|
type Params = {
|
|
6
7
|
serv: string;
|
|
7
8
|
appId: string;
|
|
8
9
|
cdnConfigUrl?: string;
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
+
declare function init(param: Params): {
|
|
11
12
|
cancel: (options?: {
|
|
12
13
|
clearData?: boolean;
|
|
13
14
|
}) => void;
|
|
14
15
|
};
|
|
15
|
-
|
|
16
|
+
declare function cancelRecord(options?: {
|
|
16
17
|
clearData?: boolean;
|
|
17
18
|
}): void;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 获取当前是否处于只采集不上报模式
|
|
26
|
-
* @returns 是否启用只采集不上报模式
|
|
27
|
-
*/
|
|
28
|
-
export declare function isConsumeOnlyMode(): boolean;
|
|
29
|
-
/**
|
|
30
|
-
* 切换只采集不上报模式
|
|
31
|
-
*/
|
|
32
|
-
export declare function toggleConsumeOnlyMode(): boolean;
|
|
33
|
-
export { updateRouterConfig, getCurrentRouteInfo, manualRouteChange, stopRouterMonitor, };
|
|
34
|
-
export { setCustomHeaders, setWhiteListUrls, setBlackListUrls, getBlackListUrls, getWhiteListUrls, getSdkLogEndpoint, };
|
|
35
|
-
export { cleanupErrorHandler };
|
|
36
|
-
export declare const debug: {
|
|
37
|
-
/**
|
|
38
|
-
* 获取存储适配器类型
|
|
39
|
-
*/
|
|
19
|
+
declare function addCustomEvent(tagName: string, payload: any): void;
|
|
20
|
+
declare function setConsumeOnlyMode(enable: boolean): void;
|
|
21
|
+
declare function isConsumeOnlyMode(): boolean;
|
|
22
|
+
declare function toggleConsumeOnlyMode(): boolean;
|
|
23
|
+
declare function reportError(error: Error | string): void;
|
|
24
|
+
declare const debug: {
|
|
40
25
|
getStorageAdapterType(): string;
|
|
41
|
-
/**
|
|
42
|
-
* 获取设备ID
|
|
43
|
-
*/
|
|
44
26
|
getDeviceId: () => string;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*/
|
|
27
|
+
getSessionId: () => string;
|
|
28
|
+
getStorageKey: () => string;
|
|
48
29
|
resetUploadState: typeof forceResetUploadState;
|
|
49
|
-
/**
|
|
50
|
-
* 获取存储状态
|
|
51
|
-
*/
|
|
52
30
|
getStorageState(): Promise<{
|
|
53
31
|
adapterType: string;
|
|
54
32
|
eventCount: number;
|
|
55
33
|
}>;
|
|
56
|
-
/**
|
|
57
|
-
* 清空存储数据
|
|
58
|
-
*/
|
|
59
34
|
clearStorage(): Promise<void>;
|
|
60
|
-
|
|
61
|
-
* 检查URL是否应该被记录(白名单且不在黑名单中)
|
|
62
|
-
*/
|
|
63
|
-
shouldRecordUrl: typeof shouldRecordUrl;
|
|
35
|
+
getConfig: typeof getConfig;
|
|
64
36
|
};
|
|
37
|
+
export { init, cancelRecord, addCustomEvent, setConsumeOnlyMode, isConsumeOnlyMode, toggleConsumeOnlyMode, updateRouterConfig, getCurrentRouteInfo, manualRouteChange, stopRouterMonitor, shouldRecordUrl, setCustomHeaders, getCustomHeaders, setWhiteListUrls, setBlackListUrls, getBlackListUrls, getWhiteListUrls, getSdkLogEndpoint, reportError, cleanupErrorHandler, debug, };
|
|
65
38
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,WAAW,CAAC;AAInB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,WAAW,CAAC;AAInB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAgB,SAAS,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAmB,MAAM,aAAa,CAAC;AAQnE,KAAK,MAAM,GAAG;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,iBAAS,IAAI,CAAC,KAAK,EAAE,MAAM;uBAQL;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE;EAQ5C;AAED,iBAAS,YAAY,CAAC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,QAS1D;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAMpD;AAED,iBAAS,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAEjD;AAED,iBAAS,iBAAiB,IAAI,OAAO,CAKpC;AAED,iBAAS,qBAAqB,IAAI,OAAO,CAIxC;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CA6BhD;AAED,QAAA,MAAM,KAAK;6BACgB,MAAM;;;;;;;;;;;CAgBhC,CAAC;AAGF,OAAO,EAEL,IAAI,EACJ,YAAY,EAEZ,cAAc,EAEd,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EAErB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAEjB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAEjB,WAAW,EACX,mBAAmB,EAEnB,KAAK,GACN,CAAC"}
|