wok-server 0.5.0 → 0.6.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 (372) hide show
  1. package/README.en.md +61 -0
  2. package/README.md +44 -29
  3. package/dist/cache/cache.js +98 -98
  4. package/dist/cache/config.js +19 -19
  5. package/dist/cache/index.js +27 -27
  6. package/dist/cache/purge-task.js +46 -46
  7. package/dist/cache/stat.js +47 -47
  8. package/dist/config/convert.js +36 -36
  9. package/dist/config/exception.js +14 -14
  10. package/dist/config/index.js +81 -81
  11. package/dist/http-client/index.js +136 -136
  12. package/dist/i18n/ar.js +17 -17
  13. package/dist/i18n/de.js +17 -17
  14. package/dist/i18n/en-us.js +17 -17
  15. package/dist/i18n/es.js +17 -17
  16. package/dist/i18n/fr.js +17 -17
  17. package/dist/i18n/i18n.js +231 -231
  18. package/dist/i18n/index.js +52 -52
  19. package/dist/i18n/ja.js +17 -17
  20. package/dist/i18n/ko.js +17 -17
  21. package/dist/i18n/msg.js +2 -2
  22. package/dist/i18n/pt.js +17 -17
  23. package/dist/i18n/ru.js +17 -17
  24. package/dist/i18n/tag.js +18 -18
  25. package/dist/i18n/zh-HK.js +17 -17
  26. package/dist/i18n/zh-TW.js +17 -17
  27. package/dist/i18n/zh-cn.js +17 -17
  28. package/dist/index.js +14 -14
  29. package/dist/lock/index.js +114 -114
  30. package/dist/log/config.js +35 -35
  31. package/dist/log/date.js +21 -21
  32. package/dist/log/file.js +198 -198
  33. package/dist/log/index.js +135 -135
  34. package/dist/log/level.js +33 -33
  35. package/dist/log/log.js +56 -56
  36. package/dist/log/store.js +19 -19
  37. package/dist/mongodb/collection.js +2 -2
  38. package/dist/mongodb/config.js +34 -34
  39. package/dist/mongodb/doc.js +2 -2
  40. package/dist/mongodb/exception.js +14 -14
  41. package/dist/mongodb/index.js +58 -58
  42. package/dist/mongodb/manager/base.js +563 -563
  43. package/dist/mongodb/manager/index.js +63 -63
  44. package/dist/mongodb/manager/tx-strict.js +84 -84
  45. package/dist/mongodb/manager/tx.js +30 -30
  46. package/dist/mongodb/migration.js +52 -52
  47. package/dist/mvc/access-log.js +33 -33
  48. package/dist/mvc/config.js +27 -27
  49. package/dist/mvc/exchange.js +113 -113
  50. package/dist/mvc/handler/index.js +7 -6
  51. package/dist/mvc/handler/json.js +65 -65
  52. package/dist/mvc/handler/restful.js +35 -35
  53. package/dist/mvc/handler/sse.js +65 -0
  54. package/dist/mvc/handler/upload.js +31 -31
  55. package/dist/mvc/index.js +50 -50
  56. package/dist/mvc/interceptor.js +2 -2
  57. package/dist/mvc/query.js +43 -43
  58. package/dist/mvc/render/file.js +132 -132
  59. package/dist/mvc/render/html/html.js +90 -90
  60. package/dist/mvc/render/html/index.js +18 -18
  61. package/dist/mvc/render/html/style.js +2 -2
  62. package/dist/mvc/render/index.js +7 -7
  63. package/dist/mvc/render/json.js +26 -26
  64. package/dist/mvc/render/text.js +16 -16
  65. package/dist/mvc/router.js +2 -2
  66. package/dist/mvc/server.js +272 -272
  67. package/dist/mvc/static/header.js +67 -67
  68. package/dist/mvc/static/index.js +6 -6
  69. package/dist/mvc/static/mime-type.js +84 -84
  70. package/dist/mvc/static/server-cache-config.js +66 -66
  71. package/dist/mvc/static/server-cache.js +133 -133
  72. package/dist/mvc/static/static-handler.js +372 -372
  73. package/dist/mysql/config.js +51 -51
  74. package/dist/mysql/exception.js +14 -14
  75. package/dist/mysql/index.js +87 -87
  76. package/dist/mysql/manager/base.js +239 -239
  77. package/dist/mysql/manager/index.js +107 -107
  78. package/dist/mysql/manager/ops/count.js +20 -20
  79. package/dist/mysql/manager/ops/criteria.js +356 -356
  80. package/dist/mysql/manager/ops/delete.js +65 -65
  81. package/dist/mysql/manager/ops/exist.js +26 -26
  82. package/dist/mysql/manager/ops/find.js +169 -169
  83. package/dist/mysql/manager/ops/index.js +14 -14
  84. package/dist/mysql/manager/ops/insert.js +106 -106
  85. package/dist/mysql/manager/ops/modify.js +10 -10
  86. package/dist/mysql/manager/ops/paginate.js +23 -23
  87. package/dist/mysql/manager/ops/query.js +9 -9
  88. package/dist/mysql/manager/ops/update.js +216 -216
  89. package/dist/mysql/manager/ops/utils.js +24 -24
  90. package/dist/mysql/manager/tx-strict.js +103 -103
  91. package/dist/mysql/manager/tx.js +30 -30
  92. package/dist/mysql/manager/utils.js +56 -56
  93. package/dist/mysql/migration.js +136 -136
  94. package/dist/mysql/table-info.js +8 -8
  95. package/dist/task/daily.js +59 -59
  96. package/dist/task/fixed-delay.js +38 -38
  97. package/dist/task/fixed-rate.js +42 -42
  98. package/dist/task/index.js +9 -9
  99. package/dist/task/task.js +56 -56
  100. package/dist/validation/exception.js +36 -36
  101. package/dist/validation/index.js +40 -40
  102. package/dist/validation/validator/array.js +34 -34
  103. package/dist/validation/validator/enum.js +28 -28
  104. package/dist/validation/validator/index.js +14 -14
  105. package/dist/validation/validator/length.js +40 -40
  106. package/dist/validation/validator/max-length.js +35 -35
  107. package/dist/validation/validator/max.js +29 -29
  108. package/dist/validation/validator/min-length.js +33 -33
  109. package/dist/validation/validator/min.js +29 -29
  110. package/dist/validation/validator/not-blank.js +33 -33
  111. package/dist/validation/validator/not-null.js +21 -21
  112. package/dist/validation/validator/plain-obj.js +32 -32
  113. package/dist/validation/validator/regexp.js +34 -34
  114. package/documentation/en/cache.md +56 -0
  115. package/documentation/en/config.md +96 -0
  116. package/documentation/en/engineering.md +256 -0
  117. package/documentation/en/http-client.md +32 -0
  118. package/documentation/en/i18n.md +143 -0
  119. package/documentation/en/index.md +24 -0
  120. package/documentation/en/lock.md +51 -0
  121. package/documentation/en/log.md +109 -0
  122. package/documentation/en/mongodb.md +256 -0
  123. package/documentation/en/mvc.md +688 -0
  124. package/documentation/en/mysql.md +552 -0
  125. package/documentation/en/task.md +45 -0
  126. package/documentation/en/test.md +56 -0
  127. package/documentation/en/validate.md +130 -0
  128. package/documentation/zh-cn/mvc.md +66 -24
  129. package/package.json +3 -1
  130. package/skills/wok-server-api-rules/SKILL.md +350 -0
  131. package/skills/wok-server-cache/SKILL.md +216 -0
  132. package/skills/wok-server-config/SKILL.md +200 -0
  133. package/skills/wok-server-getting-started/SKILL.md +123 -0
  134. package/skills/wok-server-getting-started/references/engineering.md +169 -0
  135. package/skills/wok-server-http-client/SKILL.md +164 -0
  136. package/skills/wok-server-i18n/SKILL.md +214 -0
  137. package/skills/wok-server-lock/SKILL.md +144 -0
  138. package/skills/wok-server-log/SKILL.md +218 -0
  139. package/skills/wok-server-mongodb/SKILL.md +235 -0
  140. package/skills/wok-server-mvc/SKILL.md +251 -0
  141. package/skills/wok-server-mvc/references/respond-html.md +157 -0
  142. package/skills/wok-server-mvc/references/sse.md +121 -0
  143. package/skills/wok-server-mvc/references/static-files.md +47 -0
  144. package/skills/wok-server-mvc/references/upload.md +62 -0
  145. package/skills/wok-server-mvc/references/websocket.md +30 -0
  146. package/skills/wok-server-mysql/SKILL.md +315 -0
  147. package/skills/wok-server-mysql/references/multi-datasource.md +76 -0
  148. package/skills/wok-server-mysql/references/version-control.md +22 -0
  149. package/skills/wok-server-task/SKILL.md +158 -0
  150. package/skills/wok-server-validate/SKILL.md +167 -0
  151. package/src/cache/cache.ts +118 -0
  152. package/src/cache/config.ts +53 -0
  153. package/src/cache/index.ts +27 -0
  154. package/src/cache/purge-task.ts +53 -0
  155. package/src/cache/stat.ts +47 -0
  156. package/src/config/convert.ts +27 -0
  157. package/src/config/exception.ts +8 -0
  158. package/src/config/index.ts +92 -0
  159. package/src/http-client/index.ts +202 -0
  160. package/src/i18n/ar.ts +16 -0
  161. package/src/i18n/de.ts +16 -0
  162. package/src/i18n/en-us.ts +16 -0
  163. package/src/i18n/es.ts +16 -0
  164. package/src/i18n/fr.ts +16 -0
  165. package/src/i18n/i18n.ts +230 -0
  166. package/src/i18n/index.ts +50 -0
  167. package/src/i18n/ja.ts +16 -0
  168. package/src/i18n/ko.ts +16 -0
  169. package/src/i18n/msg.ts +50 -0
  170. package/src/i18n/pt.ts +16 -0
  171. package/src/i18n/ru.ts +16 -0
  172. package/src/i18n/tag.ts +18 -0
  173. package/src/i18n/zh-HK.ts +16 -0
  174. package/src/i18n/zh-TW.ts +16 -0
  175. package/src/i18n/zh-cn.ts +16 -0
  176. package/src/index.ts +11 -0
  177. package/src/lock/index.ts +164 -0
  178. package/src/log/config.ts +71 -0
  179. package/src/log/date.ts +19 -0
  180. package/src/log/file.ts +215 -0
  181. package/src/log/index.ts +136 -0
  182. package/src/log/level.ts +29 -0
  183. package/src/log/log.ts +77 -0
  184. package/src/log/store.ts +31 -0
  185. package/src/mongodb/collection.ts +25 -0
  186. package/src/mongodb/config.ts +69 -0
  187. package/src/mongodb/doc.ts +12 -0
  188. package/src/mongodb/exception.ts +8 -0
  189. package/src/mongodb/index.ts +71 -0
  190. package/src/mongodb/manager/base.ts +674 -0
  191. package/src/mongodb/manager/index.ts +80 -0
  192. package/src/mongodb/manager/tx-strict.ts +153 -0
  193. package/src/mongodb/manager/tx.ts +34 -0
  194. package/src/mongodb/migration.ts +66 -0
  195. package/src/mvc/access-log.ts +33 -0
  196. package/src/mvc/config.ts +70 -0
  197. package/src/mvc/exchange.ts +126 -0
  198. package/src/mvc/handler/index.ts +4 -0
  199. package/src/mvc/handler/json.ts +96 -0
  200. package/src/mvc/handler/restful.ts +39 -0
  201. package/src/mvc/handler/sse.ts +90 -0
  202. package/src/mvc/handler/upload.ts +54 -0
  203. package/src/mvc/index.ts +48 -0
  204. package/src/mvc/interceptor.ts +12 -0
  205. package/src/mvc/query.ts +36 -0
  206. package/src/mvc/render/file.ts +148 -0
  207. package/src/mvc/render/html/html.ts +187 -0
  208. package/src/mvc/render/html/index.ts +16 -0
  209. package/src/mvc/render/html/style.ts +1201 -0
  210. package/src/mvc/render/index.ts +4 -0
  211. package/src/mvc/render/json.ts +24 -0
  212. package/src/mvc/render/text.ts +14 -0
  213. package/src/mvc/router.ts +13 -0
  214. package/src/mvc/server.ts +315 -0
  215. package/src/mvc/static/header.ts +86 -0
  216. package/src/mvc/static/index.ts +3 -0
  217. package/src/mvc/static/mime-type.ts +81 -0
  218. package/src/mvc/static/server-cache-config.ts +92 -0
  219. package/src/mvc/static/server-cache.ts +171 -0
  220. package/src/mvc/static/static-handler.ts +445 -0
  221. package/src/mysql/config.ts +130 -0
  222. package/src/mysql/exception.ts +8 -0
  223. package/src/mysql/index.ts +88 -0
  224. package/src/mysql/manager/base.ts +285 -0
  225. package/src/mysql/manager/index.ts +112 -0
  226. package/src/mysql/manager/ops/count.ts +30 -0
  227. package/src/mysql/manager/ops/criteria.ts +412 -0
  228. package/src/mysql/manager/ops/delete.ts +96 -0
  229. package/src/mysql/manager/ops/exist.ts +41 -0
  230. package/src/mysql/manager/ops/find.ts +226 -0
  231. package/src/mysql/manager/ops/index.ts +11 -0
  232. package/src/mysql/manager/ops/insert.ts +120 -0
  233. package/src/mysql/manager/ops/modify.ts +14 -0
  234. package/src/mysql/manager/ops/paginate.ts +60 -0
  235. package/src/mysql/manager/ops/query.ts +13 -0
  236. package/src/mysql/manager/ops/update.ts +294 -0
  237. package/src/mysql/manager/ops/utils.ts +20 -0
  238. package/src/mysql/manager/tx-strict.ts +138 -0
  239. package/src/mysql/manager/tx.ts +31 -0
  240. package/src/mysql/manager/utils.ts +75 -0
  241. package/src/mysql/migration.ts +149 -0
  242. package/src/mysql/table-info.ts +41 -0
  243. package/src/task/daily.ts +70 -0
  244. package/src/task/fixed-delay.ts +45 -0
  245. package/src/task/fixed-rate.ts +49 -0
  246. package/src/task/index.ts +4 -0
  247. package/src/task/task.ts +70 -0
  248. package/src/validation/exception.ts +27 -0
  249. package/src/validation/index.ts +61 -0
  250. package/src/validation/validator/array.ts +32 -0
  251. package/src/validation/validator/enum.ts +25 -0
  252. package/src/validation/validator/index.ts +11 -0
  253. package/src/validation/validator/length.ts +42 -0
  254. package/src/validation/validator/max-length.ts +33 -0
  255. package/src/validation/validator/max.ts +26 -0
  256. package/src/validation/validator/min-length.ts +31 -0
  257. package/src/validation/validator/min.ts +26 -0
  258. package/src/validation/validator/not-blank.ts +31 -0
  259. package/src/validation/validator/not-null.ts +19 -0
  260. package/src/validation/validator/plain-obj.ts +30 -0
  261. package/src/validation/validator/regexp.ts +32 -0
  262. package/types/cache/cache.d.ts +52 -52
  263. package/types/cache/config.d.ts +32 -32
  264. package/types/cache/index.d.ts +2 -2
  265. package/types/cache/purge-task.d.ts +11 -11
  266. package/types/cache/stat.d.ts +26 -26
  267. package/types/config/convert.d.ts +6 -6
  268. package/types/config/exception.d.ts +7 -7
  269. package/types/config/index.d.ts +25 -25
  270. package/types/http-client/index.d.ts +71 -71
  271. package/types/i18n/ar.d.ts +2 -2
  272. package/types/i18n/de.d.ts +2 -2
  273. package/types/i18n/en-us.d.ts +2 -2
  274. package/types/i18n/es.d.ts +2 -2
  275. package/types/i18n/fr.d.ts +2 -2
  276. package/types/i18n/i18n.d.ts +102 -102
  277. package/types/i18n/index.d.ts +9 -9
  278. package/types/i18n/ja.d.ts +2 -2
  279. package/types/i18n/ko.d.ts +2 -2
  280. package/types/i18n/msg.d.ts +50 -50
  281. package/types/i18n/pt.d.ts +2 -2
  282. package/types/i18n/ru.d.ts +2 -2
  283. package/types/i18n/tag.d.ts +11 -11
  284. package/types/i18n/zh-HK.d.ts +2 -2
  285. package/types/i18n/zh-TW.d.ts +2 -2
  286. package/types/i18n/zh-cn.d.ts +2 -2
  287. package/types/index.d.ts +11 -11
  288. package/types/lock/index.d.ts +64 -64
  289. package/types/log/config.d.ts +35 -35
  290. package/types/log/date.d.ts +2 -2
  291. package/types/log/file.d.ts +13 -13
  292. package/types/log/index.d.ts +53 -53
  293. package/types/log/level.d.ts +14 -14
  294. package/types/log/log.d.ts +40 -40
  295. package/types/log/store.d.ts +19 -19
  296. package/types/mongodb/collection.d.ts +25 -25
  297. package/types/mongodb/config.d.ts +45 -45
  298. package/types/mongodb/doc.d.ts +11 -11
  299. package/types/mongodb/exception.d.ts +7 -7
  300. package/types/mongodb/index.d.ts +29 -29
  301. package/types/mongodb/manager/base.d.ts +188 -188
  302. package/types/mongodb/manager/index.d.ts +38 -38
  303. package/types/mongodb/manager/tx-strict.d.ts +41 -41
  304. package/types/mongodb/manager/tx.d.ts +21 -21
  305. package/types/mongodb/migration.d.ts +12 -12
  306. package/types/mvc/access-log.d.ts +7 -7
  307. package/types/mvc/config.d.ts +42 -42
  308. package/types/mvc/exchange.d.ts +72 -72
  309. package/types/mvc/handler/index.d.ts +4 -3
  310. package/types/mvc/handler/json.d.ts +44 -44
  311. package/types/mvc/handler/restful.d.ts +11 -11
  312. package/types/mvc/handler/sse.d.ts +34 -0
  313. package/types/mvc/handler/upload.d.ts +36 -36
  314. package/types/mvc/index.d.ts +22 -22
  315. package/types/mvc/interceptor.d.ts +11 -11
  316. package/types/mvc/query.d.ts +13 -13
  317. package/types/mvc/render/file.d.ts +10 -10
  318. package/types/mvc/render/html/html.d.ts +98 -98
  319. package/types/mvc/render/html/index.d.ts +11 -11
  320. package/types/mvc/render/html/style.d.ts +1201 -1201
  321. package/types/mvc/render/index.d.ts +4 -4
  322. package/types/mvc/render/json.d.ts +17 -17
  323. package/types/mvc/render/text.d.ts +10 -10
  324. package/types/mvc/router.d.ts +11 -11
  325. package/types/mvc/server.d.ts +90 -90
  326. package/types/mvc/static/header.d.ts +27 -27
  327. package/types/mvc/static/index.d.ts +3 -3
  328. package/types/mvc/static/mime-type.d.ts +2 -2
  329. package/types/mvc/static/server-cache-config.d.ts +30 -30
  330. package/types/mvc/static/server-cache.d.ts +76 -76
  331. package/types/mvc/static/static-handler.d.ts +77 -77
  332. package/types/mysql/config.d.ts +90 -90
  333. package/types/mysql/exception.d.ts +7 -7
  334. package/types/mysql/index.d.ts +16 -16
  335. package/types/mysql/manager/base.d.ts +165 -165
  336. package/types/mysql/manager/index.d.ts +36 -36
  337. package/types/mysql/manager/ops/count.d.ts +13 -13
  338. package/types/mysql/manager/ops/criteria.d.ts +134 -134
  339. package/types/mysql/manager/ops/delete.d.ts +46 -46
  340. package/types/mysql/manager/ops/exist.d.ts +6 -6
  341. package/types/mysql/manager/ops/find.d.ts +86 -86
  342. package/types/mysql/manager/ops/index.d.ts +10 -10
  343. package/types/mysql/manager/ops/insert.d.ts +18 -18
  344. package/types/mysql/manager/ops/modify.d.ts +3 -3
  345. package/types/mysql/manager/ops/paginate.d.ts +36 -36
  346. package/types/mysql/manager/ops/query.d.ts +3 -3
  347. package/types/mysql/manager/ops/update.d.ts +76 -76
  348. package/types/mysql/manager/ops/utils.d.ts +5 -5
  349. package/types/mysql/manager/tx-strict.d.ts +36 -36
  350. package/types/mysql/manager/tx.d.ts +15 -15
  351. package/types/mysql/manager/utils.d.ts +17 -17
  352. package/types/mysql/migration.d.ts +8 -8
  353. package/types/mysql/table-info.d.ts +36 -36
  354. package/types/task/daily.d.ts +16 -16
  355. package/types/task/fixed-delay.d.ts +9 -9
  356. package/types/task/fixed-rate.d.ts +9 -9
  357. package/types/task/index.d.ts +4 -4
  358. package/types/task/task.d.ts +34 -34
  359. package/types/validation/exception.d.ts +38 -38
  360. package/types/validation/index.d.ts +32 -32
  361. package/types/validation/validator/array.d.ts +5 -5
  362. package/types/validation/validator/enum.d.ts +8 -8
  363. package/types/validation/validator/index.d.ts +11 -11
  364. package/types/validation/validator/length.d.ts +10 -10
  365. package/types/validation/validator/max-length.d.ts +8 -8
  366. package/types/validation/validator/max.d.ts +7 -7
  367. package/types/validation/validator/min-length.d.ts +6 -6
  368. package/types/validation/validator/min.d.ts +7 -7
  369. package/types/validation/validator/not-blank.d.ts +7 -7
  370. package/types/validation/validator/not-null.d.ts +6 -6
  371. package/types/validation/validator/plain-obj.d.ts +7 -7
  372. package/types/validation/validator/regexp.d.ts +8 -8
@@ -0,0 +1,130 @@
1
+ # Validation
2
+
3
+ The validation component provides a validate function to validate objects with many built-in validation rules. The component supports internationalization, and error messages depend on the current language. See the internationalization section for details.
4
+
5
+ Here is a simple usage example:
6
+
7
+ ```ts
8
+ validate(
9
+ // Object to validate
10
+ { name: 'tom' },
11
+ // Validation rules, multiple rules per property
12
+ {
13
+ name: [notNull(), length({ min: 2, max: 16 })]
14
+ }
15
+ )
16
+ ```
17
+
18
+ Built-in validation rule functions:
19
+
20
+ | Function | Description |
21
+ | :------------ | :----------------------------------------------------------------------- |
22
+ | notNull | Not null validation, cannot be null or undefined |
23
+ | notBlank | Not blank validation, cannot be null, undefined, or blank string |
24
+ | min | Validate minimum number value |
25
+ | max | Validate maximum number value |
26
+ | length | Validate length, applicable to strings and arrays |
27
+ | maxLength | Check maximum length, applicable to strings and arrays |
28
+ | minLength | Check minimum length, applicable to strings and arrays |
29
+ | regexp | Regular expression validation |
30
+ | enumerate | Enumeration validation, value must be one of the specified list |
31
+ | array | Array validation, set element validation rules to validate each element |
32
+ | plainObject | Object validation, validate nested object properties |
33
+
34
+ Here is an example of nested object and array validation:
35
+
36
+ ```ts
37
+ interface Tag {
38
+ id: string
39
+ name: string
40
+ permissinos: { edit?: boolean; read?: boolean }
41
+ }
42
+ interface User {
43
+ profile: {
44
+ theme: string
45
+ }
46
+ tags: Tag[]
47
+ }
48
+ validate<User>(
49
+ {
50
+ profile: {
51
+ theme: 'light'
52
+ },
53
+ tags: [
54
+ { id: '001', name: 'basketball', permissinos: { edit: true, read: true } },
55
+ { id: '002', name: 'soccer', permissinos: { edit: true } }
56
+ ]
57
+ },
58
+ {
59
+ profile: [
60
+ notNull(),
61
+ plainObject({
62
+ theme: [notBlank()]
63
+ })
64
+ ],
65
+ tags: [
66
+ // Maximum 5 tags
67
+ maxLength(5),
68
+ // Tags list cannot be null
69
+ notNull(),
70
+ // Validate tag array elements
71
+ array([
72
+ // Element cannot be null
73
+ notNull(),
74
+ // Element property validation
75
+ plainObject({
76
+ id: [notBlank()],
77
+ name: [notBlank()],
78
+ permissinos: [
79
+ notNull(),
80
+ plainObject({
81
+ edit: [notNull()],
82
+ read: [notNull()]
83
+ })
84
+ ]
85
+ })
86
+ ])
87
+ ]
88
+ }
89
+ )
90
+ ```
91
+
92
+ In actual development, it's recommended to keep validation at most one level deep, without nesting, otherwise the program will be difficult to maintain.
93
+
94
+ ## Custom Validation Rules
95
+
96
+ If the built-in validation rules cannot meet your needs, you can write custom validation rules.
97
+
98
+ ```ts
99
+ /**
100
+ * Custom validation
101
+ * @returns Property validator
102
+ */
103
+ function customValidate(): PropValidator {
104
+ // Validator name for tracking
105
+ const validator = 'custom'
106
+ const message = 'Cannot start with t'
107
+ return val => {
108
+ // Skip null validation
109
+ if (!val) {
110
+ return { ok: true }
111
+ }
112
+ if (typeof val !== 'string') {
113
+ return { ok: false, validator, message: 'Value is not a string' }
114
+ }
115
+ if (val.startsWith('t')) {
116
+ return { ok: false, validator, message }
117
+ }
118
+ return { ok: true }
119
+ }
120
+ }
121
+
122
+ validate(
123
+ { name: 'tim' },
124
+ {
125
+ name: [customValidate()]
126
+ }
127
+ )
128
+ ```
129
+
130
+ Built-in validation rules have internationalization support. If you need internationalization for custom validation rules, you need to handle it yourself. See the internationalization chapter for details.
@@ -632,36 +632,78 @@ await startWebServer({
632
632
 
633
633
  ### Server-Sent Events
634
634
 
635
- 组件本身没有直接提供对 SSE(Server-Sent Events) 的支持,可以在路由的处理函数中适当的进行处理来实现。
635
+ 0.6.0 版本开始,MVC 组件内置了 `createSseHandler`,封装了 SSE 协议细节,大幅简化服务端推送实现。
636
636
 
637
637
  ```ts
638
- // 启动服务
638
+ import { createSseHandler } from 'wok-server'
639
+
639
640
  await startWebServer({
640
- // 路由配置
641
641
  routers: {
642
- '/sse': async exchange => {
643
- const { response } = exchange
644
- // 设置消息头
645
- response.setHeader('Content-Type', 'text/event-stream')
646
- response.setHeader('Cache-Control', 'no-cache')
647
- response.setHeader('Connection', 'keep-alive')
648
- // 模拟异步操作更新多条消息
649
- let counter = 0
650
- for (let i = 0; i < 10; i++) {
651
- // 沉睡一秒,模拟异步业务处理
652
- await new Promise<void>((resolve, reject) => {
653
- setTimeout(resolve, 1000)
654
- })
655
- counter++
656
- // 写数据到响应信息中,前端在 EventSource 的 message 事件中处理
657
- response.write(`data: ${JSON.stringify({ message: '实时更新', count: counter })}\n\n`)
658
- if (counter >= 10) {
659
- break
642
+ '/sse': createSseHandler({
643
+ async handle(ctx) {
644
+ let counter = 0
645
+ for (let i = 0; i < 10; i++) {
646
+ await new Promise<void>(resolve => setTimeout(resolve, 1000))
647
+ counter++
648
+ ctx.send({ message: '实时更新', count: counter })
649
+ if (counter >= 10) {
650
+ break
651
+ }
660
652
  }
653
+ ctx.close()
661
654
  }
662
- // 最后结束响应
663
- response.end()
664
- }
655
+ })
656
+ }
657
+ })
658
+ ```
659
+
660
+ `handle` 函数接收一个 `SseContext` 对象,提供以下能力:
661
+
662
+ | 方法/属性 | 说明 |
663
+ | :---------------------------------------- | :----------------------------------------------------------- |
664
+ | `ctx.send(data, event?, id?)` | 发送 SSE 事件,`data` 会被 JSON 序列化。`event` 指定事件名(前端用 `addEventListener` 监听),`id` 设置事件 ID(用于断线重连的 `Last-Event-ID`) |
665
+ | `ctx.close()` | 显式结束 SSE 连接。`handle` 返回或抛异常时连接也会自动关闭 |
666
+ | `ctx.request` | 原始 `IncomingMessage`,可读取请求头等信息 |
667
+ | `ctx.response` | 原始 `ServerResponse`,高级场景下使用 |
668
+
669
+ #### 命名事件
670
+
671
+ 通过 `event` 参数发送命名事件,前端可按事件类型分别处理:
672
+
673
+ ```ts
674
+ createSseHandler({
675
+ async handle(ctx) {
676
+ ctx.send({ title: '新消息' }, 'notification')
677
+ ctx.send({ progress: 50 }, 'progress')
665
678
  }
666
679
  })
667
680
  ```
681
+
682
+ 前端:
683
+
684
+ ```ts
685
+ const es = new EventSource('/sse')
686
+ es.addEventListener('notification', e => {
687
+ const data = JSON.parse(e.data)
688
+ console.log('收到通知:', data.title)
689
+ })
690
+ ```
691
+
692
+ #### 断线重连
693
+
694
+ 通过 `id` 参数设置事件 ID,前端断线重连时浏览器会自动发送 `Last-Event-ID` 请求头:
695
+
696
+ ```ts
697
+ createSseHandler({
698
+ async handle(ctx) {
699
+ const lastId = ctx.request.headers['last-event-id']
700
+ // 根据 lastId 确定从何处恢复推送
701
+ }
702
+ })
703
+ ```
704
+
705
+ #### 连接生命周期
706
+
707
+ - `handle` 开始执行时,SSE 消息头已发送,连接已建立
708
+ - 客户端断开连接时,`ctx.send()` 调用变为空操作(自动忽略)
709
+ - `handle` 返回或抛异常时,连接自动关闭
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wok-server",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "packageManager": "pnpm@8.9.0",
5
5
  "description": "一个基于 NodeJs 和 TypeScript 的后端框架,轻量级、克制、简洁。A lightweight, restrained, and concise backend framework based on Node.js and TypeScript.",
6
6
  "scripts": {
@@ -19,6 +19,8 @@
19
19
  "dist/",
20
20
  "docs/",
21
21
  "documentation/",
22
+ "skills/",
23
+ "src/",
22
24
  "README.md"
23
25
  ],
24
26
  "author": "peak",
@@ -0,0 +1,350 @@
1
+ ---
2
+ name: wok-server-api-rules
3
+ description: 介绍 wok-server API 的使用纪律。
4
+ license: MIT
5
+ metadata:
6
+ author: Peak Tai
7
+ email: peaktai@qq.com
8
+ ---
9
+
10
+ # API 使用纪律
11
+
12
+ 当你生成与 wok-server 有关的代码时,以下规则优先级高于一切:
13
+
14
+ ## 规则 1:禁止猜测任何 API
15
+
16
+ 不要使用训练数据中出现的、或你自己"觉得应该有"的函数、组件、类型。
17
+
18
+ ### 消除臆造的具体方法
19
+
20
+ - 所有 API 统一从 `wok-server` 包导入,禁止从子路径导入(如 `wok-server/mvc`)。
21
+ - 生成任何调用前,必须先查阅 `node_modules/wok-server/types/` 下对应模块的定义文件。types 目录按模块组织,常见模块与定义文件对照如下:
22
+
23
+ | 模块 | 主要入口函数/类型 | 类型定义文件路径 |
24
+ |------|-------------------|------------------|
25
+ | 日志 | `getLogger()` | `types/log/index.d.ts` |
26
+ | 缓存 | `getCache()` | `types/cache/cache.d.ts` |
27
+ | 国际化 | `getI18n()` | `types/i18n/i18n.d.ts` |
28
+ | 校验 | `validate()` | `types/validation/index.d.ts` |
29
+ | 配置 | `registerConfig()`, `getConfig()` | `types/config/index.d.ts` |
30
+ | 锁 | `getLockManager()` | `types/lock/index.d.ts` |
31
+ | 任务调度 | `scheduleWithFixedDelay()`, `scheduleWithFixedRate()`, `scheduleDailyTask()` | `types/task/index.d.ts` |
32
+ | HTTP客户端 | `doRequest()`, `postJson()`, `getJson()` | `types/http-client/index.d.ts` |
33
+ | MySQL | `enableMysql()`, `getMysqlManager()` | `types/mysql/index.d.ts` |
34
+ | MongoDB | `enableMongoDB()`, `getMongoDBManager()` | `types/mongodb/index.d.ts` |
35
+ | MVC | `startWebServer()`, `stopWebServer()`, `createJsonHandler()`, `createUploadHandler()`, `createSseHandler()`, `restful()`, `removeServerStaticCache()` | `types/mvc/index.d.ts` |
36
+
37
+ - 代码必须严格匹配签名——函数参数名称、顺序、类型完全一致,返回值类型正确处理(如 `Promise` 需 `await`)。
38
+
39
+ ### 示例
40
+
41
+ ❌ 错误:`getCache().add('key', data)` —— cache 没有 `add` 方法,属于臆造。
42
+
43
+ ✅ 正确:查阅 `node_modules/wok-server/types/cache/cache.d.ts` 后,使用 `getCache().put('key', data)` 并严格按签名调用。
44
+
45
+ ❌ 错误:`exchange.send(data)` 或 `exchange.json(data)` —— `ServerExchange` 没有这些方法。
46
+
47
+ ✅ 正确:使用 `exchange.respondJson(data)` 或 `exchange.respondText(text)` 等,详见下方 ServerExchange 速查表。
48
+
49
+ ---
50
+
51
+ ## 规则 2:每个拦截器和每个路由 handler 都应该有单独的文件
52
+
53
+ 禁止多个拦截器写在一个文件里,禁止多个接口的处理逻辑在一个文件里。
54
+ 即使内容再少,也不允许写在一起。
55
+
56
+ 路由的配置(`routers` 对象)必须在入口文件(如 `main.ts`)或独立的 router 目录中**集中管理**,不允许在业务目录中分散配置路由映射。集中配置是为了方便查找所有路由。
57
+
58
+ ### 拦截器标准签名
59
+
60
+ ```ts
61
+ import { ServerExchange } from 'wok-server'
62
+
63
+ // 每个拦截器单独一个文件,export 一个函数
64
+ export async function authInterceptor(
65
+ exchange: ServerExchange,
66
+ next: () => Promise<void>
67
+ ): Promise<void> {
68
+ // 前置处理...
69
+ await next()
70
+ // 后置处理...
71
+ }
72
+ ```
73
+
74
+ 类型定义为:
75
+
76
+ ```ts
77
+ interface Interceptor {
78
+ (exchange: ServerExchange, next: () => Promise<void>): Promise<void>
79
+ }
80
+ ```
81
+
82
+ ---
83
+
84
+ ## 规则 3:每个路由 handler 文件的参数和响应定义都应该保持在内部
85
+
86
+ 每个路由的处理逻辑是独立的,不向外导出除 handler 以外的函数、组件、类型,不和别的路由共享数据。
87
+
88
+ ### 可用的 Handler 工厂函数
89
+
90
+ wok-server 提供了以下 4 种 handler 工厂函数,禁止使用除此之外任何臆造的工厂函数:
91
+
92
+ | 工厂函数 | 用途 | 请求格式 | 响应格式 |
93
+ |----------|------|----------|----------|
94
+ | `createJsonHandler` | JSON 请求/响应 | POST,JSON body | JSON |
95
+ | `createUploadHandler` | 二进制文件上传 | POST,binary body | JSON |
96
+ | `createSseHandler` | Server-Sent Events 推送 | GET | SSE 事件流 |
97
+ | `restful` | 按 HTTP 方法分发 | 任意 | 由内层 handler 决定 |
98
+
99
+ #### createJsonHandler 示例
100
+
101
+ ```ts
102
+ // create-user.ts
103
+ import { createJsonHandler, notBlank, length, min, max, notNull } from 'wok-server'
104
+
105
+ interface Form {
106
+ name: string
107
+ age: number
108
+ }
109
+
110
+ interface Resp {
111
+ id: string
112
+ }
113
+
114
+ export const createUserHandler = createJsonHandler<Form, Resp>({
115
+ validation: {
116
+ name: [notBlank(), length({ min: 2, max: 16 })],
117
+ age: [notNull(), min(1), max(150)]
118
+ },
119
+ // 可选:缓存支持
120
+ async cache(body) {
121
+ return { key: `user-${body.name}`, expiresInSeconds: 60 }
122
+ },
123
+ async handle(body) {
124
+ const newUser = await createUser(body)
125
+ return { id: newUser.id }
126
+ }
127
+ })
128
+ ```
129
+
130
+ 命名约定:请求数据类型推荐命名为 `Form`,响应数据类型推荐命名为 `Resp`。
131
+ 由于这两个数据类型是保持在文件内部的,所以不同的 handler 文件可以使用这两个名称,不会冲突,
132
+ 这也是推荐的方式。如果每个具体的业务,根据场景命名也是可以的,如 CreateUserForm、CreateUserResp,
133
+ 这样更严谨,查询可能更方便,但是开发效率会稍低。
134
+
135
+ #### createUploadHandler 示例
136
+
137
+ 上传请求正文是文件二进制内容,额外参数通过 QueryString 传递。请求体类型是 `Buffer`,不需要定义 Form。
138
+
139
+ ```ts
140
+ // upload-avatar.ts
141
+ import { createUploadHandler, validate, notBlank } from 'wok-server'
142
+
143
+ interface Resp {
144
+ url: string
145
+ }
146
+
147
+ export const uploadAvatarHandler = createUploadHandler<Resp>({
148
+ async handle(body, exchange) {
149
+ const userId = exchange.query.getStr('userId')
150
+ validate({ userId }, { userId: [notBlank()] })
151
+ // body 就是文件的 Buffer,可直接使用
152
+ const key = `avatars/${userId}`
153
+ await oss.putObject(key, body)
154
+ return { url: oss.getUrl(key) }
155
+ }
156
+ })
157
+ ```
158
+
159
+ #### createSseHandler 示例
160
+
161
+ SSE handler 没有请求/响应数据类型,只有 `SseContext`。
162
+
163
+ ```ts
164
+ // sse-notify.ts
165
+ import { createSseHandler } from 'wok-server'
166
+
167
+ export const notifyHandler = createSseHandler({
168
+ async handle(ctx) {
169
+ // ctx.send(data, event?, id?) 发送事件
170
+ // ctx.close() 关闭连接
171
+ ctx.send({ message: '连接成功' }, 'connected')
172
+ // ... 业务逻辑
173
+ ctx.close()
174
+ }
175
+ })
176
+ ```
177
+
178
+ #### restful 示例
179
+
180
+ ```ts
181
+ // user-router.ts
182
+ import { restful } from 'wok-server'
183
+ import { createUserHandler } from './create-user'
184
+ import { getUserHandler } from './get-user'
185
+
186
+ export const userRouter = restful({
187
+ get: getUserHandler,
188
+ post: createUserHandler
189
+ })
190
+ ```
191
+
192
+ ---
193
+
194
+ ## 规则 4:业务错误应抛出异常,由全局异常拦截器统一处理
195
+
196
+ 推荐的处理模式:
197
+ 1. 定义 `BusinessException` 自定义业务异常类
198
+ 2. 创建 `globalErrorInterceptor` 放在拦截器链**第一位**
199
+ 3. Handler 中遇到业务错误,抛出异常来中止处理流程
200
+
201
+ ```ts
202
+ // exception.ts —— 全局异常定义文件
203
+ import { ServerExchange, ValidationException } from 'wok-server'
204
+
205
+ export class BusinessException {
206
+ constructor(
207
+ readonly message: string,
208
+ readonly status?: number
209
+ ) {}
210
+ }
211
+
212
+ export async function globalErrorInterceptor(
213
+ exchange: ServerExchange,
214
+ next: () => Promise<void>
215
+ ): Promise<void> {
216
+ try {
217
+ await next()
218
+ } catch (e) {
219
+ if (e instanceof BusinessException) {
220
+ exchange.respondErrMsg(e.message, e.status ?? 400)
221
+ return
222
+ }
223
+ if (e instanceof ValidationException) {
224
+ exchange.respondErrMsg(`${e.propertyPath}:${e.errMsg}`, 400)
225
+ return
226
+ }
227
+ throw e
228
+ }
229
+ }
230
+ ```
231
+
232
+ ```ts
233
+ // main.ts 入口文件,将错误拦截器放在第一位
234
+ import { startWebServer } from 'wok-server'
235
+ import { globalErrorInterceptor } from './exception'
236
+
237
+ await startWebServer({
238
+ interceptors: [globalErrorInterceptor /* , 其他拦截器 */],
239
+ routers: { /* ... */ }
240
+ })
241
+ ```
242
+
243
+ ---
244
+
245
+ ## 附录 A:ServerExchange 速查表
246
+
247
+ 所有路由 handler 和拦截器都通过 `ServerExchange` 与请求/响应交互。以下是其完整方法列表,禁止使用表中未列出的方法。
248
+
249
+ ### 读取请求
250
+
251
+ | 方法/属性 | 返回类型 | 说明 |
252
+ |-----------|----------|------|
253
+ | `exchange.request` | `IncomingMessage` | Node.js 原生请求对象 |
254
+ | `exchange.response` | `ServerResponse` | Node.js 原生响应对象 |
255
+ | `await exchange.bodyJson<T>()` | `Promise<T>` | 读取 JSON 请求体(空体返回 `{}`) |
256
+ | `await exchange.bodyBuffer()` | `Promise<Buffer>` | 读取二进制请求体 |
257
+ | `await exchange.bodyText()` | `Promise<string>` | 读取文本请求体 |
258
+ | `exchange.parseQueryString()` | `QueryString` | 解析 URL 查询字符串 |
259
+
260
+ > **注意**:如果使用了第三方库读取 request 内容,则不能再调用 `bodyXxx` 系列方法,反之亦然。但 `bodyXxx` 系列方法之间可以重复调用。
261
+
262
+ ### 响应
263
+
264
+ | 方法 | 说明 |
265
+ |------|------|
266
+ | `exchange.respondJson(json, status?)` | 响应 JSON,默认 status 200 |
267
+ | `exchange.respondErrMsg(message, status?)` | 响应统一错误格式 `{ message: "..." }`,默认 status 400 |
268
+ | `exchange.respondText(text, status?)` | 响应纯文本,默认 status 200 |
269
+ | `exchange.respondFile(filePath, download?)` | 响应文件,`download=true` 触发下载 |
270
+ | `exchange.respondHtml(html, status?)` | 响应 HTML |
271
+ | `exchange.respond({ statusCode, body?, headers? })` | 底层通用响应 |
272
+
273
+ ---
274
+
275
+ ## 附录 B:startWebServer 完整配置
276
+
277
+ ```ts
278
+ import { startWebServer } from 'wok-server'
279
+
280
+ await startWebServer({
281
+ // 必填:路由配置,键为路径,值为 RouterHandler
282
+ // 路径仅支持明确地址,不支持动态参数(如 /users/:id)和通配符
283
+ // '*' 为特殊路径,用于兜底处理 404
284
+ routers: {
285
+ '/user/create': createUserHandler,
286
+ '/user/delete': deleteUserHandler,
287
+ '/sse/notify': notifyHandler,
288
+ '*': notFoundHandler
289
+ },
290
+ // 可选:拦截器链,按数组顺序执行
291
+ interceptors: [globalErrorInterceptor, authInterceptor],
292
+ // 可选:前置处理,可整合 socket.io 等原生 http 组件
293
+ preHandler: async (server) => {
294
+ // const io = new Server(server)
295
+ },
296
+ // 可选:静态文件服务配置
297
+ static: {
298
+ '/': { dir: 'fe', cacheAge: 600 }
299
+ }
300
+ })
301
+ ```
302
+
303
+ ---
304
+
305
+ ## 附录 C:内置校验器列表
306
+
307
+ 以下校验器从 `wok-server` 导入,禁止臆造不存在的校验器:
308
+
309
+ | 函数 | 作用 |
310
+ |------|------|
311
+ | `notNull()` | 非空校验(不能是 null/undefined) |
312
+ | `notBlank()` | 字符串非空校验(不能是 null/undefined/空白字符串) |
313
+ | `min(n)` | 数字最小值 |
314
+ | `max(n)` | 数字最大值 |
315
+ | `length({ min?, max? })` | 字符串/数组长度范围 |
316
+ | `maxLength(n)` | 字符串/数组最大长度 |
317
+ | `minLength(n)` | 字符串/数组最小长度 |
318
+ | `regexp(re)` | 正则校验 |
319
+ | `enumerate(list)` | 枚举校验,值必须在指定列表中 |
320
+ | `array(validators)` | 数组元素校验 |
321
+ | `plainObject(opts)` | 嵌套对象校验 |
322
+
323
+ 所有内置校验器已支持国际化,自动根据请求头 `accept-language` 切换提示语言。
324
+
325
+ ---
326
+
327
+ ## 附录 D:目录结构参考
328
+
329
+ ```
330
+ src/
331
+ ├── exception.ts # 全局异常定义 + 错误拦截器
332
+ ├── main.ts # 入口:启动服务、集中配置路由
333
+ ├── auth/ # 授权模块
334
+ │ ├── auth-interceptor.ts
335
+ │ ├── create-auth.ts
336
+ │ └── index.ts
337
+ ├── user/ # 用户模块
338
+ │ ├── user.ts # 实体配置(mysql/mongo 等)
339
+ │ ├── create-user.ts # POST /user/create
340
+ │ ├── update-user.ts # POST /user/update
341
+ │ └── index.ts
342
+ └── tag/ # 标签模块
343
+ ├── tag.ts
344
+ ├── create-tag.ts
345
+ └── index.ts
346
+ ```
347
+
348
+ - 目录按业务功能划分,而非按技术层(service/controller)划分。
349
+ - 路由配置集中在 `main.ts` 或独立 `router/` 目录中。
350
+ - 每个 handler 和 interceptor 都是单独文件。