@jayfong/x-server 2.119.0 → 3.1.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 (288) hide show
  1. package/lib/_virtual/_rolldown/runtime.mjs +4 -0
  2. package/lib/cli/api_generator.d.mts +75 -0
  3. package/lib/cli/api_generator.mjs +334 -0
  4. package/lib/cli/build_util.d.mts +15 -0
  5. package/lib/cli/build_util.mjs +101 -0
  6. package/lib/cli/cli.d.mts +1 -0
  7. package/lib/cli/cli.mjs +345 -0
  8. package/lib/cli/css_register.d.mts +1 -0
  9. package/lib/cli/css_register.mjs +7 -0
  10. package/lib/cli/deploy_util.d.mts +23 -0
  11. package/lib/cli/deploy_util.mjs +70 -0
  12. package/lib/cli/dev_util.d.mts +9 -0
  13. package/lib/cli/dev_util.mjs +25 -0
  14. package/lib/cli/env_util.d.mts +45 -0
  15. package/lib/cli/env_util.mjs +207 -0
  16. package/lib/cli/template_util.d.mts +18 -0
  17. package/lib/cli/template_util.mjs +85 -0
  18. package/lib/cli/templates/crons.ts +1 -1
  19. package/lib/cli/templates/handlers.ts +1 -1
  20. package/lib/cli/templates/hooks.ts +1 -1
  21. package/lib/cli/templates/models.ts +7 -7
  22. package/lib/cli/templates/package.json +11 -1
  23. package/lib/cli/templates/routes.ts +2 -2
  24. package/lib/core/ctx_storage.d.mts +3 -0
  25. package/lib/core/ctx_storage.mjs +4 -0
  26. package/lib/core/define_bus.d.mts +37 -0
  27. package/lib/core/define_bus.mjs +12 -0
  28. package/lib/core/{define_cron.d.ts → define_cron.d.mts} +2 -2
  29. package/lib/core/define_cron.mjs +11 -0
  30. package/lib/core/{define_handler.d.ts → define_handler.d.mts} +19 -19
  31. package/lib/core/define_handler.mjs +44 -0
  32. package/lib/core/define_hook.d.mts +2 -0
  33. package/lib/core/define_hook.mjs +6 -0
  34. package/lib/core/define_server.d.mts +3 -0
  35. package/lib/core/define_server.mjs +8 -0
  36. package/lib/core/{define_task.d.ts → define_task.d.mts} +2 -2
  37. package/lib/core/define_task.mjs +106 -0
  38. package/lib/core/get_handler_url.d.mts +2 -0
  39. package/lib/core/get_handler_url.mjs +7 -0
  40. package/lib/core/handler.d.mts +16 -0
  41. package/lib/core/handler.mjs +132 -0
  42. package/lib/core/http_error.d.mts +2 -0
  43. package/lib/core/http_error.mjs +1 -0
  44. package/lib/core/http_header.d.mts +856 -0
  45. package/lib/core/http_header.mjs +860 -0
  46. package/lib/core/http_method.d.mts +3 -0
  47. package/lib/core/http_method.mjs +10 -0
  48. package/lib/core/http_redirect.d.mts +5 -0
  49. package/lib/core/http_redirect.mjs +10 -0
  50. package/lib/core/server.d.mts +20 -0
  51. package/lib/core/server.mjs +186 -0
  52. package/lib/core/types.d.mts +256 -0
  53. package/lib/exports.d.mts +46 -0
  54. package/lib/exports.mjs +46 -0
  55. package/lib/index.d.mts +48 -0
  56. package/lib/index.mjs +45 -0
  57. package/lib/plugins/base.d.mts +4 -0
  58. package/lib/plugins/compress.d.mts +12 -0
  59. package/lib/plugins/compress.mjs +15 -0
  60. package/lib/plugins/cookie.d.mts +12 -0
  61. package/lib/plugins/cookie.mjs +15 -0
  62. package/lib/plugins/cors.d.mts +22 -0
  63. package/lib/plugins/cors.mjs +34 -0
  64. package/lib/plugins/file_parser.d.mts +15 -0
  65. package/lib/plugins/file_parser.mjs +24 -0
  66. package/lib/plugins/form_body_parser.d.mts +12 -0
  67. package/lib/plugins/form_body_parser.mjs +15 -0
  68. package/lib/plugins/ws_parser.d.mts +12 -0
  69. package/lib/plugins/ws_parser.mjs +15 -0
  70. package/lib/plugins/xml_parser.d.mts +19 -0
  71. package/lib/plugins/xml_parser.mjs +40 -0
  72. package/lib/services/ai.d.mts +31 -0
  73. package/lib/services/ai.mjs +44 -0
  74. package/lib/services/base.d.mts +4 -0
  75. package/lib/services/base.mjs +1 -0
  76. package/lib/services/cache.d.mts +165 -0
  77. package/lib/services/cache.mjs +323 -0
  78. package/lib/services/captcha.d.mts +65 -0
  79. package/lib/services/captcha.mjs +61 -0
  80. package/lib/services/{crypto.js → crypto.d.mts} +19 -78
  81. package/lib/services/crypto.mjs +141 -0
  82. package/lib/services/db_value.d.mts +60 -0
  83. package/lib/services/db_value.mjs +64 -0
  84. package/lib/services/dingtalk.d.mts +39 -0
  85. package/lib/services/dingtalk.mjs +44 -0
  86. package/lib/services/dispose.d.mts +17 -0
  87. package/lib/services/dispose.mjs +18 -0
  88. package/lib/services/emoji.d.mts +10 -0
  89. package/lib/services/emoji.mjs +2025 -0
  90. package/lib/services/file_store.d.mts +49 -0
  91. package/lib/services/file_store.mjs +58 -0
  92. package/lib/services/html.d.mts +11 -0
  93. package/lib/services/html.mjs +12 -0
  94. package/lib/services/jwt.d.mts +33 -0
  95. package/lib/services/jwt.mjs +42 -0
  96. package/lib/services/log.d.mts +37 -0
  97. package/lib/services/log.mjs +99 -0
  98. package/lib/services/mail.d.mts +22 -0
  99. package/lib/services/mail.mjs +28 -0
  100. package/lib/services/pay.d.mts +123 -0
  101. package/lib/services/pay.mjs +157 -0
  102. package/lib/services/random.d.mts +27 -0
  103. package/lib/services/random.mjs +42 -0
  104. package/lib/services/rate_limit.d.mts +37 -0
  105. package/lib/services/rate_limit.mjs +40 -0
  106. package/lib/services/redis.d.mts +11 -0
  107. package/lib/services/redis.mjs +6 -0
  108. package/lib/services/sensitive_words.d.mts +29 -0
  109. package/lib/services/sensitive_words.mjs +37 -0
  110. package/lib/services/sms.d.mts +40 -0
  111. package/lib/services/sms.mjs +30238 -0
  112. package/lib/types/dto.d.mts +30 -0
  113. package/lib/types/dto.mjs +1 -0
  114. package/lib/x.d.mts +11 -0
  115. package/lib/x.mjs +21 -0
  116. package/lib/x_init.d.mts +1 -0
  117. package/lib/x_init.mjs +10 -0
  118. package/package.json +82 -32
  119. package/lib/_cjs/cli/api_generator.js +0 -458
  120. package/lib/_cjs/cli/build_util.js +0 -243
  121. package/lib/_cjs/cli/cli.js +0 -378
  122. package/lib/_cjs/cli/css_register.js +0 -7
  123. package/lib/_cjs/cli/deploy_util.js +0 -76
  124. package/lib/_cjs/cli/dev_util.js +0 -26
  125. package/lib/_cjs/cli/env_util.js +0 -252
  126. package/lib/_cjs/cli/esbuild_register.js +0 -7
  127. package/lib/_cjs/cli/template_util.js +0 -101
  128. package/lib/_cjs/cli/templates/crons.ts +0 -2
  129. package/lib/_cjs/cli/templates/handlers.ts +0 -3
  130. package/lib/_cjs/cli/templates/hooks.ts +0 -2
  131. package/lib/_cjs/cli/templates/models.ts +0 -123
  132. package/lib/_cjs/cli/templates/package.json +0 -3
  133. package/lib/_cjs/cli/templates/routes.ts +0 -68
  134. package/lib/_cjs/core/ctx_storage.js +0 -6
  135. package/lib/_cjs/core/define_bus.js +0 -31
  136. package/lib/_cjs/core/define_cron.js +0 -13
  137. package/lib/_cjs/core/define_handler.js +0 -56
  138. package/lib/_cjs/core/define_hook.js +0 -8
  139. package/lib/_cjs/core/define_server.js +0 -10
  140. package/lib/_cjs/core/define_task.js +0 -113
  141. package/lib/_cjs/core/get_handler_url.js +0 -11
  142. package/lib/_cjs/core/handler.js +0 -216
  143. package/lib/_cjs/core/http_error.js +0 -6
  144. package/lib/_cjs/core/http_header.js +0 -142
  145. package/lib/_cjs/core/http_method.js +0 -12
  146. package/lib/_cjs/core/http_redirect.js +0 -11
  147. package/lib/_cjs/core/server.js +0 -219
  148. package/lib/_cjs/core/types.js +0 -8
  149. package/lib/_cjs/exports.js +0 -273
  150. package/lib/_cjs/index.js +0 -15
  151. package/lib/_cjs/plugins/base.js +0 -3
  152. package/lib/_cjs/plugins/compress.js +0 -18
  153. package/lib/_cjs/plugins/cookie.js +0 -18
  154. package/lib/_cjs/plugins/cors.js +0 -38
  155. package/lib/_cjs/plugins/file_parser.js +0 -28
  156. package/lib/_cjs/plugins/form_body_parser.js +0 -18
  157. package/lib/_cjs/plugins/ws_parser.js +0 -18
  158. package/lib/_cjs/plugins/xml_parser.js +0 -48
  159. package/lib/_cjs/services/ai.js +0 -48
  160. package/lib/_cjs/services/base.js +0 -3
  161. package/lib/_cjs/services/cache.js +0 -400
  162. package/lib/_cjs/services/captcha.js +0 -78
  163. package/lib/_cjs/services/crypto.js +0 -175
  164. package/lib/_cjs/services/db_value.js +0 -77
  165. package/lib/_cjs/services/dingtalk.js +0 -51
  166. package/lib/_cjs/services/dispose.js +0 -23
  167. package/lib/_cjs/services/emoji.js +0 -2034
  168. package/lib/_cjs/services/file_store.js +0 -67
  169. package/lib/_cjs/services/html.js +0 -17
  170. package/lib/_cjs/services/jwt.js +0 -65
  171. package/lib/_cjs/services/log.js +0 -108
  172. package/lib/_cjs/services/mail.js +0 -31
  173. package/lib/_cjs/services/pay.js +0 -191
  174. package/lib/_cjs/services/random.js +0 -51
  175. package/lib/_cjs/services/rate_limit.js +0 -54
  176. package/lib/_cjs/services/redis.js +0 -12
  177. package/lib/_cjs/services/sensitive_words.js +0 -61
  178. package/lib/_cjs/services/sms.js +0 -84
  179. package/lib/_cjs/types/dto.js +0 -3
  180. package/lib/_cjs/x.js +0 -35
  181. package/lib/cli/api_generator.d.ts +0 -74
  182. package/lib/cli/api_generator.js +0 -452
  183. package/lib/cli/build_util.d.ts +0 -17
  184. package/lib/cli/build_util.js +0 -236
  185. package/lib/cli/cli.d.ts +0 -2
  186. package/lib/cli/cli.js +0 -374
  187. package/lib/cli/css_register.js +0 -5
  188. package/lib/cli/deploy_util.d.ts +0 -23
  189. package/lib/cli/deploy_util.js +0 -70
  190. package/lib/cli/dev_util.d.ts +0 -8
  191. package/lib/cli/dev_util.js +0 -20
  192. package/lib/cli/env_util.d.ts +0 -45
  193. package/lib/cli/env_util.js +0 -246
  194. package/lib/cli/esbuild_register.js +0 -5
  195. package/lib/cli/template_util.d.ts +0 -18
  196. package/lib/cli/template_util.js +0 -95
  197. package/lib/core/ctx_storage.d.ts +0 -3
  198. package/lib/core/ctx_storage.js +0 -2
  199. package/lib/core/define_bus.d.ts +0 -37
  200. package/lib/core/define_bus.js +0 -27
  201. package/lib/core/define_cron.js +0 -9
  202. package/lib/core/define_handler.js +0 -48
  203. package/lib/core/define_hook.d.ts +0 -2
  204. package/lib/core/define_hook.js +0 -4
  205. package/lib/core/define_server.d.ts +0 -3
  206. package/lib/core/define_server.js +0 -6
  207. package/lib/core/define_task.js +0 -107
  208. package/lib/core/get_handler_url.d.ts +0 -2
  209. package/lib/core/get_handler_url.js +0 -7
  210. package/lib/core/handler.d.ts +0 -16
  211. package/lib/core/handler.js +0 -209
  212. package/lib/core/http_error.d.ts +0 -2
  213. package/lib/core/http_error.js +0 -2
  214. package/lib/core/http_header.d.ts +0 -856
  215. package/lib/core/http_header.js +0 -139
  216. package/lib/core/http_method.d.ts +0 -3
  217. package/lib/core/http_method.js +0 -8
  218. package/lib/core/http_redirect.d.ts +0 -5
  219. package/lib/core/http_redirect.js +0 -6
  220. package/lib/core/server.d.ts +0 -20
  221. package/lib/core/server.js +0 -213
  222. package/lib/core/types.d.ts +0 -265
  223. package/lib/core/types.js +0 -4
  224. package/lib/exports.d.ts +0 -45
  225. package/lib/exports.js +0 -47
  226. package/lib/index.d.ts +0 -2
  227. package/lib/index.js +0 -3
  228. package/lib/plugins/base.d.ts +0 -4
  229. package/lib/plugins/base.js +0 -1
  230. package/lib/plugins/compress.d.ts +0 -13
  231. package/lib/plugins/compress.js +0 -12
  232. package/lib/plugins/cookie.d.ts +0 -13
  233. package/lib/plugins/cookie.js +0 -12
  234. package/lib/plugins/cors.d.ts +0 -22
  235. package/lib/plugins/cors.js +0 -32
  236. package/lib/plugins/file_parser.d.ts +0 -16
  237. package/lib/plugins/file_parser.js +0 -22
  238. package/lib/plugins/form_body_parser.d.ts +0 -13
  239. package/lib/plugins/form_body_parser.js +0 -12
  240. package/lib/plugins/ws_parser.d.ts +0 -13
  241. package/lib/plugins/ws_parser.js +0 -12
  242. package/lib/plugins/xml_parser.d.ts +0 -19
  243. package/lib/plugins/xml_parser.js +0 -43
  244. package/lib/services/ai.d.ts +0 -31
  245. package/lib/services/ai.js +0 -43
  246. package/lib/services/base.d.ts +0 -4
  247. package/lib/services/base.js +0 -1
  248. package/lib/services/cache.d.ts +0 -173
  249. package/lib/services/cache.js +0 -394
  250. package/lib/services/captcha.d.ts +0 -65
  251. package/lib/services/captcha.js +0 -72
  252. package/lib/services/crypto.d.ts +0 -110
  253. package/lib/services/db_value.d.ts +0 -60
  254. package/lib/services/db_value.js +0 -72
  255. package/lib/services/dingtalk.d.ts +0 -39
  256. package/lib/services/dingtalk.js +0 -45
  257. package/lib/services/dispose.d.ts +0 -17
  258. package/lib/services/dispose.js +0 -17
  259. package/lib/services/emoji.d.ts +0 -10
  260. package/lib/services/emoji.js +0 -2029
  261. package/lib/services/file_store.d.ts +0 -49
  262. package/lib/services/file_store.js +0 -61
  263. package/lib/services/html.d.ts +0 -11
  264. package/lib/services/html.js +0 -12
  265. package/lib/services/jwt.d.ts +0 -34
  266. package/lib/services/jwt.js +0 -59
  267. package/lib/services/log.d.ts +0 -37
  268. package/lib/services/log.js +0 -102
  269. package/lib/services/mail.d.ts +0 -23
  270. package/lib/services/mail.js +0 -25
  271. package/lib/services/pay.d.ts +0 -123
  272. package/lib/services/pay.js +0 -185
  273. package/lib/services/random.d.ts +0 -27
  274. package/lib/services/random.js +0 -45
  275. package/lib/services/rate_limit.d.ts +0 -37
  276. package/lib/services/rate_limit.js +0 -49
  277. package/lib/services/redis.d.ts +0 -12
  278. package/lib/services/redis.js +0 -7
  279. package/lib/services/sensitive_words.d.ts +0 -29
  280. package/lib/services/sensitive_words.js +0 -56
  281. package/lib/services/sms.d.ts +0 -40
  282. package/lib/services/sms.js +0 -78
  283. package/lib/types/dto.d.ts +0 -86
  284. package/lib/types/dto.js +0 -1
  285. package/lib/x.d.ts +0 -17
  286. package/lib/x.js +0 -30
  287. /package/lib/{cli/css_register.d.ts → core/types.mjs} +0 -0
  288. /package/lib/{cli/esbuild_register.d.ts → plugins/base.mjs} +0 -0
@@ -0,0 +1,323 @@
1
+ import { x } from "../x.mjs";
2
+ import { ms } from "vtils";
3
+ import cuid from "cuid";
4
+ import superjson from "superjson";
5
+ // src/services/cache.ts
6
+ const nativeJsonSerializer = {
7
+ stringify: JSON.stringify,
8
+ parse: JSON.parse
9
+ };
10
+ const superJsonSerializer = {
11
+ stringify: superjson.stringify,
12
+ parse: superjson.parse
13
+ };
14
+ var CacheService = class CacheService {
15
+ options;
16
+ serviceName = "cache";
17
+ prefix;
18
+ hasMemoryCache = false;
19
+ hasMemoryCacheOnly = false;
20
+ memoryCache;
21
+ serializer;
22
+ constructor(options) {
23
+ this.options = options;
24
+ this.prefix = `${x.appId}:`;
25
+ this.hasMemoryCache = !!options.memory;
26
+ this.hasMemoryCacheOnly = options.memory === "only";
27
+ this.serializer = options.serializer == null || options.serializer === "nativeJson" ? nativeJsonSerializer : options.serializer === "superJson" ? superJsonSerializer : options.serializer;
28
+ this.memoryCache = !this.hasMemoryCache ? void 0 : /* @__PURE__ */ new Map();
29
+ }
30
+ toRedisKey(key) {
31
+ return `${this.prefix}${Array.isArray(key) ? key.join("_") : String(key)}`;
32
+ }
33
+ serialize(value) {
34
+ return this.serializer.stringify(value);
35
+ }
36
+ deserialize(value) {
37
+ return this.serializer.parse(value);
38
+ }
39
+ /**
40
+ * 设置缓存内容。对象类内容尽量避免使用,以免造成问题。
41
+ *
42
+ * @memory 支持
43
+ * @param key 键
44
+ * @param value 值
45
+ * @param ttlOrOptions 缓存时间或选项
46
+ * @returns 返回设置的缓存内容
47
+ */
48
+ async set(key, value, ttlOrOptions) {
49
+ const ttl = ttlOrOptions == null ? this.options.ttl : typeof ttlOrOptions === "object" ? ttlOrOptions.ttl : ttlOrOptions;
50
+ const redisTtl = typeof ttl === "function" ? ttl(value, this.options.ttl) : ttl;
51
+ if (redisTtl) {
52
+ const redisTtlMs = ms(redisTtl);
53
+ if (redisTtlMs > 0) {
54
+ const redisKey = this.toRedisKey(key);
55
+ if (!this.hasMemoryCacheOnly) {
56
+ const redisValue = this.serialize(value);
57
+ await x.redis.set(redisKey, redisValue, "PX", redisTtlMs);
58
+ }
59
+ if (this.hasMemoryCache) this.memoryCache.set(redisKey, value);
60
+ }
61
+ }
62
+ return value;
63
+ }
64
+ /**
65
+ * 存储值然后返回其对应的键,该键 URL 友好。
66
+ *
67
+ * @memory 支持
68
+ * @param value 值
69
+ * @param ttl 存活时间
70
+ */
71
+ async save(value, ttl = this.options.ttl) {
72
+ const key = `X__${cuid()}`;
73
+ await this.set(key, typeof value === "function" ? await value(key) : value, ttl);
74
+ return key;
75
+ }
76
+ /**
77
+ * 获取缓存内容。
78
+ *
79
+ * @memory 支持
80
+ * @param key 键
81
+ * @param options 选项
82
+ * @returns 返回获取到的缓存内容
83
+ */
84
+ async get(key) {
85
+ const redisKey = this.toRedisKey(key);
86
+ if (this.hasMemoryCache) {
87
+ if (this.memoryCache.has(redisKey)) return this.memoryCache.get(redisKey);
88
+ else if (this.hasMemoryCacheOnly) return null;
89
+ }
90
+ const gotValue = await x.redis.get(redisKey);
91
+ if (gotValue) try {
92
+ const parsedValue = this.deserialize(gotValue);
93
+ if (this.hasMemoryCache) this.memoryCache.set(redisKey, parsedValue);
94
+ return parsedValue;
95
+ } catch {}
96
+ return null;
97
+ }
98
+ /**
99
+ * 获取多个缓存内容。
100
+ *
101
+ * @memory 支持
102
+ * @param keys 键
103
+ * @returns 返回获取到的缓存内容
104
+ */
105
+ async getMany(...keys) {
106
+ const redisKeys = keys.map((key) => this.toRedisKey(key));
107
+ if (!redisKeys.length) return [];
108
+ if (this.hasMemoryCacheOnly) return redisKeys.map((redisKey) => this.memoryCache.has(redisKey) ? this.memoryCache.get(redisKey) : null);
109
+ if (this.hasMemoryCache) {
110
+ const result = new Array(keys.length).fill(null);
111
+ const missIndexes = [];
112
+ const missRedisKeys = [];
113
+ for (let i = 0; i < redisKeys.length; i++) if (this.memoryCache.has(redisKeys[i])) result[i] = this.memoryCache.get(redisKeys[i]);
114
+ else {
115
+ missIndexes.push(i);
116
+ missRedisKeys.push(redisKeys[i]);
117
+ }
118
+ if (missRedisKeys.length) (await x.redis.mget(...missRedisKeys)).forEach((value, idx) => {
119
+ if (value != null) try {
120
+ const parsed = this.deserialize(value);
121
+ this.memoryCache.set(missRedisKeys[idx], parsed);
122
+ result[missIndexes[idx]] = parsed;
123
+ } catch {}
124
+ });
125
+ return result;
126
+ }
127
+ return (await x.redis.mget(...redisKeys)).map((value) => {
128
+ if (value == null) return null;
129
+ try {
130
+ return this.deserialize(value);
131
+ } catch {
132
+ return null;
133
+ }
134
+ });
135
+ }
136
+ /**
137
+ * 获取距离过期时间的毫秒数(未设置过期时间返回-1,键不存在返回-2)。
138
+ * memory=only 模式下内存缓存无 TTL 概念,始终返回-1。
139
+ *
140
+ * @memory 支持
141
+ * @param key 键
142
+ * @returns 返回距离过期时间的毫秒数
143
+ */
144
+ async ttl(key) {
145
+ if (this.hasMemoryCacheOnly) return -1;
146
+ const redisKey = this.toRedisKey(key);
147
+ return x.redis.pttl(redisKey);
148
+ }
149
+ /**
150
+ * 缓存内容。
151
+ *
152
+ * @memory 支持
153
+ * @param key 键
154
+ * @param action 获取缓存内容的操作
155
+ * @param ttlOrOptions 缓存时间或选项
156
+ * @returns 返回获取到的内容
157
+ */
158
+ async remember(key, action, ttlOrOptions) {
159
+ let value = await this.get(key);
160
+ if (value === null) {
161
+ value = await action();
162
+ await this.set(key, value, ttlOrOptions);
163
+ }
164
+ return value;
165
+ }
166
+ async rememberMany(raws, key, action, ttlOrOptions) {
167
+ const keys = raws.map(key);
168
+ const values = await this.getMany(...keys);
169
+ const shouldUpdateIndexes = [];
170
+ for (let i = 0, len = values.length; i < len; i++) if (values[i] === null) shouldUpdateIndexes.push(i);
171
+ if (shouldUpdateIndexes.length) {
172
+ const nextValues = await action(shouldUpdateIndexes.map((i) => raws[i]));
173
+ await Promise.all(nextValues.map(async (nextValue, index) => {
174
+ values[shouldUpdateIndexes[index]] = nextValue;
175
+ await this.set(keys[shouldUpdateIndexes[index]], nextValue, ttlOrOptions);
176
+ }));
177
+ }
178
+ return values;
179
+ }
180
+ /**
181
+ * 自增。
182
+ *
183
+ * @memory 支持
184
+ * @param key 键
185
+ * @param increment 增量
186
+ */
187
+ async increase(key, increment = 1) {
188
+ const redisKey = this.toRedisKey(key);
189
+ if (this.hasMemoryCacheOnly) {
190
+ const next = (this.memoryCache.get(redisKey) ?? 0) + increment;
191
+ this.memoryCache.set(redisKey, next);
192
+ return next;
193
+ }
194
+ const result = await x.redis.incrby(redisKey, increment);
195
+ if (this.hasMemoryCache) this.memoryCache.delete(redisKey);
196
+ return result;
197
+ }
198
+ /**
199
+ * 自减。
200
+ *
201
+ * @memory 支持
202
+ * @param key 键
203
+ * @param decrement 减量
204
+ */
205
+ async decrease(key, decrement = 1) {
206
+ return this.increase(key, -decrement);
207
+ }
208
+ /**
209
+ * 新增元素。
210
+ *
211
+ * @memory 支持
212
+ * @param key 键
213
+ * @param values 元素列表
214
+ */
215
+ async push(key, ...values) {
216
+ const redisKey = this.toRedisKey(key);
217
+ if (this.hasMemoryCacheOnly) {
218
+ const arr = this.memoryCache.get(redisKey) ?? [];
219
+ arr.push(...values);
220
+ this.memoryCache.set(redisKey, arr);
221
+ return arr.length;
222
+ }
223
+ const result = await x.redis.rpush(redisKey, ...values.map((value) => this.serialize(value)));
224
+ if (this.hasMemoryCache) this.memoryCache.delete(redisKey);
225
+ return result;
226
+ }
227
+ /**
228
+ * 从头部弹出元素并返回。
229
+ *
230
+ * @memory 支持
231
+ * @param key 键
232
+ * @param count 弹出元素个数
233
+ */
234
+ async shift(key, count = 1) {
235
+ const redisKey = this.toRedisKey(key);
236
+ if (this.hasMemoryCacheOnly) {
237
+ const arr = this.memoryCache.get(redisKey) ?? [];
238
+ const res = arr.splice(0, count);
239
+ if (arr.length) this.memoryCache.set(redisKey, arr);
240
+ else this.memoryCache.delete(redisKey);
241
+ return res;
242
+ }
243
+ const res = [];
244
+ for (let i = 0; i < count; i++) {
245
+ const item = await x.redis.lpop(redisKey);
246
+ if (item) res.push(this.deserialize(item));
247
+ else break;
248
+ }
249
+ if (this.hasMemoryCache && res.length) this.memoryCache.delete(redisKey);
250
+ return res;
251
+ }
252
+ /**
253
+ * 删除缓存。
254
+ *
255
+ * @memory 支持
256
+ * @param keys 键列表
257
+ */
258
+ async remove(...keys) {
259
+ if (!keys.length) return 0;
260
+ const redisKeys = keys.map((key) => this.toRedisKey(key));
261
+ let count = 0;
262
+ if (!this.hasMemoryCacheOnly) count = await x.redis.del(...redisKeys);
263
+ if (this.hasMemoryCache) {
264
+ let deletedCount = 0;
265
+ redisKeys.forEach((redisKey) => {
266
+ if (this.memoryCache.delete(redisKey)) deletedCount++;
267
+ });
268
+ if (this.hasMemoryCacheOnly) count = deletedCount;
269
+ }
270
+ return count;
271
+ }
272
+ /**
273
+ * 清空全部缓存。
274
+ *
275
+ * @memory 支持
276
+ */
277
+ async clearAll() {
278
+ let count = 0;
279
+ if (!this.hasMemoryCacheOnly) {
280
+ const keys = await x.redis.keys(`${this.prefix}*`);
281
+ count = keys.length ? await x.redis.del(...keys) : 0;
282
+ }
283
+ if (this.hasMemoryCache) {
284
+ const memoryCacheSize = this.memoryCache.size;
285
+ this.memoryCache.clear();
286
+ if (this.hasMemoryCacheOnly) count = memoryCacheSize;
287
+ }
288
+ return count;
289
+ }
290
+ /**
291
+ * 清空指定前缀的缓存。
292
+ *
293
+ * @memory 支持
294
+ */
295
+ async clear(...prefixes) {
296
+ if (!prefixes.length) return 0;
297
+ let count = 0;
298
+ if (!this.hasMemoryCacheOnly) {
299
+ const keys = (await Promise.all(prefixes.map((prefix) => x.redis.keys(`${this.toRedisKey(prefix)}*`)))).flat();
300
+ count = keys.length ? await x.redis.del(...keys) : 0;
301
+ }
302
+ if (this.options.memory) {
303
+ let deletedCount = 0;
304
+ this.memoryCache.forEach((_v, k) => {
305
+ if (prefixes.some((prefix) => k.startsWith(this.toRedisKey(prefix)))) {
306
+ if (this.memoryCache.delete(k)) deletedCount++;
307
+ }
308
+ });
309
+ if (this.hasMemoryCacheOnly) count = deletedCount;
310
+ }
311
+ return count;
312
+ }
313
+ /**
314
+ * 派生出一个指定类型的缓存服务。
315
+ */
316
+ fork(options) {
317
+ return options ? new CacheService({
318
+ ...this.options,
319
+ ...options
320
+ }) : this;
321
+ }
322
+ };
323
+ export { CacheService };
@@ -0,0 +1,65 @@
1
+ import { BaseService } from "./base.mjs";
2
+ import { MsValue } from "vtils";
3
+ export type CaptchaServiceGenerateCharset = '09' | '19' | 'az' | 'AZ' | 'aZ' | '0z' | '0Z' | '1z' | '1Z';
4
+ export interface CaptchaServiceGeneratePayload<T> {
5
+ /**
6
+ * 场景值
7
+ *
8
+ * 比如:防止后台验证码图片登录用其他场景下的短信验证码
9
+ */
10
+ scene: string;
11
+ /**
12
+ * 验证码长度
13
+ */
14
+ size: number;
15
+ /**
16
+ * 验证码存活时长
17
+ */
18
+ ttl: MsValue;
19
+ /**
20
+ * 字符集
21
+ */
22
+ charset: CaptchaServiceGenerateCharset;
23
+ /**
24
+ * 可重试次数
25
+ *
26
+ * @default 0
27
+ */
28
+ retryCount?: number;
29
+ /**
30
+ * 其他信息
31
+ */
32
+ extra?: T;
33
+ }
34
+ export interface CaptchaServiceGenerateResult {
35
+ token: string;
36
+ code: string;
37
+ }
38
+ export interface CaptchaServiceGenerateImageResult {
39
+ token: string;
40
+ code: string;
41
+ svg: string;
42
+ }
43
+ export interface CaptchaServiceGenerateDataUrlResult {
44
+ token: string;
45
+ code: string;
46
+ dataUrl: string;
47
+ }
48
+ export interface CaptchaServiceVerifyOptions<T> {
49
+ token: string;
50
+ code: string;
51
+ scene: string;
52
+ extra?: (extra: T) => boolean;
53
+ }
54
+ export declare class CaptchaService implements BaseService {
55
+ serviceName: string;
56
+ private charsetMap;
57
+ generate<T extends Record<string, any>>(payload: CaptchaServiceGeneratePayload<T>): Promise<CaptchaServiceGenerateResult>;
58
+ generateDataUrl<T extends Record<string, any>>(payload: CaptchaServiceGeneratePayload<T>): Promise<CaptchaServiceGenerateDataUrlResult>;
59
+ verify<T extends Record<string, any>>(options: CaptchaServiceVerifyOptions<T>): Promise<boolean>;
60
+ }
61
+ declare module '../x.mjs' {
62
+ interface X {
63
+ captcha: CaptchaService;
64
+ }
65
+ }
@@ -0,0 +1,61 @@
1
+ import { x } from "../x.mjs";
2
+ import { sample } from "vtils";
3
+ import svgToDataUrl from "mini-svg-data-uri";
4
+ import svgCaptcha from "svg-captcha";
5
+ // src/services/captcha.ts
6
+ var CaptchaService = class {
7
+ serviceName = "captcha";
8
+ charsetMap = {
9
+ "09": "0123456789".split(""),
10
+ "19": "123456789".split(""),
11
+ az: "abcdefghijklmnopqrstuvwxyz".split(""),
12
+ AZ: "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),
13
+ aZ: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),
14
+ "0z": "0123456789abcdefghijklmnopqrstuvwxyz".split(""),
15
+ "0Z": "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),
16
+ "1z": "123456789abcdefghijklmnopqrstuvwxyz".split(""),
17
+ "1Z": "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
18
+ };
19
+ async generate(payload) {
20
+ const chars = this.charsetMap[payload.charset];
21
+ let code = "";
22
+ for (let i = 0; i < payload.size; i++) code += sample(chars);
23
+ return {
24
+ token: await x.cache.save({
25
+ code,
26
+ scene: payload.scene,
27
+ retryCount: payload.retryCount ?? 0,
28
+ extra: payload.extra
29
+ }, payload.ttl),
30
+ code
31
+ };
32
+ }
33
+ async generateDataUrl(payload) {
34
+ const { text: code, data: svg } = svgCaptcha.create({
35
+ size: payload.size,
36
+ charPreset: this.charsetMap[payload.charset].join("")
37
+ });
38
+ return {
39
+ token: await x.cache.save({
40
+ code,
41
+ scene: payload.scene,
42
+ retryCount: payload.retryCount || 0,
43
+ extra: payload.extra
44
+ }, payload.ttl),
45
+ code,
46
+ dataUrl: svgToDataUrl(svg)
47
+ };
48
+ }
49
+ async verify(options) {
50
+ const expected = await x.cache.get(options.token);
51
+ if (expected == null) return false;
52
+ if (expected.retryCount === 0) await x.cache.remove(options.token);
53
+ else {
54
+ expected.retryCount--;
55
+ const ttl = await x.cache.ttl(options.token);
56
+ await x.cache.set(options.token, expected, ttl);
57
+ }
58
+ return expected.scene === options.scene && options.code.toLowerCase() === expected.code.toLowerCase() && (options.extra ? options.extra(expected.extra) : true);
59
+ }
60
+ };
61
+ export { CaptchaService };
@@ -1,28 +1,20 @@
1
- import crypto from 'node:crypto';
2
- export class CryptoService {
3
- constructor() {
4
- this.serviceName = 'crypto';
5
- }
1
+ import { BaseService } from "./base.mjs";
2
+ export declare class CryptoService implements BaseService {
3
+ serviceName: string;
6
4
  /**
7
5
  * 将给定的文本转换为 Base64 编码的字符串
8
6
  *
9
7
  * @param text 需要编码的原始文本
10
8
  * @returns 返回 Base64 编码后的字符串
11
9
  */
12
- base64Encode(text) {
13
- return Buffer.from(text).toString('base64');
14
- }
15
-
10
+ base64Encode(text: string): string;
16
11
  /**
17
12
  * 将 Base64 编码的字符串转换为 UTF-8 编码的字符串
18
13
  *
19
14
  * @param text Base64 编码的字符串
20
15
  * @returns 转换后的 UTF-8 编码的字符串
21
16
  */
22
- base64Decode(text) {
23
- return Buffer.from(text, 'base64').toString('utf8');
24
- }
25
-
17
+ base64Decode(text: string): string;
26
18
  /**
27
19
  * 将字符串文本编码为Base64 URL格式
28
20
  *
@@ -33,23 +25,7 @@ export class CryptoService {
33
25
  * @param text 需要被编码的字符串文本
34
26
  * @returns 编码后的Base64 URL安全字符串
35
27
  */
36
- base64UrlEncode(text) {
37
- // 将输入文本转换为Buffer对象,并进一步将其转换为Base64编码的字符串
38
- let base64 = Buffer.from(text).toString('base64');
39
-
40
- // 将Base64编码中的'+'替换为'-',以适应URL安全要求
41
- base64 = base64.replace(/\+/g, '-');
42
-
43
- // 将Base64编码中的'/'替换为'_',以适应URL安全要求
44
- base64 = base64.replace(/\//g, '_');
45
-
46
- // 移除Base64编码中用于填充的'='字符,以适应URL安全要求
47
- base64 = base64.replace(/=/g, '');
48
-
49
- // 返回经过URL安全处理的Base64编码字符串
50
- return base64;
51
- }
52
-
28
+ base64UrlEncode(text: string): string;
53
29
  /**
54
30
  * 解码base64url格式的字符串
55
31
  * base64url是一种用于URL的base64编码变体,它将标准base64中的'+'和'/'字符替换为'-'和'_',以避免URL编码
@@ -58,22 +34,14 @@ export class CryptoService {
58
34
  * @param text 需要解码的base64url格式的字符串
59
35
  * @returns 解码后的原始字符串
60
36
  */
61
- base64UrlDecode(text) {
62
- // 将base64url编码中的'-'和'_'替换回标准base64编码中的'+'和'/'
63
- // 然后使用Node.js的Buffer对象从base64编码转换为utf8格式的字符串
64
- return Buffer.from(text.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');
65
- }
66
-
37
+ base64UrlDecode(text: string): string;
67
38
  /**
68
39
  * 使用MD5算法对文本进行哈希处理
69
40
  *
70
41
  * @param text 需要进行哈希处理的文本
71
42
  * @returns 返回经过MD5哈希处理后的字符串
72
43
  */
73
- md5(text) {
74
- return crypto.createHash('md5').update(text).digest('hex');
75
- }
76
-
44
+ md5(text: string): string;
77
45
  /**
78
46
  * 使用SHA-1算法对文本进行哈希处理
79
47
  *
@@ -84,56 +52,35 @@ export class CryptoService {
84
52
  * @param text 待哈希处理的文本字符串
85
53
  * @returns 返回文本的SHA-1散列值,以十六进制字符串形式表示
86
54
  */
87
- sha1(text) {
88
- return crypto.createHash('sha1').update(text).digest('hex');
89
- }
90
-
55
+ sha1(text: string): string;
91
56
  /**
92
57
  * 使用SHA-256算法对文本进行哈希处理
93
58
  *
94
59
  * @param text 输入的文本字符串
95
60
  * @returns 返回经过SHA-256哈希处理后的十六进制字符串
96
61
  */
97
- sha256(text) {
98
- return crypto.createHash('sha256').update(text).digest('hex');
99
- }
100
-
62
+ sha256(text: string): string;
101
63
  /**
102
64
  * 使用SHA-512算法对文本进行哈希处理
103
65
  *
104
66
  * @param text 输入的文本字符串
105
67
  * @returns 返回经过SHA-512哈希处理后的字符串
106
68
  */
107
- sha512(text) {
108
- return crypto.createHash('sha512').update(text).digest('hex');
109
- }
110
-
69
+ sha512(text: string): string;
111
70
  /**
112
71
  * 使用给定的密钥对给定的字符串执行 AES 加密(加密模式为 ECB,填充方式为 PKCS7)。
113
72
  *
114
73
  * @param text - 要加密的字符串。
115
74
  * @param key - 用于加密的密钥(仅支持16字节的密钥)。
116
75
  */
117
- aesEncrypt(text, key) {
118
- const cipher = crypto.createCipheriv('aes-128-ecb', key.substring(0, 16), null);
119
- let encrypted = cipher.update(text, 'utf8', 'base64');
120
- encrypted += cipher.final('base64');
121
- return encrypted;
122
- }
123
-
76
+ aesEncrypt(text: string, key: string): string;
124
77
  /**
125
78
  * 使用给定的密钥对给定的字符串执行 AES 解密(解密模式为 ECB,填充方式为 PKCS7)。
126
79
  *
127
80
  * @param text - 要解密的字符串。
128
81
  * @param key - 用于解密的密钥(仅支持16字节的密钥)。
129
82
  */
130
- aesDecrypt(text, key) {
131
- const decipher = crypto.createDecipheriv('aes-128-ecb', key.substring(0, 16), null);
132
- let decrypted = decipher.update(text, 'base64', 'utf8');
133
- decrypted += decipher.final('utf8');
134
- return decrypted;
135
- }
136
-
83
+ aesDecrypt(text: string, key: string): string;
137
84
  /**
138
85
  * 使用AES加密算法对JSON数据进行加密
139
86
  *
@@ -146,13 +93,7 @@ export class CryptoService {
146
93
  * @returns 返回加密后的字符串数据
147
94
  * 加密后的数据可以安全地进行网络传输或存储
148
95
  */
149
- aesEncryptJson(payload, key) {
150
- // 将payload对象序列化为JSON字符串,以便进行加密处理
151
- // 使用指定的密钥对序列化后的JSON字符串进行AES加密
152
- // 返回加密后的数据,确保数据在传输或存储过程中的安全性
153
- return this.aesEncrypt(JSON.stringify(payload), key);
154
- }
155
-
96
+ aesEncryptJson(payload: any, key: string): string;
156
97
  /**
157
98
  * 使用AES算法解密给定的文本,并将解密后的结果解析为JSON对象
158
99
  *
@@ -160,10 +101,10 @@ export class CryptoService {
160
101
  * @param key 解密用的密钥,必须与加密时使用的密钥相同
161
102
  * @returns 返回解密后的JSON对象,类型为泛型T,根据调用时指定的类型解析
162
103
  */
163
- aesDecryptJson(text, key) {
164
- // 使用指定的密钥对给定的加密数据进行AES解密
165
- // 将解密后的数据反序列化为JSON对象,以便后续的处理
166
- // 返回解密后的数据,确保数据在传输或存储过程中的安全性
167
- return JSON.parse(this.aesDecrypt(text, key));
104
+ aesDecryptJson<T>(text: string, key: string): T;
105
+ }
106
+ declare module '../x.mjs' {
107
+ interface X {
108
+ crypto: CryptoService;
168
109
  }
169
110
  }