@arms/rum-core 0.1.2 → 0.1.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.
- package/es/index.d.ts +1 -0
- package/es/index.js +1 -0
- package/es/model/configManager.js +16 -16
- package/es/model/context.d.ts +2 -0
- package/es/model/context.js +2 -0
- package/es/model/reporter.js +11 -11
- package/es/types/client.d.ts +12 -3
- package/es/types/rum-event.d.ts +75 -3
- package/es/types/rum-event.js +3 -0
- package/es/utils/base.d.ts +0 -11
- package/es/utils/base.js +26 -27
- package/es/utils/events.d.ts +1 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +7 -0
- package/lib/model/configManager.js +16 -16
- package/lib/model/context.d.ts +2 -0
- package/lib/model/context.js +2 -0
- package/lib/model/reporter.js +11 -11
- package/lib/types/client.d.ts +12 -3
- package/lib/types/rum-event.d.ts +75 -3
- package/lib/types/rum-event.js +1 -0
- package/lib/utils/base.d.ts +0 -11
- package/lib/utils/base.js +26 -29
- package/lib/utils/events.d.ts +1 -2
- package/package.json +1 -1
package/es/index.d.ts
CHANGED
package/es/index.js
CHANGED
|
@@ -32,38 +32,38 @@ export var ConfigManager = /*#__PURE__*/function () {
|
|
|
32
32
|
var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(config) {
|
|
33
33
|
var _this = this;
|
|
34
34
|
var remoteConfig, cacheConfig, asyncConfigPromise;
|
|
35
|
-
return _regeneratorRuntime.wrap(function
|
|
35
|
+
return _regeneratorRuntime.wrap(function (_context) {
|
|
36
36
|
while (1) switch (_context.prev = _context.next) {
|
|
37
37
|
case 0:
|
|
38
38
|
if (!this.initialized) {
|
|
39
|
-
_context.next =
|
|
39
|
+
_context.next = 1;
|
|
40
40
|
break;
|
|
41
41
|
}
|
|
42
42
|
return _context.abrupt("return");
|
|
43
|
-
case
|
|
43
|
+
case 1:
|
|
44
44
|
this.currentConfig = _extends({}, config);
|
|
45
45
|
this.initialized = true;
|
|
46
46
|
remoteConfig = parseRemoteConfig(config);
|
|
47
47
|
this.currentConfig.remoteConfig = remoteConfig;
|
|
48
48
|
if (remoteConfig.enable) {
|
|
49
|
-
_context.next =
|
|
49
|
+
_context.next = 2;
|
|
50
50
|
break;
|
|
51
51
|
}
|
|
52
52
|
return _context.abrupt("return");
|
|
53
|
-
case
|
|
54
|
-
_context.next =
|
|
53
|
+
case 2:
|
|
54
|
+
_context.next = 3;
|
|
55
55
|
return this.getCacheConfig();
|
|
56
|
-
case
|
|
56
|
+
case 3:
|
|
57
57
|
cacheConfig = _context.sent;
|
|
58
58
|
if (cacheConfig && cacheConfig.content) {
|
|
59
59
|
this.currentConfig = this.mergeRemoteCfg(cacheConfig.content);
|
|
60
60
|
}
|
|
61
61
|
if (!this.isCacheValid(cacheConfig, remoteConfig.cacheTimeout)) {
|
|
62
|
-
_context.next =
|
|
62
|
+
_context.next = 4;
|
|
63
63
|
break;
|
|
64
64
|
}
|
|
65
65
|
return _context.abrupt("return");
|
|
66
|
-
case
|
|
66
|
+
case 4:
|
|
67
67
|
asyncConfigPromise = this.fetchRemoteCfg(this.currentConfig).then(function (resp) {
|
|
68
68
|
if (!resp) return;
|
|
69
69
|
var asyncRemoteConfig = _this.parseConfig(resp);
|
|
@@ -74,12 +74,12 @@ export var ConfigManager = /*#__PURE__*/function () {
|
|
|
74
74
|
});
|
|
75
75
|
});
|
|
76
76
|
if (!(remoteConfig.mode === 'remote-first')) {
|
|
77
|
-
_context.next =
|
|
77
|
+
_context.next = 5;
|
|
78
78
|
break;
|
|
79
79
|
}
|
|
80
|
-
_context.next =
|
|
80
|
+
_context.next = 5;
|
|
81
81
|
return asyncConfigPromise;
|
|
82
|
-
case
|
|
82
|
+
case 5:
|
|
83
83
|
case "end":
|
|
84
84
|
return _context.stop();
|
|
85
85
|
}
|
|
@@ -110,17 +110,17 @@ export var ConfigManager = /*#__PURE__*/function () {
|
|
|
110
110
|
/*#__PURE__*/
|
|
111
111
|
function () {
|
|
112
112
|
var _setConfig = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(config) {
|
|
113
|
-
return _regeneratorRuntime.wrap(function
|
|
113
|
+
return _regeneratorRuntime.wrap(function (_context2) {
|
|
114
114
|
while (1) switch (_context2.prev = _context2.next) {
|
|
115
115
|
case 0:
|
|
116
116
|
if (this.currentConfig) {
|
|
117
|
-
_context2.next =
|
|
117
|
+
_context2.next = 1;
|
|
118
118
|
break;
|
|
119
119
|
}
|
|
120
120
|
return _context2.abrupt("return");
|
|
121
|
-
case
|
|
121
|
+
case 1:
|
|
122
122
|
this.currentConfig = _extends({}, this.currentConfig, config);
|
|
123
|
-
case
|
|
123
|
+
case 2:
|
|
124
124
|
case "end":
|
|
125
125
|
return _context2.stop();
|
|
126
126
|
}
|
package/es/model/context.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { IConfiguration, IContext, IRumSession } from "../types/client";
|
|
2
2
|
import { RumEvent, IViewData } from "../types/rum-event";
|
|
3
3
|
import { IConfigManager } from "../types/config";
|
|
4
|
+
import { EventEmitter } from "../utils/events";
|
|
4
5
|
declare class Context implements IContext {
|
|
5
6
|
private config;
|
|
6
7
|
private rumEvent;
|
|
7
8
|
private views;
|
|
9
|
+
emitter: EventEmitter;
|
|
8
10
|
session: IRumSession;
|
|
9
11
|
configManager: IConfigManager;
|
|
10
12
|
constructor(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager);
|
package/es/model/context.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { EventEmitter } from "../utils/events";
|
|
1
2
|
var Context = /*#__PURE__*/function () {
|
|
2
3
|
function Context(config, rumSession, configManager) {
|
|
3
4
|
this.config = config;
|
|
4
5
|
this.rumEvent = void 0;
|
|
5
6
|
this.views = [];
|
|
7
|
+
this.emitter = new EventEmitter();
|
|
6
8
|
this.session = void 0;
|
|
7
9
|
this.configManager = void 0;
|
|
8
10
|
if (rumSession) {
|
package/es/model/reporter.js
CHANGED
|
@@ -193,8 +193,8 @@ var Reporter = /*#__PURE__*/function () {
|
|
|
193
193
|
_reportConfig$maxRetr,
|
|
194
194
|
_reportConfig$retryDe,
|
|
195
195
|
_this2 = this;
|
|
196
|
-
var reportConfig, maxRetryCount, retryDelay;
|
|
197
|
-
return _regeneratorRuntime.wrap(function
|
|
196
|
+
var reportConfig, maxRetryCount, retryDelay, _t;
|
|
197
|
+
return _regeneratorRuntime.wrap(function (_context) {
|
|
198
198
|
while (1) switch (_context.prev = _context.next) {
|
|
199
199
|
case 0:
|
|
200
200
|
if (retry === void 0) {
|
|
@@ -203,26 +203,26 @@ var Reporter = /*#__PURE__*/function () {
|
|
|
203
203
|
reportConfig = (_this$ctx$getConfig = this.ctx.getConfig()) === null || _this$ctx$getConfig === void 0 ? void 0 : _this$ctx$getConfig.reportConfig;
|
|
204
204
|
maxRetryCount = (_reportConfig$maxRetr = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.maxRetryCount) !== null && _reportConfig$maxRetr !== void 0 ? _reportConfig$maxRetr : 0;
|
|
205
205
|
retryDelay = (_reportConfig$retryDe = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.retryDelay) !== null && _reportConfig$retryDe !== void 0 ? _reportConfig$retryDe : 3000;
|
|
206
|
-
_context.prev =
|
|
206
|
+
_context.prev = 1;
|
|
207
207
|
bundle._retry = retry;
|
|
208
|
-
_context.next =
|
|
208
|
+
_context.next = 2;
|
|
209
209
|
return this.request(this.ctx, bundle);
|
|
210
|
-
case
|
|
211
|
-
_context.next =
|
|
210
|
+
case 2:
|
|
211
|
+
_context.next = 4;
|
|
212
212
|
break;
|
|
213
|
-
case
|
|
214
|
-
_context.prev =
|
|
215
|
-
|
|
213
|
+
case 3:
|
|
214
|
+
_context.prev = 3;
|
|
215
|
+
_t = _context["catch"](1);
|
|
216
216
|
if (retry < maxRetryCount - 1) {
|
|
217
217
|
setTimeout(function () {
|
|
218
218
|
return _this2.tryRequest(bundle, retry + 1);
|
|
219
219
|
}, retryDelay);
|
|
220
220
|
}
|
|
221
|
-
case
|
|
221
|
+
case 4:
|
|
222
222
|
case "end":
|
|
223
223
|
return _context.stop();
|
|
224
224
|
}
|
|
225
|
-
}, _callee, this, [[
|
|
225
|
+
}, _callee, this, [[1, 3]]);
|
|
226
226
|
}));
|
|
227
227
|
function tryRequest(_x, _x2) {
|
|
228
228
|
return _tryRequest.apply(this, arguments);
|
package/es/types/client.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import { ICollector } from './collector';
|
|
|
2
2
|
import { IProcessor } from './processor';
|
|
3
3
|
import { IReporter } from './reporter';
|
|
4
4
|
import { RumEvent, RumEventBundle, IViewData } from './rum-event';
|
|
5
|
-
import { MatchOption } from
|
|
6
|
-
import { IConfigManager } from
|
|
5
|
+
import { MatchOption } from '../utils/match';
|
|
6
|
+
import { IConfigManager } from './config';
|
|
7
|
+
import { EventEmitter } from '../utils/events';
|
|
7
8
|
export declare enum EventType {
|
|
8
9
|
/**
|
|
9
10
|
* 收集数据
|
|
@@ -12,6 +13,7 @@ export declare enum EventType {
|
|
|
12
13
|
}
|
|
13
14
|
export interface IContext {
|
|
14
15
|
session: IRumSession;
|
|
16
|
+
emitter: EventEmitter;
|
|
15
17
|
/**
|
|
16
18
|
* user config
|
|
17
19
|
*/
|
|
@@ -90,7 +92,7 @@ export interface IRemoteConfig {
|
|
|
90
92
|
[key: string]: unknown;
|
|
91
93
|
}
|
|
92
94
|
export interface ICollectorConfig {
|
|
93
|
-
name
|
|
95
|
+
name?: string;
|
|
94
96
|
enable?: boolean;
|
|
95
97
|
sampling?: number;
|
|
96
98
|
filters?: MatchOption[];
|
|
@@ -218,5 +220,12 @@ export interface IConfiguration {
|
|
|
218
220
|
* 检测正则匹配内容
|
|
219
221
|
*/
|
|
220
222
|
regexp?: string;
|
|
223
|
+
/**
|
|
224
|
+
* 检测元素是否包含特定属性或者属性值的元素,支持正则匹配
|
|
225
|
+
*/
|
|
226
|
+
attributeRules?: Array<{
|
|
227
|
+
attributeName: string;
|
|
228
|
+
attributeValue?: Array<string | RegExp> | null;
|
|
229
|
+
}>;
|
|
221
230
|
[key: string]: unknown;
|
|
222
231
|
}
|
package/es/types/rum-event.d.ts
CHANGED
|
@@ -10,9 +10,11 @@ export declare enum RumEventType {
|
|
|
10
10
|
export interface BaseObject {
|
|
11
11
|
[key: string]: BaseObjectValue;
|
|
12
12
|
}
|
|
13
|
-
export
|
|
13
|
+
export type loading_type = 'initial_load' | 'route_change';
|
|
14
|
+
export interface IViewData extends BaseObject {
|
|
14
15
|
id: string;
|
|
15
16
|
name: string;
|
|
17
|
+
loading_type?: loading_type;
|
|
16
18
|
}
|
|
17
19
|
export type BaseObjectPrimitiveValue = string | number | boolean | null | undefined;
|
|
18
20
|
export type BaseObjectValue = BaseObjectPrimitiveValue | BaseObject | BaseObjectPrimitiveValue[] | IViewData;
|
|
@@ -26,27 +28,64 @@ export interface RumBaseEvent extends BaseObject {
|
|
|
26
28
|
snapshots?: string;
|
|
27
29
|
properties?: BaseObject;
|
|
28
30
|
}
|
|
31
|
+
/** 事件类型:页面浏览、性能指标、Web Vitals、自定义指标、会话回放 */
|
|
32
|
+
export type view_type = 'pv' | 'perf' | 'webvitals' | 'custom' | 'replay' | 'view-stats';
|
|
29
33
|
export interface RumViewEvent extends RumBaseEvent {
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
/** 页面加载类型:初始加载或路由切换 */
|
|
35
|
+
loading_type?: loading_type;
|
|
36
|
+
type: view_type;
|
|
37
|
+
/** 最大内容绘制时间 (LCP) - 页面加载过程中最大文本块或图像元素的渲染时间 */
|
|
32
38
|
largest_contentful_paint?: number;
|
|
39
|
+
/** 首次输入延迟 (FID) - 用户首次与页面交互到浏览器响应该交互的时间 */
|
|
33
40
|
first_input_delay?: number;
|
|
41
|
+
/** 累积布局偏移 (CLS) - 页面可见元素意外移动的累积分数 */
|
|
34
42
|
cumulative_layout_shift?: number;
|
|
43
|
+
/** 首次输入时间 (FIT) - 用户首次与页面交互的时间戳 */
|
|
35
44
|
first_input_time?: number;
|
|
45
|
+
/** 页面加载时间 - 从开始加载到页面完全加载的时间 */
|
|
36
46
|
loading_time?: number;
|
|
47
|
+
/** 首次绘制时间 (FP) - 浏览器首次渲染任何内容的时间 */
|
|
37
48
|
first_paint?: number;
|
|
49
|
+
/** 首次内容绘制时间 (FCP) - 浏览器首次渲染DOM内容的时间 */
|
|
38
50
|
first_contentful_paint?: number;
|
|
51
|
+
/** DOM 交互时间 - DOM 构建完成且脚本开始执行的时间 */
|
|
39
52
|
dom_interactive?: number;
|
|
53
|
+
/** DOM 内容加载完成时间 - DOM 和所有子资源加载完成的时间 */
|
|
40
54
|
dom_content_loaded?: number;
|
|
55
|
+
/** DOM 完成时间 - 页面及其所有资源加载完成的时间 */
|
|
41
56
|
dom_complete?: number;
|
|
57
|
+
/** 加载事件时间 - load 事件触发的时间 */
|
|
42
58
|
load_event?: number;
|
|
59
|
+
/** 自定义性能指标 T1 */
|
|
43
60
|
t1?: number;
|
|
61
|
+
/** 自定义性能指标 T2 */
|
|
44
62
|
t2?: number;
|
|
63
|
+
/** 自定义性能指标 T3 */
|
|
45
64
|
t3?: number;
|
|
65
|
+
/** 来源页面 URL */
|
|
46
66
|
referrer?: string;
|
|
67
|
+
/** 当前页面 URL */
|
|
47
68
|
url?: string;
|
|
69
|
+
/** 性能时序数据 (JSON 字符串格式) */
|
|
48
70
|
timing_data?: string;
|
|
49
71
|
}
|
|
72
|
+
export interface RumReplayEvent extends RumBaseEvent {
|
|
73
|
+
type: 'replay';
|
|
74
|
+
/** 当前Records记录的结束时间 */
|
|
75
|
+
records_end?: number;
|
|
76
|
+
/** 会话回放片段索引 */
|
|
77
|
+
records_index?: number;
|
|
78
|
+
/** 当前会话包含的record数量 */
|
|
79
|
+
records_count?: number;
|
|
80
|
+
/** 创建record原因 */
|
|
81
|
+
records_reason?: string;
|
|
82
|
+
/** 包含的replay数据大小 */
|
|
83
|
+
records_size?: number;
|
|
84
|
+
/** 是否包含完整的Snapshot */
|
|
85
|
+
has_full_snapshot?: number;
|
|
86
|
+
/** 上报的录屏数据 */
|
|
87
|
+
records_data?: string;
|
|
88
|
+
}
|
|
50
89
|
/**
|
|
51
90
|
* 枚举值,表示资源是否加载成功
|
|
52
91
|
*/
|
|
@@ -96,10 +135,43 @@ export interface RumLongTaskEvent extends RumBaseEvent {
|
|
|
96
135
|
snapshots: string;
|
|
97
136
|
}
|
|
98
137
|
export interface RumActionEvent extends RumBaseEvent {
|
|
138
|
+
event_type: RumEventType.ACTION;
|
|
139
|
+
/** 行为类型 */
|
|
99
140
|
type?: string;
|
|
141
|
+
/** 行为名称 */
|
|
100
142
|
name?: string;
|
|
143
|
+
/** 目标元素名称XPath */
|
|
101
144
|
target_name?: string;
|
|
145
|
+
/** 操作持续时间(毫秒) */
|
|
102
146
|
duration?: number;
|
|
147
|
+
/**
|
|
148
|
+
* Heatmap Analysis - 热力图分析
|
|
149
|
+
* 当 trackUserInteractions 开启时才会采集以下数据
|
|
150
|
+
* */
|
|
151
|
+
/** 点击位置信息 */
|
|
152
|
+
position?: {
|
|
153
|
+
/** 点击 X 坐标(相对于文档) */
|
|
154
|
+
x?: number;
|
|
155
|
+
/** 点击 Y 坐标(相对于文档) */
|
|
156
|
+
y?: number;
|
|
157
|
+
/** 元素内相对 X 坐标 */
|
|
158
|
+
ex?: number;
|
|
159
|
+
/** 元素内相对 Y 坐标 */
|
|
160
|
+
ey?: number;
|
|
161
|
+
};
|
|
162
|
+
/** 目标元素信息 */
|
|
163
|
+
target?: {
|
|
164
|
+
/** 元素的 selector:#root > div > button:nth-child(15) */
|
|
165
|
+
selector?: string;
|
|
166
|
+
/** 元素的宽度(像素) */
|
|
167
|
+
width?: number;
|
|
168
|
+
/** 元素的高度(像素) */
|
|
169
|
+
height?: number;
|
|
170
|
+
/** 是否为可交互元素(0=不可交互, 1=可交互),用于无效点击分析 */
|
|
171
|
+
reaction?: number;
|
|
172
|
+
/** 是否可信的交互(0=不可信, 1=可信),用于错误点击分析 */
|
|
173
|
+
trust?: number;
|
|
174
|
+
};
|
|
103
175
|
}
|
|
104
176
|
export interface RumCustomEvent extends RumBaseEvent {
|
|
105
177
|
type: string;
|
package/es/types/rum-event.js
CHANGED
package/es/utils/base.d.ts
CHANGED
|
@@ -41,17 +41,6 @@ export declare function debounce(func: Function, wait: number): () => void;
|
|
|
41
41
|
* @param wait 延迟执行毫秒数
|
|
42
42
|
*/
|
|
43
43
|
export declare function delay(func: Function, wait: number, ...args: any[]): number;
|
|
44
|
-
/**
|
|
45
|
-
* @desc 需要严格区分object和array
|
|
46
|
-
* @param obj 任意对象
|
|
47
|
-
*/
|
|
48
|
-
export declare function getType(obj: any): any;
|
|
49
|
-
/**
|
|
50
|
-
* @desc 将字符串转换成正则表达式
|
|
51
|
-
* @param str 任意字符串
|
|
52
|
-
* 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
|
|
53
|
-
*/
|
|
54
|
-
export declare function transStrToReg(str: string): string | RegExp;
|
|
55
44
|
/**
|
|
56
45
|
* 解析正则表达式字符串,支持 /pattern/flags 格式
|
|
57
46
|
* @param str 正则表达式字符串,如 "/a/ig" 或 "a"
|
package/es/utils/base.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { isFunction } from "./is";
|
|
2
2
|
|
|
3
|
-
// 类型匹配正则
|
|
4
|
-
var TYPE_REG = /^\[object ([a-z]*)\]$/;
|
|
5
|
-
|
|
6
3
|
/**
|
|
7
4
|
* 劫持函数或原型
|
|
8
5
|
*/
|
|
@@ -150,30 +147,32 @@ export function delay(func, wait) {
|
|
|
150
147
|
return setTimeout.apply(void 0, [func, +wait || 0].concat(args));
|
|
151
148
|
}
|
|
152
149
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
150
|
+
// // 类型匹配正则
|
|
151
|
+
// const TYPE_REG = /^\[object ([a-z]*)\]$/;
|
|
152
|
+
// /**
|
|
153
|
+
// * @desc 需要严格区分object和array
|
|
154
|
+
// * @param obj 任意对象
|
|
155
|
+
// */
|
|
156
|
+
// export function getType(obj: any) {
|
|
157
|
+
// let type = Object.prototype.toString.call(obj);
|
|
158
|
+
// type = type.toLowerCase() || '';
|
|
159
|
+
// const arr = type.match(TYPE_REG);
|
|
160
|
+
// return arr?.[1];
|
|
161
|
+
// }
|
|
162
|
+
//
|
|
163
|
+
// /**
|
|
164
|
+
// * @desc 将字符串转换成正则表达式
|
|
165
|
+
// * @param str 任意字符串
|
|
166
|
+
// * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
|
|
167
|
+
// */
|
|
168
|
+
// export function transStrToReg(str: string) {
|
|
169
|
+
// if (getType(str) !== 'string') return str;
|
|
170
|
+
// if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
|
|
171
|
+
// return new RegExp(str.substr(1, str.length - 2));
|
|
172
|
+
// }
|
|
173
|
+
// return str;
|
|
174
|
+
// }
|
|
175
|
+
//
|
|
177
176
|
// /**
|
|
178
177
|
// *
|
|
179
178
|
// * @param config 配置
|
package/es/utils/events.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type EventHandler = (...args: any[]) => void;
|
|
1
|
+
export type EventHandler = (...args: any[]) => void;
|
|
2
2
|
export declare class EventEmitter {
|
|
3
3
|
private events;
|
|
4
4
|
/**
|
|
@@ -26,4 +26,3 @@ export declare class EventEmitter {
|
|
|
26
26
|
*/
|
|
27
27
|
once(eventName: string, handler: EventHandler): void;
|
|
28
28
|
}
|
|
29
|
-
export {};
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -127,4 +127,11 @@ Object.keys(_url).forEach(function (key) {
|
|
|
127
127
|
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
128
128
|
if (key in exports && exports[key] === _url[key]) return;
|
|
129
129
|
exports[key] = _url[key];
|
|
130
|
+
});
|
|
131
|
+
var _events = require("./utils/events");
|
|
132
|
+
Object.keys(_events).forEach(function (key) {
|
|
133
|
+
if (key === "default" || key === "__esModule") return;
|
|
134
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
135
|
+
if (key in exports && exports[key] === _events[key]) return;
|
|
136
|
+
exports[key] = _events[key];
|
|
130
137
|
});
|
|
@@ -37,38 +37,38 @@ var ConfigManager = exports.ConfigManager = /*#__PURE__*/function () {
|
|
|
37
37
|
var _init = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(config) {
|
|
38
38
|
var _this = this;
|
|
39
39
|
var remoteConfig, cacheConfig, asyncConfigPromise;
|
|
40
|
-
return _regenerator["default"].wrap(function
|
|
40
|
+
return _regenerator["default"].wrap(function (_context) {
|
|
41
41
|
while (1) switch (_context.prev = _context.next) {
|
|
42
42
|
case 0:
|
|
43
43
|
if (!this.initialized) {
|
|
44
|
-
_context.next =
|
|
44
|
+
_context.next = 1;
|
|
45
45
|
break;
|
|
46
46
|
}
|
|
47
47
|
return _context.abrupt("return");
|
|
48
|
-
case
|
|
48
|
+
case 1:
|
|
49
49
|
this.currentConfig = (0, _extends2["default"])({}, config);
|
|
50
50
|
this.initialized = true;
|
|
51
51
|
remoteConfig = parseRemoteConfig(config);
|
|
52
52
|
this.currentConfig.remoteConfig = remoteConfig;
|
|
53
53
|
if (remoteConfig.enable) {
|
|
54
|
-
_context.next =
|
|
54
|
+
_context.next = 2;
|
|
55
55
|
break;
|
|
56
56
|
}
|
|
57
57
|
return _context.abrupt("return");
|
|
58
|
-
case
|
|
59
|
-
_context.next =
|
|
58
|
+
case 2:
|
|
59
|
+
_context.next = 3;
|
|
60
60
|
return this.getCacheConfig();
|
|
61
|
-
case
|
|
61
|
+
case 3:
|
|
62
62
|
cacheConfig = _context.sent;
|
|
63
63
|
if (cacheConfig && cacheConfig.content) {
|
|
64
64
|
this.currentConfig = this.mergeRemoteCfg(cacheConfig.content);
|
|
65
65
|
}
|
|
66
66
|
if (!this.isCacheValid(cacheConfig, remoteConfig.cacheTimeout)) {
|
|
67
|
-
_context.next =
|
|
67
|
+
_context.next = 4;
|
|
68
68
|
break;
|
|
69
69
|
}
|
|
70
70
|
return _context.abrupt("return");
|
|
71
|
-
case
|
|
71
|
+
case 4:
|
|
72
72
|
asyncConfigPromise = this.fetchRemoteCfg(this.currentConfig).then(function (resp) {
|
|
73
73
|
if (!resp) return;
|
|
74
74
|
var asyncRemoteConfig = _this.parseConfig(resp);
|
|
@@ -79,12 +79,12 @@ var ConfigManager = exports.ConfigManager = /*#__PURE__*/function () {
|
|
|
79
79
|
});
|
|
80
80
|
});
|
|
81
81
|
if (!(remoteConfig.mode === 'remote-first')) {
|
|
82
|
-
_context.next =
|
|
82
|
+
_context.next = 5;
|
|
83
83
|
break;
|
|
84
84
|
}
|
|
85
|
-
_context.next =
|
|
85
|
+
_context.next = 5;
|
|
86
86
|
return asyncConfigPromise;
|
|
87
|
-
case
|
|
87
|
+
case 5:
|
|
88
88
|
case "end":
|
|
89
89
|
return _context.stop();
|
|
90
90
|
}
|
|
@@ -115,17 +115,17 @@ var ConfigManager = exports.ConfigManager = /*#__PURE__*/function () {
|
|
|
115
115
|
/*#__PURE__*/
|
|
116
116
|
function () {
|
|
117
117
|
var _setConfig = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(config) {
|
|
118
|
-
return _regenerator["default"].wrap(function
|
|
118
|
+
return _regenerator["default"].wrap(function (_context2) {
|
|
119
119
|
while (1) switch (_context2.prev = _context2.next) {
|
|
120
120
|
case 0:
|
|
121
121
|
if (this.currentConfig) {
|
|
122
|
-
_context2.next =
|
|
122
|
+
_context2.next = 1;
|
|
123
123
|
break;
|
|
124
124
|
}
|
|
125
125
|
return _context2.abrupt("return");
|
|
126
|
-
case
|
|
126
|
+
case 1:
|
|
127
127
|
this.currentConfig = (0, _extends2["default"])({}, this.currentConfig, config);
|
|
128
|
-
case
|
|
128
|
+
case 2:
|
|
129
129
|
case "end":
|
|
130
130
|
return _context2.stop();
|
|
131
131
|
}
|
package/lib/model/context.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { IConfiguration, IContext, IRumSession } from "../types/client";
|
|
2
2
|
import { RumEvent, IViewData } from "../types/rum-event";
|
|
3
3
|
import { IConfigManager } from "../types/config";
|
|
4
|
+
import { EventEmitter } from "../utils/events";
|
|
4
5
|
declare class Context implements IContext {
|
|
5
6
|
private config;
|
|
6
7
|
private rumEvent;
|
|
7
8
|
private views;
|
|
9
|
+
emitter: EventEmitter;
|
|
8
10
|
session: IRumSession;
|
|
9
11
|
configManager: IConfigManager;
|
|
10
12
|
constructor(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager);
|
package/lib/model/context.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports["default"] = void 0;
|
|
5
|
+
var _events = require("../utils/events");
|
|
5
6
|
var Context = /*#__PURE__*/function () {
|
|
6
7
|
function Context(config, rumSession, configManager) {
|
|
7
8
|
this.config = config;
|
|
8
9
|
this.rumEvent = void 0;
|
|
9
10
|
this.views = [];
|
|
11
|
+
this.emitter = new _events.EventEmitter();
|
|
10
12
|
this.session = void 0;
|
|
11
13
|
this.configManager = void 0;
|
|
12
14
|
if (rumSession) {
|
package/lib/model/reporter.js
CHANGED
|
@@ -198,8 +198,8 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
|
|
|
198
198
|
_reportConfig$maxRetr,
|
|
199
199
|
_reportConfig$retryDe,
|
|
200
200
|
_this2 = this;
|
|
201
|
-
var reportConfig, maxRetryCount, retryDelay;
|
|
202
|
-
return _regenerator["default"].wrap(function
|
|
201
|
+
var reportConfig, maxRetryCount, retryDelay, _t;
|
|
202
|
+
return _regenerator["default"].wrap(function (_context) {
|
|
203
203
|
while (1) switch (_context.prev = _context.next) {
|
|
204
204
|
case 0:
|
|
205
205
|
if (retry === void 0) {
|
|
@@ -208,26 +208,26 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
|
|
|
208
208
|
reportConfig = (_this$ctx$getConfig = this.ctx.getConfig()) === null || _this$ctx$getConfig === void 0 ? void 0 : _this$ctx$getConfig.reportConfig;
|
|
209
209
|
maxRetryCount = (_reportConfig$maxRetr = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.maxRetryCount) !== null && _reportConfig$maxRetr !== void 0 ? _reportConfig$maxRetr : 0;
|
|
210
210
|
retryDelay = (_reportConfig$retryDe = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.retryDelay) !== null && _reportConfig$retryDe !== void 0 ? _reportConfig$retryDe : 3000;
|
|
211
|
-
_context.prev =
|
|
211
|
+
_context.prev = 1;
|
|
212
212
|
bundle._retry = retry;
|
|
213
|
-
_context.next =
|
|
213
|
+
_context.next = 2;
|
|
214
214
|
return this.request(this.ctx, bundle);
|
|
215
|
-
case
|
|
216
|
-
_context.next =
|
|
215
|
+
case 2:
|
|
216
|
+
_context.next = 4;
|
|
217
217
|
break;
|
|
218
|
-
case
|
|
219
|
-
_context.prev =
|
|
220
|
-
|
|
218
|
+
case 3:
|
|
219
|
+
_context.prev = 3;
|
|
220
|
+
_t = _context["catch"](1);
|
|
221
221
|
if (retry < maxRetryCount - 1) {
|
|
222
222
|
setTimeout(function () {
|
|
223
223
|
return _this2.tryRequest(bundle, retry + 1);
|
|
224
224
|
}, retryDelay);
|
|
225
225
|
}
|
|
226
|
-
case
|
|
226
|
+
case 4:
|
|
227
227
|
case "end":
|
|
228
228
|
return _context.stop();
|
|
229
229
|
}
|
|
230
|
-
}, _callee, this, [[
|
|
230
|
+
}, _callee, this, [[1, 3]]);
|
|
231
231
|
}));
|
|
232
232
|
function tryRequest(_x, _x2) {
|
|
233
233
|
return _tryRequest.apply(this, arguments);
|
package/lib/types/client.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import { ICollector } from './collector';
|
|
|
2
2
|
import { IProcessor } from './processor';
|
|
3
3
|
import { IReporter } from './reporter';
|
|
4
4
|
import { RumEvent, RumEventBundle, IViewData } from './rum-event';
|
|
5
|
-
import { MatchOption } from
|
|
6
|
-
import { IConfigManager } from
|
|
5
|
+
import { MatchOption } from '../utils/match';
|
|
6
|
+
import { IConfigManager } from './config';
|
|
7
|
+
import { EventEmitter } from '../utils/events';
|
|
7
8
|
export declare enum EventType {
|
|
8
9
|
/**
|
|
9
10
|
* 收集数据
|
|
@@ -12,6 +13,7 @@ export declare enum EventType {
|
|
|
12
13
|
}
|
|
13
14
|
export interface IContext {
|
|
14
15
|
session: IRumSession;
|
|
16
|
+
emitter: EventEmitter;
|
|
15
17
|
/**
|
|
16
18
|
* user config
|
|
17
19
|
*/
|
|
@@ -90,7 +92,7 @@ export interface IRemoteConfig {
|
|
|
90
92
|
[key: string]: unknown;
|
|
91
93
|
}
|
|
92
94
|
export interface ICollectorConfig {
|
|
93
|
-
name
|
|
95
|
+
name?: string;
|
|
94
96
|
enable?: boolean;
|
|
95
97
|
sampling?: number;
|
|
96
98
|
filters?: MatchOption[];
|
|
@@ -218,5 +220,12 @@ export interface IConfiguration {
|
|
|
218
220
|
* 检测正则匹配内容
|
|
219
221
|
*/
|
|
220
222
|
regexp?: string;
|
|
223
|
+
/**
|
|
224
|
+
* 检测元素是否包含特定属性或者属性值的元素,支持正则匹配
|
|
225
|
+
*/
|
|
226
|
+
attributeRules?: Array<{
|
|
227
|
+
attributeName: string;
|
|
228
|
+
attributeValue?: Array<string | RegExp> | null;
|
|
229
|
+
}>;
|
|
221
230
|
[key: string]: unknown;
|
|
222
231
|
}
|
package/lib/types/rum-event.d.ts
CHANGED
|
@@ -10,9 +10,11 @@ export declare enum RumEventType {
|
|
|
10
10
|
export interface BaseObject {
|
|
11
11
|
[key: string]: BaseObjectValue;
|
|
12
12
|
}
|
|
13
|
-
export
|
|
13
|
+
export type loading_type = 'initial_load' | 'route_change';
|
|
14
|
+
export interface IViewData extends BaseObject {
|
|
14
15
|
id: string;
|
|
15
16
|
name: string;
|
|
17
|
+
loading_type?: loading_type;
|
|
16
18
|
}
|
|
17
19
|
export type BaseObjectPrimitiveValue = string | number | boolean | null | undefined;
|
|
18
20
|
export type BaseObjectValue = BaseObjectPrimitiveValue | BaseObject | BaseObjectPrimitiveValue[] | IViewData;
|
|
@@ -26,27 +28,64 @@ export interface RumBaseEvent extends BaseObject {
|
|
|
26
28
|
snapshots?: string;
|
|
27
29
|
properties?: BaseObject;
|
|
28
30
|
}
|
|
31
|
+
/** 事件类型:页面浏览、性能指标、Web Vitals、自定义指标、会话回放 */
|
|
32
|
+
export type view_type = 'pv' | 'perf' | 'webvitals' | 'custom' | 'replay' | 'view-stats';
|
|
29
33
|
export interface RumViewEvent extends RumBaseEvent {
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
/** 页面加载类型:初始加载或路由切换 */
|
|
35
|
+
loading_type?: loading_type;
|
|
36
|
+
type: view_type;
|
|
37
|
+
/** 最大内容绘制时间 (LCP) - 页面加载过程中最大文本块或图像元素的渲染时间 */
|
|
32
38
|
largest_contentful_paint?: number;
|
|
39
|
+
/** 首次输入延迟 (FID) - 用户首次与页面交互到浏览器响应该交互的时间 */
|
|
33
40
|
first_input_delay?: number;
|
|
41
|
+
/** 累积布局偏移 (CLS) - 页面可见元素意外移动的累积分数 */
|
|
34
42
|
cumulative_layout_shift?: number;
|
|
43
|
+
/** 首次输入时间 (FIT) - 用户首次与页面交互的时间戳 */
|
|
35
44
|
first_input_time?: number;
|
|
45
|
+
/** 页面加载时间 - 从开始加载到页面完全加载的时间 */
|
|
36
46
|
loading_time?: number;
|
|
47
|
+
/** 首次绘制时间 (FP) - 浏览器首次渲染任何内容的时间 */
|
|
37
48
|
first_paint?: number;
|
|
49
|
+
/** 首次内容绘制时间 (FCP) - 浏览器首次渲染DOM内容的时间 */
|
|
38
50
|
first_contentful_paint?: number;
|
|
51
|
+
/** DOM 交互时间 - DOM 构建完成且脚本开始执行的时间 */
|
|
39
52
|
dom_interactive?: number;
|
|
53
|
+
/** DOM 内容加载完成时间 - DOM 和所有子资源加载完成的时间 */
|
|
40
54
|
dom_content_loaded?: number;
|
|
55
|
+
/** DOM 完成时间 - 页面及其所有资源加载完成的时间 */
|
|
41
56
|
dom_complete?: number;
|
|
57
|
+
/** 加载事件时间 - load 事件触发的时间 */
|
|
42
58
|
load_event?: number;
|
|
59
|
+
/** 自定义性能指标 T1 */
|
|
43
60
|
t1?: number;
|
|
61
|
+
/** 自定义性能指标 T2 */
|
|
44
62
|
t2?: number;
|
|
63
|
+
/** 自定义性能指标 T3 */
|
|
45
64
|
t3?: number;
|
|
65
|
+
/** 来源页面 URL */
|
|
46
66
|
referrer?: string;
|
|
67
|
+
/** 当前页面 URL */
|
|
47
68
|
url?: string;
|
|
69
|
+
/** 性能时序数据 (JSON 字符串格式) */
|
|
48
70
|
timing_data?: string;
|
|
49
71
|
}
|
|
72
|
+
export interface RumReplayEvent extends RumBaseEvent {
|
|
73
|
+
type: 'replay';
|
|
74
|
+
/** 当前Records记录的结束时间 */
|
|
75
|
+
records_end?: number;
|
|
76
|
+
/** 会话回放片段索引 */
|
|
77
|
+
records_index?: number;
|
|
78
|
+
/** 当前会话包含的record数量 */
|
|
79
|
+
records_count?: number;
|
|
80
|
+
/** 创建record原因 */
|
|
81
|
+
records_reason?: string;
|
|
82
|
+
/** 包含的replay数据大小 */
|
|
83
|
+
records_size?: number;
|
|
84
|
+
/** 是否包含完整的Snapshot */
|
|
85
|
+
has_full_snapshot?: number;
|
|
86
|
+
/** 上报的录屏数据 */
|
|
87
|
+
records_data?: string;
|
|
88
|
+
}
|
|
50
89
|
/**
|
|
51
90
|
* 枚举值,表示资源是否加载成功
|
|
52
91
|
*/
|
|
@@ -96,10 +135,43 @@ export interface RumLongTaskEvent extends RumBaseEvent {
|
|
|
96
135
|
snapshots: string;
|
|
97
136
|
}
|
|
98
137
|
export interface RumActionEvent extends RumBaseEvent {
|
|
138
|
+
event_type: RumEventType.ACTION;
|
|
139
|
+
/** 行为类型 */
|
|
99
140
|
type?: string;
|
|
141
|
+
/** 行为名称 */
|
|
100
142
|
name?: string;
|
|
143
|
+
/** 目标元素名称XPath */
|
|
101
144
|
target_name?: string;
|
|
145
|
+
/** 操作持续时间(毫秒) */
|
|
102
146
|
duration?: number;
|
|
147
|
+
/**
|
|
148
|
+
* Heatmap Analysis - 热力图分析
|
|
149
|
+
* 当 trackUserInteractions 开启时才会采集以下数据
|
|
150
|
+
* */
|
|
151
|
+
/** 点击位置信息 */
|
|
152
|
+
position?: {
|
|
153
|
+
/** 点击 X 坐标(相对于文档) */
|
|
154
|
+
x?: number;
|
|
155
|
+
/** 点击 Y 坐标(相对于文档) */
|
|
156
|
+
y?: number;
|
|
157
|
+
/** 元素内相对 X 坐标 */
|
|
158
|
+
ex?: number;
|
|
159
|
+
/** 元素内相对 Y 坐标 */
|
|
160
|
+
ey?: number;
|
|
161
|
+
};
|
|
162
|
+
/** 目标元素信息 */
|
|
163
|
+
target?: {
|
|
164
|
+
/** 元素的 selector:#root > div > button:nth-child(15) */
|
|
165
|
+
selector?: string;
|
|
166
|
+
/** 元素的宽度(像素) */
|
|
167
|
+
width?: number;
|
|
168
|
+
/** 元素的高度(像素) */
|
|
169
|
+
height?: number;
|
|
170
|
+
/** 是否为可交互元素(0=不可交互, 1=可交互),用于无效点击分析 */
|
|
171
|
+
reaction?: number;
|
|
172
|
+
/** 是否可信的交互(0=不可信, 1=可信),用于错误点击分析 */
|
|
173
|
+
trust?: number;
|
|
174
|
+
};
|
|
103
175
|
}
|
|
104
176
|
export interface RumCustomEvent extends RumBaseEvent {
|
|
105
177
|
type: string;
|
package/lib/types/rum-event.js
CHANGED
package/lib/utils/base.d.ts
CHANGED
|
@@ -41,17 +41,6 @@ export declare function debounce(func: Function, wait: number): () => void;
|
|
|
41
41
|
* @param wait 延迟执行毫秒数
|
|
42
42
|
*/
|
|
43
43
|
export declare function delay(func: Function, wait: number, ...args: any[]): number;
|
|
44
|
-
/**
|
|
45
|
-
* @desc 需要严格区分object和array
|
|
46
|
-
* @param obj 任意对象
|
|
47
|
-
*/
|
|
48
|
-
export declare function getType(obj: any): any;
|
|
49
|
-
/**
|
|
50
|
-
* @desc 将字符串转换成正则表达式
|
|
51
|
-
* @param str 任意字符串
|
|
52
|
-
* 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
|
|
53
|
-
*/
|
|
54
|
-
export declare function transStrToReg(str: string): string | RegExp;
|
|
55
44
|
/**
|
|
56
45
|
* 解析正则表达式字符串,支持 /pattern/flags 格式
|
|
57
46
|
* @param str 正则表达式字符串,如 "/a/ig" 或 "a"
|
package/lib/utils/base.js
CHANGED
|
@@ -7,15 +7,10 @@ exports.generateEventId = generateEventId;
|
|
|
7
7
|
exports.generateGUID = generateGUID;
|
|
8
8
|
exports.generateSpanId = generateSpanId;
|
|
9
9
|
exports.generateTraceId = generateTraceId;
|
|
10
|
-
exports.getType = getType;
|
|
11
10
|
exports.interceptFunction = interceptFunction;
|
|
12
11
|
exports.parseRegExpString = parseRegExpString;
|
|
13
12
|
exports.restoreFunction = restoreFunction;
|
|
14
|
-
exports.transStrToReg = transStrToReg;
|
|
15
13
|
var _is = require("./is");
|
|
16
|
-
// 类型匹配正则
|
|
17
|
-
var TYPE_REG = /^\[object ([a-z]*)\]$/;
|
|
18
|
-
|
|
19
14
|
/**
|
|
20
15
|
* 劫持函数或原型
|
|
21
16
|
*/
|
|
@@ -163,30 +158,32 @@ function delay(func, wait) {
|
|
|
163
158
|
return setTimeout.apply(void 0, [func, +wait || 0].concat(args));
|
|
164
159
|
}
|
|
165
160
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
161
|
+
// // 类型匹配正则
|
|
162
|
+
// const TYPE_REG = /^\[object ([a-z]*)\]$/;
|
|
163
|
+
// /**
|
|
164
|
+
// * @desc 需要严格区分object和array
|
|
165
|
+
// * @param obj 任意对象
|
|
166
|
+
// */
|
|
167
|
+
// export function getType(obj: any) {
|
|
168
|
+
// let type = Object.prototype.toString.call(obj);
|
|
169
|
+
// type = type.toLowerCase() || '';
|
|
170
|
+
// const arr = type.match(TYPE_REG);
|
|
171
|
+
// return arr?.[1];
|
|
172
|
+
// }
|
|
173
|
+
//
|
|
174
|
+
// /**
|
|
175
|
+
// * @desc 将字符串转换成正则表达式
|
|
176
|
+
// * @param str 任意字符串
|
|
177
|
+
// * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
|
|
178
|
+
// */
|
|
179
|
+
// export function transStrToReg(str: string) {
|
|
180
|
+
// if (getType(str) !== 'string') return str;
|
|
181
|
+
// if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
|
|
182
|
+
// return new RegExp(str.substr(1, str.length - 2));
|
|
183
|
+
// }
|
|
184
|
+
// return str;
|
|
185
|
+
// }
|
|
186
|
+
//
|
|
190
187
|
// /**
|
|
191
188
|
// *
|
|
192
189
|
// * @param config 配置
|
package/lib/utils/events.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type EventHandler = (...args: any[]) => void;
|
|
1
|
+
export type EventHandler = (...args: any[]) => void;
|
|
2
2
|
export declare class EventEmitter {
|
|
3
3
|
private events;
|
|
4
4
|
/**
|
|
@@ -26,4 +26,3 @@ export declare class EventEmitter {
|
|
|
26
26
|
*/
|
|
27
27
|
once(eventName: string, handler: EventHandler): void;
|
|
28
28
|
}
|
|
29
|
-
export {};
|