@wutiange/log-listener-plugin 2.0.1-alpha.3 → 2.0.1

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 (37) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +163 -163
  3. package/dist/src/HTTPInterceptor.js +2 -1
  4. package/dist/src/HTTPInterceptor.js.map +1 -1
  5. package/dist/src/__tests__/Server.test.js +4 -4
  6. package/dist/src/__tests__/Server.test.js.map +1 -1
  7. package/dist/src/__tests__/console.test.d.ts +1 -0
  8. package/dist/src/__tests__/console.test.js +29 -0
  9. package/dist/src/__tests__/console.test.js.map +1 -0
  10. package/dist/src/__tests__/utils.test.js +5 -1
  11. package/dist/src/__tests__/utils.test.js.map +1 -1
  12. package/dist/src/common.d.ts +1 -7
  13. package/dist/src/common.js +2 -14
  14. package/dist/src/common.js.map +1 -1
  15. package/dist/src/logPlugin.js +22 -17
  16. package/dist/src/logPlugin.js.map +1 -1
  17. package/dist/src/server.d.ts +21 -0
  18. package/dist/src/{Server.js → server.js} +47 -31
  19. package/dist/src/server.js.map +1 -0
  20. package/dist/src/utils.js +4 -4
  21. package/dist/src/utils.js.map +1 -1
  22. package/index.ts +3 -3
  23. package/package.json +59 -59
  24. package/src/HTTPInterceptor.ts +340 -339
  25. package/src/Server.ts +178 -167
  26. package/src/__mocks__/react-native/Libraries/Blob/FileReader.js +44 -44
  27. package/src/__mocks__/react-native/Libraries/Network/XHRInterceptor.js +39 -39
  28. package/src/__tests__/HTTPInterceptor.test.ts +322 -322
  29. package/src/__tests__/Server.test.ts +149 -149
  30. package/src/__tests__/utils.test.ts +113 -112
  31. package/src/common.ts +57 -70
  32. package/src/logPlugin.ts +231 -224
  33. package/src/logger.ts +14 -14
  34. package/src/utils.ts +112 -112
  35. package/tsconfig.json +26 -26
  36. package/dist/src/Server.d.ts +0 -20
  37. package/dist/src/Server.js.map +0 -1
package/src/Server.ts CHANGED
@@ -1,167 +1,178 @@
1
- import { hasPort, sleep } from "./utils";
2
- import Zeroconf from "react-native-zeroconf";
3
- import { getBaseData, getErrMsg, LOG_KEY } from "./common";
4
- import logger from "./logger";
5
- import md5 from 'crypto-js/md5';
6
-
7
-
8
- const DEFAULT_PORT = 27751;
9
- class Server {
10
- private baseUrlObj: Record<string, string> = {};
11
- private timeout: number;
12
- private baseData: Record<string, any> = {};
13
- private urlsListener: (
14
- urls: string[],
15
- urlsObj: Record<string, string>
16
- ) => void;
17
- private innerBaseData: Record<string, string> = {};
18
-
19
- constructor(url?: string | Record<string, string>, timeout: number = 30000) {
20
- if (typeof url === "string") {
21
- this.updateUrl(url);
22
- } else {
23
- this.setBaseUrlObj(url ?? {});
24
- }
25
- this.timeout = timeout;
26
- this.innerBaseData = getBaseData();
27
- this.handleZeroConf();
28
- }
29
-
30
- addUrlsListener = (
31
- onNewUrlCallback: (urls: string[], urlsObj: Record<string, string>) => void
32
- ) => {
33
- this.urlsListener = onNewUrlCallback;
34
- };
35
-
36
- private requestJoin = async (url: string, token: string) => {
37
- const response = await fetch(url, {
38
- method: "POST",
39
- headers: {
40
- "Content-Type": "application/json;charset=utf-8",
41
- },
42
- body: JSON.stringify({
43
- token,
44
- model: this.innerBaseData.Model ?? `${this.innerBaseData.systemName}v${this.innerBaseData.osVersion}`,
45
- id: md5(JSON.stringify(this.innerBaseData)).toString(),
46
- }),
47
- });
48
- if (response.status !== 200) {
49
- return false;
50
- }
51
- const json = await response.json();
52
-
53
- if (json.code !== 0) {
54
- return false;
55
- }
56
- return true
57
- }
58
-
59
- private async handleZeroConf() {
60
- try {
61
- const Zeroconf = require("react-native-zeroconf")?.default;
62
- if (!Zeroconf) {
63
- return;
64
- }
65
- // @ts-ignore
66
- const zeroconf: Zeroconf = new Zeroconf();
67
- zeroconf.on("resolved", async (service) => {
68
- try {
69
- const { path, token } = service.txt ?? {};
70
- if (!(path && token) || this.baseUrlObj[token]) {
71
- return;
72
- }
73
- const url = `http://${service.host}:${service.port}`;
74
- if (!(await this.requestJoin(`${url}${path}`, token))) {
75
- return;
76
- }
77
- this.baseUrlObj[token] = url;
78
- if (this.urlsListener) {
79
- this.urlsListener(this.getUrls(), this.baseUrlObj);
80
- }
81
- } catch (error) {
82
- logger.warn(LOG_KEY, "加入日志系统失败---", error);
83
- }
84
- });
85
- zeroconf.scan("http", "tcp");
86
- } catch (error: any) {
87
- logger.warn(LOG_KEY, "zeroconf扫描或处理相关逻辑失败或者您根本就没有安装 react-native-zeroconf ,如果您没有安装,那么您将无法使用发现功能", error);
88
- }
89
- }
90
-
91
- updateTimeout(timeout = 3000) {
92
- this.timeout = timeout;
93
- }
94
-
95
- getUrls() {
96
- return Object.values(this.baseUrlObj).map((e) => {
97
- if (hasPort(e)) {
98
- return e;
99
- }
100
- return `${e}:${DEFAULT_PORT}`;
101
- });
102
- }
103
-
104
- private send = async (
105
- path: string,
106
- data: Record<string, any>
107
- ): Promise<void> => {
108
- const request = async (url: string, _data: Record<string, any>) => {
109
- await Promise.race([
110
- fetch(`${url}/${path}`, {
111
- method: "POST",
112
- headers: {
113
- "Content-Type": "application/json;charset=utf-8",
114
- },
115
- body: JSON.stringify(
116
- { ...this.innerBaseData, ...this.baseData, ..._data },
117
- (_, val) => {
118
- if (val instanceof Error) {
119
- return val.toString();
120
- }
121
- return val;
122
- }
123
- ),
124
- }),
125
- sleep(this.timeout, true),
126
- ]);
127
- };
128
- try {
129
- if (Object.keys(this.baseUrlObj).length === 0) {
130
- return;
131
- }
132
- await Promise.all(this.getUrls().map(async (e) => request(e, data)));
133
- } catch (error: any) {
134
- if (error?.message?.includes("Network request failed")) {
135
- return
136
- }
137
- logger.warn(LOG_KEY, "上报日志失败", error)
138
- }
139
- };
140
-
141
- updateUrl(url: string) {
142
- const tempUrl = url.includes("http") ? url : `http://${url}`;
143
- if (!url) {
144
- delete this.baseUrlObj["Default"];
145
- } else {
146
- this.baseUrlObj["Default"] = tempUrl;
147
- }
148
- }
149
-
150
- setBaseUrlObj(urlObj: Record<string, string>) {
151
- this.baseUrlObj = urlObj;
152
- }
153
-
154
- updateBaseData(data: Record<string, any>) {
155
- this.baseData = data;
156
- }
157
-
158
- log = async (data: Record<string, any>) => {
159
- return this.send("log", data);
160
- };
161
-
162
- network = async (data: Record<string, any>) => {
163
- return this.send("network", data);
164
- };
165
- }
166
-
167
- export default Server;
1
+ import { hasPort, sleep } from "./utils";
2
+ import Zeroconf from "react-native-zeroconf";
3
+ import { getBaseData, LOG_KEY } from "./common";
4
+ import logger from "./logger";
5
+ import md5 from 'crypto-js/md5';
6
+
7
+
8
+ const DEFAULT_PORT = 27751;
9
+ class Server {
10
+ private baseUrlArr: Set<string> = new Set();
11
+ private urlsObj: Map<string, string> = new Map();
12
+ private timeout: number;
13
+ private baseData: Record<string, any> = {};
14
+ private urlsListener: (urls: Set<string>) => void;
15
+ private innerBaseData: Record<string, string> = {};
16
+
17
+ constructor(url?: string | Set<string>, timeout: number = 30000) {
18
+ if (typeof url === "string") {
19
+ this.updateUrl(url);
20
+ } else {
21
+ this.setBaseUrlArr(url ?? new Set());
22
+ }
23
+ this.timeout = timeout;
24
+ this.innerBaseData = getBaseData();
25
+ this.handleZeroConf();
26
+ }
27
+
28
+ addUrlsListener = (
29
+ onNewUrlCallback: (urls: Set<string>) => void
30
+ ) => {
31
+ this.urlsListener = onNewUrlCallback;
32
+ };
33
+
34
+ private requestJoin = async (url: string, token: string) => {
35
+ const response = await fetch(url, {
36
+ method: "POST",
37
+ headers: {
38
+ "Content-Type": "application/json;charset=utf-8",
39
+ },
40
+ body: JSON.stringify({
41
+ token,
42
+ model: this.innerBaseData.Model ?? `${this.innerBaseData.systemName}v${this.innerBaseData.osVersion}`,
43
+ id: md5(JSON.stringify(this.innerBaseData)).toString(),
44
+ }),
45
+ });
46
+ if (response.status !== 200) {
47
+ return false;
48
+ }
49
+ const json = await response.json();
50
+ if (json.code !== 0) {
51
+ return false;
52
+ }
53
+ return true
54
+ }
55
+
56
+ private async handleZeroConf() {
57
+ try {
58
+ const Zeroconf = require("react-native-zeroconf")?.default;
59
+ if (!Zeroconf) {
60
+ return;
61
+ }
62
+ // @ts-ignore
63
+ const zeroconf: Zeroconf = new Zeroconf();
64
+ zeroconf.on("resolved", async (service) => {
65
+ try {
66
+ const { path, token } = service.txt ?? {};
67
+ const url = `http://${service.host}:${service.port}`;
68
+ if (!(path && token) || this.baseUrlArr.has(url)) {
69
+ return;
70
+ }
71
+ if (!(await this.requestJoin(`${url}${path}`, token))) {
72
+ return;
73
+ }
74
+ this.baseUrlArr.add(url);
75
+ this.urlsObj.set(service.name, url)
76
+ if (this.urlsListener) {
77
+ this.urlsListener(this.baseUrlArr);
78
+ }
79
+ } catch (error) {
80
+ logger.warn(LOG_KEY, "加入日志系统失败---", error);
81
+ }
82
+ });
83
+ zeroconf.on("remove", (name) => {
84
+ const currentUrl = this.urlsObj.get(name);
85
+ this.baseUrlArr.delete(currentUrl)
86
+ this.urlsObj.delete(name)
87
+ if (this.urlsListener) {
88
+ this.urlsListener(this.baseUrlArr);
89
+ }
90
+ });
91
+ zeroconf.on("error", (err) => {
92
+ logger.warn(LOG_KEY, "zeroconf出现错误", err);
93
+ })
94
+ zeroconf.scan("http", "tcp");
95
+ } catch (error: any) {
96
+ logger.warn(LOG_KEY, "zeroconf扫描或处理相关逻辑失败或者您根本就没有安装 react-native-zeroconf ,如果您没有安装,那么您将无法使用发现功能", error);
97
+ }
98
+ }
99
+
100
+ updateTimeout(timeout = 3000) {
101
+ this.timeout = timeout;
102
+ }
103
+
104
+ private send = async (
105
+ path: string,
106
+ data: Record<string, any>
107
+ ): Promise<void> => {
108
+ const request = async (url: string, _data: Record<string, any>) => {
109
+ await Promise.race([
110
+ fetch(`${url}/${path}`, {
111
+ method: "POST",
112
+ headers: {
113
+ "Content-Type": "application/json;charset=utf-8",
114
+ },
115
+ body: JSON.stringify(
116
+ { ...this.innerBaseData, ...this.baseData, ..._data },
117
+ (_, val) => {
118
+ if (val instanceof Error) {
119
+ return val.toString();
120
+ }
121
+ return val;
122
+ }
123
+ ),
124
+ }),
125
+ sleep(this.timeout, true),
126
+ ]);
127
+ };
128
+ if (this.baseUrlArr.size === 0) {
129
+ return;
130
+ }
131
+ this.baseUrlArr.forEach(async (e) => {
132
+ try {
133
+ await request(e, data)
134
+ } catch (error: any) {
135
+ if (error?.message?.includes("Network request failed") || error?.message?.includes("Timeout")) {
136
+ return
137
+ }
138
+ logger.warn(LOG_KEY, "上报日志失败", error)
139
+ }
140
+ })
141
+ };
142
+
143
+ updateUrl(url: string = '') {
144
+ const tempUrl = url.includes("http") ? url : `http://${url}`;
145
+ if (!url) {
146
+ const currentUrl = this.urlsObj.get("Default");
147
+ this.baseUrlArr.delete(currentUrl);
148
+ this.urlsObj.delete("Default");
149
+ } else if (!hasPort(tempUrl)) {
150
+ this.updateUrl(`${tempUrl}:${DEFAULT_PORT}`);
151
+ } else {
152
+ this.baseUrlArr.add(tempUrl);
153
+ this.urlsObj.set("Default", tempUrl);
154
+ }
155
+ }
156
+
157
+ setBaseUrlArr(urlArr: Set<string> = new Set()) {
158
+ this.baseUrlArr = urlArr;
159
+ }
160
+
161
+ getBaseUrlArr() {
162
+ return this.baseUrlArr;
163
+ }
164
+
165
+ updateBaseData(data: Record<string, any> = {}) {
166
+ this.baseData = data;
167
+ }
168
+
169
+ log = async (data: Record<string, any>) => {
170
+ return this.send("log", data);
171
+ };
172
+
173
+ network = async (data: Record<string, any>) => {
174
+ return this.send("network", data);
175
+ };
176
+ }
177
+
178
+ export default Server;
@@ -1,45 +1,45 @@
1
- class FileReader {
2
- constructor() {
3
- this.result = null;
4
- this.error = null;
5
- this.readyState = FileReader.EMPTY;
6
- }
7
-
8
- static EMPTY = 0;
9
- static LOADING = 1;
10
- static DONE = 2;
11
-
12
- addEventListener(event, callback) {
13
- this[`on${event}`] = callback;
14
- }
15
-
16
- removeEventListener(event, callback) {
17
- if (this[`on${event}`] === callback) {
18
- this[`on${event}`] = null;
19
- }
20
- }
21
-
22
- readAsText(blob) {
23
- this._read(blob, 'text');
24
- }
25
-
26
- readAsArrayBuffer(blob) {
27
- this._read(blob, 'arraybuffer');
28
- }
29
-
30
- _read(blob, resultType) {
31
- this.readyState = FileReader.LOADING;
32
- setTimeout(() => {
33
- this.readyState = FileReader.DONE;
34
- if (resultType === 'text') {
35
- this.result = blob.text();
36
- } else if (resultType === 'arraybuffer') {
37
- // 这里我们简单地返回一个空的 ArrayBuffer
38
- this.result = new ArrayBuffer(0);
39
- }
40
- if (this.onload) this.onload({target: this});
41
- }, 0);
42
- }
43
- }
44
-
1
+ class FileReader {
2
+ constructor() {
3
+ this.result = null;
4
+ this.error = null;
5
+ this.readyState = FileReader.EMPTY;
6
+ }
7
+
8
+ static EMPTY = 0;
9
+ static LOADING = 1;
10
+ static DONE = 2;
11
+
12
+ addEventListener(event, callback) {
13
+ this[`on${event}`] = callback;
14
+ }
15
+
16
+ removeEventListener(event, callback) {
17
+ if (this[`on${event}`] === callback) {
18
+ this[`on${event}`] = null;
19
+ }
20
+ }
21
+
22
+ readAsText(blob) {
23
+ this._read(blob, 'text');
24
+ }
25
+
26
+ readAsArrayBuffer(blob) {
27
+ this._read(blob, 'arraybuffer');
28
+ }
29
+
30
+ _read(blob, resultType) {
31
+ this.readyState = FileReader.LOADING;
32
+ setTimeout(() => {
33
+ this.readyState = FileReader.DONE;
34
+ if (resultType === 'text') {
35
+ this.result = blob.text();
36
+ } else if (resultType === 'arraybuffer') {
37
+ // 这里我们简单地返回一个空的 ArrayBuffer
38
+ this.result = new ArrayBuffer(0);
39
+ }
40
+ if (this.onload) this.onload({target: this});
41
+ }, 0);
42
+ }
43
+ }
44
+
45
45
  module.exports = FileReader;
@@ -1,39 +1,39 @@
1
- // __mocks__/react-native/Libraries/XHRInterceptor.js
2
-
3
- class XHRInterceptor {
4
- static _isInterceptorEnabled = false
5
- static openCallback = null
6
- static requestHeaderCallback = null
7
- static headerReceivedCallback = null
8
- static sendCallback = null
9
- static responseCallback = null
10
-
11
- static setOpenCallback = jest.fn((callback) => {
12
- XHRInterceptor.openCallback = callback;
13
- })
14
- static setRequestHeaderCallback = jest.fn((callback) => {
15
- XHRInterceptor.requestHeaderCallback = callback;
16
- })
17
- static setHeaderReceivedCallback = jest.fn((callback) => {
18
- XHRInterceptor.headerReceivedCallback = callback;
19
- })
20
- static setSendCallback = jest.fn((callback) => {
21
- XHRInterceptor.sendCallback = callback;
22
- })
23
- static setResponseCallback = jest.fn((callback) => {
24
- XHRInterceptor.responseCallback = callback;
25
- })
26
-
27
- static enableInterception = jest.fn(() => {
28
- XHRInterceptor._isInterceptorEnabled = true;
29
- })
30
-
31
- static disableInterception = jest.fn(() => {
32
- XHRInterceptor._isInterceptorEnabled = false;
33
- })
34
-
35
- static isInterceptorEnabled = jest.fn(() => XHRInterceptor._isInterceptorEnabled)
36
- };
37
-
38
- module.exports = XHRInterceptor;
39
-
1
+ // __mocks__/react-native/Libraries/XHRInterceptor.js
2
+
3
+ class XHRInterceptor {
4
+ static _isInterceptorEnabled = false
5
+ static openCallback = null
6
+ static requestHeaderCallback = null
7
+ static headerReceivedCallback = null
8
+ static sendCallback = null
9
+ static responseCallback = null
10
+
11
+ static setOpenCallback = jest.fn((callback) => {
12
+ XHRInterceptor.openCallback = callback;
13
+ })
14
+ static setRequestHeaderCallback = jest.fn((callback) => {
15
+ XHRInterceptor.requestHeaderCallback = callback;
16
+ })
17
+ static setHeaderReceivedCallback = jest.fn((callback) => {
18
+ XHRInterceptor.headerReceivedCallback = callback;
19
+ })
20
+ static setSendCallback = jest.fn((callback) => {
21
+ XHRInterceptor.sendCallback = callback;
22
+ })
23
+ static setResponseCallback = jest.fn((callback) => {
24
+ XHRInterceptor.responseCallback = callback;
25
+ })
26
+
27
+ static enableInterception = jest.fn(() => {
28
+ XHRInterceptor._isInterceptorEnabled = true;
29
+ })
30
+
31
+ static disableInterception = jest.fn(() => {
32
+ XHRInterceptor._isInterceptorEnabled = false;
33
+ })
34
+
35
+ static isInterceptorEnabled = jest.fn(() => XHRInterceptor._isInterceptorEnabled)
36
+ };
37
+
38
+ module.exports = XHRInterceptor;
39
+