@kevisual/query 0.0.40 → 0.0.42
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/query-adapter.js +107 -124
- package/dist/query-api.d.ts +317 -0
- package/dist/query-api.js +449 -0
- package/dist/query-browser.d.ts +1 -8
- package/dist/query-browser.js +489 -582
- package/dist/query-ws.js +163 -181
- package/dist/query.d.ts +1 -8
- package/dist/query.js +278 -359
- package/package.json +13 -25
- package/src/adapter.ts +1 -1
- package/src/create-query/index.ts +159 -0
- package/src/query-api.ts +136 -0
- package/src/query-browser.ts +2 -2
- package/src/query.ts +1 -10
package/dist/query-browser.js
CHANGED
|
@@ -1,131 +1,114 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// src/adapter.ts
|
|
2
|
+
var isTextForContentType = (contentType) => {
|
|
3
|
+
if (!contentType)
|
|
4
|
+
return false;
|
|
5
|
+
const textTypes = ["text/", "xml", "html", "javascript", "css", "csv", "plain", "x-www-form-urlencoded", "md"];
|
|
6
|
+
return textTypes.some((type) => contentType.includes(type));
|
|
6
7
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
else {
|
|
106
|
-
return response;
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
.catch((err) => {
|
|
110
|
-
if (err.name === 'AbortError') {
|
|
111
|
-
return {
|
|
112
|
-
code: 408,
|
|
113
|
-
message: '请求超时',
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
code: 500,
|
|
118
|
-
message: err.message || '网络错误',
|
|
119
|
-
};
|
|
120
|
-
})
|
|
121
|
-
.finally(() => {
|
|
122
|
-
clearTimeout(timer);
|
|
123
|
-
});
|
|
8
|
+
var adapter = async (opts = {}, overloadOpts) => {
|
|
9
|
+
const controller = new AbortController;
|
|
10
|
+
const signal = controller.signal;
|
|
11
|
+
const isPostFile = opts.isPostFile || false;
|
|
12
|
+
let responseType = opts.responseType || "json";
|
|
13
|
+
if (opts.isBlob) {
|
|
14
|
+
responseType = "blob";
|
|
15
|
+
} else if (opts.isText) {
|
|
16
|
+
responseType = "text";
|
|
17
|
+
}
|
|
18
|
+
const timeout = opts.timeout || 60000 * 3;
|
|
19
|
+
const timer = setTimeout(() => {
|
|
20
|
+
controller.abort();
|
|
21
|
+
}, timeout);
|
|
22
|
+
let method = overloadOpts?.method || opts?.method || "POST";
|
|
23
|
+
let headers = { ...opts?.headers, ...overloadOpts?.headers };
|
|
24
|
+
let origin = "";
|
|
25
|
+
let url;
|
|
26
|
+
if (opts?.url?.startsWith("http")) {
|
|
27
|
+
url = new URL(opts.url);
|
|
28
|
+
} else {
|
|
29
|
+
origin = globalThis?.location?.origin || "http://localhost:51515";
|
|
30
|
+
url = new URL(opts?.url || "", origin);
|
|
31
|
+
}
|
|
32
|
+
const isGet = method === "GET";
|
|
33
|
+
const oldSearchParams = url.searchParams;
|
|
34
|
+
if (isGet) {
|
|
35
|
+
let searchParams = new URLSearchParams({ ...Object.fromEntries(oldSearchParams), ...opts?.params, ...opts?.body });
|
|
36
|
+
url.search = searchParams.toString();
|
|
37
|
+
} else {
|
|
38
|
+
const params = {
|
|
39
|
+
...Object.fromEntries(oldSearchParams),
|
|
40
|
+
...opts.params
|
|
41
|
+
};
|
|
42
|
+
const searchParams = new URLSearchParams(params);
|
|
43
|
+
if (typeof opts.body === "object" && opts.body !== null) {
|
|
44
|
+
let body2 = opts.body || {};
|
|
45
|
+
if (!params.path && body2?.path) {
|
|
46
|
+
searchParams.set("path", body2.path);
|
|
47
|
+
if (body2?.key) {
|
|
48
|
+
searchParams.set("key", body2.key);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
url.search = searchParams.toString();
|
|
53
|
+
}
|
|
54
|
+
let body = undefined;
|
|
55
|
+
if (isGet) {
|
|
56
|
+
body = undefined;
|
|
57
|
+
} else if (isPostFile) {
|
|
58
|
+
body = opts.body;
|
|
59
|
+
} else {
|
|
60
|
+
if (opts.body && typeof opts.body === "object" && !(opts.body instanceof FormData)) {
|
|
61
|
+
headers = {
|
|
62
|
+
"Content-Type": "application/json",
|
|
63
|
+
...headers
|
|
64
|
+
};
|
|
65
|
+
body = JSON.stringify(opts.body);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return fetch(url, {
|
|
69
|
+
method: method.toUpperCase(),
|
|
70
|
+
signal,
|
|
71
|
+
body,
|
|
72
|
+
...overloadOpts,
|
|
73
|
+
headers
|
|
74
|
+
}).then(async (response) => {
|
|
75
|
+
const contentType = response.headers.get("Content-Type");
|
|
76
|
+
if (responseType === "blob") {
|
|
77
|
+
return await response.blob();
|
|
78
|
+
}
|
|
79
|
+
const isText = responseType === "text";
|
|
80
|
+
const isJson = contentType && contentType.includes("application/json");
|
|
81
|
+
if (isJson && !isText) {
|
|
82
|
+
return await response.json();
|
|
83
|
+
} else if (isTextForContentType(contentType)) {
|
|
84
|
+
return {
|
|
85
|
+
code: response.status,
|
|
86
|
+
status: response.status,
|
|
87
|
+
data: await response.text()
|
|
88
|
+
};
|
|
89
|
+
} else {
|
|
90
|
+
return response;
|
|
91
|
+
}
|
|
92
|
+
}).catch((err) => {
|
|
93
|
+
if (err.name === "AbortError") {
|
|
94
|
+
return {
|
|
95
|
+
code: 408,
|
|
96
|
+
message: "请求超时"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
code: 500,
|
|
101
|
+
message: err.message || "网络错误"
|
|
102
|
+
};
|
|
103
|
+
}).finally(() => {
|
|
104
|
+
clearTimeout(timer);
|
|
105
|
+
});
|
|
124
106
|
};
|
|
125
107
|
|
|
126
|
-
|
|
108
|
+
// node_modules/.pnpm/zustand@5.0.11/node_modules/zustand/esm/vanilla.mjs
|
|
109
|
+
var createStoreImpl = (createState) => {
|
|
127
110
|
let state;
|
|
128
|
-
const listeners = /* @__PURE__ */ new Set
|
|
111
|
+
const listeners = /* @__PURE__ */ new Set;
|
|
129
112
|
const setState = (partial, replace) => {
|
|
130
113
|
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
131
114
|
if (!Object.is(nextState, state)) {
|
|
@@ -144,479 +127,403 @@ const createStoreImpl = (createState) => {
|
|
|
144
127
|
const initialState = state = createState(setState, getState, api);
|
|
145
128
|
return api;
|
|
146
129
|
};
|
|
147
|
-
|
|
130
|
+
var createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
148
131
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
132
|
+
// src/utils.ts
|
|
133
|
+
var parseWsUrl = (url) => {
|
|
134
|
+
try {
|
|
135
|
+
new URL(url);
|
|
136
|
+
return url;
|
|
137
|
+
} catch (e) {
|
|
138
|
+
const _url = new URL(url, location.origin);
|
|
139
|
+
if (_url.protocol === "http:") {
|
|
140
|
+
_url.protocol = "ws:";
|
|
141
|
+
}
|
|
142
|
+
if (_url.protocol === "https:") {
|
|
143
|
+
_url.protocol = "wss:";
|
|
144
|
+
}
|
|
145
|
+
return _url.href;
|
|
146
|
+
}
|
|
164
147
|
};
|
|
165
148
|
|
|
149
|
+
// src/ws.ts
|
|
166
150
|
class QueryWs {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
store.getState().setStatus('connected');
|
|
219
|
-
resolve(true);
|
|
220
|
-
clearTimeout(timer);
|
|
221
|
-
};
|
|
222
|
-
ws.onclose = (ev) => {
|
|
223
|
-
store.getState().setConnected(false);
|
|
224
|
-
store.getState().setStatus('disconnected');
|
|
225
|
-
this.ws = null;
|
|
226
|
-
};
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* ws.onopen 必须用这个去获取,否者会丢失链接信息
|
|
231
|
-
* @param callback
|
|
232
|
-
* @returns
|
|
233
|
-
*/
|
|
234
|
-
listenConnect(callback) {
|
|
235
|
-
const store = this.store;
|
|
236
|
-
const { connected } = store.getState();
|
|
237
|
-
if (connected) {
|
|
238
|
-
callback();
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
const subscriptionOne = (selector, listener) => {
|
|
242
|
-
const unsubscribe = store.subscribe((newState, oldState) => {
|
|
243
|
-
if (selector(newState) !== selector(oldState)) {
|
|
244
|
-
listener(newState, oldState);
|
|
245
|
-
unsubscribe();
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
return unsubscribe;
|
|
249
|
-
};
|
|
250
|
-
const cancel = subscriptionOne((state) => state.connected, () => {
|
|
251
|
-
callback();
|
|
252
|
-
});
|
|
253
|
-
return cancel;
|
|
254
|
-
}
|
|
255
|
-
listenClose(callback) {
|
|
256
|
-
const store = this.store;
|
|
257
|
-
const { status } = store.getState();
|
|
258
|
-
if (status === 'disconnected') {
|
|
259
|
-
callback();
|
|
260
|
-
}
|
|
261
|
-
const subscriptionOne = (selector, listener) => {
|
|
262
|
-
const unsubscribe = store.subscribe((newState, oldState) => {
|
|
263
|
-
if (selector(newState) !== selector(oldState)) {
|
|
264
|
-
listener(newState, oldState);
|
|
265
|
-
unsubscribe();
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
return unsubscribe;
|
|
269
|
-
};
|
|
270
|
-
const cancel = subscriptionOne((state) => state.status, (newState, oldState) => {
|
|
271
|
-
if (newState.status === 'disconnected') {
|
|
272
|
-
callback();
|
|
273
|
-
}
|
|
274
|
-
});
|
|
275
|
-
return cancel;
|
|
276
|
-
}
|
|
277
|
-
onMessage(fn, opts) {
|
|
278
|
-
const ws = this.ws;
|
|
279
|
-
const isJson = opts?.isJson ?? true;
|
|
280
|
-
const selector = opts?.selector;
|
|
281
|
-
const parseIfJson = (data) => {
|
|
282
|
-
try {
|
|
283
|
-
return JSON.parse(data);
|
|
284
|
-
}
|
|
285
|
-
catch (e) {
|
|
286
|
-
return data;
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
const listener = (event) => {
|
|
290
|
-
const received = parseIfJson(event.data);
|
|
291
|
-
if (typeof received === 'string' && !isJson) {
|
|
292
|
-
fn(received, event);
|
|
293
|
-
}
|
|
294
|
-
else if (typeof received === 'object' && isJson) {
|
|
295
|
-
fn(selector ? selector(received) : received, event);
|
|
296
|
-
}
|
|
297
|
-
else ;
|
|
298
|
-
};
|
|
299
|
-
ws.addEventListener('message', listener);
|
|
300
|
-
return () => {
|
|
301
|
-
ws.removeEventListener('message', listener);
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
close() {
|
|
305
|
-
const ws = this.ws;
|
|
306
|
-
const store = this.store;
|
|
307
|
-
ws?.close?.();
|
|
308
|
-
this.ws = null;
|
|
151
|
+
url;
|
|
152
|
+
store;
|
|
153
|
+
ws;
|
|
154
|
+
constructor(opts) {
|
|
155
|
+
const url = opts?.url || "/api/router";
|
|
156
|
+
if (opts?.store) {
|
|
157
|
+
this.store = opts.store;
|
|
158
|
+
} else {
|
|
159
|
+
const store = createStore((set) => ({
|
|
160
|
+
connected: false,
|
|
161
|
+
status: "connecting",
|
|
162
|
+
setConnected: (connected) => set({ connected }),
|
|
163
|
+
setStatus: (status) => set({ status })
|
|
164
|
+
}));
|
|
165
|
+
this.store = store;
|
|
166
|
+
}
|
|
167
|
+
const wsUrl = parseWsUrl(url);
|
|
168
|
+
if (opts?.ws && opts.ws instanceof WebSocket) {
|
|
169
|
+
this.ws = opts.ws;
|
|
170
|
+
} else {
|
|
171
|
+
this.ws = new WebSocket(wsUrl);
|
|
172
|
+
}
|
|
173
|
+
this.connect();
|
|
174
|
+
}
|
|
175
|
+
async connect(opts) {
|
|
176
|
+
const store = this.store;
|
|
177
|
+
const that = this;
|
|
178
|
+
const connected = store.getState().connected;
|
|
179
|
+
if (connected) {
|
|
180
|
+
return Promise.resolve(true);
|
|
181
|
+
}
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
const ws = that.ws || new WebSocket(that.url);
|
|
184
|
+
const timeout = opts?.timeout || 5 * 60 * 1000;
|
|
185
|
+
let timer = setTimeout(() => {
|
|
186
|
+
const isOpen = ws.readyState === WebSocket.OPEN;
|
|
187
|
+
if (isOpen) {
|
|
188
|
+
console.log("WebSocket 连接成功 in timer");
|
|
189
|
+
resolve(true);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
console.error("WebSocket 连接超时", that.url);
|
|
193
|
+
resolve(false);
|
|
194
|
+
}, timeout);
|
|
195
|
+
ws.onopen = (ev) => {
|
|
196
|
+
store.getState().setConnected(true);
|
|
197
|
+
store.getState().setStatus("connected");
|
|
198
|
+
resolve(true);
|
|
199
|
+
clearTimeout(timer);
|
|
200
|
+
};
|
|
201
|
+
ws.onclose = (ev) => {
|
|
309
202
|
store.getState().setConnected(false);
|
|
310
|
-
store.getState().setStatus(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
203
|
+
store.getState().setStatus("disconnected");
|
|
204
|
+
this.ws = null;
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
listenConnect(callback) {
|
|
209
|
+
const store = this.store;
|
|
210
|
+
const { connected } = store.getState();
|
|
211
|
+
if (connected) {
|
|
212
|
+
callback();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const subscriptionOne = (selector, listener) => {
|
|
216
|
+
const unsubscribe = store.subscribe((newState, oldState) => {
|
|
217
|
+
if (selector(newState) !== selector(oldState)) {
|
|
218
|
+
listener(newState, oldState);
|
|
219
|
+
unsubscribe();
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
return unsubscribe;
|
|
223
|
+
};
|
|
224
|
+
const cancel = subscriptionOne((state) => state.connected, () => {
|
|
225
|
+
callback();
|
|
226
|
+
});
|
|
227
|
+
return cancel;
|
|
228
|
+
}
|
|
229
|
+
listenClose(callback) {
|
|
230
|
+
const store = this.store;
|
|
231
|
+
const { status } = store.getState();
|
|
232
|
+
if (status === "disconnected") {
|
|
233
|
+
callback();
|
|
234
|
+
}
|
|
235
|
+
const subscriptionOne = (selector, listener) => {
|
|
236
|
+
const unsubscribe = store.subscribe((newState, oldState) => {
|
|
237
|
+
if (selector(newState) !== selector(oldState)) {
|
|
238
|
+
listener(newState, oldState);
|
|
239
|
+
unsubscribe();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
return unsubscribe;
|
|
243
|
+
};
|
|
244
|
+
const cancel = subscriptionOne((state) => state.status, (newState, oldState) => {
|
|
245
|
+
if (newState.status === "disconnected") {
|
|
246
|
+
callback();
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
return cancel;
|
|
250
|
+
}
|
|
251
|
+
onMessage(fn, opts) {
|
|
252
|
+
const ws = this.ws;
|
|
253
|
+
const isJson = opts?.isJson ?? true;
|
|
254
|
+
const selector = opts?.selector;
|
|
255
|
+
const parseIfJson = (data) => {
|
|
256
|
+
try {
|
|
257
|
+
return JSON.parse(data);
|
|
258
|
+
} catch (e) {
|
|
259
|
+
return data;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
const listener = (event) => {
|
|
263
|
+
const received = parseIfJson(event.data);
|
|
264
|
+
if (typeof received === "string" && !isJson) {
|
|
265
|
+
fn(received, event);
|
|
266
|
+
} else if (typeof received === "object" && isJson) {
|
|
267
|
+
fn(selector ? selector(received) : received, event);
|
|
268
|
+
} else {}
|
|
269
|
+
};
|
|
270
|
+
ws.addEventListener("message", listener);
|
|
271
|
+
return () => {
|
|
272
|
+
ws.removeEventListener("message", listener);
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
close() {
|
|
276
|
+
const ws = this.ws;
|
|
277
|
+
const store = this.store;
|
|
278
|
+
ws?.close?.();
|
|
279
|
+
this.ws = null;
|
|
280
|
+
store.getState().setConnected(false);
|
|
281
|
+
store.getState().setStatus("disconnected");
|
|
282
|
+
}
|
|
283
|
+
send(data, opts) {
|
|
284
|
+
const ws = this.ws;
|
|
285
|
+
const isJson = opts?.isJson ?? true;
|
|
286
|
+
const wrapper = opts?.wrapper;
|
|
287
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
288
|
+
console.error("WebSocket is not open");
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (isJson) {
|
|
292
|
+
ws.send(JSON.stringify(wrapper ? wrapper(data) : data));
|
|
293
|
+
} else {
|
|
294
|
+
ws.send(data);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
getOpen() {
|
|
298
|
+
if (!this.ws) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
return this.ws.readyState === WebSocket.OPEN;
|
|
302
|
+
}
|
|
340
303
|
}
|
|
341
304
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return result;
|
|
305
|
+
// src/query.ts
|
|
306
|
+
var wrapperError = ({ code, message }) => {
|
|
307
|
+
const result = {
|
|
308
|
+
code: code || 500,
|
|
309
|
+
success: false,
|
|
310
|
+
message: message || "api request error",
|
|
311
|
+
showError: (fn) => {},
|
|
312
|
+
noMsg: true
|
|
313
|
+
};
|
|
314
|
+
return result;
|
|
353
315
|
};
|
|
354
|
-
|
|
355
|
-
* const query = new Query();
|
|
356
|
-
* const res = await query.post({
|
|
357
|
-
* path: 'demo',
|
|
358
|
-
* key: '1',
|
|
359
|
-
* });
|
|
360
|
-
*
|
|
361
|
-
* U是参数 V是返回值
|
|
362
|
-
*/
|
|
316
|
+
|
|
363
317
|
class Query {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
catch (e) {
|
|
467
|
-
console.error('request beforeFn error', e, req);
|
|
468
|
-
return wrapperError({
|
|
469
|
-
code: 500,
|
|
470
|
-
message: 'api request beforeFn error'});
|
|
471
|
-
}
|
|
472
|
-
if (this.stop && !options?.noStop) {
|
|
473
|
-
const that = this;
|
|
474
|
-
await new Promise((resolve) => {
|
|
475
|
-
let timer = 0;
|
|
476
|
-
const detect = setInterval(() => {
|
|
477
|
-
if (!that.stop) {
|
|
478
|
-
clearInterval(detect);
|
|
479
|
-
resolve(true);
|
|
480
|
-
}
|
|
481
|
-
timer++;
|
|
482
|
-
if (timer > 30) {
|
|
483
|
-
console.error('request stop: timeout', req.url, timer);
|
|
484
|
-
}
|
|
485
|
-
}, 1000);
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
return _adapter(req).then(async (res) => {
|
|
489
|
-
try {
|
|
490
|
-
if (_afterResponse) {
|
|
491
|
-
return await _afterResponse(res, {
|
|
492
|
-
req,
|
|
493
|
-
res,
|
|
494
|
-
fetch: adapter,
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
return res;
|
|
498
|
-
}
|
|
499
|
-
catch (e) {
|
|
500
|
-
console.error('request afterFn error', e, req);
|
|
501
|
-
return wrapperError({
|
|
502
|
-
code: 500,
|
|
503
|
-
message: 'api request afterFn error'});
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* 设置请求前处理,设置请求前处理函数
|
|
509
|
-
* @param fn 处理函数
|
|
510
|
-
*/
|
|
511
|
-
before(fn) {
|
|
512
|
-
this.beforeRequest = fn;
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* 设置请求后处理,设置请求后处理函数
|
|
516
|
-
* @param fn 处理函数
|
|
517
|
-
*/
|
|
518
|
-
after(fn) {
|
|
519
|
-
this.afterResponse = fn;
|
|
520
|
-
}
|
|
521
|
-
async fetchText(urlOrOptions, options) {
|
|
522
|
-
let _options = { ...options };
|
|
523
|
-
if (typeof urlOrOptions === 'string' && !_options.url) {
|
|
524
|
-
_options.url = urlOrOptions;
|
|
525
|
-
}
|
|
526
|
-
if (typeof urlOrOptions === 'object') {
|
|
527
|
-
_options = { ...urlOrOptions, ..._options };
|
|
528
|
-
}
|
|
529
|
-
const res = await adapter({
|
|
530
|
-
method: 'GET',
|
|
531
|
-
..._options,
|
|
532
|
-
headers: {
|
|
533
|
-
...this.headers,
|
|
534
|
-
...(_options?.headers || {}),
|
|
535
|
-
},
|
|
536
|
-
});
|
|
537
|
-
if (res && !res.code) {
|
|
538
|
-
return {
|
|
539
|
-
code: 200,
|
|
540
|
-
data: res,
|
|
541
|
-
};
|
|
318
|
+
adapter;
|
|
319
|
+
url;
|
|
320
|
+
beforeRequest;
|
|
321
|
+
afterResponse;
|
|
322
|
+
headers;
|
|
323
|
+
timeout;
|
|
324
|
+
stop;
|
|
325
|
+
qws;
|
|
326
|
+
isClient = false;
|
|
327
|
+
constructor(opts) {
|
|
328
|
+
this.adapter = opts?.adapter || adapter;
|
|
329
|
+
const defaultURL = opts?.isClient ? "/client/router" : "/api/router";
|
|
330
|
+
this.url = opts?.url || defaultURL;
|
|
331
|
+
this.headers = opts?.headers || {
|
|
332
|
+
"Content-Type": "application/json"
|
|
333
|
+
};
|
|
334
|
+
this.timeout = opts?.timeout || 60000 * 3;
|
|
335
|
+
if (opts?.beforeRequest) {
|
|
336
|
+
this.beforeRequest = opts.beforeRequest;
|
|
337
|
+
} else {
|
|
338
|
+
this.beforeRequest = async (opts2) => {
|
|
339
|
+
const token = globalThis?.localStorage?.getItem("token");
|
|
340
|
+
if (token) {
|
|
341
|
+
opts2.headers = {
|
|
342
|
+
...opts2.headers,
|
|
343
|
+
Authorization: `Bearer ${token}`
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
return opts2;
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
setQueryWs(qws) {
|
|
351
|
+
this.qws = qws;
|
|
352
|
+
}
|
|
353
|
+
setStop(stop) {
|
|
354
|
+
this.stop = stop;
|
|
355
|
+
}
|
|
356
|
+
async get(params, options) {
|
|
357
|
+
return this.post(params, options);
|
|
358
|
+
}
|
|
359
|
+
async post(body, options) {
|
|
360
|
+
const url = options?.url || this.url;
|
|
361
|
+
console.log("query post", url, body, options);
|
|
362
|
+
const { headers, adapter: adapter2, beforeRequest, afterResponse, timeout, ...rest } = options || {};
|
|
363
|
+
const _headers = { ...this.headers, ...headers };
|
|
364
|
+
const _adapter = adapter2 || this.adapter;
|
|
365
|
+
const _beforeRequest = beforeRequest || this.beforeRequest;
|
|
366
|
+
const _afterResponse = afterResponse || this.afterResponse;
|
|
367
|
+
const _timeout = timeout || this.timeout;
|
|
368
|
+
const req = {
|
|
369
|
+
url,
|
|
370
|
+
headers: _headers,
|
|
371
|
+
body,
|
|
372
|
+
timeout: _timeout,
|
|
373
|
+
...rest
|
|
374
|
+
};
|
|
375
|
+
try {
|
|
376
|
+
if (_beforeRequest) {
|
|
377
|
+
const res = await _beforeRequest(req);
|
|
378
|
+
if (res === false) {
|
|
379
|
+
return wrapperError({
|
|
380
|
+
code: 500,
|
|
381
|
+
message: "request is cancel",
|
|
382
|
+
req
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} catch (e) {
|
|
387
|
+
console.error("request beforeFn error", e, req);
|
|
388
|
+
return wrapperError({
|
|
389
|
+
code: 500,
|
|
390
|
+
message: "api request beforeFn error",
|
|
391
|
+
req
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
if (this.stop && !options?.noStop) {
|
|
395
|
+
const that = this;
|
|
396
|
+
await new Promise((resolve) => {
|
|
397
|
+
let timer = 0;
|
|
398
|
+
const detect = setInterval(() => {
|
|
399
|
+
if (!that.stop) {
|
|
400
|
+
clearInterval(detect);
|
|
401
|
+
resolve(true);
|
|
402
|
+
}
|
|
403
|
+
timer++;
|
|
404
|
+
if (timer > 30) {
|
|
405
|
+
console.error("request stop: timeout", req.url, timer);
|
|
406
|
+
}
|
|
407
|
+
}, 1000);
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
return _adapter(req).then(async (res) => {
|
|
411
|
+
try {
|
|
412
|
+
if (_afterResponse) {
|
|
413
|
+
return await _afterResponse(res, {
|
|
414
|
+
req,
|
|
415
|
+
res,
|
|
416
|
+
fetch: adapter2
|
|
417
|
+
});
|
|
542
418
|
}
|
|
543
419
|
return res;
|
|
544
|
-
|
|
420
|
+
} catch (e) {
|
|
421
|
+
console.error("request afterFn error", e, req);
|
|
422
|
+
return wrapperError({
|
|
423
|
+
code: 500,
|
|
424
|
+
message: "api request afterFn error",
|
|
425
|
+
req
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
before(fn) {
|
|
431
|
+
this.beforeRequest = fn;
|
|
432
|
+
}
|
|
433
|
+
after(fn) {
|
|
434
|
+
this.afterResponse = fn;
|
|
435
|
+
}
|
|
436
|
+
async fetchText(urlOrOptions, options) {
|
|
437
|
+
let _options = { ...options };
|
|
438
|
+
if (typeof urlOrOptions === "string" && !_options.url) {
|
|
439
|
+
_options.url = urlOrOptions;
|
|
440
|
+
}
|
|
441
|
+
if (typeof urlOrOptions === "object") {
|
|
442
|
+
_options = { ...urlOrOptions, ..._options };
|
|
443
|
+
}
|
|
444
|
+
const res = await adapter({
|
|
445
|
+
method: "GET",
|
|
446
|
+
..._options,
|
|
447
|
+
headers: {
|
|
448
|
+
...this.headers,
|
|
449
|
+
..._options?.headers || {}
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
if (res && !res.code) {
|
|
453
|
+
return {
|
|
454
|
+
code: 200,
|
|
455
|
+
data: res
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
return res;
|
|
459
|
+
}
|
|
545
460
|
}
|
|
546
461
|
class BaseQuery {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
post(data, options)
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
get(data, options)
|
|
568
|
-
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
/**
|
|
572
|
-
* @deprecated
|
|
573
|
-
* 前端调用后端QueryRouter, 默认路径 /client/router
|
|
574
|
-
*/
|
|
575
|
-
class ClientQuery extends Query {
|
|
576
|
-
constructor(opts) {
|
|
577
|
-
super({ ...opts, url: opts?.url || '/client/router' });
|
|
578
|
-
}
|
|
462
|
+
query;
|
|
463
|
+
queryDefine;
|
|
464
|
+
constructor(opts) {
|
|
465
|
+
if (opts?.clientQuery) {
|
|
466
|
+
this.query = opts.clientQuery;
|
|
467
|
+
} else {
|
|
468
|
+
this.query = opts?.query;
|
|
469
|
+
}
|
|
470
|
+
if (opts.queryDefine) {
|
|
471
|
+
this.queryDefine = opts.queryDefine;
|
|
472
|
+
this.queryDefine.query = this.query;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
get chain() {
|
|
476
|
+
return this.queryDefine.queryChain;
|
|
477
|
+
}
|
|
478
|
+
post(data, options) {
|
|
479
|
+
return this.query.post(data, options);
|
|
480
|
+
}
|
|
481
|
+
get(data, options) {
|
|
482
|
+
return this.query.get(data, options);
|
|
483
|
+
}
|
|
579
484
|
}
|
|
580
485
|
|
|
581
|
-
|
|
582
|
-
* 前端调用后端QueryRouter, 封装 beforeRequest 和 wss
|
|
583
|
-
*/
|
|
486
|
+
// src/query-browser.ts
|
|
584
487
|
class QueryClient extends Query {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
return opts;
|
|
488
|
+
tokenName;
|
|
489
|
+
storage;
|
|
490
|
+
token;
|
|
491
|
+
constructor(opts) {
|
|
492
|
+
super(opts);
|
|
493
|
+
this.tokenName = opts?.tokenName || "token";
|
|
494
|
+
this.storage = opts?.storage || globalThis.localStorage;
|
|
495
|
+
this.beforeRequest = async (opts2) => {
|
|
496
|
+
const token = this.token || this.getToken();
|
|
497
|
+
if (token) {
|
|
498
|
+
opts2.headers = {
|
|
499
|
+
...opts2.headers,
|
|
500
|
+
Authorization: `Bearer ${token}`
|
|
601
501
|
};
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
502
|
+
}
|
|
503
|
+
return opts2;
|
|
504
|
+
};
|
|
505
|
+
if (opts?.io) {
|
|
506
|
+
this.createWs();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
createWs(opts) {
|
|
510
|
+
this.qws = new QueryWs({ url: this.url, ...opts });
|
|
511
|
+
}
|
|
512
|
+
getToken() {
|
|
513
|
+
return this.storage.getItem(this.tokenName);
|
|
514
|
+
}
|
|
515
|
+
saveToken(token) {
|
|
516
|
+
this.storage.setItem(this.tokenName, token);
|
|
517
|
+
}
|
|
518
|
+
removeToken() {
|
|
519
|
+
this.storage.removeItem(this.tokenName);
|
|
520
|
+
}
|
|
618
521
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
522
|
+
export {
|
|
523
|
+
wrapperError,
|
|
524
|
+
adapter,
|
|
525
|
+
QueryWs,
|
|
526
|
+
QueryClient,
|
|
527
|
+
Query,
|
|
528
|
+
BaseQuery
|
|
529
|
+
};
|