@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,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 { xr } from "@jayfong/x-request";
3
+ import { isUrl, ms } from "vtils";
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 { SendMailOptions } 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 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<import("nodemailer").SentMessageInfo>;
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 { createTransport } 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 = 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 };