node-karin 1.15.5 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/adapter-BqlH3u3X.mjs +218 -0
  3. package/dist/app-DdMQbBEY.mjs +4109 -0
  4. package/dist/cache-CPcPeo6N.mjs +163 -0
  5. package/dist/chunk-NzVPYdc1.mjs +21 -0
  6. package/dist/cli/index.cjs +10900 -1
  7. package/dist/cli/index.d.ts +1 -1
  8. package/dist/cli/index.mjs +10770 -10224
  9. package/dist/file-ZGuqNDd-.mjs +15987 -0
  10. package/dist/file-dGy9of8-.mjs +268 -0
  11. package/dist/fsSync-Cf5MWILk.mjs +65 -0
  12. package/dist/index.d.ts +12235 -12738
  13. package/dist/index.mjs +2054 -25247
  14. package/dist/internal-DupfycKE.mjs +597 -0
  15. package/dist/kv-DZp4UIxg.mjs +192 -0
  16. package/dist/module/art-template.d.ts +2 -13
  17. package/dist/module/art-template.mjs +3 -1
  18. package/dist/module/axios.d.ts +3 -2
  19. package/dist/module/axios.mjs +5 -2
  20. package/dist/module/chalk.d.ts +3 -2
  21. package/dist/module/chalk.mjs +5 -2
  22. package/dist/module/chokidar.d.ts +3 -2
  23. package/dist/module/chokidar.mjs +5 -2
  24. package/dist/module/express.d.ts +2 -1
  25. package/dist/module/express.mjs +3 -1
  26. package/dist/module/lodash.d.ts +2 -1
  27. package/dist/module/lodash.mjs +3 -1
  28. package/dist/module/log4js.d.ts +3 -2
  29. package/dist/module/log4js.mjs +5 -2
  30. package/dist/module/moment.d.ts +2 -1
  31. package/dist/module/moment.mjs +3 -1
  32. package/dist/module/node-schedule.d.ts +3 -2
  33. package/dist/module/node-schedule.mjs +5 -2
  34. package/dist/module/redis.d.ts +3 -2
  35. package/dist/module/redis.mjs +5 -2
  36. package/dist/module/sqlite3.d.ts +3 -2
  37. package/dist/module/sqlite3.mjs +5 -2
  38. package/dist/module/ws.d.ts +3 -2
  39. package/dist/module/ws.mjs +5 -2
  40. package/dist/module/yaml.d.ts +3 -2
  41. package/dist/module/yaml.mjs +5 -2
  42. package/dist/queue-CnKedaZA.mjs +70 -0
  43. package/dist/redis-aLJ7wbJH.mjs +1556 -0
  44. package/dist/render-DPqueDZr.mjs +170 -0
  45. package/dist/root.d.ts +46 -46
  46. package/dist/root.mjs +136 -93
  47. package/dist/router-zPSN9-tY.mjs +124 -0
  48. package/dist/server-DT64D-m-.mjs +38 -0
  49. package/dist/snapka-BTlnZOyI.mjs +450 -0
  50. package/dist/sqlite-Dcj9jlW9.mjs +307 -0
  51. package/dist/start/app.d.ts +1 -1
  52. package/dist/start/app.mjs +14 -7
  53. package/dist/start/index.d.ts +1 -1
  54. package/dist/start/index.mjs +325 -656
  55. package/dist/template-Djk6y0uC.mjs +133 -0
  56. package/dist/terminalManager-Lxa8Sm06.mjs +783 -0
  57. package/dist/uptime-C121X_rq.mjs +210 -0
  58. package/dist/web/{CompressaPRO-GX.woff2.br → CompressaPRO-GX.woff2} +0 -0
  59. package/dist/web/assets/css/style-CBB8wM_W.css +14880 -0
  60. package/dist/web/assets/js/entry-Blf4Trpx.js +258540 -0
  61. package/dist/web/{googleapis.woff2.br → googleapis.woff2} +0 -0
  62. package/dist/web/index.html +2 -15
  63. package/dist/web/karin.png +0 -0
  64. package/dist/web/sha256.min.js +9 -0
  65. package/dist/ws-BLDoC2gV.mjs +80 -0
  66. package/dist/ws-CcoWd3Ar.mjs +106 -0
  67. package/package.json +7 -7
  68. package/dist/global.d.d.ts +0 -68
  69. package/dist/types-hAhbXJDZ.d.ts +0 -109
  70. package/dist/web/assets/css/components-ep7vm38G.css +0 -1
  71. package/dist/web/assets/css/index-Dadvd9mn.css.br +0 -0
  72. package/dist/web/assets/css/vendor-editor-CFbL2ovg.css.br +0 -0
  73. package/dist/web/assets/css/vendor-others-ZgkIHsf0.css +0 -1
  74. package/dist/web/assets/js/components-CU2xw4lY.js.br +0 -0
  75. package/dist/web/assets/js/entry-Dvb7eYLE.js.br +0 -0
  76. package/dist/web/assets/js/hooks-CRfhs4ON.js.br +0 -0
  77. package/dist/web/assets/js/page-404.tsx-DYMd_RI_.js +0 -1
  78. package/dist/web/assets/js/page-dashboard-CG60V_Z-.js.br +0 -0
  79. package/dist/web/assets/js/page-loading.tsx-wY8a9me3.js.br +0 -0
  80. package/dist/web/assets/js/page-login.tsx-B54ZOEZB.js.br +0 -0
  81. package/dist/web/assets/js/utils-C9nWTSuo.js +0 -2
  82. package/dist/web/assets/js/vendor-editor-BmqYP7lh.js.br +0 -0
  83. package/dist/web/assets/js/vendor-heroui-ClBCy2zk.js.br +0 -0
  84. package/dist/web/assets/js/vendor-others-6GiMrjd4.js.br +0 -0
  85. package/dist/web/assets/js/vendor-react-Dc9jdQiK.js.br +0 -0
  86. package/dist/web/assets/js/vendor-ui-utils-D0xkboLL.js.br +0 -0
  87. package/dist/web/assets/js/vendor-visual-saF8KLH_.js.br +0 -0
  88. package/dist/web/karin.png.br +0 -0
  89. package/dist/web/sha256.min.js.br +0 -0
@@ -0,0 +1,1556 @@
1
+ import { t as __exportAll } from "./chunk-NzVPYdc1.mjs";
2
+ import { redisSqlite3Path } from "./root.mjs";
3
+ import { Ir as diffSimpleArray, Mi as isWin, n as redis$1 } from "./file-ZGuqNDd-.mjs";
4
+ import { f as exec } from "./uptime-C121X_rq.mjs";
5
+ import { t as SQLiteWrapper } from "./sqlite-Dcj9jlW9.mjs";
6
+ import path from "node:path";
7
+ import lodash from "lodash";
8
+ import { EventEmitter } from "node:events";
9
+ import os from "node:os";
10
+ import moment from "moment";
11
+ import { createClient } from "redis";
12
+
13
+ //#region src/core/db/redis/mock/index.ts
14
+ /**
15
+ * @description 轻量化的 Redis 客户端 仅支持部分命令
16
+ * @class RedisClient
17
+ */
18
+ var RedisClient = class extends EventEmitter {
19
+ id;
20
+ /** 键、类型、过期时间映射 */
21
+ store = {};
22
+ /** 键值对 */
23
+ #str = {};
24
+ /** 数字对 */
25
+ #num = {};
26
+ /** 哈希表 */
27
+ #hash = {};
28
+ /** 列表 */
29
+ #list = {};
30
+ /** 集合 */
31
+ #set = {};
32
+ /** 有序集合 */
33
+ #zset = {};
34
+ /** HyperLogLog */
35
+ #pf = {};
36
+ /** 位图 */
37
+ #bit = {};
38
+ /** sqlite3 */
39
+ #sqlite;
40
+ constructor(sqlite) {
41
+ super();
42
+ this.id = "mock";
43
+ this.store = {};
44
+ this.#str = {};
45
+ this.#num = {};
46
+ this.#hash = {};
47
+ this.#list = {};
48
+ this.#set = {};
49
+ this.#zset = {};
50
+ this.#pf = {};
51
+ this.#bit = {};
52
+ this.#sqlite = sqlite;
53
+ }
54
+ async init() {
55
+ await this.loadData();
56
+ /** 每30秒检查过期 */
57
+ setInterval(() => {
58
+ Object.keys(this.store).forEach((key) => this.checkExpire(key));
59
+ }, 3e4);
60
+ /** 每5分钟存一次sqlite */
61
+ setInterval(() => this.save(), 300 * 1e3);
62
+ return this;
63
+ }
64
+ /**
65
+ * @description 加载数据
66
+ */
67
+ async loadData() {
68
+ const list = await this.#sqlite.getAllData();
69
+ const keyMap = {
70
+ ["str"]: (key, value) => {
71
+ this.#str[key] = value;
72
+ },
73
+ ["num"]: (key, value) => {
74
+ this.#num[key] = Number(value);
75
+ },
76
+ ["hash"]: (key, value) => {
77
+ const hash = JSON.parse(value);
78
+ for (const field in hash) if (typeof hash[field] !== "string") hash[field] = Buffer.from(hash[field]);
79
+ this.#hash[key] = hash;
80
+ },
81
+ ["list"]: (key, value) => {
82
+ this.#list[key] = JSON.parse(value);
83
+ },
84
+ ["set"]: (key, value) => {
85
+ this.#set[key] = new Set(JSON.parse(value));
86
+ },
87
+ ["zset"]: (key, value) => {
88
+ this.#zset[key] = JSON.parse(value);
89
+ },
90
+ ["pf"]: (key, value) => {
91
+ this.#pf[key] = new Set(JSON.parse(value));
92
+ },
93
+ ["bit"]: (key, value) => {
94
+ this.#bit[key] = Buffer.from(value);
95
+ }
96
+ };
97
+ const isKey = (type) => {
98
+ return keyMap[type] !== void 0;
99
+ };
100
+ list.forEach((item) => {
101
+ const { key, type, expire, value } = item;
102
+ if (isKey(type)) {
103
+ this.store[key] = {
104
+ type,
105
+ expire
106
+ };
107
+ keyMap[type](key, value);
108
+ } else this.#sqlite.del(key);
109
+ });
110
+ logger.debug(`[Redis-mock] 加载数据完成: ${list.length}`);
111
+ }
112
+ /**
113
+ * @description 检查过期
114
+ * @param key 键
115
+ * @param isRemove 是否删除 默认删除
116
+ * @returns 是否过期或值
117
+ */
118
+ checkExpire(key, isRemove = true) {
119
+ if (!this.store[key]) return false;
120
+ if (this.store[key].expire !== -1 && this.store[key].expire < moment().valueOf()) {
121
+ if (!isRemove) return true;
122
+ this.#del(key);
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+ /**
128
+ * @description 直接删除键 不检查是否存在
129
+ * @param key 键
130
+ */
131
+ #del(key) {
132
+ const { type } = this.store[key];
133
+ delete this.store[key];
134
+ switch (type) {
135
+ case "str":
136
+ delete this.#str[key];
137
+ break;
138
+ case "num":
139
+ delete this.#num[key];
140
+ break;
141
+ case "hash":
142
+ delete this.#hash[key];
143
+ break;
144
+ case "list":
145
+ delete this.#list[key];
146
+ break;
147
+ case "set":
148
+ delete this.#set[key];
149
+ break;
150
+ case "zset":
151
+ delete this.#zset[key];
152
+ break;
153
+ case "pf":
154
+ delete this.#pf[key];
155
+ break;
156
+ case "bit":
157
+ delete this.#bit[key];
158
+ break;
159
+ }
160
+ this.#sqlite.del(key);
161
+ logger.trace(`[Redis-mock] 删除键 ${key}`);
162
+ }
163
+ /**
164
+ * @description 获取键的类型
165
+ * @param key 键
166
+ * @returns 键的类型
167
+ */
168
+ type(key) {
169
+ return this.store[key]?.type;
170
+ }
171
+ /**
172
+ * @description 存储键值对
173
+ * @param key 键
174
+ * @param value 值
175
+ * @param options 其他参数
176
+ */
177
+ async set(key, value, options = {}) {
178
+ let expire = -1;
179
+ if (!Buffer.isBuffer(value) && typeof value !== "string") value = String(value);
180
+ else if (Buffer.isBuffer(value)) value = value.toString();
181
+ /** 参数3如果为空直接保存即可 */
182
+ if (lodash.isEmpty(options)) {
183
+ this.store[key] = {
184
+ type: "str",
185
+ expire
186
+ };
187
+ this.#str[key] = value;
188
+ this.#sqlite.set(key, value, "str", expire);
189
+ return "OK";
190
+ }
191
+ /** EX */
192
+ if (options?.EX !== void 0) {
193
+ const EX = Number(options.EX);
194
+ if (!isNaN(EX)) expire = moment().add(EX, "seconds").valueOf();
195
+ this.store[key] = {
196
+ type: "str",
197
+ expire
198
+ };
199
+ this.#str[key] = value;
200
+ } else if (options?.PX !== void 0) {
201
+ const PX = Number(options.PX);
202
+ if (!isNaN(PX)) expire = moment().add(PX, "milliseconds").valueOf();
203
+ this.store[key] = {
204
+ type: "str",
205
+ expire
206
+ };
207
+ this.#str[key] = value;
208
+ } else if (options?.EXAT !== void 0) {
209
+ const EXAT = Number(options.EXAT);
210
+ if (!isNaN(EXAT)) expire = EXAT;
211
+ this.store[key] = {
212
+ type: "str",
213
+ expire
214
+ };
215
+ this.#str[key] = value;
216
+ } else if (options?.PXAT !== void 0) {
217
+ const PXAT = Number(options.PXAT);
218
+ if (!isNaN(PXAT)) expire = PXAT;
219
+ this.store[key] = {
220
+ type: "str",
221
+ expire
222
+ };
223
+ this.#str[key] = value;
224
+ } else if (options?.KEEPTTL) if (this.#str[key] && this.store[key]) {
225
+ this.#str[key] = value;
226
+ expire = this.store[key].expire;
227
+ } else {
228
+ this.store[key] = {
229
+ type: "str",
230
+ expire: -1
231
+ };
232
+ this.#str[key] = value;
233
+ expire = -1;
234
+ }
235
+ else if (options?.NX) {
236
+ if (!this.store[key] || this.checkExpire(key, false)) {
237
+ this.store[key] = {
238
+ type: "str",
239
+ expire: -1
240
+ };
241
+ this.#str[key] = value;
242
+ this.#sqlite.set(key, value, "str", -1);
243
+ }
244
+ return "OK";
245
+ } else if (options?.XX) if (this.store[key]) {
246
+ const currentExpire = this.store[key].expire;
247
+ const oldType = this.store[key].type;
248
+ if (oldType !== "str") switch (oldType) {
249
+ case "num":
250
+ delete this.#num[key];
251
+ break;
252
+ case "hash":
253
+ delete this.#hash[key];
254
+ break;
255
+ case "list":
256
+ delete this.#list[key];
257
+ break;
258
+ case "set":
259
+ delete this.#set[key];
260
+ break;
261
+ case "zset":
262
+ delete this.#zset[key];
263
+ break;
264
+ case "pf":
265
+ delete this.#pf[key];
266
+ break;
267
+ case "bit":
268
+ delete this.#bit[key];
269
+ break;
270
+ }
271
+ this.store[key] = {
272
+ type: "str",
273
+ expire: currentExpire
274
+ };
275
+ this.#str[key] = value;
276
+ this.#sqlite.set(key, value, "str", currentExpire);
277
+ return "OK";
278
+ } else return null;
279
+ else if (options?.GET) {
280
+ this.store[key] = {
281
+ type: "str",
282
+ expire: -1
283
+ };
284
+ if (this.#str[key]) {
285
+ const oldValue = this.#str[key];
286
+ this.#str[key] = value;
287
+ this.#sqlite.set(key, value, "str", expire);
288
+ return oldValue;
289
+ }
290
+ this.#str[key] = value;
291
+ this.#sqlite.set(key, value, "str", expire);
292
+ return null;
293
+ } else {
294
+ this.store[key] = {
295
+ type: "str",
296
+ expire: -1
297
+ };
298
+ this.#str[key] = value;
299
+ }
300
+ this.#sqlite.set(key, value, "str", expire);
301
+ return "OK";
302
+ }
303
+ /**
304
+ * @description 获取键值
305
+ * @param key 键
306
+ */
307
+ async get(key) {
308
+ if (!this.store[key]) return null;
309
+ /** 检查过期 */
310
+ if (this.checkExpire(key)) return null;
311
+ const { type } = this.store[key];
312
+ if (type === "num") return String(this.#num[key]);
313
+ else return this.#str[key].toString();
314
+ }
315
+ /**
316
+ * @description 设置键值对并指定过期时间(秒)
317
+ * @param key 键
318
+ * @param seconds 过期时间(秒)
319
+ * @param value 值
320
+ */
321
+ async setEx(key, seconds, value) {
322
+ return await this.set(key, value, { EX: seconds });
323
+ }
324
+ /**
325
+ * @description 设置键值对并指定过期时间(毫秒)
326
+ * @param key 键
327
+ * @param milliseconds 过期时间(毫秒)
328
+ * @param value 值
329
+ */
330
+ async pSetEx(key, milliseconds, value) {
331
+ return await this.set(key, value, { PX: milliseconds });
332
+ }
333
+ /**
334
+ * @description 仅当键不存在时设置键值对
335
+ * @param key 键
336
+ * @param value 值
337
+ * @returns 返回 1 表示键已设置,0 表示键已存在
338
+ */
339
+ async setNX(key, value) {
340
+ if (this.store[key] && !this.checkExpire(key)) return 0;
341
+ await this.set(key, value, { NX: true });
342
+ return 1;
343
+ }
344
+ /**
345
+ * @description 获取键值并设置过期时间
346
+ * @param key 键
347
+ * @param options 过期时间选项(EX: 秒, PX: 毫秒, EXAT: 秒级时间戳, PXAT: 毫秒级时间戳)
348
+ */
349
+ async getEx(key, options) {
350
+ const value = await this.get(key);
351
+ if (value === null) return null;
352
+ if (options?.PERSIST) {
353
+ if (this.store[key]) {
354
+ this.store[key].expire = -1;
355
+ const { type } = this.store[key];
356
+ const currentValue = this.getValueStringByKey(key);
357
+ this.#sqlite.set(key, currentValue, type, -1);
358
+ }
359
+ } else if (options?.EX !== void 0) await this.expire(key, options.EX);
360
+ else if (options?.PX !== void 0) {
361
+ const expire = moment().add(options.PX, "milliseconds").valueOf();
362
+ this.store[key].expire = expire;
363
+ const { type } = this.store[key];
364
+ const currentValue = this.getValueStringByKey(key);
365
+ this.#sqlite.set(key, currentValue, type, expire);
366
+ } else if (options?.EXAT !== void 0) {
367
+ this.store[key].expire = options.EXAT * 1e3;
368
+ const { type } = this.store[key];
369
+ const currentValue = this.getValueStringByKey(key);
370
+ this.#sqlite.set(key, currentValue, type, options.EXAT * 1e3);
371
+ } else if (options?.PXAT !== void 0) {
372
+ this.store[key].expire = options.PXAT;
373
+ const { type } = this.store[key];
374
+ const currentValue = this.getValueStringByKey(key);
375
+ this.#sqlite.set(key, currentValue, type, options.PXAT);
376
+ }
377
+ return value;
378
+ }
379
+ /**
380
+ * @description 获取键值并删除键
381
+ * @param key 键
382
+ */
383
+ async getDel(key) {
384
+ const value = await this.get(key);
385
+ if (value !== null) await this.del(key);
386
+ return value;
387
+ }
388
+ /**
389
+ * @description 删除键
390
+ * @param key 键
391
+ */
392
+ async del(key) {
393
+ if (!this.store[key]) return 0;
394
+ this.#del(key);
395
+ return 1;
396
+ }
397
+ /**
398
+ * @description 检查键是否存在
399
+ * @param key 键
400
+ */
401
+ async exists(key) {
402
+ if (!this.store[key]) return 0;
403
+ if (this.checkExpire(key)) return 0;
404
+ return 1;
405
+ }
406
+ /**
407
+ * @description 设置键的过期时间
408
+ * @param key 键
409
+ * @param seconds 过期时间(秒)
410
+ */
411
+ async expire(key, seconds) {
412
+ if (!this.store[key]) return 0;
413
+ const expire = moment().add(seconds, "seconds").valueOf();
414
+ this.store[key].expire = expire;
415
+ this.#sqlite.expire(key, expire);
416
+ return 1;
417
+ }
418
+ /**
419
+ * @description 设置键的过期时间戳(秒)
420
+ * @param key 键
421
+ * @param timestamp 过期时间戳(秒)
422
+ */
423
+ async expireAt(key, timestamp) {
424
+ if (!this.store[key]) return 0;
425
+ this.store[key].expire = timestamp * 1e3;
426
+ this.#sqlite.expire(key, timestamp * 1e3);
427
+ return 1;
428
+ }
429
+ /**
430
+ * @description 设置键的过期时间(毫秒)
431
+ * @param key 键
432
+ * @param milliseconds 过期时间(毫秒)
433
+ */
434
+ async pExpire(key, milliseconds) {
435
+ if (!this.store[key]) return 0;
436
+ const expire = moment().add(milliseconds, "milliseconds").valueOf();
437
+ this.store[key].expire = expire;
438
+ this.#sqlite.expire(key, expire);
439
+ return 1;
440
+ }
441
+ /**
442
+ * @description 设置键的过期时间戳(毫秒)
443
+ * @param key 键
444
+ * @param timestamp 过期时间戳(毫秒)
445
+ */
446
+ async pExpireAt(key, timestamp) {
447
+ if (!this.store[key]) return 0;
448
+ this.store[key].expire = timestamp;
449
+ this.#sqlite.expire(key, timestamp);
450
+ return 1;
451
+ }
452
+ /**
453
+ * @description 移除键的过期时间
454
+ * @param key 键
455
+ */
456
+ async persist(key) {
457
+ if (!this.store[key]) return 0;
458
+ if (this.store[key].expire === -1) return 0;
459
+ this.store[key].expire = -1;
460
+ const { type } = this.store[key];
461
+ const currentValue = this.getValueStringByKey(key);
462
+ this.#sqlite.set(key, currentValue, type, -1);
463
+ return 1;
464
+ }
465
+ /**
466
+ * @description 获取键的过期时间
467
+ * @param key 键
468
+ */
469
+ async ttl(key) {
470
+ if (!this.store[key]) return -2;
471
+ if (this.store[key].expire === -1) return -1;
472
+ if (this.checkExpire(key)) return -2;
473
+ return moment(this.store[key].expire).diff(moment(), "seconds");
474
+ }
475
+ /**
476
+ * @description 获取键的过期时间(毫秒)
477
+ * @param key 键
478
+ */
479
+ async pTTL(key) {
480
+ if (!this.store[key]) return -2;
481
+ if (this.store[key].expire === -1) return -1;
482
+ if (this.checkExpire(key)) return -2;
483
+ return moment(this.store[key].expire).diff(moment(), "milliseconds");
484
+ }
485
+ /**
486
+ * @description 获取字符串长度
487
+ * @param key 键
488
+ */
489
+ async strLen(key) {
490
+ if (!this.store[key]) return 0;
491
+ if (this.checkExpire(key)) return 0;
492
+ const { type } = this.store[key];
493
+ if (type === "str") return this.#str[key].length;
494
+ return 0;
495
+ }
496
+ /**
497
+ * @description 重命名键
498
+ * @param key 原键名
499
+ * @param newKey 新键名
500
+ */
501
+ async rename(key, newKey) {
502
+ if (!this.store[key]) throw new Error("no such key");
503
+ const { type, expire } = this.store[key];
504
+ const value = this.getValueStringByKey(key);
505
+ this.#del(key);
506
+ this.store[newKey] = {
507
+ type,
508
+ expire
509
+ };
510
+ switch (type) {
511
+ case "str":
512
+ this.#str[newKey] = value;
513
+ break;
514
+ case "num":
515
+ this.#num[newKey] = Number(value);
516
+ break;
517
+ case "hash":
518
+ this.#hash[newKey] = JSON.parse(value);
519
+ break;
520
+ case "list":
521
+ this.#list[newKey] = JSON.parse(value);
522
+ break;
523
+ case "set":
524
+ this.#set[newKey] = new Set(JSON.parse(value));
525
+ break;
526
+ case "zset":
527
+ this.#zset[newKey] = JSON.parse(value);
528
+ break;
529
+ case "pf":
530
+ this.#pf[newKey] = new Set(JSON.parse(value));
531
+ break;
532
+ case "bit":
533
+ this.#bit[newKey] = Buffer.from(value, "base64");
534
+ break;
535
+ }
536
+ this.#sqlite.set(newKey, value, type, expire);
537
+ return "OK";
538
+ }
539
+ /**
540
+ * @description 仅当新键不存在时重命名键
541
+ * @param key 原键名
542
+ * @param newKey 新键名
543
+ */
544
+ async renameNX(key, newKey) {
545
+ if (!this.store[key]) return 0;
546
+ if (this.store[newKey] && !this.checkExpire(newKey)) return 0;
547
+ await this.rename(key, newKey);
548
+ return 1;
549
+ }
550
+ /**
551
+ * @description 返回数据库中键的数量
552
+ */
553
+ async dbSize() {
554
+ Object.keys(this.store).forEach((key) => this.checkExpire(key));
555
+ return Object.keys(this.store).length;
556
+ }
557
+ /**
558
+ * @description 从数据库中随机返回一个键
559
+ */
560
+ async randomKey() {
561
+ const keys = Object.keys(this.store);
562
+ if (keys.length === 0) return null;
563
+ keys.forEach((key) => this.checkExpire(key));
564
+ const validKeys = Object.keys(this.store);
565
+ if (validKeys.length === 0) return null;
566
+ return validKeys[Math.floor(Math.random() * validKeys.length)];
567
+ }
568
+ /**
569
+ * @description 获取所有键
570
+ * @param pattern 匹配规则
571
+ */
572
+ async keys(pattern) {
573
+ const reg = new RegExp(pattern.replace(/\*/g, ".*"));
574
+ const keys = Object.keys(this.store);
575
+ const result = [];
576
+ await Promise.all(keys.map(async (key) => {
577
+ if (this.checkExpire(key)) return;
578
+ if (reg.test(key)) result.push(key);
579
+ }));
580
+ return result;
581
+ }
582
+ /**
583
+ * @description 清空所有键
584
+ */
585
+ async flushAll() {
586
+ this.#str = {};
587
+ this.#num = {};
588
+ this.#hash = {};
589
+ this.#list = {};
590
+ this.#set = {};
591
+ this.#zset = {};
592
+ this.#pf = {};
593
+ this.#bit = {};
594
+ this.store = {};
595
+ return "OK";
596
+ }
597
+ /**
598
+ * @description 自增
599
+ * @param key 键
600
+ */
601
+ async incr(key) {
602
+ if (!this.#num[key]) {
603
+ this.#num[key] = 0;
604
+ this.store[key] = {
605
+ type: "num",
606
+ expire: -1
607
+ };
608
+ } else if (this.checkExpire(key, false)) {
609
+ this.store[key].expire = -1;
610
+ this.#num[key] = 0;
611
+ }
612
+ this.#num[key] += 1;
613
+ this.#sqlite.set(key, String(this.#num[key]), "num", this.store[key].expire);
614
+ return this.#num[key];
615
+ }
616
+ /**
617
+ * @description 自增指定值
618
+ * @param key 键
619
+ * @param increment 增量
620
+ */
621
+ async incrBy(key, increment) {
622
+ if (!this.#num[key]) {
623
+ this.#num[key] = 0;
624
+ this.store[key] = {
625
+ type: "num",
626
+ expire: -1
627
+ };
628
+ } else if (this.checkExpire(key, false)) {
629
+ this.store[key].expire = -1;
630
+ this.#num[key] = 0;
631
+ }
632
+ this.#num[key] += increment;
633
+ this.#sqlite.set(key, String(this.#num[key]), "num", this.store[key].expire);
634
+ return this.#num[key];
635
+ }
636
+ /**
637
+ * @description 自增指定浮点值
638
+ * @param key 键
639
+ * @param increment 增量(浮点数)
640
+ */
641
+ async incrByFloat(key, increment) {
642
+ if (!this.#num[key]) {
643
+ this.#num[key] = 0;
644
+ this.store[key] = {
645
+ type: "num",
646
+ expire: -1
647
+ };
648
+ } else if (this.checkExpire(key, false)) {
649
+ this.store[key].expire = -1;
650
+ this.#num[key] = 0;
651
+ }
652
+ this.#num[key] += increment;
653
+ this.#sqlite.set(key, String(this.#num[key]), "num", this.store[key].expire);
654
+ return this.#num[key];
655
+ }
656
+ /**
657
+ * @description 自减
658
+ * @param key 键
659
+ */
660
+ async decr(key) {
661
+ if (!this.#num[key]) {
662
+ this.#num[key] = 0;
663
+ this.store[key] = {
664
+ type: "num",
665
+ expire: -1
666
+ };
667
+ } else if (this.checkExpire(key, false)) {
668
+ this.store[key].expire = -1;
669
+ this.#num[key] = 0;
670
+ }
671
+ this.#num[key] -= 1;
672
+ this.#sqlite.set(key, String(this.#num[key]), "num", this.store[key].expire);
673
+ return this.#num[key];
674
+ }
675
+ /**
676
+ * @description 自减指定值
677
+ * @param key 键
678
+ * @param decrement 减量
679
+ */
680
+ async decrBy(key, decrement) {
681
+ if (!this.#num[key]) {
682
+ this.#num[key] = 0;
683
+ this.store[key] = {
684
+ type: "num",
685
+ expire: -1
686
+ };
687
+ } else if (this.checkExpire(key, false)) {
688
+ this.store[key].expire = -1;
689
+ this.#num[key] = 0;
690
+ }
691
+ this.#num[key] -= decrement;
692
+ this.#sqlite.set(key, String(this.#num[key]), "num", this.store[key].expire);
693
+ return this.#num[key];
694
+ }
695
+ /**
696
+ * @description 追加字符串
697
+ * @param key 键
698
+ * @param value 值
699
+ */
700
+ async append(key, value) {
701
+ if (!this.#str[key]) {
702
+ this.#str[key] = "";
703
+ this.store[key] = {
704
+ type: "str",
705
+ expire: -1
706
+ };
707
+ } else if (this.checkExpire(key, false)) {
708
+ this.store[key].expire = -1;
709
+ this.#str[key] = "";
710
+ }
711
+ if (Buffer.isBuffer(value)) this.#str[key] += Buffer.concat([Buffer.from(this.#str[key]), value]).toString();
712
+ else this.#str[key] += value;
713
+ this.#sqlite.set(key, this.#str[key], "str", this.store[key].expire);
714
+ return this.#str[key].length;
715
+ }
716
+ /**
717
+ * @description
718
+ * @param key
719
+ * @param field
720
+ * @param value
721
+ * @returns
722
+ */
723
+ /**
724
+ * 将字段和值设置到指定键的哈希表中
725
+ * 如果键不存在,则创建一个新的哈希表
726
+ * @param key 哈希表的键
727
+ * @param field 哈希表中的字段
728
+ * @param value 要设置的值,可以是字符串或缓冲区
729
+ * @returns 返回 1 表示设置成功,0 表示设置失败
730
+ */
731
+ async hSet(key, field, value) {
732
+ if (!this.#hash[key]) {
733
+ this.store[key] = {
734
+ type: "hash",
735
+ expire: -1
736
+ };
737
+ this.#hash[key] = {};
738
+ } else if (this.checkExpire(key, false)) {
739
+ this.store[key].expire = -1;
740
+ this.#hash[key] = {};
741
+ }
742
+ this.#hash[key][field] = value;
743
+ this.#sqlite.set(key, JSON.stringify(this.#hash[key]), "hash", this.store[key].expire);
744
+ return 1;
745
+ }
746
+ /**
747
+ * 获取哈希表字段的值
748
+ * @param key 哈希表的键
749
+ * @param field 哈希表中的字段
750
+ * @returns 返回字段的值,如果字段不存在则返回 null
751
+ */
752
+ async hGet(key, field) {
753
+ if (!this.#hash[key] || !this.#hash[key][field]) return null;
754
+ if (this.checkExpire(key)) return null;
755
+ return this.#hash[key][field].toString();
756
+ }
757
+ /**
758
+ * 删除哈希表中的一个或多个字段
759
+ * @param key 哈希表的键
760
+ * @param field 要删除的字段
761
+ * @returns 返回成功删除的字段数量
762
+ */
763
+ async hDel(key, field) {
764
+ if (!this.#hash[key] || !this.#hash[key][field]) return 0;
765
+ if (this.checkExpire(key)) return 0;
766
+ delete this.#hash[key][field];
767
+ this.#sqlite.set(key, JSON.stringify(this.#hash[key]), "hash", this.store[key].expire);
768
+ return 1;
769
+ }
770
+ /**
771
+ * 获取哈希表中所有字段的值
772
+ * @param key 哈希表的键
773
+ * @returns 返回所有字段的值
774
+ */
775
+ async hGetAll(key) {
776
+ if (!this.#hash[key]) return {};
777
+ if (this.checkExpire(key)) return {};
778
+ return lodash.mapValues(this.#hash[key], (value) => value.toString());
779
+ }
780
+ /**
781
+ * 将一个或多个值插入到列表的头部
782
+ * @param key 列表的键
783
+ * @param values 要插入的值
784
+ */
785
+ async lPush(key, ...values) {
786
+ if (!this.#list[key]) {
787
+ this.store[key] = {
788
+ type: "list",
789
+ expire: -1
790
+ };
791
+ this.#list[key] = [];
792
+ } else if (this.checkExpire(key, false)) {
793
+ this.store[key].expire = -1;
794
+ this.#list[key] = [];
795
+ }
796
+ this.#list[key].unshift(...values);
797
+ this.#sqlite.set(key, JSON.stringify(this.#list[key]), "list", this.store[key].expire);
798
+ return this.#list[key].length;
799
+ }
800
+ /**
801
+ * 将一个或多个值插入到列表的尾部
802
+ * @param key 列表的键
803
+ * @param values 要插入的值
804
+ */
805
+ async rPush(key, ...values) {
806
+ if (!this.#list[key]) {
807
+ this.store[key] = {
808
+ type: "list",
809
+ expire: -1
810
+ };
811
+ this.#list[key] = [];
812
+ } else if (this.checkExpire(key, false)) {
813
+ this.store[key].expire = -1;
814
+ this.#list[key] = [];
815
+ }
816
+ this.#list[key].push(...values);
817
+ this.#sqlite.set(key, JSON.stringify(this.#list[key]), "list", this.store[key].expire);
818
+ return this.#list[key].length;
819
+ }
820
+ /**
821
+ * 移除并返回列表的第一个元素
822
+ * @param key 列表的键
823
+ * @returns 返回列表的第一个元素,如果列表为空则返回 null
824
+ */
825
+ async lPop(key) {
826
+ if (!this.#list[key] || this.#list[key].length === 0) return null;
827
+ if (this.checkExpire(key)) return null;
828
+ const value = this.#list[key].shift();
829
+ this.#sqlite.set(key, JSON.stringify(this.#list[key]), "list", this.store[key].expire);
830
+ return value ? value.toString() : null;
831
+ }
832
+ /**
833
+ * 移除并返回列表的最后一个元素
834
+ * @param key 列表的键
835
+ * @returns 返回列表的最后一个元素,如果列表为空则返回 null
836
+ */
837
+ async rPop(key) {
838
+ if (!this.#list[key] || this.#list[key].length === 0) return null;
839
+ if (this.checkExpire(key)) return null;
840
+ const value = this.#list[key].pop();
841
+ this.#sqlite.set(key, JSON.stringify(this.#list[key]), "list", this.store[key].expire);
842
+ return value ? value.toString() : null;
843
+ }
844
+ /**
845
+ * 返回列表指定范围内的元素
846
+ * @param key 列表的键
847
+ * @returns 返回列表指定范围内的元素
848
+ */
849
+ async lRange(key, start, stop) {
850
+ if (!this.#list[key]) return [];
851
+ if (this.checkExpire(key)) return [];
852
+ const value = this.#list[key].slice(start, stop + 1).map((value) => value.toString());
853
+ this.#sqlite.set(key, JSON.stringify(this.#list[key]), "list", this.store[key].expire);
854
+ return value;
855
+ }
856
+ /**
857
+ * 向集合添加一个或多个成员
858
+ * @param key 集合的键
859
+ * @param members 要添加的成员
860
+ * @returns 返回成功添加的成员数量
861
+ */
862
+ async sAdd(key, ...members) {
863
+ if (!this.#set[key]) {
864
+ this.store[key] = {
865
+ type: "set",
866
+ expire: -1
867
+ };
868
+ this.#set[key] = /* @__PURE__ */ new Set();
869
+ } else if (this.checkExpire(key, false)) {
870
+ this.store[key].expire = -1;
871
+ this.#set[key] = /* @__PURE__ */ new Set();
872
+ }
873
+ let added = 0;
874
+ for (const member of members) if (!this.#set[key].has(member.toString())) {
875
+ this.#set[key].add(member.toString());
876
+ added++;
877
+ }
878
+ this.#sqlite.set(key, JSON.stringify(this.#set[key]), "set", this.store[key].expire);
879
+ return added;
880
+ }
881
+ /**
882
+ * 从集合中移除一个或多个成员
883
+ * @param key 集合的键
884
+ * @param members 要移除的成员
885
+ * @returns 返回成功移除的成员数量
886
+ */
887
+ async sRem(key, ...members) {
888
+ if (!this.#set[key]) return 0;
889
+ if (this.checkExpire(key)) return 0;
890
+ let removed = 0;
891
+ for (const member of members) if (this.#set[key].has(member.toString())) {
892
+ this.#set[key].delete(member.toString());
893
+ removed++;
894
+ }
895
+ this.#sqlite.set(key, JSON.stringify(this.#set[key]), "set", this.store[key].expire);
896
+ return removed;
897
+ }
898
+ /**
899
+ * 返回集合的所有成员
900
+ * @param key 集合的键
901
+ * @returns 返回集合的所有成员
902
+ */
903
+ async sMembers(key) {
904
+ if (!this.#set[key]) return [];
905
+ if (this.checkExpire(key)) return [];
906
+ return Array.from(this.#set[key]).map((member) => member.toString());
907
+ }
908
+ /**
909
+ * 检查成员是否是集合的成员
910
+ * @param key 集合的键
911
+ * @param member 要检查的成员
912
+ * @returns 返回 1 表示是集合的成员,0 表示不是集合的成员
913
+ */
914
+ async sismember(key, member) {
915
+ if (!this.#set[key]) return 0;
916
+ if (this.checkExpire(key)) return 0;
917
+ return this.#set[key].has(member.toString()) ? 1 : 0;
918
+ }
919
+ /**
920
+ * 向有序集合添加一个或多个成员
921
+ * @param key 有序集合的键
922
+ * @param score 分数
923
+ * @param member 成员
924
+ * @returns 返回成功添加的成员数量
925
+ */
926
+ async zAdd(key, score, member) {
927
+ if (!this.#zset[key]) {
928
+ this.store[key] = {
929
+ type: "zset",
930
+ expire: -1
931
+ };
932
+ this.#zset[key] = [];
933
+ } else if (this.checkExpire(key, false)) {
934
+ this.store[key].expire = -1;
935
+ this.#zset[key] = [];
936
+ }
937
+ const index = this.#zset[key].findIndex((entry) => entry.member === member.toString());
938
+ if (index === -1) this.#zset[key].push({
939
+ score,
940
+ member
941
+ });
942
+ else this.#zset[key][index] = {
943
+ score,
944
+ member
945
+ };
946
+ this.#sqlite.set(key, JSON.stringify(this.#zset[key]), "zset", this.store[key].expire);
947
+ return 1;
948
+ }
949
+ /**
950
+ * 返回有序集合的成员数量
951
+ * @param key 有序集合的键
952
+ * @returns 返回有序集合的成员数量
953
+ */
954
+ async zcard(key) {
955
+ if (!this.#list[key]) return 0;
956
+ if (this.checkExpire(key)) return 0;
957
+ return this.#list[key].length;
958
+ }
959
+ /**
960
+ * 返回有序集合中指定成员的排名
961
+ * @param key 有序集合的键
962
+ * @param member 成员
963
+ * @returns 返回成员的排名,如果成员不存在则返回 null
964
+ */
965
+ async zRank(key, member) {
966
+ if (!this.#list[key]) return null;
967
+ if (this.checkExpire(key)) return null;
968
+ const index = this.#list[key].findIndex((entry) => entry === member.toString());
969
+ return index !== -1 ? index : null;
970
+ }
971
+ /**
972
+ * 返回有序集合中指定成员的分数
973
+ * @param key 有序集合的键
974
+ * @param member 成员
975
+ * @returns 返回成员的分数,如果成员不存在则返回 null
976
+ */
977
+ async zScore(key, member) {
978
+ if (!this.#list[key]) return null;
979
+ if (this.checkExpire(key)) return null;
980
+ const entry = this.#list[key].find((entry) => entry === member.toString());
981
+ return entry ? entry.length : null;
982
+ }
983
+ /**
984
+ * 从 HyperLogLog 中添加一个或多个元素
985
+ * @param key HyperLogLog 的键
986
+ * @param elements 要添加的元素
987
+ * @returns 返回 1 表示添加成功,0 表示添加失败
988
+ */
989
+ async pfAdd(key, ...elements) {
990
+ if (!this.#pf[key]) {
991
+ this.store[key] = {
992
+ type: "pf",
993
+ expire: -1
994
+ };
995
+ this.#pf[key] = /* @__PURE__ */ new Set();
996
+ } else if (this.checkExpire(key, false)) {
997
+ this.store[key].expire = -1;
998
+ this.#pf[key] = /* @__PURE__ */ new Set();
999
+ }
1000
+ let added = 0;
1001
+ for (const element of elements) if (!this.#pf[key].has(element.toString())) {
1002
+ this.#pf[key].add(element.toString());
1003
+ added++;
1004
+ }
1005
+ this.#sqlite.set(key, JSON.stringify(this.#pf[key]), "pf", this.store[key].expire);
1006
+ return added > 0;
1007
+ }
1008
+ /**
1009
+ * 返回 HyperLogLog 的基数估算值
1010
+ * @param key HyperLogLog 的键
1011
+ * @returns 返回基数估算值
1012
+ */
1013
+ async pfCount(key) {
1014
+ if (!this.#pf[key]) return 0;
1015
+ if (this.checkExpire(key)) return 0;
1016
+ return this.#pf[key].size;
1017
+ }
1018
+ /**
1019
+ * @description 发布消息到频道
1020
+ * @param channel 频道
1021
+ * @param message 消息
1022
+ * @returns 返回订阅者数量
1023
+ */
1024
+ async publish(channel, message) {
1025
+ this.emit(channel, message.toString());
1026
+ return this.listenerCount(channel);
1027
+ }
1028
+ /**
1029
+ * @description 订阅一个或多个频道
1030
+ * @param channels 频道
1031
+ * @param listener 监听器
1032
+ * @returns 返回订阅的频道数量
1033
+ */
1034
+ async subscribe(channels, listener) {
1035
+ channels.forEach((channel) => this.on(channel, listener));
1036
+ return channels.length;
1037
+ }
1038
+ /**
1039
+ * @description 取消订阅一个或多个频道
1040
+ * @param channels 频道
1041
+ * @param listener 监听器
1042
+ * @returns 返回取消订阅的频道数量
1043
+ */
1044
+ async unsubscribe(channels, listener) {
1045
+ channels.forEach((channel) => this.off(channel, listener));
1046
+ return channels.length;
1047
+ }
1048
+ /**
1049
+ * @description 设置位图指定偏移量的值
1050
+ * @param key 键
1051
+ * @param offset 偏移量
1052
+ * @param value 值
1053
+ * @returns 返回设置前的位
1054
+ */
1055
+ async setBit(key, offset, value) {
1056
+ if (!this.#bit[key]) {
1057
+ this.store[key] = {
1058
+ type: "bit",
1059
+ expire: -1
1060
+ };
1061
+ this.#bit[key] = Buffer.alloc(0);
1062
+ } else if (this.checkExpire(key, false)) {
1063
+ this.store[key].expire = -1;
1064
+ this.#bit[key] = Buffer.alloc(0);
1065
+ }
1066
+ const byteOffset = Math.floor(offset / 8);
1067
+ const bitOffset = offset % 8;
1068
+ const oldValue = this.#bit[key].readUInt8(byteOffset);
1069
+ const newValue = value ? oldValue | 1 << bitOffset : oldValue & ~(1 << bitOffset);
1070
+ this.#bit[key].writeUInt8(newValue, byteOffset);
1071
+ this.#sqlite.set(key, this.#bit[key].toString("base64"), "bit", this.store[key].expire);
1072
+ return oldValue;
1073
+ }
1074
+ /**
1075
+ * @description 获取位图指定偏移量的值
1076
+ * @param key 键
1077
+ * @param offset 偏移量
1078
+ * @returns 返回位
1079
+ */
1080
+ async getBit(key, offset) {
1081
+ if (!this.#bit[key]) return 0;
1082
+ if (this.checkExpire(key)) return 0;
1083
+ const byteOffset = Math.floor(offset / 8);
1084
+ const bitOffset = offset % 8;
1085
+ return this.#bit[key].readUInt8(byteOffset) & 1 << bitOffset ? 1 : 0;
1086
+ }
1087
+ /**
1088
+ * @description 获取位图的指定范围内的位
1089
+ * @param key 键
1090
+ * @param start 起始偏移量
1091
+ * @param end 结束偏移量
1092
+ * @returns 返回位数组
1093
+ */
1094
+ async getRange(key, start, end) {
1095
+ if (!this.#bit[key]) return [];
1096
+ if (this.checkExpire(key)) return [];
1097
+ const result = [];
1098
+ for (let i = start; i <= end; i++) result.push(await this.getBit(key, i));
1099
+ return result;
1100
+ }
1101
+ /**
1102
+ * 获取哈希表中字段是否存在
1103
+ * @param key 哈希表的键
1104
+ * @param field 哈希表中的字段
1105
+ * @returns 返回1表示字段存在,0表示字段不存在
1106
+ */
1107
+ async hExists(key, field) {
1108
+ if (!this.#hash[key]) return 0;
1109
+ if (this.checkExpire(key)) return 0;
1110
+ return this.#hash[key][field] !== void 0 ? 1 : 0;
1111
+ }
1112
+ /**
1113
+ * 获取哈希表中所有字段名
1114
+ * @param key 哈希表的键
1115
+ * @returns 返回所有字段名数组
1116
+ */
1117
+ async hKeys(key) {
1118
+ if (!this.#hash[key]) return [];
1119
+ if (this.checkExpire(key)) return [];
1120
+ return Object.keys(this.#hash[key]);
1121
+ }
1122
+ /**
1123
+ * 获取哈希表中所有值
1124
+ * @param key 哈希表的键
1125
+ * @returns 返回所有值数组
1126
+ */
1127
+ async hVals(key) {
1128
+ if (!this.#hash[key]) return [];
1129
+ if (this.checkExpire(key)) return [];
1130
+ return Object.values(this.#hash[key]).map((value) => value.toString());
1131
+ }
1132
+ /**
1133
+ * 获取哈希表中字段数量
1134
+ * @param key 哈希表的键
1135
+ * @returns 返回字段数量
1136
+ */
1137
+ async hLen(key) {
1138
+ if (!this.#hash[key]) return 0;
1139
+ if (this.checkExpire(key)) return 0;
1140
+ return Object.keys(this.#hash[key]).length;
1141
+ }
1142
+ /**
1143
+ * 批量获取哈希表中字段的值
1144
+ * @param key 哈希表的键
1145
+ * @param fields 要获取的字段数组
1146
+ * @returns 返回字段值数组,不存在的字段返回null
1147
+ */
1148
+ async hMGet(key, ...fields) {
1149
+ if (!this.#hash[key]) return fields.map(() => null);
1150
+ if (this.checkExpire(key)) return fields.map(() => null);
1151
+ return fields.map((field) => {
1152
+ const value = this.#hash[key][field];
1153
+ return value !== void 0 ? value.toString() : null;
1154
+ });
1155
+ }
1156
+ /**
1157
+ * 批量设置哈希表中字段的值
1158
+ * @param key 哈希表的键
1159
+ * @param fieldValues 字段和值的数组,格式为[field1, value1, field2, value2, ...]
1160
+ * @returns 返回"OK"
1161
+ */
1162
+ async hMSet(key, ...fieldValues) {
1163
+ if (!this.#hash[key]) {
1164
+ this.store[key] = {
1165
+ type: "hash",
1166
+ expire: -1
1167
+ };
1168
+ this.#hash[key] = {};
1169
+ } else if (this.checkExpire(key, false)) {
1170
+ this.store[key].expire = -1;
1171
+ this.#hash[key] = {};
1172
+ }
1173
+ for (let i = 0; i < fieldValues.length; i += 2) if (i + 1 < fieldValues.length) {
1174
+ const field = fieldValues[i].toString();
1175
+ const value = fieldValues[i + 1];
1176
+ this.#hash[key][field] = value;
1177
+ }
1178
+ this.#sqlite.set(key, JSON.stringify(this.#hash[key]), "hash", this.store[key].expire);
1179
+ return "OK";
1180
+ }
1181
+ /**
1182
+ * 获取列表长度
1183
+ * @param key 列表的键
1184
+ * @returns 返回列表长度
1185
+ */
1186
+ async lLen(key) {
1187
+ if (!this.#list[key]) return 0;
1188
+ if (this.checkExpire(key)) return 0;
1189
+ return this.#list[key].length;
1190
+ }
1191
+ /**
1192
+ * 获取列表指定索引的元素
1193
+ * @param key 列表的键
1194
+ * @param index 索引,0表示第一个元素,-1表示最后一个元素
1195
+ * @returns 返回元素值,索引超出范围返回null
1196
+ */
1197
+ async lIndex(key, index) {
1198
+ if (!this.#list[key]) return null;
1199
+ if (this.checkExpire(key)) return null;
1200
+ const list = this.#list[key];
1201
+ if (index < 0) index = list.length + index;
1202
+ if (index < 0 || index >= list.length) return null;
1203
+ return list[index].toString();
1204
+ }
1205
+ /**
1206
+ * 设置列表指定索引的元素值
1207
+ * @param key 列表的键
1208
+ * @param index 索引
1209
+ * @param value 值
1210
+ * @returns 成功返回"OK",失败返回错误
1211
+ */
1212
+ async lSet(key, index, value) {
1213
+ if (!this.#list[key]) return null;
1214
+ if (this.checkExpire(key)) return null;
1215
+ const list = this.#list[key];
1216
+ if (index < 0) index = list.length + index;
1217
+ if (index < 0 || index >= list.length) return null;
1218
+ list[index] = value;
1219
+ this.#sqlite.set(key, JSON.stringify(list), "list", this.store[key].expire);
1220
+ return "OK";
1221
+ }
1222
+ /**
1223
+ * 移除列表中与指定值相等的元素
1224
+ * @param key 列表的键
1225
+ * @param count 移除的数量,0表示移除所有匹配的元素,正数表示从头部开始移除,负数表示从尾部开始移除
1226
+ * @param value 要移除的值
1227
+ * @returns 返回移除的元素数量
1228
+ */
1229
+ async lRem(key, count, value) {
1230
+ if (!this.#list[key]) return 0;
1231
+ if (this.checkExpire(key)) return 0;
1232
+ const list = this.#list[key];
1233
+ const strValue = value.toString();
1234
+ let removed = 0;
1235
+ if (count === 0) {
1236
+ const newList = list.filter((item) => item.toString() !== strValue);
1237
+ removed = list.length - newList.length;
1238
+ this.#list[key] = newList;
1239
+ } else if (count > 0) {
1240
+ for (let i = 0; i < list.length && removed < count; i++) if (list[i].toString() === strValue) {
1241
+ list.splice(i, 1);
1242
+ removed++;
1243
+ i--;
1244
+ }
1245
+ } else {
1246
+ count = Math.abs(count);
1247
+ for (let i = list.length - 1; i >= 0 && removed < count; i--) if (list[i].toString() === strValue) {
1248
+ list.splice(i, 1);
1249
+ removed++;
1250
+ }
1251
+ }
1252
+ this.#sqlite.set(key, JSON.stringify(list), "list", this.store[key].expire);
1253
+ return removed;
1254
+ }
1255
+ /**
1256
+ * 获取集合中元素数量
1257
+ * @param key 集合的键
1258
+ * @returns 返回集合中元素数量
1259
+ */
1260
+ async sCard(key) {
1261
+ if (!this.#set[key]) return 0;
1262
+ if (this.checkExpire(key)) return 0;
1263
+ return this.#set[key].size;
1264
+ }
1265
+ /**
1266
+ * 计算集合的差集
1267
+ * @param keys 集合的键数组
1268
+ * @returns 返回差集数组
1269
+ */
1270
+ async sDiff(...keys) {
1271
+ if (keys.length === 0) return [];
1272
+ const firstKey = keys[0];
1273
+ if (!this.#set[firstKey]) return [];
1274
+ if (this.checkExpire(firstKey)) return [];
1275
+ const result = /* @__PURE__ */ new Set();
1276
+ for (const item of this.#set[firstKey]) result.add(item.toString());
1277
+ for (let i = 1; i < keys.length; i++) {
1278
+ const key = keys[i];
1279
+ if (!this.#set[key] || this.checkExpire(key)) continue;
1280
+ for (const item of this.#set[key]) result.delete(item.toString());
1281
+ }
1282
+ return Array.from(result);
1283
+ }
1284
+ /**
1285
+ * 计算集合的交集
1286
+ * @param keys 集合的键数组
1287
+ * @returns 返回交集数组
1288
+ */
1289
+ async sInter(...keys) {
1290
+ if (keys.length === 0) return [];
1291
+ const validKeys = keys.filter((key) => this.#set[key] && !this.checkExpire(key));
1292
+ if (validKeys.length === 0) return [];
1293
+ const result = /* @__PURE__ */ new Set();
1294
+ const firstKey = validKeys[0];
1295
+ for (const item of this.#set[firstKey]) {
1296
+ let inAllSets = true;
1297
+ for (let i = 1; i < validKeys.length; i++) {
1298
+ const key = validKeys[i];
1299
+ if (!this.#set[key].has(item.toString())) {
1300
+ inAllSets = false;
1301
+ break;
1302
+ }
1303
+ }
1304
+ if (inAllSets) result.add(item.toString());
1305
+ }
1306
+ return Array.from(result);
1307
+ }
1308
+ /**
1309
+ * 计算集合的并集
1310
+ * @param keys 集合的键数组
1311
+ * @returns 返回并集数组
1312
+ */
1313
+ async sUnion(...keys) {
1314
+ const result = /* @__PURE__ */ new Set();
1315
+ for (const key of keys) {
1316
+ if (!this.#set[key] || this.checkExpire(key)) continue;
1317
+ for (const item of this.#set[key]) result.add(item.toString());
1318
+ }
1319
+ return Array.from(result);
1320
+ }
1321
+ /**
1322
+ * 将多个键的值同时获取
1323
+ * @param keys 要获取的键数组
1324
+ * @returns 返回值数组,不存在的键返回null
1325
+ */
1326
+ async mGet(...keys) {
1327
+ return Promise.all(keys.map((key) => this.get(key)));
1328
+ }
1329
+ /**
1330
+ * 同时设置多个键值对
1331
+ * @param keyValues 键值对数组,格式为[key1, value1, key2, value2, ...]
1332
+ * @returns 返回"OK"
1333
+ */
1334
+ async mSet(...keyValues) {
1335
+ for (let i = 0; i < keyValues.length; i += 2) if (i + 1 < keyValues.length) {
1336
+ const key = keyValues[i].toString();
1337
+ const value = keyValues[i + 1];
1338
+ await this.set(key, value);
1339
+ }
1340
+ return "OK";
1341
+ }
1342
+ /**
1343
+ * 设置键的新值并返回旧值
1344
+ * @param key 键
1345
+ * @param value 新值
1346
+ * @returns 返回旧值,如果键不存在则返回null
1347
+ */
1348
+ async getSet(key, value) {
1349
+ const oldValue = await this.get(key);
1350
+ await this.set(key, value);
1351
+ return oldValue;
1352
+ }
1353
+ /**
1354
+ * 修复zRange方法,使用正确的zset数据结构
1355
+ * 返回有序集合的成员数量
1356
+ * @param key 有序集合的键
1357
+ * @returns 返回有序集合的成员数量
1358
+ */
1359
+ async zRange(key, start, stop) {
1360
+ if (!this.#zset[key]) return [];
1361
+ if (this.checkExpire(key)) return [];
1362
+ return [...this.#zset[key]].sort((a, b) => a.score - b.score).slice(start, stop + 1).map((entry) => entry.member.toString());
1363
+ }
1364
+ /**
1365
+ * 按分数范围返回有序集合的成员
1366
+ * @param key 有序集合的键
1367
+ * @param min 最小分数
1368
+ * @param max 最大分数
1369
+ * @returns 返回指定分数范围的成员数组
1370
+ */
1371
+ async zRangeByScore(key, min, max) {
1372
+ if (!this.#zset[key]) return [];
1373
+ if (this.checkExpire(key)) return [];
1374
+ return this.#zset[key].filter((entry) => entry.score >= min && entry.score <= max).sort((a, b) => a.score - b.score).map((entry) => entry.member.toString());
1375
+ }
1376
+ /**
1377
+ * 按分数降序返回有序集合的成员
1378
+ * @param key 有序集合的键
1379
+ * @param start 起始索引
1380
+ * @param stop 结束索引
1381
+ * @returns 返回指定范围的成员数组(按分数降序)
1382
+ */
1383
+ async zRevRange(key, start, stop) {
1384
+ if (!this.#zset[key]) return [];
1385
+ if (this.checkExpire(key)) return [];
1386
+ return [...this.#zset[key]].sort((a, b) => b.score - a.score).slice(start, stop + 1).map((entry) => entry.member.toString());
1387
+ }
1388
+ /**
1389
+ * 获取有序集合中指定成员的排名(按分数降序)
1390
+ * @param key 有序集合的键
1391
+ * @param member 成员
1392
+ * @returns 返回成员的排名,不存在返回null
1393
+ */
1394
+ async zRevRank(key, member) {
1395
+ if (!this.#zset[key]) return null;
1396
+ if (this.checkExpire(key)) return null;
1397
+ const strMember = member.toString();
1398
+ const sortedEntries = [...this.#zset[key]].sort((a, b) => b.score - a.score);
1399
+ for (let i = 0; i < sortedEntries.length; i++) if (sortedEntries[i].member.toString() === strMember) return i;
1400
+ return null;
1401
+ }
1402
+ /**
1403
+ * 从有序集合中移除一个或多个成员
1404
+ * @param key 有序集合的键
1405
+ * @param member 要移除的成员
1406
+ * @returns 返回成功移除的成员数量
1407
+ */
1408
+ async zRem(key, member) {
1409
+ if (!this.#zset[key]) return 0;
1410
+ if (this.checkExpire(key)) return 0;
1411
+ const strMember = member.toString();
1412
+ const index = this.#zset[key].findIndex((entry) => entry.member.toString() === strMember);
1413
+ if (index !== -1) {
1414
+ this.#zset[key].splice(index, 1);
1415
+ this.#sqlite.set(key, JSON.stringify(this.#zset[key]), "zset", this.store[key].expire);
1416
+ return 1;
1417
+ }
1418
+ return 0;
1419
+ }
1420
+ /**
1421
+ * 根据键类型获取值的字符串表示
1422
+ * @param key 键名
1423
+ * @returns 值的字符串表示
1424
+ */
1425
+ getValueStringByKey(key) {
1426
+ const { type } = this.store[key];
1427
+ switch (type) {
1428
+ case "str": return this.#str[key];
1429
+ case "num": return String(this.#num[key]);
1430
+ case "hash": return JSON.stringify(this.#hash[key]);
1431
+ case "list": return JSON.stringify(this.#list[key]);
1432
+ case "set": return JSON.stringify(Array.from(this.#set[key]));
1433
+ case "zset": return JSON.stringify(this.#zset[key]);
1434
+ case "pf": return JSON.stringify(Array.from(this.#pf[key]));
1435
+ case "bit": return this.#bit[key].toString("base64");
1436
+ default: return "";
1437
+ }
1438
+ }
1439
+ async save() {
1440
+ const { removed, added, common } = diffSimpleArray(await this.#sqlite.keys(), Object.keys(this.store));
1441
+ removed.forEach((key) => {
1442
+ this.#sqlite.del(key);
1443
+ });
1444
+ added.forEach((key) => {
1445
+ const { type, expire } = this.store[key];
1446
+ const value = this.getValueStringByKey(key);
1447
+ this.#sqlite.set(key, value, type, expire);
1448
+ });
1449
+ await Promise.all(common.map(async (key) => {
1450
+ const data = this.store[key];
1451
+ if (!data) return;
1452
+ const { type, expire } = data;
1453
+ const currentValue = this.getValueStringByKey(key);
1454
+ const sql = await this.#sqlite.get(key);
1455
+ if (sql?.expire !== expire || sql?.value !== currentValue) this.#sqlite.set(key, currentValue, type, expire);
1456
+ }));
1457
+ return "OK";
1458
+ }
1459
+ };
1460
+
1461
+ //#endregion
1462
+ //#region src/core/db/redis/redis.ts
1463
+ var redis_exports = /* @__PURE__ */ __exportAll({
1464
+ createRedis: () => createRedis,
1465
+ redis: () => redis
1466
+ });
1467
+ /**
1468
+ * @public
1469
+ * @description Redis数据库
1470
+ */
1471
+ let redis;
1472
+ /**
1473
+ * @description 创建 Redis 客户端
1474
+ * @param options Redis 客户端配置
1475
+ * @returns Redis 客户端
1476
+ */
1477
+ const create = async (options) => {
1478
+ try {
1479
+ const client = createClient(options);
1480
+ await client.connect();
1481
+ Object.defineProperty(client, "id", { value: "Redis" });
1482
+ return client;
1483
+ } catch (error) {
1484
+ logger.debug(`${logger.red("[redis] 启动失败:")} ${JSON.stringify(options)}`);
1485
+ logger.debug(error);
1486
+ }
1487
+ };
1488
+ /**
1489
+ * @description 尝试主动拉起 Redis
1490
+ * @returns 是否成功
1491
+ */
1492
+ const start = async () => {
1493
+ logger.debug("[redis] 正在尝试启动 Redis...");
1494
+ if (isWin()) {
1495
+ const result = await exec("redis-server.exe redis.conf", { booleanResult: true });
1496
+ if (result) return result;
1497
+ return await exec("net start Redis", { booleanResult: true });
1498
+ }
1499
+ return await exec("redis-server --save 300 10 --daemonize yes" + await isArm64(), { booleanResult: true });
1500
+ };
1501
+ /**
1502
+ * @description Redis 服务
1503
+ * @returns Redis 客户端
1504
+ */
1505
+ const createRedis = async () => {
1506
+ try {
1507
+ const options = redis$1();
1508
+ let client = await create(options);
1509
+ if (client) {
1510
+ logger.info(`[redis] ${logger.green("Redis 连接成功")}`);
1511
+ redis = client;
1512
+ return redis;
1513
+ }
1514
+ if (await start()) {
1515
+ logger.debug(logger.green("[redis] 主动拉起 Redis 成功"));
1516
+ client = await create(options);
1517
+ } else logger.debug(logger.red("[redis] 主动拉起 Redis 失败"));
1518
+ if (client) {
1519
+ redis = client;
1520
+ return redis;
1521
+ }
1522
+ throw new Error("Redis 启动失败");
1523
+ } catch (error) {
1524
+ logger.debug(`[redis] ${logger.red("Redis 连接失败")}`);
1525
+ logger.debug(error);
1526
+ logger.debug(logger.yellow("[redis] 将降级为 redis-mock 实现"));
1527
+ redis = await mock();
1528
+ return redis;
1529
+ }
1530
+ };
1531
+ /**
1532
+ * @description 判断是否为 arm64 架构
1533
+ * @returns 返回 arm64 专属参数
1534
+ */
1535
+ const isArm64 = async () => {
1536
+ if (os.arch() !== "arm64") return "";
1537
+ /** 提取版本 只有>=6的版本才忽略警告 */
1538
+ const { stdout } = await exec("redis-server -v");
1539
+ const version = stdout.toString();
1540
+ if (!version) return "";
1541
+ const RedisVersion = version.match(/v=(\d)./);
1542
+ if (RedisVersion && Number(RedisVersion[1]) >= 6) return " --ignore-warnings ARM64-COW-BUG";
1543
+ return "";
1544
+ };
1545
+ /**
1546
+ * @description 伪 Redis 实现
1547
+ * @returns Redis 客户端
1548
+ */
1549
+ const mock = async () => {
1550
+ const redis = await new RedisClient(await new SQLiteWrapper(path.join(redisSqlite3Path, "redis.db")).init()).init();
1551
+ Object.defineProperty(redis, "id", { value: "mock" });
1552
+ return redis;
1553
+ };
1554
+
1555
+ //#endregion
1556
+ export { redis as n, redis_exports as r, createRedis as t };