@jayfong/x-server 2.119.0 → 3.0.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 (290) hide show
  1. package/lib/_virtual/_rolldown/runtime.mjs +4 -0
  2. package/lib/cli/api_generator.d.mts +74 -0
  3. package/lib/cli/api_generator.mjs +310 -0
  4. package/lib/cli/build_util.d.mts +17 -0
  5. package/lib/cli/build_util.mjs +156 -0
  6. package/lib/cli/cli.d.mts +1 -0
  7. package/lib/cli/cli.mjs +355 -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 +7 -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/esbuild_register.d.mts +1 -0
  17. package/lib/cli/esbuild_register.mjs +7 -0
  18. package/lib/cli/template_util.d.mts +18 -0
  19. package/lib/cli/template_util.mjs +85 -0
  20. package/lib/cli/templates/crons.ts +1 -1
  21. package/lib/cli/templates/handlers.ts +1 -1
  22. package/lib/cli/templates/hooks.ts +1 -1
  23. package/lib/cli/templates/models.ts +7 -7
  24. package/lib/cli/templates/package.json +11 -1
  25. package/lib/cli/templates/routes.ts +2 -1
  26. package/lib/core/ctx_storage.d.mts +3 -0
  27. package/lib/core/ctx_storage.mjs +4 -0
  28. package/lib/core/define_bus.d.mts +37 -0
  29. package/lib/core/define_bus.mjs +12 -0
  30. package/lib/core/{define_cron.d.ts → define_cron.d.mts} +2 -2
  31. package/lib/core/define_cron.mjs +11 -0
  32. package/lib/core/{define_handler.d.ts → define_handler.d.mts} +19 -19
  33. package/lib/core/define_handler.mjs +44 -0
  34. package/lib/core/define_hook.d.mts +2 -0
  35. package/lib/core/define_hook.mjs +6 -0
  36. package/lib/core/define_server.d.mts +3 -0
  37. package/lib/core/define_server.mjs +8 -0
  38. package/lib/core/{define_task.d.ts → define_task.d.mts} +2 -2
  39. package/lib/core/define_task.mjs +102 -0
  40. package/lib/core/get_handler_url.d.mts +2 -0
  41. package/lib/core/get_handler_url.mjs +7 -0
  42. package/lib/core/handler.d.mts +16 -0
  43. package/lib/core/handler.mjs +132 -0
  44. package/lib/core/http_error.d.mts +2 -0
  45. package/lib/core/http_error.mjs +1 -0
  46. package/lib/core/http_header.d.mts +856 -0
  47. package/lib/core/http_header.mjs +860 -0
  48. package/lib/core/http_method.d.mts +3 -0
  49. package/lib/core/http_method.mjs +10 -0
  50. package/lib/core/http_redirect.d.mts +5 -0
  51. package/lib/core/http_redirect.mjs +10 -0
  52. package/lib/core/server.d.mts +20 -0
  53. package/lib/core/server.mjs +186 -0
  54. package/lib/core/types.d.mts +256 -0
  55. package/lib/exports.d.mts +46 -0
  56. package/lib/exports.mjs +46 -0
  57. package/lib/index.d.mts +48 -0
  58. package/lib/index.mjs +45 -0
  59. package/lib/plugins/base.d.mts +4 -0
  60. package/lib/plugins/compress.d.mts +12 -0
  61. package/lib/plugins/compress.mjs +15 -0
  62. package/lib/plugins/cookie.d.mts +12 -0
  63. package/lib/plugins/cookie.mjs +15 -0
  64. package/lib/plugins/cors.d.mts +22 -0
  65. package/lib/plugins/cors.mjs +34 -0
  66. package/lib/plugins/file_parser.d.mts +15 -0
  67. package/lib/plugins/file_parser.mjs +24 -0
  68. package/lib/plugins/form_body_parser.d.mts +12 -0
  69. package/lib/plugins/form_body_parser.mjs +15 -0
  70. package/lib/plugins/ws_parser.d.mts +12 -0
  71. package/lib/plugins/ws_parser.mjs +15 -0
  72. package/lib/plugins/xml_parser.d.mts +19 -0
  73. package/lib/plugins/xml_parser.mjs +40 -0
  74. package/lib/services/ai.d.mts +31 -0
  75. package/lib/services/ai.mjs +44 -0
  76. package/lib/services/base.d.mts +4 -0
  77. package/lib/services/base.mjs +1 -0
  78. package/lib/services/cache.d.mts +165 -0
  79. package/lib/services/cache.mjs +323 -0
  80. package/lib/services/captcha.d.mts +65 -0
  81. package/lib/services/captcha.mjs +61 -0
  82. package/lib/services/{crypto.js → crypto.d.mts} +19 -78
  83. package/lib/services/crypto.mjs +141 -0
  84. package/lib/services/db_value.d.mts +60 -0
  85. package/lib/services/db_value.mjs +64 -0
  86. package/lib/services/dingtalk.d.mts +39 -0
  87. package/lib/services/dingtalk.mjs +44 -0
  88. package/lib/services/dispose.d.mts +17 -0
  89. package/lib/services/dispose.mjs +18 -0
  90. package/lib/services/emoji.d.mts +10 -0
  91. package/lib/services/emoji.mjs +2025 -0
  92. package/lib/services/file_store.d.mts +49 -0
  93. package/lib/services/file_store.mjs +58 -0
  94. package/lib/services/html.d.mts +11 -0
  95. package/lib/services/html.mjs +12 -0
  96. package/lib/services/jwt.d.mts +33 -0
  97. package/lib/services/jwt.mjs +42 -0
  98. package/lib/services/log.d.mts +37 -0
  99. package/lib/services/log.mjs +99 -0
  100. package/lib/services/mail.d.mts +22 -0
  101. package/lib/services/mail.mjs +28 -0
  102. package/lib/services/pay.d.mts +123 -0
  103. package/lib/services/pay.mjs +157 -0
  104. package/lib/services/random.d.mts +27 -0
  105. package/lib/services/random.mjs +42 -0
  106. package/lib/services/rate_limit.d.mts +37 -0
  107. package/lib/services/rate_limit.mjs +40 -0
  108. package/lib/services/redis.d.mts +11 -0
  109. package/lib/services/redis.mjs +6 -0
  110. package/lib/services/sensitive_words.d.mts +29 -0
  111. package/lib/services/sensitive_words.mjs +37 -0
  112. package/lib/services/sms.d.mts +40 -0
  113. package/lib/services/sms.mjs +30238 -0
  114. package/lib/types/dto.d.mts +30 -0
  115. package/lib/types/dto.mjs +1 -0
  116. package/lib/x.d.mts +11 -0
  117. package/lib/x.mjs +21 -0
  118. package/lib/x_init.d.mts +1 -0
  119. package/lib/x_init.mjs +10 -0
  120. package/package.json +71 -16
  121. package/lib/_cjs/cli/api_generator.js +0 -458
  122. package/lib/_cjs/cli/build_util.js +0 -243
  123. package/lib/_cjs/cli/cli.js +0 -378
  124. package/lib/_cjs/cli/css_register.js +0 -7
  125. package/lib/_cjs/cli/deploy_util.js +0 -76
  126. package/lib/_cjs/cli/dev_util.js +0 -26
  127. package/lib/_cjs/cli/env_util.js +0 -252
  128. package/lib/_cjs/cli/esbuild_register.js +0 -7
  129. package/lib/_cjs/cli/template_util.js +0 -101
  130. package/lib/_cjs/cli/templates/crons.ts +0 -2
  131. package/lib/_cjs/cli/templates/handlers.ts +0 -3
  132. package/lib/_cjs/cli/templates/hooks.ts +0 -2
  133. package/lib/_cjs/cli/templates/models.ts +0 -123
  134. package/lib/_cjs/cli/templates/package.json +0 -3
  135. package/lib/_cjs/cli/templates/routes.ts +0 -68
  136. package/lib/_cjs/core/ctx_storage.js +0 -6
  137. package/lib/_cjs/core/define_bus.js +0 -31
  138. package/lib/_cjs/core/define_cron.js +0 -13
  139. package/lib/_cjs/core/define_handler.js +0 -56
  140. package/lib/_cjs/core/define_hook.js +0 -8
  141. package/lib/_cjs/core/define_server.js +0 -10
  142. package/lib/_cjs/core/define_task.js +0 -113
  143. package/lib/_cjs/core/get_handler_url.js +0 -11
  144. package/lib/_cjs/core/handler.js +0 -216
  145. package/lib/_cjs/core/http_error.js +0 -6
  146. package/lib/_cjs/core/http_header.js +0 -142
  147. package/lib/_cjs/core/http_method.js +0 -12
  148. package/lib/_cjs/core/http_redirect.js +0 -11
  149. package/lib/_cjs/core/server.js +0 -219
  150. package/lib/_cjs/core/types.js +0 -8
  151. package/lib/_cjs/exports.js +0 -273
  152. package/lib/_cjs/index.js +0 -15
  153. package/lib/_cjs/plugins/base.js +0 -3
  154. package/lib/_cjs/plugins/compress.js +0 -18
  155. package/lib/_cjs/plugins/cookie.js +0 -18
  156. package/lib/_cjs/plugins/cors.js +0 -38
  157. package/lib/_cjs/plugins/file_parser.js +0 -28
  158. package/lib/_cjs/plugins/form_body_parser.js +0 -18
  159. package/lib/_cjs/plugins/ws_parser.js +0 -18
  160. package/lib/_cjs/plugins/xml_parser.js +0 -48
  161. package/lib/_cjs/services/ai.js +0 -48
  162. package/lib/_cjs/services/base.js +0 -3
  163. package/lib/_cjs/services/cache.js +0 -400
  164. package/lib/_cjs/services/captcha.js +0 -78
  165. package/lib/_cjs/services/crypto.js +0 -175
  166. package/lib/_cjs/services/db_value.js +0 -77
  167. package/lib/_cjs/services/dingtalk.js +0 -51
  168. package/lib/_cjs/services/dispose.js +0 -23
  169. package/lib/_cjs/services/emoji.js +0 -2034
  170. package/lib/_cjs/services/file_store.js +0 -67
  171. package/lib/_cjs/services/html.js +0 -17
  172. package/lib/_cjs/services/jwt.js +0 -65
  173. package/lib/_cjs/services/log.js +0 -108
  174. package/lib/_cjs/services/mail.js +0 -31
  175. package/lib/_cjs/services/pay.js +0 -191
  176. package/lib/_cjs/services/random.js +0 -51
  177. package/lib/_cjs/services/rate_limit.js +0 -54
  178. package/lib/_cjs/services/redis.js +0 -12
  179. package/lib/_cjs/services/sensitive_words.js +0 -61
  180. package/lib/_cjs/services/sms.js +0 -84
  181. package/lib/_cjs/types/dto.js +0 -3
  182. package/lib/_cjs/x.js +0 -35
  183. package/lib/cli/api_generator.d.ts +0 -74
  184. package/lib/cli/api_generator.js +0 -452
  185. package/lib/cli/build_util.d.ts +0 -17
  186. package/lib/cli/build_util.js +0 -236
  187. package/lib/cli/cli.d.ts +0 -2
  188. package/lib/cli/cli.js +0 -374
  189. package/lib/cli/css_register.js +0 -5
  190. package/lib/cli/deploy_util.d.ts +0 -23
  191. package/lib/cli/deploy_util.js +0 -70
  192. package/lib/cli/dev_util.d.ts +0 -8
  193. package/lib/cli/dev_util.js +0 -20
  194. package/lib/cli/env_util.d.ts +0 -45
  195. package/lib/cli/env_util.js +0 -246
  196. package/lib/cli/esbuild_register.js +0 -5
  197. package/lib/cli/template_util.d.ts +0 -18
  198. package/lib/cli/template_util.js +0 -95
  199. package/lib/core/ctx_storage.d.ts +0 -3
  200. package/lib/core/ctx_storage.js +0 -2
  201. package/lib/core/define_bus.d.ts +0 -37
  202. package/lib/core/define_bus.js +0 -27
  203. package/lib/core/define_cron.js +0 -9
  204. package/lib/core/define_handler.js +0 -48
  205. package/lib/core/define_hook.d.ts +0 -2
  206. package/lib/core/define_hook.js +0 -4
  207. package/lib/core/define_server.d.ts +0 -3
  208. package/lib/core/define_server.js +0 -6
  209. package/lib/core/define_task.js +0 -107
  210. package/lib/core/get_handler_url.d.ts +0 -2
  211. package/lib/core/get_handler_url.js +0 -7
  212. package/lib/core/handler.d.ts +0 -16
  213. package/lib/core/handler.js +0 -209
  214. package/lib/core/http_error.d.ts +0 -2
  215. package/lib/core/http_error.js +0 -2
  216. package/lib/core/http_header.d.ts +0 -856
  217. package/lib/core/http_header.js +0 -139
  218. package/lib/core/http_method.d.ts +0 -3
  219. package/lib/core/http_method.js +0 -8
  220. package/lib/core/http_redirect.d.ts +0 -5
  221. package/lib/core/http_redirect.js +0 -6
  222. package/lib/core/server.d.ts +0 -20
  223. package/lib/core/server.js +0 -213
  224. package/lib/core/types.d.ts +0 -265
  225. package/lib/core/types.js +0 -4
  226. package/lib/exports.d.ts +0 -45
  227. package/lib/exports.js +0 -47
  228. package/lib/index.d.ts +0 -2
  229. package/lib/index.js +0 -3
  230. package/lib/plugins/base.d.ts +0 -4
  231. package/lib/plugins/base.js +0 -1
  232. package/lib/plugins/compress.d.ts +0 -13
  233. package/lib/plugins/compress.js +0 -12
  234. package/lib/plugins/cookie.d.ts +0 -13
  235. package/lib/plugins/cookie.js +0 -12
  236. package/lib/plugins/cors.d.ts +0 -22
  237. package/lib/plugins/cors.js +0 -32
  238. package/lib/plugins/file_parser.d.ts +0 -16
  239. package/lib/plugins/file_parser.js +0 -22
  240. package/lib/plugins/form_body_parser.d.ts +0 -13
  241. package/lib/plugins/form_body_parser.js +0 -12
  242. package/lib/plugins/ws_parser.d.ts +0 -13
  243. package/lib/plugins/ws_parser.js +0 -12
  244. package/lib/plugins/xml_parser.d.ts +0 -19
  245. package/lib/plugins/xml_parser.js +0 -43
  246. package/lib/services/ai.d.ts +0 -31
  247. package/lib/services/ai.js +0 -43
  248. package/lib/services/base.d.ts +0 -4
  249. package/lib/services/base.js +0 -1
  250. package/lib/services/cache.d.ts +0 -173
  251. package/lib/services/cache.js +0 -394
  252. package/lib/services/captcha.d.ts +0 -65
  253. package/lib/services/captcha.js +0 -72
  254. package/lib/services/crypto.d.ts +0 -110
  255. package/lib/services/db_value.d.ts +0 -60
  256. package/lib/services/db_value.js +0 -72
  257. package/lib/services/dingtalk.d.ts +0 -39
  258. package/lib/services/dingtalk.js +0 -45
  259. package/lib/services/dispose.d.ts +0 -17
  260. package/lib/services/dispose.js +0 -17
  261. package/lib/services/emoji.d.ts +0 -10
  262. package/lib/services/emoji.js +0 -2029
  263. package/lib/services/file_store.d.ts +0 -49
  264. package/lib/services/file_store.js +0 -61
  265. package/lib/services/html.d.ts +0 -11
  266. package/lib/services/html.js +0 -12
  267. package/lib/services/jwt.d.ts +0 -34
  268. package/lib/services/jwt.js +0 -59
  269. package/lib/services/log.d.ts +0 -37
  270. package/lib/services/log.js +0 -102
  271. package/lib/services/mail.d.ts +0 -23
  272. package/lib/services/mail.js +0 -25
  273. package/lib/services/pay.d.ts +0 -123
  274. package/lib/services/pay.js +0 -185
  275. package/lib/services/random.d.ts +0 -27
  276. package/lib/services/random.js +0 -45
  277. package/lib/services/rate_limit.d.ts +0 -37
  278. package/lib/services/rate_limit.js +0 -49
  279. package/lib/services/redis.d.ts +0 -12
  280. package/lib/services/redis.js +0 -7
  281. package/lib/services/sensitive_words.d.ts +0 -29
  282. package/lib/services/sensitive_words.js +0 -56
  283. package/lib/services/sms.d.ts +0 -40
  284. package/lib/services/sms.js +0 -78
  285. package/lib/types/dto.d.ts +0 -86
  286. package/lib/types/dto.js +0 -1
  287. package/lib/x.d.ts +0 -17
  288. package/lib/x.js +0 -30
  289. /package/lib/{cli/css_register.d.ts → core/types.mjs} +0 -0
  290. /package/lib/{cli/esbuild_register.d.ts → plugins/base.mjs} +0 -0
@@ -0,0 +1,49 @@
1
+ import { BaseService } from "./base.mjs";
2
+ export type FileStoreServiceOptions = {
3
+ accessKey: string;
4
+ secretKey: string;
5
+ /** 如: cos.ap-guangzhou.myqcloud.com */
6
+ endpoint: string;
7
+ /** 如: image-311111 */
8
+ bucket: string;
9
+ /** 如: x */
10
+ dir: string;
11
+ /** 如: cdn.com */
12
+ cdnUrl: string;
13
+ };
14
+ export type FileStoreServiceGetUploadUrlPayload = {
15
+ fileName: string;
16
+ ttl: number;
17
+ keepName?: boolean;
18
+ };
19
+ export type FileStoreServiceGetUploadUrlResult = {
20
+ /** 文件类型 */
21
+ contentType: string;
22
+ /** 文件上传地址 */
23
+ uploadUrl: string;
24
+ /** 文件公开访问地址 */
25
+ publicUrl: string;
26
+ };
27
+ export type FileStoreServiceUploadPayload = {
28
+ /** 文件名 */
29
+ fileName: string;
30
+ /** 文件内容 */
31
+ content: Buffer;
32
+ keepName?: boolean;
33
+ };
34
+ export type FileStoreServiceUploadResult = FileStoreServiceGetUploadUrlResult;
35
+ export declare class FileStoreService implements BaseService {
36
+ private options;
37
+ serviceName: string;
38
+ private endpoint;
39
+ private dir;
40
+ private cdnUrl;
41
+ constructor(options: FileStoreServiceOptions);
42
+ getUploadUrl(payload: FileStoreServiceGetUploadUrlPayload): Promise<FileStoreServiceGetUploadUrlResult>;
43
+ upload(payload: FileStoreServiceUploadPayload): Promise<FileStoreServiceUploadResult>;
44
+ }
45
+ declare module '../x.mjs' {
46
+ interface X {
47
+ fileStore: FileStoreService;
48
+ }
49
+ }
@@ -0,0 +1,58 @@
1
+ import { x } from "../x.mjs";
2
+ import { isUrl, ms } from "vtils";
3
+ import { xr } from "@jayfong/x-request";
4
+ import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
5
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
6
+ import mime from "mime";
7
+ // src/services/file_store.ts
8
+ var FileStoreService = class {
9
+ options;
10
+ serviceName = "fileStore";
11
+ endpoint = "";
12
+ dir = "";
13
+ cdnUrl = "";
14
+ constructor(options) {
15
+ this.options = options;
16
+ this.endpoint = isUrl(this.options.endpoint) ? this.options.endpoint : `https://${this.options.endpoint}`;
17
+ this.dir = this.options.dir ? `${this.options.dir.replace(/^\/+/, "").replace(/\/+$/, "")}` : "";
18
+ this.cdnUrl = (isUrl(this.options.cdnUrl) ? this.options.cdnUrl : `https://${this.options.cdnUrl}`).replace(/\/+$/, "");
19
+ }
20
+ async getUploadUrl(payload) {
21
+ const s3Client = new S3Client({
22
+ credentials: {
23
+ accessKeyId: this.options.accessKey,
24
+ secretAccessKey: this.options.secretKey
25
+ },
26
+ endpoint: this.endpoint,
27
+ region: "x"
28
+ });
29
+ const contentType = mime.getType(payload.fileName) || "application/octet-stream";
30
+ const fileName = payload.keepName ? payload.fileName : `${x.random.cuid2()}.${mime.getExtension(contentType)}`;
31
+ const dir = this.dir ? `${this.dir}/` : "";
32
+ const command = new PutObjectCommand({
33
+ Bucket: this.options.bucket,
34
+ Key: `${dir}${fileName}`,
35
+ ContentType: contentType
36
+ });
37
+ return {
38
+ contentType,
39
+ uploadUrl: await getSignedUrl(s3Client, command, { expiresIn: ms(payload.ttl, true) }),
40
+ publicUrl: `${this.cdnUrl}/${dir}${fileName}`
41
+ };
42
+ }
43
+ async upload(payload) {
44
+ const res = await this.getUploadUrl({
45
+ fileName: payload.fileName,
46
+ ttl: ms("1m"),
47
+ keepName: payload.keepName
48
+ });
49
+ await xr.post({
50
+ url: res.uploadUrl,
51
+ method: "PUT",
52
+ headers: { "Content-Type": res.contentType },
53
+ data: payload.content
54
+ });
55
+ return res;
56
+ }
57
+ };
58
+ export { FileStoreService };
@@ -0,0 +1,11 @@
1
+ import { BaseService } from "./base.mjs";
2
+ export declare class HtmlService implements BaseService {
3
+ serviceName: string;
4
+ escape(html: string): string;
5
+ unescape(html: string): string;
6
+ }
7
+ declare module '../x.mjs' {
8
+ interface X {
9
+ html: HtmlService;
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ import { escapeHTML, unescapeHTML } from "fast-escape-html";
2
+ // src/services/html.ts
3
+ var HtmlService = class {
4
+ serviceName = "html";
5
+ escape(html) {
6
+ return escapeHTML(html);
7
+ }
8
+ unescape(html) {
9
+ return unescapeHTML(html);
10
+ }
11
+ };
12
+ export { HtmlService };
@@ -0,0 +1,33 @@
1
+ import { BaseService } from "./base.mjs";
2
+ import { MsValue } from "vtils";
3
+ import jwt from "jsonwebtoken";
4
+ import { LRUCache } from "lru-cache";
5
+ import { RequiredBy } from "vtils/types";
6
+ import { IncomingHttpHeaders } from "node:http";
7
+ export interface JwtServiceJwtPayload extends Record<string, any> {}
8
+ export interface JwtServiceOptions {
9
+ secret: string;
10
+ ttl: MsValue;
11
+ cache?: LRUCache.Options<string, JwtServiceJwtPayload, any>;
12
+ onVerify?: (payload: JwtServiceJwtPayload & RequiredBy<jwt.JwtPayload, 'iat' | 'exp'> & {
13
+ token: string;
14
+ }) => any;
15
+ }
16
+ export declare class JwtService implements BaseService {
17
+ private options;
18
+ serviceName: string;
19
+ private cache;
20
+ constructor(options: JwtServiceOptions);
21
+ sign<T extends JwtServiceJwtPayload>(payload: T, ttl?: MsValue): string;
22
+ verify<T extends JwtServiceJwtPayload>(token: string): Promise<T & {
23
+ token: string;
24
+ }>;
25
+ verifyFromHttpHeaders<T extends JwtServiceJwtPayload>(headers: IncomingHttpHeaders): Promise<T & {
26
+ token: string;
27
+ }>;
28
+ }
29
+ declare module '../x.mjs' {
30
+ interface X {
31
+ jwt: JwtService;
32
+ }
33
+ }
@@ -0,0 +1,42 @@
1
+ import { HttpError } from "../core/http_error.mjs";
2
+ import { ms } from "vtils";
3
+ import jwt from "jsonwebtoken";
4
+ import { LRUCache } from "lru-cache";
5
+ import { differenceInMilliseconds, fromUnixTime } from "vtils/date";
6
+ // src/services/jwt.ts
7
+ var JwtService = class {
8
+ options;
9
+ serviceName = "jwt";
10
+ cache;
11
+ constructor(options) {
12
+ this.options = options;
13
+ if (options.cache) this.cache = new LRUCache(options.cache);
14
+ }
15
+ sign(payload, ttl = this.options.ttl) {
16
+ const token = jwt.sign(payload, this.options.secret, { expiresIn: ms(ttl, true) });
17
+ if (this.cache) this.cache.set(token, payload, { ttl: ms(ttl) });
18
+ return token;
19
+ }
20
+ async verify(token) {
21
+ const data = await new Promise((resolve, reject) => {
22
+ if (this.cache && this.cache.has(token)) resolve(this.cache.get(token));
23
+ else jwt.verify(token, this.options.secret, { ignoreExpiration: false }, (err, data) => {
24
+ if (err || !data || typeof data === "string" || !data.iat || !data.exp) reject(new HttpError.Unauthorized("data"));
25
+ else {
26
+ data.token = token;
27
+ if (this.cache) this.cache.set(token, data, { ttl: differenceInMilliseconds(fromUnixTime(data.exp), /* @__PURE__ */ new Date()) });
28
+ resolve(data);
29
+ }
30
+ });
31
+ });
32
+ await this.options.onVerify?.(data);
33
+ return data;
34
+ }
35
+ async verifyFromHttpHeaders(headers) {
36
+ const authorization = headers.authorization || headers["sec-websocket-protocol"] && `Bearer ${headers["sec-websocket-protocol"]}` || "";
37
+ if (!authorization) throw new HttpError.Unauthorized("header");
38
+ const [scheme, token = scheme] = authorization.split(" ");
39
+ return this.verify(token);
40
+ }
41
+ };
42
+ export { JwtService };
@@ -0,0 +1,37 @@
1
+ import { BaseService } from "./base.mjs";
2
+ import { Merge } from "vtils/types";
3
+ export type LogServiceLevel = 'error' | 'info' | 'success';
4
+ export type LogServiceDesc = Record<string, any> | any[];
5
+ export type LogServiceWriter = 'file' | 'console';
6
+ export type LogServicePayload = {
7
+ writer?: LogServiceWriter;
8
+ level: LogServiceLevel;
9
+ title: string;
10
+ desc?: LogServiceDesc;
11
+ };
12
+ export type LogServiceLogItem<K extends string = string> = Merge<LogServicePayload, {
13
+ traceId: string;
14
+ time: string;
15
+ desc: Record<K, any>;
16
+ }>;
17
+ export declare class LogService implements BaseService {
18
+ serviceName: string;
19
+ getLogFile(date: Date): string;
20
+ private get logFile();
21
+ private getLogWriter;
22
+ parseLogLineText<K extends string = string>(text: string, keysMap?: Record<string, string[]>): LogServiceLogItem<K>;
23
+ private log;
24
+ info: (title: string, desc?: LogServiceDesc) => void;
25
+ success: (title: string, desc?: LogServiceDesc) => void;
26
+ error: (title: string, desc?: LogServiceDesc) => void;
27
+ console: {
28
+ info: (title: string, desc?: LogServiceDesc) => void;
29
+ success: (title: string, desc?: LogServiceDesc) => void;
30
+ error: (title: string, desc?: LogServiceDesc) => void;
31
+ };
32
+ }
33
+ declare module '../x.mjs' {
34
+ interface X {
35
+ log: LogService;
36
+ }
37
+ }
@@ -0,0 +1,99 @@
1
+ import { x } from "../x.mjs";
2
+ import { memoize } from "vtils";
3
+ import path from "node:path";
4
+ import fs from "fs-extra";
5
+ import { formatDate } from "vtils/date";
6
+ // src/services/log.ts
7
+ var LogService = class {
8
+ serviceName = "log";
9
+ getLogFile(date) {
10
+ const year = date.getFullYear();
11
+ const month = date.getMonth() + 1;
12
+ return path.join(x.dataDir, `log/${year}/${month < 10 ? `0${month}` : month}.log`);
13
+ }
14
+ get logFile() {
15
+ return this.getLogFile(/* @__PURE__ */ new Date());
16
+ }
17
+ getLogWriter = memoize((logFile) => {
18
+ fs.ensureFileSync(logFile);
19
+ return fs.createWriteStream(logFile, { flags: "a" });
20
+ }, (logFile) => logFile);
21
+ parseLogLineText(text, keysMap = {}) {
22
+ const segments = text.split(/\t+/);
23
+ if (segments[1].length < 10) segments.splice(1, 0, "");
24
+ const [time, traceId, level, title, ...desc] = segments;
25
+ return {
26
+ time,
27
+ traceId,
28
+ level,
29
+ title,
30
+ desc: desc.reduce((res, item, index) => {
31
+ if (keysMap[title]) res[keysMap[title][index]] = item;
32
+ else {
33
+ const i = item.indexOf(":");
34
+ res[item.substring(0, i)] = item.substring(i + 1);
35
+ }
36
+ return res;
37
+ }, {})
38
+ };
39
+ }
40
+ log(payload) {
41
+ const getContent = () => `${[
42
+ formatDate(/* @__PURE__ */ new Date(), "yyyy-mm-dd hh:ii:ss"),
43
+ ...!x.ctx ? [] : [x.ctx.traceId],
44
+ payload.level,
45
+ payload.title,
46
+ ...!payload.desc ? [] : Array.isArray(payload.desc) ? payload.desc : Object.keys(payload.desc).map((key) => `${key}:${payload.desc[key]}`)
47
+ ].map((item) => String(item).replace(/[\r\n\t]+/g, " ")).join(" ")}`;
48
+ if (payload.writer === "console") console[payload.level === "error" ? "error" : "log"](getContent());
49
+ else this.getLogWriter(this.logFile).write(`${getContent()}\n`);
50
+ }
51
+ info = (title, desc) => {
52
+ this.log({
53
+ level: "info",
54
+ title,
55
+ desc
56
+ });
57
+ };
58
+ success = (title, desc) => {
59
+ this.log({
60
+ level: "success",
61
+ title,
62
+ desc
63
+ });
64
+ };
65
+ error = (title, desc) => {
66
+ this.log({
67
+ level: "error",
68
+ title,
69
+ desc
70
+ });
71
+ };
72
+ console = {
73
+ info: (title, desc) => {
74
+ this.log({
75
+ writer: "console",
76
+ level: "info",
77
+ title,
78
+ desc
79
+ });
80
+ },
81
+ success: (title, desc) => {
82
+ this.log({
83
+ writer: "console",
84
+ level: "success",
85
+ title,
86
+ desc
87
+ });
88
+ },
89
+ error: (title, desc) => {
90
+ this.log({
91
+ writer: "console",
92
+ level: "error",
93
+ title,
94
+ desc
95
+ });
96
+ }
97
+ };
98
+ };
99
+ export { LogService };
@@ -0,0 +1,22 @@
1
+ import { BaseService } from "./base.mjs";
2
+ import nodemailer from "nodemailer";
3
+ export interface MailServiceOptions {
4
+ host: string;
5
+ port: number;
6
+ secure: boolean;
7
+ user: string;
8
+ pass: string;
9
+ }
10
+ export interface MailServiceSendOptions extends nodemailer.SendMailOptions {}
11
+ export declare class MailService implements BaseService {
12
+ private options;
13
+ serviceName: string;
14
+ private transporter;
15
+ constructor(options: MailServiceOptions);
16
+ send(options: MailServiceSendOptions): Promise<any>;
17
+ }
18
+ declare module '../x.mjs' {
19
+ interface X {
20
+ mail: MailService;
21
+ }
22
+ }
@@ -0,0 +1,28 @@
1
+ import { x } from "../x.mjs";
2
+ import nodemailer from "nodemailer";
3
+ // src/services/mail.ts
4
+ var MailService = class {
5
+ options;
6
+ serviceName = "mail";
7
+ transporter;
8
+ constructor(options) {
9
+ this.options = options;
10
+ }
11
+ async send(options) {
12
+ if (!this.transporter) {
13
+ this.transporter = nodemailer.createTransport({
14
+ host: this.options.host,
15
+ port: this.options.port,
16
+ secure: this.options.secure,
17
+ auth: {
18
+ user: this.options.user,
19
+ pass: this.options.pass
20
+ }
21
+ });
22
+ await this.transporter.verify();
23
+ x.dispose.add(() => this.transporter.close());
24
+ }
25
+ return this.transporter.sendMail(options);
26
+ }
27
+ };
28
+ export { MailService };
@@ -0,0 +1,123 @@
1
+ import { BaseService } from "./base.mjs";
2
+ export interface PayServiceOptions {
3
+ /** 支付宝 */
4
+ alipay?: {
5
+ /** 应用 ID */
6
+ appId: string;
7
+ /** 商户应用私钥 */
8
+ privateKey: string;
9
+ /** 支付宝公钥,用于对返回结果验签 */
10
+ publicKey: string;
11
+ };
12
+ /** 微信支付(APIv3),未实现回调验签,因此验证微信支付身份块不需要关心 */
13
+ wepay?: {
14
+ /** 公众号 APPID */
15
+ appId: string;
16
+ /** 商户 ID */
17
+ merchantId: string;
18
+ /** 商户API证书私钥 */
19
+ privateKey: string;
20
+ /** 商户API证书序列号 */
21
+ certificateSerialNumber: string;
22
+ /** 密钥,用于解密回调数据 */
23
+ secretKey: string;
24
+ };
25
+ }
26
+ export interface PayServicePrepareAlipayOptions {
27
+ /** 商品名称 */
28
+ goodsName: string;
29
+ /** 交易单号 */
30
+ tradeNumber: string;
31
+ /** 总金额 */
32
+ totalMoney: number;
33
+ /** 通知地址(POST) */
34
+ notifyUrl: string;
35
+ /** 返回地址 */
36
+ returnUrl?: string;
37
+ }
38
+ export interface PayServicePrepareAlipayResult {
39
+ /** 支付地址,需跳转过去 */
40
+ payUrl: string;
41
+ }
42
+ export interface PayServicePrepareWepayOptions {
43
+ /** 商品名称 */
44
+ goodsName: string;
45
+ /** 交易单号 */
46
+ tradeNumber: string;
47
+ /** 总金额 */
48
+ totalMoney: number;
49
+ /** 通知地址(POST) */
50
+ notifyUrl: string;
51
+ /** 公众号用户的 openid */
52
+ openid: string;
53
+ }
54
+ export interface PayServicePrepareWepayResult {
55
+ /** 支付参数,可直接传给 JSSDK 调用 */
56
+ payParams: {
57
+ appId: string;
58
+ timestamp: string;
59
+ nonceStr: string;
60
+ package: string;
61
+ signType: string;
62
+ paySign: string;
63
+ };
64
+ }
65
+ export interface PayServiceVerifyNotifyDataResult {
66
+ /**
67
+ * 渠道订单号。
68
+ *
69
+ * - 支付宝最长 `64` 位;
70
+ * - 微信支付最长 `32` 位。
71
+ */
72
+ channelOrderNo: string;
73
+ }
74
+ export interface PayServiceGetOrderInfoPayload {
75
+ /**
76
+ * 渠道。
77
+ */
78
+ channel: 'alipay' | 'wepay';
79
+ /**
80
+ * 商家订单号。
81
+ */
82
+ orderNo?: string;
83
+ /**
84
+ * 渠道订单号。
85
+ */
86
+ channelOrderNo?: string;
87
+ }
88
+ export interface PayServiceGetOrderInfoResult {
89
+ /**
90
+ * 商家订单号。
91
+ */
92
+ orderNo: string;
93
+ /**
94
+ * 渠道订单号。
95
+ *
96
+ * - 支付宝最长 `64` 位;
97
+ * - 微信支付最长 `32` 位。
98
+ */
99
+ channelOrderNo: string;
100
+ /**
101
+ * 订单状态。
102
+ */
103
+ status: 'success' | 'fail';
104
+ }
105
+ export declare class PayService implements BaseService {
106
+ private options;
107
+ serviceName: string;
108
+ private alipaySdk;
109
+ constructor(options: PayServiceOptions);
110
+ prepareAlipay(options: PayServicePrepareAlipayOptions): Promise<PayServicePrepareAlipayResult>;
111
+ prepareWepay(options: PayServicePrepareWepayOptions): Promise<PayServicePrepareWepayResult>;
112
+ verifyNotifyData(data: any): false | PayServiceVerifyNotifyDataResult;
113
+ verifyNotifyDataOrFail(data: any, message?: string): PayServiceVerifyNotifyDataResult;
114
+ getOrderInfo(payload: PayServiceGetOrderInfoPayload): Promise<PayServiceGetOrderInfoResult>;
115
+ private wepaySign;
116
+ private wepayDecrypt;
117
+ private wepayRequest;
118
+ }
119
+ declare module '../x.mjs' {
120
+ interface X {
121
+ pay: PayService;
122
+ }
123
+ }
@@ -0,0 +1,157 @@
1
+ import { HttpError } from "../core/http_error.mjs";
2
+ import { xr } from "@jayfong/x-request";
3
+ import crypto from "node:crypto";
4
+ import { AlipayFormData, AlipaySdk } from "alipay-sdk";
5
+ // src/services/pay.ts
6
+ var PayService = class {
7
+ options;
8
+ serviceName = "pay";
9
+ alipaySdk;
10
+ constructor(options) {
11
+ this.options = options;
12
+ }
13
+ async prepareAlipay(options) {
14
+ if (!this.alipaySdk) this.alipaySdk = new AlipaySdk({
15
+ appId: this.options.alipay.appId,
16
+ privateKey: this.options.alipay.privateKey,
17
+ alipayPublicKey: this.options.alipay.publicKey
18
+ });
19
+ const formData = new AlipayFormData();
20
+ formData.setMethod("get");
21
+ formData.addField("notifyUrl", options.notifyUrl);
22
+ if (options.returnUrl) formData.addField("returnUrl", options.returnUrl);
23
+ formData.addField("bizContent", {
24
+ outTradeNo: options.tradeNumber,
25
+ productCode: "FAST_INSTANT_TRADE_PAY",
26
+ totalAmount: options.totalMoney,
27
+ subject: options.goodsName,
28
+ goodsType: "0",
29
+ passbackParams: "alipay"
30
+ });
31
+ return { payUrl: await this.alipaySdk.exec("alipay.trade.page.pay", {}, { formData }) };
32
+ }
33
+ async prepareWepay(options) {
34
+ const res = await this.wepayRequest("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", {
35
+ appid: this.options.wepay.appId,
36
+ mchid: this.options.wepay.merchantId,
37
+ description: options.goodsName,
38
+ out_trade_no: options.tradeNumber,
39
+ attach: "wepay",
40
+ notify_url: options.notifyUrl,
41
+ amount: {
42
+ total: options.totalMoney * 100,
43
+ currency: "CNY"
44
+ },
45
+ payer: { openid: options.openid }
46
+ });
47
+ if (!res || !res.prepay_id) {
48
+ const error = res && res.message || "支付错误";
49
+ throw new Error(error);
50
+ }
51
+ const params = {
52
+ appId: this.options.wepay.appId,
53
+ timestamp: String(Math.round(Date.now() / 1e3)),
54
+ nonceStr: Math.random().toString().substr(2, 12),
55
+ package: `prepay_id=${res.prepay_id}`,
56
+ signType: "RSA",
57
+ paySign: ""
58
+ };
59
+ params.paySign = this.wepaySign([
60
+ params.appId,
61
+ params.timestamp,
62
+ params.nonceStr,
63
+ params.package
64
+ ]);
65
+ return { payParams: params };
66
+ }
67
+ verifyNotifyData(data) {
68
+ try {
69
+ if (!data || typeof data !== "object") return false;
70
+ if (data.passback_params === "alipay") {
71
+ if (!this.alipaySdk?.checkNotifySign(data)) return false;
72
+ return { channelOrderNo: data.trade_no };
73
+ }
74
+ if (data.resource) {
75
+ const params = JSON.parse(this.wepayDecrypt(data.resource));
76
+ if (params.attach === "wepay") return { channelOrderNo: params.transaction_id };
77
+ return false;
78
+ }
79
+ return false;
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+ verifyNotifyDataOrFail(data, message) {
85
+ const res = this.verifyNotifyData(data);
86
+ if (!res) throw new HttpError.BadRequest(message);
87
+ return res;
88
+ }
89
+ async getOrderInfo(payload) {
90
+ if (payload.channel === "wepay") {
91
+ const res = await this.wepayRequest(payload.orderNo ? `https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/${payload.orderNo}?mchid=${this.options.wepay.merchantId}` : `https://api.mch.weixin.qq.com/v3/pay/transactions/id/${payload.channelOrderNo}?mchid=${this.options.wepay.merchantId}`);
92
+ return {
93
+ channelOrderNo: res.transaction_id,
94
+ orderNo: res.out_trade_no,
95
+ status: res.trade_state === "SUCCESS" ? "success" : "fail"
96
+ };
97
+ }
98
+ const res = await this.alipaySdk.exec("alipay.trade.query", { biz_content: payload.orderNo ? { out_trade_no: payload.orderNo } : { trade_no: payload.channelOrderNo } });
99
+ return {
100
+ channelOrderNo: res.trade_no,
101
+ orderNo: res.out_trade_no,
102
+ status: res.trade_status === "TRADE_SUCCESS" || res.trade_status === "TRADE_FINISHED" ? "success" : "fail"
103
+ };
104
+ }
105
+ wepaySign(data) {
106
+ return crypto.createSign("RSA-SHA256").update(data.map((v) => `${v}\n`).join("")).sign(this.options.wepay.privateKey, "base64");
107
+ }
108
+ wepayDecrypt(payload) {
109
+ const ciphertextBuffer = Buffer.from(payload.ciphertext, "base64");
110
+ const authTag = ciphertextBuffer.slice(ciphertextBuffer.length - 16);
111
+ const data = ciphertextBuffer.slice(0, ciphertextBuffer.length - 16);
112
+ const decipherIv = crypto.createDecipheriv("aes-256-gcm", this.options.wepay.secretKey, payload.nonce);
113
+ decipherIv.setAuthTag(Buffer.from(authTag));
114
+ decipherIv.setAAD(Buffer.from(payload.associated_data));
115
+ const decryptStr = decipherIv.update(data, void 0, "utf8");
116
+ decipherIv.final();
117
+ return decryptStr;
118
+ }
119
+ async wepayRequest(url, data) {
120
+ const path = url.replace(/^https?:\/\/[^/]+/, "");
121
+ const method = data == null ? "GET" : "POST";
122
+ const body = method === "POST" ? JSON.stringify(data) : "";
123
+ const params = {
124
+ method,
125
+ url: path,
126
+ time: String(Math.round(Date.now() / 1e3)),
127
+ rand: Math.random().toString().substr(2, 12),
128
+ body,
129
+ signature: ""
130
+ };
131
+ params.signature = this.wepaySign([
132
+ params.method,
133
+ params.url,
134
+ params.time,
135
+ params.rand,
136
+ params.body
137
+ ]);
138
+ const Authorization = [
139
+ `WECHATPAY2-SHA256-RSA2048 `,
140
+ `mchid="${this.options.wepay.merchantId}",`,
141
+ `nonce_str="${params.rand}",`,
142
+ `signature="${params.signature}",`,
143
+ `timestamp="${params.time}",`,
144
+ `serial_no="${this.options.wepay.certificateSerialNumber}"`
145
+ ].join("");
146
+ const { data: res } = method === "POST" ? await xr.postJson({
147
+ url,
148
+ headers: { Authorization },
149
+ data
150
+ }) : await xr.getJson({
151
+ url,
152
+ headers: { Authorization }
153
+ });
154
+ return res;
155
+ }
156
+ };
157
+ export { PayService };