@wutiange/log-listener-plugin 1.3.0-alpha.0 → 1.3.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +2 -2
  3. package/dist/server.d.ts +10 -0
  4. package/dist/server.js +45 -0
  5. package/dist/server.js.map +1 -0
  6. package/dist/src/HTTPInterceptor.d.ts +48 -0
  7. package/dist/src/HTTPInterceptor.js +202 -0
  8. package/dist/src/HTTPInterceptor.js.map +1 -0
  9. package/dist/src/logPlugin.d.ts +19 -20
  10. package/dist/src/logPlugin.js +108 -122
  11. package/dist/src/logPlugin.js.map +1 -1
  12. package/package.json +47 -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 -36
  23. package/dist/packages/network-logger/NetworkRequestInfo.js +0 -129
  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 -74
  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 -133
  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 -64
package/package.json CHANGED
@@ -1,47 +1,47 @@
1
- {
2
- "name": "@wutiange/log-listener-plugin",
3
- "version": "1.3.0-alpha.0",
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.2",
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
+ }
@@ -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;