@wutiange/log-listener-plugin 2.0.1-alpha.2 → 2.0.1-alpha.4

Sign up to get free protection for your applications and to get access to all the features.
package/src/Server.ts CHANGED
@@ -1,164 +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,
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
- logger.warn(LOG_KEY, "上报日志失败", error)
135
- }
136
- };
137
-
138
- updateUrl(url: string) {
139
- const tempUrl = url.includes("http") ? url : `http://${url}`;
140
- if (!url) {
141
- delete this.baseUrlObj["Default"];
142
- } else {
143
- this.baseUrlObj["Default"] = tempUrl;
144
- }
145
- }
146
-
147
- setBaseUrlObj(urlObj: Record<string, string>) {
148
- this.baseUrlObj = urlObj;
149
- }
150
-
151
- updateBaseData(data: Record<string, any>) {
152
- this.baseData = data;
153
- }
154
-
155
- log = async (data: Record<string, any>) => {
156
- return this.send("log", data);
157
- };
158
-
159
- network = async (data: Record<string, any>) => {
160
- return this.send("network", data);
161
- };
162
- }
163
-
164
- export default Server;
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 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
+