@kevisual/api 0.0.52 → 0.0.54
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-ai.js +16 -3
- package/dist/query-app.js +16 -3
- package/dist/query-config.js +14 -1
- package/dist/query-login-node.d.ts +340 -0
- package/dist/query-login-node.js +1374 -0
- package/dist/query-login.js +17 -1
- package/dist/query-mark.js +14 -1
- package/dist/query-proxy.js +134 -76
- package/dist/query-resources.js +1 -1
- package/dist/query-secret.js +14 -1
- package/dist/query-shop.js +16 -3
- package/dist/store-mark.js +13 -0
- package/package.json +7 -6
- package/query/query-login/login-node-cache.ts +50 -25
- package/query/query-login/query-login-node.ts +8 -3
- package/query/query-login/query-login.ts +3 -0
|
@@ -0,0 +1,1374 @@
|
|
|
1
|
+
// node_modules/@kevisual/query/dist/query-browser.js
|
|
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", "json"];
|
|
6
|
+
return textTypes.some((type) => contentType.includes(type));
|
|
7
|
+
};
|
|
8
|
+
var adapter = async (opts = {}, overloadOpts) => {
|
|
9
|
+
const controller = new AbortController;
|
|
10
|
+
const signal = controller.signal;
|
|
11
|
+
const isPostFile = opts.isPostFile || false;
|
|
12
|
+
const timeout = opts.timeout || 60000 * 3;
|
|
13
|
+
const timer = setTimeout(() => {
|
|
14
|
+
controller.abort();
|
|
15
|
+
}, timeout);
|
|
16
|
+
let method = overloadOpts?.method || opts?.method || "POST";
|
|
17
|
+
let headers = { ...opts?.headers, ...overloadOpts?.headers };
|
|
18
|
+
let origin = "";
|
|
19
|
+
let url;
|
|
20
|
+
if (opts?.url?.startsWith("http")) {
|
|
21
|
+
url = new URL(opts.url);
|
|
22
|
+
} else {
|
|
23
|
+
origin = globalThis?.location?.origin || "http://localhost:51515";
|
|
24
|
+
url = new URL(opts?.url || "", origin);
|
|
25
|
+
}
|
|
26
|
+
const isGet = method === "GET";
|
|
27
|
+
const oldSearchParams = url.searchParams;
|
|
28
|
+
if (isGet) {
|
|
29
|
+
let searchParams = new URLSearchParams({ ...Object.fromEntries(oldSearchParams), ...opts?.params, ...opts?.body });
|
|
30
|
+
url.search = searchParams.toString();
|
|
31
|
+
} else {
|
|
32
|
+
const params = {
|
|
33
|
+
...Object.fromEntries(oldSearchParams),
|
|
34
|
+
...opts.params
|
|
35
|
+
};
|
|
36
|
+
const searchParams = new URLSearchParams(params);
|
|
37
|
+
if (typeof opts.body === "object" && opts.body !== null) {
|
|
38
|
+
let body2 = opts.body || {};
|
|
39
|
+
if (!params.path && body2?.path) {
|
|
40
|
+
searchParams.set("path", body2.path);
|
|
41
|
+
if (body2?.key) {
|
|
42
|
+
searchParams.set("key", body2.key);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
url.search = searchParams.toString();
|
|
47
|
+
}
|
|
48
|
+
let body = undefined;
|
|
49
|
+
if (isGet) {
|
|
50
|
+
body = undefined;
|
|
51
|
+
} else if (isPostFile) {
|
|
52
|
+
body = opts.body;
|
|
53
|
+
} else {
|
|
54
|
+
if (opts.body && typeof opts.body === "object" && !(opts.body instanceof FormData)) {
|
|
55
|
+
headers = {
|
|
56
|
+
"Content-Type": "application/json",
|
|
57
|
+
...headers
|
|
58
|
+
};
|
|
59
|
+
body = JSON.stringify(opts.body);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return fetch(url, {
|
|
63
|
+
method: method.toUpperCase(),
|
|
64
|
+
signal,
|
|
65
|
+
body,
|
|
66
|
+
...overloadOpts,
|
|
67
|
+
headers
|
|
68
|
+
}).then(async (response) => {
|
|
69
|
+
const contentType = response.headers.get("Content-Type");
|
|
70
|
+
const isJson = contentType && contentType.includes("application/json");
|
|
71
|
+
const isSuccess = response.ok;
|
|
72
|
+
if (isJson) {
|
|
73
|
+
const json = await response.json();
|
|
74
|
+
if (json?.code) {
|
|
75
|
+
return json;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
code: isSuccess ? 200 : response.status,
|
|
79
|
+
status: response.status,
|
|
80
|
+
data: json
|
|
81
|
+
};
|
|
82
|
+
} else if (isTextForContentType(contentType)) {
|
|
83
|
+
return {
|
|
84
|
+
code: isSuccess ? 200 : response.status,
|
|
85
|
+
status: response.status,
|
|
86
|
+
data: await response.text()
|
|
87
|
+
};
|
|
88
|
+
} else {
|
|
89
|
+
return {
|
|
90
|
+
code: isSuccess ? 200 : response.status,
|
|
91
|
+
status: response.status,
|
|
92
|
+
data: "非文本非JSON响应, 请手动处理response。",
|
|
93
|
+
response
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}).catch((err) => {
|
|
97
|
+
if (err.name === "AbortError") {
|
|
98
|
+
return {
|
|
99
|
+
code: 408,
|
|
100
|
+
message: "请求超时"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
code: 500,
|
|
105
|
+
message: err.message || "网络错误"
|
|
106
|
+
};
|
|
107
|
+
}).finally(() => {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
var wrapperError = ({ code, message }) => {
|
|
112
|
+
const result = {
|
|
113
|
+
code: code || 500,
|
|
114
|
+
message: message || "请求错误"
|
|
115
|
+
};
|
|
116
|
+
return result;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
class Query {
|
|
120
|
+
adapter;
|
|
121
|
+
baseURL;
|
|
122
|
+
url;
|
|
123
|
+
beforeRequest;
|
|
124
|
+
afterResponse;
|
|
125
|
+
headers;
|
|
126
|
+
timeout;
|
|
127
|
+
stop;
|
|
128
|
+
qws;
|
|
129
|
+
tokenName;
|
|
130
|
+
storage;
|
|
131
|
+
token;
|
|
132
|
+
constructor(opts) {
|
|
133
|
+
this.adapter = opts?.adapter || adapter;
|
|
134
|
+
this.tokenName = opts?.tokenName || "token";
|
|
135
|
+
this.storage = opts?.storage || globalThis?.localStorage;
|
|
136
|
+
const defaultURL = opts?.isClient ? "/client/router" : "/api/router";
|
|
137
|
+
this.url = opts?.url || defaultURL;
|
|
138
|
+
if (this.url.startsWith("http")) {
|
|
139
|
+
const urlObj = new URL(this.url);
|
|
140
|
+
this.baseURL = urlObj.origin;
|
|
141
|
+
}
|
|
142
|
+
this.baseURL = opts?.baseURL || this.baseURL;
|
|
143
|
+
this.headers = opts?.headers || {
|
|
144
|
+
"Content-Type": "application/json"
|
|
145
|
+
};
|
|
146
|
+
this.timeout = opts?.timeout || 60000 * 3;
|
|
147
|
+
if (opts?.beforeRequest) {
|
|
148
|
+
this.beforeRequest = opts.beforeRequest;
|
|
149
|
+
} else {
|
|
150
|
+
this.beforeRequest = async (opts2) => {
|
|
151
|
+
const token = this.token || this.storage?.getItem?.(this.tokenName);
|
|
152
|
+
if (token) {
|
|
153
|
+
opts2.headers = {
|
|
154
|
+
...opts2.headers,
|
|
155
|
+
Authorization: `Bearer ${token}`
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return opts2;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
setQueryWs(qws) {
|
|
163
|
+
this.qws = qws;
|
|
164
|
+
}
|
|
165
|
+
setStop(stop) {
|
|
166
|
+
this.stop = stop;
|
|
167
|
+
}
|
|
168
|
+
async get(params, options) {
|
|
169
|
+
return this.post(params, options);
|
|
170
|
+
}
|
|
171
|
+
async post(body, options) {
|
|
172
|
+
const url = options?.url || this.url;
|
|
173
|
+
const { headers, adapter: adapter2, beforeRequest, afterResponse, timeout, ...rest } = options || {};
|
|
174
|
+
const _headers = { ...this.headers, ...headers };
|
|
175
|
+
const _adapter = adapter2 || this.adapter;
|
|
176
|
+
const _beforeRequest = beforeRequest || this.beforeRequest;
|
|
177
|
+
const _afterResponse = afterResponse || this.afterResponse;
|
|
178
|
+
const _timeout = timeout || this.timeout;
|
|
179
|
+
const req = {
|
|
180
|
+
url,
|
|
181
|
+
headers: _headers,
|
|
182
|
+
body,
|
|
183
|
+
timeout: _timeout,
|
|
184
|
+
...rest
|
|
185
|
+
};
|
|
186
|
+
const isStartsWithHttp = req.url.startsWith("http");
|
|
187
|
+
if (!isStartsWithHttp) {
|
|
188
|
+
if (this.baseURL) {
|
|
189
|
+
const baseURL = new URL(this.baseURL || globalThis?.location?.origin).origin;
|
|
190
|
+
req.url = baseURL + req.url;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
if (_beforeRequest) {
|
|
195
|
+
const res = await _beforeRequest(req);
|
|
196
|
+
if (res === false) {
|
|
197
|
+
return wrapperError({
|
|
198
|
+
code: 500,
|
|
199
|
+
message: "请求取消",
|
|
200
|
+
req
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.error("request beforeFn error", e, req);
|
|
206
|
+
return wrapperError({
|
|
207
|
+
code: 500,
|
|
208
|
+
message: "请求在请求前处理时发生错误",
|
|
209
|
+
req
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
if (this.stop && !options?.noStop) {
|
|
213
|
+
const that = this;
|
|
214
|
+
const res = await new Promise((resolve) => {
|
|
215
|
+
let timer = 0;
|
|
216
|
+
const detect = setInterval(() => {
|
|
217
|
+
if (!that.stop) {
|
|
218
|
+
clearInterval(detect);
|
|
219
|
+
resolve(true);
|
|
220
|
+
}
|
|
221
|
+
timer++;
|
|
222
|
+
if (timer > 5) {
|
|
223
|
+
console.error("等待请求失败:", req.url, timer);
|
|
224
|
+
clearInterval(detect);
|
|
225
|
+
resolve(false);
|
|
226
|
+
}
|
|
227
|
+
}, 1000);
|
|
228
|
+
});
|
|
229
|
+
if (!res) {
|
|
230
|
+
return wrapperError({
|
|
231
|
+
code: 500,
|
|
232
|
+
message: "请求取消,可能是因为用户未登录或者token过期",
|
|
233
|
+
req
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return _adapter(req).then(async (res) => {
|
|
238
|
+
try {
|
|
239
|
+
if (_afterResponse) {
|
|
240
|
+
return await _afterResponse(res, {
|
|
241
|
+
req,
|
|
242
|
+
res,
|
|
243
|
+
fetch: adapter2
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
return res;
|
|
247
|
+
} catch (e) {
|
|
248
|
+
console.error("请求在响应后处理时发生错误", e, req);
|
|
249
|
+
return wrapperError({
|
|
250
|
+
code: 500,
|
|
251
|
+
message: "请求在响应后处理时发生错误",
|
|
252
|
+
req
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
before(fn) {
|
|
258
|
+
this.beforeRequest = fn;
|
|
259
|
+
}
|
|
260
|
+
after(fn) {
|
|
261
|
+
this.afterResponse = fn;
|
|
262
|
+
}
|
|
263
|
+
async fetchText(urlOrOptions, options) {
|
|
264
|
+
let _options = { ...options };
|
|
265
|
+
if (typeof urlOrOptions === "string" && !_options.url) {
|
|
266
|
+
_options.url = urlOrOptions;
|
|
267
|
+
}
|
|
268
|
+
if (typeof urlOrOptions === "object") {
|
|
269
|
+
_options = { ...urlOrOptions, ..._options };
|
|
270
|
+
}
|
|
271
|
+
const res = await adapter({
|
|
272
|
+
method: "GET",
|
|
273
|
+
..._options,
|
|
274
|
+
headers: {
|
|
275
|
+
...this.headers,
|
|
276
|
+
..._options?.headers || {}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
if (res && !res.code) {
|
|
280
|
+
return {
|
|
281
|
+
code: 200,
|
|
282
|
+
data: res
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
return res;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
class BaseQuery {
|
|
290
|
+
query;
|
|
291
|
+
queryDefine;
|
|
292
|
+
constructor(opts) {
|
|
293
|
+
if (opts?.clientQuery) {
|
|
294
|
+
this.query = opts.clientQuery;
|
|
295
|
+
} else {
|
|
296
|
+
this.query = opts?.query;
|
|
297
|
+
}
|
|
298
|
+
if (opts.queryDefine) {
|
|
299
|
+
this.queryDefine = opts.queryDefine;
|
|
300
|
+
this.queryDefine.query = this.query;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
get chain() {
|
|
304
|
+
return this.queryDefine.queryChain;
|
|
305
|
+
}
|
|
306
|
+
post(data, options) {
|
|
307
|
+
return this.query.post(data, options);
|
|
308
|
+
}
|
|
309
|
+
get(data, options) {
|
|
310
|
+
return this.query.get(data, options);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// query/query-login/login-cache.ts
|
|
315
|
+
class LoginCacheStore {
|
|
316
|
+
cache;
|
|
317
|
+
name;
|
|
318
|
+
cacheData;
|
|
319
|
+
constructor(opts) {
|
|
320
|
+
if (!opts.cache) {
|
|
321
|
+
throw new Error("cache is required");
|
|
322
|
+
}
|
|
323
|
+
this.cache = opts.cache;
|
|
324
|
+
this.cacheData = {
|
|
325
|
+
loginUsers: [],
|
|
326
|
+
user: undefined,
|
|
327
|
+
id: undefined,
|
|
328
|
+
accessToken: undefined,
|
|
329
|
+
refreshToken: undefined
|
|
330
|
+
};
|
|
331
|
+
this.name = opts.name;
|
|
332
|
+
}
|
|
333
|
+
async setValue(value) {
|
|
334
|
+
await this.cache.set(this.name, value);
|
|
335
|
+
this.cacheData = value;
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
async delValue() {
|
|
339
|
+
await this.cache.del();
|
|
340
|
+
}
|
|
341
|
+
getValue() {
|
|
342
|
+
return this.cache.get(this.name);
|
|
343
|
+
}
|
|
344
|
+
async init() {
|
|
345
|
+
const defaultData = {
|
|
346
|
+
loginUsers: [],
|
|
347
|
+
user: null,
|
|
348
|
+
id: null,
|
|
349
|
+
accessToken: null,
|
|
350
|
+
refreshToken: null
|
|
351
|
+
};
|
|
352
|
+
if (this.cache.init) {
|
|
353
|
+
try {
|
|
354
|
+
const cacheData = await this.cache.init();
|
|
355
|
+
this.cacheData = cacheData || defaultData;
|
|
356
|
+
} catch (error) {
|
|
357
|
+
console.log("cacheInit error", error);
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
this.cacheData = await this.getValue() || defaultData;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async setLoginUser(user) {
|
|
364
|
+
const has = this.cacheData.loginUsers.find((u) => u.id === user.id);
|
|
365
|
+
if (has) {
|
|
366
|
+
this.cacheData.loginUsers = this.cacheData?.loginUsers?.filter((u) => u?.id && u.id !== user.id);
|
|
367
|
+
}
|
|
368
|
+
this.cacheData.loginUsers.push(user);
|
|
369
|
+
this.cacheData.user = user.user;
|
|
370
|
+
this.cacheData.id = user.id;
|
|
371
|
+
this.cacheData.accessToken = user.accessToken;
|
|
372
|
+
this.cacheData.refreshToken = user.refreshToken;
|
|
373
|
+
this.cacheData.accessTokenExpiresIn = user.accessTokenExpiresIn;
|
|
374
|
+
this.cacheData.createdAt = user.createdAt;
|
|
375
|
+
await this.setValue(this.cacheData);
|
|
376
|
+
}
|
|
377
|
+
getCurrentUser() {
|
|
378
|
+
const cacheData = this.cacheData;
|
|
379
|
+
return Promise.resolve(cacheData.user);
|
|
380
|
+
}
|
|
381
|
+
getCurrentUserList() {
|
|
382
|
+
return Promise.resolve(this.cacheData.loginUsers.filter((u) => u?.id));
|
|
383
|
+
}
|
|
384
|
+
getRefreshToken() {
|
|
385
|
+
const cacheData = this.cacheData;
|
|
386
|
+
return Promise.resolve(cacheData.refreshToken || "");
|
|
387
|
+
}
|
|
388
|
+
getAccessToken() {
|
|
389
|
+
const cacheData = this.cacheData;
|
|
390
|
+
return Promise.resolve(cacheData.accessToken || "");
|
|
391
|
+
}
|
|
392
|
+
async clearCurrentUser() {
|
|
393
|
+
const user = await this.getCurrentUser();
|
|
394
|
+
const has = this.cacheData.loginUsers.find((u) => u.id === user.id);
|
|
395
|
+
if (has) {
|
|
396
|
+
this.cacheData.loginUsers = this.cacheData?.loginUsers?.filter((u) => u?.id && u.id !== user.id);
|
|
397
|
+
}
|
|
398
|
+
this.cacheData.user = undefined;
|
|
399
|
+
this.cacheData.id = undefined;
|
|
400
|
+
this.cacheData.accessToken = undefined;
|
|
401
|
+
this.cacheData.refreshToken = undefined;
|
|
402
|
+
await this.setValue(this.cacheData);
|
|
403
|
+
}
|
|
404
|
+
async clearAll() {
|
|
405
|
+
this.cacheData.loginUsers = [];
|
|
406
|
+
this.cacheData.user = undefined;
|
|
407
|
+
this.cacheData.id = undefined;
|
|
408
|
+
this.cacheData.accessToken = undefined;
|
|
409
|
+
this.cacheData.refreshToken = undefined;
|
|
410
|
+
await this.setValue(this.cacheData);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// node_modules/.pnpm/@kevisual+load@0.0.6/node_modules/@kevisual/load/dist/load.js
|
|
415
|
+
function getDefaultExportFromCjs(x) {
|
|
416
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
417
|
+
}
|
|
418
|
+
var eventemitter3 = { exports: {} };
|
|
419
|
+
var hasRequiredEventemitter3;
|
|
420
|
+
function requireEventemitter3() {
|
|
421
|
+
if (hasRequiredEventemitter3)
|
|
422
|
+
return eventemitter3.exports;
|
|
423
|
+
hasRequiredEventemitter3 = 1;
|
|
424
|
+
(function(module) {
|
|
425
|
+
var has = Object.prototype.hasOwnProperty, prefix = "~";
|
|
426
|
+
function Events() {}
|
|
427
|
+
if (Object.create) {
|
|
428
|
+
Events.prototype = Object.create(null);
|
|
429
|
+
if (!new Events().__proto__)
|
|
430
|
+
prefix = false;
|
|
431
|
+
}
|
|
432
|
+
function EE(fn, context, once) {
|
|
433
|
+
this.fn = fn;
|
|
434
|
+
this.context = context;
|
|
435
|
+
this.once = once || false;
|
|
436
|
+
}
|
|
437
|
+
function addListener(emitter, event, fn, context, once) {
|
|
438
|
+
if (typeof fn !== "function") {
|
|
439
|
+
throw new TypeError("The listener must be a function");
|
|
440
|
+
}
|
|
441
|
+
var listener = new EE(fn, context || emitter, once), evt = prefix ? prefix + event : event;
|
|
442
|
+
if (!emitter._events[evt])
|
|
443
|
+
emitter._events[evt] = listener, emitter._eventsCount++;
|
|
444
|
+
else if (!emitter._events[evt].fn)
|
|
445
|
+
emitter._events[evt].push(listener);
|
|
446
|
+
else
|
|
447
|
+
emitter._events[evt] = [emitter._events[evt], listener];
|
|
448
|
+
return emitter;
|
|
449
|
+
}
|
|
450
|
+
function clearEvent(emitter, evt) {
|
|
451
|
+
if (--emitter._eventsCount === 0)
|
|
452
|
+
emitter._events = new Events;
|
|
453
|
+
else
|
|
454
|
+
delete emitter._events[evt];
|
|
455
|
+
}
|
|
456
|
+
function EventEmitter() {
|
|
457
|
+
this._events = new Events;
|
|
458
|
+
this._eventsCount = 0;
|
|
459
|
+
}
|
|
460
|
+
EventEmitter.prototype.eventNames = function eventNames() {
|
|
461
|
+
var names = [], events, name;
|
|
462
|
+
if (this._eventsCount === 0)
|
|
463
|
+
return names;
|
|
464
|
+
for (name in events = this._events) {
|
|
465
|
+
if (has.call(events, name))
|
|
466
|
+
names.push(prefix ? name.slice(1) : name);
|
|
467
|
+
}
|
|
468
|
+
if (Object.getOwnPropertySymbols) {
|
|
469
|
+
return names.concat(Object.getOwnPropertySymbols(events));
|
|
470
|
+
}
|
|
471
|
+
return names;
|
|
472
|
+
};
|
|
473
|
+
EventEmitter.prototype.listeners = function listeners(event) {
|
|
474
|
+
var evt = prefix ? prefix + event : event, handlers = this._events[evt];
|
|
475
|
+
if (!handlers)
|
|
476
|
+
return [];
|
|
477
|
+
if (handlers.fn)
|
|
478
|
+
return [handlers.fn];
|
|
479
|
+
for (var i = 0, l = handlers.length, ee = new Array(l);i < l; i++) {
|
|
480
|
+
ee[i] = handlers[i].fn;
|
|
481
|
+
}
|
|
482
|
+
return ee;
|
|
483
|
+
};
|
|
484
|
+
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
|
485
|
+
var evt = prefix ? prefix + event : event, listeners = this._events[evt];
|
|
486
|
+
if (!listeners)
|
|
487
|
+
return 0;
|
|
488
|
+
if (listeners.fn)
|
|
489
|
+
return 1;
|
|
490
|
+
return listeners.length;
|
|
491
|
+
};
|
|
492
|
+
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
|
493
|
+
var evt = prefix ? prefix + event : event;
|
|
494
|
+
if (!this._events[evt])
|
|
495
|
+
return false;
|
|
496
|
+
var listeners = this._events[evt], len = arguments.length, args, i;
|
|
497
|
+
if (listeners.fn) {
|
|
498
|
+
if (listeners.once)
|
|
499
|
+
this.removeListener(event, listeners.fn, undefined, true);
|
|
500
|
+
switch (len) {
|
|
501
|
+
case 1:
|
|
502
|
+
return listeners.fn.call(listeners.context), true;
|
|
503
|
+
case 2:
|
|
504
|
+
return listeners.fn.call(listeners.context, a1), true;
|
|
505
|
+
case 3:
|
|
506
|
+
return listeners.fn.call(listeners.context, a1, a2), true;
|
|
507
|
+
case 4:
|
|
508
|
+
return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
|
509
|
+
case 5:
|
|
510
|
+
return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
|
511
|
+
case 6:
|
|
512
|
+
return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
|
513
|
+
}
|
|
514
|
+
for (i = 1, args = new Array(len - 1);i < len; i++) {
|
|
515
|
+
args[i - 1] = arguments[i];
|
|
516
|
+
}
|
|
517
|
+
listeners.fn.apply(listeners.context, args);
|
|
518
|
+
} else {
|
|
519
|
+
var length = listeners.length, j;
|
|
520
|
+
for (i = 0;i < length; i++) {
|
|
521
|
+
if (listeners[i].once)
|
|
522
|
+
this.removeListener(event, listeners[i].fn, undefined, true);
|
|
523
|
+
switch (len) {
|
|
524
|
+
case 1:
|
|
525
|
+
listeners[i].fn.call(listeners[i].context);
|
|
526
|
+
break;
|
|
527
|
+
case 2:
|
|
528
|
+
listeners[i].fn.call(listeners[i].context, a1);
|
|
529
|
+
break;
|
|
530
|
+
case 3:
|
|
531
|
+
listeners[i].fn.call(listeners[i].context, a1, a2);
|
|
532
|
+
break;
|
|
533
|
+
case 4:
|
|
534
|
+
listeners[i].fn.call(listeners[i].context, a1, a2, a3);
|
|
535
|
+
break;
|
|
536
|
+
default:
|
|
537
|
+
if (!args)
|
|
538
|
+
for (j = 1, args = new Array(len - 1);j < len; j++) {
|
|
539
|
+
args[j - 1] = arguments[j];
|
|
540
|
+
}
|
|
541
|
+
listeners[i].fn.apply(listeners[i].context, args);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return true;
|
|
546
|
+
};
|
|
547
|
+
EventEmitter.prototype.on = function on(event, fn, context) {
|
|
548
|
+
return addListener(this, event, fn, context, false);
|
|
549
|
+
};
|
|
550
|
+
EventEmitter.prototype.once = function once(event, fn, context) {
|
|
551
|
+
return addListener(this, event, fn, context, true);
|
|
552
|
+
};
|
|
553
|
+
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
|
554
|
+
var evt = prefix ? prefix + event : event;
|
|
555
|
+
if (!this._events[evt])
|
|
556
|
+
return this;
|
|
557
|
+
if (!fn) {
|
|
558
|
+
clearEvent(this, evt);
|
|
559
|
+
return this;
|
|
560
|
+
}
|
|
561
|
+
var listeners = this._events[evt];
|
|
562
|
+
if (listeners.fn) {
|
|
563
|
+
if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) {
|
|
564
|
+
clearEvent(this, evt);
|
|
565
|
+
}
|
|
566
|
+
} else {
|
|
567
|
+
for (var i = 0, events = [], length = listeners.length;i < length; i++) {
|
|
568
|
+
if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) {
|
|
569
|
+
events.push(listeners[i]);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (events.length)
|
|
573
|
+
this._events[evt] = events.length === 1 ? events[0] : events;
|
|
574
|
+
else
|
|
575
|
+
clearEvent(this, evt);
|
|
576
|
+
}
|
|
577
|
+
return this;
|
|
578
|
+
};
|
|
579
|
+
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
|
580
|
+
var evt;
|
|
581
|
+
if (event) {
|
|
582
|
+
evt = prefix ? prefix + event : event;
|
|
583
|
+
if (this._events[evt])
|
|
584
|
+
clearEvent(this, evt);
|
|
585
|
+
} else {
|
|
586
|
+
this._events = new Events;
|
|
587
|
+
this._eventsCount = 0;
|
|
588
|
+
}
|
|
589
|
+
return this;
|
|
590
|
+
};
|
|
591
|
+
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
592
|
+
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
|
|
593
|
+
EventEmitter.prefixed = prefix;
|
|
594
|
+
EventEmitter.EventEmitter = EventEmitter;
|
|
595
|
+
{
|
|
596
|
+
module.exports = EventEmitter;
|
|
597
|
+
}
|
|
598
|
+
})(eventemitter3);
|
|
599
|
+
return eventemitter3.exports;
|
|
600
|
+
}
|
|
601
|
+
var eventemitter3Exports = requireEventemitter3();
|
|
602
|
+
var EventEmitter = /* @__PURE__ */ getDefaultExportFromCjs(eventemitter3Exports);
|
|
603
|
+
var reRunFn = (promiseOpts) => {
|
|
604
|
+
const timeout = promiseOpts.timeout || 5 * 60 * 1000;
|
|
605
|
+
const interval = promiseOpts.interval || 1000;
|
|
606
|
+
const checkSuccess = promiseOpts?.checkSuccess || (() => true);
|
|
607
|
+
const signal = promiseOpts.signal;
|
|
608
|
+
return new Promise(async (resolve, reject) => {
|
|
609
|
+
let intervalId;
|
|
610
|
+
let timeoutId = setTimeout(() => {
|
|
611
|
+
clearTimeout(intervalId);
|
|
612
|
+
resolve({
|
|
613
|
+
code: 500,
|
|
614
|
+
message: "timeout"
|
|
615
|
+
});
|
|
616
|
+
}, timeout);
|
|
617
|
+
const fn = promiseOpts.fn || (() => true);
|
|
618
|
+
const runFn = async () => {
|
|
619
|
+
if (signal?.aborted) {
|
|
620
|
+
clearInterval(intervalId);
|
|
621
|
+
clearTimeout(timeoutId);
|
|
622
|
+
return resolve({
|
|
623
|
+
code: 499,
|
|
624
|
+
message: "operation cancelled"
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
const res = await fn();
|
|
628
|
+
if (!!checkSuccess(res)) {
|
|
629
|
+
clearInterval(intervalId);
|
|
630
|
+
clearTimeout(timeoutId);
|
|
631
|
+
resolve({
|
|
632
|
+
code: 200,
|
|
633
|
+
data: res
|
|
634
|
+
});
|
|
635
|
+
} else {
|
|
636
|
+
setTimeout(() => {
|
|
637
|
+
runFn();
|
|
638
|
+
}, interval);
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
if (signal) {
|
|
642
|
+
signal.addEventListener("abort", () => {
|
|
643
|
+
clearInterval(intervalId);
|
|
644
|
+
clearTimeout(timeoutId);
|
|
645
|
+
resolve({
|
|
646
|
+
code: 499,
|
|
647
|
+
message: "operation cancelled"
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
runFn();
|
|
652
|
+
});
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
class BaseLoad {
|
|
656
|
+
modules = new Map;
|
|
657
|
+
event;
|
|
658
|
+
loading;
|
|
659
|
+
static reRunFn = reRunFn;
|
|
660
|
+
timeout = 5 * 60 * 1000;
|
|
661
|
+
constructor() {
|
|
662
|
+
this.event = new EventEmitter;
|
|
663
|
+
this.loading = false;
|
|
664
|
+
}
|
|
665
|
+
listenKey(key, listenOpts) {
|
|
666
|
+
const timeout = listenOpts?.timeout ?? this.timeout;
|
|
667
|
+
return new Promise((resolve) => {
|
|
668
|
+
const timeoutId = setTimeout(() => {
|
|
669
|
+
this.event.removeListener(key, onEvent);
|
|
670
|
+
resolve({
|
|
671
|
+
code: 500,
|
|
672
|
+
message: "timeout"
|
|
673
|
+
});
|
|
674
|
+
}, timeout);
|
|
675
|
+
const onEvent = (error) => {
|
|
676
|
+
clearTimeout(timeoutId);
|
|
677
|
+
if (error) {
|
|
678
|
+
return resolve({
|
|
679
|
+
code: 500,
|
|
680
|
+
message: error
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
const data = this.modules.get(key);
|
|
684
|
+
if (data?.loadSuccessClear) {
|
|
685
|
+
this.remove(key);
|
|
686
|
+
}
|
|
687
|
+
resolve({
|
|
688
|
+
code: 200,
|
|
689
|
+
data: data?.modules
|
|
690
|
+
});
|
|
691
|
+
};
|
|
692
|
+
this.event.once(key, onEvent);
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
async hasLoaded(key, hasLoadOpts) {
|
|
696
|
+
if (!key) {
|
|
697
|
+
return {
|
|
698
|
+
code: 404,
|
|
699
|
+
message: "key is required"
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
const has = this.modules.has(key);
|
|
703
|
+
if (!has) {
|
|
704
|
+
const isExist = hasLoadOpts?.isExist ?? true;
|
|
705
|
+
const timeout = hasLoadOpts?.timeout ?? this.timeout;
|
|
706
|
+
if (isExist) {
|
|
707
|
+
return await this.listenKey(key, { timeout });
|
|
708
|
+
}
|
|
709
|
+
return {
|
|
710
|
+
code: 404
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
const data = this.modules.get(key);
|
|
714
|
+
if (data?.status === "loaded") {
|
|
715
|
+
return {
|
|
716
|
+
code: 200,
|
|
717
|
+
data: data.modules
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
if (data?.status === "loading") {
|
|
721
|
+
return await this.listenKey(key, { timeout: hasLoadOpts?.timeout ?? this.timeout });
|
|
722
|
+
}
|
|
723
|
+
if (data?.status === "error") {
|
|
724
|
+
return {
|
|
725
|
+
code: 500,
|
|
726
|
+
message: "load error"
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
if (data?.status === "cancel") {
|
|
730
|
+
return {
|
|
731
|
+
code: 499,
|
|
732
|
+
message: "operation cancelled"
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
code: 404
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
async loadFn(loadContent, opts) {
|
|
740
|
+
const key = opts.key;
|
|
741
|
+
if (!key) {
|
|
742
|
+
return {
|
|
743
|
+
code: 404,
|
|
744
|
+
message: "key is required"
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
const newModule = {
|
|
748
|
+
key: opts.key,
|
|
749
|
+
status: "loading",
|
|
750
|
+
loading: true,
|
|
751
|
+
loadSuccessClear: opts.loadSuccessClear ?? true
|
|
752
|
+
};
|
|
753
|
+
let errorMessage = "";
|
|
754
|
+
try {
|
|
755
|
+
const isReRun = opts.isReRun ?? false;
|
|
756
|
+
let res;
|
|
757
|
+
if (!isReRun) {
|
|
758
|
+
this.modules.set(key, newModule);
|
|
759
|
+
res = await loadContent();
|
|
760
|
+
} else {
|
|
761
|
+
newModule.controller = new AbortController;
|
|
762
|
+
const signal = newModule.controller.signal;
|
|
763
|
+
this.modules.set(key, newModule);
|
|
764
|
+
const data = await reRunFn({
|
|
765
|
+
timeout: opts.timeout,
|
|
766
|
+
interval: opts.interval,
|
|
767
|
+
checkSuccess: opts.checkSuccess,
|
|
768
|
+
fn: loadContent,
|
|
769
|
+
signal
|
|
770
|
+
});
|
|
771
|
+
newModule.controller = null;
|
|
772
|
+
if (data.code === 499) {
|
|
773
|
+
newModule.status = "cancel";
|
|
774
|
+
return {
|
|
775
|
+
code: 499,
|
|
776
|
+
message: "operation cancelled"
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
if (data.code !== 200) {
|
|
780
|
+
throw new Error(data.message);
|
|
781
|
+
}
|
|
782
|
+
res = data.data;
|
|
783
|
+
}
|
|
784
|
+
newModule.modules = res;
|
|
785
|
+
newModule.status = "loaded";
|
|
786
|
+
return {
|
|
787
|
+
code: 200,
|
|
788
|
+
data: res
|
|
789
|
+
};
|
|
790
|
+
} catch (error) {
|
|
791
|
+
errorMessage = error.message;
|
|
792
|
+
newModule.status = "error";
|
|
793
|
+
return {
|
|
794
|
+
code: 500,
|
|
795
|
+
message: error
|
|
796
|
+
};
|
|
797
|
+
} finally {
|
|
798
|
+
newModule.loading = false;
|
|
799
|
+
this.modules.set(opts.key, newModule);
|
|
800
|
+
if (!errorMessage) {
|
|
801
|
+
this.event.emit(opts.key);
|
|
802
|
+
} else {
|
|
803
|
+
this.event.emit(opts.key, errorMessage);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
async load(loadContent, opts) {
|
|
808
|
+
this.loading = true;
|
|
809
|
+
const key = opts.key;
|
|
810
|
+
if (!key) {
|
|
811
|
+
return {
|
|
812
|
+
code: 404,
|
|
813
|
+
message: "key is required"
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
if (opts?.force) {
|
|
817
|
+
this.remove(key);
|
|
818
|
+
}
|
|
819
|
+
const has = this.modules.has(key);
|
|
820
|
+
if (has) {
|
|
821
|
+
return await this.hasLoaded(key);
|
|
822
|
+
}
|
|
823
|
+
if (typeof loadContent === "function") {
|
|
824
|
+
return this.loadFn(loadContent, opts);
|
|
825
|
+
}
|
|
826
|
+
console.error("loadContent is not a function and not has loaded");
|
|
827
|
+
}
|
|
828
|
+
remove(key) {
|
|
829
|
+
const has = this.modules.has(key);
|
|
830
|
+
if (has) {
|
|
831
|
+
this.checkRemoveController(key);
|
|
832
|
+
this.modules.delete(key);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
emitLoaded(key) {
|
|
836
|
+
this.checkRemoveController(key);
|
|
837
|
+
this.event.emit(key);
|
|
838
|
+
}
|
|
839
|
+
setModule(key, data, loadData) {
|
|
840
|
+
const newModule = {
|
|
841
|
+
key,
|
|
842
|
+
status: "loaded",
|
|
843
|
+
loading: false,
|
|
844
|
+
modules: data || {},
|
|
845
|
+
...loadData
|
|
846
|
+
};
|
|
847
|
+
this.modules.set(key, newModule);
|
|
848
|
+
this.emitLoaded(key);
|
|
849
|
+
return newModule;
|
|
850
|
+
}
|
|
851
|
+
cancel(key) {
|
|
852
|
+
this.checkRemoveController(key);
|
|
853
|
+
}
|
|
854
|
+
checkRemoveController(key) {
|
|
855
|
+
const data = this.modules.get(key);
|
|
856
|
+
if (data?.controller) {
|
|
857
|
+
data.controller?.abort?.();
|
|
858
|
+
delete data.controller;
|
|
859
|
+
this.modules.set(key, data);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// query/query-login/query-login.ts
|
|
865
|
+
class QueryLogin extends BaseQuery {
|
|
866
|
+
cacheStore;
|
|
867
|
+
isBrowser;
|
|
868
|
+
load;
|
|
869
|
+
storage;
|
|
870
|
+
onLoad;
|
|
871
|
+
constructor(opts) {
|
|
872
|
+
super({
|
|
873
|
+
query: opts?.query || new Query
|
|
874
|
+
});
|
|
875
|
+
this.cacheStore = new LoginCacheStore({ name: "login", cache: opts?.cache });
|
|
876
|
+
this.isBrowser = opts?.isBrowser ?? true;
|
|
877
|
+
this.init();
|
|
878
|
+
this.onLoad = opts?.onLoad;
|
|
879
|
+
this.storage = opts?.storage || globalThis?.localStorage;
|
|
880
|
+
if (!this.storage) {
|
|
881
|
+
throw new Error("storage is required");
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
setQuery(query) {
|
|
885
|
+
this.query = query;
|
|
886
|
+
}
|
|
887
|
+
async init() {
|
|
888
|
+
await this.cacheStore.init();
|
|
889
|
+
this.load = true;
|
|
890
|
+
this.onLoad?.();
|
|
891
|
+
}
|
|
892
|
+
async post(data, opts) {
|
|
893
|
+
try {
|
|
894
|
+
return this.query.post({ path: "user", ...data }, opts);
|
|
895
|
+
} catch (error) {
|
|
896
|
+
console.log("error", error);
|
|
897
|
+
return {
|
|
898
|
+
code: 400
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
async login(data) {
|
|
903
|
+
const res = await this.post({ key: "login", ...data });
|
|
904
|
+
if (res.code === 200) {
|
|
905
|
+
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
|
906
|
+
this.storage.setItem("token", accessToken || "");
|
|
907
|
+
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
|
908
|
+
}
|
|
909
|
+
return res;
|
|
910
|
+
}
|
|
911
|
+
async loginByCode(data) {
|
|
912
|
+
const res = await this.post({ path: "sms", key: "login", data });
|
|
913
|
+
if (res.code === 200) {
|
|
914
|
+
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
|
915
|
+
this.storage.setItem("token", accessToken || "");
|
|
916
|
+
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
|
917
|
+
}
|
|
918
|
+
return res;
|
|
919
|
+
}
|
|
920
|
+
async setLoginToken(token) {
|
|
921
|
+
const { accessToken, refreshToken, accessTokenExpiresIn } = token;
|
|
922
|
+
this.storage.setItem("token", accessToken || "");
|
|
923
|
+
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
|
924
|
+
}
|
|
925
|
+
async loginByWechat(data) {
|
|
926
|
+
const res = await this.post({ path: "wx", key: "open-login", code: data.code });
|
|
927
|
+
if (res.code === 200) {
|
|
928
|
+
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
|
929
|
+
this.storage.setItem("token", accessToken || "");
|
|
930
|
+
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
|
931
|
+
}
|
|
932
|
+
return res;
|
|
933
|
+
}
|
|
934
|
+
async checkWechat({ onSuccess, onError }) {
|
|
935
|
+
const url = new URL(window.location.href);
|
|
936
|
+
const code = url.searchParams.get("code");
|
|
937
|
+
const state = url.searchParams.get("state");
|
|
938
|
+
if (code && state) {
|
|
939
|
+
const res = await this.loginByWechat({ code });
|
|
940
|
+
if (res.code === 200) {
|
|
941
|
+
onSuccess?.(res.data);
|
|
942
|
+
} else {
|
|
943
|
+
onError?.(res);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
async beforeSetLoginUser({ accessToken, refreshToken, check401, accessTokenExpiresIn }) {
|
|
948
|
+
if (accessToken && refreshToken) {
|
|
949
|
+
const resUser = await this.getMe(accessToken, check401);
|
|
950
|
+
if (resUser.code === 200) {
|
|
951
|
+
const user = resUser.data;
|
|
952
|
+
if (user) {
|
|
953
|
+
this.cacheStore.setLoginUser({
|
|
954
|
+
user,
|
|
955
|
+
id: user.id,
|
|
956
|
+
accessToken,
|
|
957
|
+
refreshToken,
|
|
958
|
+
accessTokenExpiresIn,
|
|
959
|
+
createdAt: Date.now()
|
|
960
|
+
});
|
|
961
|
+
} else {
|
|
962
|
+
console.error("登录失败");
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
async queryRefreshToken(refreshToken) {
|
|
968
|
+
const _refreshToken = refreshToken || this.cacheStore.getRefreshToken();
|
|
969
|
+
let data = { refreshToken: _refreshToken };
|
|
970
|
+
if (!_refreshToken) {
|
|
971
|
+
await this.cacheStore.clearCurrentUser();
|
|
972
|
+
return {
|
|
973
|
+
code: 401,
|
|
974
|
+
message: "请先登录",
|
|
975
|
+
data: {}
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
return this.post({ key: "refreshToken", data }, {
|
|
979
|
+
afterResponse: async (response, ctx) => {
|
|
980
|
+
return response;
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
async afterCheck401ToRefreshToken(response, ctx, refetch) {
|
|
985
|
+
const that = this;
|
|
986
|
+
if (response?.code === 401) {
|
|
987
|
+
const hasRefreshToken = await that.cacheStore.getRefreshToken();
|
|
988
|
+
if (hasRefreshToken) {
|
|
989
|
+
const res = await that.queryRefreshToken(hasRefreshToken);
|
|
990
|
+
if (res.code === 200) {
|
|
991
|
+
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
|
992
|
+
that.storage.setItem("token", accessToken || "");
|
|
993
|
+
await that.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn, check401: false });
|
|
994
|
+
if (refetch && ctx && ctx.req && ctx.req.url && ctx.fetch) {
|
|
995
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
996
|
+
const url = ctx.req?.url;
|
|
997
|
+
const body = ctx.req?.body;
|
|
998
|
+
const headers = ctx.req?.headers;
|
|
999
|
+
const res2 = await ctx.fetch(url, {
|
|
1000
|
+
method: "POST",
|
|
1001
|
+
body,
|
|
1002
|
+
headers: { ...headers, Authorization: `Bearer ${accessToken}` }
|
|
1003
|
+
});
|
|
1004
|
+
return res2;
|
|
1005
|
+
}
|
|
1006
|
+
} else {
|
|
1007
|
+
that.storage.removeItem("token");
|
|
1008
|
+
await that.cacheStore.clearCurrentUser();
|
|
1009
|
+
}
|
|
1010
|
+
return res;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
return response;
|
|
1014
|
+
}
|
|
1015
|
+
async run401Action(response, ctx, opts) {
|
|
1016
|
+
const that = this;
|
|
1017
|
+
const refetch = opts?.refetch ?? false;
|
|
1018
|
+
if (response?.code === 401) {
|
|
1019
|
+
if (that.query.stop === true) {
|
|
1020
|
+
return { code: 500, success: false, message: "refresh token loading..." };
|
|
1021
|
+
}
|
|
1022
|
+
that.query.stop = true;
|
|
1023
|
+
const res = await that.afterCheck401ToRefreshToken(response, ctx, refetch);
|
|
1024
|
+
that.query.stop = false;
|
|
1025
|
+
opts?.afterCheck?.(res);
|
|
1026
|
+
if (res.code === 401) {
|
|
1027
|
+
opts?.afterAlso401?.(res);
|
|
1028
|
+
}
|
|
1029
|
+
return res;
|
|
1030
|
+
} else {
|
|
1031
|
+
return response;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
async getMe(token, check401 = true) {
|
|
1035
|
+
const _token = token || this.storage.getItem("token");
|
|
1036
|
+
const that = this;
|
|
1037
|
+
return that.post({ key: "me" }, {
|
|
1038
|
+
beforeRequest: async (config) => {
|
|
1039
|
+
if (config.headers) {
|
|
1040
|
+
config.headers["Authorization"] = `Bearer ${_token}`;
|
|
1041
|
+
}
|
|
1042
|
+
if (!_token) {
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
return config;
|
|
1046
|
+
},
|
|
1047
|
+
afterResponse: async (response, ctx) => {
|
|
1048
|
+
if (response?.code === 401 && check401 && !token) {
|
|
1049
|
+
return await that.afterCheck401ToRefreshToken(response, ctx);
|
|
1050
|
+
}
|
|
1051
|
+
return response;
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
async checkLocalUser() {
|
|
1056
|
+
const user = await this.cacheStore.getCurrentUser();
|
|
1057
|
+
if (user) {
|
|
1058
|
+
return user;
|
|
1059
|
+
}
|
|
1060
|
+
return null;
|
|
1061
|
+
}
|
|
1062
|
+
async checkLocalToken() {
|
|
1063
|
+
const token = this.storage.getItem("token");
|
|
1064
|
+
return !!token;
|
|
1065
|
+
}
|
|
1066
|
+
async getToken() {
|
|
1067
|
+
const token = this.storage.getItem("token");
|
|
1068
|
+
return token || "";
|
|
1069
|
+
}
|
|
1070
|
+
async beforeRequest(opts = {}) {
|
|
1071
|
+
const token = this.storage.getItem("token");
|
|
1072
|
+
if (token) {
|
|
1073
|
+
opts.headers = { ...opts.headers, Authorization: `Bearer ${token}` };
|
|
1074
|
+
}
|
|
1075
|
+
return opts;
|
|
1076
|
+
}
|
|
1077
|
+
async postSwitchUser(username) {
|
|
1078
|
+
return this.post({ key: "switchCheck", data: { username } });
|
|
1079
|
+
}
|
|
1080
|
+
async switchUser(username) {
|
|
1081
|
+
const localUserList = await this.cacheStore.getCurrentUserList();
|
|
1082
|
+
const user = localUserList.find((userItem) => userItem.user.username === username);
|
|
1083
|
+
if (user) {
|
|
1084
|
+
this.storage.setItem("token", user.accessToken || "");
|
|
1085
|
+
await this.beforeSetLoginUser({
|
|
1086
|
+
accessToken: user.accessToken,
|
|
1087
|
+
refreshToken: user.refreshToken,
|
|
1088
|
+
accessTokenExpiresIn: user.accessTokenExpiresIn
|
|
1089
|
+
});
|
|
1090
|
+
return {
|
|
1091
|
+
code: 200,
|
|
1092
|
+
data: {
|
|
1093
|
+
accessToken: user.accessToken,
|
|
1094
|
+
refreshToken: user.refreshToken,
|
|
1095
|
+
accessTokenExpiresIn: user.accessTokenExpiresIn
|
|
1096
|
+
},
|
|
1097
|
+
success: true,
|
|
1098
|
+
message: "切换用户成功"
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
const res = await this.postSwitchUser(username);
|
|
1102
|
+
if (res.code === 200) {
|
|
1103
|
+
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
|
1104
|
+
this.storage.setItem("token", accessToken || "");
|
|
1105
|
+
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
|
1106
|
+
}
|
|
1107
|
+
return res;
|
|
1108
|
+
}
|
|
1109
|
+
async logout() {
|
|
1110
|
+
this.storage.removeItem("token");
|
|
1111
|
+
const users = await this.cacheStore.getCurrentUserList();
|
|
1112
|
+
const tokens = users.map((user) => {
|
|
1113
|
+
return user?.accessToken;
|
|
1114
|
+
}).filter(Boolean);
|
|
1115
|
+
this.cacheStore.delValue();
|
|
1116
|
+
return this.post({ key: "logout", data: { tokens } });
|
|
1117
|
+
}
|
|
1118
|
+
async hasUser(username) {
|
|
1119
|
+
const that = this;
|
|
1120
|
+
return this.post({
|
|
1121
|
+
path: "org",
|
|
1122
|
+
key: "hasUser",
|
|
1123
|
+
data: {
|
|
1124
|
+
username
|
|
1125
|
+
}
|
|
1126
|
+
}, {
|
|
1127
|
+
afterResponse: async (response, ctx) => {
|
|
1128
|
+
if (response?.code === 401) {
|
|
1129
|
+
const res = await that.afterCheck401ToRefreshToken(response, ctx, true);
|
|
1130
|
+
return res;
|
|
1131
|
+
}
|
|
1132
|
+
return response;
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
async checkLoginStatus(token) {
|
|
1137
|
+
const res = await this.post({
|
|
1138
|
+
path: "user",
|
|
1139
|
+
key: "checkLoginStatus",
|
|
1140
|
+
loginToken: token
|
|
1141
|
+
});
|
|
1142
|
+
if (res.code === 200) {
|
|
1143
|
+
const { accessTokenExpiresIn, accessToken, refreshToken } = res.data;
|
|
1144
|
+
this.storage.setItem("token", accessToken || "");
|
|
1145
|
+
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
|
1146
|
+
return res;
|
|
1147
|
+
}
|
|
1148
|
+
return false;
|
|
1149
|
+
}
|
|
1150
|
+
loginWithWeb(baseURL, { MD5, jsonwebtoken }) {
|
|
1151
|
+
const randomId = Math.random().toString(36).substring(2, 15);
|
|
1152
|
+
const timestamp = Date.now();
|
|
1153
|
+
const tokenSecret = "xiao" + randomId;
|
|
1154
|
+
let sign = "";
|
|
1155
|
+
if (MD5) {
|
|
1156
|
+
sign = MD5(`${tokenSecret}${timestamp}`).toString();
|
|
1157
|
+
}
|
|
1158
|
+
let token = "";
|
|
1159
|
+
if (jsonwebtoken) {
|
|
1160
|
+
token = jsonwebtoken.sign({ randomId, timestamp, sign }, tokenSecret, {
|
|
1161
|
+
expiresIn: 60 * 10
|
|
1162
|
+
});
|
|
1163
|
+
} else {
|
|
1164
|
+
token = tokenSecret;
|
|
1165
|
+
}
|
|
1166
|
+
const url = `${baseURL}/api/router?path=user&key=webLogin&p&loginToken=${token}&sign=${sign}&randomId=${randomId}`;
|
|
1167
|
+
return { url, token, tokenSecret };
|
|
1168
|
+
}
|
|
1169
|
+
async pollLoginStatus(data) {
|
|
1170
|
+
const token = data.token;
|
|
1171
|
+
const load = new BaseLoad;
|
|
1172
|
+
load.load(async () => {
|
|
1173
|
+
const res2 = await this.checkLoginStatus(token);
|
|
1174
|
+
if (res2.code === 500) {
|
|
1175
|
+
load.cancel("check-login-status");
|
|
1176
|
+
}
|
|
1177
|
+
return res2;
|
|
1178
|
+
}, {
|
|
1179
|
+
key: "check-login-status",
|
|
1180
|
+
isReRun: true,
|
|
1181
|
+
checkSuccess: (data2) => {
|
|
1182
|
+
return data2?.code === 200;
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
const res = await load.hasLoaded("check-login-status", {
|
|
1186
|
+
timeout: 60 * 3 * 1000
|
|
1187
|
+
});
|
|
1188
|
+
if (res.code === 200 && res.data?.code === 200) {
|
|
1189
|
+
try {
|
|
1190
|
+
console.log("网页登录成功");
|
|
1191
|
+
return true;
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
console.log("登录失败", error);
|
|
1194
|
+
return false;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
console.log("登录失败", res);
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// query/query-login/login-node-cache.ts
|
|
1203
|
+
import { homedir } from "node:os";
|
|
1204
|
+
import { join, dirname } from "node:path";
|
|
1205
|
+
import fs from "node:fs";
|
|
1206
|
+
import { readFileSync, writeFileSync, accessSync, unlinkSync, mkdirSync } from "node:fs";
|
|
1207
|
+
var fileExists = (filePath, { createIfNotExists = true, isFile = true, isDir = false } = {}) => {
|
|
1208
|
+
try {
|
|
1209
|
+
accessSync(filePath, fs.constants.F_OK);
|
|
1210
|
+
return true;
|
|
1211
|
+
} catch (error) {
|
|
1212
|
+
if (createIfNotExists && isDir) {
|
|
1213
|
+
mkdirSync(filePath, { recursive: true });
|
|
1214
|
+
return true;
|
|
1215
|
+
} else if (createIfNotExists && isFile) {
|
|
1216
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
1217
|
+
return false;
|
|
1218
|
+
}
|
|
1219
|
+
return false;
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
var readConfigFile = (filePath) => {
|
|
1223
|
+
try {
|
|
1224
|
+
const data = readFileSync(filePath, "utf-8");
|
|
1225
|
+
const jsonData = JSON.parse(data);
|
|
1226
|
+
return jsonData;
|
|
1227
|
+
} catch (error) {
|
|
1228
|
+
return {};
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
var writeConfigFile = (filePath, data) => {
|
|
1232
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
1233
|
+
};
|
|
1234
|
+
var getHostName = (baseURL) => {
|
|
1235
|
+
const configDir = join(homedir(), ".config", "envision");
|
|
1236
|
+
const configFile = join(configDir, "config.json");
|
|
1237
|
+
const config = readConfigFile(configFile);
|
|
1238
|
+
const _baseURL = baseURL || config.baseURL || "https://kevisual.cn";
|
|
1239
|
+
const hostname = new URL(_baseURL).hostname;
|
|
1240
|
+
return hostname;
|
|
1241
|
+
};
|
|
1242
|
+
|
|
1243
|
+
class StorageNode {
|
|
1244
|
+
cacheData;
|
|
1245
|
+
filePath = "";
|
|
1246
|
+
hostname = "";
|
|
1247
|
+
isLoaded = false;
|
|
1248
|
+
constructor(opts) {
|
|
1249
|
+
this.cacheData = {};
|
|
1250
|
+
const hostname = getHostName(opts?.baseURL);
|
|
1251
|
+
this.setHostName(hostname, { load: opts?.load });
|
|
1252
|
+
}
|
|
1253
|
+
setHostName(hostname, opts) {
|
|
1254
|
+
const load = opts?.load ?? false;
|
|
1255
|
+
if (hostname.startsWith("http")) {
|
|
1256
|
+
hostname = new URL(hostname).hostname;
|
|
1257
|
+
}
|
|
1258
|
+
const configDir = join(homedir(), ".config", "envision");
|
|
1259
|
+
this.filePath = join(configDir, "config", `${hostname}-storage.json`);
|
|
1260
|
+
this.hostname = hostname;
|
|
1261
|
+
fileExists(this.filePath, { isFile: true });
|
|
1262
|
+
if (load) {
|
|
1263
|
+
this.loadCache();
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
loadCache(force) {
|
|
1267
|
+
if (this.isLoaded && !force)
|
|
1268
|
+
return;
|
|
1269
|
+
const filePath = this.filePath;
|
|
1270
|
+
try {
|
|
1271
|
+
const data = readConfigFile(filePath);
|
|
1272
|
+
this.cacheData = data;
|
|
1273
|
+
this.isLoaded = true;
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
this.cacheData = {};
|
|
1276
|
+
writeFileSync(filePath, JSON.stringify(this.cacheData, null, 2));
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
get length() {
|
|
1280
|
+
return Object.keys(this.cacheData).length;
|
|
1281
|
+
}
|
|
1282
|
+
getItem(key) {
|
|
1283
|
+
return this.cacheData[key];
|
|
1284
|
+
}
|
|
1285
|
+
setItem(key, value) {
|
|
1286
|
+
this.cacheData[key] = value;
|
|
1287
|
+
writeFileSync(this.filePath, JSON.stringify(this.cacheData, null, 2));
|
|
1288
|
+
}
|
|
1289
|
+
removeItem(key) {
|
|
1290
|
+
delete this.cacheData[key];
|
|
1291
|
+
writeFileSync(this.filePath, JSON.stringify(this.cacheData, null, 2));
|
|
1292
|
+
}
|
|
1293
|
+
clear() {
|
|
1294
|
+
this.cacheData = {};
|
|
1295
|
+
writeFileSync(this.filePath, JSON.stringify(this.cacheData, null, 2));
|
|
1296
|
+
}
|
|
1297
|
+
key(index) {
|
|
1298
|
+
return Object.keys(this.cacheData)[index];
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
class LoginNodeCache {
|
|
1303
|
+
filepath;
|
|
1304
|
+
isLoaded = false;
|
|
1305
|
+
constructor(opts) {
|
|
1306
|
+
this.filepath = join(homedir(), ".config", "envision", "config", `${getHostName(opts?.baseURL)}-login.json`);
|
|
1307
|
+
fileExists(this.filepath, { isFile: true });
|
|
1308
|
+
if (opts?.load) {
|
|
1309
|
+
this.loadCache(this.filepath);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
async get(_key) {
|
|
1313
|
+
try {
|
|
1314
|
+
const filePath = this.filepath;
|
|
1315
|
+
const data = readConfigFile(filePath);
|
|
1316
|
+
return data;
|
|
1317
|
+
} catch (error) {
|
|
1318
|
+
console.log("get error", error);
|
|
1319
|
+
return {};
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
async set(_key, value) {
|
|
1323
|
+
try {
|
|
1324
|
+
const data = readConfigFile(this.filepath);
|
|
1325
|
+
const newData = { ...data, ...value };
|
|
1326
|
+
writeConfigFile(this.filepath, newData);
|
|
1327
|
+
} catch (error) {
|
|
1328
|
+
console.log("set error", error);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
async del() {
|
|
1332
|
+
unlinkSync(this.filepath);
|
|
1333
|
+
}
|
|
1334
|
+
loadCache(filePath, force) {
|
|
1335
|
+
if (this.isLoaded && !force)
|
|
1336
|
+
return;
|
|
1337
|
+
try {
|
|
1338
|
+
const data = readFileSync(filePath, "utf-8");
|
|
1339
|
+
const jsonData = JSON.parse(data);
|
|
1340
|
+
this.isLoaded = true;
|
|
1341
|
+
return jsonData;
|
|
1342
|
+
} catch (error) {
|
|
1343
|
+
console.log("create new cache file:", filePath);
|
|
1344
|
+
const defaultData = { loginUsers: [] };
|
|
1345
|
+
writeConfigFile(filePath, defaultData);
|
|
1346
|
+
return defaultData;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
init() {
|
|
1350
|
+
return this.loadCache(this.filepath);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// query/query-login/query-login-node.ts
|
|
1355
|
+
var cache = new LoginNodeCache;
|
|
1356
|
+
|
|
1357
|
+
class QueryLoginNode extends QueryLogin {
|
|
1358
|
+
constructor(opts) {
|
|
1359
|
+
const baseURL = opts?.query?.baseURL;
|
|
1360
|
+
const storage = new StorageNode({ baseURL, load: true });
|
|
1361
|
+
const cache2 = new LoginNodeCache({ baseURL, load: true });
|
|
1362
|
+
super({
|
|
1363
|
+
...opts,
|
|
1364
|
+
isBrowser: false,
|
|
1365
|
+
storage,
|
|
1366
|
+
cache: cache2
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
export {
|
|
1371
|
+
cache,
|
|
1372
|
+
StorageNode,
|
|
1373
|
+
QueryLoginNode
|
|
1374
|
+
};
|