@wutiange/log-listener-plugin 1.3.0-alpha.1 → 1.3.0-alpha.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +2 -2
  3. package/console.ts +21 -0
  4. package/dist/src/HTTPInterceptor.d.ts +48 -0
  5. package/dist/src/HTTPInterceptor.js +202 -0
  6. package/dist/src/HTTPInterceptor.js.map +1 -0
  7. package/dist/src/logPlugin.d.ts +19 -20
  8. package/dist/src/logPlugin.js +108 -122
  9. package/dist/src/logPlugin.js.map +1 -1
  10. package/fetch.ts +39 -0
  11. package/index.ts +3 -0
  12. package/package.json +49 -47
  13. package/src/HTTPInterceptor.ts +319 -0
  14. package/src/__tests__/console.test.ts +25 -25
  15. package/src/common.ts +4 -4
  16. package/src/logPlugin.ts +238 -229
  17. package/src/server.ts +66 -66
  18. package/src/utils.ts +47 -47
  19. package/dist/packages/network-logger/Logger.d.ts +0 -28
  20. package/dist/packages/network-logger/Logger.js +0 -192
  21. package/dist/packages/network-logger/Logger.js.map +0 -1
  22. package/dist/packages/network-logger/NetworkRequestInfo.d.ts +0 -37
  23. package/dist/packages/network-logger/NetworkRequestInfo.js +0 -151
  24. package/dist/packages/network-logger/NetworkRequestInfo.js.map +0 -1
  25. package/dist/packages/network-logger/constant.d.ts +0 -2
  26. package/dist/packages/network-logger/constant.js +0 -6
  27. package/dist/packages/network-logger/constant.js.map +0 -1
  28. package/dist/packages/network-logger/types.d.ts +0 -14
  29. package/dist/packages/network-logger/types.js +0 -3
  30. package/dist/packages/network-logger/types.js.map +0 -1
  31. package/dist/packages/network-logger/utils/debounce.d.ts +0 -2
  32. package/dist/packages/network-logger/utils/debounce.js +0 -20
  33. package/dist/packages/network-logger/utils/debounce.js.map +0 -1
  34. package/dist/packages/network-logger/utils/extractHost.d.ts +0 -2
  35. package/dist/packages/network-logger/utils/extractHost.js +0 -9
  36. package/dist/packages/network-logger/utils/extractHost.js.map +0 -1
  37. package/dist/packages/network-logger/utils/fromEntries.d.ts +0 -2
  38. package/dist/packages/network-logger/utils/fromEntries.js +0 -8
  39. package/dist/packages/network-logger/utils/fromEntries.js.map +0 -1
  40. package/dist/packages/network-logger/utils/logger.d.ts +0 -1
  41. package/dist/packages/network-logger/utils/logger.js +0 -6
  42. package/dist/packages/network-logger/utils/logger.js.map +0 -1
  43. package/dist/src/CompatibilityManager.d.ts +0 -27
  44. package/dist/src/CompatibilityManager.js +0 -82
  45. package/dist/src/CompatibilityManager.js.map +0 -1
  46. package/dist/src/console.d.ts +0 -1
  47. package/dist/src/console.js +0 -20
  48. package/dist/src/console.js.map +0 -1
  49. package/dist/src/fetch.d.ts +0 -1
  50. package/dist/src/fetch.js +0 -48
  51. package/dist/src/fetch.js.map +0 -1
  52. package/dist/src/index.d.ts +0 -2
  53. package/dist/src/index.js +0 -8
  54. package/dist/src/index.js.map +0 -1
  55. package/packages/network-logger/Logger.ts +0 -274
  56. package/packages/network-logger/NetworkRequestInfo.ts +0 -161
  57. package/packages/network-logger/constant.ts +0 -3
  58. package/packages/network-logger/types.ts +0 -36
  59. package/packages/network-logger/utils/debounce.ts +0 -21
  60. package/packages/network-logger/utils/extractHost.ts +0 -7
  61. package/packages/network-logger/utils/fromEntries.ts +0 -7
  62. package/packages/network-logger/utils/logger.ts +0 -2
  63. package/src/CompatibilityManager.ts +0 -71
package/package.json CHANGED
@@ -1,47 +1,49 @@
1
- {
2
- "name": "@wutiange/log-listener-plugin",
3
- "version": "1.3.0-alpha.1",
4
- "description": "这是log-record的插件,如果需要使用这个日志监听,那么就需要把这个插件安装到项目中",
5
- "main": "dist/src/index.js",
6
- "types": "dist/src/index.d.ts",
7
- "source": "src/index.ts",
8
- "repository": {
9
- "url": "https://github.com/wutiange/log-listener-plugin.git"
10
- },
11
- "author": "wutiange <wutiange20@qq,com>",
12
- "license": "MIT",
13
- "private": false,
14
- "exports": {
15
- "console": {
16
- "default": "./dist/console.js"
17
- },
18
- "fetch": {
19
- "default": "./dist/fetch.js"
20
- }
21
- },
22
- "scripts": {
23
- "build": "tsc",
24
- "dev": "ts-node ./src/index.ts",
25
- "test": "jest"
26
- },
27
- "devDependencies": {
28
- "@jest/globals": "^29.7.0",
29
- "@types/jest": "^29.5.12",
30
- "jest": "^29.7.0",
31
- "ts-jest": "^29.1.2",
32
- "ts-node": "^10.9.2",
33
- "typescript": "^5.3.3",
34
- "react-native": "0.73.5"
35
- },
36
- "peerDependencies": {
37
- "react-native": "*"
38
- },
39
- "files": [
40
- "src",
41
- "package.json",
42
- "packages",
43
- "README.md",
44
- "LICENSE",
45
- "dist"
46
- ]
47
- }
1
+ {
2
+ "name": "@wutiange/log-listener-plugin",
3
+ "version": "1.3.0-alpha.3",
4
+ "description": "这是log-record的插件,如果需要使用这个日志监听,那么就需要把这个插件安装到项目中",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "source": "index.ts",
8
+ "repository": {
9
+ "url": "https://github.com/wutiange/log-listener-plugin.git"
10
+ },
11
+ "author": "wutiange <wutiange20@qq,com>",
12
+ "license": "MIT",
13
+ "private": false,
14
+ "exports": {
15
+ "console": {
16
+ "default": "./dist/console.js"
17
+ },
18
+ "fetch": {
19
+ "default": "./dist/fetch.js"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "ts-node ./src/index.ts",
25
+ "test": "jest"
26
+ },
27
+ "devDependencies": {
28
+ "@jest/globals": "^29.7.0",
29
+ "@types/jest": "^29.5.12",
30
+ "jest": "^29.7.0",
31
+ "ts-jest": "^29.1.2",
32
+ "ts-node": "^10.9.2",
33
+ "typescript": "^5.3.3",
34
+ "react-native": "0.73.5"
35
+ },
36
+ "peerDependencies": {
37
+ "react-native": "*"
38
+ },
39
+ "files": [
40
+ "src",
41
+ "package.json",
42
+ "README.md",
43
+ "LICENSE",
44
+ "dist",
45
+ "console.ts",
46
+ "fetch.ts",
47
+ "index.ts"
48
+ ]
49
+ }
@@ -0,0 +1,319 @@
1
+ // @ts-ignore
2
+ import XHRInterceptor from 'react-native/Libraries/Network/XHRInterceptor';
3
+ // @ts-ignore
4
+ import BlobFileReader from 'react-native/Libraries/Blob/FileReader';
5
+
6
+ type StartNetworkLoggingOptions = {
7
+ /** List of hosts to ignore, e.g. `services.test.com` */
8
+ ignoredHosts?: string[];
9
+ /** List of urls to ignore, e.g. `https://services.test.com/test` */
10
+ ignoredUrls?: string[];
11
+ /**
12
+ * List of url patterns to ignore, e.g. `/^GET https://test.com\/pages\/.*$/`
13
+ *
14
+ * Url to match with is in the format: `${method} ${url}`, e.g. `GET https://test.com/pages/123`
15
+ */
16
+ ignoredPatterns?: RegExp[];
17
+ /**
18
+ * Force the network logger to start even if another program is using the network interceptor
19
+ * e.g. a dev/debuging program
20
+ */
21
+ forceEnable?: boolean;
22
+ };
23
+
24
+ interface HttpRequestInfo {
25
+ id: string;
26
+ method: RequestMethod;
27
+ url: string;
28
+ timeout: number;
29
+ requestHeaders: Record<string, string>;
30
+ requestData: string;
31
+ startTime: number;
32
+ endTime: number;
33
+ responseHeaders: Headers;
34
+ responseData: string;
35
+ status: number;
36
+ duration: number;
37
+ responseContentType: string;
38
+ responseSize: number;
39
+ responseURL: string;
40
+ responseType: string;
41
+ }
42
+
43
+ type RequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
44
+
45
+ type XHR = {
46
+ uniqueId: string;
47
+ responseHeaders?: Headers;
48
+ };
49
+
50
+ type EventName =
51
+ | 'open'
52
+ | 'requestHeader'
53
+ | 'headerReceived'
54
+ | 'send'
55
+ | 'response';
56
+
57
+ const extractHost = (url: string) => {
58
+ const host = url.split('//')[1]?.split(':')[0]?.split('/')[0] || undefined;
59
+
60
+ return host;
61
+ };
62
+
63
+ const generateUniqueId = () => {
64
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
65
+ };
66
+
67
+ const parseResponseBlob = async (response: string) => {
68
+ const blobReader = new BlobFileReader();
69
+ blobReader.readAsText(response);
70
+
71
+ return await new Promise<string>((resolve, reject) => {
72
+ const handleError = () => reject(blobReader.error);
73
+
74
+ blobReader.addEventListener('load', () => {
75
+ resolve(blobReader.result);
76
+ });
77
+ blobReader.addEventListener('error', handleError);
78
+ blobReader.addEventListener('abort', handleError);
79
+ });
80
+ }
81
+
82
+ const getResponseBody = async (responseType: string, response: string) => {
83
+ try {
84
+ const body = await (responseType !== 'blob'
85
+ ? response
86
+ : parseResponseBlob(response));
87
+ return JSON.parse(body)
88
+ } catch (error) {
89
+ return null
90
+ }
91
+ }
92
+
93
+ class HTTPInterceptor {
94
+ private static _index = 0;
95
+ private ignoredHosts: Set<string> | undefined;
96
+ private ignoredUrls: Set<string> | undefined;
97
+ private ignoredPatterns: RegExp[] | undefined;
98
+ // 只保存正在请求中的
99
+ private allRequests = new Map<string, Partial<HttpRequestInfo>>();
100
+
101
+ private userListeners: [
102
+ EventName,
103
+ (data: Partial<HttpRequestInfo>) => Promise<void> | void,
104
+ ][] = [];
105
+
106
+ private enabled = false;
107
+
108
+ addListener = (
109
+ eventName: EventName,
110
+ listener: (data: Partial<HttpRequestInfo>) => Promise<void> | void,
111
+ ) => {
112
+ // 如果之前已经订阅过了就过滤掉
113
+ if (
114
+ this.userListeners.find(
115
+ ([name, tempListener]) =>
116
+ name === eventName && tempListener === listener,
117
+ )
118
+ ) {
119
+ return;
120
+ }
121
+ this.userListeners.push([eventName, listener]);
122
+
123
+ return () => {
124
+ this.userListeners = this.userListeners.filter(
125
+ ([name, tempListener]) =>
126
+ name !== eventName || tempListener !== listener,
127
+ );
128
+ };
129
+ };
130
+
131
+ removeListener = (
132
+ eventName: EventName,
133
+ listener: (data: Partial<HttpRequestInfo>) => Promise<void> | void,
134
+ ) => {
135
+ this.userListeners = this.userListeners.filter(
136
+ ([name, tempListener]) => name !== eventName || tempListener !== listener,
137
+ );
138
+ };
139
+
140
+ removeAllListener() {
141
+ this.userListeners = [];
142
+ }
143
+
144
+ private listenerHandle = (
145
+ eventName: EventName,
146
+ data: Partial<HttpRequestInfo>,
147
+ ) => {
148
+ this.userListeners.forEach(async ([name, listener]) => {
149
+ if (name === eventName) {
150
+ await listener(data);
151
+ }
152
+ });
153
+ };
154
+
155
+
156
+
157
+ private openHandle = (method: RequestMethod, url: string, xhr: XHR) => {
158
+ if (this.ignoredHosts) {
159
+ const host = extractHost(url);
160
+ if (host && this.ignoredHosts.has(host)) {
161
+ return;
162
+ }
163
+ }
164
+ if (this.ignoredUrls && this.ignoredUrls.has(url)) {
165
+ return;
166
+ }
167
+
168
+ if (this.ignoredPatterns) {
169
+ if (
170
+ this.ignoredPatterns.some(pattern => pattern.test(`${method} ${url}`))
171
+ ) {
172
+ return;
173
+ }
174
+ }
175
+ xhr.uniqueId = HTTPInterceptor._index + generateUniqueId();
176
+ const newRequest = {
177
+ id: xhr.uniqueId,
178
+ method,
179
+ url,
180
+ };
181
+ this.allRequests.set(xhr.uniqueId, newRequest);
182
+ this.listenerHandle('open', newRequest);
183
+ };
184
+
185
+ private requestHeaderHandle = (header: string, value: string, xhr: XHR) => {
186
+ const currentRequest = this.allRequests.get(xhr.uniqueId);
187
+ if (!currentRequest) {
188
+ return;
189
+ }
190
+ if (!currentRequest.requestHeaders) {
191
+ currentRequest.requestHeaders = {};
192
+ }
193
+ currentRequest.requestHeaders[header] = value;
194
+ this.listenerHandle('requestHeader', currentRequest);
195
+ };
196
+
197
+ private headerReceivedHandle = (
198
+ responseContentType: string,
199
+ responseSize: number,
200
+ responseHeaders: Headers,
201
+ xhr: XHR,
202
+ ) => {
203
+ const currentRequest = this.allRequests.get(xhr.uniqueId);
204
+ if (!currentRequest) {
205
+ return;
206
+ }
207
+ currentRequest.responseContentType = responseContentType;
208
+ currentRequest.responseSize = responseSize;
209
+ currentRequest.responseHeaders = xhr.responseHeaders;
210
+ this.listenerHandle('headerReceived', currentRequest);
211
+ };
212
+
213
+ private responseHandle = async (
214
+ status: number,
215
+ timeout: number,
216
+ response: string,
217
+ responseURL: string,
218
+ responseType: string,
219
+ xhr: XHR,
220
+ ) => {
221
+ const currentRequest = this.allRequests.get(xhr.uniqueId);
222
+ if (!currentRequest) {
223
+ return;
224
+ }
225
+ currentRequest.endTime = Date.now();
226
+ currentRequest.status = status;
227
+ currentRequest.timeout = timeout;
228
+ currentRequest.responseData = await getResponseBody(responseType, response);
229
+ currentRequest.responseURL = responseURL;
230
+ currentRequest.responseType = responseType;
231
+ currentRequest.duration =
232
+ currentRequest.endTime - (currentRequest.startTime ?? 0);
233
+ this.listenerHandle('response', currentRequest);
234
+ this.allRequests.delete(xhr.uniqueId);
235
+ };
236
+
237
+ private sendHandle = (data: string, xhr: XHR) => {
238
+ const currentRequest = this.allRequests.get(xhr.uniqueId);
239
+ if (!currentRequest) {
240
+ return;
241
+ }
242
+ try {
243
+ currentRequest.requestData = JSON.parse(data);
244
+ } catch (error) {
245
+ currentRequest.requestData = null;
246
+ }
247
+ currentRequest.startTime = Date.now();
248
+ this.listenerHandle('send', currentRequest);
249
+ };
250
+
251
+ enable = (options?: StartNetworkLoggingOptions) => {
252
+ try {
253
+ if (
254
+ this.enabled ||
255
+ (XHRInterceptor.isInterceptorEnabled() && !options?.forceEnable)
256
+ ) {
257
+ if (!this.enabled) {
258
+ console.warn(
259
+ 'network interceptor has not been enabled as another interceptor is already running (e.g. another debugging program). Use option `forceEnable: true` to override this behaviour.',
260
+ );
261
+ }
262
+ return;
263
+ }
264
+
265
+ if (options?.ignoredHosts) {
266
+ if (
267
+ !Array.isArray(options.ignoredHosts) ||
268
+ typeof options.ignoredHosts[0] !== 'string'
269
+ ) {
270
+ console.warn(
271
+ 'ignoredHosts must be an array of strings. The logger has not been started.',
272
+ );
273
+ return;
274
+ }
275
+ this.ignoredHosts = new Set(options.ignoredHosts);
276
+ }
277
+
278
+ if (options?.ignoredPatterns) {
279
+ this.ignoredPatterns = options.ignoredPatterns;
280
+ }
281
+
282
+ if (options?.ignoredUrls) {
283
+ if (
284
+ !Array.isArray(options.ignoredUrls) ||
285
+ typeof options.ignoredUrls[0] !== 'string'
286
+ ) {
287
+ console.warn(
288
+ 'ignoredUrls must be an array of strings. The logger has not been started.',
289
+ );
290
+ return;
291
+ }
292
+ this.ignoredUrls = new Set(options.ignoredUrls);
293
+ }
294
+ XHRInterceptor.setOpenCallback(this.openHandle);
295
+ XHRInterceptor.setRequestHeaderCallback(this.requestHeaderHandle);
296
+ XHRInterceptor.setHeaderReceivedCallback(this.headerReceivedHandle);
297
+ XHRInterceptor.setSendCallback(this.sendHandle);
298
+ XHRInterceptor.setResponseCallback(this.responseHandle);
299
+ XHRInterceptor.enableInterception();
300
+ this.enabled = true;
301
+ } catch (error) {}
302
+ };
303
+
304
+ disable = () => {
305
+ if (!this.enabled) {
306
+ return;
307
+ }
308
+ XHRInterceptor.disableInterception();
309
+ this.enabled = false;
310
+ }
311
+ }
312
+
313
+ const httpInterceptor = new HTTPInterceptor();
314
+ export {
315
+ type StartNetworkLoggingOptions,
316
+ httpInterceptor,
317
+ type EventName,
318
+ type RequestMethod,
319
+ };
@@ -1,26 +1,26 @@
1
- import '../../console'
2
- import logger from '../../index'
3
- describe("重写日志", () => {
4
- it("log 没有提前设置 url", () => {
5
- console.log("log 是否正常打印")
6
- expect(1).toBe(1)
7
- })
8
-
9
- it("log 提前设置了 url", () => {
10
- logger.setBaseUrl("http://192.168.118.103")
11
- console.log("log 是否正常打印")
12
- expect(1).toBe(1)
13
- })
14
-
15
- it('warn', () => {
16
- logger.setBaseUrl("http://192.168.118.103")
17
- console.warn("warn 是否正常打印")
18
- expect(1).toBe(1)
19
- })
20
-
21
- it('error', () => {
22
- logger.setBaseUrl("http://192.168.118.103")
23
- console.error("error 是否正常打印")
24
- expect(1).toBe(1)
25
- })
1
+ import '../../console'
2
+ import logger from '../../index'
3
+ describe("重写日志", () => {
4
+ it("log 没有提前设置 url", () => {
5
+ console.log("log 是否正常打印")
6
+ expect(1).toBe(1)
7
+ })
8
+
9
+ it("log 提前设置了 url", () => {
10
+ logger.setBaseUrl("http://192.168.118.103")
11
+ console.log("log 是否正常打印")
12
+ expect(1).toBe(1)
13
+ })
14
+
15
+ it('warn', () => {
16
+ logger.setBaseUrl("http://192.168.118.103")
17
+ console.warn("warn 是否正常打印")
18
+ expect(1).toBe(1)
19
+ })
20
+
21
+ it('error', () => {
22
+ logger.setBaseUrl("http://192.168.118.103")
23
+ console.error("error 是否正常打印")
24
+ expect(1).toBe(1)
25
+ })
26
26
  })
package/src/common.ts CHANGED
@@ -1,4 +1,4 @@
1
- export const [log, warn, error] = [console.log, console.warn, console.error];
2
-
3
- // @ts-ignore
4
- export const tempFetch = global.fetch as typeof fetch;
1
+ export const [log, warn, error] = [console.log, console.warn, console.error];
2
+
3
+ // @ts-ignore
4
+ export const tempFetch = global.fetch as typeof fetch;