@kevisual/api 0.0.51 → 0.0.53

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.
@@ -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
+ };