@jayfong/x-utils 1.0.0-202510061015 → 3.4.0

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 (143) hide show
  1. package/lib/ai.d.mts +103 -0
  2. package/lib/ai.mjs +75 -0
  3. package/lib/cache.d.mts +464 -0
  4. package/lib/cache.mjs +531 -0
  5. package/lib/captcha.d.mts +259 -0
  6. package/lib/captcha.mjs +174 -0
  7. package/lib/case.d.mts +184 -0
  8. package/lib/case.mjs +120 -0
  9. package/lib/chinese.d.mts +57 -0
  10. package/lib/chinese.mjs +79 -0
  11. package/lib/cli.d.mts +52 -0
  12. package/lib/cli.mjs +62 -0
  13. package/lib/clipboard.d.mts +50 -0
  14. package/lib/clipboard.mjs +122 -0
  15. package/lib/cmd.d.mts +38 -0
  16. package/lib/cmd.mjs +52 -0
  17. package/lib/crawler.d.mts +330 -0
  18. package/lib/crawler.mjs +313 -0
  19. package/lib/crypto.d.mts +158 -0
  20. package/lib/crypto.mjs +213 -0
  21. package/lib/csv.d.mts +67 -0
  22. package/lib/csv.mjs +76 -0
  23. package/lib/data_set.d.mts +76 -0
  24. package/lib/data_set.mjs +104 -0
  25. package/lib/db_value.d.mts +213 -0
  26. package/lib/db_value.mjs +208 -0
  27. package/lib/dispose.d.mts +98 -0
  28. package/lib/dispose.mjs +107 -0
  29. package/lib/file_store.d.mts +167 -0
  30. package/lib/file_store.mjs +120 -0
  31. package/lib/fs.d.mts +111 -0
  32. package/lib/fs.mjs +127 -0
  33. package/lib/html.d.mts +103 -0
  34. package/lib/html.mjs +112 -0
  35. package/lib/json.d.mts +50 -0
  36. package/lib/json.mjs +74 -0
  37. package/lib/jwt.d.mts +128 -0
  38. package/lib/jwt.mjs +104 -0
  39. package/lib/mail.d.mts +125 -0
  40. package/lib/mail.mjs +108 -0
  41. package/lib/pay.d.mts +394 -0
  42. package/lib/pay.mjs +343 -0
  43. package/lib/puppeteer.d.mts +88 -0
  44. package/lib/puppeteer.mjs +219 -0
  45. package/lib/random.d.mts +71 -0
  46. package/lib/random.mjs +92 -0
  47. package/lib/redis.d.mts +32 -0
  48. package/lib/redis.mjs +24 -0
  49. package/lib/runner.d.mts +80 -0
  50. package/lib/runner.mjs +66 -0
  51. package/lib/sensitive_words.d.mts +82 -0
  52. package/lib/sensitive_words.mjs +73 -0
  53. package/lib/sms.d.mts +133 -0
  54. package/lib/sms.mjs +100 -0
  55. package/lib/task.d.mts +37 -0
  56. package/lib/task.mjs +43 -0
  57. package/lib/text.d.mts +84 -0
  58. package/lib/text.mjs +141 -0
  59. package/lib/yaml.d.mts +51 -0
  60. package/lib/yaml.mjs +64 -0
  61. package/package.json +82 -164
  62. package/_cjs/ai.js +0 -80
  63. package/_cjs/alipan.js +0 -173
  64. package/_cjs/cli.js +0 -51
  65. package/_cjs/clipboard.js +0 -65
  66. package/_cjs/cmd.js +0 -42
  67. package/_cjs/compressor.js +0 -47
  68. package/_cjs/crawler.js +0 -341
  69. package/_cjs/csv.js +0 -97
  70. package/_cjs/data_set.js +0 -115
  71. package/_cjs/env.js +0 -82
  72. package/_cjs/fs.js +0 -86
  73. package/_cjs/html.js +0 -62
  74. package/_cjs/http_server.js +0 -79
  75. package/_cjs/json.js +0 -49
  76. package/_cjs/ksb.js +0 -218
  77. package/_cjs/number.js +0 -39
  78. package/_cjs/ocr.js +0 -74
  79. package/_cjs/package.json +0 -3
  80. package/_cjs/path.js +0 -35
  81. package/_cjs/pinyin.js +0 -37
  82. package/_cjs/puppeteer.js +0 -271
  83. package/_cjs/runner.js +0 -88
  84. package/_cjs/task.js +0 -41
  85. package/_cjs/text.js +0 -136
  86. package/_cjs/unicode/lib_unicode.js +0 -58643
  87. package/_cjs/unicode/unicode.js +0 -441
  88. package/_cjs/upload.js +0 -101
  89. package/_cjs/yaml.js +0 -52
  90. package/ai.d.ts +0 -26
  91. package/ai.js +0 -60
  92. package/alipan.d.ts +0 -209
  93. package/alipan.js +0 -153
  94. package/cli.d.ts +0 -14
  95. package/cli.js +0 -21
  96. package/clipboard.d.ts +0 -6
  97. package/clipboard.js +0 -35
  98. package/cmd.d.ts +0 -5
  99. package/cmd.js +0 -22
  100. package/compressor.d.ts +0 -5
  101. package/compressor.js +0 -17
  102. package/crawler.d.ts +0 -162
  103. package/crawler.js +0 -332
  104. package/csv.d.ts +0 -14
  105. package/csv.js +0 -67
  106. package/data_set.d.ts +0 -22
  107. package/data_set.js +0 -85
  108. package/env.d.ts +0 -6
  109. package/env.js +0 -52
  110. package/fs.d.ts +0 -23
  111. package/fs.js +0 -56
  112. package/html.d.ts +0 -7
  113. package/html.js +0 -45
  114. package/http_server.d.ts +0 -13
  115. package/http_server.js +0 -49
  116. package/json.d.ts +0 -6
  117. package/json.js +0 -19
  118. package/ksb.d.ts +0 -37
  119. package/ksb.js +0 -198
  120. package/number.d.ts +0 -3
  121. package/number.js +0 -9
  122. package/ocr.d.ts +0 -17
  123. package/ocr.js +0 -54
  124. package/path.d.ts +0 -2
  125. package/path.js +0 -5
  126. package/pinyin.d.ts +0 -8
  127. package/pinyin.js +0 -17
  128. package/puppeteer.d.ts +0 -38
  129. package/puppeteer.js +0 -241
  130. package/runner.d.ts +0 -13
  131. package/runner.js +0 -58
  132. package/task.d.ts +0 -6
  133. package/task.js +0 -21
  134. package/text.d.ts +0 -63
  135. package/text.js +0 -119
  136. package/unicode/lib_unicode.d.ts +0 -4
  137. package/unicode/lib_unicode.js +0 -58623
  138. package/unicode/unicode.d.ts +0 -347
  139. package/unicode/unicode.js +0 -426
  140. package/upload.d.ts +0 -34
  141. package/upload.js +0 -71
  142. package/yaml.d.ts +0 -6
  143. package/yaml.js +0 -22
package/lib/ai.d.mts ADDED
@@ -0,0 +1,103 @@
1
+ import { PartialBy } from "vtils/types";
2
+ /**
3
+ * AI 服务配置选项。
4
+ *
5
+ * 同时作为静态调用 `AiService.ask(payload)` 与实例化
6
+ * `new AiService(options)` 的公共配置。
7
+ */
8
+ export interface AiServiceOptions {
9
+ /** 接口基础地址,例如 `https://dashscope.aliyuncs.com/compatible-mode/v1`。 */
10
+ baseUrl: string;
11
+ /** API 密钥,例如 `sk-xxx`;请求时会以 `Bearer <apiKey>` 形式放入 Authorization 头。 */
12
+ apiKey: string;
13
+ /** 模型名称,例如 `deepseek-v3.1`。 */
14
+ model: string;
15
+ /**
16
+ * 请求超时毫秒数,默认 1 分钟;
17
+ * 静态与实例调用均可通过该字段自定义超时时间。
18
+ */
19
+ timeoutMs?: number;
20
+ /**
21
+ * 额外请求头,会与内置的 `Authorization` 头合并;
22
+ * 同名键(如 `Authorization`)会覆盖内置值。
23
+ */
24
+ headers?: Record<string, string>;
25
+ }
26
+ /**
27
+ * 单次问答的请求参数。
28
+ *
29
+ * - 静态调用 `AiService.ask(payload)` 时,需要完整传入 `baseUrl` / `apiKey` / `model`;
30
+ * - 实例调用 `ai.ask(payload)` 时,以上配置可省略(缺省时回退到构造时的 options)。
31
+ */
32
+ export interface AiServiceAskPayload extends AiServiceOptions {
33
+ /** 系统提示词,用于设定助手的角色或背景;不传时仅发送用户问题。 */
34
+ prompt?: string;
35
+ /** 用户提出的问题。 */
36
+ question: string;
37
+ }
38
+ /**
39
+ * Chat Completions 接口返回的单条消息。
40
+ */
41
+ export interface AiServiceChatMessage {
42
+ /** 消息角色,例如 `system` / `user` / `assistant`。 */
43
+ role: string;
44
+ /** 消息内容文本。 */
45
+ content: string;
46
+ }
47
+ /**
48
+ * Chat Completions 接口返回的候选回答。
49
+ */
50
+ export interface AiServiceChatChoice {
51
+ /** 候选回答中的消息内容。 */
52
+ message: AiServiceChatMessage;
53
+ }
54
+ /**
55
+ * Chat Completions 接口的响应体(仅保留本项目用到的字段)。
56
+ */
57
+ export interface AiServiceChatResponse {
58
+ /** 候选回答列表,通常取第一条作为最终回答。 */
59
+ choices: AiServiceChatChoice[];
60
+ }
61
+ /**
62
+ * 单次问答的返回结果。
63
+ */
64
+ export interface AiServiceAskResult {
65
+ /** 模型返回的回答文本。 */
66
+ answer: string;
67
+ }
68
+ /**
69
+ * 基于 OpenAI 兼容的 Chat Completions 接口封装的 AI 问答服务。
70
+ *
71
+ * 支持两种调用方式:
72
+ * 1. 静态调用(一次性传入全部配置):
73
+ * `await AiService.ask({ baseUrl, apiKey, model, question: '你好' })`
74
+ * 2. 实例调用(配置复用,仅需传入问题):
75
+ * `const ai = new AiService({ baseUrl, apiKey, model }); await ai.ask({ question: '你好' })`
76
+ */
77
+ export declare class AiService {
78
+ private options;
79
+ constructor(options: AiServiceOptions);
80
+ /**
81
+ * 发送一次问答请求。
82
+ *
83
+ * 行为说明:
84
+ * 1. 请求地址为 `${baseUrl}/chat/completions`;
85
+ * 2. 自动拼接 `Authorization: Bearer <apiKey>` 头,并合并 `headers` 自定义头(自定义头优先);
86
+ * 3. 若传入 `prompt`,会作为 `system` 消息放在 `user` 消息之前;否则仅发送 `user` 消息;
87
+ * 4. 默认 `stream: false`,一次性返回完整回答;
88
+ * 5. 默认请求超时为 1 分钟,可通过 `timeoutMs` 自定义(单位毫秒);
89
+ * 且不自动抛出 HTTP 错误(由本方法自行判断状态码)。
90
+ *
91
+ * 异常场景:
92
+ * - 当接口返回非 200 状态码时,先输出原始错误信息便于排查,再抛出包含响应体的异常;
93
+ * - 当返回的 `choices` 为空或首条消息缺少 `content` 时,抛出提示异常的异常,避免返回空回答。
94
+ */
95
+ static ask(payload: AiServiceAskPayload): Promise<AiServiceAskResult>;
96
+ /**
97
+ * 实例问答:复用构造时传入的配置,允许按需覆盖部分配置。
98
+ *
99
+ * 最终配置为构造配置与本次参数的合并(`{ ...this.options, ...payload }`),
100
+ * 因此可在单次调用中覆盖 `model`、`prompt` 等任意字段。
101
+ */
102
+ ask(payload: PartialBy<AiServiceAskPayload, keyof AiServiceOptions>): Promise<AiServiceAskResult>;
103
+ }
package/lib/ai.mjs ADDED
@@ -0,0 +1,75 @@
1
+ import { xr } from "@jayfong/x-request";
2
+ import { ms } from "vtils";
3
+ // src/ai.ts
4
+ /**
5
+ * 基于 OpenAI 兼容的 Chat Completions 接口封装的 AI 问答服务。
6
+ *
7
+ * 支持两种调用方式:
8
+ * 1. 静态调用(一次性传入全部配置):
9
+ * `await AiService.ask({ baseUrl, apiKey, model, question: '你好' })`
10
+ * 2. 实例调用(配置复用,仅需传入问题):
11
+ * `const ai = new AiService({ baseUrl, apiKey, model }); await ai.ask({ question: '你好' })`
12
+ */
13
+ var AiService = class AiService {
14
+ options;
15
+ constructor(options) {
16
+ this.options = options;
17
+ }
18
+ /**
19
+ * 发送一次问答请求。
20
+ *
21
+ * 行为说明:
22
+ * 1. 请求地址为 `${baseUrl}/chat/completions`;
23
+ * 2. 自动拼接 `Authorization: Bearer <apiKey>` 头,并合并 `headers` 自定义头(自定义头优先);
24
+ * 3. 若传入 `prompt`,会作为 `system` 消息放在 `user` 消息之前;否则仅发送 `user` 消息;
25
+ * 4. 默认 `stream: false`,一次性返回完整回答;
26
+ * 5. 默认请求超时为 1 分钟,可通过 `timeoutMs` 自定义(单位毫秒);
27
+ * 且不自动抛出 HTTP 错误(由本方法自行判断状态码)。
28
+ *
29
+ * 异常场景:
30
+ * - 当接口返回非 200 状态码时,先输出原始错误信息便于排查,再抛出包含响应体的异常;
31
+ * - 当返回的 `choices` 为空或首条消息缺少 `content` 时,抛出提示异常的异常,避免返回空回答。
32
+ */
33
+ static async ask(payload) {
34
+ const res = await xr.postJson({
35
+ url: `${payload.baseUrl}/chat/completions`,
36
+ headers: {
37
+ Authorization: `Bearer ${payload.apiKey}`,
38
+ ...payload.headers
39
+ },
40
+ data: {
41
+ model: payload.model,
42
+ messages: [...payload.prompt ? [{
43
+ role: "system",
44
+ content: payload.prompt
45
+ }] : [], {
46
+ role: "user",
47
+ content: payload.question
48
+ }],
49
+ stream: false
50
+ },
51
+ timeoutMs: payload.timeoutMs ?? ms("1m"),
52
+ noThrowHttpErrors: true
53
+ });
54
+ if (res.status !== 200) {
55
+ console.error(res.data);
56
+ throw new Error(JSON.stringify(res.data));
57
+ }
58
+ const answer = res.data?.choices?.[0]?.message?.content;
59
+ if (answer == null) throw new Error("AI 服务返回的 choices 为空,或首条消息缺少 content");
60
+ return { answer };
61
+ }
62
+ /**
63
+ * 实例问答:复用构造时传入的配置,允许按需覆盖部分配置。
64
+ *
65
+ * 最终配置为构造配置与本次参数的合并(`{ ...this.options, ...payload }`),
66
+ * 因此可在单次调用中覆盖 `model`、`prompt` 等任意字段。
67
+ */
68
+ ask(payload) {
69
+ return AiService.ask({
70
+ ...this.options,
71
+ ...payload
72
+ });
73
+ }
74
+ };
75
+ export { AiService };
@@ -0,0 +1,464 @@
1
+ import { XRedis } from "./redis.mjs";
2
+ import { MsValue } from "vtils";
3
+ import { AsyncOrSync, IsEmptyArray } from "vtils/types";
4
+ /**
5
+ * 序列化工具接口。
6
+ *
7
+ * 用于在写入 Redis 前将任意值转换为字符串,并在读取时还原为原值。
8
+ * 内置 `nativeJsonSerializer` 与 `superJsonSerializer` 两个实现,
9
+ * 也可自行实现以支持自定义数据格式(例如加密、压缩)。
10
+ */
11
+ export interface XCacheSerializer {
12
+ /**
13
+ * 将值序列化为字符串。
14
+ *
15
+ * @param value 待序列化的值。
16
+ * @returns 序列化后的字符串。
17
+ */
18
+ stringify(value: unknown): string;
19
+ /**
20
+ * 将字符串反序列化为原值。
21
+ *
22
+ * @param value 待反序列化的字符串。
23
+ * @returns 反序列化后的值。
24
+ */
25
+ parse<T>(value: string): T;
26
+ }
27
+ /**
28
+ * {@link XCache} 的配置项。
29
+ */
30
+ export interface XCacheOptions {
31
+ /**
32
+ * 缓存键前缀。
33
+ *
34
+ * 所有写入 Redis 的键都会加上该前缀,用于区分不同应用或模块的缓存,
35
+ * 例如 `app:` 会将键 `user_1` 落为 `app:user_1`。
36
+ */
37
+ prefix: string;
38
+ /**
39
+ * Redis 客户端实例。
40
+ *
41
+ * 仅在 `memory` 不为 `'only'` 时使用;`memory=only` 模式下可传入任意
42
+ * 实现,但不会被访问。
43
+ */
44
+ redis: XRedis;
45
+ /**
46
+ * 默认过期时间。
47
+ *
48
+ * 在 `set`/`remember` 等写入方法未显式指定 TTL 时使用。可为毫秒数或
49
+ * 时间字符串(如 `'1h'`、`'30s'`),解析规则同 `vtils` 的 `ms`。
50
+ */
51
+ ttl: MsValue;
52
+ /**
53
+ * 是否启用内存缓存。
54
+ *
55
+ * - `true`:启用内存缓存,写入时同时写 Redis 与内存,读取时优先命中内存;
56
+ * - `'only'`:仅使用内存缓存,完全不读写 Redis(TTL 不生效);
57
+ * - 缺省:不使用内存缓存,全部走 Redis。
58
+ */
59
+ memory?: boolean | 'only';
60
+ /**
61
+ * 序列化工具。
62
+ *
63
+ * - `'nativeJson'`:使用原生 JSON 序列化/反序列化(默认),性能最好,
64
+ * 但无法还原 `Date`、`RegExp`、`Set` 等特殊类型;
65
+ * - `'superJson'`:使用 SuperJson 序列化/反序列化,支持更多数据类型,
66
+ * 但性能较原生 JSON 略差;
67
+ * - 也可直接传入自定义 `{ stringify, parse }` 实现。
68
+ */
69
+ serializer?: 'nativeJson' | 'superJson' | XCacheSerializer;
70
+ }
71
+ /**
72
+ * 缓存数据描述类型。
73
+ *
74
+ * 作为 {@link XCache} 的泛型约束:键为字符串、值为函数。函数名即缓存键,
75
+ * 函数入参与返回值分别用于推导完整键路径与缓存值类型。
76
+ *
77
+ * @example
78
+ * type UserData = {
79
+ * user: (id: number) => string;
80
+ * totalUser: () => number;
81
+ * };
82
+ */
83
+ export type XCacheData = { [K in string]: (...args: any[]) => any; };
84
+ /**
85
+ * 缓存数据描述中的键名集合。
86
+ */
87
+ export type XCacheKey<T extends XCacheData> = keyof T;
88
+ /**
89
+ * 完整缓存键路径。
90
+ *
91
+ * - 无参函数:键名本身,如 `totalUser`;
92
+ * - 有参函数:`[键名, ...参数]` 元组,如 `['user', 1]`。
93
+ */
94
+ export type XCacheKeyPath<T extends XCacheData> = { [K in keyof T]: T[K] extends ((...args: infer X) => any) ? IsEmptyArray<X> extends true ? K : [K, ...X] : never; }[keyof T];
95
+ /**
96
+ * 数字值对应的完整缓存键路径。
97
+ *
98
+ * 与 {@link XCacheKeyPath} 结构一致,但仅保留返回值为 `number` 的函数,
99
+ * 用于 `increase`/`decrease` 等数值操作方法。
100
+ */
101
+ export type XCacheKeyPathForNumberValue<T extends XCacheData> = { [K in keyof T]: T[K] extends ((...args: infer X) => number) ? IsEmptyArray<X> extends true ? K : [K, ...X] : never; }[keyof T];
102
+ /**
103
+ * 根据缓存键路径推导缓存值类型。
104
+ */
105
+ export type XCacheValue<T extends XCacheData, P extends XCacheKeyPath<T>> = ReturnType<T[P extends any[] ? P[0] : P]>;
106
+ /**
107
+ * 允许参数部分缺省的缓存键路径。
108
+ *
109
+ * 与 {@link XCacheKeyPath} 结构一致,但函数入参使用 `Partial`,
110
+ * 用于 `clear` 等按前缀(部分参数)清理的方法。
111
+ */
112
+ export type XCacheKeyPartialPath<T extends XCacheData> = { [K in keyof T]: T[K] extends ((...args: infer X) => any) ? IsEmptyArray<X> extends true ? K : [K, ...Partial<X>] : never; }[keyof T];
113
+ /**
114
+ * 自定义 TTL。
115
+ *
116
+ * 可直接传时间值(毫秒数或时间字符串),也可传函数,依据写入的数据与
117
+ * 默认 TTL 动态计算过期时间。
118
+ */
119
+ export type XCacheSetTTL<V> = MsValue | ((data: V, defaultTTL: MsValue) => MsValue);
120
+ /**
121
+ * `set`/`remember`/`rememberMany` 等方法中 TTL 相关选项。
122
+ *
123
+ * 可直接传 {@link XCacheSetTTL},或传包含可选 `ttl` 字段的对象;
124
+ * 对象中未指定 `ttl` 时使用构造时的默认 TTL。
125
+ */
126
+ export type XCacheSetOptions<V> = XCacheSetTTL<V> | {
127
+ /**
128
+ * 缓存过期时间。
129
+ *
130
+ * 缺省时使用构造时的默认 TTL({@link XCacheOptions.ttl})。
131
+ */
132
+ ttl?: XCacheSetTTL<V>;
133
+ };
134
+ /**
135
+ * 通用缓存服务。
136
+ *
137
+ * 基于 Redis 实现,可选叠加一层进程内存缓存。通过泛型方式描述缓存键与
138
+ * 值类型,从而获得类型安全的读写体验。
139
+ *
140
+ * 泛型说明:
141
+ * - `TData`:缓存数据描述类型,形如
142
+ * `{ user: (id: number) => string; totalUser: () => number }`;
143
+ * - `TKey`:所有缓存键名(由 `TData` 推导);
144
+ * - `TKeyPath`:完整缓存键路径(无参函数为键名本身,有参函数为
145
+ * `[键名, ...参数]` 元组);
146
+ * - `TKeyPathForNumberValue`:数字值对应的完整键路径,用于自增/自减;
147
+ * - `TKeyPartialPath`:允许参数部分缺省的键路径,用于按前缀清理。
148
+ *
149
+ * 通常无需手动传泛型,直接用 `XCache` 即可;需要强类型约束时通过
150
+ * {@link XCache.fork} 传入 `TData` 派生。
151
+ *
152
+ * @example
153
+ * const cache = new XCache({
154
+ * prefix: 'app:',
155
+ * redis: new XRedis(),
156
+ * ttl: 600,
157
+ * });
158
+ *
159
+ * const userCache = cache.fork<{ user: (id: number) => string }>();
160
+ * await userCache.set(['user', 1], 'Jay');
161
+ * // 'Jay'
162
+ * const user = await userCache.get(['user', 1]);
163
+ * // 'Jay'
164
+ */
165
+ export declare class XCache<TData extends XCacheData = XCacheData, TKey extends XCacheKey<TData> = any, TKeyPath extends XCacheKeyPath<TData> = any, TKeyPathForNumberValue extends XCacheKeyPathForNumberValue<TData> = any, TKeyPartialPath extends XCacheKeyPartialPath<TData> = any> {
166
+ options: XCacheOptions;
167
+ private prefix;
168
+ private redis;
169
+ private hasMemoryCache;
170
+ private hasMemoryCacheOnly;
171
+ private memoryCache;
172
+ private serializer;
173
+ /**
174
+ * 创建缓存服务实例。
175
+ *
176
+ * @param options 缓存配置,含前缀、Redis 实例、默认 TTL 等。
177
+ */
178
+ constructor(options: XCacheOptions);
179
+ /**
180
+ * 将缓存键转换为 Redis 键。
181
+ *
182
+ * 元组键用 `_` 连接各段(如 `['user', 1]` → `user_1`),普通键直接
183
+ * 转为字符串,最终加上 {@link XCacheOptions.prefix} 前缀。
184
+ *
185
+ * 注意:使用 `_` 连接时,元组各段自身若含 `_`,可能与其他键发生冲突。
186
+ */
187
+ private toRedisKey;
188
+ /**
189
+ * 序列化值。
190
+ *
191
+ * @param value 待序列化的值。
192
+ * @returns 序列化后的字符串。
193
+ */
194
+ private serialize;
195
+ /**
196
+ * 反序列化字符串。
197
+ *
198
+ * @param value 待反序列化的字符串。
199
+ * @returns 反序列化后的值。
200
+ */
201
+ private deserialize;
202
+ /**
203
+ * 设置缓存内容。
204
+ *
205
+ * 对象类内容建议避免缓存,以免反序列化后类型丢失等问题;确需缓存对象时
206
+ * 推荐使用 `'superJson'` 序列化器。
207
+ *
208
+ * 行为与分支:
209
+ * - 未传 `ttlOrOptions`,或传入对象但未指定 `ttl` 时,使用构造时的默认
210
+ * TTL({@link XCacheOptions.ttl});
211
+ * - `ttl` 支持函数形式,可依据写入值与默认 TTL 动态计算;
212
+ * - TTL 换算后小于等于 0 时不写入任何缓存(视为禁用缓存);
213
+ * - 非 `memory=only` 模式写入 Redis;启用内存缓存时同步写入内存。
214
+ *
215
+ * @param key 缓存键,可为字符串或 `[键名, ...参数]` 元组。
216
+ * @param value 缓存值。
217
+ * @param ttlOrOptions 缓存时间或选项;缺省时使用默认 TTL。
218
+ * @returns 返回写入的缓存值。
219
+ *
220
+ * @example
221
+ * await cache.set('greeting', 'hello');
222
+ * // 'hello'
223
+ * await cache.set(['user', 1], 'Jay', 500);
224
+ * // 'Jay',500 毫秒后过期
225
+ */
226
+ set<K extends TKeyPath, V extends XCacheValue<TData, K>>(key: K, value: V, ttlOrOptions?: XCacheSetOptions<V>): Promise<V>;
227
+ /**
228
+ * 存储一个值并返回其对应的键。
229
+ *
230
+ * 键由 `X__` 前缀与 CUID2 随机串组成,仅包含字母与数字,URL 友好。
231
+ * 值可为固定值,也可为以生成键为入参的函数,便于生成引用自身的键。
232
+ *
233
+ * @param value 待存储的值,或接收生成的键并返回值的函数。
234
+ * @param ttl 存活时间;缺省时使用构造时的默认 TTL。
235
+ * @returns 生成的缓存键。
236
+ *
237
+ * @example
238
+ * const key = await cache.save('hello');
239
+ * // 'X__dj8fyuqt57ejnnbsnik8q1d6'
240
+ * await cache.get(key);
241
+ * // 'hello'
242
+ */
243
+ save<T>(value: T | ((key: string) => AsyncOrSync<T>), ttl?: MsValue): Promise<string>;
244
+ /**
245
+ * 获取缓存内容。
246
+ *
247
+ * 查找顺序:
248
+ * 1. 启用内存缓存时先查内存,命中直接返回;
249
+ * 2. `memory=only` 模式内存未命中即返回 `null`,不回源 Redis;
250
+ * 3. 其余情况从 Redis 读取;命中后反序列化,并在启用内存缓存时回填内存。
251
+ *
252
+ * Redis 中无该键、值为空或反序列化失败时均返回 `null`。
253
+ *
254
+ * @param key 缓存键。
255
+ * @returns 缓存值;不存在时返回 `null`。
256
+ *
257
+ * @example
258
+ * const user = await cache.get(['user', 1]);
259
+ * // 'Jay' | null
260
+ */
261
+ get<K extends TKeyPath, V extends XCacheValue<TData, K>>(key: K): Promise<V | null>;
262
+ /**
263
+ * 批量获取缓存内容。
264
+ *
265
+ * - 未传任何键时返回空数组;
266
+ * - `memory=only` 模式直接按内存缓存逐个返回;
267
+ * - 启用内存缓存时,内存命中的直接返回,未命中的再从 Redis 批量读取
268
+ * 并回填内存;
269
+ * - 其余情况从 Redis 批量读取。
270
+ *
271
+ * 单个键读取失败(如反序列化异常)时对应位置返回 `null`,不影响其他键。
272
+ *
273
+ * @param keys 缓存键列表。
274
+ * @returns 与入参顺序一致的缓存值数组,未命中的位置为 `null`。
275
+ *
276
+ * @example
277
+ * await cache.getMany(['user', 1], ['user', 2]);
278
+ * // ['Jay', 'Tom']
279
+ */
280
+ getMany<K extends TKeyPath, V extends XCacheValue<TData, K>>(...keys: K[]): Promise<Array<V | null>>;
281
+ /**
282
+ * 获取距离过期时间的毫秒数。
283
+ *
284
+ * - Redis 中未设置过期时间返回 `-1`,键不存在返回 `-2`;
285
+ * - `memory=only` 模式内存缓存无 TTL 概念,始终返回 `-1`。
286
+ *
287
+ * @param key 缓存键。
288
+ * @returns 距离过期的毫秒数。
289
+ *
290
+ * @example
291
+ * await cache.ttl('greeting');
292
+ * // 还剩多少毫秒过期;未设置过期时间时返回 -1
293
+ */
294
+ ttl<K extends TKeyPath>(key: K): Promise<number>;
295
+ /**
296
+ * 读取缓存,未命中时执行 `action` 获取值并写回缓存。
297
+ *
298
+ * 先按 {@link XCache.get} 逻辑读取;命中直接返回,否则执行 `action`,
299
+ * 将结果写入缓存并返回。适合「缓存优先、未命中再计算」的场景。
300
+ *
301
+ * 注意:`action` 返回 `null` 时也会写入缓存,但下次读取仍视为未命中,
302
+ * 会再次执行 `action`。
303
+ *
304
+ * @param key 缓存键。
305
+ * @param action 缓存未命中时获取内容的操作,支持同步或异步。
306
+ * @param ttlOrOptions 缓存时间或选项;缺省时使用默认 TTL。
307
+ * @returns 缓存值或 `action` 计算得到的新值。
308
+ *
309
+ * @example
310
+ * const user = await cache.remember(['user', 1], async () => {
311
+ * return await fetchUser(1);
312
+ * });
313
+ * // 命中缓存时返回缓存值,否则返回 fetchUser(1) 的结果
314
+ */
315
+ remember<K extends TKeyPath, V extends XCacheValue<TData, K>>(key: K, action: () => AsyncOrSync<V>, ttlOrOptions?: XCacheSetOptions<V>): Promise<V>;
316
+ /**
317
+ * 批量读取缓存,未命中的元素执行 `action` 获取值并写回缓存。
318
+ *
319
+ * 先按 {@link XCache.getMany} 批量读取;将未命中的原始元素(`raws` 中
320
+ * 对应下标项)交给 `action` 计算新值,再逐个写回缓存,最后返回与
321
+ * `raws` 顺序一致的结果数组。
322
+ *
323
+ * @param raws 原始数据列表,用于推导键并作为 `action` 的入参。
324
+ * @param key 从原始数据推导缓存键的函数。
325
+ * @param action 缓存未命中的元素批量计算新值的操作,返回数组需与
326
+ * 未命中元素顺序一致。
327
+ * @param ttlOrOptions 缓存时间或选项;缺省时使用默认 TTL。
328
+ * @returns 与 `raws` 顺序一致的缓存值数组。
329
+ *
330
+ * @example
331
+ * const users = await cache.rememberMany(
332
+ * [1, 2],
333
+ * id => ['user', id],
334
+ * ids => ids.map(id => fetchUser(id)),
335
+ * );
336
+ */
337
+ rememberMany<T, K extends TKeyPath, V extends XCacheValue<TData, K>>(raws: T[], key: (raw: T) => K, action: (raws: T[]) => AsyncOrSync<V[]>, ttlOrOptions?: XCacheSetOptions<V>): Promise<V[]>;
338
+ /**
339
+ * 自增。
340
+ *
341
+ * - `memory=only` 模式直接操作内存中的数字;
342
+ * - 其余模式调用 Redis `INCRBY`,并在启用内存缓存时删除对应内存键,
343
+ * 使下次读取从 Redis 回源。
344
+ *
345
+ * @param key 缓存键,对应的值类型需为 `number`。
346
+ * @param increment 增量,可为负数;缺省为 `1`。
347
+ * @returns 自增后的值。
348
+ *
349
+ * @example
350
+ * await cache.increase('totalUser');
351
+ * // 1
352
+ * await cache.increase('totalUser', 10);
353
+ * // 11
354
+ */
355
+ increase<K extends TKeyPathForNumberValue>(key: K, increment?: number): Promise<number>;
356
+ /**
357
+ * 自减。
358
+ *
359
+ * 行为与 {@link XCache.increase} 一致,仅将增量取负。
360
+ *
361
+ * @param key 缓存键,对应的值类型需为 `number`。
362
+ * @param decrement 减量,可为负数;缺省为 `1`。
363
+ * @returns 自减后的值。
364
+ *
365
+ * @example
366
+ * await cache.decrease('totalUser');
367
+ * // 10
368
+ */
369
+ decrease<K extends TKeyPathForNumberValue>(key: K, decrement?: number): Promise<number>;
370
+ /**
371
+ * 向列表尾部追加元素。
372
+ *
373
+ * - `memory=only` 模式直接操作内存数组;
374
+ * - 其余模式调用 Redis `RPUSH` 逐个追加(先序列化),并在启用内存缓存时
375
+ * 删除对应内存键,使下次读取从 Redis 回源。
376
+ *
377
+ * @param key 缓存键。
378
+ * @param values 待追加的元素列表。
379
+ * @returns 追加后列表的长度。
380
+ *
381
+ * @example
382
+ * await cache.push('queue', 'a', 'b');
383
+ * // 2
384
+ */
385
+ push<K extends TKeyPath, V extends XCacheValue<TData, K>>(key: K, ...values: V[]): Promise<number>;
386
+ /**
387
+ * 从列表头部弹出元素。
388
+ *
389
+ * - `memory=only` 模式直接操作内存数组;
390
+ * - 其余模式逐次调用 Redis `LPOP` 弹出并反序列化,遇到空列表提前结束;
391
+ * 弹出过元素且启用内存缓存时,删除对应内存键使下次读取回源。
392
+ *
393
+ * @param key 缓存键。
394
+ * @param count 弹出元素个数;缺省为 `1`,实际返回数量不超过列表长度。
395
+ * @returns 弹出的元素数组,列表为空时返回空数组。
396
+ *
397
+ * @example
398
+ * await cache.push('queue', 'a', 'b');
399
+ * await cache.shift('queue');
400
+ * // ['a']
401
+ */
402
+ shift<K extends TKeyPath, V extends XCacheValue<TData, K>>(key: K, count?: number): Promise<V[]>;
403
+ /**
404
+ * 删除缓存。
405
+ *
406
+ * - 未传任何键时返回 `0`;
407
+ * - 非 `memory=only` 模式调用 Redis `DEL`,并同步删除内存缓存;
408
+ * - `memory=only` 模式仅删除内存缓存,返回实际删除的内存键数量。
409
+ *
410
+ * @param keys 待删除的缓存键列表。
411
+ * @returns 删除的键数量。
412
+ *
413
+ * @example
414
+ * await cache.remove('greeting', ['user', 1]);
415
+ * // 2
416
+ */
417
+ remove<K extends TKeyPath>(...keys: K[]): Promise<number>;
418
+ /**
419
+ * 清空当前前缀下的全部缓存。
420
+ *
421
+ * - 非 `memory=only` 模式通过 `KEYS {prefix}*` 找出全部键后删除;
422
+ * - 启用内存缓存时清空内存缓存;`memory=only` 模式返回内存缓存大小。
423
+ *
424
+ * 注意:生产环境慎用 `KEYS`,键数量大时会阻塞 Redis。
425
+ *
426
+ * @returns 删除的键数量。
427
+ *
428
+ * @example
429
+ * await cache.clearAll();
430
+ * // 3
431
+ */
432
+ clearAll(): Promise<number>;
433
+ /**
434
+ * 清空指定前缀的缓存。
435
+ *
436
+ * 对每个前缀执行 `KEYS {前缀}*` 找出匹配键后删除;启用内存缓存时,
437
+ * 按前缀匹配清理内存缓存中的键。
438
+ *
439
+ * - 未传任何前缀时返回 `0`;
440
+ * - `memory=only` 模式仅清理内存缓存,返回实际删除的内存键数量。
441
+ *
442
+ * @param prefixes 缓存键或键前缀列表。
443
+ * @returns 删除的键数量。
444
+ *
445
+ * @example
446
+ * await cache.clear('user');
447
+ * // 删除所有以 user 开头的键
448
+ */
449
+ clear(...prefixes: Array<TKey | TKeyPartialPath>): Promise<number>;
450
+ /**
451
+ * 派生出一个指定数据类型的缓存服务。
452
+ *
453
+ * 传入 `TNextData` 后可获得带类型约束的读写方法;不传选项时直接返回
454
+ * 当前实例(仅调整类型),传选项时基于当前配置合并选项创建新实例。
455
+ *
456
+ * @param options 可选的配置覆盖项,会与当前实例配置合并。
457
+ * @returns 指定数据类型的缓存服务。
458
+ *
459
+ * @example
460
+ * const userCache = cache.fork<{ user: (id: number) => string }>();
461
+ * await userCache.set(['user', 1], 'Jay');
462
+ */
463
+ fork<TNextData extends XCacheData>(options?: Partial<XCacheOptions>): XCache<TNextData, XCacheKey<TNextData>, XCacheKeyPath<TNextData>, XCacheKeyPathForNumberValue<TNextData>, XCacheKeyPartialPath<TNextData>>;
464
+ }