@wutiange/log-listener-plugin 1.2.0 → 1.3.0-alpha.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/dist/console.js +14 -15
- package/dist/console.js.map +1 -1
- package/dist/fetch.js +28 -28
- package/dist/fetch.js.map +1 -1
- package/dist/index.d.ts +2 -23
- package/dist/index.js +2 -117
- package/dist/index.js.map +1 -1
- package/dist/packages/network-logger/Logger.d.ts +28 -0
- package/dist/packages/network-logger/Logger.js +192 -0
- package/dist/packages/network-logger/Logger.js.map +1 -0
- package/dist/packages/network-logger/NetworkRequestInfo.d.ts +36 -0
- package/dist/packages/network-logger/NetworkRequestInfo.js +129 -0
- package/dist/packages/network-logger/NetworkRequestInfo.js.map +1 -0
- package/dist/packages/network-logger/constant.d.ts +2 -0
- package/dist/packages/network-logger/constant.js +6 -0
- package/dist/packages/network-logger/constant.js.map +1 -0
- package/dist/packages/network-logger/types.d.ts +14 -0
- package/dist/packages/network-logger/types.js +3 -0
- package/dist/packages/network-logger/types.js.map +1 -0
- package/dist/packages/network-logger/utils/debounce.d.ts +2 -0
- package/dist/packages/network-logger/utils/debounce.js +20 -0
- package/dist/packages/network-logger/utils/debounce.js.map +1 -0
- package/dist/packages/network-logger/utils/extractHost.d.ts +2 -0
- package/dist/packages/network-logger/utils/extractHost.js +9 -0
- package/dist/packages/network-logger/utils/extractHost.js.map +1 -0
- package/dist/packages/network-logger/utils/fromEntries.d.ts +2 -0
- package/dist/packages/network-logger/utils/fromEntries.js +8 -0
- package/dist/packages/network-logger/utils/fromEntries.js.map +1 -0
- package/dist/packages/network-logger/utils/logger.d.ts +1 -0
- package/dist/packages/network-logger/utils/logger.js +6 -0
- package/dist/packages/network-logger/utils/logger.js.map +1 -0
- package/dist/src/CompatibilityManager.d.ts +27 -0
- package/dist/src/CompatibilityManager.js +74 -0
- package/dist/src/CompatibilityManager.js.map +1 -0
- package/dist/src/__tests__/console.test.d.ts +1 -0
- package/dist/{__tests__ → src/__tests__}/console.test.js +2 -2
- package/dist/src/__tests__/console.test.js.map +1 -0
- package/dist/src/common.js.map +1 -0
- package/dist/src/console.d.ts +1 -0
- package/dist/src/console.js +20 -0
- package/dist/src/console.js.map +1 -0
- package/dist/src/fetch.d.ts +1 -0
- package/dist/src/fetch.js +48 -0
- package/dist/src/fetch.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logPlugin.d.ts +32 -0
- package/dist/src/logPlugin.js +187 -0
- package/dist/src/logPlugin.js.map +1 -0
- package/dist/{server.d.ts → src/server.d.ts} +1 -1
- package/dist/{server.js → src/server.js} +14 -8
- package/dist/src/server.js.map +1 -0
- package/dist/src/utils.d.ts +3 -0
- package/dist/src/utils.js +38 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +13 -5
- package/packages/network-logger/Logger.ts +274 -0
- package/packages/network-logger/NetworkRequestInfo.ts +133 -0
- package/packages/network-logger/constant.ts +3 -0
- package/packages/network-logger/types.ts +36 -0
- package/packages/network-logger/utils/debounce.ts +21 -0
- package/packages/network-logger/utils/extractHost.ts +7 -0
- package/packages/network-logger/utils/fromEntries.ts +7 -0
- package/packages/network-logger/utils/logger.ts +2 -0
- package/src/CompatibilityManager.ts +64 -0
- package/src/__tests__/console.test.ts +2 -2
- package/src/common.ts +2 -3
- package/src/logPlugin.ts +229 -0
- package/src/server.ts +28 -23
- package/src/utils.ts +38 -0
- package/dist/__tests__/console.test.d.ts +0 -1
- package/dist/__tests__/console.test.js.map +0 -1
- package/dist/common.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +0 -14
- package/dist/utils.js.map +0 -1
- package/src/console.ts +0 -19
- package/src/fetch.ts +0 -35
- package/src/index.ts +0 -131
- /package/dist/{common.d.ts → src/common.d.ts} +0 -0
- /package/dist/{common.js → src/common.js} +0 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
// @ts-ignore
|
2
|
+
import BlobFileReader from 'react-native/Libraries/Blob/FileReader';
|
3
|
+
import type {Headers, NetworkRequestInfoRow, RequestMethod} from './types';
|
4
|
+
import fromEntries from './utils/fromEntries';
|
5
|
+
|
6
|
+
export default class NetworkRequestInfo {
|
7
|
+
id = '';
|
8
|
+
type = '';
|
9
|
+
url = '';
|
10
|
+
method: RequestMethod;
|
11
|
+
status: number = -1;
|
12
|
+
dataSent = '';
|
13
|
+
responseContentType = '';
|
14
|
+
responseSize = 0;
|
15
|
+
requestHeaders: Headers = {};
|
16
|
+
responseHeaders: Headers = {};
|
17
|
+
response = '';
|
18
|
+
responseURL = '';
|
19
|
+
responseType = '';
|
20
|
+
timeout = 0;
|
21
|
+
closeReason = '';
|
22
|
+
messages = '';
|
23
|
+
serverClose: any = undefined;
|
24
|
+
serverError: any = undefined;
|
25
|
+
startTime: number = 0;
|
26
|
+
endTime: number = 0;
|
27
|
+
gqlOperation?: string;
|
28
|
+
updatedAt: number = 0;
|
29
|
+
|
30
|
+
constructor(id: string, type: string, method: RequestMethod, url: string) {
|
31
|
+
this.id = id;
|
32
|
+
this.type = type;
|
33
|
+
this.method = method;
|
34
|
+
this.url = url;
|
35
|
+
this.updatedAt = Date.now();
|
36
|
+
}
|
37
|
+
|
38
|
+
get duration() {
|
39
|
+
return this.endTime - this.startTime;
|
40
|
+
}
|
41
|
+
|
42
|
+
get curlRequest() {
|
43
|
+
let headersPart =
|
44
|
+
this.requestHeaders &&
|
45
|
+
Object.entries(this.requestHeaders)
|
46
|
+
.map(([key, value]) => `'${key}: ${this.escapeQuotes(value)}'`)
|
47
|
+
.join(' -H ');
|
48
|
+
headersPart = headersPart ? `-H ${headersPart}` : '';
|
49
|
+
|
50
|
+
const body = this.dataSent && this.escapeQuotes(this.dataSent);
|
51
|
+
|
52
|
+
const methodPart =
|
53
|
+
this.method !== 'GET' ? `-X${this.method.toUpperCase()}` : '';
|
54
|
+
const bodyPart = body ? `-d '${body}'` : '';
|
55
|
+
|
56
|
+
const parts = ['curl', methodPart, headersPart, bodyPart, `'${this.url}'`];
|
57
|
+
|
58
|
+
return parts.filter(Boolean).join(' ');
|
59
|
+
}
|
60
|
+
|
61
|
+
update(values: Partial<NetworkRequestInfo>) {
|
62
|
+
Object.assign(this, values);
|
63
|
+
if (values.dataSent) {
|
64
|
+
const data = this.parseData(values.dataSent);
|
65
|
+
this.gqlOperation = data?.operationName;
|
66
|
+
}
|
67
|
+
this.updatedAt = Date.now();
|
68
|
+
}
|
69
|
+
|
70
|
+
private escapeQuotes(value: string) {
|
71
|
+
return value.replace?.(/'/g, "\\'");
|
72
|
+
}
|
73
|
+
|
74
|
+
private parseData(data: any) {
|
75
|
+
try {
|
76
|
+
if (data?._parts?.length) {
|
77
|
+
return fromEntries(data?._parts);
|
78
|
+
}
|
79
|
+
return JSON.parse(data);
|
80
|
+
} catch (e) {
|
81
|
+
return {data};
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
private stringifyFormat(data: any) {
|
86
|
+
return JSON.stringify(this.parseData(data), null, 2);
|
87
|
+
}
|
88
|
+
|
89
|
+
public toRow(): NetworkRequestInfoRow {
|
90
|
+
return {
|
91
|
+
url: this.url,
|
92
|
+
gqlOperation: this.gqlOperation,
|
93
|
+
id: this.id,
|
94
|
+
method: this.method,
|
95
|
+
status: this.status,
|
96
|
+
duration: this.duration,
|
97
|
+
startTime: this.startTime,
|
98
|
+
};
|
99
|
+
}
|
100
|
+
|
101
|
+
getRequestBody(replaceEscaped = false) {
|
102
|
+
const body = this.stringifyFormat(this.dataSent);
|
103
|
+
|
104
|
+
if (replaceEscaped) {
|
105
|
+
return body.replace(/\\n/g, '\n').replace(/\\"/g, '"');
|
106
|
+
}
|
107
|
+
|
108
|
+
return body;
|
109
|
+
}
|
110
|
+
|
111
|
+
private async parseResponseBlob() {
|
112
|
+
const blobReader = new BlobFileReader();
|
113
|
+
blobReader.readAsText(this.response);
|
114
|
+
|
115
|
+
return await new Promise<string>((resolve, reject) => {
|
116
|
+
const handleError = () => reject(blobReader.error);
|
117
|
+
|
118
|
+
blobReader.addEventListener('load', () => {
|
119
|
+
resolve(blobReader.result);
|
120
|
+
});
|
121
|
+
blobReader.addEventListener('error', handleError);
|
122
|
+
blobReader.addEventListener('abort', handleError);
|
123
|
+
});
|
124
|
+
}
|
125
|
+
|
126
|
+
async getResponseBody() {
|
127
|
+
const body = await (this.responseType !== 'blob'
|
128
|
+
? this.response
|
129
|
+
: this.parseResponseBlob());
|
130
|
+
|
131
|
+
return this.stringifyFormat(body);
|
132
|
+
}
|
133
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import NetworkRequestInfo from './NetworkRequestInfo';
|
2
|
+
|
3
|
+
export type Headers = {[header: string]: string};
|
4
|
+
export type RequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
5
|
+
export type StartNetworkLoggingOptions = {
|
6
|
+
/**
|
7
|
+
* Max number of requests to keep before overwriting
|
8
|
+
* @default 500
|
9
|
+
*/
|
10
|
+
maxRequests?: number;
|
11
|
+
/** List of hosts to ignore, e.g. `services.test.com` */
|
12
|
+
ignoredHosts?: string[];
|
13
|
+
/** List of urls to ignore, e.g. `https://services.test.com/test` */
|
14
|
+
ignoredUrls?: string[];
|
15
|
+
/**
|
16
|
+
* List of url patterns to ignore, e.g. `/^GET https://test.com\/pages\/.*$/`
|
17
|
+
*
|
18
|
+
* Url to match with is in the format: `${method} ${url}`, e.g. `GET https://test.com/pages/123`
|
19
|
+
*/
|
20
|
+
ignoredPatterns?: RegExp[];
|
21
|
+
/**
|
22
|
+
* Force the network logger to start even if another program is using the network interceptor
|
23
|
+
* e.g. a dev/debuging program
|
24
|
+
*/
|
25
|
+
forceEnable?: boolean;
|
26
|
+
/**
|
27
|
+
* Refresh rate of the logger in milliseconds
|
28
|
+
* @default 50
|
29
|
+
*/
|
30
|
+
refreshRate?: number;
|
31
|
+
};
|
32
|
+
|
33
|
+
export type NetworkRequestInfoRow = Pick<
|
34
|
+
NetworkRequestInfo,
|
35
|
+
'url' | 'gqlOperation' | 'id' | 'method' | 'status' | 'duration' | 'startTime'
|
36
|
+
>;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
// https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_debounce
|
2
|
+
function debounce(func: Function, wait: number, immediate: boolean = false) {
|
3
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
4
|
+
return function () {
|
5
|
+
const args = arguments;
|
6
|
+
clearTimeout(timeout);
|
7
|
+
// @ts-ignore
|
8
|
+
if (immediate && !timeout) {
|
9
|
+
func.apply(this, args);
|
10
|
+
}
|
11
|
+
timeout = setTimeout(function () {
|
12
|
+
timeout = undefined;
|
13
|
+
// @ts-ignore
|
14
|
+
if (!immediate) {
|
15
|
+
func.apply(this, args);
|
16
|
+
}
|
17
|
+
}, wait);
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
export default debounce;
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import NetworkRequestInfo from "../packages/network-logger/NetworkRequestInfo";
|
2
|
+
|
3
|
+
class CompatibilityManager {
|
4
|
+
private static requestInfoObj: Record<string, NetworkRequestInfo> = {}
|
5
|
+
static async interceptionToNetwork(data: NetworkRequestInfo[]) {
|
6
|
+
const tempWillSendArr: NetworkRequestInfo[] = []
|
7
|
+
if (Object.keys(CompatibilityManager.requestInfoObj).length === 0) {
|
8
|
+
CompatibilityManager.requestInfoObj = data.reduce((e, c) => {
|
9
|
+
if (c.endTime) {
|
10
|
+
return e
|
11
|
+
}
|
12
|
+
return {...e, [c.id]: c}
|
13
|
+
}, {})
|
14
|
+
tempWillSendArr.concat(data)
|
15
|
+
} else {
|
16
|
+
data.forEach(e => {
|
17
|
+
const tempObj = CompatibilityManager.requestInfoObj
|
18
|
+
if (!(e.id in tempObj)) {
|
19
|
+
tempWillSendArr.push(e)
|
20
|
+
if (!e.endTime) {
|
21
|
+
CompatibilityManager.requestInfoObj[e.id] = e
|
22
|
+
}
|
23
|
+
return
|
24
|
+
}
|
25
|
+
if (e.id in tempObj && e.endTime) {
|
26
|
+
tempWillSendArr.push(e)
|
27
|
+
delete CompatibilityManager.requestInfoObj[e.id]
|
28
|
+
return
|
29
|
+
}
|
30
|
+
})
|
31
|
+
}
|
32
|
+
|
33
|
+
// 将要发送的数据转换成兼容的数据
|
34
|
+
return CompatibilityManager.asyncSwapSendArr(tempWillSendArr)
|
35
|
+
}
|
36
|
+
|
37
|
+
private static async asyncSwapSendArr(data: NetworkRequestInfo[]) {
|
38
|
+
const asyncTempArr = await Promise.all(data.map(async (e) => {
|
39
|
+
if (e.endTime) {
|
40
|
+
return {
|
41
|
+
headers: e.responseHeaders,
|
42
|
+
body: await e.getResponseBody(),
|
43
|
+
requestId: e.id,
|
44
|
+
statusCode: e.status,
|
45
|
+
endTime: e.endTime,
|
46
|
+
};
|
47
|
+
} else {
|
48
|
+
return {
|
49
|
+
url: e.url,
|
50
|
+
id: e.id,
|
51
|
+
method: e.method,
|
52
|
+
headers: e.requestHeaders,
|
53
|
+
body: e.getRequestBody(),
|
54
|
+
createTime: e.startTime,
|
55
|
+
};
|
56
|
+
}
|
57
|
+
}));
|
58
|
+
|
59
|
+
return asyncTempArr;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
export default CompatibilityManager
|
package/src/common.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
export const [log, warn, error] = [console.log, console.warn, console.error]
|
2
|
-
|
1
|
+
export const [log, warn, error] = [console.log, console.warn, console.error];
|
3
2
|
|
4
3
|
// @ts-ignore
|
5
|
-
export const tempFetch = global.fetch as typeof fetch
|
4
|
+
export const tempFetch = global.fetch as typeof fetch;
|
package/src/logPlugin.ts
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
import Server from './server';
|
2
|
+
import Logger from '../packages/network-logger/Logger';
|
3
|
+
import NetworkRequestInfo from '../packages/network-logger/NetworkRequestInfo';
|
4
|
+
import { extractDomain } from './utils';
|
5
|
+
import CompatibilityManager from './CompatibilityManager';
|
6
|
+
|
7
|
+
class LogPlugin {
|
8
|
+
private server: Server | null = null;
|
9
|
+
private baseData: Record<string, any> = {};
|
10
|
+
private timeout: number | null = null;
|
11
|
+
private networkLogger = new Logger();
|
12
|
+
private host = '';
|
13
|
+
private isAuto = false
|
14
|
+
|
15
|
+
auto() {
|
16
|
+
if (this.host) {
|
17
|
+
this.startRecordNetwork();
|
18
|
+
this.startRecordLog();
|
19
|
+
}
|
20
|
+
this.isAuto = true
|
21
|
+
}
|
22
|
+
|
23
|
+
unAuto() {
|
24
|
+
this.stopRecordLog()
|
25
|
+
this.networkLogger.disableXHRInterception()
|
26
|
+
this.isAuto = false
|
27
|
+
}
|
28
|
+
|
29
|
+
startRecordLog() {
|
30
|
+
const common = require('./common')
|
31
|
+
console.log = (...data: any[]) => {
|
32
|
+
this.log(...data);
|
33
|
+
common.log(...data);
|
34
|
+
};
|
35
|
+
|
36
|
+
console.warn = (...data: any[]) => {
|
37
|
+
this.warn(...data);
|
38
|
+
common.warn(...data);
|
39
|
+
};
|
40
|
+
|
41
|
+
console.error = (...data: any[]) => {
|
42
|
+
this.error(...data);
|
43
|
+
common.error(...data);
|
44
|
+
};
|
45
|
+
}
|
46
|
+
|
47
|
+
stopRecordLog() {
|
48
|
+
const common = require('./common')
|
49
|
+
console.log = common.log
|
50
|
+
console.warn = common.warn
|
51
|
+
console.error = common.error
|
52
|
+
}
|
53
|
+
|
54
|
+
startRecordNetwork() {
|
55
|
+
this.networkLogger.setCallback(async (data: NetworkRequestInfo[]) => {
|
56
|
+
const sendData = await CompatibilityManager.interceptionToNetwork(data);
|
57
|
+
sendData.forEach(e => {
|
58
|
+
this.server?.network({
|
59
|
+
...this.baseData,
|
60
|
+
...e
|
61
|
+
});
|
62
|
+
})
|
63
|
+
});
|
64
|
+
|
65
|
+
this.networkLogger.enableXHRInterception({
|
66
|
+
ignoredHosts: [extractDomain(this.host)],
|
67
|
+
});
|
68
|
+
}
|
69
|
+
|
70
|
+
setBaseUrl(url: string) {
|
71
|
+
if (!url?.trim()) {
|
72
|
+
this.networkLogger.disableXHRInterception()
|
73
|
+
this.stopRecordLog()
|
74
|
+
return
|
75
|
+
}
|
76
|
+
this.host = url.includes("http") ? url : `http://${url}`;
|
77
|
+
if (this.server) {
|
78
|
+
this.server.updateUrl(url);
|
79
|
+
} else {
|
80
|
+
this.server = new Server(url);
|
81
|
+
}
|
82
|
+
if (this.isAuto) {
|
83
|
+
this.startRecordNetwork();
|
84
|
+
this.startRecordLog()
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
90
|
+
*/
|
91
|
+
setTimeout(timeout: number) {
|
92
|
+
if (typeof timeout === 'number') {
|
93
|
+
this.timeout = timeout;
|
94
|
+
this.server?.updateTimeout(this.timeout);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
/**
|
99
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
100
|
+
*/
|
101
|
+
getTimeout() {
|
102
|
+
if (typeof this.timeout === 'number') {
|
103
|
+
return this.timeout;
|
104
|
+
}
|
105
|
+
return null;
|
106
|
+
}
|
107
|
+
|
108
|
+
setBaseData(data: Record<string, any> = {}) {
|
109
|
+
this.baseData = data;
|
110
|
+
}
|
111
|
+
|
112
|
+
private _log(level: string, tag: string, ...data: any[]) {
|
113
|
+
const sendData = {
|
114
|
+
...this.baseData,
|
115
|
+
message: data,
|
116
|
+
tag,
|
117
|
+
level: level ?? 'log',
|
118
|
+
createTime: Date.now(),
|
119
|
+
};
|
120
|
+
this.server?.log(sendData);
|
121
|
+
}
|
122
|
+
|
123
|
+
tag(tag: string, ...data: any[]) {
|
124
|
+
this._log('log', tag, ...data);
|
125
|
+
}
|
126
|
+
|
127
|
+
log(...data: any[]) {
|
128
|
+
this._log('log', 'default', ...data);
|
129
|
+
}
|
130
|
+
|
131
|
+
warn(...data: any[]) {
|
132
|
+
this._log('warn', 'default', ...data);
|
133
|
+
}
|
134
|
+
|
135
|
+
error(...data: any[]) {
|
136
|
+
this._log('error', 'default', ...data);
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
141
|
+
*/
|
142
|
+
async uniqueReq(
|
143
|
+
uniqueId: string | undefined,
|
144
|
+
input: RequestInfo | URL,
|
145
|
+
init?: RequestInit
|
146
|
+
) {
|
147
|
+
let url: string | null = null;
|
148
|
+
let method = init?.method ?? 'get';
|
149
|
+
let headers = init?.headers;
|
150
|
+
let body = init?.body;
|
151
|
+
if (input instanceof Request) {
|
152
|
+
url = input.url;
|
153
|
+
method = input.method ?? 'get';
|
154
|
+
headers = (input.headers as Record<string, any>).map;
|
155
|
+
body = input.body;
|
156
|
+
} else if (input instanceof URL) {
|
157
|
+
url = input.href;
|
158
|
+
} else {
|
159
|
+
url = input;
|
160
|
+
}
|
161
|
+
return this.server?.network({
|
162
|
+
...this.baseData,
|
163
|
+
url,
|
164
|
+
id: uniqueId,
|
165
|
+
method,
|
166
|
+
headers,
|
167
|
+
body,
|
168
|
+
createTime: Date.now(),
|
169
|
+
});
|
170
|
+
}
|
171
|
+
|
172
|
+
private async _res(uniqueId?: string, id?: number, response?: Response) {
|
173
|
+
const body = await response?.text();
|
174
|
+
return this.server?.network({
|
175
|
+
...this.baseData,
|
176
|
+
headers: (response?.headers as Record<string, any>).map,
|
177
|
+
body,
|
178
|
+
requestId: uniqueId ?? Number(id),
|
179
|
+
statusCode: response?.status,
|
180
|
+
endTime: Date.now(),
|
181
|
+
});
|
182
|
+
}
|
183
|
+
|
184
|
+
/**
|
185
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
186
|
+
*/
|
187
|
+
async resTimeout(uniqueId: string) {
|
188
|
+
return this.server?.network({
|
189
|
+
...this.baseData,
|
190
|
+
isTimeout: true,
|
191
|
+
requestId: uniqueId,
|
192
|
+
});
|
193
|
+
}
|
194
|
+
|
195
|
+
/**
|
196
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
197
|
+
*/
|
198
|
+
async resResponseError(uniqueId: string) {
|
199
|
+
return this.server?.network({
|
200
|
+
...this.baseData,
|
201
|
+
isResponseError: true,
|
202
|
+
requestId: uniqueId,
|
203
|
+
});
|
204
|
+
}
|
205
|
+
|
206
|
+
/**
|
207
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
208
|
+
*/
|
209
|
+
async uniqueRes(uniqueId: string, response?: Response) {
|
210
|
+
return this._res(uniqueId, undefined, response);
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
215
|
+
*/
|
216
|
+
async req(input: RequestInfo | URL, init?: RequestInit) {
|
217
|
+
return this.uniqueReq(undefined, input, init);
|
218
|
+
}
|
219
|
+
|
220
|
+
/**
|
221
|
+
* @deprecated 不需要手动上报,日志插件会自动收集日志
|
222
|
+
*/
|
223
|
+
async res(id: number, response?: Response) {
|
224
|
+
return this._res(undefined, id, response);
|
225
|
+
}
|
226
|
+
}
|
227
|
+
const logPlugin = new LogPlugin();
|
228
|
+
export { LogPlugin };
|
229
|
+
export default logPlugin;
|
package/src/server.ts
CHANGED
@@ -1,61 +1,66 @@
|
|
1
|
-
import { sleep
|
2
|
-
|
1
|
+
import {hasPort, sleep} from './utils';
|
2
|
+
const DEFAULT_PORT = 27751
|
3
3
|
class Server {
|
4
4
|
private baseUrl = '';
|
5
|
-
private port = 27751
|
6
5
|
private timeout: number;
|
7
6
|
|
8
|
-
|
9
7
|
constructor(url: string, timeout: number = 3000) {
|
10
|
-
this.updateUrl(url)
|
11
|
-
this.timeout = timeout
|
8
|
+
this.updateUrl(url);
|
9
|
+
this.timeout = timeout;
|
12
10
|
}
|
13
11
|
|
14
12
|
updateTimeout(timeout = 3000) {
|
15
|
-
this.timeout = timeout
|
13
|
+
this.timeout = timeout;
|
14
|
+
}
|
15
|
+
|
16
|
+
private getPort() {
|
17
|
+
if (hasPort(this.baseUrl)) {
|
18
|
+
return ''
|
19
|
+
}
|
20
|
+
return DEFAULT_PORT;
|
16
21
|
}
|
17
22
|
|
18
23
|
private async send(path: string, data: Record<string, any>) {
|
19
24
|
try {
|
20
25
|
if (!this.baseUrl) {
|
21
|
-
return null
|
26
|
+
return null;
|
22
27
|
}
|
23
|
-
const common =
|
28
|
+
const common = require('./common');
|
24
29
|
const result = await Promise.race([
|
25
|
-
common.tempFetch(`${this.baseUrl}:${this.
|
30
|
+
common.tempFetch(`${this.baseUrl}:${this.getPort()}/${path}`, {
|
26
31
|
method: 'POST',
|
27
32
|
headers: {
|
28
|
-
'Content-Type': 'application/json;charset=utf-8'
|
33
|
+
'Content-Type': 'application/json;charset=utf-8',
|
29
34
|
},
|
30
35
|
body: JSON.stringify(data, (_, val) => {
|
31
36
|
if (val instanceof Error) {
|
32
|
-
return val.toString()
|
37
|
+
return val.toString();
|
33
38
|
}
|
34
|
-
return val
|
35
|
-
})
|
39
|
+
return val;
|
40
|
+
}),
|
36
41
|
}),
|
37
|
-
sleep(this.timeout, true)
|
38
|
-
])
|
42
|
+
sleep(this.timeout, true),
|
43
|
+
]);
|
39
44
|
if (result instanceof Response) {
|
40
|
-
return result.text()
|
45
|
+
return result.text();
|
41
46
|
}
|
42
|
-
return null
|
47
|
+
return null;
|
43
48
|
} catch (error) {
|
44
|
-
return null
|
49
|
+
return null;
|
45
50
|
}
|
46
51
|
}
|
47
52
|
|
48
53
|
updateUrl(url: string) {
|
49
|
-
this.baseUrl = url
|
54
|
+
this.baseUrl = url;
|
50
55
|
}
|
51
56
|
|
52
57
|
async log(data: Record<string, any>) {
|
53
|
-
return this.send(
|
58
|
+
return this.send('log', data);
|
54
59
|
}
|
55
60
|
|
56
61
|
async network(data: Record<string, any>) {
|
57
|
-
return this.send(
|
62
|
+
return this.send('network', data);
|
58
63
|
}
|
59
64
|
}
|
60
65
|
|
61
|
-
export default Server
|
66
|
+
export default Server;
|
package/src/utils.ts
CHANGED
@@ -7,3 +7,41 @@ export function sleep(ms: number, isReject: boolean = false) {
|
|
7
7
|
}) : resolve, ms)
|
8
8
|
})
|
9
9
|
}
|
10
|
+
|
11
|
+
export function extractDomain(url: string) {
|
12
|
+
// 如果 url 是空的或不是字符串,直接返回
|
13
|
+
if (!url || typeof url !== 'string') {
|
14
|
+
return url;
|
15
|
+
}
|
16
|
+
|
17
|
+
// 使用正则表达式匹配 URL
|
18
|
+
const match = url.match(/^(https?:\/\/)?([^/:]+)/i);
|
19
|
+
|
20
|
+
// 如果没有匹配到,返回原始输入
|
21
|
+
if (!match) {
|
22
|
+
return url;
|
23
|
+
}
|
24
|
+
|
25
|
+
// 返回匹配到的域名部分
|
26
|
+
return match[2];
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
export function hasPort(url: string) {
|
31
|
+
// 如果 url 是空的或不是字符串,返回 false
|
32
|
+
if (!url || typeof url !== 'string') {
|
33
|
+
return false;
|
34
|
+
}
|
35
|
+
|
36
|
+
try {
|
37
|
+
// 使用 URL 构造函数解析 URL
|
38
|
+
const parsedUrl = new URL(url);
|
39
|
+
|
40
|
+
// 检查 port 属性是否为空
|
41
|
+
// 注意:如果使用默认端口(如 HTTP 的 80 或 HTTPS 的 443),port 会是空字符串
|
42
|
+
return parsedUrl.port !== '';
|
43
|
+
} catch (error) {
|
44
|
+
// 如果 URL 无效,捕获错误并返回 false
|
45
|
+
return false;
|
46
|
+
}
|
47
|
+
}
|
@@ -1 +0,0 @@
|
|
1
|
-
import '../console';
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"console.test.js","sourceRoot":"","sources":["../../src/__tests__/console.test.ts"],"names":[],"mappings":";;;;;AAAA,sBAAmB;AACnB,qDAA6B;AAC7B,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QACzB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,eAAe,EAAE,GAAG,EAAE;QACvB,eAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAA;QAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QACzB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACd,eAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAA;QAC3C,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC3B,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACf,eAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAA;QAC3C,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;QAC7B,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/dist/common.js.map
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":";;;;AAAa,KAAqB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,EAA9D,WAAG,UAAE,YAAI,UAAE,aAAK,SAA8C;AAI/D,QAAA,SAAS,GAAG,MAAM,CAAC,KAAqB,CAAA"}
|
package/dist/server.js.map
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,mCAAgC;AAEhC,MAAM,MAAM;IAMV,YAAY,GAAW,EAAE,UAAkB,IAAI;QALvC,YAAO,GAAG,EAAE,CAAC;QACb,SAAI,GAAG,KAAK,CAAA;QAKlB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QACnB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,aAAa,CAAC,OAAO,GAAG,IAAI;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAEa,IAAI,CAAC,IAAY,EAAE,IAAyB;;YACxD,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClB,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;gBAC1C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;oBAChC,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE;wBACvD,MAAM,EAAE,MAAM;wBACd,OAAO,EAAE;4BACP,cAAc,EAAE,gCAAgC;yBACjD;wBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;4BACpC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;gCACzB,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;4BACvB,CAAC;4BACD,OAAO,GAAG,CAAA;wBACZ,CAAC,CAAC;qBACH,CAAC;oBACF,IAAA,aAAK,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC;iBAC1B,CAAC,CAAA;gBACF,IAAI,MAAM,YAAY,QAAQ,EAAE,CAAC;oBAC/B,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;gBACtB,CAAC;gBACD,OAAO,IAAI,CAAA;YACb,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;KAAA;IAED,SAAS,CAAC,GAAW;QACnB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAA;IACpB,CAAC;IAEK,GAAG,CAAC,IAAyB;;YACjC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAC/B,CAAC;KAAA;IAEK,OAAO,CAAC,IAAyB;;YACrC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACnC,CAAC;KAAA;CACF;AAED,kBAAe,MAAM,CAAA"}
|
package/dist/utils.d.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export declare function sleep(ms: number, isReject?: boolean): Promise<unknown>;
|